1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
/*
* id3v2 routines
*
* (c) 2005 bl0rg.net
*/
#include "conf.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "file.h"
#include "pack.h"
#include "id3.h"
/* create a sync safe integer (bit 7 is 0) */
static unsigned long id3_sync_safe(unsigned long num) {
unsigned long res = 0;
int i;
for (i = 0; i < 4; i++) {
res |= (num & 0x7F) << (i * 8);
num >>= 7;
}
return res;
}
unsigned int id3_fill_comment(unsigned char *buf, unsigned int len,
unsigned char encoding,
unsigned char *short_comment,
unsigned char *long_comment,
unsigned char *language) {
assert(buf != NULL);
assert(len > 0);
if ((short_comment == NULL) &&
(long_comment == NULL))
return 0;
if (language == NULL)
language = "eng";
unsigned int short_len = short_comment ? strlen(short_comment) : 0;
unsigned int long_len = long_comment ? strlen(long_comment) : 0;
unsigned char *ptr = buf;
unsigned int flen = 1 + 3 + short_len + 1 + long_len + 1;
if (len < 6 + flen)
return 0;
memcpy(ptr, "COM", 3); ptr += 3;
UINT24_PACK(ptr, id3_sync_safe(flen));
UINT8_PACK(ptr, encoding);
memcpy(ptr, language, 3); ptr += 3;
if (short_comment) {
memcpy(ptr, short_comment, short_len);
ptr += short_len;
}
UINT8_PACK(ptr, 0x00);
if (long_comment) {
memcpy(ptr, long_comment, long_len);
ptr += long_len;
}
UINT8_PACK(ptr, 0x00);
return 6 + flen;
}
unsigned int id3_fill_tframe(unsigned char *buf, unsigned int len,
unsigned char *type,
unsigned char encoding,
unsigned char *string) {
assert(buf != NULL);
assert(len > 0);
assert(type != NULL);
assert(string != NULL);
unsigned char *ptr = buf;
unsigned int slen = strlen(string);
unsigned int flen = slen + 2;
if (len < 6 + flen)
return 0;
memcpy(ptr, type, 3); ptr += 3;
UINT24_PACK(ptr, id3_sync_safe(flen));
UINT8_PACK(ptr, encoding);
memcpy(ptr, string, slen); ptr += slen;
UINT8_PACK(ptr, 0x00);
return flen + 6;
}
int id3_fill_header(unsigned char *buf, unsigned int len,
unsigned long id3_size) {
assert(buf != NULL);
assert(len > 0);
if (len < 10)
return 0;
unsigned char *ptr = buf;
memcpy(ptr, "ID3", 3); ptr += 3;
UINT8_PACK(ptr, 0x02); UINT8_PACK(ptr, 0x00); /* version 2.0 */
UINT8_PACK(ptr, 0x00);
UINT32_PACK(ptr, id3_sync_safe(id3_size));
return 10;
}
int id3_write_tag(file_t *outfile,
unsigned char *album_title,
unsigned char *artist,
unsigned char *title,
unsigned int track_number,
unsigned char *comment) {
/* write id3 tags */
unsigned char id3[ID3_TAG_SIZE];
unsigned char *ptr = id3 + ID3_HEADER_SIZE;
unsigned int size = 0, bytes_left = sizeof(id3) - ID3_HEADER_SIZE;
unsigned int len;
if (album_title && strlen(album_title) > 0) {
len = id3_fill_tframe(ptr, bytes_left, "TAL", 0, album_title);
if (len == 0)
return 0;
bytes_left -= len; ptr += len; size += len;
}
if (artist && strlen(artist) > 0) {
len = id3_fill_tframe(ptr, bytes_left, "TP1", 0, artist);
if (len == 0)
return 0;
bytes_left -= len; ptr += len; size += len;
}
if (title && strlen(title) > 0) {
len = id3_fill_tframe(ptr, bytes_left, "TT2", 0, title);
if (len == 0)
return 0;
bytes_left -= len; ptr += len; size += len;
}
if (track_number > 0) {
unsigned char tracknumber[256];
snprintf(tracknumber, 256, "%d", track_number);
len = id3_fill_tframe(ptr, bytes_left, "TRK", 0, tracknumber);
if (len == 0)
return 0;
bytes_left -= len; ptr += len; size += len;
}
if (comment && strlen(comment) > 0) {
len = id3_fill_comment(ptr, bytes_left, 0,
NULL,
comment,
"eng");
if (len == 0)
return 0;
bytes_left -= len; ptr += len; size += len;
}
if (id3_fill_header(id3, sizeof(id3), size) == 0)
return 0;
len = file_write(outfile, id3, size + ID3_HEADER_SIZE);
if (len != size + ID3_HEADER_SIZE)
return 0;
return 1;
}
|