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