source: titan/minidlna-1.0.22/tagutils/tagutils.c @ 13567

Last change on this file since 13567 was 13567, checked in by obi, 11 years ago

[titan] add minidlna-1.0.22 first step

File size: 9.3 KB
Line 
1//=========================================================================
2// FILENAME     : tagutils.c
3// DESCRIPTION  : MP3/MP4/Ogg/FLAC metadata reader
4//=========================================================================
5// Copyright (c) 2008- NETGEAR, Inc. All Rights Reserved.
6//=========================================================================
7
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.
12 *
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.
17 *
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/>.
20 */
21
22/* This file is derived from mt-daapd project */
23
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>
38
39#include "../config.h"
40#ifdef HAVE_ICONV_H
41#include <iconv.h>
42#endif
43
44#include <sqlite3.h>
45#include "tagutils.h"
46#include "misc.h"
47#include "textutils.h"
48#include "../metadata.h"
49#include "../log.h"
50
51struct id3header {
52        unsigned char id[3];
53        unsigned char version[2];
54        unsigned char flags;
55        unsigned char size[4];
56} __attribute((packed));
57
58char *winamp_genre[] = {
59        /*00*/ "Blues",             "Classic Rock",     "Country",           "Dance",
60               "Disco",             "Funk",             "Grunge",            "Hip-Hop",
61        /*08*/ "Jazz",              "Metal",            "New Age",           "Oldies",
62               "Other",             "Pop",              "R&B",               "Rap",
63        /*10*/ "Reggae",            "Rock",             "Techno",            "Industrial",
64               "Alternative",       "Ska",              "Death Metal",       "Pranks",
65        /*18*/ "Soundtrack",        "Euro-Techno",      "Ambient",           "Trip-Hop",
66               "Vocal",             "Jazz+Funk",        "Fusion",            "Trance",
67        /*20*/ "Classical",         "Instrumental",     "Acid",              "House",
68               "Game",              "Sound Clip",       "Gospel",            "Noise",
69        /*28*/ "AlternRock",        "Bass",             "Soul",              "Punk",
70               "Space",             "Meditative",       "Instrumental Pop",  "Instrumental Rock",
71        /*30*/ "Ethnic",            "Gothic",           "Darkwave",          "Techno-Industrial",
72               "Electronic",        "Pop-Folk",         "Eurodance",         "Dream",
73        /*38*/ "Southern Rock",     "Comedy",           "Cult",              "Gangsta",
74               "Top 40",            "Christian Rap",    "Pop/Funk",          "Jungle",
75        /*40*/ "Native American",   "Cabaret",          "New Wave",          "Psychedelic",
76               "Rave",              "Showtunes",        "Trailer",           "Lo-Fi",
77        /*48*/ "Tribal",            "Acid Punk",        "Acid Jazz",         "Polka",
78               "Retro",             "Musical",          "Rock & Roll",       "Hard Rock",
79        /*50*/ "Folk",              "Folk/Rock",        "National folk",     "Swing",
80               "Fast-fusion",       "Bebob",            "Latin",             "Revival",
81        /*58*/ "Celtic",            "Bluegrass",        "Avantgarde",        "Gothic Rock",
82               "Progressive Rock",  "Psychedelic Rock", "Symphonic Rock",    "Slow Rock",
83        /*60*/ "Big Band",          "Chorus",           "Easy Listening",    "Acoustic",
84               "Humour",            "Speech",           "Chanson",           "Opera",
85        /*68*/ "Chamber Music",     "Sonata",           "Symphony",          "Booty Bass",
86               "Primus",            "Porn Groove",      "Satire",            "Slow Jam",
87        /*70*/ "Club",              "Tango",            "Samba",             "Folklore",
88               "Ballad",            "Powder Ballad",    "Rhythmic Soul",     "Freestyle",
89        /*78*/ "Duet",              "Punk Rock",        "Drum Solo",         "A Capella",
90               "Euro-House",        "Dance Hall",       "Goa",               "Drum & Bass",
91        /*80*/ "Club House",        "Hardcore",         "Terror",            "Indie",
92               "BritPop",           "NegerPunk",        "Polsk Punk",        "Beat",
93        /*88*/ "Christian Gangsta", "Heavy Metal",      "Black Metal",       "Crossover",
94               "Contemporary C",    "Christian Rock",   "Merengue",          "Salsa",
95        /*90*/ "Thrash Metal",      "Anime",            "JPop",              "SynthPop",
96               "Unknown"
97};
98
99#define WINAMP_GENRE_UNKNOWN ((sizeof(winamp_genre) / sizeof(winamp_genre[0])) - 1)
100
101
102/*
103 * Prototype
104 */
105#include "tagutils-mp3.h"
106#include "tagutils-aac.h"
107#include "tagutils-ogg.h"
108#include "tagutils-flc.h"
109#include "tagutils-asf.h"
110#include "tagutils-wav.h"
111#include "tagutils-pcm.h"
112
113static int _get_tags(char *file, struct song_metadata *psong);
114static int _get_fileinfo(char *file, struct song_metadata *psong);
115
116
117/*
118 * Typedefs
119 */
120
121typedef 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;
126
127static 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        { NULL,  0 }
136};
137
138
139
140//*********************************************************************************
141#include "tagutils-misc.c"
142#include "tagutils-mp3.c"
143#include "tagutils-aac.c"
144#include "tagutils-ogg.c"
145#include "tagutils-flc.c"
146#include "tagutils-asf.c"
147#include "tagutils-wav.c"
148#include "tagutils-pcm.c"
149#include "tagutils-plist.c"
150
151//*********************************************************************************
152// freetags()
153#define MAYBEFREE(a) { if((a)) free((a)); };
154void
155freetags(struct song_metadata *psong)
156{
157        int role;
158
159        MAYBEFREE(psong->path);
160        MAYBEFREE(psong->image);
161        MAYBEFREE(psong->title);
162        MAYBEFREE(psong->album);
163        MAYBEFREE(psong->genre);
164        MAYBEFREE(psong->comment);
165        for(role = ROLE_START; role <= ROLE_LAST; role++)
166        {
167                MAYBEFREE(psong->contributor[role]);
168                MAYBEFREE(psong->contributor_sort[role]);
169        }
170        MAYBEFREE(psong->grouping);
171        MAYBEFREE(psong->mime);
172        MAYBEFREE(psong->dlna_pn);
173        MAYBEFREE(psong->tagversion);
174        MAYBEFREE(psong->musicbrainz_albumid);
175        MAYBEFREE(psong->musicbrainz_trackid);
176        MAYBEFREE(psong->musicbrainz_artistid);
177        MAYBEFREE(psong->musicbrainz_albumartistid);
178}
179
180// _get_fileinfo
181static int
182_get_fileinfo(char *file, struct song_metadata *psong)
183{
184        taghandler *hdl;
185
186        // dispatch to appropriate tag handler
187        for(hdl = taghandlers; hdl->type; ++hdl)
188                if(!strcmp(hdl->type, psong->type))
189                        break;
190
191        if(hdl->get_fileinfo)
192                return hdl->get_fileinfo(file, psong);
193
194        return 0;
195}
196
197
198static void
199_make_composite_tags(struct song_metadata *psong)
200{
201        int len;
202
203        len = 1;
204
205        if(!psong->contributor[ROLE_ARTIST] &&
206           (psong->contributor[ROLE_BAND] || psong->contributor[ROLE_CONDUCTOR]))
207        {
208                if(psong->contributor[ROLE_BAND])
209                        len += strlen(psong->contributor[ROLE_BAND]);
210                if(psong->contributor[ROLE_CONDUCTOR])
211                        len += strlen(psong->contributor[ROLE_CONDUCTOR]);
212
213                len += 3;
214
215                psong->contributor[ROLE_ARTIST] = (char*)calloc(len, 1);
216                if(psong->contributor[ROLE_ARTIST])
217                {
218                        if(psong->contributor[ROLE_BAND])
219                                strcat(psong->contributor[ROLE_ARTIST], psong->contributor[ROLE_BAND]);
220
221                        if(psong->contributor[ROLE_BAND] && psong->contributor[ROLE_CONDUCTOR])
222                                strcat(psong->contributor[ROLE_ARTIST], " - ");
223
224                        if(psong->contributor[ROLE_CONDUCTOR])
225                                strcat(psong->contributor[ROLE_ARTIST], psong->contributor[ROLE_CONDUCTOR]);
226                }
227        }
228
229#if 0 // already taken care of by scanner.c
230        if(!psong->title)
231        {
232                char *suffix;
233                psong->title = strdup(psong->basename);
234                suffix = strrchr(psong->title, '.');
235                if(suffix) *suffix = '\0';
236        }
237#endif
238}
239
240
241/*****************************************************************************/
242// _get_tags
243static int
244_get_tags(char *file, struct song_metadata *psong)
245{
246        taghandler *hdl;
247
248        // dispatch
249        for(hdl = taghandlers ; hdl->type ; ++hdl)
250                if(!strcasecmp(hdl->type, psong->type))
251                        break;
252
253        if(hdl->get_tags)
254        {
255                return hdl->get_tags(file, psong);
256        }
257
258        return 0;
259}
260
261/*****************************************************************************/
262// readtags
263int
264readtags(char *path, struct song_metadata *psong, struct stat *stat, char *lang, char *type)
265{
266        char *fname;
267
268        if(lang_index == -1)
269                lang_index = _lang2cp(lang);
270
271        memset((void*)psong, 0, sizeof(struct song_metadata));
272        psong->path = strdup(path);
273        psong->type = type;
274
275        fname = strrchr(psong->path, '/');
276        psong->basename = fname ? fname + 1 : psong->path;
277
278        if(stat)
279        {
280                if(!psong->time_modified)
281                        psong->time_modified = stat->st_mtime;
282                psong->file_size = stat->st_size;
283        }
284
285        // get tag
286        if( _get_tags(path, psong) == 0 )
287        {
288                _make_composite_tags(psong);
289        }
290       
291        // get fileinfo
292        return _get_fileinfo(path, psong);
293}
Note: See TracBrowser for help on using the repository browser.