1//=========================================================================
2// FILENAME	: tagutils-mp3.c
3// DESCRIPTION	: MP3 metadata reader
4//=========================================================================
5// Copyright (c) 2008- NETGEAR, Inc. All Rights Reserved.
6//=========================================================================
7
8/*
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 */
23
24/*
25 * This file is derived from mt-daap project.
26 */
27
28static int
29_get_mp3tags(char *file, struct song_metadata *psong)
30{
31	struct id3_file *pid3file;
32	struct id3_tag *pid3tag;
33	struct id3_frame *pid3frame;
34	int err;
35	int index;
36	int used;
37	unsigned char *utf8_text;
38	int genre = WINAMP_GENRE_UNKNOWN;
39	int have_utf8;
40	int have_text;
41	id3_ucs4_t const *native_text;
42	char *tmp;
43	int got_numeric_genre;
44	id3_byte_t const *image;
45	id3_length_t image_size = 0;
46
47	pid3file = id3_file_open(file, ID3_FILE_MODE_READONLY);
48	if(!pid3file)
49	{
50		DPRINTF(E_ERROR, L_SCANNER, "Cannot open %s\n", file);
51		return -1;
52	}
53
54	pid3tag = id3_file_tag(pid3file);
55
56	if(!pid3tag)
57	{
58		err = errno;
59		id3_file_close(pid3file);
60		errno = err;
61		DPRINTF(E_WARN, L_SCANNER, "Cannot get ID3 tag for %s\n", file);
62		return -1;
63	}
64
65	index = 0;
66	while((pid3frame = id3_tag_findframe(pid3tag, "", index)))
67	{
68		used = 0;
69		utf8_text = NULL;
70		native_text = NULL;
71		have_utf8 = 0;
72		have_text = 0;
73
74		if(!strcmp(pid3frame->id, "YTCP"))   /* for id3v2.2 */
75		{
76			psong->compilation = 1;
77			DPRINTF(E_DEBUG, L_SCANNER, "Compilation: %d [%s]\n", psong->compilation, basename(file));
78		}
79		else if(!strcmp(pid3frame->id, "APIC") && !image_size)
80		{
81			if( (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpeg") == 0) ||
82			    (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "jpeg") == 0) )
83			{
84				image = id3_field_getbinarydata(&pid3frame->fields[4], &image_size);
85				if( image_size )
86				{
87					psong->image = malloc(image_size);
88					memcpy(psong->image, image, image_size);
89					psong->image_size = image_size;
90					//DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Found thumbnail: %d\n", psong->image_size);
91				}
92			}
93		}
94
95		if(((pid3frame->id[0] == 'T') || (strcmp(pid3frame->id, "COMM") == 0)) &&
96		   (id3_field_getnstrings(&pid3frame->fields[1])))
97			have_text = 1;
98
99		if(have_text)
100		{
101			native_text = id3_field_getstrings(&pid3frame->fields[1], 0);
102
103			if(native_text)
104			{
105				have_utf8 = 1;
106				if(lang_index >= 0)
107					utf8_text = _get_utf8_text(native_text); // through iconv
108				else
109					utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
110
111				if(!strcmp(pid3frame->id, "TIT2"))
112				{
113					used = 1;
114					psong->title = (char*)utf8_text;
115				}
116				else if(!strcmp(pid3frame->id, "TPE1"))
117				{
118					used = 1;
119					psong->contributor[ROLE_ARTIST] = (char*)utf8_text;
120				}
121				else if(!strcmp(pid3frame->id, "TALB"))
122				{
123					used = 1;
124					psong->album = (char*)utf8_text;
125				}
126				else if(!strcmp(pid3frame->id, "TCOM"))
127				{
128					used = 1;
129					psong->contributor[ROLE_COMPOSER] = (char*)utf8_text;
130				}
131				else if(!strcmp(pid3frame->id, "TIT1"))
132				{
133					used = 1;
134					psong->grouping = (char*)utf8_text;
135				}
136				else if(!strcmp(pid3frame->id, "TPE2"))
137				{
138					used = 1;
139					psong->contributor[ROLE_BAND] = (char*)utf8_text;
140				}
141				else if(!strcmp(pid3frame->id, "TPE3"))
142				{
143					used = 1;
144					psong->contributor[ROLE_CONDUCTOR] = (char*)utf8_text;
145				}
146				else if(!strcmp(pid3frame->id, "TCON"))
147				{
148					used = 1;
149					psong->genre = (char*)utf8_text;
150					got_numeric_genre = 0;
151					if(psong->genre)
152					{
153						if(!strlen(psong->genre))
154						{
155							genre = WINAMP_GENRE_UNKNOWN;
156							got_numeric_genre = 1;
157						}
158						else if(isdigit(psong->genre[0]))
159						{
160							genre = atoi(psong->genre);
161							got_numeric_genre = 1;
162						}
163						else if((psong->genre[0] == '(') && (isdigit(psong->genre[1])))
164						{
165							genre = atoi((char*)&psong->genre[1]);
166							got_numeric_genre = 1;
167						}
168
169						if(got_numeric_genre)
170						{
171							if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN))
172								genre = WINAMP_GENRE_UNKNOWN;
173							free(psong->genre);
174							psong->genre = strdup(winamp_genre[genre]);
175						}
176					}
177				}
178				else if(!strcmp(pid3frame->id, "COMM"))
179				{
180					used = 1;
181					psong->comment = (char*)utf8_text;
182				}
183				else if(!strcmp(pid3frame->id, "TPOS"))
184				{
185					tmp = (char*)utf8_text;
186					strsep(&tmp, "/");
187					if(tmp)
188					{
189						psong->total_discs = atoi(tmp);
190					}
191					psong->disc = atoi((char*)utf8_text);
192				}
193				else if(!strcmp(pid3frame->id, "TRCK"))
194				{
195					tmp = (char*)utf8_text;
196					strsep(&tmp, "/");
197					if(tmp)
198					{
199						psong->total_tracks = atoi(tmp);
200					}
201					psong->track = atoi((char*)utf8_text);
202				}
203				else if(!strcmp(pid3frame->id, "TDRC"))
204				{
205					psong->year = atoi((char*)utf8_text);
206				}
207				else if(!strcmp(pid3frame->id, "TLEN"))
208				{
209					psong->song_length = atoi((char*)utf8_text);
210				}
211				else if(!strcmp(pid3frame->id, "TBPM"))
212				{
213					psong->bpm = atoi((char*)utf8_text);
214				}
215				else if(!strcmp(pid3frame->id, "TCMP"))
216				{
217					psong->compilation = (char)atoi((char*)utf8_text);
218				}
219			}
220		}
221
222		// check if text tag
223		if((!used) && (have_utf8) && (utf8_text))
224			free(utf8_text);
225
226		// v2 COMM
227		if((!strcmp(pid3frame->id, "COMM")) && (pid3frame->nfields == 4))
228		{
229			native_text = id3_field_getstring(&pid3frame->fields[2]);
230			if(native_text)
231			{
232				utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
233				if((utf8_text) && (strncasecmp((char*)utf8_text, "iTun", 4) != 0))
234				{
235					// read comment
236					if(utf8_text)
237						free(utf8_text);
238
239					native_text = id3_field_getfullstring(&pid3frame->fields[3]);
240					if(native_text)
241					{
242						utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
243						if(utf8_text)
244						{
245							if (psong->comment)
246								free(psong->comment);
247							psong->comment = (char*)utf8_text;
248						}
249					}
250				}
251				else
252				{
253					if(utf8_text)
254						free(utf8_text);
255				}
256			}
257		}
258
259		index++;
260	}
261
262	id3_file_close(pid3file);
263	//DEBUG DPRINTF(E_INFO, L_SCANNER, "Got id3 tag successfully for file=%s\n", file);
264	return 0;
265}
266
267// _decode_mp3_frame
268static int
269_decode_mp3_frame(unsigned char *frame, struct mp3_frameinfo *pfi)
270{
271	int ver;
272	int layer_index;
273	int sample_index;
274	int bitrate_index;
275	int samplerate_index;
276
277	if((frame[0] != 0xFF) || (frame[1] < 224))
278	{
279		pfi->is_valid = 0;
280		return -1;
281	}
282
283	ver = (frame[1] & 0x18) >> 3;
284	pfi->layer = 4 - ((frame[1] & 0x6) >> 1);
285
286	layer_index = sample_index = -1;
287
288	switch(ver)
289	{
290	case 0:
291		pfi->mpeg_version = 0x25;       // 2.5
292		sample_index = 2;
293		if(pfi->layer == 1)
294			layer_index = 3;
295		if((pfi->layer == 2) || (pfi->layer == 3))
296			layer_index = 4;
297		break;
298	case 2:
299		pfi->mpeg_version = 0x20;       // 2.0
300		sample_index = 1;
301		if(pfi->layer == 1)
302			layer_index = 3;
303		if((pfi->layer == 2) || (pfi->layer == 3))
304			layer_index = 4;
305		break;
306	case 3:
307		pfi->mpeg_version = 0x10;       // 1.0
308		sample_index = 0;
309		if(pfi->layer == 1)
310			layer_index = 0;
311		if(pfi->layer == 2)
312			layer_index = 1;
313		if(pfi->layer == 3)
314			layer_index = 2;
315		break;
316	}
317
318	if((layer_index < 0) || (layer_index > 4))
319	{
320		pfi->is_valid = 0;
321		return -1;
322	}
323
324	if((sample_index < 0) || (sample_index >= 2))
325	{
326		pfi->is_valid = 0;
327		return -1;
328	}
329
330	if(pfi->layer == 1) pfi->samples_per_frame = 384;
331	if(pfi->layer == 2) pfi->samples_per_frame = 1152;
332	if(pfi->layer == 3)
333	{
334		if(pfi->mpeg_version == 0x10)
335			pfi->samples_per_frame = 1152;
336		else
337			pfi->samples_per_frame = 576;
338	}
339
340	bitrate_index = (frame[2] & 0xF0) >> 4;
341	samplerate_index = (frame[2] & 0x0C) >> 2;
342
343	if((bitrate_index == 0xF) || (bitrate_index == 0x0))
344	{
345		pfi->is_valid = 0;
346		return -1;
347	}
348
349	if(samplerate_index == 3)
350	{
351		pfi->is_valid = 0;
352		return -1;
353	}
354
355
356	pfi->bitrate = bitrate_tbl[layer_index][bitrate_index];
357	pfi->samplerate = sample_rate_tbl[sample_index][samplerate_index];
358
359	if((frame[3] & 0xC0 >> 6) == 3)
360		pfi->stereo = 0;
361	else
362		pfi->stereo = 1;
363
364	if(frame[2] & 0x02)
365		pfi->padding = 1;
366	else
367		pfi->padding = 0;
368
369	if(pfi->mpeg_version == 0x10)
370	{
371		if(pfi->stereo)
372			pfi->xing_offset = 32;
373		else
374			pfi->xing_offset = 17;
375	}
376	else
377	{
378		if(pfi->stereo)
379			pfi->xing_offset = 17;
380		else
381			pfi->xing_offset = 9;
382	}
383
384	pfi->crc_protected = frame[1] & 0xFE;
385
386	if(pfi->layer == 1)
387		pfi->frame_length = (12 * pfi->bitrate * 1000 / pfi->samplerate + pfi->padding) * 4;
388	else
389		pfi->frame_length = 144 * pfi->bitrate * 1000 / pfi->samplerate + pfi->padding;
390
391	if((pfi->frame_length > 2880) || (pfi->frame_length <= 0))
392	{
393		pfi->is_valid = 0;
394		return -1;
395	}
396
397	pfi->is_valid = 1;
398	return 0;
399}
400
401// _mp3_get_average_bitrate
402//    read from midle of file, and estimate
403static void _mp3_get_average_bitrate(FILE *infile, struct mp3_frameinfo *pfi, const char *fname)
404{
405	off_t file_size;
406	unsigned char frame_buffer[2900];
407	unsigned char header[4];
408	int index = 0;
409	int found = 0;
410	off_t pos;
411	struct mp3_frameinfo fi;
412	int frame_count = 0;
413	int bitrate_total = 0;
414
415	fseek(infile, 0, SEEK_END);
416	file_size = ftell(infile);
417
418	pos = file_size >> 1;
419
420	/* now, find the first frame */
421	fseek(infile, pos, SEEK_SET);
422	if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) != sizeof(frame_buffer))
423		return;
424
425	while(!found)
426	{
427		while((frame_buffer[index] != 0xFF) && (index < (sizeof(frame_buffer) - 4)))
428			index++;
429
430		if(index >= (sizeof(frame_buffer) - 4))   // max mp3 framesize = 2880
431		{
432			DPRINTF(E_DEBUG, L_SCANNER, "Could not find frame for %s\n", basename((char *)fname));
433			return;
434		}
435
436		if(!_decode_mp3_frame(&frame_buffer[index], &fi))
437		{
438			/* see if next frame is valid */
439			fseek(infile, pos + index + fi.frame_length, SEEK_SET);
440			if(fread(header, 1, sizeof(header), infile) != sizeof(header))
441			{
442				DPRINTF(E_DEBUG, L_SCANNER, "Could not read frame header for %s\n", basename((char *)fname));
443				return;
444			}
445
446			if(!_decode_mp3_frame(header, &fi))
447				found = 1;
448		}
449
450		if(!found)
451			index++;
452	}
453
454	pos += index;
455
456	// got first frame
457	while(frame_count < 10)
458	{
459		fseek(infile, pos, SEEK_SET);
460		if(fread(header, 1, sizeof(header), infile) != sizeof(header))
461		{
462			DPRINTF(E_DEBUG, L_SCANNER, "Could not read frame header for %s\n", basename((char *)fname));
463			return;
464		}
465		if(_decode_mp3_frame(header, &fi))
466		{
467			DPRINTF(E_DEBUG, L_SCANNER, "Invalid frame header while averaging %s\n", basename((char *)fname));
468			return;
469		}
470
471		bitrate_total += fi.bitrate;
472		frame_count++;
473		pos += fi.frame_length;
474	}
475
476	pfi->bitrate = bitrate_total / frame_count;
477
478	return;
479}
480
481// _mp3_get_frame_count
482//   do brute scan
483static void __attribute__((unused))
484_mp3_get_frame_count(FILE *infile, struct mp3_frameinfo *pfi)
485{
486	int pos;
487	int frames = 0;
488	unsigned char frame_buffer[4];
489	struct mp3_frameinfo fi;
490	off_t file_size;
491	int err = 0;
492	int cbr = 1;
493	int last_bitrate = 0;
494
495	fseek(infile, 0, SEEK_END);
496	file_size = ftell(infile);
497
498	pos = pfi->frame_offset;
499
500	while(1)
501	{
502		err = 1;
503
504		fseek(infile, pos, SEEK_SET);
505		if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) == sizeof(frame_buffer))
506		{
507			// valid frame?
508			if(!_decode_mp3_frame(frame_buffer, &fi))
509			{
510				frames++;
511				pos += fi.frame_length;
512				err = 0;
513
514				if((last_bitrate) && (fi.bitrate != last_bitrate))
515					cbr = 0;
516				last_bitrate = fi.bitrate;
517
518				// no sense to scan cbr
519				if(cbr && (frames > 100))
520				{
521					DPRINTF(E_DEBUG, L_SCANNER, "File appears to be CBR... quitting frame _mp3_get_frame_count()\n");
522					return;
523				}
524			}
525		}
526
527		if(err)
528		{
529			if(pos > (file_size - 4096))
530			{
531				pfi->number_of_frames = frames;
532				return;
533			}
534			else
535			{
536				DPRINTF(E_ERROR, L_SCANNER, "Frame count aborted on error.  Pos=%d, Count=%d\n",
537					pos, frames);
538				return;
539			}
540		}
541	}
542}
543
544// _get_mp3fileinfo
545static int
546_get_mp3fileinfo(char *file, struct song_metadata *psong)
547{
548	FILE *infile;
549	struct id3header *pid3;
550	struct mp3_frameinfo fi;
551	unsigned int size = 0;
552	unsigned int n_read;
553	off_t fp_size = 0;
554	off_t file_size;
555	unsigned char buffer[1024];
556	int index;
557
558	int xing_flags;
559	int found;
560
561	int first_check = 0;
562	char frame_buffer[4];
563
564	char id3v1taghdr[4];
565
566	if(!(infile = fopen(file, "rb")))
567	{
568		DPRINTF(E_ERROR, L_SCANNER, "Could not open %s for reading\n", file);
569		return -1;
570	}
571
572	memset((void*)&fi, 0, sizeof(fi));
573
574	fseek(infile, 0, SEEK_END);
575	file_size = ftell(infile);
576	fseek(infile, 0, SEEK_SET);
577
578	if(fread(buffer, 1, sizeof(buffer), infile) != sizeof(buffer))
579	{
580		if(ferror(infile))
581		{
582			DPRINTF(E_ERROR, L_SCANNER, "Error reading: %s [%s]\n", strerror(errno), file);
583		}
584		else
585		{
586			DPRINTF(E_WARN, L_SCANNER, "File too small. Probably corrupted. [%s]\n", file);
587		}
588		fclose(infile);
589		return -1;
590	}
591
592	pid3 = (struct id3header*)buffer;
593
594	found = 0;
595	fp_size = 0;
596
597	if(strncmp((char*)pid3->id, "ID3", 3) == 0)
598	{
599		char tagversion[16];
600
601		/* found an ID3 header... */
602		size = (pid3->size[0] << 21 | pid3->size[1] << 14 |
603			pid3->size[2] << 7 | pid3->size[3]);
604		fp_size = size + sizeof(struct id3header);
605		first_check = 1;
606
607		snprintf(tagversion, sizeof(tagversion), "ID3v2.%d.%d",
608			 pid3->version[0], pid3->version[1]);
609		psong->tagversion = strdup(tagversion);
610	}
611
612	index = 0;
613
614	/* Here we start the brute-force header seeking.  Sure wish there
615	 * weren't so many crappy mp3 files out there
616	 */
617
618	while(!found)
619	{
620		fseek(infile, fp_size, SEEK_SET);
621		if((n_read = fread(buffer, 1, sizeof(buffer), infile)) < 4)   // at least mp3 frame header size (i.e. 4 bytes)
622		{
623			fclose(infile);
624			return 0;
625		}
626
627		index = 0;
628		while(!found)
629		{
630			while((buffer[index] != 0xFF) && (index < (n_read - 50)))
631				index++;
632
633			if((first_check) && (index))
634			{
635				fp_size = 0;
636				first_check = 0;
637				if(n_read < sizeof(buffer))
638				{
639					fclose(infile);
640					return 0;
641				}
642				break;
643			}
644
645			if(index > (n_read - 50))
646			{
647				fp_size += index;
648				if(n_read < sizeof(buffer))
649				{
650					fclose(infile);
651					return 0;
652				}
653				break;
654			}
655
656			if(!_decode_mp3_frame(&buffer[index], &fi))
657			{
658				if(!strncasecmp((char*)&buffer[index + fi.xing_offset + 4], "XING", 4))
659				{
660					/* no need to check further... if there is a xing header there,
661					 * this is definately a valid frame */
662					found = 1;
663					fp_size += index;
664				}
665				else
666				{
667					/* No Xing... check for next frame to validate current fram is correct */
668					fseek(infile, fp_size + index + fi.frame_length, SEEK_SET);
669					if(fread(frame_buffer, 1, sizeof(frame_buffer), infile) == sizeof(frame_buffer))
670					{
671						if(!_decode_mp3_frame((unsigned char*)frame_buffer, &fi))
672						{
673							found = 1;
674							fp_size += index;
675						}
676					}
677					else
678					{
679						DPRINTF(E_ERROR, L_SCANNER, "Could not read frame header: %s\n", file);
680						fclose(infile);
681						return 0;
682					}
683
684					if(!found)
685					{
686						// cannot find second frame. Song may be too short. So assume first frame is valid.
687						found = 1;
688						fp_size += index;
689					}
690				}
691			}
692
693			if(!found)
694			{
695				index++;
696				if(first_check)
697				{
698					DPRINTF(E_INFO, L_SCANNER, "Bad header... dropping back for full frame search [%s]\n", psong->path);
699					first_check = 0;
700					fp_size = 0;
701					break;
702				}
703			}
704		}
705	}
706
707	fi.frame_offset = fp_size;
708
709	psong->audio_offset = fp_size;
710	psong->audio_size = file_size - fp_size;
711	// check if last 128 bytes is ID3v1.0 ID3v1.1 tag
712	fseek(infile, file_size - 128, SEEK_SET);
713	if(fread(id3v1taghdr, 1, 4, infile) == 4)
714	{
715		if(id3v1taghdr[0] == 'T' && id3v1taghdr[1] == 'A' && id3v1taghdr[2] == 'G')
716		{
717			psong->audio_size -= 128;
718		}
719	}
720
721	if(_decode_mp3_frame(&buffer[index], &fi))
722	{
723		fclose(infile);
724		DPRINTF(E_ERROR, L_SCANNER, "Could not find sync frame: %s\n", file);
725		return 0;
726	}
727
728	/* now check for an XING header */
729	psong->vbr_scale = -1;
730	if(!strncasecmp((char*)&buffer[index + fi.xing_offset + 4], "XING", 4))
731	{
732		xing_flags = *((int*)&buffer[index + fi.xing_offset + 4 + 4]);
733		xing_flags = ntohs(xing_flags);
734		psong->vbr_scale = 78;
735
736		if(xing_flags & 0x1)
737		{
738			/* Frames field is valid... */
739			fi.number_of_frames = *((int*)&buffer[index + fi.xing_offset + 4 + 8]);
740			fi.number_of_frames = ntohs(fi.number_of_frames);
741		}
742	}
743
744	if((fi.number_of_frames == 0) && (!psong->song_length))
745	{
746		_mp3_get_average_bitrate(infile, &fi, file);
747	}
748
749	psong->bitrate = fi.bitrate * 1000;
750	psong->samplerate = fi.samplerate;
751
752	if(!psong->song_length)
753	{
754		if(fi.number_of_frames)
755		{
756			psong->song_length = (int)((double)(fi.number_of_frames * fi.samples_per_frame * 1000.) /
757						   (double)fi.samplerate);
758			psong->vbr_scale = 78;
759		}
760		else
761		{
762			psong->song_length = (int)((double)(file_size - fp_size) * 8. /
763						   (double)fi.bitrate);
764		}
765	}
766	psong->channels = fi.stereo ? 2 : 1;
767
768	fclose(infile);
769	//DEBUG DPRINTF(E_INFO, L_SCANNER, "Got fileinfo successfully for file=%s song_length=%d\n", file, psong->song_length);
770
771	psong->blockalignment = 1;
772	asprintf(&(psong->dlna_pn), "MP3");
773
774	return 0;
775}
776