00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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 }