Commit b169b0a6 authored by Christophe Fergeau's avatar Christophe Fergeau

Use new tagging stuff to read and write flac metadata. Only handles...

Use new tagging stuff to read and write flac metadata. Only handles vorbiscomment tags, and not (older) id3v2 tags.

Original commit message from CVS:
Use new tagging stuff to read and write flac metadata. Only handles vorbiscomment tags, and not (older) id3v2 tags.
parent f1d94660
......@@ -32,6 +32,10 @@ plugin_init (GstPlugin *plugin)
if (!gst_library_load ("gstbytestream"))
return FALSE;
/* we need the gsttags plugin for metadata querying */
if (!gst_plugin_load ("gsttags"))
return FALSE;
if (!gst_element_register (plugin, "flacenc", GST_RANK_NONE, GST_TYPE_FLACENC))
return FALSE;
......
......@@ -25,6 +25,9 @@
/*#define DEBUG_ENABLED */
#include "gstflacdec.h"
#include <gst/gsttaginterface.h>
#include <gst/tags/gsttagediting.h>
#include "flac_compat.h"
......@@ -66,14 +69,6 @@ static gboolean gst_flacdec_src_query (GstPad *pad, GstQueryType type,
static const GstEventMask*
gst_flacdec_get_src_event_masks (GstPad *pad);
static gboolean gst_flacdec_src_event (GstPad *pad, GstEvent *event);
static void gst_flacdec_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gst_flacdec_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static FLAC__SeekableStreamDecoderReadStatus
gst_flacdec_read (const FLAC__SeekableStreamDecoder *decoder,
......@@ -186,14 +181,7 @@ gst_flacdec_class_init (FlacDecClass *klass)
gobject_class = (GObjectClass*) klass;
parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
g_object_class_install_property (gobject_class, ARG_METADATA,
g_param_spec_boxed ("metadata", "Metadata", "(logical) Stream metadata",
GST_TYPE_CAPS, G_PARAM_READABLE));
gobject_class->get_property = gst_flacdec_get_property;
gobject_class->set_property = gst_flacdec_set_property;
gstelement_class->change_state = gst_flacdec_change_state;
}
......@@ -219,7 +207,6 @@ gst_flacdec_init (FlacDec *flacdec)
flacdec->init = TRUE;
flacdec->eos = FALSE;
flacdec->seek_pending = FALSE;
flacdec->metadata = NULL;
FLAC__seekable_stream_decoder_set_read_callback (flacdec->decoder, gst_flacdec_read);
FLAC__seekable_stream_decoder_set_seek_callback (flacdec->decoder, gst_flacdec_seek);
......@@ -246,20 +233,15 @@ gst_flacdec_init (FlacDec *flacdec)
static gboolean
gst_flacdec_update_metadata (FlacDec *flacdec, const FLAC__StreamMetadata *metadata)
{
GstTagList *list;
guint32 number_of_comments, cursor, str_len;
gchar *p_value, *value, *name, *str_ptr;
GstProps *props = NULL;
GstPropsEntry *entry;
/* clear old one */
if (flacdec->metadata) {
gst_caps_unref (flacdec->metadata);
flacdec->metadata = NULL;
list = gst_tag_list_new ();
if (list == NULL) {
return FALSE;
}
/* create props to hold the key/value pairs */
props = gst_props_empty_new ();
number_of_comments = metadata->data.vorbis_comment.num_comments;
value = NULL;
GST_DEBUG ("%d tag(s) found", number_of_comments);
......@@ -271,23 +253,20 @@ gst_flacdec_update_metadata (FlacDec *flacdec, const FLAC__StreamMetadata *metad
if (p_value)
{
name = g_strndup (str_ptr, p_value - str_ptr);
value = g_strndup (p_value + 1, str_ptr + str_len - p_value);
value = g_strndup (p_value + 1, str_ptr + str_len - p_value - 1);
entry = gst_props_entry_new (name, GST_PROPS_STRING_TYPE, value);
gst_props_add_entry (props, (GstPropsEntry *) entry);
GST_DEBUG ("%s : %s", name, value);
gst_vorbis_tag_add (list, name, value);
g_free (name);
g_free (value);
}
}
flacdec->metadata = gst_caps_new ("vorbisfile_metadata",
"application/x-gst-metadata",
props);
g_object_notify (G_OBJECT (flacdec), "metadata");
gst_element_found_tags (GST_ELEMENT (flacdec), list);
if (GST_PAD_IS_USABLE (flacdec->srcpad)) {
gst_pad_push (flacdec->srcpad, GST_DATA (gst_event_new_tag (list)));
}
return TRUE;
}
......@@ -790,38 +769,3 @@ gst_flacdec_change_state (GstElement *element)
return GST_STATE_SUCCESS;
}
static void
gst_flacdec_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
FlacDec *flacdec;
g_return_if_fail (GST_IS_FLACDEC (object));
flacdec = GST_FLACDEC (object);
switch (prop_id) {
default:
g_warning ("Unknown property id\n");
}
}
static void
gst_flacdec_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
FlacDec *flacdec;
g_return_if_fail (GST_IS_FLACDEC(object));
flacdec = GST_FLACDEC (object);
switch (prop_id) {
case ARG_METADATA:
g_value_set_boxed (value, flacdec->metadata);
break;
default:
g_warning ("Unknown property id\n");
}
}
......@@ -45,7 +45,6 @@ struct _FlacDec {
GstElement element;
GstPad *sinkpad,*srcpad;
GstCaps *metadata;
GstByteStream *bs;
FLAC__SeekableStreamDecoder *decoder;
......
......@@ -25,7 +25,8 @@
#include <string.h>
#include <gstflacenc.h>
#include <gst/tags/gsttagediting.h>
#include <gst/gsttaginterface.h>
#include "flac_compat.h"
static GstPadTemplate *src_template, *sink_template;
......@@ -108,7 +109,15 @@ flacenc_get_type (void)
0,
(GInstanceInitFunc)gst_flacenc_init,
};
static const GInterfaceInfo tag_setter_info = {
NULL,
NULL,
NULL
};
flacenc_type = g_type_register_static (GST_TYPE_ELEMENT, "FlacEnc", &flacenc_info, 0);
g_type_add_interface_static (flacenc_type, GST_TYPE_TAG_SETTER, &tag_setter_info);
}
return flacenc_type;
}
......@@ -333,31 +342,13 @@ gst_flacenc_init (FlacEnc *flacenc)
FLAC__seekable_stream_encoder_set_client_data (flacenc->encoder,
flacenc);
flacenc->metadata = GST_CAPS_NEW (
"flacenc_metadata",
"application/x-gst-metadata",
"DESCRIPTION", GST_PROPS_STRING ("Track encoded with GStreamer"),
"DATE", GST_PROPS_STRING (""),
"TRACKNUMBER", GST_PROPS_STRING (""),
"TITLE", GST_PROPS_STRING (""),
"ARTIST", GST_PROPS_STRING (""),
"ALBUM", GST_PROPS_STRING (""),
"GENRE", GST_PROPS_STRING (""),
"VERSION", GST_PROPS_STRING (""),
"COPYRIGHT", GST_PROPS_STRING (""),
"LICENSE", GST_PROPS_STRING (""),
"ORGANISATION", GST_PROPS_STRING (""),
"LOCATION", GST_PROPS_STRING (""),
"CONTACT", GST_PROPS_STRING (""),
"ISRC", GST_PROPS_STRING ("")
);
flacenc->negotiated = FALSE;
flacenc->first = TRUE;
flacenc->first_buf = NULL;
flacenc->data = NULL;
gst_flacenc_update_quality (flacenc, DEFAULT_QUALITY);
flacenc->tags = gst_tag_list_new ();
}
static void
......@@ -492,46 +483,51 @@ gst_flacenc_write_callback (const FLAC__SeekableStreamEncoder *encoder,
return FLAC__STREAM_ENCODER_OK;
}
void add_one_tag (const GstTagList *list,
const gchar *tag,
gpointer user_data)
{
GList *comments;
GList *it;
FlacEnc *flacenc = GST_FLACENC (user_data);
comments = gst_tag_to_vorbis_comments (list, tag);
for (it = comments; it != NULL; it = it->next) {
FLAC__StreamMetadata_VorbisComment_Entry commment_entry;
commment_entry.length = GUINT32_TO_LE (strlen(it->data) + 1);
commment_entry.entry = it->data;
FLAC__metadata_object_vorbiscomment_insert_comment (flacenc->meta[0],
flacenc->meta[0]->data.vorbis_comment.num_comments,
commment_entry,
TRUE);
g_free (it->data);
}
g_list_free (comments);
}
static void
gst_flacenc_set_metadata (FlacEnc *flacenc, GstCaps *caps)
gst_flacenc_set_metadata (FlacEnc *flacenc)
{
guint indice;
guint comments;
const gchar *meta_types[] = { "TITLE", "VERSION", "ALBUM", "TRACKNUMBER",
"ARTIST", "PERFORMER", "COPYRIGHT", "LICENSE",
"ORGANISATION", "DESCRIPTION", "GENRE", "DATE",
"LOCATION", "CONTACT", "ISRC", NULL };
const GstTagList *user_tags;
GstTagList *copy;
g_return_if_fail (flacenc != NULL);
user_tags = gst_tag_setter_get_list (GST_TAG_SETTER (flacenc));
if ((flacenc->tags == NULL) && (user_tags == NULL)) {
return;
}
copy = gst_tag_list_merge (user_tags, flacenc->tags,
gst_tag_setter_get_merge_mode (GST_TAG_SETTER (flacenc)));
flacenc->meta = g_malloc (sizeof (FLAC__StreamMetadata **));
flacenc->meta[0] = FLAC__metadata_object_new (FLAC__METADATA_TYPE_VORBIS_COMMENT);
for ( indice = 0, comments=0; meta_types[indice] != NULL; indice++) {
if (gst_caps_has_property(caps, meta_types[indice])) {
const gchar *entry;
gchar *data;
FLAC__StreamMetadata_VorbisComment_Entry commment_entry;
gst_caps_get_string(caps, (gchar *)meta_types[indice], &entry);
if (!strcmp (entry, ""))
continue;
data = g_strdup_printf("%s=%s", meta_types[indice], entry);
commment_entry.length = GUINT32_TO_LE (strlen(entry) + strlen(meta_types[indice]) + 1);
commment_entry.entry = g_convert (data, commment_entry.length, "UTF8", "ISO-8859-1", NULL, NULL, NULL);
FLAC__metadata_object_vorbiscomment_insert_comment (flacenc->meta[0], comments++, commment_entry, TRUE);
}
}
gst_tag_list_foreach ((GstTagList*)copy, add_one_tag, flacenc);
FLAC__seekable_stream_encoder_set_metadata(flacenc->encoder, flacenc->meta, 1);
gst_tag_list_free (copy);
}
static void
gst_flacenc_chain (GstPad *pad, GstData *_data)
{
......@@ -553,10 +549,19 @@ gst_flacenc_chain (GstPad *pad, GstData *_data)
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
FLAC__seekable_stream_encoder_finish(flacenc->encoder);
break;
case GST_EVENT_TAG:
if (flacenc->tags) {
gst_tag_list_merge (flacenc->tags, gst_event_tag_get_list (event),
gst_tag_setter_get_merge_mode (GST_TAG_SETTER (flacenc)));
} else {
g_assert_not_reached ();
}
break;
default:
gst_pad_event_default (pad, event);
break;
}
gst_pad_event_default (pad, event);
return;
}
......@@ -575,8 +580,7 @@ gst_flacenc_chain (GstPad *pad, GstData *_data)
FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
{
FLAC__SeekableStreamEncoderState state;
gst_flacenc_set_metadata (flacenc, flacenc->metadata);
gst_flacenc_set_metadata (flacenc);
state = FLAC__seekable_stream_encoder_init (flacenc->encoder);
if (state != FLAC__STREAM_ENCODER_OK) {
gst_element_error (GST_ELEMENT (flacenc),
......
......@@ -44,8 +44,6 @@ struct _FlacEnc {
GstPad *sinkpad,*srcpad;
GstCaps *metadata;
gboolean first;
GstBuffer *first_buf;
gboolean eos;
......@@ -59,6 +57,8 @@ struct _FlacEnc {
FLAC__SeekableStreamEncoder *encoder;
FLAC__StreamMetadata **meta;
GstTagList * tags;
};
struct _FlacEncClass {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment