source: titan/titan/id3.h @ 40399

Last change on this file since 40399 was 37216, checked in by obi, 8 years ago

fix compiler warnings

File size: 20.2 KB
Line 
1#ifndef ID3_H
2#define ID3_H
3
4#define TMPID3PICJPG "/tmp/id3pic.jpg"
5#define TMPID3PICPNG "/tmp/id3pic.png"
6
7struct id3genre id3genrelist[] =
8{
9        {0 , "Blues"}, {1 , "Classic Rock"}, {2 , "Country"}, {3 , "Dance"}, {4 , "Disco"}, {5 , "Funk"}, {6 , "Grunge"}, {7 , "Hip-Hop"}, {8 , "Jazz"}, {9 , "Metal"}, {10 , "New Age"},
10        {11 , "Oldies"}, {12 , "Other"}, {13 , "Pop"}, {14 , "R&B"}, {15 , "Rap"}, {16 , "Reggae"}, {17 , "Rock"}, {18 , "Techno"}, {19 , "Industrial"}, {20 , "Alternative"},
11        {21 , "Ska"}, {22 , "Death Metal"}, {23 , "Pranks"}, {24 , "Soundtrack"}, {25 , "Euro-Techno"}, {26 , "Ambient"}, {27 , "Trip-Hop"}, {28 , "Vocal"}, {29 , "Jazz+Funk"}, {30 , "Fusion"},
12        {31 , "Trance"}, {32 , "Classical"}, {33 , "Instrumental"}, {34 , "Acid"}, {35 , "House"}, {36 , "Game"}, {37 , "Sound Clip"}, {38 , "Gospel"}, {39 , "Noise"}, {40 , "Alternative Rock"},
13        {41 , "Bass"}, {42 , "Soul"}, {43 , "Punk"}, {44 , "Space"}, {45 , "Meditative"}, {46 , "Instrumental Pop"}, {47 , "Instrumental Rock"}, {48 , "Ethnic"}, {49 , "Gothic"}, {50 , "Darkwave"},
14        {51 , "Techno-Industrial"}, {52 , "Electronic"}, {53 , "Pop-Folk"}, {54 , "Eurodance"}, {55 , "Dream"}, {56 , "Southern Rock"}, {57 , "Comedy"}, {58 , "Cult"}, {59 , "Gangsta"}, {60 , "Top 40"},
15        {61 , "Christian Rap"}, {62 , "Pop/Funk"}, {63 , "Jungle"}, {64 , "Native US"}, {65 , "Cabaret"}, {66 , "New Wave"}, {67 , "Psychadelic"}, {68 , "Rave"}, {69 , "Showtunes"}, {70 , "Trailer"},
16        {71 , "Lo-Fi"}, {72 , "Tribal"}, {73 , "Acid Punk"}, {74 , "Acid Jazz"}, {75 , "Polka"}, {76 , "Retro"}, {77 , "Musical"}, {78 , "Rock & Roll"}, {79 , "Hard Rock"}, {80 , "Folk"},
17        {81 , "Folk-Rock"}, {82 , "National Folk"}, {83 , "Swing"}, {84 , "Fast Fusion"}, {85 , "Bebob"}, {86 , "Latin"}, {87 , "Revival"}, {88 , "Celtic"}, {89 , "Bluegrass"}, {90 , "Avantgarde"},
18        {91 , "Gothic Rock"}, {92 , "Progressive Rock"}, {93 , "Psychedelic Rock"}, {94 , "Symphonic Rock"}, {95 , "Slow Rock"}, {96 , "Big Band"}, {97 , "Chorus"}, {98 , "Easy Listening"}, {99 , "Acoustic"},
19        {100 , "Humour"}, {101 , "Speech"}, {102 , "Chanson"}, {103 , "Opera"}, {104 , "Chamber Music"}, {105 , "Sonata"}, {106 , "Symphony"}, {107 , "Booty Bass"}, {108 , "Primus"}, {109 , "Porn Groove"},
20        {110 , "Satire"}, {111 , "Slow Jam"}, {112 , "Club"}, {113 , "Tango"}, {114 , "Samba"}, {115 , "Folklore"}, {116 , "Ballad"}, {117 , "Power Ballad"}, {118 , "Rhytmic Soul"}, {119 , "Freestyle"}, {120 , "Duet"},
21        {121 , "Punk Rock"}, {122 , "Drum Solo"}, {123 , "A capella"}, {124 , "Euro-House"}, {125 , "Dance Hall"}, {126 , "Goa"}, {127 , "Drum & Bass"}, {128 , "Club-House"}, {129 , "Hardcore"}, {130 , "Terror"},
22        {131 , "Indie"}, {132 , "BritPop"}, {133 , "Negerpunk"}, {134 , "Polsk Punk"}, {135 , "Beat"}, {136 , "Christian Gangsta"}, {137 , "Heavy Metal"}, {138 , "Black Metal"}, {139 , "Crossover"}, {140 , "Contemporary C"},
23        {141 , "Christian Rock"}, {142 , "Merengue"}, {143 , "Salsa"}, {144 , "Thrash Metal"}, {145 , "Anime"}, {146 , "JPop"}, {147 , "SynthPop"}
24};
25
26void id3debug(struct id3tag* node)
27{
28        if(node == NULL) return;
29
30        debug(278, "Version: %d", node->version);
31        debug(278, "Title: %s", node->title);
32        debug(278, "Artist: %s", node->artist);
33        debug(278, "Album: %s", node->album);
34        debug(278, "Year: %s", node->year);
35        debug(278, "Comment: %s", node->comment);
36        debug(278, "Genrecode: %s", node->genrecode);
37        debug(278, "Genretext: %s", node->genretext);
38        debug(278, "Track: %d", node->track);
39        debug(278, "Len: %d", node->len);
40        debug(278, "Picturetype: %d", node->picturetype);
41        debug(278, "Picturepos: %d", node->picturepos);
42        debug(278, "Picturelen: %d", node->picturelen);
43        debug(278, "Poster: %s", node->poster);
44}
45
46void id3writepic(int fd, struct id3tag* node, char* outfile)
47{
48        int fdw = -1;
49        char* buf = NULL;
50
51        if(fd < 0 || node == NULL || node->picturepos == 0 || node->picturelen == 0) return;
52
53        buf = malloc(node->picturelen);
54        if(buf == NULL)
55        {
56                err("no mem");
57                return;
58        }
59
60        if(node->picturetype == 0) //jpg
61        {
62                if(outfile == NULL) outfile = TMPID3PICJPG;
63                fdw = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0777);
64        }
65        else if(node->picturetype == 1) //png
66        {
67                if(outfile == NULL) outfile = TMPID3PICPNG;
68                fdw = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0777);
69        }
70
71        if(fdw < 0)
72        {
73                free(buf);
74                perr("write id3 picture file");
75                return;
76        }
77
78        lseek(fd, node->picturepos, SEEK_SET);
79        read(fd, buf, node->picturelen);
80        write(fdw, buf, node->picturelen);
81       
82        node->poster = ostrcat(outfile, NULL, 0, 0);
83
84        free(buf);
85        close(fdw);
86}
87
88void freeid3(struct id3tag* node)
89{
90        if(node == NULL) return;
91
92        free(node->title); node->title = NULL;
93        free(node->artist); node->artist = NULL;
94        free(node->album); node->album = NULL;
95        free(node->year); node->year = NULL;
96        free(node->comment); node->comment = NULL;
97        free(node->genrecode); node->genrecode = NULL;
98        free(node->genretext); node->genretext = NULL;
99        free(node->poster); node->poster = NULL;
100       
101        free(node); node = NULL;
102       
103        unlink(TMPID3PICJPG);
104        unlink(TMPID3PICPNG);
105}
106
107int id3swapendian16(int value)
108{
109        int i = value;
110
111        i = ((i & 0xFF00) >> 8) | ((i & 0x00FF) << 8);
112        return i;
113}
114
115int id3swapendian32(int value)
116{
117        int i = value;
118
119        i = ((i & 0xFF000000) >> 24) | ((i & 0x00FF0000) >> 8) | ((i & 0x0000FF00) << 8) | ((i & 0x000000FF) << 24);
120        return i;
121}
122
123//Search for FF+D8+FF bytes (first bytes of a jpeg image)
124//Returns file position:
125int id3jpgstart(int fp, int delta)
126{
127        int ret = -1;
128        int i = 0;
129        unsigned char tmpstr[3];
130
131        int startpos = lseek(fp, 0, SEEK_CUR);
132       
133        for(i = 0; i < delta; i++)
134        {
135                read(fp, tmpstr, sizeof(tmpstr));
136                if(tmpstr[0] == 0xFF && tmpstr[1] == 0xD8 && tmpstr[2] == 0xFF)
137                {
138                        ret = lseek(fp, 0, SEEK_CUR) - 3;
139                        break;
140                }
141                lseek(fp, -2, SEEK_CUR);
142        }
143       
144        lseek(fp, startpos, SEEK_SET);
145        return ret;
146}
147
148//Search for 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 bytes (first bytes of a PNG image)
149//Returns file position:
150int id3pngstart(int fp, int delta)
151{
152        int ret = -1, treffer = 0;
153        int i = 0, j = 0;
154        unsigned char tmpstr[16];
155        unsigned char pngchar[16] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52};
156
157        int startpos = lseek(fp, 0, SEEK_CUR);
158
159        for(i = 0; i < delta; i++)
160        {
161                read(fp, tmpstr, sizeof(tmpstr));
162                treffer = 1;
163                for(j = 0; j < 16; j++)
164                {
165                        if(tmpstr[j] != pngchar[j])
166                        {
167                                treffer = 0;
168                                break;
169                        }
170                }
171
172                if(treffer == 1)
173                {
174                        ret = lseek(fp, 0, SEEK_CUR) - 16;
175                        break;
176                }
177               
178                lseek(fp, -15, SEEK_CUR);
179        }
180       
181        lseek(fp, startpos, SEEK_SET);
182        return ret;
183}
184
185char* id3readtag(int fd, int taglen, int maxtaglen)
186{
187        int i = 0, y = 0;
188        char* tmpstr = NULL;
189
190        if(taglen > maxtaglen) taglen = maxtaglen;
191
192        tmpstr = malloc(taglen + 1);
193        if(tmpstr == NULL) return NULL;
194
195        read(fd, tmpstr, taglen);
196        tmpstr[taglen] = '\0';
197
198        //remove non printable chars
199        for(i = 0; i < taglen; i++)
200        {
201                if((tmpstr[i] >= 0x20 && tmpstr[i] < 0x7F) || (tmpstr[i] >= 0xC0 && tmpstr[i] < 0xFD))
202                {
203                        tmpstr[y] = tmpstr[i];
204                        y++;
205                }
206        }
207        tmpstr[y] = '\0';
208
209        return tmpstr;
210}
211
212int id3tagsize(int fd)
213{
214        int size = 0;
215
216        if(fd < 0) return 0;
217
218        lseek(fd, 6, SEEK_SET);
219        read(fd, &size, sizeof(unsigned int));
220
221        //The ID3 tag size is encoded with four bytes where the first bit
222        //(bit 7) is set to zero in every byte, making a total of 28 bits. The zeroed
223        //bits are ignored, so a 257 bytes long tag is represented as $00 00 02 01.
224
225        size = id3swapendian32(size);
226        size = (((size & 0x7f000000) >> 3 ) | ((size & 0x7f0000) >> 2 ) | ((size & 0x7f00) >> 1 ) | (size & 0x7f));
227
228        lseek(fd, 0, SEEK_SET);
229        return size;
230}
231
232int id3getversion(int fd)
233{
234        char sig[3];
235        unsigned short int version = 0;
236
237        if(fd < 0) return -1;
238
239        read(fd, sig, sizeof(sig));
240        if(ostrncmp("ID3", sig, 3) == 0)
241                read(fd, &version, sizeof(unsigned short int));
242
243        version = id3swapendian16(version);
244        version /= 256;
245
246        lseek(fd, 0, SEEK_SET);
247        return (int)version;
248}
249
250void id3parse1_0(int fd, struct id3tag *node)
251{
252        char buf[128];
253
254        if(fd < 0 || node == NULL) return;
255
256        lseek(fd, -128, SEEK_END);
257        read(fd, buf, 128);
258
259        if(strstr(buf, "TAG") != NULL)
260        {
261                lseek(fd, -125, SEEK_END);
262                if(node->title == NULL) node->title = malloc(31);
263                if(node->title != NULL)
264                {
265                        read(fd, node->title, 30);
266                        node->title[30] = '\0';
267                }
268
269                lseek(fd, -95, SEEK_END);
270                if(node->artist == NULL) node->artist = malloc(31);
271                if(node->artist != NULL)
272                {
273                        read(fd, node->artist, 30);
274                        node->artist[30] = '\0';
275                }
276
277                lseek(fd, -65, SEEK_END);
278                if(node->album == NULL) node->album = malloc(31);
279                if(node->album != NULL)
280                {
281                        read(fd, node->album, 30);
282                        node->album[30] = '\0';
283                }
284
285                lseek(fd, -35, SEEK_END);
286                if(node->year == NULL) node->year = malloc(5);
287                if(node->year != NULL)
288                {
289                        read(fd, node->year, 4);
290                        node->year[4] = '\0';
291                }
292
293                lseek(fd, -31, SEEK_END);
294                if(node->comment == NULL) node->comment = malloc(31);
295                if(node->comment != NULL)
296                {
297                        read(fd, node->comment, 30);
298                        node->comment[30] = '\0';
299                }
300
301                lseek(fd, -1, SEEK_END);
302                if(node->genrecode == NULL) node->genrecode = malloc(2);
303                if(node->genrecode != NULL)
304                {
305                        read(fd, node->genrecode, 1);
306                        node->genrecode[1] = '\0';
307                }
308
309                //Track
310                if(node->comment != NULL)
311                {
312                        if(*(node->comment + 28) == 0 && *(node->comment + 29) > 0)
313                        {
314                                node->track = (int)*(node->comment + 29);
315                                node->version = 1;
316                        }
317                        else
318                        {
319                                node->track = 1;
320                                node->version = 0;
321                        }
322                }
323
324                if(node->genrecode != NULL)
325                {
326                        if((int)node->genrecode[0] >= 0 && (int)node->genrecode[0] < sizeof(id3genrelist) / sizeof(struct id3genre))
327                        {
328                                free(node->genretext); node->genretext = NULL;
329                                //node->genretext = ostrcat(id3genrelist[(int)node->genrecode[0]].text, NULL, 0, 0);
330                                node->genretext = malloc(31);
331                                strcpy(node->genretext, id3genrelist[(int)node->genrecode[0]].text);
332                                node->genretext[30] = '\0';
333                        }
334                }
335        }
336}
337
338void id3parse2_2(int fd, struct id3tag *node)
339{
340        int size = 0;
341        int taglen = 0;
342        char tag[3];
343        char* buf = NULL;
344       
345        if(fd < 0 || node == NULL) return;
346
347        size = id3tagsize(fd);
348        lseek(fd, 10, SEEK_SET);
349
350        while(size != 0)
351        {
352                read(fd, tag, 3);
353                size -= 3;
354
355                //read 3 byte big endian tag length
356                read(fd, &taglen, sizeof(unsigned int));
357                lseek(fd, -1, SEEK_CUR);
358
359                taglen = id3swapendian32(taglen);
360                taglen = (taglen / 256);
361                size -= 3;
362
363                //perform checks for end of tags and tag length overflow or zero
364                if(*tag == 0 || taglen > size || taglen == 0) break;
365
366                if(ostrncmp("TP1", tag, 3) == 0) //artist
367                {
368                        lseek(fd, 1, SEEK_CUR);
369                        free(node->artist); node->artist = NULL;
370                        node->artist = id3readtag(fd, taglen - 1, 260);
371                }
372                else if(ostrncmp("TP2", tag, 3) == 0) //title
373                {
374                        lseek(fd, 1, SEEK_CUR);
375                        free(node->title); node->title = NULL;
376                        node->title = id3readtag(fd, taglen - 1, 260);
377                }
378                else if(ostrncmp("TAL", tag, 3) == 0) //album
379                {
380                        lseek(fd, 1, SEEK_CUR);
381                        free(node->album); node->album = NULL;
382                        node->album = id3readtag(fd, taglen - 1, 260);
383                }
384                else if(ostrncmp("TRK", tag, 3) == 0) //track nr.
385                {
386                        lseek(fd, 1, SEEK_CUR);
387                        buf = id3readtag(fd, taglen - 1, 8);
388                        if(buf != NULL) node->track = atoi(buf);
389                        free(buf); buf = NULL;
390                }
391                else if(ostrncmp("TYE", tag, 3) == 0) //year
392                {
393                        lseek(fd, 1, SEEK_CUR);
394                        free(node->year); node->year = NULL;
395                        node->year = id3readtag(fd, taglen - 1, 12);
396                }
397                else if(ostrncmp("TLE", tag, 3) == 0) //length
398                {
399                        lseek(fd, 1, SEEK_CUR);
400                        buf = id3readtag(fd, taglen - 1, 264);
401                        if(buf != NULL) node->len = atoi(buf);
402                        free(buf); buf = NULL;
403                }
404                else if(ostrncmp("COM", tag, 3) == 0) //comment
405                {
406                        lseek(fd, 1, SEEK_CUR);
407                        free(node->comment); node->comment = NULL;
408                        node->comment = id3readtag(fd, taglen - 1, 260);
409                }
410                else if(ostrncmp("TCO", tag, 3) == 0) //genre
411                {
412                        lseek(fd, 1, SEEK_CUR);
413                        free(node->genretext); node->genretext = NULL;
414                        node->genretext = id3readtag(fd, taglen - 1, 260);
415                }
416                else if(ostrncmp("PIC", tag, 3) == 0) //picture
417                {
418                        lseek(fd, 1, SEEK_CUR);
419                        lseek(fd, 5, SEEK_CUR);
420                        node->picturetype = 0; //jpg
421                        node->picturepos = id3jpgstart(fd, 20);
422                       
423                        if(node->picturepos < 0)
424                        {
425                                node->picturetype = 1; //png
426                                node->picturepos = id3pngstart(fd, 20);
427                        }
428                       
429                        taglen = taglen - (node->picturepos - lseek(fd, 0, SEEK_CUR));
430                        node->picturelen = taglen - 6;
431                        lseek(fd, taglen - 6, SEEK_CUR);
432                       
433                        if(node->picturepos < 0)
434                        {
435                                node->picturetype = 0;
436                                node->picturepos = 0;
437                                node->picturelen = 0;
438                        }
439                }
440                else
441                {
442                        lseek(fd, taglen, SEEK_CUR);
443                }
444                size -= taglen;
445        }
446
447        node->version = 2;
448}
449
450void id3parse2_3(int fd, struct id3tag *node)
451{
452        int size = 0;
453        int taglen = 0;
454        char tag[4];
455        char* buf = NULL;
456       
457        if(fd < 0 || node == NULL) return;
458
459        size = id3tagsize(fd);
460        lseek(fd, 10, SEEK_SET);
461
462        while(size != 0)
463        {
464                read(fd, tag, 4);
465                size -= 4;
466
467                //read 4 byte big endian tag length
468                read(fd, &taglen, sizeof(unsigned int));
469                taglen = id3swapendian32(taglen);
470                size -= 4;
471
472                lseek(fd, 2, SEEK_CUR);
473                size -= 2;
474
475                //perform checks for end of tags and tag length overflow or zero
476                if(*tag == 0 || taglen > size || taglen == 0) break;
477
478                if(ostrncmp("TPE1", tag, 4) == 0) //artist
479                {
480                        lseek(fd, 1, SEEK_CUR);
481                        free(node->artist); node->artist = NULL;
482                        node->artist = id3readtag(fd, taglen - 1, 260);
483                }
484                else if(ostrncmp("TIT2", tag, 4) == 0) //title
485                {
486                        lseek(fd, 1, SEEK_CUR);
487                        free(node->title); node->title = NULL;
488                        node->title = id3readtag(fd, taglen - 1, 260);
489                }
490                else if(ostrncmp("TALB", tag, 4) == 0) //album
491                {
492                        lseek(fd, 1, SEEK_CUR);
493                        free(node->album); node->album = NULL;
494                        node->album = id3readtag(fd, taglen - 1, 260);
495                }
496                else if(ostrncmp("TRCK", tag, 4) == 0) //track nr
497                {
498                        lseek(fd, 1, SEEK_CUR);
499                        buf = id3readtag(fd, taglen - 1, 8);
500                        if(buf != NULL) node->track = atoi(buf);
501                        free(buf); buf = NULL;
502                }
503                else if(ostrncmp("TYER", tag, 4) == 0) //year
504                {
505                        lseek(fd, 1, SEEK_CUR);
506                        free(node->year); node->year = NULL;
507                        node->year = id3readtag(fd, taglen - 1, 12);
508                }
509                else if(ostrncmp("TLEN", tag, 4) == 0) //length in milliseconds
510                {
511                        lseek(fd, 1, SEEK_CUR);
512                        buf = id3readtag(fd, taglen - 1, 264);
513                        if(buf != NULL) node->len = atol(buf) / 1000;
514                        free(buf); buf = NULL;
515                }
516                else if(ostrncmp("TCON", tag, 4) == 0) //genre
517                {
518                        lseek(fd, 1, SEEK_CUR);
519                        free(node->genretext); node->genretext = NULL;
520                        node->genretext = id3readtag(fd, taglen - 1, 260);
521                }
522                else if(ostrncmp("COMM", tag, 4) == 0) //comment
523                {
524                        lseek(fd, 1, SEEK_CUR);
525                        free(node->comment); node->comment = NULL;
526                        node->comment = id3readtag(fd, taglen - 1, 260);
527                }
528                else if(ostrncmp("APIC", tag, 4) == 0) //picture
529                {
530                        lseek(fd, 1, SEEK_CUR);
531                        lseek(fd, 12, SEEK_CUR);
532                        node->picturetype = 0; //jpg
533                        node->picturepos = id3jpgstart(fd, 20);
534                       
535                        if(node->picturepos < 0)
536                        {
537                                node->picturetype = 1; //png
538                                node->picturepos = id3pngstart(fd, 20);
539                        }
540                       
541                        taglen = taglen - (node->picturepos - lseek(fd, 0, SEEK_CUR));
542                        node->picturelen = taglen - 13;
543                        lseek(fd, taglen - 13, SEEK_CUR);
544                       
545                        if(node->picturepos < 0)
546                        {
547                                node->picturetype = 0;
548                                node->picturepos = 0;
549                                node->picturelen = 0;
550                        }
551                }
552                else
553                {
554                        lseek(fd, taglen, SEEK_CUR);
555                }
556                size -= taglen;
557        }
558       
559        node->version = 3;
560}
561
562
563void id3parse2_4(int fd, struct id3tag *node)
564{
565        int size = 0;
566        int taglen = 0;
567        char tag[4];
568        char* buf = NULL;
569
570        if(fd < 0 || node == NULL) return;
571       
572        size = id3tagsize(fd);
573        lseek(fd, 10, SEEK_SET);
574
575        while(size != 0)
576        {
577                read(fd, tag, 4);
578                size -= 4;
579
580                //read 4 byte big endian tag length
581                read(fd, &taglen, sizeof(unsigned int));
582                taglen = id3swapendian32(taglen);
583                size -= 4;
584
585                lseek(fd, 2, SEEK_CUR);
586                size -= 2;
587
588                //perform checks for end of tags and tag length overflow or zero
589                if(*tag == 0 || taglen > size || taglen == 0) break;
590
591                if(ostrncmp("TPE1", tag, 4) == 0) //artist
592                {
593                        lseek(fd, 1, SEEK_CUR);
594                        free(node->artist); node->artist = NULL;
595                        node->artist = id3readtag(fd, taglen - 1, 260);
596                }
597                else if(ostrncmp("TIT2", tag, 4) == 0) //title
598                {
599                        lseek(fd, 1, SEEK_CUR);
600                        free(node->title); node->title = NULL;
601                        node->title = id3readtag(fd, taglen - 1, 260);
602                }
603                else if(ostrncmp("TALB", tag, 4) == 0) //album
604                {
605                        lseek(fd, 1, SEEK_CUR);
606                        free(node->album); node->album = NULL;
607                        node->album = id3readtag(fd, taglen - 1, 260);
608                }
609                else if(ostrncmp("TRCK", tag, 4) == 0) //track nr
610                {
611                        lseek(fd, 1, SEEK_CUR);
612                        buf = id3readtag(fd, taglen - 1, 8);
613                        if(buf != NULL) node->track = atoi(buf);
614                        free(buf); buf = NULL;
615                }
616                else if(ostrncmp("TYER", tag, 4) == 0) //year
617                {
618                        lseek(fd, 1, SEEK_CUR);
619                        free(node->year); node->year = NULL;
620                        node->year = id3readtag(fd, taglen - 1, 12);
621                }
622                else if(ostrncmp("TLEN", tag, 4) == 0) //length in milliseconds
623                {
624                        lseek(fd, 1, SEEK_CUR);
625                        buf = id3readtag(fd, taglen - 1, 264);
626                        if(buf != NULL) node->len = atol(buf) / 1000;
627                        free(buf); buf = NULL;
628                }
629                else if(ostrncmp("TCON", tag, 4) == 0) //genre
630                {
631                        lseek(fd, 1, SEEK_CUR);
632                        free(node->genretext); node->genretext = NULL;
633                        node->genretext = id3readtag(fd, taglen - 1, 260);
634                }
635                else if(ostrncmp("COMM", tag, 4) == 0) //comment
636                {
637                        lseek(fd, 1, SEEK_CUR);
638                        free(node->comment); node->comment = NULL;
639                        node->comment = id3readtag(fd, taglen - 1, 260);
640                }
641                else if(ostrncmp("APIC", tag, 4) == 0) //picture
642                {
643                        lseek(fd, 1, SEEK_CUR);
644                        lseek(fd, 12, SEEK_CUR);
645                        node->picturetype = 0; //jpg
646                        node->picturepos = id3jpgstart(fd, 20);
647                       
648                        if(node->picturepos < 0)
649                        {
650                                node->picturetype = 1; //png
651                                node->picturepos = id3pngstart(fd, 20);
652                        }
653                       
654                        taglen = taglen - (node->picturepos - lseek(fd, 0, SEEK_CUR));
655                        node->picturelen = taglen - 13;
656                        lseek(fd, taglen - 13, SEEK_CUR);
657                       
658                        if(node->picturepos < 0)
659                        {
660                                node->picturetype = 0;
661                                node->picturepos = 0;
662                                node->picturelen = 0;
663                        }
664                }
665                else
666                {
667                        lseek(fd, taglen, SEEK_CUR);
668                }
669                size -= taglen;
670        }
671       
672        node->version = 4;
673}
674
675int id3parse(int fd, struct id3tag *node)
676{
677        switch(id3getversion(fd))
678        {
679                case 0:
680                        id3parse1_0(fd, node);
681                        break;
682                case 2:
683                        id3parse2_2(fd, node);
684                        break;
685                case 3:
686                        id3parse2_3(fd, node);
687                        break;
688                case 4:
689                        id3parse2_4(fd, node);
690                        break;
691                default:
692                        return -1;
693        }
694       
695        return 0;
696}
697
698//flag: 0 = save in tmp
699//flag: 1 = save pic in mediadb path if pic not exist
700//flag: 2 = save no pic
701struct id3tag* getid3(char* file, char* id, int flag)
702{
703        int fd = -1;
704        struct id3tag *node = NULL;
705        char* savefile = NULL, * savethumb = NULL;
706        unsigned char* buf = NULL;
707        int channels = 0;
708        unsigned long width = 0, height = 0, rowbytes = 0;
709       
710        if(file == NULL) return NULL;
711       
712        fd = open(file, O_RDONLY);
713        if(fd < 0) return NULL;
714
715        node = (struct id3tag*)calloc(1, sizeof(struct id3tag));
716        if(node != NULL)
717        {
718                id3parse(fd, node);
719
720                //del spaces
721                node->title = strstrip(node->title);
722                node->artist = strstrip(node->artist);
723                node->album = strstrip(node->album);
724                node->year = strstrip(node->year);
725                node->comment = strstrip(node->comment);
726                node->genrecode = strstrip(node->genrecode);
727                node->genretext = strstrip(node->genretext);
728                node->poster = strstrip(node->poster);
729
730                if(flag == 1 && id != NULL)
731                {
732                        savefile = ostrcat(getconfig("mediadbpath", NULL), "/", 0, 0);
733                        savefile = ostrcat(savefile, id, 1, 0);
734                        savefile = ostrcat(savefile, "_cover.jpg", 1, 0);
735                       
736                        if(!file_exist(savefile))
737                                id3writepic(fd, node, savefile);
738
739                        //create thumb
740                        savethumb = ostrcat(getconfig("mediadbpath", NULL), "/", 0, 0);
741                        savethumb = ostrcat(savethumb, id, 1, 0);
742                        savethumb = ostrcat(savethumb, "_thumb.jpg", 1, 0);
743                        if(file_exist(savefile) && !file_exist(savethumb))
744                        {
745                                buf = loadjpg(savefile, &width, &height, &rowbytes, &channels, 16);
746                                buf = savejpg(savethumb, width, height, channels, 91, 140, 70, buf);
747                        }
748                        free(savethumb); savethumb = NULL;
749                        free(buf); buf = NULL;
750
751                        free(savefile); savefile = NULL;
752                }
753                else if(flag == 0)
754                        id3writepic(fd, node, NULL);   
755        }
756       
757        close(fd);
758        return node;
759}
760
761#endif
Note: See TracBrowser for help on using the repository browser.