tracker-extract-mp3.c 59.7 KB
Newer Older
1
/*
2
 * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org>
3
 * Copyright (C) 2008-2009, Nokia <ivan.frade@nokia.com>
4
 *
5 6
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2.1 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 14 15 16
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#include "config.h"

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
34
#include <errno.h>
35 36 37 38 39 40

#include <glib.h>
#include <glib/gstdio.h>

#ifndef G_OS_WIN32
#include <sys/mman.h>
41
#endif /* G_OS_WIN32 */
42

43 44
#include <libtracker-common/tracker-common.h>

45 46
#include <libtracker-extract/tracker-extract.h>

47
#include "tracker-media-art.h"
48

49 50 51 52
#ifdef FRAME_ENABLE_TRACE
#warning Frame traces enabled
#endif /* FRAME_ENABLE_TRACE */

53 54 55 56 57 58 59
/* We mmap the beginning of the file and read separately the last 128
 * bytes for id3v1 tags. While these are probably cornercases the
 * rationale is that we don't want to fault a whole page for the last
 * 128 bytes and on the other we don't want to mmap the whole file
 * with unlimited size (might need to create private copy in some
 * special cases, finding continuous space etc). We now take 5 first
 * MB of the file and assume that this is enough. In theory there is
60
 * no maximum size as someone could embed 50 gigabytes of album art
61
 * there.
62
 */
63

64
#define MAX_FILE_READ     1024 * 1024 * 5
65 66
#define MAX_MP3_SCAN_DEEP 16768

67 68 69 70
#define MAX_FRAMES_SCAN   512
#define VBR_THRESHOLD     16

#define ID3V1_SIZE        128
71

72 73 74 75
typedef struct {
	gchar *title;
	gchar *artist;
	gchar *album;
76
	gchar *recording_time;
77 78
	gchar *comment;
	gchar *genre;
79
	gchar *encoding;
80
	gint   track_number;
81 82
} id3tag;

83 84 85 86 87
typedef struct {
	gchar *album;
	gchar *comment;
	gchar *content_type;
	gchar *copyright;
88
	gchar *encoded_by;
89 90 91
	guint32 length;
	gchar *performer1;
	gchar *performer2;
92
	gchar *composer;
93 94 95
	gchar *publisher;
	gchar *recording_time;
	gchar *release_time;
96
	gchar *text, *toly;
97 98 99 100
	gchar *title1;
	gchar *title2;
	gchar *title3;
	gint track_number;
101
	gint track_count;
102 103
	gint set_number;
	gint set_count;
104 105
} id3v2tag;

106 107 108 109 110 111 112
typedef enum {
	ID3V2_UNKNOWN,
	ID3V2_COM,
	ID3V2_PIC,
	ID3V2_TAL,
	ID3V2_TCO,
	ID3V2_TCR,
113
	ID3V2_TEN,
114 115 116 117
	ID3V2_TLE,
	ID3V2_TPB,
	ID3V2_TP1,
	ID3V2_TP2,
118
	ID3V2_TRK,
119 120 121 122 123 124
	ID3V2_TT1,
	ID3V2_TT2,
	ID3V2_TT3,
	ID3V2_TXT,
	ID3V2_TYE,
} id3v2frame;
125

126 127 128 129 130
typedef enum {
	ID3V24_UNKNOWN,
	ID3V24_APIC,
	ID3V24_COMM,
	ID3V24_TALB,
131
	ID3V24_TCOM,
132 133 134 135
	ID3V24_TCON,
	ID3V24_TCOP,
	ID3V24_TDRC,
	ID3V24_TDRL,
136
	ID3V24_TENC,
137 138 139 140 141
	ID3V24_TEXT,
	ID3V24_TIT1,
	ID3V24_TIT2,
	ID3V24_TIT3,
	ID3V24_TLEN,
142
	ID3V24_TOLY,
143 144 145 146
	ID3V24_TPE1,
	ID3V24_TPE2,
	ID3V24_TPUB,
	ID3V24_TRCK,
147
	ID3V24_TPOS,
148 149 150
	ID3V24_TYER,
} id3v24frame;

151 152 153 154
typedef struct {
	size_t size;
	size_t id3v2_size;

155 156
	const gchar *title;
	const gchar *performer;
157
	gchar *performer_uri;
158
	const gchar *lyricist;
159
	gchar *lyricist_uri;
160
	const gchar *album;
161
	gchar *album_uri;
162 163 164
	const gchar *genre;
	const gchar *text;
	const gchar *recording_time;
165
	const gchar *encoded_by;
166 167 168 169
	const gchar *copyright;
	const gchar *publisher;
	const gchar *comment;
	const gchar *composer;
170
	gchar *composer_uri;
171
	gint track_number;
172
	gint track_count;
173 174
	gint set_number;
	gint set_count;
175

176 177 178
	unsigned char *media_art_data;
	size_t media_art_size;
	gchar *media_art_mime;
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199

	id3tag id3v1;
	id3v2tag id3v22;
	id3v2tag id3v23;
	id3v2tag id3v24;
} MP3Data;

enum {
	MPEG_ERR,
	MPEG_V1,
	MPEG_V2,
	MPEG_V25
};

enum {
	LAYER_ERR,
	LAYER_1,
	LAYER_2,
	LAYER_3
};

