Exemple #1
0
static gboolean
xmms_metadata_test_xform_init (xmms_xform_t *xform)
{
	const gchar *musicbrainz_va_id = "89ad4ac3-39f7-470e-963a-56509c546377";
	const gchar *title, *rpgain;
	gint track, totaltracks, compilation;

	CU_ASSERT_FALSE (xmms_xform_metadata_mapper_match (xform, "missing", "missing", -1));

	/* Basic string mapping */
	CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "title", "the title", -1));
	CU_ASSERT_TRUE (xmms_xform_metadata_get_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TITLE, &title));
	CU_ASSERT_STRING_EQUAL ("the title", title);

	/* Mapping track number, without total tracks */
	CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "tracknr", "1", -1));
	CU_ASSERT_TRUE (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR, &track));
	CU_ASSERT_FALSE (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TOTALTRACKS, &totaltracks));
	CU_ASSERT_EQUAL (1, track);

	/* Mapping track number, with total tracks */
	CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "tracknr", "1/10", -1));
	CU_ASSERT_TRUE (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR, &track));
	CU_ASSERT_TRUE (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TOTALTRACKS, &totaltracks));
	CU_ASSERT_EQUAL (1, track);
	CU_ASSERT_EQUAL (10, totaltracks);

	/* Broken track number */
	CU_ASSERT_FALSE (xmms_xform_metadata_mapper_match (xform, "tracknr", "bad", -1));

	/* Mapping compilation indicator to boolean compilation */
	CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "compilation", "1", -1));
	CU_ASSERT_TRUE (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_COMPILATION, &compilation));
	CU_ASSERT_EQUAL (TRUE, compilation);

	/* Mapping compilation indicator to boolean compilation */
	CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "compilation", musicbrainz_va_id, -1));
	CU_ASSERT_TRUE (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_COMPILATION, &compilation));
	CU_ASSERT_EQUAL (TRUE, compilation);


	/* Mapping replaygain to the format the replaygain xform expects */
	CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "replaygain_track_gain", "-14.69", -1));
	CU_ASSERT_TRUE (xmms_xform_metadata_get_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_TRACK, &rpgain));
	CU_ASSERT_STRING_EQUAL ("0.18428", rpgain);
	CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "replaygain_track_gain", "-14.69 dB", -1));
	CU_ASSERT_TRUE (xmms_xform_metadata_get_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_TRACK, &rpgain));
	CU_ASSERT_STRING_EQUAL ("0.18428", rpgain);


	CU_ASSERT_TRUE (xmms_xform_metadata_mapper_match (xform, "coverart", "test", 10));

	xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", XMMS_STREAM_TYPE_END);

	return TRUE;
}
Exemple #2
0
static void
handle_comments (xmms_xform_t *xform, xmms_flac_data_t *data)
{
	FLAC__StreamMetadata_VorbisComment *vc;
	gint i;

	g_return_if_fail (data->vorbiscomment);

	vc = &data->vorbiscomment->data.vorbis_comment;

	for (i = 0; i < vc->num_comments; i++) {
		const gchar *entry, *ptr;
		gchar key[64];
		gsize length;

		entry = (const gchar *) vc->comments[i].entry;
		length = vc->comments[i].length;

		if (entry == NULL || *entry == '\0')
			continue;

		ptr = memchr (entry, '=', length);
		if (ptr == NULL)
			continue;

		ptr++;

		g_strlcpy (key, entry, MIN (ptr - entry, sizeof (key)));

		if (!xmms_xform_metadata_mapper_match (xform, key, ptr, length - (ptr - entry))) {
			XMMS_DBG ("Unhandled tag '%s'", entry);
		}
	}
}
Exemple #3
0
static gboolean
xmms_asf_handle_tag_old_tracknr (xmms_xform_t *xform, const gchar *key,
                                 const gchar *value, gsize length)
{
    gint ivalue;

    /* WM/TrackNumber overrides WM/Track value as specified in the Microsoft
     * documentation at http://msdn2.microsoft.com/en-us/library/aa392014.aspx
     * so lets check if something else has set the tracknr property before us.
     */
    if (xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR, &ivalue)) {
        return FALSE;
    }

    /* Ok, nothing set, lets handle "WM/Track" as "WM/TrackNumber" */
    if (!xmms_xform_metadata_mapper_match (xform, "WM/TrackNumber", value, length)) {
        return FALSE;
    }

    /* Last quirk, WM/Track is 0-indexed, need to fix that */
    xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR, &ivalue);
    xmms_xform_metadata_set_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TRACKNR, ivalue + 1);

    return TRUE;
}
Exemple #4
0
static void
xmms_vorbis_read_metadata (xmms_xform_t *xform, xmms_vorbis_data_t *data)
{
	vorbis_comment *vc;
	gint i;

	vc = ov_comment (&data->vorbisfile, -1);
	if (!vc)
		return;

	for (i = 0; i < vc->comments; i++) {
		const gchar *ptr, *entry;
		gsize length;
		gchar key[64];

		entry = vc->user_comments[i];
		length = vc->comment_lengths[i];

		if (entry == NULL || *entry == '\0')
			continue;

		/* check whether it's a valid comment */
		ptr = memchr (entry, '=', length);
		if (ptr == NULL)
			continue;

		ptr++;

		g_strlcpy (key, entry, MIN (ptr - entry, sizeof (key)));

		if (!xmms_xform_metadata_mapper_match (xform, key, ptr, length - (ptr - entry))) {
			XMMS_DBG ("Unhandled tag '%s'", entry);
		}
	}
}
Exemple #5
0
static void
xmms_mp4_get_mediainfo (xmms_xform_t *xform)
{
	xmms_mp4_data_t *data;
	const gchar *metakey;
	glong temp;
	gint i, num_items;

	g_return_if_fail (xform);

	data = xmms_xform_private_data_get (xform);
	g_return_if_fail (data);

	if ((temp = mp4ff_get_sample_rate (data->mp4ff, data->track)) > 0) {
		glong srate = temp;

		if ((temp = mp4ff_get_track_duration (data->mp4ff, data->track)) >= 0) {
			glong msec = ((gint64) temp) * 1000 / srate;

			metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION,
			xmms_xform_metadata_set_int (xform, metakey, msec);
		}
	}

	if ((temp = mp4ff_get_avg_bitrate (data->mp4ff, data->track)) >= 0) {
		metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE;
		xmms_xform_metadata_set_int (xform, metakey, temp);
	}

	num_items = mp4ff_meta_get_num_items (data->mp4ff);
	for (i = 0; i < num_items; i++) {
		gchar *key, *value;
		guint length;

		length = mp4ff_meta_get_by_index (data->mp4ff, i, &key, &value);
		if (length > 0) {
			if (!xmms_xform_metadata_mapper_match (xform, key, value, length)) {
				/* iTunSMPB should be handled in xmms_mp4_gapless_try */
				if (0 != g_ascii_strcasecmp (key, "iTunSMPB")) {
					XMMS_DBG ("Unhandled tag '%s' = '%s'", key, value);
				}
			}
			g_free (key);
			g_free (value);
		}
	}
}
Exemple #6
0
static void
xmms_opus_read_metadata (xmms_xform_t *xform, xmms_opus_data_t *data)
{
	data->opushead = op_head (data->opusfile, -1);
	data->opustags = op_tags (data->opusfile, -1);
	data->channels = op_channel_count (data->opusfile, -1);

	gint i;

	if (!data->opustags)
		return;

	for (i = 0; i < data->opustags->comments; i++) {
		const gchar *ptr, *entry;
		gsize length;
		gchar key[64];

		entry = data->opustags->user_comments[i];
		length = data->opustags->comment_lengths[i];

		if (entry == NULL || *entry == '\0')
			continue;

		/* check whether it's a valid comment */
		ptr = memchr (entry, '=', length);
		if (ptr == NULL)
			continue;

		ptr++;

		g_strlcpy (key, entry, MIN (ptr - entry, sizeof (key)));

		if (!xmms_xform_metadata_mapper_match (xform, key, ptr, length - (ptr - entry))) {
			XMMS_DBG ("Unhandled tag '%s'", entry);
		}

	}
}
Exemple #7
0
static gboolean
xmms_apetag_read (xmms_xform_t *xform)
{
	guchar buffer[32], *tagdata;
	xmms_error_t error;
	guint version, tag_size, items, flags;
	gint64 tag_position;
	gint pos, i, ret;

	g_return_val_if_fail (xform, FALSE);

	/* Try to find the 32-byte footer from the end of file */
	tag_position = xmms_xform_seek (xform, -32, XMMS_XFORM_SEEK_END, &error);
	if (tag_position < 0) {
		/* Seeking failed, failed to read tags */
		return FALSE;
	}

	/* Read footer data if seeking was possible */
	ret = xmms_xform_read (xform, buffer, 32, &error);
	if (ret != 32) {
		xmms_log_error ("Failed to read APE tag footer");
		return FALSE;
	}

	/* Check that the footer is valid, if not continue searching */
	if (memcmp (buffer, "APETAGEX", 8)) {
		/* Try to find the 32-byte footer before 128-byte ID3v1 tag */
		tag_position = xmms_xform_seek (xform, -160, XMMS_XFORM_SEEK_END, &error);
		if (tag_position < 0) {
			/* Seeking failed, failed to read tags */
			xmms_log_error ("Failed to seek to APE tag footer");
			return FALSE;
		}

		/* Read footer data if seeking was possible */
		ret = xmms_xform_read (xform, buffer, 32, &error);
		if (ret != 32) {
			xmms_log_error ("Failed to read APE tag footer");
			return FALSE;
		}

		if (memcmp (buffer, "APETAGEX", 8)) {
			/* Didn't find any APE tag from the file */
			return FALSE;
		}
	}

	version = xmms_apetag_get_le32 (buffer + 8);
	tag_size = xmms_apetag_get_le32 (buffer + 12);
	items = xmms_apetag_get_le32 (buffer + 16);
	flags = xmms_apetag_get_le32 (buffer + 20);

	if (flags & APE_TAG_FLAG_IS_HEADER) {
		/* We need a footer, not a header... */
		return FALSE;
	}

	if (version != 1000 && version != 2000) {
		xmms_log_error ("Invalid tag version, the writer is probably corrupted!");
		return FALSE;
	}

	/* Seek to the beginning of the actual tag data */
	ret = xmms_xform_seek (xform, tag_position - tag_size + 32,
	                       XMMS_XFORM_SEEK_SET, &error);
	if (ret < 0) {
		xmms_log_error ("Couldn't seek to the tag starting position, returned %d", ret);
		return FALSE;
	}

	tagdata = g_malloc (tag_size);
	ret = xmms_xform_read (xform, tagdata, tag_size, &error);
	if (ret != tag_size) {
		xmms_log_error ("Couldn't read the tag data, returned %d", ret);
		g_free (tagdata);
		return FALSE;
	}

	pos = 0;
	for (i = 0; i < items; i++) {
		gint itemlen, flags;
		gchar *key, *item;

		itemlen = xmms_apetag_get_le32 (tagdata + pos);
		pos += 4;
		flags = xmms_apetag_get_le32 (tagdata + pos);
		pos += 4;
		key = (gchar *) tagdata + pos;
		pos += strlen (key) + 1;

		switch (flags & APE_TAG_FLAG_DATA_TYPE) {
			case APE_TAG_DATA_TYPE_UTF8:
				item = g_strndup ((gchar *) tagdata + pos, itemlen);
				break;
			case APE_TAG_DATA_TYPE_BINARY:
				item = g_malloc (itemlen);
				memcpy (item, tagdata + pos, itemlen);
				break;
			case APE_TAG_DATA_TYPE_LOCATOR:
				item = NULL;
				break;
		}

		if (item != NULL && !xmms_xform_metadata_mapper_match (xform, key, item, itemlen)) {
			if ((flags & APE_TAG_FLAG_DATA_TYPE) == APE_TAG_DATA_TYPE_UTF8) {
				XMMS_DBG ("Unhandled tag '%s' = '%s'", key, item);
			} else {
				XMMS_DBG ("Unhandled tag '%s' = '(binary)'", key);
			}
		}

		g_free (item);
		pos += itemlen;
	}
	g_free (tagdata);

	return TRUE;
}
Exemple #8
0
static void
xmms_asf_get_mediainfo (xmms_xform_t *xform)
{
    xmms_asf_data_t *data;
    asf_metadata_t *metadata;
    uint64_t tmp;
    gint i;

    g_return_if_fail (xform);

    data = xmms_xform_private_data_get (xform);
    g_return_if_fail (data);

    if ((tmp = asf_get_duration (data->file)) > 0) {
        xmms_xform_metadata_set_int (xform,
                                     XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION,
                                     tmp/10000);
    }

    if ((tmp = asf_get_max_bitrate (data->file)) > 0) {
        xmms_xform_metadata_set_int (xform,
                                     XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE,
                                     tmp);
    }

    metadata = asf_header_get_metadata (data->file);
    if (!metadata) {
        XMMS_DBG ("No metadata object found in the file");
        return;
    }

    if (metadata->title && metadata->title[0]) {
        xmms_xform_metadata_set_str (xform,
                                     XMMS_MEDIALIB_ENTRY_PROPERTY_TITLE,
                                     metadata->title);
    }

    if (metadata->artist && metadata->artist[0]) {
        xmms_xform_metadata_set_str (xform,
                                     XMMS_MEDIALIB_ENTRY_PROPERTY_ARTIST,
                                     metadata->artist);
    }

    if (metadata->description && metadata->description[0]) {
        xmms_xform_metadata_set_str (xform,
                                     XMMS_MEDIALIB_ENTRY_PROPERTY_COMMENT,
                                     metadata->description);
    }

    for (i = 0; i < metadata->extended_count; i++) {
        const char *key, *value;
        guint16 length;

        key = metadata->extended[i].key;
        value = metadata->extended[i].value;
        length = metadata->extended[i].length;

        if (!xmms_xform_metadata_mapper_match (xform, key, value, length)) {
            XMMS_DBG ("Unhandled tag '%s' = '%s'", key, value);
        }
    }

    asf_metadata_destroy (metadata);
}