summaryrefslogtreecommitdiff
path: root/gst/id3tag
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim@centricular.net>2012-08-21 10:22:49 +0100
committerTim-Philipp Müller <tim@centricular.net>2012-08-21 10:22:49 +0100
commit38c749ca2fee21d66ff6bae848146007fbd0e52e (patch)
treed8b90218c3546855f95def4e08a3f979995deddf /gst/id3tag
parent77377c55a29b4058d27b10dabf6907113cabc0cd (diff)
id3tag: port to 0.11
Diffstat (limited to 'gst/id3tag')
-rw-r--r--gst/id3tag/gstid3mux.c37
-rw-r--r--gst/id3tag/id3tag.c155
2 files changed, 112 insertions, 80 deletions
diff --git a/gst/id3tag/gstid3mux.c b/gst/id3tag/gstid3mux.c
index 59bd8a00b..de6d80662 100644
--- a/gst/id3tag/gstid3mux.c
+++ b/gst/id3tag/gstid3mux.c
@@ -1,7 +1,7 @@
/* GStreamer ID3 v1 and v2 muxer
*
* Copyright (C) 2006 Christophe Fergeau <teuf@gnome.org>
- * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2006-2012 Tim-Philipp Müller <tim centricular net>
* Copyright (C) 2009 Pioneers of the Inevitable <songbird@songbirdnest.com>
*
* This library is free software; you can redistribute it and/or
@@ -81,7 +81,7 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("application/x-id3"));
-GST_BOILERPLATE (GstId3Mux, gst_id3_mux, GstTagMux, GST_TYPE_TAG_MUX);
+G_DEFINE_TYPE (GstId3Mux, gst_id3_mux, GST_TYPE_TAG_MUX);
static GstBuffer *gst_id3_mux_render_v2_tag (GstTagMux * mux,
const GstTagList * taglist);
@@ -94,26 +94,9 @@ static void gst_id3_mux_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void
-gst_id3_mux_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_template));
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_template));
-
- gst_element_class_set_details_simple (element_class,
- "ID3 v1 and v2 Muxer", "Formatter/Metadata",
- "Adds an ID3v2 header and ID3v1 footer to a file",
- "Michael Smith <msmith@songbirdnest.com>, "
- "Tim-Philipp Müller <tim centricular net>");
-}
-
-static void
gst_id3_mux_class_init (GstId3MuxClass * klass)
{
+ GstElementClass *element_class = (GstElementClass *) klass;
GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_id3_mux_set_property;
@@ -139,10 +122,22 @@ gst_id3_mux_class_init (GstId3MuxClass * klass)
GST_DEBUG_FUNCPTR (gst_id3_mux_render_v2_tag);
GST_TAG_MUX_CLASS (klass)->render_end_tag =
GST_DEBUG_FUNCPTR (gst_id3_mux_render_v1_tag);
+
+ gst_element_class_set_details_simple (element_class,
+ "ID3 v1 and v2 Muxer", "Formatter/Metadata",
+ "Adds an ID3v2 header and ID3v1 footer to a file",
+ "Michael Smith <msmith@songbirdnest.com>, "
+ "Tim-Philipp Müller <tim centricular net>");
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&sink_template));
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&src_template));
}
static void
-gst_id3_mux_init (GstId3Mux * id3mux, GstId3MuxClass * id3mux_class)
+gst_id3_mux_init (GstId3Mux * id3mux)
{
id3mux->write_v1 = DEFAULT_WRITE_V1;
id3mux->write_v2 = DEFAULT_WRITE_V2;
diff --git a/gst/id3tag/id3tag.c b/gst/id3tag/id3tag.c
index fc69a49c4..70d169a02 100644
--- a/gst/id3tag/id3tag.c
+++ b/gst/id3tag/id3tag.c
@@ -192,6 +192,7 @@ static GstBuffer *
id3v2_tag_to_buffer (GstId3v2Tag * tag)
{
GstByteWriter *w;
+ GstMapInfo info;
GstBuffer *buf;
guint8 *dest;
guint i, size, offset, size_frames = 0;
@@ -217,8 +218,9 @@ id3v2_tag_to_buffer (GstId3v2Tag * tag)
gst_byte_writer_write_uint8 (w, 0); /* flags */
gst_byte_writer_write_uint32_syncsafe (w, size - 10);
- buf = gst_buffer_new_and_alloc (size);
- dest = GST_BUFFER_DATA (buf);
+ buf = gst_buffer_new_allocate (NULL, size, NULL);
+ gst_buffer_map (buf, &info, GST_MAP_WRITE);
+ dest = info.data;
gst_byte_writer_copy_bytes (w, dest, 0, 10);
offset = 10;
@@ -233,6 +235,7 @@ id3v2_tag_to_buffer (GstId3v2Tag * tag)
memset (dest + offset, 0, size - offset);
gst_byte_writer_free (w);
+ gst_buffer_unmap (buf, &info);
return buf;
}
@@ -472,6 +475,7 @@ add_text_tag (GstId3v2Tag * id3v2tag, const GstTagList * list,
g_free (strings);
}
+/* FIXME: id3v2-private frames need to be extracted as samples */
static void
add_id3v2frame_tag (GstId3v2Tag * id3v2tag, const GstTagList * list,
const gchar * tag, guint num_tags, const gchar * unused)
@@ -479,42 +483,57 @@ add_id3v2frame_tag (GstId3v2Tag * id3v2tag, const GstTagList * list,
guint i;
for (i = 0; i < num_tags; ++i) {
- const GValue *val;
+ GstSample *sample;
GstBuffer *buf;
+ GstCaps *caps;
- val = gst_tag_list_get_value_index (list, tag, i);
- buf = gst_value_get_buffer (val);
+ if (!gst_tag_list_get_sample_index (list, tag, i, &sample))
+ continue;
- if (buf && GST_BUFFER_CAPS (buf)) {
+ buf = gst_sample_get_buffer (sample);
+
+ /* FIXME: should use auxiliary sample struct instead of caps for this */
+ caps = gst_sample_get_caps (sample);
+
+ if (buf && caps) {
GstStructure *s;
gint version = 0;
- s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0);
+ s = gst_caps_get_structure (caps, 0);
/* We can only add it if this private buffer is for the same ID3 version,
because we don't understand the contents at all. */
if (s && gst_structure_get_int (s, "version", &version) &&
version == id3v2tag->major_version) {
GstId3v2Frame frame;
+ GstMapInfo mapinfo;
gchar frame_id[5];
guint16 flags;
- guint8 *data = GST_BUFFER_DATA (buf);
- gint size = GST_BUFFER_SIZE (buf);
-
- if (size < 10) /* header size */
- return;
-
- /* We only reach here if the frame version matches the muxer. Since the
- muxer only does v2.3 or v2.4, the frame must be one of those - and
- so the frame header is the same format */
- memcpy (frame_id, data, 4);
- frame_id[4] = 0;
- flags = GST_READ_UINT16_BE (data + 8);
-
- id3v2_frame_init (&frame, frame_id, flags);
- id3v2_frame_write_bytes (&frame, data + 10, size - 10);
-
- g_array_append_val (id3v2tag->frames, frame);
- GST_DEBUG ("Added unparsed tag with %d bytes", size);
+ guint8 *data;
+ gint size;
+
+ if (!gst_buffer_map (buf, &mapinfo, GST_MAP_READ))
+ continue;
+
+ size = mapinfo.size;
+ data = mapinfo.data;
+
+ if (size >= 10) { /* header size */
+ /* We only get here if the frame version matches the muxer. Since the
+ * muxer only does v2.3 or v2.4, the frame must be one of those - and
+ * so the frame header is the same format */
+ memcpy (frame_id, data, 4);
+ frame_id[4] = 0;
+ flags = GST_READ_UINT16_BE (data + 8);
+
+ id3v2_frame_init (&frame, frame_id, flags);
+ id3v2_frame_write_bytes (&frame, data + 10, size - 10);
+
+ g_array_append_val (id3v2tag->frames, frame);
+ GST_DEBUG ("Added unparsed tag with %d bytes", size);
+ gst_buffer_unmap (buf, &mapinfo);
+ } else {
+ GST_WARNING ("Short ID3v2 frame");
+ }
} else {
GST_WARNING ("Discarding unrecognised ID3 tag for different ID3 "
"version");
@@ -687,25 +706,29 @@ add_image_tag (GstId3v2Tag * id3v2tag, const GstTagList * list,
guint n;
for (n = 0; n < num_tags; ++n) {
- const GValue *val;
+ GstSample *sample;
GstBuffer *image;
+ GstCaps *caps;
GST_DEBUG ("image %u/%u", n + 1, num_tags);
- val = gst_tag_list_get_value_index (list, tag, n);
- image = gst_value_get_buffer (val);
+ if (!gst_tag_list_get_sample_index (list, tag, n, &sample))
+ continue;
+
+ image = gst_sample_get_buffer (sample);
+ caps = gst_sample_get_caps (sample);
- if (GST_IS_BUFFER (image) && GST_BUFFER_SIZE (image) > 0 &&
- GST_BUFFER_CAPS (image) != NULL &&
- !gst_caps_is_empty (GST_BUFFER_CAPS (image))) {
+ if (image != NULL && gst_buffer_get_size (image) > 0 &&
+ caps != NULL && !gst_caps_is_empty (caps)) {
const gchar *mime_type;
GstStructure *s;
- s = gst_caps_get_structure (GST_BUFFER_CAPS (image), 0);
+ s = gst_caps_get_structure (caps, 0);
mime_type = gst_structure_get_name (s);
if (mime_type != NULL) {
const gchar *desc;
GstId3v2Frame frame;
+ GstMapInfo mapinfo;
int encoding;
/* APIC frame specifies "-->" if we're providing a URL to the image
@@ -713,8 +736,8 @@ add_image_tag (GstId3v2Tag * id3v2tag, const GstTagList * list,
if (strcmp (mime_type, "text/uri-list") == 0)
mime_type = "-->";
- GST_DEBUG ("Attaching picture of %u bytes and mime type %s",
- GST_BUFFER_SIZE (image), mime_type);
+ GST_DEBUG ("Attaching picture of %" G_GSIZE_FORMAT " bytes and "
+ "mime type %s", gst_buffer_get_size (image), mime_type);
id3v2_frame_init (&frame, "APIC", 0);
@@ -734,14 +757,17 @@ add_image_tag (GstId3v2Tag * id3v2tag, const GstTagList * list,
id3v2_frame_write_string (&frame, encoding, desc, TRUE);
- id3v2_frame_write_bytes (&frame, GST_BUFFER_DATA (image),
- GST_BUFFER_SIZE (image));
-
- g_array_append_val (id3v2tag->frames, frame);
+ if (gst_buffer_map (image, &mapinfo, GST_MAP_READ)) {
+ id3v2_frame_write_bytes (&frame, mapinfo.data, mapinfo.size);
+ g_array_append_val (id3v2tag->frames, frame);
+ gst_buffer_unmap (image, &mapinfo);
+ } else {
+ GST_WARNING ("Couldn't map image tag buffer");
+ id3v2_frame_unset (&frame);
+ }
}
} else {
- GST_WARNING ("NULL image or no caps on image buffer (%p, caps=%"
- GST_PTR_FORMAT ")", image, (image) ? GST_BUFFER_CAPS (image) : NULL);
+ GST_WARNING ("no image or caps: %p, caps=%" GST_PTR_FORMAT, image, caps);
}
}
}
@@ -839,28 +865,32 @@ add_date_tag (GstId3v2Tag * id3v2tag, const GstTagList * list,
else
frame_id = "TDRC";
- GST_LOG ("Adding date frame");
+ GST_LOG ("Adding date time frame");
strings = g_new0 (gchar *, num_tags + 1);
for (n = 0; n < num_tags; ++n) {
- GDate *date = NULL;
+ GstDateTime *dt = NULL;
+ guint year;
+ gchar *s;
- if (gst_tag_list_get_date_index (list, tag, n, &date) && date != NULL) {
- GDateYear year;
- gchar *s;
+ if (!gst_tag_list_get_date_time_index (list, tag, n, &dt) || dt == NULL)
+ continue;
- year = g_date_get_year (date);
- if (year > 500 && year < 2100) {
- s = g_strdup_printf ("%u", year);
- GST_LOG ("%s[%u] = '%s'", tag, n, s);
- strings[i] = s;
- i++;
- } else {
- GST_WARNING ("invalid year %u, skipping", year);
- }
+ year = gst_date_time_get_year (dt);
+ if (year > 500 && year < 2100) {
+ s = g_strdup_printf ("%u", year);
+ GST_LOG ("%s[%u] = '%s'", tag, n, s);
+ strings[i] = s;
+ i++;
+ } else {
+ GST_WARNING ("invalid year %u, skipping", year);
+ }
- g_date_free (date);
+ if (gst_date_time_has_month (dt)) {
+ if (id3v2tag->major_version == 3)
+ GST_FIXME ("write TDAT and possibly also TIME frame");
}
+ gst_date_time_free (dt);
}
if (strings[0] != NULL) {
@@ -1089,7 +1119,7 @@ static const struct
/* Up to here, all the frame ids and contents have been the same between
versions 2.3 and 2.4. The rest of them differ... */
/* Date (in ID3v2.3, this is a TYER tag. In v2.4, it's a TDRC tag */
- GST_TAG_DATE, add_date_tag, NULL}, {
+ GST_TAG_DATE_TIME, add_date_tag, NULL}, {
/* Replaygain data (not really supported in 2.3, we use an experimental
tag there) */
@@ -1159,7 +1189,7 @@ id3_mux_render_v2_tag (GstTagMux * mux, const GstTagList * taglist, int version)
/* Create buffer with tag */
buf = id3v2_tag_to_buffer (&tag);
- GST_LOG_OBJECT (mux, "tag size = %d bytes", GST_BUFFER_SIZE (buf));
+ GST_LOG_OBJECT (mux, "tag size = %d bytes", (int) gst_buffer_get_size (buf));
id3v2_tag_unset (&tag);
@@ -1265,6 +1295,7 @@ track_number_convert (const GstTagList * list, const gchar * tag,
}
}
+/* FIXME: get rid of silly table */
static const struct
{
const gchar *gst_tag;
@@ -1286,11 +1317,15 @@ static const struct
GstBuffer *
id3_mux_render_v1_tag (GstTagMux * mux, const GstTagList * taglist)
{
- GstBuffer *buf = gst_buffer_new_and_alloc (ID3_V1_TAG_SIZE);
- guint8 *data = GST_BUFFER_DATA (buf);
+ GstMapInfo info;
+ GstBuffer *buf;
+ guint8 *data;
gboolean wrote_tag = FALSE;
int i;
+ buf = gst_buffer_new_allocate (NULL, ID3_V1_TAG_SIZE, NULL);
+ gst_buffer_map (buf, &info, GST_MAP_WRITE);
+ data = info.data;
memset (data, 0, ID3_V1_TAG_SIZE);
data[0] = 'T';
@@ -1305,6 +1340,8 @@ id3_mux_render_v1_tag (GstTagMux * mux, const GstTagList * taglist)
v1_funcs[i].length, &wrote_tag);
}
+ gst_buffer_unmap (buf, &info);
+
if (!wrote_tag) {
GST_WARNING_OBJECT (mux, "no ID3v1 tag written (no suitable tags found)");
gst_buffer_unref (buf);