200
/* sorted array */
201 202 203
static const struct {
	const char *name;
	id3v24frame frame;
204
} id3v24_frames[] = {
205 206 207
	{ "APIC", ID3V24_APIC },
	{ "COMM", ID3V24_COMM },
	{ "TALB", ID3V24_TALB },
208
	{ "TCOM", ID3V24_TCOM },
209 210 211 212
	{ "TCON", ID3V24_TCON },
	{ "TCOP", ID3V24_TCOP },
	{ "TDRC", ID3V24_TDRC },
	{ "TDRL", ID3V24_TDRL },
213
	{ "TENC", ID3V24_TENC },
214 215 216 217 218
	{ "TEXT", ID3V24_TEXT },
	{ "TIT1", ID3V24_TIT1 },
	{ "TIT2", ID3V24_TIT2 },
	{ "TIT3", ID3V24_TIT3 },
	{ "TLEN", ID3V24_TLEN },
219
	{ "TOLY", ID3V24_TOLY },
220 221
	{ "TPE1", ID3V24_TPE1 },
	{ "TPE2", ID3V24_TPE2 },
222
	{ "TPOS", ID3V24_TPOS },
223 224 225 226 227 228
	{ "TPUB", ID3V24_TPUB },
	{ "TRCK", ID3V24_TRCK },
	{ "TYER", ID3V24_TYER },
};

/* sorted array */
229 230 231
static const struct {
	const char *name;
	id3v2frame frame;
232
} id3v2_frames[] = {
233 234 235 236 237
	{ "COM", ID3V2_COM },
	{ "PIC", ID3V2_PIC },
	{ "TAL", ID3V2_TAL },
	{ "TCO", ID3V2_TCO },
	{ "TCR", ID3V2_TCR },
238
	{ "TEN", ID3V2_TEN },
239 240 241
	{ "TLE", ID3V2_TLE },
	{ "TP1", ID3V2_TP1 },
	{ "TP2", ID3V2_TP2 },
242
	{ "TPB", ID3V2_TPB },
243
	{ "TRK", ID3V2_TRK },
244 245 246 247 248 249 250
	{ "TT1", ID3V2_TT1 },
	{ "TT2", ID3V2_TT2 },
	{ "TT3", ID3V2_TT3 },
	{ "TXT", ID3V2_TXT },
	{ "TYE", ID3V2_TYE },
};

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
static const char *const genre_names[] = {
	"Blues",
	"Classic Rock",
	"Country",
	"Dance",
	"Disco",
	"Funk",
	"Grunge",
	"Hip-Hop",
	"Jazz",
	"Metal",
	"New Age",
	"Oldies",
	"Other",
	"Pop",
	"R&B",
	"Rap",
	"Reggae",
	"Rock",
	"Techno",
	"Industrial",
	"Alternative",
	"Ska",
	"Death Metal",
	"Pranks",
	"Soundtrack",
	"Euro-Techno",
	"Ambient",
	"Trip-Hop",
	"Vocal",
	"Jazz+Funk",
	"Fusion",
	"Trance",
	"Classical",
	"Instrumental",
	"Acid",
	"House",
	"Game",
	"Sound Clip",
	"Gospel",
	"Noise",
	"Alt. Rock",
	"Bass",
	"Soul",
	"Punk",
	"Space",
	"Meditative",
	"Instrumental Pop",
	"Instrumental Rock",
	"Ethnic",
	"Gothic",
	"Darkwave",
	"Techno-Industrial",
	"Electronic",
	"Pop-Folk",
	"Eurodance",
	"Dream",
	"Southern Rock",
	"Comedy",
	"Cult",
	"Gangsta Rap",
	"Top 40",
	"Christian Rap",
	"Pop/Funk",
	"Jungle",
	"Native American",
	"Cabaret",
	"New Wave",
	"Psychedelic",
	"Rave",
	"Showtunes",
	"Trailer",
	"Lo-Fi",
	"Tribal",
	"Acid Punk",
	"Acid Jazz",
	"Polka",
	"Retro",
	"Musical",
	"Rock & Roll",
	"Hard Rock",
	"Folk",
	"Folk/Rock",
	"National Folk",
	"Swing",
	"Fast-Fusion",
	"Bebob",
	"Latin",
	"Revival",
	"Celtic",
	"Bluegrass",
	"Avantgarde",
	"Gothic Rock",
	"Progressive Rock",
	"Psychedelic Rock",
	"Symphonic Rock",
	"Slow Rock",
	"Big Band",
	"Chorus",
	"Easy Listening",
	"Acoustic",
	"Humour",
	"Speech",
	"Chanson",
	"Opera",
	"Chamber Music",
	"Sonata",
	"Symphony",
	"Booty Bass",
	"Primus",
	"Porn Groove",
	"Satire",
	"Slow Jam",
	"Club",
	"Tango",
	"Samba",
	"Folklore",
	"Ballad",
	"Power Ballad",
	"Rhythmic Soul",
	"Freestyle",
	"Duet",
	"Punk Rock",
	"Drum Solo",
	"A Cappella",
	"Euro-House",
	"Dance Hall",
	"Goa",
	"Drum & Bass",
	"Club-House",
	"Hardcore",
	"Terror",
	"Indie",
	"BritPop",
	"Negerpunk",
	"Polsk Punk",
	"Beat",
	"Christian Gangsta Rap",
	"Heavy Metal",
	"Black Metal",
	"Crossover",
	"Contemporary Christian",
	"Christian Rock",
	"Merengue",
	"Salsa",
	"Thrash Metal",
	"Anime",
	"JPop",
	"Synthpop"
};

static const guint sync_mask = 0xE0FF;
static const guint mpeg_ver_mask = 0x1800;
static const guint mpeg_layer_mask = 0x600;
static const guint bitrate_mask = 0xF00000;
static const guint freq_mask = 0xC0000;
static const guint ch_mask = 0xC0000000;
static const guint pad_mask = 0x20000;

