tracker-0.16.2/src/tracker-extract/tracker-extract-mp3.c

Location Tool Test ID Function Issue
tracker-extract-mp3.c:646:15 gcc pointer-sign un_unsync pointer targets in assignment differ in signedness
tracker-extract-mp3.c:1311:4 gcc pointer-sign get_id3v24_tags pointer targets in passing argument 2 of 'get_genre_number' differ in signedness
tracker-extract-mp3.c:1503:4 gcc pointer-sign get_id3v23_tags pointer targets in passing argument 2 of 'get_genre_number' differ in signedness
tracker-extract-mp3.c:1654:4 gcc pointer-sign get_id3v20_tags pointer targets in passing argument 2 of 'get_genre_number' differ in signedness
tracker-extract-mp3.c:1826:4 gcc pointer-sign parse_id3v24 pointer targets in passing argument 1 of 'un_unsync' differ in signedness
tracker-extract-mp3.c:1953:4 gcc pointer-sign parse_id3v23 pointer targets in passing argument 1 of 'un_unsync' differ in signedness
tracker-extract-mp3.c:2032:4 gcc pointer-sign parse_id3v20 pointer targets in passing argument 1 of 'un_unsync' differ in signedness
tracker-extract-mp3.c:2130:0 cppcheck uninitvar Uninitialized variable: buffer

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found tracker-extract-mp3.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
   1 /*
   2  * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org>
   3  * Copyright (C) 2008-2009, Nokia <ivan.frade@nokia.com>
   4  *
   5  * This library is free software; you can redistribute it and/or
   6  * 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  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13  * Lesser General Public License for more details.
  14  *
  15  * You should have received a copy of the GNU Lesser General Public
  16  * License along with this library; if not, write to the
  17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  18  * Boston, MA  02110-1301, USA.
  19  */
  20 
  21 #include "config.h"
  22 
  23 #ifndef _GNU_SOURCE
  24 #define _GNU_SOURCE
  25 #endif
  26 
  27 #include <stdio.h>
  28 #include <stdlib.h>
  29 #include <string.h>
  30 #include <unistd.h>
  31 #include <fcntl.h>
  32 #include <sys/types.h>
  33 #include <sys/stat.h>
  34 #include <errno.h>
  35 
  36 #include <glib.h>
  37 #include <glib/gstdio.h>
  38 
  39 #ifndef G_OS_WIN32
  40 #include <sys/mman.h>
  41 #endif /* G_OS_WIN32 */
  42 
  43 #include <libtracker-common/tracker-common.h>
  44 
  45 #include <libtracker-extract/tracker-extract.h>
  46 
  47 #include "tracker-media-art.h"
  48 
  49 #ifdef FRAME_ENABLE_TRACE
  50 #warning Frame traces enabled
  51 #endif /* FRAME_ENABLE_TRACE */
  52 
  53 /* We mmap the beginning of the file and read separately the last 128
  54  * bytes for id3v1 tags. While these are probably cornercases the
  55  * rationale is that we don't want to fault a whole page for the last
  56  * 128 bytes and on the other we don't want to mmap the whole file
  57  * with unlimited size (might need to create private copy in some
  58  * special cases, finding continuous space etc). We now take 5 first
  59  * 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 #define MAX_MP3_SCAN_DEEP 16768
  66 
  67 #define MAX_FRAMES_SCAN   512
  68 #define VBR_THRESHOLD     16
  69 
  70 #define ID3V1_SIZE        128
  71 
  72 typedef struct {
  73 	gchar *title;
  74 	gchar *artist;
  75 	gchar *album;
  76 	gchar *recording_time;
  77 	gchar *comment;
  78 	gchar *genre;
  79 	gchar *encoding;
  80 	gint   track_number;
  81 } id3tag;
  82 
  83 typedef struct {
  84 	gchar *album;
  85 	gchar *comment;
  86 	gchar *content_type;
  87 	gchar *copyright;
  88 	gchar *encoded_by;
  89 	guint32 length;
  90 	gchar *performer1;
  91 	gchar *performer2;
  92 	gchar *composer;
  93 	gchar *publisher;
  94 	gchar *recording_time;
  95 	gchar *release_time;
  96 	gchar *text, *toly;
  97 	gchar *title1;
  98 	gchar *title2;
  99 	gchar *title3;
 100 	gint track_number;
 101 	gint track_count;
 102 	gint set_number;
 103 	gint set_count;
 104 } id3v2tag;
 105 
 106 typedef enum {
 107 	ID3V2_UNKNOWN,
 108 	ID3V2_COM,
 109 	ID3V2_PIC,
 110 	ID3V2_TAL,
 111 	ID3V2_TCO,
 112 	ID3V2_TCR,
 113 	ID3V2_TEN,
 114 	ID3V2_TLE,
 115 	ID3V2_TPB,
 116 	ID3V2_TP1,
 117 	ID3V2_TP2,
 118 	ID3V2_TRK,
 119 	ID3V2_TT1,
 120 	ID3V2_TT2,
 121 	ID3V2_TT3,
 122 	ID3V2_TXT,
 123 	ID3V2_TYE,
 124 } id3v2frame;
 125 
 126 typedef enum {
 127 	ID3V24_UNKNOWN,
 128 	ID3V24_APIC,
 129 	ID3V24_COMM,
 130 	ID3V24_TALB,
 131 	ID3V24_TCOM,
 132 	ID3V24_TCON,
 133 	ID3V24_TCOP,
 134 	ID3V24_TDRC,
 135 	ID3V24_TDRL,
 136 	ID3V24_TENC,
 137 	ID3V24_TEXT,
 138 	ID3V24_TIT1,
 139 	ID3V24_TIT2,
 140 	ID3V24_TIT3,
 141 	ID3V24_TLEN,
 142 	ID3V24_TOLY,
 143 	ID3V24_TPE1,
 144 	ID3V24_TPE2,
 145 	ID3V24_TPUB,
 146 	ID3V24_TRCK,
 147 	ID3V24_TPOS,
 148 	ID3V24_TYER,
 149 } id3v24frame;
 150 
 151 typedef struct {
 152 	size_t size;
 153 	size_t id3v2_size;
 154 
 155 	const gchar *title;
 156 	const gchar *performer;
 157 	gchar *performer_uri;
 158 	const gchar *lyricist;
 159 	gchar *lyricist_uri;
 160 	const gchar *album;
 161 	gchar *album_uri;
 162 	const gchar *genre;
 163 	const gchar *text;
 164 	const gchar *recording_time;
 165 	const gchar *encoded_by;
 166 	const gchar *copyright;
 167 	const gchar *publisher;
 168 	const gchar *comment;
 169 	const gchar *composer;
 170 	gchar *composer_uri;
 171 	gint track_number;
 172 	gint track_count;
 173 	gint set_number;
 174 	gint set_count;
 175 
 176 	unsigned char *media_art_data;
 177 	size_t media_art_size;
 178 	gchar *media_art_mime;
 179 
 180 	id3tag id3v1;
 181 	id3v2tag id3v22;
 182 	id3v2tag id3v23;
 183 	id3v2tag id3v24;
 184 } MP3Data;
 185 
 186 enum {
 187 	MPEG_ERR,
 188 	MPEG_V1,
 189 	MPEG_V2,
 190 	MPEG_V25
 191 };
 192 
 193 enum {
 194 	LAYER_ERR,
 195 	LAYER_1,
 196 	LAYER_2,
 197 	LAYER_3
 198 };
 199 
 200 /* sorted array */
 201 static const struct {
 202 	const char *name;
 203 	id3v24frame frame;
 204 } id3v24_frames[] = {
 205 	{ "APIC", ID3V24_APIC },
 206 	{ "COMM", ID3V24_COMM },
 207 	{ "TALB", ID3V24_TALB },
 208 	{ "TCOM", ID3V24_TCOM },
 209 	{ "TCON", ID3V24_TCON },
 210 	{ "TCOP", ID3V24_TCOP },
 211 	{ "TDRC", ID3V24_TDRC },
 212 	{ "TDRL", ID3V24_TDRL },
 213 	{ "TENC", ID3V24_TENC },
 214 	{ "TEXT", ID3V24_TEXT },
 215 	{ "TIT1", ID3V24_TIT1 },
 216 	{ "TIT2", ID3V24_TIT2 },
 217 	{ "TIT3", ID3V24_TIT3 },
 218 	{ "TLEN", ID3V24_TLEN },
 219 	{ "TOLY", ID3V24_TOLY },
 220 	{ "TPE1", ID3V24_TPE1 },
 221 	{ "TPE2", ID3V24_TPE2 },
 222 	{ "TPOS", ID3V24_TPOS },
 223 	{ "TPUB", ID3V24_TPUB },
 224 	{ "TRCK", ID3V24_TRCK },
 225 	{ "TYER", ID3V24_TYER },
 226 };
 227 
 228 /* sorted array */
 229 static const struct {
 230 	const char *name;
 231 	id3v2frame frame;
 232 } id3v2_frames[] = {
 233 	{ "COM", ID3V2_COM },
 234 	{ "PIC", ID3V2_PIC },
 235 	{ "TAL", ID3V2_TAL },
 236 	{ "TCO", ID3V2_TCO },
 237 	{ "TCR", ID3V2_TCR },
 238 	{ "TEN", ID3V2_TEN },
 239 	{ "TLE", ID3V2_TLE },
 240 	{ "TP1", ID3V2_TP1 },
 241 	{ "TP2", ID3V2_TP2 },
 242 	{ "TPB", ID3V2_TPB },
 243 	{ "TRK", ID3V2_TRK },
 244 	{ "TT1", ID3V2_TT1 },
 245 	{ "TT2", ID3V2_TT2 },
 246 	{ "TT3", ID3V2_TT3 },
 247 	{ "TXT", ID3V2_TXT },
 248 	{ "TYE", ID3V2_TYE },
 249 };
 250 
 251 static const char *const genre_names[] = {
 252 	"Blues",
 253 	"Classic Rock",
 254 	"Country",
 255 	"Dance",
 256 	"Disco",
 257 	"Funk",
 258 	"Grunge",
 259 	"Hip-Hop",
 260 	"Jazz",
 261 	"Metal",
 262 	"New Age",
 263 	"Oldies",
 264 	"Other",
 265 	"Pop",
 266 	"R&B",
 267 	"Rap",
 268 	"Reggae",
 269 	"Rock",
 270 	"Techno",
 271 	"Industrial",
 272 	"Alternative",
 273 	"Ska",
 274 	"Death Metal",
 275 	"Pranks",
 276 	"Soundtrack",
 277 	"Euro-Techno",
 278 	"Ambient",
 279 	"Trip-Hop",
 280 	"Vocal",
 281 	"Jazz+Funk",
 282 	"Fusion",
 283 	"Trance",
 284 	"Classical",
 285 	"Instrumental",
 286 	"Acid",
 287 	"House",
 288 	"Game",
 289 	"Sound Clip",
 290 	"Gospel",
 291 	"Noise",
 292 	"Alt. Rock",
 293 	"Bass",
 294 	"Soul",
 295 	"Punk",
 296 	"Space",
 297 	"Meditative",
 298 	"Instrumental Pop",
 299 	"Instrumental Rock",
 300 	"Ethnic",
 301 	"Gothic",
 302 	"Darkwave",
 303 	"Techno-Industrial",
 304 	"Electronic",
 305 	"Pop-Folk",
 306 	"Eurodance",
 307 	"Dream",
 308 	"Southern Rock",
 309 	"Comedy",
 310 	"Cult",
 311 	"Gangsta Rap",
 312 	"Top 40",
 313 	"Christian Rap",
 314 	"Pop/Funk",
 315 	"Jungle",
 316 	"Native American",
 317 	"Cabaret",
 318 	"New Wave",
 319 	"Psychedelic",
 320 	"Rave",
 321 	"Showtunes",
 322 	"Trailer",
 323 	"Lo-Fi",
 324 	"Tribal",
 325 	"Acid Punk",
 326 	"Acid Jazz",
 327 	"Polka",
 328 	"Retro",
 329 	"Musical",
 330 	"Rock & Roll",
 331 	"Hard Rock",
 332 	"Folk",
 333 	"Folk/Rock",
 334 	"National Folk",
 335 	"Swing",
 336 	"Fast-Fusion",
 337 	"Bebob",
 338 	"Latin",
 339 	"Revival",
 340 	"Celtic",
 341 	"Bluegrass",
 342 	"Avantgarde",
 343 	"Gothic Rock",
 344 	"Progressive Rock",
 345 	"Psychedelic Rock",
 346 	"Symphonic Rock",
 347 	"Slow Rock",
 348 	"Big Band",
 349 	"Chorus",
 350 	"Easy Listening",
 351 	"Acoustic",
 352 	"Humour",
 353 	"Speech",
 354 	"Chanson",
 355 	"Opera",
 356 	"Chamber Music",
 357 	"Sonata",
 358 	"Symphony",
 359 	"Booty Bass",
 360 	"Primus",
 361 	"Porn Groove",
 362 	"Satire",
 363 	"Slow Jam",
 364 	"Club",
 365 	"Tango",
 366 	"Samba",
 367 	"Folklore",
 368 	"Ballad",
 369 	"Power Ballad",
 370 	"Rhythmic Soul",
 371 	"Freestyle",
 372 	"Duet",
 373 	"Punk Rock",
 374 	"Drum Solo",
 375 	"A Cappella",
 376 	"Euro-House",
 377 	"Dance Hall",
 378 	"Goa",
 379 	"Drum & Bass",
 380 	"Club-House",
 381 	"Hardcore",
 382 	"Terror",
 383 	"Indie",
 384 	"BritPop",
 385 	"Negerpunk",
 386 	"Polsk Punk",
 387 	"Beat",
 388 	"Christian Gangsta Rap",
 389 	"Heavy Metal",
 390 	"Black Metal",
 391 	"Crossover",
 392 	"Contemporary Christian",
 393 	"Christian Rock",
 394 	"Merengue",
 395 	"Salsa",
 396 	"Thrash Metal",
 397 	"Anime",
 398 	"JPop",
 399 	"Synthpop"
 400 };
 401 
 402 static const guint sync_mask = 0xE0FF;
 403 static const guint mpeg_ver_mask = 0x1800;
 404 static const guint mpeg_layer_mask = 0x600;
 405 static const guint bitrate_mask = 0xF00000;
 406 static const guint freq_mask = 0xC0000;
 407 static const guint ch_mask = 0xC0000000;
 408 static const guint pad_mask = 0x20000;
 409 
 410 static gint bitrate_table[16][6] = {
 411 	{   0,   0,   0,   0,   0,   0 },
 412 	{  32,  32,  32,  32,   8,   8 },
 413 	{  64,  48,  40,  48,  16,  16 },
 414 	{  96,  56,  48,  56,  24,  24 },
 415 	{ 128,  64,  56,  64,  32,  32 },
 416 	{ 160,  80,  64,  80,  40,  40 },
 417 	{ 192,  96,  80,  96,  48,  48 },
 418 	{ 224, 112,  96, 112,  56,  56 },
 419 	{ 256, 128, 112, 128,  64,  64 },
 420 	{ 288, 160, 128, 144,  80,  80 },
 421 	{ 320, 192, 160, 160,  96,  96 },
 422 	{ 352, 224, 192, 176, 112, 112 },
 423 	{ 384, 256, 224, 192, 128, 128 },
 424 	{ 416, 320, 256, 224, 144, 144 },
 425 	{ 448, 384, 320, 256, 160, 160 },
 426 	{  -1,  -1,  -1,  -1,  -1,  -1 }
 427 };
 428 
 429 static gint freq_table[4][3] = {
 430 	{ 44100, 22050, 11025 },
 431 	{ 48000, 24000, 12000 },
 432 	{ 32000, 16000,  8000 },
 433 	{    -1,     -1,   -1 }
 434 };
 435 
 436 static gint spf_table[6] = {
 437 	48, 144, 144, 48, 144,  72
 438 };
 439 
 440 static void
 441 id3tag_free (id3tag *tags)
 442 {
 443 	g_free (tags->title);
 444 	g_free (tags->artist);
 445 	g_free (tags->album);
 446 	g_free (tags->recording_time);
 447 	g_free (tags->comment);
 448 	g_free (tags->genre);
 449 	g_free (tags->encoding);
 450 }
 451 
 452 static void
 453 id3v2tag_free (id3v2tag *tags)
 454 {
 455 	g_free (tags->album);
 456 	g_free (tags->comment);
 457 	g_free (tags->content_type);
 458 	g_free (tags->copyright);
 459 	g_free (tags->performer1);
 460 	g_free (tags->performer2);
 461 	g_free (tags->composer);
 462 	g_free (tags->publisher);
 463 	g_free (tags->recording_time);
 464 	g_free (tags->release_time);
 465 	g_free (tags->encoded_by);
 466 	g_free (tags->text);
 467 	g_free (tags->toly);
 468 	g_free (tags->title1);
 469 	g_free (tags->title2);
 470 	g_free (tags->title3);
 471 }
 472 
 473 static gboolean
 474 guess_dlna_profile (gint          bitrate,
 475                     gint          frequency,
 476                     gint          mpeg_version,
 477                     gint          layer_version,
 478                     gint          n_channels,
 479                     const gchar **dlna_profile,
 480                     const gchar **dlna_mimetype)
 481 {
 482 	if (mpeg_version == MPEG_V1 &&
 483 	    layer_version == LAYER_3 &&
 484 	    (bitrate >= 32000 && bitrate <= 320000) &&
 485 	    (n_channels == 1 || n_channels == 2) &&
 486 	    (frequency == freq_table[0][0] ||
 487 	     frequency == freq_table[1][0] ||
 488 	     frequency == freq_table[2][0])) {
 489 		*dlna_profile = "MP3";
 490 		*dlna_mimetype = "audio/mpeg";
 491 		return TRUE;
 492 	}
 493 
 494 	if ((bitrate >= 8000 && bitrate <= 320000) &&
 495 	    (mpeg_version == MPEG_V1 || mpeg_version == MPEG_V2) &&
 496 	    (frequency == freq_table[0][0] || frequency == freq_table[0][1] ||
 497 	     frequency == freq_table[1][0] || frequency == freq_table[1][1] ||
 498 	     frequency == freq_table[2][0] || frequency == freq_table[2][1])) {
 499 		*dlna_profile = "MP3X";
 500 		*dlna_mimetype = "audio/mpeg";
 501 		return TRUE;
 502 	}
 503 
 504 	return FALSE;
 505 }
 506 
 507 static char *
 508 read_id3v1_buffer (int     fd,
 509                    goffset size)
 510 {
 511 	char *buffer;
 512 	guint bytes_read;
 513 	guint rc;
 514 
 515 	if (size < 128) {
 516 		return NULL;
 517 	}
 518 
 519 	if (lseek (fd, size - ID3V1_SIZE, SEEK_SET) < 0) {
 520 		return NULL;
 521 	}
 522 
 523 	buffer = g_malloc (ID3V1_SIZE);
 524 
 525 	if (!buffer) {
 526 		return NULL;
 527 	}
 528 
 529 	bytes_read = 0;
 530 
 531 	while (bytes_read < ID3V1_SIZE) {
 532 		rc = read (fd,
 533 		           buffer + bytes_read,
 534 		           ID3V1_SIZE - bytes_read);
 535 		if (rc == -1) {
 536 			if (errno != EINTR) {
 537 				g_free (buffer);
 538 				return NULL;
 539 			}
 540 		} else if (rc == 0) {
 541 			break;
 542 		} else {
 543 			bytes_read += rc;
 544 		}
 545 	}
 546 
 547 	return buffer;
 548 }
 549 
 550 /* Convert from UCS-2 to UTF-8 checking the BOM.*/
 551 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 	case 0xfeff:
 563 	case 0xfffe:
 564 		be = (G_BYTE_ORDER == G_BIG_ENDIAN);
 565 		be = (c == 0xfeff) ? be : !be;
 566 		encoding = be ? "UCS-2BE" : "UCS-2LE";
 567 		data += 2;
 568 		len -= 2;
 569 		break;
 570 	default:
 571 		encoding = "UCS-2";
 572 		break;
 573 	}
 574 
 575 	utf8 = g_convert (data, len, "UTF-8", encoding, NULL, NULL, NULL);
 576 
 577 	return utf8;
 578 }
 579 
 580 /* Get the genre codes from regular expressions */
 581 static gboolean
 582 get_genre_number (const char *str, guint *genre)
 583 {
 584 	static GRegex *regex1 = NULL;
 585 	static GRegex *regex2 = NULL;
 586 	GMatchInfo *info = NULL;
 587 	gchar *result = NULL;
 588 
 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 	if (g_regex_match (regex1, str, 0, &info)) {
 598 		result = g_match_info_fetch (info, 1);
 599 		if (result) {
 600 			*genre = atoi (result);
 601 			g_free (result);
 602 			g_match_info_free (info);
 603 			return TRUE;
 604 		}
 605 	}
 606 
 607 	g_match_info_free (info);
 608 
 609 	if (g_regex_match (regex2, str, 0, &info)) {
 610 		result = g_match_info_fetch (info, 1);
 611 		if (result) {
 612 			*genre = atoi (result);
 613 			g_free (result);
 614 			g_match_info_free (info);
 615 			return TRUE;
 616 		}
 617 	}
 618 
 619 	g_match_info_free (info);
 620 
 621 	return FALSE;
 622 }
 623 
 624 static const gchar *
 625 get_genre_name (guint number)
 626 {
 627 	if (number >= G_N_ELEMENTS (genre_names)) {
 628 		return NULL;
 629 	}
 630 
 631 	return genre_names[number];
 632 }
 633 
 634 static void
 635 un_unsync (const unsigned char *source,
 636            size_t               size,
 637            unsigned char      **destination,
 638            size_t              *dest_size)
 639 {
 640 	size_t offset;
 641 	gchar *dest;
 642 	size_t new_size;
 643 
 644 	offset       = 0;
 645 	*destination = g_malloc0 (size);
 646 	dest         = *destination;
pointer targets in assignment differ in signedness
(emitted by gcc)
647 new_size = size; 648 649 while (offset < size) { 650 *dest = source[offset]; 651 652 if ((source[offset] == 0xFF) && 653 (source[offset + 1] == 0x00)) { 654 offset++; 655 new_size--; 656 } 657 dest++; 658 offset++; 659 } 660 661 *dest_size = new_size; 662 } 663 664 static gchar * 665 get_encoding (const gchar *data, 666 gsize size, 667 gboolean *encoding_found) 668 { 669 gchar *encoding; 670 671 /* Try to guess encoding */ 672 encoding = (data && size ? 673 tracker_encoding_guess (data, size) : 674 NULL); 675 676 /* Notify if a proper detection was done */ 677 if (encoding_found) { 678 *encoding_found = (encoding ? TRUE : FALSE);; 679 } 680 681 /* If no proper detection was done, return default */ 682 if (!encoding) { 683 /* Use Windows-1252 instead of ISO-8859-1 as the former is a 684 superset in terms of printable characters and some 685 applications use it to encode characters in ID3 tags */ 686 encoding = g_strdup ("Windows-1252"); 687 } 688 689 return encoding; 690 } 691 692 static gchar * 693 convert_to_encoding (const gchar *str, 694 gssize len, 695 const gchar *to_codeset, 696 const gchar *from_codeset, 697 gsize *bytes_read, 698 gsize *bytes_written, 699 GError **error_out) 700 { 701 GError *error = NULL; 702 gchar *word; 703 704 /* g_print ("%s for %s\n", from_codeset, str); */ 705 706 word = g_convert (str, 707 len, 708 to_codeset, 709 from_codeset, 710 bytes_read, 711 bytes_written, 712 &error); 713 714 if (error) { 715 gchar *encoding; 716 717 encoding = get_encoding (str, len, NULL); 718 g_free (word); 719 720 word = g_convert (str, 721 len, 722 to_codeset, 723 encoding, 724 bytes_read, 725 bytes_written, 726 error_out); 727 728 g_free (encoding); 729 g_error_free (error); 730 } 731 732 return word; 733 } 734 735 static gboolean 736 get_id3 (const gchar *data, 737 size_t size, 738 id3tag *id3) 739 { 740 gchar *encoding, *year; 741 const gchar *pos; 742 743 if (!data) { 744 return FALSE; 745 } 746 747 if (size < 128) { 748 return FALSE; 749 } 750 751 pos = &data[size - 128]; 752 753 if (strncmp ("TAG", pos, 3) != 0) { 754 return FALSE; 755 } 756 757 /* Now convert all the data separately */ 758 pos += 3; 759 760 /* We don't use our magic convert_to_encoding here because we 761 * have a better way to collect a bit more data before we let 762 * enca loose on it for v1. 763 */ 764 if (tracker_encoding_can_guess ()) { 765 GString *s; 766 gboolean encoding_was_found; 767 768 /* Get the encoding for ALL the data we are extracting here */ 769 /* This wont work with encodings where a NUL byte may be actually valid, 770 * like UTF-16 */ 771 s = g_string_new_len (pos, strnlen (pos, 30)); 772 g_string_append_len (s, pos + 30, strnlen (pos+30, 30)); 773 g_string_append_len (s, pos + 60, strnlen (pos+60, 30)); 774 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 if (encoding_was_found) { 779 id3->encoding = g_strdup (encoding); 780 } 781 782 g_string_free (s, TRUE); 783 } else { 784 /* If we cannot guess encoding, don't even try it, just 785 * use the default one */ 786 encoding = get_encoding (NULL, 0, NULL); 787 } 788 789 id3->title = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL); 790 791 pos += 30; 792 id3->artist = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL); 793 794 pos += 30; 795 id3->album = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL); 796 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 if (pos[28] != 0) { 807 id3->comment = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL); 808 id3->track_number = 0; 809 } else { 810 gchar buf[5]; 811 812 id3->comment = g_convert (pos, 28, "UTF-8", encoding, NULL, NULL, NULL); 813 814 snprintf (buf, 5, "%d", pos[29]); 815 id3->track_number = atoi (buf); 816 } 817 818 pos += 30; 819 id3->genre = g_strdup (get_genre_name ((guint) pos[0])); 820 821 if (!id3->genre) { 822 id3->genre = g_strdup (""); 823 } 824 825 g_free (encoding); 826 827 return TRUE; 828 } 829 830 /* 831 * For the MP3 frame header description, see 832 * http://www.mp3-tech.org/programmer/frame_header.html 833 */ 834 static gboolean 835 mp3_parse_header (const gchar *data, 836 size_t size, 837 size_t seek_pos, 838 const gchar *uri, 839 TrackerSparqlBuilder *metadata, 840 MP3Data *filedata) 841 { 842 const gchar *dlna_profile, *dlna_mimetype; 843 guint header; 844 gchar mpeg_ver = 0; 845 gchar layer_ver = 0; 846 gint spfp8 = 0; 847 guint padsize = 0; 848 gint idx_num = 0; 849 gint bitrate = 0; 850 guint avg_bps = 0; 851 gint vbr_flag = 0; 852 guint length = 0; 853 gint sample_rate = 0; 854 guint frame_size; 855 guint frames = 0; 856 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 case 0x1000: 865 mpeg_ver = MPEG_V2; 866 break; 867 case 0x1800: 868 mpeg_ver = MPEG_V1; 869 break; 870 case 0: 871 mpeg_ver = MPEG_V25; 872 break; 873 default: 874 /* unknown version */ 875 return FALSE; 876 } 877 878 switch (header & mpeg_layer_mask) { 879 case 0x400: 880 layer_ver = LAYER_2; 881 padsize = 1; 882 break; 883 case 0x200: 884 layer_ver = LAYER_3; 885 padsize = 1; 886 break; 887 case 0x600: 888 layer_ver = LAYER_1; 889 padsize = 4; 890 break; 891 default: 892 /* unknown layer */ 893 return FALSE; 894 } 895 896 if (mpeg_ver < 3) { 897 idx_num = (mpeg_ver - 1) * 3 + layer_ver - 1; 898 } else { 899 idx_num = 2 + layer_ver; 900 } 901 902 spfp8 = spf_table[idx_num]; 903 904 /* We assume mpeg version, layer and channels are constant in frames */ 905 do { 906 frames++; 907 908 bitrate = 1000 * bitrate_table[(header & bitrate_mask) >> 20][idx_num]; 909 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 /* Skip frame headers with frequency index '11' (reserved) */ 919 if (sample_rate <= 0) { 920 frames--; 921 return FALSE; 922 } 923 924 frame_size = spfp8 * bitrate / sample_rate + padsize*((header & pad_mask) >> 17); 925 avg_bps += bitrate / 1000; 926 927 pos += frame_size; 928 929 if (frames > MAX_FRAMES_SCAN) { 930 /* Optimization */ 931 break; 932 } 933 934 if (avg_bps / frames != bitrate / 1000) { 935 vbr_flag = 1; 936 } 937 938 if (pos + sizeof (header) > size) { 939 /* EOF */ 940 break; 941 } 942 943 if ((!vbr_flag) && (frames > VBR_THRESHOLD)) { 944 break; 945 } 946 947 memcpy(&header, &data[pos], sizeof (header)); 948 } while ((header & sync_mask) == sync_mask); 949 950 /* At least 2 frames to check the right position */ 951 if (frames < 2) { 952 /* No valid frames */ 953 return FALSE; 954 } 955 956 tracker_sparql_builder_predicate (metadata, "nfo:codec"); 957 tracker_sparql_builder_object_string (metadata, "MPEG"); 958 959 n_channels = ((header & ch_mask) == ch_mask) ? 1 : 2; 960 961 tracker_sparql_builder_predicate (metadata, "nfo:channels"); 962 tracker_sparql_builder_object_int64 (metadata, n_channels); 963 964 avg_bps /= frames; 965 966 if ((!vbr_flag && frames > VBR_THRESHOLD) || (frames > MAX_FRAMES_SCAN)) { 967 /* If not all frames scanned 968 * Note that bitrate is always > 0, checked before */ 969 length = (filedata->size - filedata->id3v2_size) / (avg_bps ? avg_bps : bitrate) / 125; 970 } else { 971 /* Note that sample_rate is always > 0, checked before */ 972 length = spfp8 * 8 * frames / sample_rate; 973 } 974 975 tracker_sparql_builder_predicate (metadata, "nfo:duration"); 976 tracker_sparql_builder_object_int64 (metadata, length); 977 978 tracker_sparql_builder_predicate (metadata, "nfo:sampleRate"); 979 tracker_sparql_builder_object_int64 (metadata, sample_rate); 980 tracker_sparql_builder_predicate (metadata, "nfo:averageBitrate"); 981 tracker_sparql_builder_object_int64 (metadata, avg_bps*1000); 982 983 if (guess_dlna_profile (bitrate, sample_rate, 984 mpeg_ver, layer_ver, n_channels, 985 &dlna_profile, &dlna_mimetype)) { 986 tracker_sparql_builder_predicate (metadata, "nmm:dlnaProfile"); 987 tracker_sparql_builder_object_string (metadata, dlna_profile); 988 tracker_sparql_builder_predicate (metadata, "nmm:dlnaMime"); 989 tracker_sparql_builder_object_string (metadata, dlna_mimetype); 990 } 991 992 return TRUE; 993 } 994 995 static void 996 mp3_parse (const gchar *data, 997 size_t size, 998 size_t offset, 999 const gchar *uri, 1000 TrackerSparqlBuilder *metadata, 1001 MP3Data *filedata) 1002 { 1003 guint header; 1004 guint counter = 0; 1005 guint pos = offset; 1006 1007 do { 1008 /* Seek for frame start */ 1009 if (pos + sizeof (header) > size) { 1010 return; 1011 } 1012 1013 memcpy (&header, &data[pos], sizeof (header)); 1014 1015 if ((header & sync_mask) == sync_mask) { 1016 /* Found header sync */ 1017 if (mp3_parse_header (data, size, pos, uri, metadata, filedata)) { 1018 return; 1019 } 1020 } 1021 1022 pos++; 1023 counter++; 1024 } while (counter < MAX_MP3_SCAN_DEEP); 1025 } 1026 1027 static gssize 1028 id3v2_nul_size (const gchar encoding) 1029 { 1030 switch (encoding) { 1031 case 0x01: 1032 case 0x02: 1033 /* UTF-16, string terminated by two NUL bytes */ 1034 return 2; 1035 default: 1036 return 1; 1037 } 1038 } 1039 1040 static gssize 1041 id3v2_strlen (const gchar encoding, 1042 const gchar *text, 1043 gssize len) 1044 { 1045 const gchar *pos; 1046 1047 switch (encoding) { 1048 case 0x01: 1049 case 0x02: 1050 1051 /* UTF-16, string terminated by two NUL bytes */ 1052 pos = memmem (text, len, "\0\0\0", 3); 1053 1054 if (pos == NULL) { 1055 pos = memmem (text, len, "\0\0", 2); 1056 } else { 1057 pos++; 1058 } 1059 1060 if (pos != NULL) { 1061 return pos - text; 1062 } else { 1063 return len; 1064 } 1065 default: 1066 return strnlen (text, len); 1067 } 1068 } 1069 1070 static gchar * 1071 id3v24_text_to_utf8 (const gchar encoding, 1072 const gchar *text, 1073 gssize len, 1074 id3tag *info) 1075 { 1076 /* This byte describes the encoding 1077 * try to convert strings to UTF-8 1078 * if it fails, then forget it. 1079 * For UTF-16 if size odd assume invalid 00 term. 1080 */ 1081 1082 switch (encoding) { 1083 case 0x00: 1084 /* Use Windows-1252 instead of ISO-8859-1 as the former is a 1085 superset in terms of printable characters and some 1086 applications use it to encode characters in ID3 tags */ 1087 return convert_to_encoding (text, 1088 len, 1089 "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 "UTF-8", 1096 "UTF-16", 1097 NULL, NULL, NULL); 1098 case 0x02 : 1099 return convert_to_encoding (text, 1100 len - len%2, 1101 "UTF-8", 1102 "UTF-16BE", 1103 NULL, NULL, NULL); 1104 case 0x03 : 1105 return strndup (text, len); 1106 1107 default: 1108 /* Bad encoding byte, 1109 * try to convert from 1110 * Windows-1252 1111 */ 1112 return convert_to_encoding (text, 1113 len, 1114 "UTF-8", 1115 info->encoding ? info->encoding : "Windows-1252", 1116 NULL, NULL, NULL); 1117 } 1118 } 1119 1120 static gchar * 1121 id3v2_text_to_utf8 (const gchar encoding, 1122 const gchar *text, 1123 gssize len, 1124 id3tag *info) 1125 { 1126 /* This byte describes the encoding 1127 * try to convert strings to UTF-8 1128 * if it fails, then forget it 1129 * For UCS2 if size odd assume invalid 00 term. 1130 */ 1131 1132 switch (encoding) { 1133 case 0x00: 1134 /* Use Windows-1252 instead of ISO-8859-1 as the former is a 1135 superset in terms of printable characters and some 1136 applications use it to encode characters in ID3 tags */ 1137 return convert_to_encoding (text, 1138 len, 1139 "UTF-8", 1140 info->encoding ? info->encoding : "Windows-1252", 1141 NULL, NULL, NULL); 1142 case 0x01 : 1143 /* return g_convert (text, */ 1144 /* len, */ 1145 /* "UTF-8", */ 1146 /* "UCS-2", */ 1147 /* NULL, NULL, NULL); */ 1148 return ucs2_to_utf8 (text, len - len%2); 1149 1150 default: 1151 /* Bad encoding byte, 1152 * try to convert from 1153 * Windows-1252 1154 */ 1155 return convert_to_encoding (text, 1156 len, 1157 "UTF-8", 1158 info->encoding ? info->encoding : "Windows-1252", 1159 NULL, NULL, NULL); 1160 } 1161 } 1162 1163 static id3v24frame 1164 id3v24_get_frame (const gchar *name) 1165 { 1166 gint l, r, m; 1167 1168 /* use binary search */ 1169 1170 l = 0; 1171 r = G_N_ELEMENTS (id3v24_frames) - 1; 1172 m = 0; 1173 1174 do { 1175 m = (l + r) / 2; 1176 if (strncmp (name, id3v24_frames[m].name, 4) < 0) { 1177 /* left half */ 1178 r = m - 1; 1179 } else { 1180 /* right half */ 1181 l = m + 1; 1182 } 1183 } while (l <= r && strncmp (id3v24_frames[m].name, name, 4) != 0); 1184 1185 if (strncmp (id3v24_frames[m].name, name, 4) == 0) { 1186 return id3v24_frames[m].frame; 1187 } else { 1188 return ID3V24_UNKNOWN; 1189 } 1190 } 1191 1192 static id3v2frame 1193 id3v2_get_frame (const gchar *name) 1194 { 1195 gint l, r, m; 1196 1197 /* use binary search */ 1198 1199 l = 0; 1200 r = G_N_ELEMENTS (id3v2_frames) - 1; 1201 m = 0; 1202 1203 do { 1204 m = (l + r) / 2; 1205 if (strncmp (name, id3v2_frames[m].name, 3) < 0) { 1206 /* left half */ 1207 r = m - 1; 1208 } else { 1209 /* right half */ 1210 l = m + 1; 1211 } 1212 } while (l <= r && strncmp (id3v2_frames[m].name, name, 3) != 0); 1213 1214 if (strncmp (id3v2_frames[m].name, name, 3) == 0) { 1215 return id3v2_frames[m].frame; 1216 } else { 1217 return ID3V2_UNKNOWN; 1218 } 1219 } 1220 1221 static void 1222 get_id3v24_tags (id3v24frame frame, 1223 const gchar *data, 1224 size_t csize, 1225 id3tag *info, 1226 const gchar *uri, 1227 TrackerSparqlBuilder *metadata, 1228 MP3Data *filedata) 1229 { 1230 id3v2tag *tag = &filedata->id3v24; 1231 guint pos = 0; 1232 1233 switch (frame) { 1234 case ID3V24_APIC: { 1235 /* embedded image */ 1236 gchar text_type; 1237 const gchar *mime; 1238 gchar pic_type; 1239 const gchar *desc; 1240 guint offset; 1241 gint mime_len; 1242 1243 text_type = data[pos + 0]; 1244 mime = &data[pos + 1]; 1245 mime_len = strnlen (mime, csize - 1); 1246 pic_type = data[pos + 1 + mime_len + 1]; 1247 desc = &data[pos + 1 + mime_len + 1 + 1]; 1248 1249 if (pic_type == 3 || (pic_type == 0 && filedata->media_art_size == 0)) { 1250 offset = pos + 1 + mime_len + 2; 1251 offset += id3v2_strlen (text_type, desc, csize - offset) + id3v2_nul_size (text_type); 1252 1253 filedata->media_art_data = g_malloc0 (csize - offset); 1254 filedata->media_art_mime = g_strndup (mime, mime_len); 1255 memcpy (filedata->media_art_data, &data[offset], csize - offset); 1256 filedata->media_art_size = csize - offset; 1257 } 1258 break; 1259 } 1260 1261 case ID3V24_COMM: { 1262 gchar *word; 1263 gchar text_encode; 1264 const gchar *text_desc; 1265 const gchar *text; 1266 guint offset; 1267 gint text_desc_len; 1268 1269 text_encode = data[pos + 0]; /* $xx */ 1270 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 offset = 4 + text_desc_len + id3v2_nul_size (text_encode); 1274 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 if (!tracker_is_empty_string (word)) { 1279 g_strstrip (word); 1280 g_free (tag->comment); 1281 tag->comment = word; 1282 } else { 1283 g_free (word); 1284 } 1285 break; 1286 } 1287 1288 default: { 1289 gchar *word; 1290 1291 /* text frames */ 1292 word = id3v24_text_to_utf8 (data[pos], &data[pos + 1], csize - 1, info); 1293 if (!tracker_is_empty_string (word)) { 1294 g_strstrip (word); 1295 } else { 1296 /* Can't do anything without word. */ 1297 break; 1298 } 1299 1300 #ifdef FRAME_ENABLE_TRACE 1301 g_debug ("ID3v2.4: Frame is %d, word is %s", frame, word); 1302 #endif /* FRAME_ENABLE_TRACE */ 1303 1304 switch (frame) { 1305 case ID3V24_TALB: 1306 tag->album = word; 1307 break; 1308 case ID3V24_TCON: { 1309 gint genre; 1310 1311 if (get_genre_number (word, &genre)) {
pointer targets in passing argument 2 of 'get_genre_number' differ in signedness
(emitted by gcc)
1312 g_free (word); 1313 word = g_strdup (get_genre_name (genre)); 1314 } 1315 if (word && strcasecmp (word, "unknown") != 0) { 1316 tag->content_type = word; 1317 } else { 1318 g_free (word); 1319 } 1320 break; 1321 } 1322 case ID3V24_TCOP: 1323 tag->copyright = word; 1324 break; 1325 case ID3V24_TDRC: 1326 tag->recording_time = tracker_date_guess (word); 1327 g_free (word); 1328 break; 1329 case ID3V24_TDRL: 1330 tag->release_time = tracker_date_guess (word); 1331 g_free (word); 1332 break; 1333 case ID3V24_TENC: 1334 tag->encoded_by = word; 1335 break; 1336 case ID3V24_TEXT: 1337 tag->text = word; 1338 break; 1339 case ID3V24_TOLY: 1340 tag->toly = word; 1341 break; 1342 case ID3V24_TCOM: 1343 tag->composer = word; 1344 break; 1345 case ID3V24_TIT1: 1346 tag->title1 = word; 1347 break; 1348 case ID3V24_TIT2: 1349 tag->title2 = word; 1350 break; 1351 case ID3V24_TIT3: 1352 tag->title3 = word; 1353 break; 1354 case ID3V24_TLEN: 1355 tag->length = atoi (word) / 1000; 1356 g_free (word); 1357 break; 1358 case ID3V24_TPE1: 1359 tag->performer1 = word; 1360 break; 1361 case ID3V24_TPE2: 1362 tag->performer2 = word; 1363 break; 1364 case ID3V24_TPUB: 1365 tag->publisher = word; 1366 break; 1367 case ID3V24_TRCK: { 1368 gchar **parts; 1369 1370 parts = g_strsplit (word, "/", 2); 1371 if (parts[0]) { 1372 tag->track_number = atoi (parts[0]); 1373 if (parts[1]) { 1374 tag->track_count = atoi (parts[1]); 1375 } 1376 } 1377 g_strfreev (parts); 1378 g_free (word); 1379 1380 break; 1381 } 1382 case ID3V24_TPOS: { 1383 gchar **parts; 1384 1385 parts = g_strsplit (word, "/", 2); 1386 if (parts[0]) { 1387 tag->set_number = atoi (parts[0]); 1388 if (parts[1]) { 1389 tag->set_count = atoi (parts[1]); 1390 } 1391 } 1392 g_strfreev (parts); 1393 g_free (word); 1394 1395 break; 1396 } 1397 case ID3V24_TYER: 1398 if (atoi (word) > 0) { 1399 tag->recording_time = tracker_date_guess (word); 1400 } 1401 g_free (word); 1402 break; 1403 default: 1404 g_free (word); 1405 } 1406 } 1407 } 1408 } 1409 1410 static void 1411 get_id3v23_tags (id3v24frame frame, 1412 const gchar *data, 1413 size_t csize, 1414 id3tag *info, 1415 const gchar *uri, 1416 TrackerSparqlBuilder *metadata, 1417 MP3Data *filedata) 1418 { 1419 id3v2tag *tag = &filedata->id3v23; 1420 guint pos = 0; 1421 1422 switch (frame) { 1423 case ID3V24_APIC: { 1424 /* embedded image */ 1425 gchar text_type; 1426 const gchar *mime; 1427 gchar pic_type; 1428 const gchar *desc; 1429 guint offset; 1430 gint mime_len; 1431 1432 text_type = data[pos + 0]; 1433 mime = &data[pos + 1]; 1434 mime_len = strnlen (mime, csize - 1); 1435 pic_type = data[pos + 1 + mime_len + 1]; 1436 desc = &data[pos + 1 + mime_len + 1 + 1]; 1437 1438 if (pic_type == 3 || (pic_type == 0 && filedata->media_art_size == 0)) { 1439 offset = pos + 1 + mime_len + 2; 1440 offset += id3v2_strlen (text_type, desc, csize - offset) + id3v2_nul_size (text_type); 1441 1442 filedata->media_art_data = g_malloc0 (csize - offset); 1443 filedata->media_art_mime = g_strndup (mime, mime_len); 1444 memcpy (filedata->media_art_data, &data[offset], csize - offset); 1445 filedata->media_art_size = csize - offset; 1446 } 1447 break; 1448 } 1449 1450 case ID3V24_COMM: { 1451 gchar *word; 1452 gchar text_encode; 1453 const gchar *text_desc; 1454 const gchar *text; 1455 guint offset; 1456 gint text_desc_len; 1457 1458 text_encode = data[pos + 0]; /* $xx */ 1459 text_desc = &data[pos + 4]; /* <text string according to encoding> $00 (00) */ 1460 text_desc_len = id3v2_strlen (text_encode, text_desc, csize - 4); 1461 1462 offset = 4 + text_desc_len + id3v2_nul_size (text_encode); 1463 text = &data[pos + offset]; /* <full text string according to encoding> */ 1464 1465 word = id3v2_text_to_utf8 (text_encode, text, csize - offset, info); 1466 1467 if (!tracker_is_empty_string (word)) { 1468 g_strstrip (word); 1469 g_free (tag->comment); 1470 tag->comment = word; 1471 } else { 1472 g_free (word); 1473 } 1474 1475 break; 1476 } 1477 1478 default: { 1479 gchar *word; 1480 1481 /* text frames */ 1482 word = id3v2_text_to_utf8 (data[pos], &data[pos + 1], csize - 1, info); 1483 1484 if (!tracker_is_empty_string (word)) { 1485 g_strstrip (word); 1486 } else { 1487 /* Can't do anything without word. */ 1488 break; 1489 } 1490 1491 1492 #ifdef FRAME_ENABLE_TRACE 1493 g_debug ("ID3v2.3: Frame is %d, word is %s", frame, word); 1494 #endif /* FRAME_ENABLE_TRACE */ 1495 1496 switch (frame) { 1497 case ID3V24_TALB: 1498 tag->album = word; 1499 break; 1500 case ID3V24_TCON: { 1501 gint genre; 1502 1503 if (get_genre_number (word, &genre)) {
pointer targets in passing argument 2 of 'get_genre_number' differ in signedness
(emitted by gcc)
1504 g_free (word); 1505 word = g_strdup (get_genre_name (genre)); 1506 } 1507 if (word && strcasecmp (word, "unknown") != 0) { 1508 tag->content_type = word; 1509 } else { 1510 g_free (word); 1511 } 1512 break; 1513 } 1514 case ID3V24_TCOP: 1515 tag->copyright = word; 1516 break; 1517 case ID3V24_TENC: 1518 tag->encoded_by = word; 1519 break; 1520 case ID3V24_TEXT: 1521 tag->text = word; 1522 break; 1523 case ID3V24_TOLY: 1524 tag->toly = word; 1525 break; 1526 case ID3V24_TCOM: 1527 tag->composer = word; 1528 break; 1529 case ID3V24_TIT1: 1530 tag->title1 = word; 1531 break; 1532 case ID3V24_TIT2: 1533 tag->title2 = word; 1534 break; 1535 case ID3V24_TIT3: 1536 tag->title3 = word; 1537 break; 1538 case ID3V24_TLEN: 1539 tag->length = atoi (word) / 1000; 1540 g_free (word); 1541 break; 1542 case ID3V24_TPE1: 1543 tag->performer1 = word; 1544 break; 1545 case ID3V24_TPE2: 1546 tag->performer2 = word; 1547 break; 1548 case ID3V24_TPUB: 1549 tag->publisher = word; 1550 break; 1551 case ID3V24_TRCK: { 1552 gchar **parts; 1553 1554 parts = g_strsplit (word, "/", 2); 1555 if (parts[0]) { 1556 tag->track_number = atoi (parts[0]); 1557 if (parts[1]) { 1558 tag->track_count = atoi (parts[1]); 1559 } 1560 } 1561 g_strfreev (parts); 1562 g_free (word); 1563 1564 break; 1565 } 1566 case ID3V24_TPOS: { 1567 gchar **parts; 1568 1569 parts = g_strsplit (word, "/", 2); 1570 if (parts[0]) { 1571 tag->set_number = atoi (parts[0]); 1572 if (parts[1]) { 1573 tag->set_count = atoi (parts[1]); 1574 } 1575 } 1576 g_strfreev (parts); 1577 g_free (word); 1578 1579 break; 1580 } 1581 case ID3V24_TYER: 1582 if (atoi (word) > 0) { 1583 tag->recording_time = tracker_date_guess (word); 1584 } 1585 g_free (word); 1586 break; 1587 default: 1588 g_free (word); 1589 } 1590 } 1591 } 1592 } 1593 1594 static void 1595 get_id3v20_tags (id3v2frame frame, 1596 const gchar *data, 1597 size_t csize, 1598 id3tag *info, 1599 const gchar *uri, 1600 TrackerSparqlBuilder *metadata, 1601 MP3Data *filedata) 1602 { 1603 id3v2tag *tag = &filedata->id3v22; 1604 guint pos = 0; 1605 1606 if (frame == ID3V2_PIC) { 1607 /* embedded image */ 1608 gchar text_type; 1609 gchar pic_type; 1610 const gchar *desc; 1611 guint offset; 1612 const gchar *mime; 1613 1614 text_type = data[pos + 0]; 1615 mime = &data[pos + 1]; 1616 pic_type = data[pos + 1 + 3]; 1617 desc = &data[pos + 1 + 3 + 1]; 1618 1619 if (pic_type == 3 || (pic_type == 0 && filedata->media_art_size == 0)) { 1620 offset = pos + 1 + 3 + 1; 1621 offset += id3v2_strlen (text_type, desc, csize - offset) + id3v2_nul_size (text_type); 1622 1623 filedata->media_art_mime = g_strndup (mime, 3); 1624 filedata->media_art_data = g_malloc0 (csize - offset); 1625 memcpy (filedata->media_art_data, &data[offset], csize - offset); 1626 filedata->media_art_size = csize - offset; 1627 } 1628 } else { 1629 /* text frames */ 1630 gchar *word; 1631 1632 word = id3v2_text_to_utf8 (data[pos], &data[pos + 1], csize - 1, info); 1633 if (!tracker_is_empty_string (word)) { 1634 g_strstrip (word); 1635 } else { 1636 /* Can't do anything without word. */ 1637 return; 1638 } 1639 1640 #ifdef FRAME_ENABLE_TRACE 1641 g_debug ("ID3v2.2: Frame is %d, word is %s", frame, word); 1642 #endif /* FRAME_ENABLE_TRACE */ 1643 1644 switch (frame) { 1645 case ID3V2_COM: 1646 tag->comment = word; 1647 break; 1648 case ID3V2_TAL: 1649 tag->album = word; 1650 break; 1651 case ID3V2_TCO: { 1652 gint genre; 1653 1654 if (get_genre_number (word, &genre)) {
pointer targets in passing argument 2 of 'get_genre_number' differ in signedness
(emitted by gcc)
1655 g_free (word); 1656 word = g_strdup (get_genre_name (genre)); 1657 } 1658 1659 if (word && strcasecmp (word, "unknown") != 0) { 1660 tag->content_type = word; 1661 } else { 1662 g_free (word); 1663 } 1664 1665 break; 1666 } 1667 case ID3V2_TCR: 1668 tag->copyright = word; 1669 break; 1670 case ID3V2_TEN: 1671 tag->encoded_by = word; 1672 break; 1673 case ID3V2_TLE: 1674 tag->length = atoi (word) / 1000; 1675 g_free (word); 1676 break; 1677 case ID3V2_TPB: 1678 tag->publisher = word; 1679 break; 1680 case ID3V2_TP1: 1681 tag->performer1 = word; 1682 break; 1683 case ID3V2_TP2: 1684 tag->performer2 = word; 1685 break; 1686 case ID3V2_TRK: { 1687 gchar **parts; 1688 1689 parts = g_strsplit (word, "/", 2); 1690 if (parts[0]) { 1691 tag->track_number = atoi (parts[0]); 1692 if (parts[1]) { 1693 tag->track_count = atoi (parts[1]); 1694 } 1695 } 1696 g_strfreev (parts); 1697 g_free (word); 1698 1699 break; 1700 } 1701 case ID3V2_TT1: 1702 tag->title1 = word; 1703 break; 1704 case ID3V2_TT2: 1705 tag->title2 = word; 1706 break; 1707 case ID3V2_TT3: 1708 tag->title3 = word; 1709 break; 1710 case ID3V2_TXT: 1711 tag->text = word; 1712 break; 1713 case ID3V2_TYE: 1714 if (atoi (word) > 0) { 1715 tag->recording_time = tracker_date_guess (word); 1716 } 1717 g_free (word); 1718 break; 1719 default: 1720 g_free (word); 1721 } 1722 } 1723 } 1724 1725 static void 1726 parse_id3v24 (const gchar *data, 1727 size_t size, 1728 id3tag *info, 1729 const gchar *uri, 1730 TrackerSparqlBuilder *metadata, 1731 MP3Data *filedata, 1732 size_t *offset_delta) 1733 { 1734 gint unsync; 1735 gint ext_header; 1736 gint experimental; 1737 guint tsize; 1738 guint pos; 1739 guint ext_header_size; 1740 1741 if ((size < 16) || 1742 (data[0] != 0x49) || 1743 (data[1] != 0x44) || 1744 (data[2] != 0x33) || 1745 (data[3] != 0x04) || 1746 (data[4] != 0x00) ) { 1747 return; 1748 } 1749 1750 unsync = (data[5] & 0x80) > 0; 1751 ext_header = (data[5] & 0x40) > 0; 1752 experimental = (data[5] & 0x20) > 0; 1753 tsize = (((data[6] & 0x7F) << 21) | 1754 ((data[7] & 0x7F) << 14) | 1755 ((data[8] & 0x7F) << 7) | 1756 ((data[9] & 0x7F) << 0)); 1757 1758 if ((tsize + 10 > size) || (experimental)) { 1759 return; 1760 } 1761 1762 pos = 10; 1763 1764 if (ext_header) { 1765 ext_header_size = (((data[10] & 0x7F) << 21) | 1766 ((data[11] & 0x7F) << 14) | 1767 ((data[12] & 0x7F) << 7) | 1768 ((data[13] & 0x7F) << 0)); 1769 pos += ext_header_size; 1770 1771 if (pos + tsize > size) { 1772 /* invalid size: extended header longer than tag */ 1773 return; 1774 } 1775 } 1776 1777 while (pos < size) { 1778 id3v24frame frame; 1779 size_t csize; 1780 unsigned short flags; 1781 1782 if (pos + 10 > size) { 1783 return; 1784 } 1785 1786 frame = id3v24_get_frame (&data[pos]); 1787 1788 csize = (((data[pos+4] & 0x7F) << 21) | 1789 ((data[pos+5] & 0x7F) << 14) | 1790 ((data[pos+6] & 0x7F) << 7) | 1791 ((data[pos+7] & 0x7F) << 0)); 1792 1793 flags = (((unsigned char) (data[pos + 8]) << 8) + 1794 ((unsigned char) (data[pos + 9]))); 1795 1796 pos += 10; 1797 1798 if (frame == ID3V24_UNKNOWN) { 1799 /* ignore unknown frames */ 1800 pos += csize; 1801 continue; 1802 } 1803 1804 if (pos + csize > size) { 1805 break; 1806 } else if (csize == 0) { 1807 continue; 1808 } 1809 1810 if (((flags & 0x80) > 0) || 1811 ((flags & 0x40) > 0)) { 1812 pos += csize; 1813 continue; 1814 } 1815 1816 if ((flags & 0x20) > 0) { 1817 /* The "group" identifier, skip a byte */ 1818 pos++; 1819 csize--; 1820 } 1821 1822 if ((flags & 0x02) || unsync) { 1823 size_t unsync_size; 1824 gchar *body; 1825 1826 un_unsync (&data[pos], csize, (unsigned char **) &body, &unsync_size);
pointer targets in passing argument 1 of 'un_unsync' differ in signedness
(emitted by gcc)
1827 get_id3v24_tags (frame, body, unsync_size, info, uri, metadata, filedata); 1828 g_free (body); 1829 } else { 1830 get_id3v24_tags (frame, &data[pos], csize, info, uri, metadata, filedata); 1831 } 1832 1833 pos += csize; 1834 } 1835 1836 *offset_delta = tsize + 10; 1837 } 1838 1839 static void 1840 parse_id3v23 (const gchar *data, 1841 size_t size, 1842 id3tag *info, 1843 const gchar *uri, 1844 TrackerSparqlBuilder *metadata, 1845 MP3Data *filedata, 1846 size_t *offset_delta) 1847 { 1848 gint unsync; 1849 gint ext_header; 1850 gint experimental; 1851 guint tsize; 1852 guint pos; 1853 guint ext_header_size; 1854 guint padding; 1855 1856 if ((size < 16) || 1857 (data[0] != 0x49) || 1858 (data[1] != 0x44) || 1859 (data[2] != 0x33) || 1860 (data[3] != 0x03) || 1861 (data[4] != 0x00)) { 1862 return; 1863 } 1864 1865 unsync = (data[5] & 0x80) > 0; 1866 ext_header = (data[5] & 0x40) > 0; 1867 experimental = (data[5] & 0x20) > 0; 1868 tsize = (((data[6] & 0x7F) << 21) | 1869 ((data[7] & 0x7F) << 14) | 1870 ((data[8] & 0x7F) << 7) | 1871 ((data[9] & 0x7F) << 0)); 1872 1873 if ((tsize + 10 > size) || (experimental)) { 1874 return; 1875 } 1876 1877 pos = 10; 1878 padding = 0; 1879 1880 if (ext_header) { 1881 ext_header_size = (((unsigned char)(data[10]) << 24) | 1882 ((unsigned char)(data[11]) << 16) | 1883 ((unsigned char)(data[12]) << 8) | 1884 ((unsigned char)(data[12]) << 0)); 1885 1886 padding = (((unsigned char)(data[15]) << 24) | 1887 ((unsigned char)(data[16]) << 16) | 1888 ((unsigned char)(data[17]) << 8) | 1889 ((unsigned char)(data[18]) << 0)); 1890 1891 pos += 4 + ext_header_size; 1892 1893 if (padding < tsize) 1894 tsize -= padding; 1895 else { 1896 return; 1897 } 1898 1899 if (pos + tsize > size) { 1900 /* invalid size: extended header longer than tag */ 1901 return; 1902 } 1903 } 1904 1905 while (pos < size) { 1906 id3v24frame frame; 1907 size_t csize; 1908 unsigned short flags; 1909 1910 if (pos + 10 > size) { 1911 return; 1912 } 1913 1914 frame = id3v24_get_frame (&data[pos]); 1915 1916 csize = (((unsigned char)(data[pos + 4]) << 24) | 1917 ((unsigned char)(data[pos + 5]) << 16) | 1918 ((unsigned char)(data[pos + 6]) << 8) | 1919 ((unsigned char)(data[pos + 7]) << 0) ); 1920 1921 flags = (((unsigned char)(data[pos + 8]) << 8) + 1922 ((unsigned char)(data[pos + 9]))); 1923 1924 pos += 10; 1925 1926 if (frame == ID3V24_UNKNOWN) { 1927 /* ignore unknown frames */ 1928 pos += csize; 1929 continue; 1930 } 1931 1932 if (pos + csize > size) { 1933 break; 1934 } else if (csize == 0) { 1935 continue; 1936 } 1937 1938 if (((flags & 0x80) > 0) || ((flags & 0x40) > 0)) { 1939 pos += csize; 1940 continue; 1941 } 1942 1943 if ((flags & 0x20) > 0) { 1944 /* The "group" identifier, skip a byte */ 1945 pos++; 1946 csize--; 1947 } 1948 1949 if ((flags & 0x02) || unsync) { 1950 size_t unsync_size; 1951 gchar *body; 1952 1953 un_unsync (&data[pos], csize, (unsigned char **) &body, &unsync_size);
pointer targets in passing argument 1 of 'un_unsync' differ in signedness
(emitted by gcc)
1954 get_id3v23_tags (frame, body, unsync_size, info, uri, metadata, filedata); 1955 g_free (body); 1956 } else { 1957 get_id3v23_tags (frame, &data[pos], csize, info, uri, metadata, filedata); 1958 } 1959 1960 pos += csize; 1961 } 1962 1963 *offset_delta = tsize + 10; 1964 } 1965 1966 static void 1967 parse_id3v20 (const gchar *data, 1968 size_t size, 1969 id3tag *info, 1970 const gchar *uri, 1971 TrackerSparqlBuilder *metadata, 1972 MP3Data *filedata, 1973 size_t *offset_delta) 1974 { 1975 gint unsync; 1976 guint tsize; 1977 guint pos; 1978 1979 if ((size < 16) || 1980 (data[0] != 0x49) || 1981 (data[1] != 0x44) || 1982 (data[2] != 0x33) || 1983 (data[3] != 0x02) || 1984 (data[4] != 0x00)) { 1985 return; 1986 } 1987 1988 unsync = (data[5] & 0x80) > 0; 1989 tsize = (((data[6] & 0x7F) << 21) | 1990 ((data[7] & 0x7F) << 14) | 1991 ((data[8] & 0x7F) << 07) | 1992 ((data[9] & 0x7F) << 00)); 1993 1994 if (tsize + 10 > size) { 1995 return; 1996 } 1997 pos = 10; 1998 1999 while (pos < size) { 2000 id3v2frame frame; 2001 size_t csize; 2002 2003 if (pos + 6 > size) { 2004 return; 2005 } 2006 2007 frame = id3v2_get_frame (&data[pos]); 2008 2009 csize = (((unsigned char)(data[pos + 3]) << 16) + 2010 ((unsigned char)(data[pos + 4]) << 8) + 2011 ((unsigned char)(data[pos + 5]) ) ); 2012 2013 pos += 6; 2014 2015 if (frame == ID3V2_UNKNOWN) { 2016 /* ignore unknown frames */ 2017 pos += csize; 2018 continue; 2019 } 2020 2021 if (pos + csize > size) { 2022 break; 2023 } else if (csize == 0) { 2024 continue; 2025 } 2026 2027 /* Early versions do not have unsynch per frame */ 2028 if (unsync) { 2029 size_t unsync_size; 2030 gchar *body; 2031 2032 un_unsync (&data[pos], csize, (unsigned char **) &body, &unsync_size);
pointer targets in passing argument 1 of 'un_unsync' differ in signedness
(emitted by gcc)
2033 get_id3v20_tags (frame, body, unsync_size, info, uri, metadata, filedata); 2034 g_free (body); 2035 } else { 2036 get_id3v20_tags (frame, &data[pos], csize, info, uri, metadata, filedata); 2037 } 2038 2039 pos += csize; 2040 } 2041 2042 *offset_delta = tsize + 10; 2043 } 2044 2045 static goffset 2046 parse_id3v2 (const gchar *data, 2047 size_t size, 2048 id3tag *info, 2049 const gchar *uri, 2050 TrackerSparqlBuilder *metadata, 2051 MP3Data *filedata) 2052 { 2053 gboolean done = FALSE; 2054 size_t offset = 0; 2055 2056 do { 2057 size_t offset_delta = 0; 2058 parse_id3v24 (data + offset, size - offset, info, uri, metadata, filedata, &offset_delta); 2059 parse_id3v23 (data + offset, size - offset, info, uri, metadata, filedata, &offset_delta); 2060 parse_id3v20 (data + offset, size - offset, info, uri, metadata, filedata, &offset_delta); 2061 2062 if (offset_delta == 0) { 2063 done = TRUE; 2064 filedata->id3v2_size = offset; 2065 } else { 2066 offset += offset_delta; 2067 } 2068 2069 } while (!done); 2070 2071 return offset; 2072 } 2073 2074 G_MODULE_EXPORT gboolean 2075 tracker_extract_get_metadata (TrackerExtractInfo *info) 2076 { 2077 gchar *filename, *uri; 2078 int fd; 2079 void *buffer; 2080 void *id3v1_buffer; 2081 goffset size; 2082 goffset buffer_size; 2083 goffset audio_offset; 2084 MP3Data md = { 0 }; 2085 TrackerSparqlBuilder *metadata, *preupdate; 2086 GFile *file; 2087 const gchar *graph; 2088 2089 graph = tracker_extract_info_get_graph (info); 2090 metadata = tracker_extract_info_get_metadata_builder (info); 2091 preupdate = tracker_extract_info_get_preupdate_builder (info); 2092 2093 file = tracker_extract_info_get_file (info); 2094 filename = g_file_get_path (file); 2095 2096 size = tracker_file_get_size (filename); 2097 2098 if (size == 0) { 2099 g_free (filename); 2100 return FALSE; 2101 } 2102 2103 md.size = size; 2104 buffer_size = MIN (size, MAX_FILE_READ); 2105 2106 fd = tracker_file_open_fd (filename); 2107 2108 if (fd == -1) { 2109 return FALSE; 2110 } 2111 2112 #ifndef G_OS_WIN32 2113 /* We don't use GLib's mmap because size can not be specified */ 2114 buffer = mmap (NULL, 2115 buffer_size, 2116 PROT_READ, 2117 MAP_PRIVATE, 2118 fd, 2119 0); 2120 #endif 2121 2122 id3v1_buffer = read_id3v1_buffer (fd, size); 2123 2124 #ifdef HAVE_POSIX_FADVISE 2125 posix_fadvise (fd, 0, 0, POSIX_FADV_DONTNEED); 2126 #endif /* HAVE_POSIX_FADVISE */ 2127 2128 close (fd); 2129 2130 if (buffer == NULL || buffer == (void*) -1) {
Uninitialized variable: buffer
(emitted by cppcheck)
2131 g_free (filename); 2132 return FALSE; 2133 } 2134 2135 if (!get_id3 (id3v1_buffer, ID3V1_SIZE, &md.id3v1)) { 2136 /* Do nothing? */ 2137 } 2138 2139 g_free (id3v1_buffer); 2140 2141 if (md.id3v1.encoding != NULL) { 2142 gchar *locale; 2143 2144 locale = tracker_locale_get (TRACKER_LOCALE_LANGUAGE); 2145 if (!g_str_has_prefix (locale, "ru") && 2146 !g_str_has_prefix (locale, "uk")) { 2147 /* use guessed encoding for ID3v2 tags only in selected locales 2148 where broken ID3v2 is widespread */ 2149 g_free (md.id3v1.encoding); 2150 md.id3v1.encoding = NULL; 2151 } 2152 g_free (locale); 2153 locale = NULL; 2154 } 2155 2156 /* Get other embedded tags */ 2157 uri = g_file_get_uri (file); 2158 audio_offset = parse_id3v2 (buffer, buffer_size, &md.id3v1, uri, metadata, &md); 2159 2160 md.title = tracker_coalesce_strip (4, md.id3v24.title2, 2161 md.id3v23.title2, 2162 md.id3v22.title2, 2163 md.id3v1.title); 2164 2165 md.lyricist = tracker_coalesce_strip (4, md.id3v24.text, 2166 md.id3v23.toly, 2167 md.id3v23.text, 2168 md.id3v22.text); 2169 2170 md.composer = tracker_coalesce_strip (3, md.id3v24.composer, 2171 md.id3v23.composer, 2172 md.id3v22.composer); 2173 2174 md.performer = tracker_coalesce_strip (7, md.id3v24.performer1, 2175 md.id3v24.performer2, 2176 md.id3v23.performer1, 2177 md.id3v23.performer2, 2178 md.id3v22.performer1, 2179 md.id3v22.performer2, 2180 md.id3v1.artist); 2181 2182 md.album = tracker_coalesce_strip (4, md.id3v24.album, 2183 md.id3v23.album, 2184 md.id3v22.album, 2185 md.id3v1.album); 2186 2187 md.genre = tracker_coalesce_strip (7, md.id3v24.content_type, 2188 md.id3v24.title1, 2189 md.id3v23.content_type, 2190 md.id3v23.title1, 2191 md.id3v22.content_type, 2192 md.id3v22.title1, 2193 md.id3v1.genre); 2194 2195 md.recording_time = tracker_coalesce_strip (7, md.id3v24.recording_time, 2196 md.id3v24.release_time, 2197 md.id3v23.recording_time, 2198 md.id3v23.release_time, 2199 md.id3v22.recording_time, 2200 md.id3v22.release_time, 2201 md.id3v1.recording_time); 2202 2203 md.publisher = tracker_coalesce_strip (3, md.id3v24.publisher, 2204 md.id3v23.publisher, 2205 md.id3v22.publisher); 2206 2207 md.copyright = tracker_coalesce_strip (3, md.id3v24.copyright, 2208 md.id3v23.copyright, 2209 md.id3v22.copyright); 2210 2211 md.comment = tracker_coalesce_strip (7, md.id3v24.title3, 2212 md.id3v24.comment, 2213 md.id3v23.title3, 2214 md.id3v23.comment, 2215 md.id3v22.title3, 2216 md.id3v22.comment, 2217 md.id3v1.comment); 2218 2219 md.encoded_by = tracker_coalesce_strip (3, md.id3v24.encoded_by, 2220 md.id3v23.encoded_by, 2221 md.id3v22.encoded_by); 2222 2223 if (md.id3v24.track_number != 0) { 2224 md.track_number = md.id3v24.track_number; 2225 } else if (md.id3v23.track_number != 0) { 2226 md.track_number = md.id3v23.track_number; 2227 } else if (md.id3v22.track_number != 0) { 2228 md.track_number = md.id3v22.track_number; 2229 } else if (md.id3v1.track_number != 0) { 2230 md.track_number = md.id3v1.track_number; 2231 } 2232 2233 if (md.id3v24.track_count != 0) { 2234 md.track_count = md.id3v24.track_count; 2235 } else if (md.id3v23.track_count != 0) { 2236 md.track_count = md.id3v23.track_count; 2237 } else if (md.id3v22.track_count != 0) { 2238 md.track_count = md.id3v22.track_count; 2239 } 2240 2241 if (md.id3v24.set_number != 0) { 2242 md.set_number = md.id3v24.set_number; 2243 } else if (md.id3v23.set_number != 0) { 2244 md.set_number = md.id3v23.set_number; 2245 } else if (md.id3v22.set_number != 0) { 2246 md.set_number = md.id3v22.set_number; 2247 } 2248 2249 if (md.id3v24.set_count != 0) { 2250 md.set_count = md.id3v24.set_count; 2251 } else if (md.id3v23.set_count != 0) { 2252 md.set_count = md.id3v23.set_count; 2253 } else if (md.id3v22.set_count != 0) { 2254 md.set_count = md.id3v22.set_count; 2255 } 2256 2257 if (md.performer) { 2258 md.performer_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", md.performer); 2259 2260 tracker_sparql_builder_insert_open (preupdate, NULL); 2261 if (graph) { 2262 tracker_sparql_builder_graph_open (preupdate, graph); 2263 } 2264 2265 tracker_sparql_builder_subject_iri (preupdate, md.performer_uri); 2266 tracker_sparql_builder_predicate (preupdate, "a"); 2267 tracker_sparql_builder_object (preupdate, "nmm:Artist"); 2268 tracker_sparql_builder_predicate (preupdate, "nmm:artistName"); 2269 tracker_sparql_builder_object_unvalidated (preupdate, md.performer); 2270 2271 if (graph) { 2272 tracker_sparql_builder_graph_close (preupdate); 2273 } 2274 tracker_sparql_builder_insert_close (preupdate); 2275 } 2276 2277 if (md.composer) { 2278 md.composer_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", md.composer); 2279 2280 tracker_sparql_builder_insert_open (preupdate, NULL); 2281 if (graph) { 2282 tracker_sparql_builder_graph_open (preupdate, graph); 2283 } 2284 2285 tracker_sparql_builder_subject_iri (preupdate, md.composer_uri); 2286 tracker_sparql_builder_predicate (preupdate, "a"); 2287 tracker_sparql_builder_object (preupdate, "nmm:Artist"); 2288 tracker_sparql_builder_predicate (preupdate, "nmm:artistName"); 2289 tracker_sparql_builder_object_unvalidated (preupdate, md.composer); 2290 2291 if (graph) { 2292 tracker_sparql_builder_graph_close (preupdate); 2293 } 2294 tracker_sparql_builder_insert_close (preupdate); 2295 } 2296 2297 if (md.lyricist) { 2298 md.lyricist_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", md.lyricist); 2299 2300 tracker_sparql_builder_insert_open (preupdate, NULL); 2301 if (graph) { 2302 tracker_sparql_builder_graph_open (preupdate, graph); 2303 } 2304 2305 tracker_sparql_builder_subject_iri (preupdate, md.lyricist_uri); 2306 tracker_sparql_builder_predicate (preupdate, "a"); 2307 tracker_sparql_builder_object (preupdate, "nmm:Artist"); 2308 tracker_sparql_builder_predicate (preupdate, "nmm:artistName"); 2309 tracker_sparql_builder_object_unvalidated (preupdate, md.lyricist); 2310 2311 if (graph) { 2312 tracker_sparql_builder_graph_close (preupdate); 2313 } 2314 tracker_sparql_builder_insert_close (preupdate); 2315 } 2316 2317 if (md.album) { 2318 md.album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s", md.album); 2319 2320 tracker_sparql_builder_insert_open (preupdate, NULL); 2321 if (graph) { 2322 tracker_sparql_builder_graph_open (preupdate, graph); 2323 } 2324 2325 tracker_sparql_builder_subject_iri (preupdate, md.album_uri); 2326 tracker_sparql_builder_predicate (preupdate, "a"); 2327 tracker_sparql_builder_object (preupdate, "nmm:MusicAlbum"); 2328 /* FIXME: nmm:albumTitle is now deprecated 2329 * tracker_sparql_builder_predicate (preupdate, "nie:title"); 2330 */ 2331 tracker_sparql_builder_predicate (preupdate, "nmm:albumTitle"); 2332 tracker_sparql_builder_object_unvalidated (preupdate, md.album); 2333 2334 if (md.performer_uri) { 2335 tracker_sparql_builder_predicate (preupdate, "nmm:albumArtist"); 2336 tracker_sparql_builder_object_iri (preupdate, md.performer_uri); 2337 } 2338 2339 if (graph) { 2340 tracker_sparql_builder_graph_close (preupdate); 2341 } 2342 tracker_sparql_builder_insert_close (preupdate); 2343 2344 if (md.track_count > 0) { 2345 tracker_sparql_builder_delete_open (preupdate, NULL); 2346 tracker_sparql_builder_subject_iri (preupdate, md.album_uri); 2347 tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); 2348 tracker_sparql_builder_object_variable (preupdate, "unknown"); 2349 tracker_sparql_builder_delete_close (preupdate); 2350 tracker_sparql_builder_where_open (preupdate); 2351 tracker_sparql_builder_subject_iri (preupdate, md.album_uri); 2352 tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); 2353 tracker_sparql_builder_object_variable (preupdate, "unknown"); 2354 tracker_sparql_builder_where_close (preupdate); 2355 2356 tracker_sparql_builder_insert_open (preupdate, NULL); 2357 if (graph) { 2358 tracker_sparql_builder_graph_open (preupdate, graph); 2359 } 2360 2361 tracker_sparql_builder_subject_iri (preupdate, md.album_uri); 2362 tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); 2363 tracker_sparql_builder_object_int64 (preupdate, md.track_count); 2364 2365 if (graph) { 2366 tracker_sparql_builder_graph_close (preupdate); 2367 } 2368 tracker_sparql_builder_insert_close (preupdate); 2369 } 2370 } 2371 2372 tracker_sparql_builder_predicate (metadata, "a"); 2373 tracker_sparql_builder_object (metadata, "nmm:MusicPiece"); 2374 tracker_sparql_builder_object (metadata, "nfo:Audio"); 2375 2376 tracker_guarantee_title_from_file (metadata, 2377 "nie:title", 2378 md.title, 2379 uri, 2380 NULL); 2381 2382 if (md.lyricist_uri) { 2383 tracker_sparql_builder_predicate (metadata, "nmm:lyricist"); 2384 tracker_sparql_builder_object_iri (metadata, md.lyricist_uri); 2385 g_free (md.lyricist_uri); 2386 } 2387 2388 if (md.performer_uri) { 2389 tracker_sparql_builder_predicate (metadata, "nmm:performer"); 2390 tracker_sparql_builder_object_iri (metadata, md.performer_uri); 2391 g_free (md.performer_uri); 2392 } 2393 2394 if (md.composer_uri) { 2395 tracker_sparql_builder_predicate (metadata, "nmm:composer"); 2396 tracker_sparql_builder_object_iri (metadata, md.composer_uri); 2397 g_free (md.composer_uri); 2398 } 2399 2400 if (md.album_uri) { 2401 tracker_sparql_builder_predicate (metadata, "nmm:musicAlbum"); 2402 tracker_sparql_builder_object_iri (metadata, md.album_uri); 2403 } 2404 2405 if (md.recording_time) { 2406 tracker_sparql_builder_predicate (metadata, "nie:contentCreated"); 2407 tracker_sparql_builder_object_unvalidated (metadata, md.recording_time); 2408 } 2409 2410 if (md.genre) { 2411 tracker_sparql_builder_predicate (metadata, "nfo:genre"); 2412 tracker_sparql_builder_object_unvalidated (metadata, md.genre); 2413 } 2414 2415 if (md.copyright) { 2416 tracker_sparql_builder_predicate (metadata, "nie:copyright"); 2417 tracker_sparql_builder_object_unvalidated (metadata, md.copyright); 2418 } 2419 2420 if (md.comment) { 2421 tracker_sparql_builder_predicate (metadata, "nie:comment"); 2422 tracker_sparql_builder_object_unvalidated (metadata, md.comment); 2423 } 2424 2425 if (md.publisher) { 2426 tracker_sparql_builder_predicate (metadata, "nco:publisher"); 2427 tracker_sparql_builder_object_blank_open (metadata); 2428 tracker_sparql_builder_predicate (metadata, "a"); 2429 tracker_sparql_builder_object (metadata, "nco:Contact"); 2430 tracker_sparql_builder_predicate (metadata, "nco:fullname"); 2431 tracker_sparql_builder_object_unvalidated (metadata, md.publisher); 2432 tracker_sparql_builder_object_blank_close (metadata); 2433 } 2434 2435 if (md.encoded_by) { 2436 tracker_sparql_builder_predicate (metadata, "nfo:encodedBy"); 2437 tracker_sparql_builder_object_unvalidated (metadata, md.encoded_by); 2438 } 2439 2440 if (md.track_number > 0) { 2441 tracker_sparql_builder_predicate (metadata, "nmm:trackNumber"); 2442 tracker_sparql_builder_object_int64 (metadata, md.track_number); 2443 } 2444 2445 if (md.album) { 2446 gchar *album_disc_uri; 2447 2448 album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d", 2449 md.album, 2450 md.set_number > 0 ? md.set_number : 1); 2451 2452 tracker_sparql_builder_delete_open (preupdate, NULL); 2453 tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); 2454 tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); 2455 tracker_sparql_builder_object_variable (preupdate, "unknown"); 2456 tracker_sparql_builder_delete_close (preupdate); 2457 tracker_sparql_builder_where_open (preupdate); 2458 tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); 2459 tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); 2460 tracker_sparql_builder_object_variable (preupdate, "unknown"); 2461 tracker_sparql_builder_where_close (preupdate); 2462 2463 tracker_sparql_builder_delete_open (preupdate, NULL); 2464 tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); 2465 tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); 2466 tracker_sparql_builder_object_variable (preupdate, "unknown"); 2467 tracker_sparql_builder_delete_close (preupdate); 2468 tracker_sparql_builder_where_open (preupdate); 2469 tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); 2470 tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); 2471 tracker_sparql_builder_object_variable (preupdate, "unknown"); 2472 tracker_sparql_builder_where_close (preupdate); 2473 2474 tracker_sparql_builder_insert_open (preupdate, NULL); 2475 if (graph) { 2476 tracker_sparql_builder_graph_open (preupdate, graph); 2477 } 2478 2479 tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); 2480 tracker_sparql_builder_predicate (preupdate, "a"); 2481 tracker_sparql_builder_object (preupdate, "nmm:MusicAlbumDisc"); 2482 tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); 2483 tracker_sparql_builder_object_int64 (preupdate, md.set_number > 0 ? md.set_number : 1); 2484 tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); 2485 tracker_sparql_builder_object_iri (preupdate, md.album_uri); 2486 2487 if (graph) { 2488 tracker_sparql_builder_graph_close (preupdate); 2489 } 2490 tracker_sparql_builder_insert_close (preupdate); 2491 2492 tracker_sparql_builder_predicate (metadata, "nmm:musicAlbumDisc"); 2493 tracker_sparql_builder_object_iri (metadata, album_disc_uri); 2494 2495 g_free (album_disc_uri); 2496 } 2497 2498 g_free (md.album_uri); 2499 2500 /* Get mp3 stream info */ 2501 mp3_parse (buffer, buffer_size, audio_offset, uri, metadata, &md); 2502 2503 tracker_media_art_process (md.media_art_data, 2504 md.media_art_size, 2505 md.media_art_mime, 2506 TRACKER_MEDIA_ART_ALBUM, 2507 md.performer, 2508 md.album, 2509 uri); 2510 g_free (md.media_art_data); 2511 g_free (md.media_art_mime); 2512 2513 id3v2tag_free (&md.id3v22); 2514 id3v2tag_free (&md.id3v23); 2515 id3v2tag_free (&md.id3v24); 2516 id3tag_free (&md.id3v1); 2517 2518 #ifndef G_OS_WIN32 2519 munmap (buffer, buffer_size); 2520 #endif 2521 2522 g_free (filename); 2523 g_free (uri); 2524 2525 return TRUE; 2526 }