return 1;
}
-static const char *ID3v1GenreList[] = {
- "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
- "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
- "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
- "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
- "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal",
- "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid",
- "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
- "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
- "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
- "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
- "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40",
- "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
- "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
- "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
- "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk",
- "Swing", "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic",
- "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock",
- "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
- "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
- "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
- "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
- "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle",
- "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House",
- "Dance Hall", "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
- "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
- "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover",
- "Contemporary C", "Christian Rock", "Merengue", "Salsa", "Thrash Metal",
- "Anime", "JPop", "SynthPop",
-};
-
static char *read_string(struct mp4 *f, uint32_t length)
{
char *str = para_malloc(length + 1);
return membuffer_write(buf, data, 4) == 4 ? 1 : 0;
}
-static unsigned membuffer_write_int16(struct membuffer *buf, uint16_t data)
-{
- uint8_t temp[2];
-
- write_u16_be(temp, data);
- return membuffer_write(buf, temp, 2);
-}
-
static unsigned membuffer_write_int32(struct membuffer *buf, uint32_t data)
{
uint8_t temp[4];
return membuffer_write(buf, temp, 4);
}
-static void membuffer_write_track_tag(struct membuffer *buf, const char *name,
- uint32_t index, uint32_t total)
-{
- membuffer_write_int32(buf,
- 8 /*atom header */ + 8 /*data atom header */ +
- 8 /*flags + reserved */ + 8 /*actual data */ );
- membuffer_write_atom_name(buf, name);
- membuffer_write_int32(buf,
- 8 /*data atom header */ +
- 8 /*flags + reserved */ + 8 /*actual data */ );
- membuffer_write_atom_name(buf, "data");
- membuffer_write_int32(buf, 0); //flags
- membuffer_write_int32(buf, 0); //reserved
- membuffer_write_int16(buf, 0);
- membuffer_write_int16(buf, (uint16_t) index); //track number
- membuffer_write_int16(buf, (uint16_t) total); //total tracks
- membuffer_write_int16(buf, 0);
-}
-
-static void membuffer_write_int16_tag(struct membuffer *buf, const char *name,
- uint16_t value)
-{
- membuffer_write_int32(buf,
- 8 /*atom header */ + 8 /*data atom header */ +
- 8 /*flags + reserved */ + 2 /*actual data */ );
- membuffer_write_atom_name(buf, name);
- membuffer_write_int32(buf,
- 8 /*data atom header */ +
- 8 /*flags + reserved */ + 2 /*actual data */ );
- membuffer_write_atom_name(buf, "data");
- membuffer_write_int32(buf, 0); //flags
- membuffer_write_int32(buf, 0); //reserved
- membuffer_write_int16(buf, value); //value
-}
-
-static uint32_t myatoi(const char *param)
-{
- return param ? atoi(param) : 0;
-}
-
-static uint32_t meta_genre_to_index(const char *genrestr)
-{
- unsigned n;
- for (n = 0; n < sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0]); n++) {
- if (!strcasecmp(genrestr, ID3v1GenreList[n]))
- return n + 1;
- }
- return 0;
-}
-
struct stdmeta_entry {
const char *atom;
const char *name;
struct stdmeta_entry stdmetas[] = {
{"\xA9" "nam", "title"},
{"\xA9" "ART", "artist"},
- {"\xA9" "wrt", "writer"},
{"\xA9" "alb", "album"},
{"\xA9" "day", "date"},
- {"\xA9" "too", "tool"},
{"\xA9" "cmt", "comment"},
- {"cpil", "compilation"},
- {"covr", "cover"},
- {"aART", "album_artist"},
};
static const char *find_standard_meta(const char *name) //returns atom name if found, 0 if not
membuffer_write(buf, value, strlen(value));
}
-static void membuffer_write_custom_tag(struct membuffer *buf, const char *name,
- const char *value)
-{
- membuffer_write_int32(buf,
- 8 /*atom header */ +
- 0x1C /*weirdo itunes atom */ +
- 12 /*name atom header */ + strlen(name) +
- 16 /*data atom header + flags */ + strlen(value));
- membuffer_write_atom_name(buf, "----");
- membuffer_write_int32(buf, 0x1C); //weirdo itunes atom
- membuffer_write_atom_name(buf, "mean");
- membuffer_write_int32(buf, 0);
- membuffer_write(buf, "com.apple.iTunes", 16);
- membuffer_write_int32(buf, 12 + strlen(name));
- membuffer_write_atom_name(buf, "name");
- membuffer_write_int32(buf, 0);
- membuffer_write(buf, name, strlen(name));
- membuffer_write_int32(buf,
- 8 /*data atom header */ +
- 8 /*flags + reserved */ + strlen(value));
- membuffer_write_atom_name(buf, "data");
- membuffer_write_int32(buf, 1); //flags
- membuffer_write_int32(buf, 0); //reserved
- membuffer_write(buf, value, strlen(value));
-}
-
static unsigned membuffer_error(const struct membuffer *buf)
{
return buf->error;
{
struct membuffer *buf = membuffer_create();
unsigned metaptr;
- char *mask = para_calloc(meta->count);
- const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
- const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
- const char *genre_ptr = 0, *tempo_ptr = 0;
-
- for (metaptr = 0; metaptr < meta->count; metaptr++) {
- struct mp4_tag *tag = &meta->tags[metaptr];
- if (!strcasecmp(tag->item, "tracknumber")
- || !strcasecmp(tag->item, "track")) {
- if (tracknumber_ptr == 0)
- tracknumber_ptr = tag->value;
- mask[metaptr] = 1;
- } else if (!strcasecmp(tag->item, "totaltracks")) {
- if (totaltracks_ptr == 0)
- totaltracks_ptr = tag->value;
- mask[metaptr] = 1;
- } else if (!strcasecmp(tag->item, "discnumber")
- || !strcasecmp(tag->item, "disc")) {
- if (discnumber_ptr == 0)
- discnumber_ptr = tag->value;
- mask[metaptr] = 1;
- } else if (!strcasecmp(tag->item, "totaldiscs")) {
- if (totaldiscs_ptr == 0)
- totaldiscs_ptr = tag->value;
- mask[metaptr] = 1;
- } else if (!strcasecmp(tag->item, "genre")) {
- if (genre_ptr == 0)
- genre_ptr = tag->value;
- mask[metaptr] = 1;
- } else if (!strcasecmp(tag->item, "tempo")) {
- if (tempo_ptr == 0)
- tempo_ptr = tag->value;
- mask[metaptr] = 1;
- }
- }
- if (tracknumber_ptr)
- membuffer_write_track_tag(buf, "trkn", myatoi(tracknumber_ptr),
- myatoi(totaltracks_ptr));
- if (discnumber_ptr)
- membuffer_write_track_tag(buf, "disk", myatoi(discnumber_ptr),
- myatoi(totaldiscs_ptr));
- if (tempo_ptr)
- membuffer_write_int16_tag(buf, "tmpo", myatoi(tempo_ptr));
-
- if (genre_ptr) {
- uint32_t index = meta_genre_to_index(genre_ptr);
- if (index == 0)
- membuffer_write_std_tag(buf, "©gen", genre_ptr);
- else
- membuffer_write_int16_tag(buf, "gnre", index);
- }
for (metaptr = 0; metaptr < meta->count; metaptr++) {
- struct mp4_tag *tag;
- const char *std_meta_atom;
-
- if (mask[metaptr])
- continue;
- tag = &meta->tags[metaptr];
- std_meta_atom = find_standard_meta(tag->item);
+ struct mp4_tag *tag = meta->tags + metaptr;
+ const char *std_meta_atom = find_standard_meta(tag->item);
if (std_meta_atom)
membuffer_write_std_tag(buf, std_meta_atom, tag->value);
else
- membuffer_write_custom_tag(buf, tag->item, tag->value);
+ PARA_ERROR_LOG("invalid tag item: %s\n", tag->item);
}
- free(mask);
-
if (membuffer_error(buf)) {
membuffer_free(buf);
return 0;