410
static gint bitrate_table[16][6] = {
411
	{   0,   0,   0,   0,   0,   0 },
412 413 414 415 416 417 418 419 420 421 422 423 424 425
	{  32,  32,  32,  32,   8,   8 },
	{  64,  48,  40,  48,  16,  16 },
	{  96,  56,  48,  56,  24,  24 },
	{ 128,  64,  56,  64,  32,  32 },
	{ 160,  80,  64,  80,  40,  40 },
	{ 192,  96,  80,  96,  48,  48 },
	{ 224, 112,  96, 112,  56,  56 },
	{ 256, 128, 112, 128,  64,  64 },
	{ 288, 160, 128, 144,  80,  80 },
	{ 320, 192, 160, 160,  96,  96 },
	{ 352, 224, 192, 176, 112, 112 },
	{ 384, 256, 224, 192, 128, 128 },
	{ 416, 320, 256, 224, 144, 144 },
	{ 448, 384, 320, 256, 160, 160 },
426
	{  -1,  -1,  -1,  -1,  -1,  -1 }
427 428 429
};

static gint freq_table[4][3] = {
430 431
	{ 44100, 22050, 11025 },
	{ 48000, 24000, 12000 },
432 433
	{ 32000, 16000,  8000 },
	{    -1,     -1,   -1 }
434 435
};

436 437
static gint spf_table[6] = {
	48, 144, 144, 48, 144,  72
438
};
439

440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
static void
id3tag_free (id3tag *tags)
{
	g_free (tags->title);
	g_free (tags->artist);
	g_free (tags->album);
	g_free (tags->recording_time);
	g_free (tags->comment);
	g_free (tags->genre);
	g_free (tags->encoding);
}

static void
id3v2tag_free (id3v2tag *tags)
{
	g_free (tags->album);
	g_free (tags->comment);
	g_free (tags->content_type);
	g_free (tags->copyright);
	g_free (tags->performer1);
	g_free (tags->performer2);
	g_free (tags->composer);
	g_free (tags->publisher);
	g_free (tags->recording_time);
	g_free (tags->release_time);
465
	g_free (tags->encoded_by);
466 467 468 469 470 471 472
	g_free (tags->text);
	g_free (tags->toly);
	g_free (tags->title1);
	g_free (tags->title2);
	g_free (tags->title3);
}

473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
static gboolean
guess_dlna_profile (gint          bitrate,
                    gint          frequency,
                    gint          mpeg_version,
                    gint          layer_version,
                    gint          n_channels,
                    const gchar **dlna_profile,
                    const gchar **dlna_mimetype)
{
	if (mpeg_version == MPEG_V1 &&
	    layer_version == LAYER_3 &&
	    (bitrate >= 32000 && bitrate <= 320000) &&
	    (n_channels == 1 || n_channels == 2) &&
	    (frequency == freq_table[0][0] ||
	     frequency == freq_table[1][0] ||
	     frequency == freq_table[2][0])) {
		*dlna_profile = "MP3";
		*dlna_mimetype = "audio/mpeg";
		return TRUE;
	}

	if ((bitrate >= 8000 && bitrate <= 320000) &&
	    (mpeg_version == MPEG_V1 || mpeg_version == MPEG_V2) &&
	    (frequency == freq_table[0][0] || frequency == freq_table[0][1] ||
	     frequency == freq_table[1][0] || frequency == freq_table[1][1] ||
	     frequency == freq_table[2][0] || frequency == freq_table[2][1])) {
		*dlna_profile = "MP3X";
		*dlna_mimetype = "audio/mpeg";
		return TRUE;
	}

	return FALSE;
}

507
static char *
508 509
read_id3v1_buffer (int     fd,
                   goffset size)
510 511 512 513 514
{
	char *buffer;
	guint bytes_read;
	guint rc;

515
	if (size < 128) {
516 517
		return NULL;
	}
518

519
	if (lseek (fd, size - ID3V1_SIZE, SEEK_SET) < 0) {
520 521
		return NULL;
	}
522

523 524 525
	buffer = g_malloc (ID3V1_SIZE);

	if (!buffer) {
526 527 528 529
		return NULL;
	}

	bytes_read = 0;
530

531
	while (bytes_read < ID3V1_SIZE) {
532
		rc = read (fd,
533 534
		           buffer + bytes_read,
		           ID3V1_SIZE - bytes_read);
535 536 537 538 539
		if (rc == -1) {
			if (errno != EINTR) {
				g_free (buffer);
				return NULL;
			}
540
		} else if (rc == 0) {
541
			break;
542
		} else {
543
			bytes_read += rc;
544
		}
545
	}
546

547 548 549
	return buffer;
}

550 551
/* Convert from UCS-2 to UTF-8 checking the BOM.*/
static gchar *
552
ucs2_to_utf8(const gchar *data, guint len)
553
{
554
	const gchar *encoding = NULL;
555
	guint16  c;
556
	gboolean be;
557
	gchar *utf8 = NULL;
558

559
	memcpy (&c, data, 2);
560

561
	switch (c) {
562 563
	case 0xfeff:
	case 0xfffe:
564 565 566
		be = (G_BYTE_ORDER == G_BIG_ENDIAN);
		be = (c == 0xfeff) ? be : !be;
		encoding = be ? "UCS-2BE" : "UCS-2LE";
567 568 569 570 571 572 573
		data += 2;
		len -= 2;
		break;
	default:
		encoding = "UCS-2";
		break;
	}
574

575
	utf8 = g_convert (data, len, "UTF-8", encoding, NULL, NULL, NULL);
576

577
	return utf8;
578 579
}

