minidlna: update to 1.1.5
[tomato.git] / release / src / router / minidlna / tagutils / tagutils.c
blob337119b23814628ab527192876b20b7afe3b6138
1 //=========================================================================
2 // FILENAME : tagutils.c
3 // DESCRIPTION : MP3/MP4/Ogg/FLAC metadata reader
4 //=========================================================================
5 // Copyright (c) 2008- NETGEAR, Inc. All Rights Reserved.
6 //=========================================================================
8 /* This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /* This file is derived from mt-daapd project */
24 #include <ctype.h>
25 #include <errno.h>
26 #include <id3tag.h>
27 #include <stdlib.h>
28 #include <stddef.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <time.h>
33 #include <sys/time.h>
34 #include <netinet/in.h>
35 #include <ogg/ogg.h>
36 #include <vorbis/codec.h>
37 #include <FLAC/metadata.h>
39 #include "config.h"
40 #ifdef HAVE_ICONV
41 #include <iconv.h>
42 #endif
43 #include <sqlite3.h>
44 #include "tagutils.h"
45 #include "../metadata.h"
46 #include "../utils.h"
47 #include "../log.h"
49 struct id3header {
50 unsigned char id[3];
51 unsigned char version[2];
52 unsigned char flags;
53 unsigned char size[4];
54 } __attribute((packed));
56 char *winamp_genre[] = {
57 /*00*/ "Blues", "Classic Rock", "Country", "Dance",
58 "Disco", "Funk", "Grunge", "Hip-Hop",
59 /*08*/ "Jazz", "Metal", "New Age", "Oldies",
60 "Other", "Pop", "R&B", "Rap",
61 /*10*/ "Reggae", "Rock", "Techno", "Industrial",
62 "Alternative", "Ska", "Death Metal", "Pranks",
63 /*18*/ "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop",
64 "Vocal", "Jazz+Funk", "Fusion", "Trance",
65 /*20*/ "Classical", "Instrumental", "Acid", "House",
66 "Game", "Sound Clip", "Gospel", "Noise",
67 /*28*/ "AlternRock", "Bass", "Soul", "Punk",
68 "Space", "Meditative", "Instrumental Pop", "Instrumental Rock",
69 /*30*/ "Ethnic", "Gothic", "Darkwave", "Techno-Industrial",
70 "Electronic", "Pop-Folk", "Eurodance", "Dream",
71 /*38*/ "Southern Rock", "Comedy", "Cult", "Gangsta",
72 "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
73 /*40*/ "Native American", "Cabaret", "New Wave", "Psychedelic",
74 "Rave", "Showtunes", "Trailer", "Lo-Fi",
75 /*48*/ "Tribal", "Acid Punk", "Acid Jazz", "Polka",
76 "Retro", "Musical", "Rock & Roll", "Hard Rock",
77 /*50*/ "Folk", "Folk/Rock", "National folk", "Swing",
78 "Fast-fusion", "Bebob", "Latin", "Revival",
79 /*58*/ "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock",
80 "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock",
81 /*60*/ "Big Band", "Chorus", "Easy Listening", "Acoustic",
82 "Humour", "Speech", "Chanson", "Opera",
83 /*68*/ "Chamber Music", "Sonata", "Symphony", "Booty Bass",
84 "Primus", "Porn Groove", "Satire", "Slow Jam",
85 /*70*/ "Club", "Tango", "Samba", "Folklore",
86 "Ballad", "Powder Ballad", "Rhythmic Soul", "Freestyle",
87 /*78*/ "Duet", "Punk Rock", "Drum Solo", "A Capella",
88 "Euro-House", "Dance Hall", "Goa", "Drum & Bass",
89 /*80*/ "Club House", "Hardcore", "Terror", "Indie",
90 "BritPop", "NegerPunk", "Polsk Punk", "Beat",
91 /*88*/ "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover",
92 "Contemporary C", "Christian Rock", "Merengue", "Salsa",
93 /*90*/ "Thrash Metal", "Anime", "JPop", "SynthPop",
94 "Unknown"
97 #define WINAMP_GENRE_UNKNOWN ((sizeof(winamp_genre) / sizeof(winamp_genre[0])) - 1)
101 * Prototype
103 #include "tagutils-mp3.h"
104 #include "tagutils-aac.h"
105 #include "tagutils-ogg.h"
106 #include "tagutils-flc.h"
107 #include "tagutils-asf.h"
108 #include "tagutils-wav.h"
109 #include "tagutils-pcm.h"
110 #include "tagutils-dsf.h"
111 #include "tagutils-dff.h"
113 static int _get_tags(char *file, struct song_metadata *psong);
114 static int _get_fileinfo(char *file, struct song_metadata *psong);
118 * Typedefs
121 typedef struct {
122 char* type;
123 int (*get_tags)(char* file, struct song_metadata* psong);
124 int (*get_fileinfo)(char* file, struct song_metadata* psong);
125 } taghandler;
127 static taghandler taghandlers[] = {
128 { "aac", _get_aactags, _get_aacfileinfo },
129 { "mp3", _get_mp3tags, _get_mp3fileinfo },
130 { "flc", _get_flctags, _get_flcfileinfo },
131 { "ogg", 0, _get_oggfileinfo },
132 { "asf", 0, _get_asffileinfo },
133 { "wav", _get_wavtags, _get_wavfileinfo },
134 { "pcm", 0, _get_pcmfileinfo },
135 { "dsf", _get_dsftags, _get_dsffileinfo },
136 { "dff", 0, _get_dfffileinfo },
137 { NULL, 0 }
142 //*********************************************************************************
143 #include "tagutils-misc.c"
144 #include "tagutils-mp3.c"
145 #include "tagutils-aac.c"
146 #include "tagutils-ogg.c"
147 #include "tagutils-flc.c"
148 #include "tagutils-asf.c"
149 #include "tagutils-wav.c"
150 #include "tagutils-pcm.c"
151 #include "tagutils-plist.c"
152 #include "tagutils-dsf.c"
153 #include "tagutils-dff.c"
155 //*********************************************************************************
156 // freetags()
157 #define MAYBEFREE(a) { if((a)) free((a)); };
158 void
159 freetags(struct song_metadata *psong)
161 int role;
163 MAYBEFREE(psong->path);
164 MAYBEFREE(psong->image);
165 MAYBEFREE(psong->title);
166 MAYBEFREE(psong->album);
167 MAYBEFREE(psong->genre);
168 MAYBEFREE(psong->comment);
169 for(role = ROLE_START; role <= ROLE_LAST; role++)
171 MAYBEFREE(psong->contributor[role]);
172 MAYBEFREE(psong->contributor_sort[role]);
174 MAYBEFREE(psong->grouping);
175 MAYBEFREE(psong->mime);
176 MAYBEFREE(psong->dlna_pn);
177 MAYBEFREE(psong->tagversion);
178 MAYBEFREE(psong->musicbrainz_albumid);
179 MAYBEFREE(psong->musicbrainz_trackid);
180 MAYBEFREE(psong->musicbrainz_artistid);
181 MAYBEFREE(psong->musicbrainz_albumartistid);
184 // _get_fileinfo
185 static int
186 _get_fileinfo(char *file, struct song_metadata *psong)
188 taghandler *hdl;
190 // dispatch to appropriate tag handler
191 for(hdl = taghandlers; hdl->type; ++hdl)
192 if(!strcmp(hdl->type, psong->type))
193 break;
195 if(hdl->get_fileinfo)
196 return hdl->get_fileinfo(file, psong);
198 return 0;
202 static void
203 _make_composite_tags(struct song_metadata *psong)
205 int len;
207 len = 1;
209 if(!psong->contributor[ROLE_ARTIST] &&
210 (psong->contributor[ROLE_BAND] || psong->contributor[ROLE_CONDUCTOR]))
212 if(psong->contributor[ROLE_BAND])
213 len += strlen(psong->contributor[ROLE_BAND]);
214 if(psong->contributor[ROLE_CONDUCTOR])
215 len += strlen(psong->contributor[ROLE_CONDUCTOR]);
217 len += 3;
219 psong->contributor[ROLE_ARTIST] = (char*)calloc(len, 1);
220 if(psong->contributor[ROLE_ARTIST])
222 if(psong->contributor[ROLE_BAND])
223 strcat(psong->contributor[ROLE_ARTIST], psong->contributor[ROLE_BAND]);
225 if(psong->contributor[ROLE_BAND] && psong->contributor[ROLE_CONDUCTOR])
226 strcat(psong->contributor[ROLE_ARTIST], " - ");
228 if(psong->contributor[ROLE_CONDUCTOR])
229 strcat(psong->contributor[ROLE_ARTIST], psong->contributor[ROLE_CONDUCTOR]);
233 #if 0 // already taken care of by scanner.c
234 if(!psong->title)
236 char *suffix;
237 psong->title = strdup(psong->basename);
238 suffix = strrchr(psong->title, '.');
239 if(suffix) *suffix = '\0';
241 #endif
245 /*****************************************************************************/
246 // _get_tags
247 static int
248 _get_tags(char *file, struct song_metadata *psong)
250 taghandler *hdl;
252 // dispatch
253 for(hdl = taghandlers ; hdl->type ; ++hdl)
254 if(!strcasecmp(hdl->type, psong->type))
255 break;
257 if(hdl->get_tags)
259 return hdl->get_tags(file, psong);
262 return 0;
265 /*****************************************************************************/
266 // readtags
268 readtags(char *path, struct song_metadata *psong, struct stat *stat, char *lang, char *type)
270 char *fname;
272 if(lang_index == -1)
273 lang_index = _lang2cp(lang);
275 memset((void*)psong, 0, sizeof(struct song_metadata));
276 psong->path = strdup(path);
277 psong->type = type;
279 fname = strrchr(psong->path, '/');
280 psong->basename = fname ? fname + 1 : psong->path;
282 if(stat)
284 if(!psong->time_modified)
285 psong->time_modified = stat->st_mtime;
286 psong->file_size = stat->st_size;
289 // get tag
290 if( _get_tags(path, psong) == 0 )
292 _make_composite_tags(psong);
295 // get fileinfo
296 return _get_fileinfo(path, psong);