Improved mp3 support.
[lms] / lightmediascanner / src / plugins / id3 / id3.c
1 /**
2  * Copyright (C) 2008 by INdT
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  * @author Andre Moreira Magalhaes <andre.magalhaes@openbossa.org>
19  */
20
21 /**
22  * @brief
23  *
24  * id3 file parser.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #define _XOPEN_SOURCE 600
32 #include <lightmediascanner_plugin.h>
33 #include <lightmediascanner_db.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41
42 #define ID3V2_GET_FRAME_INFO(frame_data, frame_size, str, len) { \
43     str = malloc(sizeof(char) * (frame_size + 1)); \
44     memcpy(str, frame_data, frame_size); \
45     str[frame_size] = '\0'; \
46     len = frame_size; \
47 }
48
49 #define ID3V2_HEADER_SIZE       10
50 #define ID3V2_FOOTER_SIZE       10
51 #define ID3V2_FRAME_HEADER_SIZE 10
52
53 #define ID3V1_NUM_GENRES 148
54
55 static const char *id3v1_genres[ID3V1_NUM_GENRES] = {
56     "Blues",
57     "Classic Rock",
58     "Country",
59     "Dance",
60     "Disco",
61     "Funk",
62     "Grunge",
63     "Hip-Hop",
64     "Jazz",
65     "Metal",
66     "New Age",
67     "Oldies",
68     "Other",
69     "Pop",
70     "R&B",
71     "Rap",
72     "Reggae",
73     "Rock",
74     "Techno",
75     "Industrial",
76     "Alternative",
77     "Ska",
78     "Death Metal",
79     "Pranks",
80     "Soundtrack",
81     "Euro-Techno",
82     "Ambient",
83     "Trip-Hop",
84     "Vocal",
85     "Jazz+Funk",
86     "Fusion",
87     "Trance",
88     "Classical",
89     "Instrumental",
90     "Acid",
91     "House",
92     "Game",
93     "Sound Clip",
94     "Gospel",
95     "Noise",
96     "Alternative Rock",
97     "Bass",
98     "Soul",
99     "Punk",
100     "Space",
101     "Meditative",
102     "Instrumental Pop",
103     "Instrumental Rock",
104     "Ethnic",
105     "Gothic",
106     "Darkwave",
107     "Techno-Industrial",
108     "Electronic",
109     "Pop-Folk",
110     "Eurodance",
111     "Dream",
112     "Southern Rock",
113     "Comedy",
114     "Cult",
115     "Gangsta",
116     "Top 40",
117     "Christian Rap",
118     "Pop/Funk",
119     "Jungle",
120     "Native American",
121     "Cabaret",
122     "New Wave",
123     "Psychedelic",
124     "Rave",
125     "Showtunes",
126     "Trailer",
127     "Lo-Fi",
128     "Tribal",
129     "Acid Punk",
130     "Acid Jazz",
131     "Polka",
132     "Retro",
133     "Musical",
134     "Rock & Roll",
135     "Hard Rock",
136     "Folk",
137     "Folk/Rock",
138     "National Folk",
139     "Swing",
140     "Fusion",
141     "Bebob",
142     "Latin",
143     "Revival",
144     "Celtic",
145     "Bluegrass",
146     "Avantgarde",
147     "Gothic Rock",
148     "Progressive Rock",
149     "Psychedelic Rock",
150     "Symphonic Rock",
151     "Slow Rock",
152     "Big Band",
153     "Chorus",
154     "Easy Listening",
155     "Acoustic",
156     "Humour",
157     "Speech",
158     "Chanson",
159     "Opera",
160     "Chamber Music",
161     "Sonata",
162     "Symphony",
163     "Booty Bass",
164     "Primus",
165     "Porn Groove",
166     "Satire",
167     "Slow Jam",
168     "Club",
169     "Tango",
170     "Samba",
171     "Folklore",
172     "Ballad",
173     "Power Ballad",
174     "Rhythmic Soul",
175     "Freestyle",
176     "Duet",
177     "Punk Rock",
178     "Drum Solo",
179     "A Cappella",
180     "Euro-House",
181     "Dance Hall",
182     "Goa",
183     "Drum & Bass",
184     "Club-House",
185     "Hardcore",
186     "Terror",
187     "Indie",
188     "BritPop",
189     "Negerpunk",
190     "Polsk Punk",
191     "Beat",
192     "Christian Gangsta Rap",
193     "Heavy Metal",
194     "Black Metal",
195     "Crossover",
196     "Contemporary Christian",
197     "Christian Rock",
198     "Merengue",
199     "Salsa",
200     "Thrash Metal",
201     "Anime",
202     "Jpop",
203     "Synthpop"
204 };
205
206 struct id3v2_frame_header {
207     char frame_id[4];
208     unsigned int frame_size;
209     int compression;
210     int data_length_indicator;
211 };
212
213 struct id3v1_tag {
214     char title[30];
215     char artist[30];
216     char album[30];
217     char year[4];
218     char comments[30];
219     char genre;
220 } __attribute__((packed));
221
222 struct plugin {
223     struct lms_plugin plugin;
224     lms_db_audio_t *audio_db;
225 };
226
227 static const char _name[] = "id3";
228 static const struct lms_string_size _exts[] = {
229     LMS_STATIC_STRING_SIZE(".mp3"),
230     LMS_STATIC_STRING_SIZE(".aac")
231 };
232
233 static int
234 _is_id3v2_second_synch_byte(unsigned char byte)
235 {
236     if (byte == 0xff)
237         return 0;
238     if ((byte & 0xE0) == 0xE0)
239         return 1;
240     return 0;
241 }
242
243 static long
244 _find_id3v2(int fd)
245 {
246     long buffer_offset = 0;
247     char buffer[1025];
248     char *p;
249     int buffer_size = sizeof(buffer);
250     const char pattern[] = "ID3";
251     ssize_t nread;
252
253     /* These variables are used to keep track of a partial match that happens at
254      * the end of a buffer. */
255     int previous_partial_match = -1;
256     int previous_partial_synch_match = 0;
257     int first_synch_byte;
258
259     /* Start the search at the beginning of the file. */
260     lseek(fd, 0, SEEK_SET);
261
262     /* This loop is the crux of the find method.  There are three cases that we
263      * want to account for:
264      * (1) The previously searched buffer contained a partial match of the search
265      * pattern and we want to see if the next one starts with the remainder of
266      * that pattern.
267      *
268      * (2) The search pattern is wholly contained within the current buffer.
269      *
270      * (3) The current buffer ends with a partial match of the pattern.  We will
271      * note this for use in the next iteration, where we will check for the rest
272      * of the pattern. */
273
274     if ((nread = read(fd, &buffer, sizeof(buffer))) <= 0)
275         return -1;
276     while (1) {
277         /* (1) previous partial match */
278         if (previous_partial_synch_match && _is_id3v2_second_synch_byte(buffer[0]))
279             return -1;
280
281         if (previous_partial_match >= 0 && previous_partial_match < buffer_size) {
282             const int pattern_offset = buffer_size - previous_partial_match;
283
284             if (memcmp(buffer, pattern + pattern_offset, 3 - pattern_offset) == 0)
285                 return buffer_offset - buffer_size + previous_partial_match;
286         }
287
288         /* (2) pattern contained in current buffer */
289         p = buffer;
290         while ((p = memchr(p, 'I', buffer_size))) {
291             if (memcmp(p, pattern, 3) == 0)
292                 return buffer_offset + (p - buffer);
293             p += 1;
294         }
295
296         p = memchr(buffer, 255, buffer_size);
297         if (p)
298             first_synch_byte = p - buffer;
299         else
300             first_synch_byte = -1;
301
302         /* Here we have to loop because there could be several of the first
303          * (11111111) byte, and we want to check all such instances until we find
304          * a full match (11111111 111) or hit the end of the buffer. */
305         while (first_synch_byte >= 0) {
306             /* if this *is not* at the end of the buffer */
307             if (first_synch_byte < buffer_size - 1) {
308                 if(_is_id3v2_second_synch_byte(buffer[first_synch_byte + 1]))
309                     /* We've found the frame synch pattern. */
310                     return -1;
311                 else
312                     /* We found 11111111 at the end of the current buffer indicating a
313                      * partial match of the synch pattern.  The find() below should
314                      * return -1 and break out of the loop. */
315                     previous_partial_synch_match = 1;
316             }
317
318             /* Check in the rest of the buffer. */
319             p = memchr(p + 1, 255, buffer_size);
320             if (p)
321                 first_synch_byte = p - buffer;
322             else
323                 first_synch_byte = -1;
324         }
325
326         /* (3) partial match */
327         if (buffer[nread - 1] == pattern[1])
328             previous_partial_match = nread - 1;
329         else if (memcmp(&buffer[nread - 2], pattern, 2) == 0)
330             previous_partial_match = nread - 2;
331         buffer_offset += buffer_size;
332
333         if ((nread = read(fd, &buffer, sizeof(buffer))) <= 0)
334             return -1;
335     }
336
337     return -1;
338 }
339
340 static unsigned int
341 _to_uint(const char *data, int data_size)
342 {
343     unsigned int sum = 0;
344     int last = data_size > 4 ? 3 : data_size - 1;
345     int i;
346
347     for (i = 0; i <= last; i++)
348         sum |= (data[i] & 0x7f) << ((last - i) * 7);
349
350     return sum;
351 }
352
353 static unsigned int
354 _get_id3v2_frame_header_size(unsigned int version)
355 {
356     switch (version) {
357     case 0:
358     case 1:
359     case 2:
360         return 6;
361     case 3:
362     case 4:
363     default:
364         return 10;
365     }
366 }
367
368 static void
369 _parse_id3v2_frame_header(char *data, unsigned int version, struct id3v2_frame_header *fh)
370 {
371     switch (version) {
372     case 0:
373     case 1:
374     case 2:
375         memcpy(fh->frame_id, data, 3);
376         fh->frame_id[3] = 0;
377         fh->frame_size = _to_uint(data + 3, 3);
378         fh->compression = 0;
379         fh->data_length_indicator = 0;
380         break;
381     case 3:
382         memcpy(fh->frame_id, data, 4);
383         fh->frame_size = _to_uint(data + 4, 4);
384         fh->compression = data[9] & 0x40;
385         fh->data_length_indicator = 0;
386         break;
387     case 4:
388     default:
389         memcpy(fh->frame_id, data, 4);
390         fh->frame_size = _to_uint(data + 4, 4);
391         fh->compression = data[9] & 0x4;
392         fh->data_length_indicator = data[9] & 0x1;
393         break;
394     }
395 }
396
397 static void
398 _parse_id3v2_frame(struct id3v2_frame_header *fh, const char *frame_data, struct lms_audio_info *info)
399 {
400     unsigned int frame_size;
401
402     /* TODO proper handle text encoding
403      *
404      * Latin1  = 0
405      * UTF16   = 1
406      * UTF16BE = 2
407      * UTF8    = 3
408      * UTF16LE = 4
409      */
410
411     /* skip first byte - text encoding */
412     frame_data += 1;
413     frame_size = fh->frame_size - 1;
414
415     if (memcmp(fh->frame_id, "TIT2", 4) == 0)
416         ID3V2_GET_FRAME_INFO(frame_data, frame_size, info->title.str, info->title.len)
417     else if (memcmp(fh->frame_id, "TPE1", 4) == 0)
418         ID3V2_GET_FRAME_INFO(frame_data, frame_size, info->artist.str, info->artist.len)
419     else if (memcmp(fh->frame_id, "TALB", 4) == 0)
420         ID3V2_GET_FRAME_INFO(frame_data, frame_size, info->album.str, info->album.len)
421     else if (memcmp(fh->frame_id, "TCON", 4) == 0) {
422         /* TODO handle multiple genres */
423         int i, is_number;
424
425         ID3V2_GET_FRAME_INFO(frame_data, frame_size, info->genre.str, info->genre.len)
426
427         is_number = 1;
428         for (i = 0; i < info->genre.len; ++i) {
429             if (!isdigit(info->genre.str[i]))
430                 is_number = 0;
431         }
432
433         if ((is_number) &&
434             (info->genre.str) &&
435             (info->genre.len > 0)) {
436             int genre = atoi(info->genre.str);
437             if (genre >= 0 && genre < ID3V1_NUM_GENRES) {
438                 free(info->genre.str);
439                 info->genre.str = strdup(id3v1_genres[(int) genre]);
440                 info->genre.len = strlen(info->genre.str);
441             }
442             else {
443                 /* ignore other genres */
444                 free(info->genre.str);
445                 info->genre.str = NULL;
446                 info->genre.len = 0;
447             }
448         }
449     }
450     else if (memcmp(fh->frame_id, "TRCK", 4) == 0) {
451         char *trackno;
452         unsigned int trackno_len;
453         ID3V2_GET_FRAME_INFO(frame_data, frame_size, trackno, trackno_len);
454         info->trackno = atoi(trackno);
455     }
456 }
457
458 static int
459 _parse_id3v2(int fd, long id3v2_offset, struct lms_audio_info *info)
460 {
461     char header_data[10], frame_header_data[10];
462     unsigned int tag_size, major_version, frame_data_pos, frame_data_length, frame_header_size;
463     int extended_header, footer_present;
464     struct id3v2_frame_header fh;
465
466     lseek(fd, id3v2_offset, SEEK_SET);
467
468     /* parse header */
469     if (read(fd, header_data, ID3V2_HEADER_SIZE) != ID3V2_HEADER_SIZE)
470         return -1;
471
472     tag_size = _to_uint(header_data + 6, 4);
473     if (tag_size == 0)
474         return -1;
475
476     /* parse frames */
477     major_version = header_data[3];
478
479     frame_data_pos = 0;
480     frame_data_length = tag_size;
481
482     /* check for extended header */
483     extended_header = header_data[5] & 0x20; /* bit 6 */
484     if (extended_header) {
485         /* skip extended header */
486         unsigned int extended_header_size;
487         char extended_header_data[4];
488
489         if (read(fd, extended_header_data, 4) != 4)
490             return -1;
491         extended_header_size = _to_uint(extended_header_data, 4);
492         lseek(fd, extended_header_size - 4, SEEK_CUR);
493         frame_data_pos += extended_header_size;
494         frame_data_length -= extended_header_size;
495     }
496
497     footer_present = header_data[5] & 0x8;   /* bit 4 */
498     if (footer_present && frame_data_length > ID3V2_FOOTER_SIZE)
499         frame_data_length -= ID3V2_FOOTER_SIZE;
500
501     frame_header_size = _get_id3v2_frame_header_size(major_version);
502     while (frame_data_pos < frame_data_length - frame_header_size) {
503         if (read(fd, frame_header_data, ID3V2_FRAME_HEADER_SIZE) != ID3V2_FRAME_HEADER_SIZE)
504             return -1;
505
506         if (frame_header_data[0] == 0)
507             break;
508
509         _parse_id3v2_frame_header(frame_header_data, major_version, &fh);
510
511         if (!fh.compression &&
512             fh.frame_id[0] == 'T' &&
513             memcmp(fh.frame_id, "TXXX", 4) != 0) {
514             char *frame_data;
515
516             if (fh.data_length_indicator)
517                 lseek(fd, 4, SEEK_CUR);
518
519             frame_data = malloc(sizeof(char) * fh.frame_size);
520             if (read(fd, frame_data, fh.frame_size) != fh.frame_size) {
521                 free(frame_data);
522                 return -1;
523             }
524
525             _parse_id3v2_frame(&fh, frame_data, info);
526             free(frame_data);
527         }
528         else {
529             if (fh.data_length_indicator)
530                 lseek(fd, fh.frame_size + 4, SEEK_CUR);
531             else
532                 lseek(fd, fh.frame_size, SEEK_CUR);
533         }
534
535         frame_data_pos += fh.frame_size + frame_header_size;
536     }
537
538     return 0;
539 }
540
541 static int
542 _parse_id3v1(int fd, struct lms_audio_info *info)
543 {
544     struct id3v1_tag tag;
545     if (read(fd, &tag, sizeof(struct id3v1_tag)) == -1)
546         return -1;
547
548     info->title.str = strdup(tag.title);
549     info->title.len = strlen(info->title.str);
550     info->artist.str = strdup(tag.artist);
551     info->artist.len = strlen(info->artist.str);
552     info->album.str = strdup(tag.album);
553     info->album.len = strlen(info->album.str);
554     info->genre.str = strdup(id3v1_genres[(int) tag.genre]);
555     info->genre.len = strlen(info->genre.str);
556     if (tag.comments[28] == 0 && tag.comments[29] != 0)
557         info->trackno = (unsigned char) tag.comments[29];
558
559     return 0;
560 }
561
562 static void *
563 _match(struct plugin *p, const char *path, int len, int base)
564 {
565     int i;
566
567     i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts));
568     if (i < 0)
569       return NULL;
570     else
571       return (void*)(i + 1);
572 }
573
574 static int
575 _parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match)
576 {
577     struct lms_audio_info info = {0, {0}, {0}, {0}, {0}, 0, 0, 0};
578     int r, fd;
579     long id3v2_offset;
580
581     fd = open(finfo->path, O_RDONLY);
582     if (fd < 0) {
583         perror("open");
584         return -1;
585     }
586
587     id3v2_offset = _find_id3v2(fd);
588     if (id3v2_offset >= 0) {
589 #if 0
590         fprintf(stderr, "id3v2 tag found in file %s with offset %ld\n",
591                 finfo->path, id3v2_offset);
592 #endif
593         if (_parse_id3v2(fd, id3v2_offset, &info) != 0) {
594             r = -2;
595             goto done;
596         }
597     }
598     else {
599         char tag[3];
600 #if 0
601         fprintf(stderr, "id3v2 tag not found in file %s. trying id3v1\n", finfo->path);
602 #endif
603         /* check for id3v1 tag */
604         if (lseek(fd, -128, SEEK_END) == -1) {
605             r = -3;
606             goto done;
607         }
608
609         if (read(fd, &tag, 3) == -1) {
610             r = -4;
611             goto done;
612         }
613
614         if (memcmp(tag, "TAG", 3) == 0) {
615 #if 0
616             fprintf(stderr, "id3v1 tag found in file %s\n", finfo->path);
617 #endif
618             if (_parse_id3v1(fd, &info) != 0) {
619                 r = -5;
620                 goto done;
621             }
622         }
623     }
624
625     lms_string_size_strip_and_free(&info.title);
626     lms_string_size_strip_and_free(&info.artist);
627     lms_string_size_strip_and_free(&info.album);
628     lms_string_size_strip_and_free(&info.genre);
629
630     if (!info.title.str) {
631         int ext_idx;
632         ext_idx = ((int)match) - 1;
633         info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len;
634         info.title.str = malloc((info.title.len + 1) * sizeof(char));
635         memcpy(info.title.str, finfo->path + finfo->base, info.title.len);
636         info.title.str[info.title.len] = '\0';
637     }
638     lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len);
639
640     if (info.artist.str)
641         lms_charset_conv(ctxt->cs_conv, &info.artist.str, &info.artist.len);
642     if (info.album.str)
643         lms_charset_conv(ctxt->cs_conv, &info.album.str, &info.album.len);
644     if (info.genre.str)
645         lms_charset_conv(ctxt->cs_conv, &info.genre.str, &info.genre.len);
646
647 #if 0
648     fprintf(stderr, "file %s info\n", finfo->path);
649     fprintf(stderr, "\ttitle='%s'\n", info.title.str);
650     fprintf(stderr, "\tartist='%s'\n", info.artist.str);
651     fprintf(stderr, "\talbum='%s'\n", info.album.str);
652     fprintf(stderr, "\tgenre='%s'\n", info.genre.str);
653     fprintf(stderr, "\ttrack number='%d'\n", info.trackno);
654 #endif
655
656     info.id = finfo->id;
657     r = lms_db_audio_add(plugin->audio_db, &info);
658
659   done:
660     close(fd);
661
662     if (info.title.str)
663         free(info.title.str);
664     if (info.artist.str)
665         free(info.artist.str);
666     if (info.album.str)
667         free(info.album.str);
668     if (info.genre.str)
669         free(info.genre.str);
670
671     return r;
672 }
673
674 static int
675 _setup(struct plugin *plugin, struct lms_context *ctxt)
676 {
677     plugin->audio_db = lms_db_audio_new(ctxt->db);
678     if (!plugin->audio_db)
679         return -1;
680     return 0;
681 }
682
683 static int
684 _start(struct plugin *plugin, struct lms_context *ctxt)
685 {
686     return lms_db_audio_start(plugin->audio_db);
687 }
688
689 static int
690 _finish(struct plugin *plugin, struct lms_context *ctxt)
691 {
692     if (plugin->audio_db)
693         lms_db_audio_free(plugin->audio_db);
694     return 0;
695 }
696
697 static int
698 _close(struct plugin *plugin)
699 {
700     free(plugin);
701     return 0;
702 }
703
704 API struct lms_plugin *
705 lms_plugin_open(void)
706 {
707     struct plugin *plugin;
708
709     plugin = (struct plugin *)malloc(sizeof(*plugin));
710     plugin->plugin.name = _name;
711     plugin->plugin.match = (lms_plugin_match_fn_t)_match;
712     plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse;
713     plugin->plugin.close = (lms_plugin_close_fn_t)_close;
714     plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup;
715     plugin->plugin.start = (lms_plugin_start_fn_t)_start;
716     plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish;
717
718     return (struct lms_plugin *)plugin;
719 }