580 581 582 583 584 585 586 587 588
/* Get the genre codes from regular expressions */
static gboolean
get_genre_number (const char *str, guint *genre)
{
	static GRegex *regex1 = NULL;
	static GRegex *regex2 = NULL;
	GMatchInfo *info = NULL;
	gchar *result = NULL;

589
	if (!regex1) {
590
		regex1 = g_regex_new ("\\(([0-9]+)\\)", 0, 0, NULL);
591
	}
592

593
	if (!regex2) {
594
		regex2 = g_regex_new ("([0-9]+)\\z", 0, 0, NULL);
595
	}
596

597 598
	if (g_regex_match (regex1, str, 0, &info)) {
		result = g_match_info_fetch (info, 1);
599
		if (result) {
600
			*genre = atoi (result);
601 602 603 604 605 606 607 608
			g_free (result);
			g_match_info_free (info);
			return TRUE;
		}
	}

	g_match_info_free (info);

609 610
	if (g_regex_match (regex2, str, 0, &info)) {
		result = g_match_info_fetch (info, 1);
611
		if (result) {
612
			*genre = atoi (result);
613 614 615
			g_free (result);
			g_match_info_free (info);
			return TRUE;
616
		}
617 618 619 620 621 622
	}

	g_match_info_free (info);

	return FALSE;
}
623

624 625 626
static const gchar *
get_genre_name (guint number)
{
627
	if (number >= G_N_ELEMENTS (genre_names)) {
628 629 630 631 632 633
		return NULL;
	}

	return genre_names[number];
}

634 635
static void
un_unsync (const unsigned char *source,
636 637 638
           size_t               size,
           unsigned char      **destination,
           size_t              *dest_size)
639
{
640 641 642
	size_t offset;
	gchar *dest;
	size_t new_size;
643

644
	offset       = 0;
645 646
	*destination = g_malloc0 (size);
	dest         = *destination;
647
	new_size     = size;
648 649 650 651

	while (offset < size) {
		*dest = source[offset];

652
		if ((source[offset] == 0xFF) &&
653
		    (source[offset + 1] == 0x00)) {
654 655 656 657 658 659
			offset++;
			new_size--;
		}
		dest++;
		offset++;
	}
660

661 662 663
	*dest_size = new_size;
}

664 665 666 667
static gchar *
get_encoding (const gchar *data,
              gsize        size,
              gboolean    *encoding_found)
668
{
669
	gchar *encoding;
670

671 672 673 674
	/* Try to guess encoding */
	encoding = (data && size ?
	            tracker_encoding_guess (data, size) :
	            NULL);
675

676 677 678
	/* Notify if a proper detection was done */
	if (encoding_found) {
		*encoding_found = (encoding ? TRUE : FALSE);;
679 680
	}

681
	/* If no proper detection was done, return default */
682
	if (!encoding) {
683 684 685 686
		/* Use Windows-1252 instead of ISO-8859-1 as the former is a
		   superset in terms of printable characters and some
		   applications use it to encode characters in ID3 tags */
		encoding = g_strdup ("Windows-1252");
687 688 689 690 691
	}

	return encoding;
}

692 693
static gchar *
convert_to_encoding (const gchar  *str,
694 695 696 697 698 699
                     gssize        len,
                     const gchar  *to_codeset,
                     const gchar  *from_codeset,
                     gsize        *bytes_read,
                     gsize        *bytes_written,
                     GError      **error_out)
700
{
701 702 703 704 705 706
	GError *error = NULL;
	gchar *word;

	/* g_print ("%s for %s\n", from_codeset, str); */

	word = g_convert (str,
707 708 709 710 711 712
	                  len,
	                  to_codeset,
	                  from_codeset,
	                  bytes_read,
	                  bytes_written,
	                  &error);
713 714 715 716 717 718 719 720

	if (error) {
		gchar *encoding;

		encoding = get_encoding (str, len, NULL);
		g_free (word);

		word = g_convert (str,
721 722 723 724 725 726
		                  len,
		                  to_codeset,
		                  encoding,
		                  bytes_read,
		                  bytes_written,
		                  error_out);
727 728 729 730 731 732

		g_free (encoding);
		g_error_free (error);
	}

	return word;
733 734
}

735 736
static gboolean
get_id3 (const gchar *data,
737 738
         size_t       size,
         id3tag      *id3)
739
{
740
	gchar *encoding, *year;
741 742
	const gchar *pos;

743 744 745
	if (!data) {
		return FALSE;
	}
746

747 748 749 750 751 752 753 754 755 756
	if (size < 128) {
		return FALSE;
	}

	pos = &data[size - 128];

	if (strncmp ("TAG", pos, 3) != 0) {
		return FALSE;
	}

757
	/* Now convert all the data separately */
758 759
	pos += 3;

760 761 762 763
	/* We don't use our magic convert_to_encoding here because we
	 * have a better way to collect a bit more data before we let
	 * enca loose on it for v1.
	 */
764 765 766
	if (tracker_encoding_can_guess ()) {
		GString *s;
		gboolean encoding_was_found;
767

768
		/* Get the encoding for ALL the data we are extracting here */
769 770
		/* This wont work with encodings where a NUL byte may be actually valid,
		 * like UTF-16 */
771 772 773 774
		s = g_string_new_len (pos, strnlen (pos, 30));
		g_string_append_len (s, pos + 30, strnlen (pos+30, 30));
		g_string_append_len (s, pos + 60, strnlen (pos+60, 30));
		g_string_append_len (s, pos + 94, strnlen (pos+94, ((pos+94)[28] != 0) ? 30 : 28));
775

776
		encoding = get_encoding (s->str, s->len, &encoding_was_found);
777 778 779 780

		if (encoding_was_found) {
			id3->encoding = g_strdup (encoding);
		}
781

782 783 784 785 786 787
		g_string_free (s, TRUE);
	} else {
		/* If we cannot guess encoding, don't even try it, just
		 * use the default one */
		encoding = get_encoding (NULL, 0, NULL);
	}
788 789

	id3->title = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL);
