id3.c

Go to the documentation of this file.
00001 /*  Copyright (c) 2006-2007, Philip Busch <broesel@studcs.uni-sb.de>
00002  *  All rights reserved.
00003  *
00004  *  Redistribution and use in source and binary forms, with or without
00005  *  modification, are permitted provided that the following conditions are met:
00006  *
00007  *   - Redistributions of source code must retain the above copyright notice,
00008  *     this list of conditions and the following disclaimer.
00009  *   - Redistributions in binary form must reproduce the above copyright
00010  *     notice, this list of conditions and the following disclaimer in the
00011  *     documentation and/or other materials provided with the distribution.
00012  *
00013  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00014  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00015  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00016  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00017  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00018  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00019  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00020  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00021  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00022  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00023  *  POSSIBILITY OF SUCH DAMAGE.
00024  */
00025 
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <assert.h>
00029 #include <stdlib.h>
00030 #include "id3.h"
00031 
00032 int id3_read(const char *_path, struct id3 *_id3)
00033 {
00034         char tmp[TAG_LENGTH];
00035 
00036         assert(_path != NULL);
00037         assert(_id3 != NULL);
00038 
00039         if(id3_read_tag(_path, tmp) < 0)
00040                 return(-1);
00041 
00042         if(id3_check_tag(tmp) < 0)
00043                 return(-1);
00044 
00045         if(id3_extract_info(tmp, _id3) < 0)
00046                 return(-1);
00047 
00048         id3_normalize_info(_id3);
00049 
00050         return(0);
00051 }
00052 
00053 int id3_write(const char *_path, struct id3 *_id3)
00054 {
00055         struct id3 tmp;
00056         FILE *fp;
00057 
00058         assert(_id3 != NULL);
00059         assert(_path != NULL);
00060 
00061         if((fp = fopen(_path, "r+")) == NULL)
00062                 return(-1);
00063 
00064         if(id3_read(_path, &tmp) == 0) {
00065                 if(fseek(fp, -1 * TAG_LENGTH, SEEK_END) == -1)
00066                         return(-1);
00067         } else {
00068                 if(fseek(fp, 0, SEEK_END) == -1)
00069                         return(-1);
00070         }
00071 
00072         id3_write_tag(fp, _id3);
00073 
00074         fclose(fp);
00075 
00076         return(0);
00077 }
00078 
00079 void id3_print(struct id3 *_id3)
00080 {
00081         char genre[1024];
00082 
00083         assert(_id3 != NULL);
00084 
00085         id3_get_genre_as_string(_id3, genre);
00086 
00087         printf("Title..: %s\n", _id3->title);
00088         printf("Artist.: %s\n", _id3->artist);
00089         printf("Album..: %s\n", _id3->album);
00090         printf("Year...: %s\n", _id3->year);
00091         printf("Comment: %s\n", _id3->comment);
00092         printf("Genre..: %s (%d)\n", genre, _id3->genre);
00093         printf("Track..: %d\n", _id3->track);
00094 }
00095 
00096 int id3_read_tag(const char *_path, char *_tag)
00097 {
00098         FILE *fp;
00099         int i;
00100         
00101         assert(_path != NULL);
00102         assert(_tag != NULL);
00103 
00104         if((fp = fopen(_path, "r")) == NULL)
00105                 return(-1);
00106 
00107         if(fseek(fp, -1 * TAG_LENGTH, SEEK_END) == -1)
00108                 return(-1);
00109 
00110         for(i = 0; i < TAG_LENGTH; i++) {
00111                 _tag[i] = fgetc(fp);
00112         }
00113 
00114         fclose(fp);
00115 
00116         return(0);
00117 }
00118 
00119 int id3_write_tag(FILE *_fp, struct id3 *_id3)
00120 {
00121         assert(_fp != NULL);
00122         assert(_id3 != NULL);
00123 
00124         fprintf(_fp, "TAG");
00125         write_with_padding(_fp, _id3->title, SIZE_INFO);
00126         write_with_padding(_fp, _id3->artist, SIZE_INFO);
00127         write_with_padding(_fp, _id3->album, SIZE_INFO);
00128         write_with_padding(_fp, _id3->year, SIZE_YEAR);
00129         write_with_padding(_fp, _id3->comment, SIZE_INFO);
00130 
00131         if(_id3->track != 0) {
00132                 fseek(_fp, -1, SEEK_CUR);
00133                 fprintf(_fp, "%c", _id3->track);
00134         }
00135 
00136         fprintf(_fp, "%c",   _id3->genre);
00137 
00138         return(0);
00139 }
00140 
00141 int id3_check_tag(const char *_tag)
00142 {
00143         assert(_tag != NULL);
00144 
00145         if((_tag[0] != 'T') || (_tag[1] != 'A') || (_tag[2] != 'G'))
00146                 return(-1);
00147 
00148         return(0);
00149 }
00150 
00151 
00152 int id3_extract_info(const char *_tag, struct id3 *_id3)
00153 {
00154         assert(_tag != NULL);
00155         assert(_id3 != NULL);
00156 
00157         memcpy(_id3->title,   _tag + OFFSET_TITLE,   SIZE_INFO);
00158         memcpy(_id3->artist,  _tag + OFFSET_ARTIST,  SIZE_INFO);
00159         memcpy(_id3->album,   _tag + OFFSET_ALBUM,   SIZE_INFO);
00160         memcpy(_id3->year,    _tag + OFFSET_YEAR,    SIZE_YEAR);
00161         memcpy(_id3->comment, _tag + OFFSET_COMMENT, SIZE_INFO);
00162 
00163         _id3->track = (_tag[OFFSET_TRACK] == '\0')?0:_tag[OFFSET_TRACK];
00164         _id3->genre = _tag[OFFSET_GENRE];
00165 
00166         _id3->title[30]   = '\0';
00167         _id3->artist[30]  = '\0';
00168         _id3->album[30]   = '\0';
00169         _id3->year[4]     = '\0';
00170         _id3->comment[30] = '\0';
00171 
00172         return(0);
00173 }
00174 
00175 static void remove_trailing_whitespaces(char *_str)
00176 {
00177         int i, size;
00178         
00179         assert(_str != NULL);
00180 
00181         if(_str == NULL)
00182                 return;
00183         
00184         size = strlen(_str);
00185         
00186         for(i = size - 1; i >= 0; i--) {
00187                 if(_str[i] == ' ') {
00188                         _str[i] = '\0';
00189                 } else break;
00190         }
00191 }
00192 
00193 void id3_normalize_info(struct id3 *_id3)
00194 {
00195         assert(_id3 != NULL);
00196 
00197         remove_trailing_whitespaces(_id3->title);
00198         remove_trailing_whitespaces(_id3->artist);
00199         remove_trailing_whitespaces(_id3->album);
00200         remove_trailing_whitespaces(_id3->comment);
00201 }
00202 
00203 void id3_get_genre_as_string(struct id3 *_id3, char *_genre)
00204 {
00205         assert(_id3 != NULL);
00206         assert(_genre != NULL);
00207 
00208         if(_id3->genre > GENRE_MAX) {
00209                 strcpy(_genre, "Unknown");
00210         } else {
00211                 strcpy(_genre, genres[_id3->genre]);
00212         }
00213 }
00214 
00215 static void write_with_padding(FILE *_fp, const char *_str, size_t _len)
00216 {
00217         unsigned int i;
00218 
00219         assert(_fp != NULL);
00220         assert(_str != NULL);
00221 
00222         fprintf(_fp, "%s", _str);
00223 
00224         for(i = 0; i < _len - strlen(_str); i++) {
00225                 fprintf(_fp, "%c", '\0');
00226         }
00227 }
00228 
00229 int main()
00230 {
00231         struct id3 id3;
00232         struct id3 tmp;
00233         
00234         strcpy(tmp.title, "Englishman in New York");
00235         strcpy(tmp.artist, "Sting");
00236         strcpy(tmp.album, "Album");
00237         strcpy(tmp.year, "Year");
00238         strcpy(tmp.comment, "Comment");
00239         tmp.genre = 24;
00240         tmp.track = 4;
00241 
00242         id3_write("sting.mp3", &tmp);
00243         id3_read("sting.mp3", &id3);
00244         id3_print(&id3);
00245 
00246         system("PAUSE");
00247         return(0);
00248 }

Generated on Thu Jul 19 13:36:09 2007 for libv by  doxygen 1.5.1-p1. Thank you, SourceForge.net Logo