home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 13 / AACD13.ISO / AACD / Sound / LAME / src / id3tag.c < prev    next >
C/C++ Source or Header  |  2000-07-03  |  17KB  |  506 lines

  1. /*
  2.  * id3tag.c -- Write ID3 version 1 and 2 tags.
  3.  *
  4.  * Copyright (C) 2000 Don Melton.
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Library General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Library General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Library General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  19.  */
  20.  
  21. /*
  22.  * HISTORY: This source file is part of LAME (see http://sulaco.org/mp3/) and
  23.  * was originally adapted by Conrad Sanderson <c.sanderson@me.gu.edu.au> from
  24.  * mp3info by Ricardo Cerqueira <rmc@rccn.net> to write only ID3 version 1 tags.
  25.  * Don Melton <don@blivet.com> COMPLETELY rewrote it to support version 2 tags,
  26.  * be more conformant to other standards while remaining flexible, and be more
  27.  * independent from LAME's APIs and data structures.
  28.  *
  29.  * NOTE: See http://id3.org/ for more information about ID3 tag formats.
  30.  */
  31.  
  32. #include "id3tag.h"
  33. #include <stddef.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <ctype.h>
  37.  
  38. static const char *genre_names[] =
  39. {
  40.     /*
  41.      * NOTE: The spelling of these genre names is identical to those found in
  42.      * Winamp and mp3info.
  43.      */
  44.     "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
  45.     "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B",
  46.     "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
  47.     "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop",
  48.     "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
  49.     "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alt. Rock",
  50.     "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
  51.     "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial",
  52.     "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
  53.     "Cult", "Gangsta Rap", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
  54.     "Native American", "Cabaret", "New Wave", "Psychedelic", "Rave",
  55.     "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz",
  56.     "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk",
  57.     "Folk/Rock", "National Folk", "Swing", "Fast-Fusion", "Bebob", "Latin",
  58.     "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock",
  59.     "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock",
  60.     "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech",
  61.     "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
  62.     "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
  63.     "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
  64.     "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall",
  65.     "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie",
  66.     "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap",
  67.     "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
  68.     "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
  69.     "Synthpop"
  70. };
  71.  
  72. #define GENRE_NAME_COUNT ((int)(sizeof genre_names / sizeof (const char *)))
  73.  
  74. static const int genre_alpha_map[] = {
  75.     123, 34, 74, 73, 99, 20, 40, 26, 145, 90, 116, 41, 135, 85, 96, 138, 89, 0,
  76.     107, 132, 65, 88, 104, 102, 97, 136, 61, 141, 32, 1, 112, 128, 57, 140, 2,
  77.     139, 58, 3, 125, 50, 22, 4, 55, 127, 122, 120, 98, 52, 48, 54, 124, 25, 84,
  78.     80, 115, 81, 119, 5, 30, 36, 59, 126, 38, 49, 91, 6, 129, 79, 137, 7, 35,
  79.     100, 131, 19, 33, 46, 47, 8, 29, 146, 63, 86, 71, 45, 142, 9, 77, 82, 64,
  80.     133, 10, 66, 39, 11, 103, 12, 75, 134, 13, 53, 62, 109, 117, 23, 108, 92,
  81.     67, 93, 43, 121, 15, 68, 14, 16, 76, 87, 118, 17, 78, 143, 114, 110, 69, 21,
  82.     111, 95, 105, 42, 37, 24, 56, 44, 101, 83, 94, 106, 147, 113, 18, 51, 130,
  83.     144, 60, 70, 31, 72, 27, 28
  84. };
  85.  
  86. #define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int)))
  87.  
  88. void
  89. id3tag_genre_list(void (*handler)(int, const char *, void *), void *cookie)
  90. {
  91.     if (handler) {
  92.         int i;
  93.         for (i = 0; i < GENRE_NAME_COUNT; ++i) {
  94.             if (i < GENRE_ALPHA_COUNT) {
  95.                 int j = genre_alpha_map[i];
  96.                 handler(j, genre_names[j], cookie);
  97.             }
  98.         }
  99.     }
  100. }
  101.  
  102. #define GENRE_NUM_UNKNOWN 255
  103.  
  104. void
  105. id3tag_init(struct id3tag_spec *spec)
  106. {
  107.     if (spec) {
  108.         memset(spec, 0, sizeof spec);
  109.         spec->genre = GENRE_NUM_UNKNOWN;
  110.     }
  111. }
  112.  
  113. #define CHANGED_FLAG    (1U << 0)
  114. #define ADD_V2_FLAG     (1U << 1)
  115. #define V1_ONLY_FLAG    (1U << 2)
  116. #define V2_ONLY_FLAG    (1U << 3)
  117. #define SPACE_V1_FLAG   (1U << 4)
  118. #define PAD_V2_FLAG     (1U << 5)
  119.  
  120. void
  121. id3tag_add_v2(struct id3tag_spec *spec)
  122. {
  123.     if (spec) {
  124.         spec->flags &= ~V1_ONLY_FLAG;
  125.         spec->flags |= ADD_V2_FLAG;
  126.     }
  127. }
  128.  
  129. void
  130. id3tag_v1_only(struct id3tag_spec *spec)
  131. {
  132.     if (spec) {
  133.         spec->flags &= ~(ADD_V2_FLAG | V2_ONLY_FLAG);
  134.         spec->flags |= V1_ONLY_FLAG;
  135.     }
  136. }
  137.  
  138. void
  139. id3tag_v2_only(struct id3tag_spec *spec)
  140. {
  141.     if (spec) {
  142.         spec->flags &= ~V1_ONLY_FLAG;
  143.         spec->flags |= V2_ONLY_FLAG;
  144.     }
  145. }
  146.  
  147. void
  148. id3tag_space_v1(struct id3tag_spec *spec)
  149. {
  150.     if (spec) {
  151.         spec->flags &= ~V2_ONLY_FLAG;
  152.         spec->flags |= SPACE_V1_FLAG;
  153.     }
  154. }
  155.  
  156. void
  157. id3tag_pad_v2(struct id3tag_spec *spec)
  158. {
  159.     if (spec) {
  160.         spec->flags &= ~V1_ONLY_FLAG;
  161.         spec->flags |= PAD_V2_FLAG;
  162.     }
  163. }
  164.  
  165. void
  166. id3tag_set_title(struct id3tag_spec *spec, const char *title)
  167. {
  168.     if (spec && title && *title) {
  169.         spec->title = title;
  170.         spec->flags |= CHANGED_FLAG;
  171.     }
  172. }
  173.  
  174. void
  175. id3tag_set_artist(struct id3tag_spec *spec, const char *artist)
  176. {
  177.     if (spec && artist && *artist) {
  178.         spec->artist = artist;
  179.         spec->flags |= CHANGED_FLAG;
  180.     }
  181. }
  182.  
  183. void
  184. id3tag_set_album(struct id3tag_spec *spec, const char *album)
  185. {
  186.     if (spec && album && *album) {
  187.         spec->album = album;
  188.         spec->flags |= CHANGED_FLAG;
  189.     }
  190. }
  191.  
  192. void
  193. id3tag_set_year(struct id3tag_spec *spec, const char *year)
  194. {
  195.     if (spec && year && *year) {
  196.         int num = atoi(year);
  197.         if (num < 0) {
  198.             num = 0;
  199.         }
  200.         /* limit a year to 4 digits so they fit in version 1 tags */
  201.         if (num > 9999) {
  202.             num = 9999;
  203.         }
  204.         if (num) {
  205.             spec->year = num;
  206.             spec->flags |= CHANGED_FLAG;
  207.         }
  208.     }
  209. }
  210.  
  211. void
  212. id3tag_set_comment(struct id3tag_spec *spec, const char *comment)
  213. {
  214.     if (spec && comment && *comment) {
  215.         spec->comment = comment;
  216.         spec->flags |= CHANGED_FLAG;
  217.     }
  218. }
  219.  
  220. void
  221. id3tag_set_track(struct id3tag_spec *spec, const char *track)
  222. {
  223.     if (spec && track && *track) {
  224.         int num = atoi(track);
  225.         if (num < 0) {
  226.             num = 0;
  227.         }
  228.         /* limit a track to 99 because CD audio doesn't allow more anyway */
  229.         if (num > 99) {
  230.             num = 99;
  231.         }
  232.         if (num) {
  233.             spec->track = num;
  234.             spec->flags |= CHANGED_FLAG;
  235.         }
  236.     }
  237. }
  238.  
  239. /* would use real "strcasecmp" but it isn't portable */
  240. static int
  241. local_strcasecmp(const char *s1, const char *s2)
  242. {
  243.     unsigned char c1;
  244.     unsigned char c2;
  245.     do {
  246.         c1 = tolower(*s1);
  247.         c2 = tolower(*s2);
  248.         if (!c1) {
  249.             break;
  250.         }
  251.         ++s1;
  252.         ++s2;
  253.     } while (c1 == c2);
  254.     return c1 - c2;
  255. }
  256.  
  257. int
  258. id3tag_set_genre(struct id3tag_spec *spec, const char *genre)
  259. {
  260.     if (spec && genre && *genre) {
  261.         char *str;
  262.         int num = strtol(genre, &str, 10);
  263.         /* is the input a string or a valid number? */
  264.         if (*str) {
  265.             int i;
  266.             for (i = 0; i < GENRE_NAME_COUNT; ++i) {
  267.                 if (!local_strcasecmp(genre, genre_names[i])) {
  268.                     num = i;
  269.                     break;
  270.                 }
  271.             }
  272.             if (i == GENRE_NAME_COUNT) {
  273.                 return -1;
  274.             }
  275.         } else if ((num < 0) || (num >= GENRE_NAME_COUNT)) {
  276.             return -1;
  277.         }
  278.         spec->genre = num;
  279.         spec->flags |= CHANGED_FLAG;
  280.     }
  281.     return 0;
  282. }
  283.  
  284. static unsigned char *
  285. set_4_byte_value(unsigned char *bytes, unsigned long value)
  286. {
  287.     int index;
  288.     for (index = 3; index >= 0; --index) {
  289.         bytes[index] = value & 0xfful;
  290.         value >>= 8;
  291.     }
  292.     return bytes + 4;
  293. }
  294.  
  295. #define FRAME_ID(a, b, c, d) \
  296.     (((unsigned long)(a) << 24) \
  297.     | ((unsigned long)(b) << 16) \
  298.     | ((unsigned long)(c) << 8) \
  299.     | (unsigned long)(d))
  300. #define TITLE_FRAME_ID FRAME_ID('T', 'I', 'T', '2')
  301. #define ARTIST_FRAME_ID FRAME_ID('T', 'P', 'E', '1')
  302. #define ALBUM_FRAME_ID FRAME_ID('T', 'A', 'L', 'B')
  303. #define YEAR_FRAME_ID FRAME_ID('T', 'Y', 'E', 'R')
  304. #define TRACK_FRAME_ID FRAME_ID('T', 'R', 'C', 'K')
  305. #define GENRE_FRAME_ID FRAME_ID('T', 'C', 'O', 'N')
  306. #define COMMENT_FRAME_ID FRAME_ID('C', 'O', 'M', 'M')
  307.  
  308. static unsigned char *
  309. set_frame(unsigned char *frame, unsigned long id, const char *text,
  310.     size_t length)
  311. {
  312.     if (length) {
  313.         size_t clear;
  314.         frame = set_4_byte_value(frame, id);
  315.         /* calulate size of cleared frame header and field bytes,
  316.          * including 2-byte header flags, 1 encoding descriptor byte,
  317.          * and for comment frames: 3-byte language descriptor and
  318.          * 1 content descriptor byte */
  319.         clear = (id == COMMENT_FRAME_ID) ? 7 : 3;
  320.         /* set frame size = total size - header size */
  321.         frame = set_4_byte_value(frame, (clear - 2) + length);
  322.  
  323.         /*
  324.          * NOTE: Since the encoding descriptor is set to zero here, that
  325.          * means all text is in ISO-8859-1 format.  And since the language
  326.          * descriptor is also set to zero, that means the language is not
  327.          * specified.
  328.          */
  329.  
  330.         while (clear--) {
  331.             *frame++ = 0;
  332.         }
  333.         while (length--) {
  334.             *frame++ = *text++;
  335.         }
  336.     }
  337.     return frame;
  338. }
  339.  
  340. int
  341. id3tag_write_v2(struct id3tag_spec *spec, FILE *stream)
  342. {
  343.     if (!spec || !stream) {
  344.         return -1;
  345.     }
  346.     if ((spec->flags & CHANGED_FLAG) && !(spec->flags & V1_ONLY_FLAG)) {
  347.         /* calculate length of four fields which may not fit in verion 1 tag */
  348.         size_t title_length = spec->title ? strlen(spec->title) : 0;
  349.         size_t artist_length = spec->artist ? strlen(spec->artist) : 0;
  350.         size_t album_length = spec->album ? strlen(spec->album) : 0;
  351.         size_t comment_length = spec->comment ? strlen(spec->comment) : 0;
  352.         /* wrtie tag if explicitly requested or if fields overflow */
  353.         if ((spec->flags & (ADD_V2_FLAG | V2_ONLY_FLAG)) || (title_length > 30)
  354.             || (artist_length > 30) || (album_length > 30)
  355.             || (comment_length > 30) || (spec->track & (comment_length > 28))) {
  356.             size_t tag_size;
  357.             char year[5];
  358.             size_t year_length;
  359.             char track[3];
  360.             size_t track_length;
  361.             const char *genre = NULL;
  362.             size_t genre_length;
  363.             unsigned char *tag;
  364.             unsigned char *p;
  365.             size_t adjusted_tag_size;
  366.             /* calulate size of tag starting with 10-byte tag header */
  367.             tag_size = 10;
  368.             if (title_length) {
  369.                 /* add 10-byte frame header, 1 encoding descriptor byte ... */
  370.                 tag_size += 11 + title_length;
  371.             }
  372.             if (artist_length) {
  373.                 tag_size += 11 + artist_length;
  374.             }
  375.             if (album_length) {
  376.                 tag_size += 11 + album_length;
  377.             }
  378.             if (spec->year) {
  379.                 sprintf(year, "%d", spec->year);
  380.                 year_length = strlen(year);
  381.                 tag_size += 11 + year_length;
  382.             } else {
  383.                 year_length = 0;
  384.             }
  385.             if (spec->track) {
  386.                 sprintf(track, "%d", spec->track);
  387.                 track_length = strlen(track);
  388.                 tag_size += 11 + track_length;
  389.             } else {
  390.                 track_length = 0;
  391.             }
  392.             if (spec->genre != GENRE_NUM_UNKNOWN) {
  393.                 genre = genre_names[spec->genre];
  394.                 genre_length = strlen(genre);
  395.                 tag_size += 11 + genre_length;
  396.             } else {
  397.                 genre_length = 0;
  398.             }
  399.             if (comment_length) {
  400.                 /* add 10-byte frame header, 1 encoding descriptor byte,
  401.                  * 3-byte language descriptor, 1 content descriptor byte ... */
  402.                 tag_size += 15 + comment_length;
  403.             }
  404.             if (spec->flags & PAD_V2_FLAG) {
  405.                 /* add 128 bytes of padding */
  406.                 tag_size += 128;
  407.             }
  408.             tag = (unsigned char *)malloc(tag_size);
  409.             if (!tag) {
  410.                 return -1;
  411.             }
  412.             p = tag;
  413.             /* set tag header starting with file identifier */
  414.             *p++ = 'I'; *p++ = 'D'; *p++ = '3';
  415.             /* set version number word */
  416.             *p++ = 3; *p++ = 0;
  417.             /* clear flags byte */
  418.             *p++ = 0;
  419.             /* calculate and set tag size = total size - header size */
  420.             adjusted_tag_size = tag_size - 10;
  421.             /* encode adjusted size into four bytes where most significant 
  422.              * bit is clear in each byte, for 28-bit total */
  423.             *p++ = (adjusted_tag_size >> 21) & 0x7fu;
  424.             *p++ = (adjusted_tag_size >> 14) & 0x7fu;
  425.             *p++ = (adjusted_tag_size >> 7) & 0x7fu;
  426.             *p++ = adjusted_tag_size & 0x7fu;
  427.  
  428.             /*
  429.              * NOTE: The remainder of the tag (frames and padding, if any)
  430.              * are not "unsynchronized" to prevent false MPEG audio headers
  431.              * from appearing in the bitstream.  Why?  Well, most players
  432.              * and utilities know how to skip the ID3 version 2 tag by now
  433.              * even if they don't read its contents, and it's actually
  434.              * very unlikely that such a false "sync" pattern would occur
  435.              * in just the simple text frames added here.
  436.              */
  437.  
  438.             /* set each frame in tag */
  439.             p = set_frame(p, TITLE_FRAME_ID, spec->title, title_length);
  440.             p = set_frame(p, ARTIST_FRAME_ID, spec->artist, artist_length);
  441.             p = set_frame(p, ALBUM_FRAME_ID, spec->album, album_length);
  442.             p = set_frame(p, YEAR_FRAME_ID, year, year_length);
  443.             p = set_frame(p, TRACK_FRAME_ID, track, track_length);
  444.             p = set_frame(p, GENRE_FRAME_ID, genre, genre_length);
  445.             p = set_frame(p, COMMENT_FRAME_ID, spec->comment, comment_length);
  446.             /* clear any padding bytes */
  447.             memset(p, 0, tag_size - (p - tag));
  448.             /* write tag into stream at current position */
  449.             if (fwrite(tag, 1, tag_size, stream) != tag_size) {
  450.                 free(tag);
  451.                 return -1;
  452.             }
  453.             free(tag);
  454.         }
  455.     }
  456.     return 0;
  457. }
  458.  
  459. static unsigned char *
  460. set_text_field(unsigned char *field, const char *text, size_t size, int pad)
  461. {
  462.     while (size--) {
  463.         if (text && *text) {
  464.             *field++ = *text++;
  465.         } else {
  466.             *field++ = pad;
  467.         }
  468.     }
  469.     return field;
  470. }
  471.  
  472. int
  473. id3tag_write_v1(struct id3tag_spec *spec, FILE *stream)
  474. {
  475.     if (!spec || !stream) {
  476.         return -1;
  477.     }
  478.     if ((spec->flags & CHANGED_FLAG) && !(spec->flags & V2_ONLY_FLAG)) {
  479.         unsigned char tag[128];
  480.         unsigned char *p = tag;
  481.         int pad = (spec->flags & SPACE_V1_FLAG) ? ' ' : 0;
  482.         char year[5];
  483.         /* set tag identifier */
  484.         *p++ = 'T'; *p++ = 'A'; *p++ = 'G';
  485.         /* set each field in tag */
  486.         p = set_text_field(p, spec->title, 30, pad);
  487.         p = set_text_field(p, spec->artist, 30, pad);
  488.         p = set_text_field(p, spec->album, 30, pad);
  489.         sprintf(year, "%d", spec->year);
  490.         p = set_text_field(p, spec->year ? year : NULL, 4, pad);
  491.         /* limit comment field to 28 bytes if a track is specified */
  492.         p = set_text_field(p, spec->comment, spec->track ? 28 : 30, pad);
  493.         if (spec->track) {
  494.             /* clear the next byte to indicate a version 1.1 tag */
  495.             *p++ = 0;
  496.             *p++ = spec->track;
  497.         }
  498.         *p++ = spec->genre;
  499.         /* write tag into stream at current position */
  500.         if (fwrite(tag, 1, sizeof tag, stream) != sizeof tag) {
  501.             return -1;
  502.         }
  503.     }
  504.     return 0;
  505. }
  506.