790

791
	pos += 30;
792 793
	id3->artist = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL);

794
	pos += 30;
795 796
	id3->album = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL);

797
	pos += 30;
798
	year = g_convert (pos, 4, "UTF-8", encoding, NULL, NULL, NULL);
799
	if (year && atoi (year) > 0) {
800
		id3->recording_time = tracker_date_guess (year);
801 802
	}
	g_free (year);
803 804

	pos += 4;
805

806 807
	if (pos[28] != 0) {
		id3->comment = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL);
808
		id3->track_number = 0;
809
	} else {
810 811 812 813
		gchar buf[5];

		id3->comment = g_convert (pos, 28, "UTF-8", encoding, NULL, NULL, NULL);

814
		snprintf (buf, 5, "%d", pos[29]);
815
		id3->track_number = atoi (buf);
816 817
	}

818
	pos += 30;
819 820 821
	id3->genre = g_strdup (get_genre_name ((guint) pos[0]));

	if (!id3->genre) {
822
		id3->genre = g_strdup ("");
823 824
	}

825 826
	g_free (encoding);

827 828 829
	return TRUE;
}

830 831 832 833
/*
 * For the MP3 frame header description, see
 * http://www.mp3-tech.org/programmer/frame_header.html
 */
834
static gboolean
835
mp3_parse_header (const gchar          *data,
836 837 838 839 840
                  size_t                size,
                  size_t                seek_pos,
                  const gchar          *uri,
                  TrackerSparqlBuilder *metadata,
                  MP3Data              *filedata)
841
{
842
	const gchar *dlna_profile, *dlna_mimetype;
843 844 845
	guint header;
	gchar mpeg_ver = 0;
	gchar layer_ver = 0;
846
	gint spfp8 = 0;
847
	guint padsize = 0;
848
	gint idx_num = 0;
849
	gint bitrate = 0;
850 851 852
	guint avg_bps = 0;
	gint vbr_flag = 0;
	guint length = 0;
853
	gint sample_rate = 0;
854 855 856
	guint frame_size;
	guint frames = 0;
	size_t pos = 0;
857
	gint n_channels;
858

859
	pos = seek_pos;
860

861
	memcpy (&header, &data[pos], sizeof (header));
862

863
	switch (header & mpeg_ver_mask) {
864 865 866 867 868 869 870 871 872 873 874 875
	case 0x1000:
		mpeg_ver = MPEG_V2;
		break;
	case 0x1800:
		mpeg_ver = MPEG_V1;
		break;
	case 0:
		mpeg_ver = MPEG_V25;
		break;
	default:
		/* unknown version */
		return FALSE;
876
	}
877

878
	switch (header & mpeg_layer_mask) {
879 880 881 882 883 884 885 886 887 888 889 890 891 892
	case 0x400:
		layer_ver = LAYER_2;
		padsize = 1;
		break;
	case 0x200:
		layer_ver = LAYER_3;
		padsize = 1;
		break;
	case 0x600:
		layer_ver = LAYER_1;
		padsize = 4;
		break;
	default:
		/* unknown layer */
893
		return FALSE;
894
	}
895

896
	if (mpeg_ver < 3) {
897 898 899 900
		idx_num = (mpeg_ver - 1) * 3 + layer_ver - 1;
	} else {
		idx_num = 2 + layer_ver;
	}
901 902

	spfp8 = spf_table[idx_num];
903

904 905 906
	/* We assume mpeg version, layer and channels are constant in frames */
	do {
		frames++;
907

908 909
		bitrate = 1000 * bitrate_table[(header & bitrate_mask) >> 20][idx_num];

910
		/* Skip frame headers with bitrate index '0000' (free) or '1111' (bad) */
911
		if (bitrate <= 0) {
912
			frames--;
913
			return FALSE;
914 915
		}

916
		sample_rate = freq_table[(header & freq_mask) >> 18][mpeg_ver - 1];
917

918 919
		/* Skip frame headers with frequency index '11' (reserved) */
		if (sample_rate <= 0) {
920
			frames--;
921
			return FALSE;
922
		}
923

924
		frame_size = spfp8 * bitrate / sample_rate + padsize*((header & pad_mask) >> 17);
925 926
		avg_bps += bitrate / 1000;

927
		pos += frame_size;
928

929
		if (frames > MAX_FRAMES_SCAN) {
930 931 932 933 934 935 936 937 938 939 940 941 942
			/* Optimization */
			break;
		}

		if (avg_bps / frames != bitrate / 1000) {
			vbr_flag = 1;
		}

		if (pos + sizeof (header) > size) {
			/* EOF */
			break;
		}

943 944 945 946
		if ((!vbr_flag) && (frames > VBR_THRESHOLD)) {
			break;
		}

947 948 949
		memcpy(&header, &data[pos], sizeof (header));
	} while ((header & sync_mask) == sync_mask);

950 951
	/* At least 2 frames to check the right position */
	if (frames < 2) {
952
		/* No valid frames */
953
		return FALSE;
954 955
	}

956 957 958
	tracker_sparql_builder_predicate (metadata, "nfo:codec");
	tracker_sparql_builder_object_string (metadata, "MPEG");

959 960
	n_channels = ((header & ch_mask) == ch_mask) ? 1 : 2;

961
	tracker_sparql_builder_predicate (metadata, "nfo:channels");
962
	tracker_sparql_builder_object_int64 (metadata, n_channels);
963

964 965
	avg_bps /= frames;

966 967 968 969 970
	if ((!vbr_flag && frames > VBR_THRESHOLD) || (frames > MAX_FRAMES_SCAN)) {
		/* If not all frames scanned
		 * Note that bitrate is always > 0, checked before */
		length = (filedata->size - filedata->id3v2_size) / (avg_bps ? avg_bps : bitrate) / 125;
	} else {
971 972
		/* Note that sample_rate is always > 0, checked before */
		length = spfp8 * 8 * frames / sample_rate;
973 974
	}

975 976 977
	tracker_sparql_builder_predicate (metadata, "nfo:duration");
	tracker_sparql_builder_object_int64 (metadata, length);

978 979 980 981
	tracker_sparql_builder_predicate (metadata, "nfo:sampleRate");
	tracker_sparql_builder_object_int64 (metadata, sample_rate);
	tracker_sparql_builder_predicate (metadata, "nfo:averageBitrate");
	tracker_sparql_builder_object_int64 (metadata, avg_bps*1000);
982

983 984 985 986 987
	if (guess_dlna_profile (bitrate, sample_rate,
	                        mpeg_ver, layer_ver, n_channels,
	                        &dlna_profile, &dlna_mimetype)) {
		tracker_sparql_builder_predicate (metadata, "nmm:dlnaProfile");
		tracker_sparql_builder_object_string (metadata, dlna_profile);
988 989
		tracker_sparql_builder_predicate (metadata, "nmm:dlnaMime");
		tracker_sparql_builder_object_string (metadata, dlna_mimetype);
990 991
	}

992 993 994 995
	return TRUE;
}

