1 #include "id3parse.h"
2 #include "genretab.h"
3 #include <string.h>
4 #include <errno.h>
5
6 /* tampers with 's' to replace non-printable chars with dots. */
7 void
convert_to_sane_string(char * s)8 convert_to_sane_string(char *s)
9 {
10 unsigned int
11 cnt = strlen(s),
12 i;
13
14 for (i = 0; i < cnt; i++)
15 {
16 if (s[i] < (char)32)
17 s[i] = '.';
18 }
19 }
20
id3Parse(const char * filename)21 id3Parse::id3Parse(const char *filename)
22 {
23 flnam = new char[strlen(filename)+1];
24 strcpy(flnam, filename);
25
26 song = new id3header;
27 memset(song->songname, 0, 31 * sizeof (char));
28 memset(song->artist, 0, 31 * sizeof (char));
29 memset(song->type, 0, 31 * sizeof (char));
30 memset(song->year, 0, 5 * sizeof (char));
31 memset(song->etc, 0, 31 * sizeof (char));
32 song->genre = '\0';
33 song->track = -1;
34 //memset(song->genre_txt, 0, 41 * sizeof (char));
35 //strncpy(song->genre_txt, "Not supported yet!",40);
36 }
37
~id3Parse()38 id3Parse::~id3Parse()
39 {
40 delete song;
41 delete[] flnam;
42 }
43
44 int
search_header(FILE * fp)45 id3Parse::search_header(FILE *fp)
46 {
47 int c, flag = 0, success = 0;
48
49 if ( fseek(fp, -128, SEEK_END) < 0)
50 return success;
51
52 for(;;)
53 {
54 if ( (c = fgetc(fp)) < 0)
55 break;
56 if (c == 0x54)
57 {
58 if ( fgetc(fp) == 0x41)
59 {
60 if (fgetc(fp) == 0x47)
61 {
62 success = 1;
63 break;
64 }
65 }
66 flag = 0;
67 }
68 else
69 flag = 0;
70 }
71
72 return success;
73 }
74
75 const char *
getGenre(const unsigned char genre)76 id3Parse::getGenre(const unsigned char genre)
77 {
78 #if 0
79 int i;
80 struct _genre_table *tmp=&genre_table[0];
81
82 for(i=0;tmp[i].text != NULL;i++) {
83 if(tmp[i].genre == genre)
84 return tmp[i].text;
85 }
86
87 return "Unknown type";
88 #endif
89 return genre_table[genre];
90 }
91
92 struct id3header *
parseID3()93 id3Parse::parseID3()
94 {
95 FILE *fp;
96 int success = 0;
97
98 if (!(fp = fopen(flnam, "r")))
99 return NULL;
100 if (!search_header(fp))
101 {
102 fclose(fp);
103 return NULL;
104 }
105
106 char buf[40];
107
108 if (fread(buf, 30, sizeof(char), fp) == sizeof(char))
109 {
110 strncpy(song->songname, buf, 30);
111 song->songname[30] = '\0';
112 convert_to_sane_string(song->songname);
113 success++;
114 }
115 if (fread(buf, 30, sizeof(char), fp) == sizeof(char))
116 {
117 strncpy(song->artist, buf, 30);
118 song->artist[30] = '\0';
119 convert_to_sane_string(song->artist);
120 success++;
121 }
122 if (fread(buf, 30, sizeof(char), fp) == sizeof(char))
123 {
124 strncpy(song->type, buf, 30);
125 song->type[30] = '\0';
126 convert_to_sane_string(song->type);
127 success++;
128 }
129 if (fread(buf, 4, sizeof(char), fp) == sizeof(char))
130 {
131 strncpy(song->year, buf, 4);
132 song->year[4] = '\0';
133 convert_to_sane_string(song->year);
134 success++;
135 }
136 if (fread(buf, 30, sizeof(char), fp) == sizeof(char))
137 {
138 strncpy(song->etc, buf, 30);
139 song->etc[30] = '\0';
140 if (buf[28] == '\0' && buf[29] != '\0')
141 {
142 //ID3V1.1 Standard - specify track in last byte of comment field
143 song->track = buf[29];
144 }
145 convert_to_sane_string(song->etc);
146 success++;
147 }
148 if (fread(buf, 1, sizeof(char), fp) == sizeof(char))
149 {
150 song->genre = (unsigned char)buf[0];
151 success++;
152 }
153 fclose(fp);
154
155 if (success == 6)
156 return song;
157 else
158 return NULL;
159 }
160
161 int
appendNewID3Header(FILE * fp)162 id3Parse::appendNewID3Header(FILE *fp)
163 {
164 int success = 0;
165
166 if (fseek(fp, 0, SEEK_END) < 0)
167 return success;
168
169 char c[] = {
170 0x54, 0x41, 0x47 };
171
172 printf("Writing header..\n");
173 if ( fwrite((void*)c, sizeof(char), 3, fp) != 3)
174 return success;
175
176 return (success = 1);
177 }
178
179 int
writeID3(struct id3header * newID3)180 id3Parse::writeID3(struct id3header *newID3)
181 {
182 int success = 0;
183 FILE *fp = fopen(flnam, "r+");
184
185 if (!fp)
186 return success;
187
188 if (!search_header(fp) && !(appendNewID3Header(fp)))
189 {
190 fclose(fp);
191 return success;
192 }
193
194 if (newID3->track != -1)
195 {
196 //ID3V1.1 standard.
197 newID3->etc[28] = '\0';
198 newID3->etc[29] = newID3->track;
199 }
200
201 //In ANSI C it's required to do an intervening file positioning function
202 //before mixing read/write on a stream..
203 fseek(fp, ftell(fp), SEEK_SET);
204
205 if (
206 (fwrite(newID3->songname, sizeof(char), 30, fp) == 30) &&
207 (fwrite(newID3->artist, sizeof(char), 30, fp) == 30) &&
208 (fwrite(newID3->type, sizeof(char), 30, fp) == 30) &&
209 (fwrite(newID3->year, sizeof(char), 4, fp) == 4) &&
210 (fwrite(newID3->etc, sizeof(char), 30, fp) == 30) &&
211 (fwrite(&(newID3->genre), sizeof(char), 1, fp) == 1))
212 success = 1;
213
214 fclose(fp);
215 return success;
216 }
217