static void
996
mp3_parse (const gchar          *data,
997 998 999 1000 1001
           size_t                size,
           size_t                offset,
           const gchar          *uri,
           TrackerSparqlBuilder *metadata,
           MP3Data              *filedata)
1002 1003 1004
{
	guint header;
	guint counter = 0;
1005
	guint pos = offset;
1006 1007 1008

	do {
		/* Seek for frame start */
1009
		if (pos + sizeof (header) > size) {
1010 1011 1012 1013 1014
			return;
		}

		memcpy (&header, &data[pos], sizeof (header));

1015
		if ((header & sync_mask) == sync_mask) {
1016
			/* Found header sync */
1017
			if (mp3_parse_header (data, size, pos, uri, metadata, filedata)) {
1018 1019 1020 1021 1022 1023 1024
				return;
			}
		}

		pos++;
		counter++;
	} while (counter < MAX_MP3_SCAN_DEEP);
1025 1026
}

1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
static gssize
id3v2_nul_size (const gchar encoding)
{
	switch (encoding) {
	case 0x01:
	case 0x02:
		/* UTF-16, string terminated by two NUL bytes */
		return 2;
	default:
		return 1;
	}
}

static gssize
id3v2_strlen (const gchar  encoding,
              const gchar *text,
              gssize       len)
{
	const gchar *pos;

	switch (encoding) {
	case 0x01:
	case 0x02:
1050
		
1051
		/* UTF-16, string terminated by two NUL bytes */
1052 1053 1054 1055 1056 1057 1058 1059
		pos = memmem (text, len, "\0\0\0", 3);

		if (pos == NULL) {
			pos = memmem (text, len, "\0\0", 2);
		} else {
			pos++;
		}

1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
		if (pos != NULL) {
			return pos - text;
		} else {
			return len;
		}
	default:
		return strnlen (text, len);
	}
}

1070
static gchar *
1071
id3v24_text_to_utf8 (const gchar  encoding,
1072
                     const gchar *text,
1073 1074
                     gssize       len,
                     id3tag      *info)
1075 1076 1077
{
	/* This byte describes the encoding
	 * try to convert strings to UTF-8
1078 1079
	 * if it fails, then forget it.
	 * For UTF-16 if size odd assume invalid 00 term.
1080 1081 1082 1083
	 */

	switch (encoding) {
	case 0x00:
1084 1085 1086
		/* Use Windows-1252 instead of ISO-8859-1 as the former is a
		   superset in terms of printable characters and some
		   applications use it to encode characters in ID3 tags */
1087
		return convert_to_encoding (text,
1088 1089
		                            len,
		                            "UTF-8",
1090
		                            info->encoding ? info->encoding : "Windows-1252",
1091
		                            NULL, NULL, NULL);
1092
	case 0x01 :
1093
		return convert_to_encoding (text,
1094
		                            len - len%2,
1095 1096 1097
		                            "UTF-8",
		                            "UTF-16",
		                            NULL, NULL, NULL);
1098
	case 0x02 :
1099
		return convert_to_encoding (text,
1100
		                            len - len%2,
1101 1102 1103
		                            "UTF-8",
		                            "UTF-16BE",
		                            NULL, NULL, NULL);
1104 1105 1106 1107 1108 1109
	case 0x03 :
		return strndup (text, len);

	default:
		/* Bad encoding byte,
		 * try to convert from
1110
		 * Windows-1252
1111
		 */
1112
		return convert_to_encoding (text,
1113 1114
		                            len,
		                            "UTF-8",
1115
		                            info->encoding ? info->encoding : "Windows-1252",
1116
		                            NULL, NULL, NULL);
1117 1118 1119 1120
	}
}

static gchar *
1121 1122
id3v2_text_to_utf8 (const gchar  encoding,
                    const gchar *text,
1123 1124
                    gssize       len,
                    id3tag      *info)
1125 1126 1127 1128
{
	/* This byte describes the encoding
	 * try to convert strings to UTF-8
	 * if it fails, then forget it
1129
	 * For UCS2 if size odd assume invalid 00 term.
1130 1131 1132 1133
	 */

	switch (encoding) {
	case 0x00:
1134 1135 1136
		/* Use Windows-1252 instead of ISO-8859-1 as the former is a
		   superset in terms of printable characters and some
		   applications use it to encode characters in ID3 tags */
1137
		return convert_to_encoding (text,
1138 1139
		                            len,
		                            "UTF-8",
1140
		                            info->encoding ? info->encoding : "Windows-1252",
1141
		                            NULL, NULL, NULL);
1142
	case 0x01 :
1143 1144 1145 1146 1147
		/* return g_convert (text, */
		/*                   len, */
		/*                   "UTF-8", */
		/*                   "UCS-2", */
		/*                   NULL, NULL, NULL); */
1148
		return ucs2_to_utf8 (text, len - len%2);
1149 1150 1151 1152

	default:
		/* Bad encoding byte,
		 * try to convert from
1153
		 * Windows-1252
1154
		 */
1155
		return convert_to_encoding (text,
1156 1157
		                            len,
		                            "UTF-8",
1158
		                            info->encoding ? info->encoding : "Windows-1252",
1159
		                            NULL, NULL, NULL);
1160 1161 1162 1163 1164 1165
	}
}

static id3v24frame
id3v24_get_frame (const gchar *name)
{
1166
	gint l, r, m;
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176

	/* use binary search */

	l = 0;
	r = G_N_ELEMENTS (id3v24_frames) - 1;
	m = 0;

	do {
		m = (l + r) / 2;
		if (strncmp (name, id3v24_frames[m].name, 4) < 0) {
1177
			/* left half */
1178 1179
			r = m - 1;
		} else {
1180
			/* right half */
1181 1182 1183
			l = m + 1;
		}
	} while (l <= r && strncmp (id3v24_frames[m].name, name, 4) != 0);
1184

1185 1186 1187 1188 1189 1190 1191 1192 1193 1194
	if (strncmp (id3v24_frames[m].name, name, 4) == 0) {
		return id3v24_frames[m].frame;
	} else {
		return ID3V24_UNKNOWN;
	}
}

static id3v2frame
id3v2_get_frame (const gchar *name)
{
1195
	gint l, r, m;
1196 1197 1198 1199 1200 1201 1202 1203 1204

	/* use binary search */

	l = 0;
	r = G_N_ELEMENTS (id3v2_frames) - 1;
	m = 0;

	do {
		m = (l + r) / 2;
1205
		if (strncmp (name, id3v2_frames[m].name, 3) < 0) {
1206
			/* left half */
1207 1208
			r = m - 1;
		} else {
1209
			/* right half */
1210 1211
			l = m + 1;
		}
1212
	} while (l <= r && strncmp (id3v2_frames[m].name, name, 3) != 0);
1213

1214
	if (strncmp (id3v2_frames[m].name, name, 3) == 0) {
1215 1216 1217 1218 1219 1220
		return id3v2_frames[m].frame;
	} else {
		return ID3V2_UNKNOWN;
	}
}

1221
static void
1222 1223 1224
get_id3v24_tags (id3v24frame           frame,
                 const gchar          *data,
                 size_t                csize,
1225 1226 1227 1228
                 id3tag               *info,
                 const gchar          *uri,
                 TrackerSparqlBuilder *metadata,
                 MP3Data              *filedata)
1229
{
1230
	id3v2tag *tag = &filedata->id3v24;
1231
	guint pos = 0;
1232

1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
	switch (frame) {
	case ID3V24_APIC: {
		/* embedded image */
		gchar text_type;
		const gchar *mime;
		gchar pic_type;
		const gchar *desc;
		guint offset;
		gint mime_len;

		text_type =  data[pos + 0];
		mime      = &data[pos + 1];
1245
		mime_len  = strnlen (mime, csize - 1);
1246 1247 1248
		pic_type  =  data[pos + 1 + mime_len + 1];
		desc      = &data[pos + 1 + mime_len + 1 + 1];

1249
		if (pic_type == 3 || (pic_type == 0 && filedata->media_art_size == 0)) {
1250 1251
			offset = pos + 1 + mime_len + 2;
			offset += id3v2_strlen (text_type, desc, csize - offset) + id3v2_nul_size (text_type);
1252

1253 1254 1255 1256
			filedata->media_art_data = g_malloc0 (csize - offset);
			filedata->media_art_mime = g_strndup (mime, mime_len);
			memcpy (filedata->media_art_data, &data[offset], csize - offset);
			filedata->media_art_size = csize - offset;
1257
		}
1258 1259
		break;
	}
1260

1261 1262 1263 1264 1265 1266 1267 1268 1269 1270
	case ID3V24_COMM: {
		gchar *word;
		gchar text_encode;
		const gchar *text_desc;
		const gchar *text;
		guint offset;
		gint text_desc_len;

		text_encode   =  data[pos + 0]; /* $xx */
		text_desc     = &data[pos + 4]; /* <text string according to encoding> $00 (00) */
1271
		text_desc_len = id3v2_strlen (text_encode, text_desc, csize - 4);
1272

1273 1274
		offset        = 4 + text_desc_len + id3v2_nul_size (text_encode);
		text          = &data[pos + offset]; /* <full text string according to encoding> */
1275

1276
		word = id3v24_text_to_utf8 (text_encode, text, csize - offset, info);
1277 1278 1279 1280 1281 1282 1283

		if (!tracker_is_empty_string (word)) {
			g_strstrip (word);
			g_free (tag->comment);
			tag->comment = word;
		} else {
			g_free (word);
1284
		}
1285 1286
		break;
	}
1287

1288 1289
	default: {
		gchar *word;
1290

1291
		/* text frames */
1292
		word = id3v24_text_to_utf8 (data[pos], &data[pos + 1], csize - 1, info);
1293 1294
		if (!tracker_is_empty_string (word)) {
			g_strstrip (word);
1295 1296
		}

1297
#ifdef FRAME_ENABLE_TRACE
1298
		g_debug ("ID3v2.4: Frame is %d, word is %s", frame, word);
1299
#endif /* FRAME_ENABLE_TRACE */
1300

1301
		switch (frame) {
1302 1303
		case ID3V24_TALB:
			tag->album = word;
1304
			break;
1305 1306
		case ID3V24_TCON: {
			gint genre;
1307

1308 1309 1310 1311 1312 1313
			if (get_genre_number (word, &genre)) {
				g_free (word);
				word = g_strdup (get_genre_name (genre));
			}
			if (word && strcasecmp (word, "unknown") != 0) {
				tag->content_type = word;
1314 1315
			} else {
				g_free (word);
1316
			}
1317
			break;
1318
		}
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371
		case ID3V24_TCOP:
			tag->copyright = word;
			break;
		case ID3V24_TDRC:
			tag->recording_time = tracker_date_guess (word);
			g_free (word);
			break;
		case ID3V24_TDRL:
			tag->release_time = tracker_date_guess (word);
			g_free (word);
			break;
		case ID3V24_TENC:
			tag->encoded_by = word;
			break;
		case ID3V24_TEXT:
			tag->text = word;
			break;
		case ID3V24_TOLY:
			tag->toly = word;
			break;
		case ID3V24_TCOM:
			tag->composer = word;
			break;
		case ID3V24_TIT1:
			tag->title1 = word;
			break;
		case ID3V24_TIT2:
			tag->title2 = word;
			break;
		case ID3V24_TIT3:
			tag->title3 = word;
			break;
		case ID3V24_TLEN:
			tag->length = atoi (word) / 1000;
			g_free (word);
			break;
		case ID3V24_TPE1:
			tag->performer1 = word;
			break;
		case ID3V24_TPE2:
			tag->performer2 = word;
			break;
		case ID3V24_TPUB:
			tag->publisher = word;
			break;
		case ID3V24_TRCK: {
			gchar **parts;

			parts = g_strsplit (word, "/", 2);
			if (parts[0]) {
				tag->track_number = atoi (parts[0]);
				if (parts[1]) {
					tag->track_count = atoi (parts[1]);
1372 1373
				}
			}
1374 1375
			g_strfreev (parts);
			g_free (word);
1376

1377
			break;
1378
		}
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
		case ID3V24_TPOS: {
			gchar **parts;

			parts = g_strsplit (word, "/", 2);
			if (parts[0]) {
				tag->set_number = atoi (parts[0]);
				if (parts[1]) {
					tag->set_count = atoi (parts[1]);
				}
			}
			g_strfreev (parts);
			g_free (word);

			break;
		}
1394 1395 1396 1397 1398 1399 1400 1401
		case ID3V24_TYER:
			if (atoi (word) > 0) {
				tag->recording_time = tracker_date_guess (word);
			}
			g_free (word);
			break;
		default:
			g_free (word);
1402
		}
1403
	}
1404 1405 1406 1407
	}
}

static void
1408 1409 1410
get_id3v23_tags (id3v24frame           frame,
                 const gchar          *data,
                 size_t                csize,
1411 1412 1413 1414
                 id3tag               *info,
                 const gchar          *uri,
                 TrackerSparqlBuilder *metadata,
                 MP3Data              *filedata)
1415
{
1416 1417
	id3v2tag *tag = &filedata->id3v23;
	guint pos = 0;
1418

1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
	switch (frame) {
	case ID3V24_APIC: {
		/* embedded image */
		gchar text_type;
		const gchar *mime;
		gchar pic_type;
		const gchar *desc;
		guint offset;
		gint  mime_len;

		text_type =  data[pos + 0];
		mime      = &data[pos + 1];
1431
		mime_len  = strnlen (mime, csize - 1);
1432 1433 1434
		pic_type  =  data[pos + 1 + mime_len + 1];
		desc      = &data[pos + 1 + mime_len + 1 + 1];

1435
		if (pic_type == 3 || (pic_type == 0 && filedata->media_art_size == 0)) {
1436 1437
			offset = pos + 1 + mime_len + 2;
			offset += id3v2_strlen (text_type, desc, csize - offset) + id3v2_nul_size (text_type);
1438

1439 1440 1441 1442
			filedata->media_art_data = g_malloc0 (csize - offset);
			filedata->media_art_mime = g_strndup (mime, mime_len);
			memcpy (filedata->media_art_data, &data[offset], csize - offset);
			filedata->media_art_size = csize - offset;
1443
		}
1444 1445
		break;
	}
1446

1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
	case