diff --git a/ChangeLog b/ChangeLog index 17664d47f1..3ed39f6cd9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2008-08-06 Sebastian Dröge + + Based on a patch by: Jonathan Matthew + + * ext/flac/Makefile.am: + * ext/flac/gstflac.c: (plugin_init): + * ext/flac/gstflactag.c: (gst_flac_tag_setup_interfaces), + (gst_flac_tag_base_init), (gst_flac_tag_class_init), + (gst_flac_tag_dispose), (gst_flac_tag_init), + (gst_flac_tag_sink_setcaps), (gst_flac_tag_chain), + (gst_flac_tag_change_state): + * ext/flac/gstflactag.h: + Port flactag to 0.10, add documentation for it and clean it up a bit. + Fixes bug #413841. + + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-good-plugins-docs.sgml: + * docs/plugins/gst-plugins-good-plugins-sections.txt: + * docs/plugins/gst-plugins-good-plugins.hierarchy: + * docs/plugins/gst-plugins-good-plugins.interfaces: + * docs/plugins/gst-plugins-good-plugins.prerequisites: + * docs/plugins/inspect/plugin-flac.xml: + * ext/flac/gstflacdec.c: (gst_flac_dec_base_init): + * ext/flac/gstflacdec.h: + * ext/flac/gstflacenc.c: (gst_flac_enc_base_init): + * ext/flac/gstflacenc.h: + Add flactag and flacenc to the documentation and mark + the private parts of the flacdec instance structure as private. + + Also use gst_element_class_set_details_simple() in flacdec and + flacenc. + 2008-08-06 Stefan Kost * gst/qtdemux/qtdemux.c: diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 2eebe7633f..b5cb41afa9 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -84,6 +84,8 @@ EXTRA_HFILES = \ $(top_srcdir)/ext/dv/gstdvdemux.h \ $(top_srcdir)/ext/esd/esdsink.h \ $(top_srcdir)/ext/flac/gstflacdec.h \ + $(top_srcdir)/ext/flac/gstflacenc.h \ + $(top_srcdir)/ext/flac/gstflactag.h \ $(top_srcdir)/ext/gdk_pixbuf/gstgdkpixbufsink.h \ $(top_srcdir)/ext/hal/gsthalaudiosink.h \ $(top_srcdir)/ext/hal/gsthalaudiosrc.h \ diff --git a/docs/plugins/gst-plugins-good-plugins-docs.sgml b/docs/plugins/gst-plugins-good-plugins-docs.sgml index f54d13309c..72b54c5b76 100644 --- a/docs/plugins/gst-plugins-good-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-good-plugins-docs.sgml @@ -46,6 +46,8 @@ + + diff --git a/docs/plugins/gst-plugins-good-plugins-sections.txt b/docs/plugins/gst-plugins-good-plugins-sections.txt index 60b3ba406d..712c0c8dc9 100644 --- a/docs/plugins/gst-plugins-good-plugins-sections.txt +++ b/docs/plugins/gst-plugins-good-plugins-sections.txt @@ -538,6 +538,34 @@ gst_flac_dec_get_type LEGACY_FLAC +
+element-flacenc +flacenc +GstFlacEnc + +GstFlacEncClass +GST_TYPE_FLAC_ENC +GST_FLAC_ENC +GST_FLAC_ENC_CLASS +GST_IS_FLAC_ENC +GST_IS_FLAC_ENC_CLASS +gst_flac_enc_get_type +
+ +
+element-flactag +flactag +GstFlacTag + +GstFlacTagClass +GST_TYPE_FLAC_TAG +GST_FLAC_TAG +GST_FLAC_TAG_CLASS +GST_IS_FLAC_TAG +GST_IS_FLAC_TAG_CLASS +gst_flac_tag_get_type +
+
element-gamma gamma diff --git a/docs/plugins/gst-plugins-good-plugins.hierarchy b/docs/plugins/gst-plugins-good-plugins.hierarchy index ef19bd526b..78d644e3aa 100644 --- a/docs/plugins/gst-plugins-good-plugins.hierarchy +++ b/docs/plugins/gst-plugins-good-plugins.hierarchy @@ -11,34 +11,89 @@ GObject GstElement GstBin GstPipeline - GstRTSPSrc - GstRgVolume - GstAutoVideoSink - GstAutoAudioSink + GstHalAudioSink + GstHalAudioSrc GstGConfVideoSink GstGConfVideoSrc GstSwitchSink GstGConfAudioSink GstGConfAudioSrc - GstHalAudioSink - GstHalAudioSrc - GstAviDemux - GstAviMux - GstAviSubtitle - GstGoom2k1 - GstEbmlRead - GstMatroskaDemux - GstMatroskaMux - GstFlxDec + GstAutoVideoSink + GstAutoAudioSink + GstRgVolume + GstRTSPSrc + GstPngDec + GstPngEnc + GstJpegEnc + GstJpegDec + GstSmokeEnc + GstSmokeDec + GstBaseSink + GstBaseAudioSink + GstAudioSink + GstEsdSink + GstPulseSink + GstOssSink + GstAASink + GstCACASink + GstVideoSink + GstGdkPixbufSink + GstShout2send + GstTest + GstMultiUDPSink + GstUDPSink + GstDynUDPSink + GstMultiFileSink + GstCmmlEnc + GstCmmlDec + GstWavpackParse + GstWavpackDec + GstWavpackEnc + GstBaseSrc + GstPushSrc + GstDV1394Src + GstSoupHTTPSrc + GstBaseAudioSrc + GstAudioSrc + GstPulseSrc + GstOssSrc + GstCddaBaseSrc + GstCdioCddaSrc + GstV4l2Src + GstXImageSrc + GstUDPSrc + GstMultiFileSrc + GstPulseMixer + GstFlacEnc + GstFlacDec + GstFlacTag + GstCairoTextOverlay GstBaseTransform + GstCairoTimeOverlay + GstPixbufScale GstVideoCrop + GstAudioFilter + GstSpectrum + GstIirEqualizer + GstIirEqualizerNBands + GstIirEqualizer3Bands + GstIirEqualizer10Bands + GstAudioInvert + GstAudioKaraoke + GstAudioAmplify + GstAudioDynamic + GstAudioChebLimit + GstAudioChebBand + GstAudioWSincLimit + GstAudioWSincBand GstVideoBox + GstLevel GstVideoFilter - GstSMPTEAlpha GstNavigationtest GstGamma - GstVideoFlip GstVideoBalance + GstVideoFlip + GstSMPTEAlpha GstEdgeTV GstAgingTV GstDiceTV @@ -52,77 +107,46 @@ GObject GstProgressReport GstTagInject GstAudioPanorama - GstAudioFilter - GstAudioInvert - GstAudioKaraoke - GstAudioAmplify - GstAudioDynamic - GstAudioChebLimit - GstAudioChebBand - GstAudioWSincLimit - GstAudioWSincBand - GstIirEqualizer - GstIirEqualizerNBands - GstIirEqualizer3Bands - GstIirEqualizer10Bands - GstSpectrum - GstAlphaColor - GstAlpha GstRgAnalysis GstRgLimiter - GstLevel - GstPixbufScale - GstCairoTimeOverlay - GstMonoscope - GstAuParse + GstAlphaColor + GstAlpha + GstDVDemux + GstDVDec + GstGdkPixbuf + GstSpeexEnc + GstSpeexDec + GstTagLibMux + GstId3v2Mux + GstApev2Mux + GstOssMixerElement + GstCutter + GstAviDemux + GstAviMux + GstAviSubtitle + GstGoom2k1 + GstALawEnc + GstALawDec + GstMuLawEnc + GstMuLawDec + GstWavEnc + GstWavParse + GstICYDemux GstVideoMixer - GstBaseSrc - GstPushSrc - GstMultiFileSrc - GstUDPSrc - GstXImageSrc - GstV4l2Src - GstBaseAudioSrc - GstAudioSrc - GstOssSrc - GstPulseSrc - GstDV1394Src - GstSoupHTTPSrc - GstCddaBaseSrc - GstCdioCddaSrc - GstBaseSink - GstMultiFileSink - GstMultiUDPSink - GstUDPSink - GstDynUDPSink - GstTest - GstBaseAudioSink - GstAudioSink - GstOssSink - GstPulseSink - GstEsdSink - GstAASink - GstVideoSink - GstGdkPixbufSink - GstCACASink - GstShout2send - GstInterleave - GstDeinterleave - GstRTPDec - GstSMPTE GstRndBufferSize GstEFence + GstFlxDec GstTagDemux GstApeDemux GstID3Demux - GstGoom + GstAuParse + GstSMPTE GstMultipartDemux GstMultipartMux - GstCutter - GstWavParse - GstQTDemux + GstInterleave + GstDeinterleave + GstRTPDepay GstBaseRTPDepayload - GstRtpXQTDepay GstRtpAC3Depay GstRTPDVDepay GstRTPiLBCDepay @@ -147,12 +171,7 @@ GObject GstRtpTheoraDepay GstRtpVorbisDepay GstRtpVRawDepay - GstMuLawEnc - GstMuLawDec - GstALawEnc - GstALawDec - GstICYDemux - GstRTPDepay + GstRtpXQTDepay GstBaseRTPPayload GstRTPDVPay GstBaseRTPAudioPayload @@ -177,31 +196,13 @@ GObject GstRtpVorbisPay GstRtpVRawPay GstAsteriskh263 - GstWavEnc - GstOssMixerElement - GstDVDemux - GstDVDec - GstSpeexEnc - GstSpeexDec - GstCmmlEnc - GstCmmlDec - GstGdkPixbuf - GstWavpackParse - GstWavpackDec - GstWavpackEnc - GstPngDec - GstPngEnc - GstCairoTextOverlay - GstTagLibMux - GstId3v2Mux - GstApev2Mux - GstFlacEnc - GstFlacDec - GstPulseMixer - GstJpegEnc - GstJpegDec - GstSmokeEnc - GstSmokeDec + GstRTPDec + GstEbmlRead + GstMatroskaDemux + GstMatroskaMux + GstMonoscope + GstGoom + GstQTDemux GstBus GstTask GstClock @@ -211,23 +212,21 @@ GObject GstRegistry GstRingBuffer GstSignalObject - GstColorBalanceChannel - GstTunerNorm - GstTunerChannel - GstMixerTrack - GstMixerOptions GstCmmlTagStream GstCmmlTagHead GstCmmlTagClip GdkPixbuf + GstTunerNorm + GstTunerChannel + GstColorBalanceChannel GInterface GTypePlugin GstChildProxy GstURIHandler - GstTagSetter - GstImplementsInterface - GstColorBalance - GstTuner - GstVideoOrientation GstPropertyProbe + GstImplementsInterface GstMixer + GstTagSetter + GstTuner + GstColorBalance + GstVideoOrientation diff --git a/docs/plugins/gst-plugins-good-plugins.interfaces b/docs/plugins/gst-plugins-good-plugins.interfaces index 252a2a392f..c431d34f3d 100644 --- a/docs/plugins/gst-plugins-good-plugins.interfaces +++ b/docs/plugins/gst-plugins-good-plugins.interfaces @@ -1,38 +1,39 @@ GstBin GstChildProxy GstPipeline GstChildProxy -GstRTSPSrc GstChildProxy GstURIHandler -GstRgVolume GstChildProxy -GstAutoVideoSink GstChildProxy -GstAutoAudioSink GstChildProxy +GstHalAudioSink GstChildProxy +GstHalAudioSrc GstChildProxy GstGConfVideoSink GstChildProxy GstGConfVideoSrc GstChildProxy GstSwitchSink GstChildProxy GstGConfAudioSink GstChildProxy GstGConfAudioSrc GstChildProxy -GstHalAudioSink GstChildProxy -GstHalAudioSrc GstChildProxy -GstAviMux GstTagSetter -GstMatroskaMux GstTagSetter -GstVideoBalance GstImplementsInterface GstColorBalance +GstAutoVideoSink GstChildProxy +GstAutoAudioSink GstChildProxy +GstRgVolume GstChildProxy +GstRTSPSrc GstChildProxy GstURIHandler +GstShout2send GstTagSetter +GstUDPSink GstURIHandler +GstDV1394Src GstURIHandler GstPropertyProbe +GstSoupHTTPSrc GstURIHandler +GstPulseSrc GstImplementsInterface GstMixer +GstOssSrc GstImplementsInterface GstMixer +GstCddaBaseSrc GstURIHandler +GstCdioCddaSrc GstURIHandler +GstV4l2Src GstPropertyProbe GstImplementsInterface GstTuner GstColorBalance GstVideoOrientation +GstUDPSrc GstURIHandler +GstPulseMixer GstPropertyProbe GstImplementsInterface GstMixer +GstFlacEnc GstTagSetter +GstFlacTag GstTagSetter GstIirEqualizer GstChildProxy GstIirEqualizerNBands GstChildProxy GstIirEqualizer3Bands GstChildProxy GstIirEqualizer10Bands GstChildProxy -GstVideoMixer GstChildProxy -GstUDPSrc GstURIHandler -GstV4l2Src GstImplementsInterface GstColorBalance GstTuner GstVideoOrientation GstPropertyProbe -GstOssSrc GstImplementsInterface GstMixer -GstPulseSrc GstImplementsInterface GstMixer -GstDV1394Src GstURIHandler GstPropertyProbe -GstSoupHTTPSrc GstURIHandler -GstCddaBaseSrc GstURIHandler -GstCdioCddaSrc GstURIHandler -GstUDPSink GstURIHandler -GstShout2send GstTagSetter -GstOssMixerElement GstImplementsInterface GstMixer +GstVideoBalance GstImplementsInterface GstColorBalance GstSpeexEnc GstTagSetter GstTagLibMux GstTagSetter GstId3v2Mux GstTagSetter GstApev2Mux GstTagSetter -GstFlacEnc GstTagSetter -GstPulseMixer GstImplementsInterface GstMixer GstPropertyProbe +GstOssMixerElement GstImplementsInterface GstMixer +GstAviMux GstTagSetter +GstVideoMixer GstChildProxy +GstMatroskaMux GstTagSetter diff --git a/docs/plugins/gst-plugins-good-plugins.prerequisites b/docs/plugins/gst-plugins-good-plugins.prerequisites index a33abde001..eb1fa169b2 100644 --- a/docs/plugins/gst-plugins-good-plugins.prerequisites +++ b/docs/plugins/gst-plugins-good-plugins.prerequisites @@ -1,7 +1,7 @@ GstChildProxy GstObject -GstTagSetter GstObject GstElement GstImplementsInterface GstObject GstElement -GstColorBalance GstObject GstImplementsInterface GstElement -GstTuner GstObject GstImplementsInterface GstElement -GstVideoOrientation GstObject GstImplementsInterface GstElement GstMixer GstObject GstImplementsInterface GstElement +GstTagSetter GstObject GstElement +GstTuner GstObject GstImplementsInterface GstElement +GstColorBalance GstObject GstImplementsInterface GstElement +GstVideoOrientation GstObject GstImplementsInterface GstElement diff --git a/docs/plugins/inspect/plugin-flac.xml b/docs/plugins/inspect/plugin-flac.xml index 616fbb570c..ab534c1eb6 100644 --- a/docs/plugins/inspect/plugin-flac.xml +++ b/docs/plugins/inspect/plugin-flac.xml @@ -3,10 +3,10 @@ The FLAC Lossless compressor Codec ../../ext/flac/.libs/libgstflac.so libgstflac.so - 0.10.9 + 0.10.9.1 LGPL gst-plugins-good - GStreamer Good Plug-ins source release + GStreamer Good Plug-ins CVS/prerelease Unknown package origin @@ -16,18 +16,18 @@ Decodes FLAC lossless audio streams Wim Taymans <wim@fluendo.com> + + src + source + always +
audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int){ 8, 16, 32 }, depth=(int)[ 4, 32 ], rate=(int)[ 1, 655350 ], channels=(int)[ 1, 8 ]
+
sink sink always
audio/x-flac
- - src - source - always -
audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int){ 8, 16, 32 }, depth=(int){ 8, 12, 16, 20, 24, 32 }, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 8 ]
-
@@ -36,6 +36,27 @@ Codec/Encoder/Audio Encodes audio with the FLAC lossless audio encoder Wim Taymans <wim.taymans@chello.be> + + + sink + sink + always +
audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)8, depth=(int)8, rate=(int)[ 1, 655350 ], channels=(int)[ 1, 8 ]; audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int){ 12, 16 }, rate=(int)[ 1, 655350 ], channels=(int)[ 1, 8 ]; audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)32, depth=(int){ 20, 24 }, rate=(int)[ 1, 655350 ], channels=(int)[ 1, 8 ]
+
+ + src + source + always +
audio/x-flac
+
+
+
+ + flactag + FLAC tagger + Formatter/Metadata + Rewrite tags in a FLAC file + Christophe Fergeau <teuf@gnome.org> src @@ -47,7 +68,7 @@ sink sink always -
audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]
+
audio/x-flac
diff --git a/ext/flac/Makefile.am b/ext/flac/Makefile.am index 2723680e64..0e7d41a2f1 100644 --- a/ext/flac/Makefile.am +++ b/ext/flac/Makefile.am @@ -1,6 +1,6 @@ plugin_LTLIBRARIES = libgstflac.la -libgstflac_la_SOURCES = gstflac.c gstflacdec.c gstflacenc.c +libgstflac_la_SOURCES = gstflac.c gstflacdec.c gstflacenc.c gstflactag.c libgstflac_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) libgstflac_la_LIBADD = \ $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) \ @@ -8,4 +8,4 @@ libgstflac_la_LIBADD = \ $(GST_BASE_LIBS) $(GST_LIBS) $(FLAC_LIBS) libgstflac_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -noinst_HEADERS = gstflacenc.h gstflacdec.h +noinst_HEADERS = gstflacenc.h gstflacdec.h gstflactag.h diff --git a/ext/flac/gstflac.c b/ext/flac/gstflac.c index d07ec479fd..7d76a41c41 100644 --- a/ext/flac/gstflac.c +++ b/ext/flac/gstflac.c @@ -23,7 +23,7 @@ #include "gstflacenc.h" #include "gstflacdec.h" -/* #include "gstflactag.h" */ +#include "gstflactag.h" #include #include @@ -43,11 +43,9 @@ plugin_init (GstPlugin * plugin) if (!gst_element_register (plugin, "flacdec", GST_RANK_PRIMARY, GST_TYPE_FLAC_DEC)) return FALSE; -#if 0 if (!gst_element_register (plugin, "flactag", GST_RANK_PRIMARY, gst_flac_tag_get_type ())) return FALSE; -#endif gst_tag_register_musicbrainz_tags (); diff --git a/ext/flac/gstflacdec.c b/ext/flac/gstflacdec.c index 7b8e381f86..66d6c14ce2 100644 --- a/ext/flac/gstflacdec.c +++ b/ext/flac/gstflacdec.c @@ -105,15 +105,7 @@ GST_DEBUG_CATEGORY_STATIC (flacdec_debug); static GstPadTemplate *src_template, *sink_template; -static const GstElementDetails flacdec_details = -GST_ELEMENT_DETAILS ("FLAC audio decoder", - "Codec/Decoder/Audio", - "Decodes FLAC lossless audio streams", - "Wim Taymans "); - - static void gst_flac_dec_finalize (GObject * object); - static void gst_flac_dec_loop (GstPad * pad); static GstStateChangeReturn gst_flac_dec_change_state (GstElement * element, @@ -237,7 +229,9 @@ gst_flac_dec_base_init (gpointer g_class) GST_PAD_ALWAYS, raw_caps); gst_element_class_add_pad_template (element_class, sink_template); gst_element_class_add_pad_template (element_class, src_template); - gst_element_class_set_details (element_class, &flacdec_details); + gst_element_class_set_details_simple (element_class, "FLAC audio decoder", + "Codec/Decoder/Audio", + "Decodes FLAC lossless audio streams", "Wim Taymans "); GST_DEBUG_CATEGORY_INIT (flacdec_debug, "flacdec", 0, "flac decoder"); } diff --git a/ext/flac/gstflacdec.h b/ext/flac/gstflacdec.h index b68986d299..100c4e0bca 100644 --- a/ext/flac/gstflacdec.h +++ b/ext/flac/gstflacdec.h @@ -47,6 +47,8 @@ typedef struct _GstFlacDecClass GstFlacDecClass; struct _GstFlacDec { GstElement element; + /* < private > */ + #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT < 8 FLAC__SeekableStreamDecoder *seekable_decoder; /* for pull-based operation */ #else diff --git a/ext/flac/gstflacenc.c b/ext/flac/gstflacenc.c index 1a2a34b6dc..1e29343cf6 100644 --- a/ext/flac/gstflacenc.c +++ b/ext/flac/gstflacenc.c @@ -77,12 +77,6 @@ static const GstAudioChannelPosition channel_positions[8][8] = { GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT} }; -static const GstElementDetails flacenc_details = -GST_ELEMENT_DETAILS ("FLAC audio encoder", - "Codec/Encoder/Audio", - "Encodes audio with the FLAC lossless audio encoder", - "Wim Taymans "); - #define FLAC_SINK_CAPS \ "audio/x-raw-int, " \ "endianness = (int) BYTE_ORDER, " \ @@ -261,7 +255,10 @@ gst_flac_enc_base_init (gpointer g_class) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&sink_factory)); - gst_element_class_set_details (element_class, &flacenc_details); + gst_element_class_set_details_simple (element_class, "FLAC audio encoder", + "Codec/Encoder/Audio", + "Encodes audio with the FLAC lossless audio encoder", + "Wim Taymans "); GST_DEBUG_CATEGORY_INIT (flacenc_debug, "flacenc", 0, "Flac encoding element"); diff --git a/ext/flac/gstflacenc.h b/ext/flac/gstflacenc.h index 016a56b616..1c6a6c66bb 100644 --- a/ext/flac/gstflacenc.h +++ b/ext/flac/gstflacenc.h @@ -45,6 +45,8 @@ typedef struct _GstFlacEncClass GstFlacEncClass; struct _GstFlacEnc { GstElement element; + /* < private > */ + GstPad *sinkpad; GstPad *srcpad; diff --git a/ext/flac/gstflactag.c b/ext/flac/gstflactag.c index 247e1dea2f..d7ca61cc41 100644 --- a/ext/flac/gstflactag.c +++ b/ext/flac/gstflactag.c @@ -1,6 +1,7 @@ - /* GStreamer * Copyright (C) 2003 Christophe Fergeau + * Copyright (C) 2008 Jonathan Matthew + * Copyright (C) 2008 Sebastian Dröge * * gstflactag.c: plug-in for reading/modifying vorbis comments in flac files * @@ -20,78 +21,58 @@ * Boston, MA 02111-1307, USA. */ +/** + * SECTION:element-flactag + * @see_also: #flacenc, #flacdec, #GstTagSetter + * + * The flactag element can change the tag contained within a raw + * FLAC stream. Specifically, it modifies the comments header packet + * of the FLAC stream. + * + * Applications can set the tags to write using the #GstTagSetter interface. + * Tags contained withing the FLAC bitstream will be picked up + * automatically (and merged according to the merge mode set via the tag + * setter interface). + * + * + * Example pipelines + * |[ + * gst-launch -v filesrc location=foo.flac ! flactag ! filesink location=bar.flac + * ]| This element is not useful with gst-launch, because it does not support + * setting the tags on a #GstTagSetter interface. Conceptually, the element + * will usually be used in this order though. + * + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif + +#include #include +#include #include #include -#define GST_TYPE_FLAC_TAG (gst_flac_tag_get_type()) -#define GST_FLAC_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FLAC_TAG, GstFlacTag)) -#define GST_FLAC_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FLAC_TAG, GstFlacTag)) -#define GST_IS_FLAC_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FLAC_TAG)) -#define GST_IS_FLAC_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FLAC_TAG)) +#include "gstflactag.h" -typedef struct _GstFlacTag GstFlacTag; -typedef struct _GstFlacTagClass GstFlacTagClass; - -static inline gint -min (gint a, gint b) -{ - if (a < b) { - return a; - } else { - return b; - } -} - - -typedef enum -{ - GST_FLAC_TAG_STATE_INIT, - GST_FLAC_TAG_STATE_METADATA_BLOCKS, - GST_FLAC_TAG_STATE_METADATA_NEXT_BLOCK, - GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK, - GST_FLAC_TAG_STATE_VC_METADATA_BLOCK, - GST_FLAC_TAG_STATE_ADD_VORBIS_COMMENT, - GST_FLAC_TAG_STATE_AUDIO_DATA -} -GstFlacTagState; - - -struct _GstFlacTag -{ - GstElement element; - - /* pads */ - GstPad *sinkpad; - GstPad *srcpad; - - GstFlacTagState state; - - GstBuffer *buffer; - GstBuffer *vorbiscomment; - GstTagList *tags; - - guint metadata_bytes_remaining; - gboolean metadata_last_block; - - gboolean only_output_tags; -}; - -struct _GstFlacTagClass -{ - GstElementClass parent_class; -}; +GST_DEBUG_CATEGORY_STATIC (flactag_debug); +#define GST_CAT_DEFAULT flactag_debug /* elementfactory information */ -static const GstElementDetails gst_flac_tag_details = -GST_ELEMENT_DETAILS ("FLAC tagger", - "Tag", - "Rewrite tags in a FLAC file", - "Christope Fergeau "); +static GstStaticPadTemplate flac_tag_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-flac") + ); +static GstStaticPadTemplate flac_tag_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-flac") + ); /* signals and args */ enum @@ -106,121 +87,42 @@ enum /* FILL ME */ }; -static GstStaticPadTemplate flac_tag_src_template = - GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-flac; application/x-gst-tags") - ); +static void gst_flac_tag_dispose (GObject * object); -static GstStaticPadTemplate flac_tag_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-flac") - ); - - -static void gst_flac_tag_base_init (gpointer g_class); -static void gst_flac_tag_class_init (GstFlacTagClass * klass); -static void gst_flac_tag_init (GstFlacTag * tag); - -static void gst_flac_tag_chain (GstPad * pad, GstData * data); +static GstFlowReturn gst_flac_tag_chain (GstPad * pad, GstBuffer * buffer); static GstStateChangeReturn gst_flac_tag_change_state (GstElement * element, GstStateChange transition); +static gboolean gst_flac_tag_sink_setcaps (GstPad * pad, GstCaps * caps); -static GstElementClass *parent_class = NULL; - -/* static guint gst_flac_tag_signals[LAST_SIGNAL] = { 0 }; */ - -GType -gst_flac_tag_get_type (void) +static void +gst_flac_tag_setup_interfaces (GType flac_tag_type) { - static GType flac_tag_type = 0; + static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL }; - if (!flac_tag_type) { - static const GTypeInfo flac_tag_info = { - sizeof (GstFlacTagClass), - gst_flac_tag_base_init, - NULL, - (GClassInitFunc) gst_flac_tag_class_init, - NULL, - NULL, - sizeof (GstFlacTag), - 0, - (GInstanceInitFunc) gst_flac_tag_init, - }; - static const GInterfaceInfo tag_setter_info = { - NULL, - NULL, - NULL - }; - - flac_tag_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstFlacTag", &flac_tag_info, - 0); - - g_type_add_interface_static (flac_tag_type, GST_TYPE_TAG_SETTER, - &tag_setter_info); - - } - return flac_tag_type; + g_type_add_interface_static (flac_tag_type, GST_TYPE_TAG_SETTER, + &tag_setter_info); } +GST_BOILERPLATE_FULL (GstFlacTag, gst_flac_tag, GstElement, GST_TYPE_ELEMENT, + gst_flac_tag_setup_interfaces); static void gst_flac_tag_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - gst_element_class_set_details (element_class, &gst_flac_tag_details); + gst_element_class_set_details_simple (element_class, "FLAC tagger", + "Formatter/Metadata", + "Rewrite tags in a FLAC file", "Christophe Fergeau "); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&flac_tag_sink_template)); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&flac_tag_src_template)); -} - -static void -send_eos (GstFlacTag * tag) -{ - gst_element_set_eos (GST_ELEMENT (tag)); - gst_pad_push (tag->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS))); - /* Seek to end of sink stream */ - if (gst_pad_send_event (GST_PAD_PEER (tag->sinkpad), - gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_END | - GST_SEEK_FLAG_FLUSH, 0))) { - } else { - g_warning ("Couldn't seek to eos on sinkpad\n"); - } -} - - -static gboolean -caps_nego (GstFlacTag * tag) -{ - /* do caps nego */ - GstCaps *caps; - - caps = gst_caps_new_simple ("audio/x-flac", NULL); - if (gst_pad_try_set_caps (tag->srcpad, caps) != GST_PAD_LINK_REFUSED) { - tag->only_output_tags = FALSE; - GST_LOG_OBJECT (tag, "normal operation, using audio/x-flac output"); - } else { - if (gst_pad_try_set_caps (tag->srcpad, - gst_caps_new_simple ("application/x-gst-tags", NULL)) - != GST_PAD_LINK_REFUSED) { - tag->only_output_tags = TRUE; - GST_LOG_OBJECT (tag, "fast operation, just outputting tags"); - printf ("output tags only\n"); - } else { - return FALSE; - } - } - return TRUE; + GST_DEBUG_CATEGORY_INIT (flactag_debug, "flactag", 0, "flac tag rewriter"); } static void @@ -234,86 +136,96 @@ gst_flac_tag_class_init (GstFlacTagClass * klass) parent_class = g_type_class_peek_parent (klass); + gobject_class->dispose = gst_flac_tag_dispose; gstelement_class->change_state = gst_flac_tag_change_state; } +static void +gst_flac_tag_dispose (GObject * object) +{ + GstFlacTag *tag = GST_FLAC_TAG (object); + + if (tag->adapter) { + gst_object_unref (tag->adapter); + tag->adapter = NULL; + } + if (tag->vorbiscomment) { + gst_buffer_unref (tag->vorbiscomment); + tag->vorbiscomment = NULL; + } + if (tag->tags) { + gst_tag_list_free (tag->tags); + tag->tags = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + static void -gst_flac_tag_init (GstFlacTag * tag) +gst_flac_tag_init (GstFlacTag * tag, GstFlacTagClass * klass) { /* create the sink and src pads */ tag->sinkpad = gst_pad_new_from_static_template (&flac_tag_sink_template, "sink"); - gst_element_add_pad (GST_ELEMENT (tag), tag->sinkpad); gst_pad_set_chain_function (tag->sinkpad, GST_DEBUG_FUNCPTR (gst_flac_tag_chain)); + gst_pad_set_setcaps_function (tag->sinkpad, + GST_DEBUG_FUNCPTR (gst_flac_tag_sink_setcaps)); + gst_element_add_pad (GST_ELEMENT (tag), tag->sinkpad); tag->srcpad = gst_pad_new_from_static_template (&flac_tag_src_template, "src"); gst_element_add_pad (GST_ELEMENT (tag), tag->srcpad); - tag->buffer = NULL; + tag->adapter = gst_adapter_new (); +} + +static gboolean +gst_flac_tag_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstFlacTag *tag = GST_FLAC_TAG (GST_PAD_PARENT (pad)); + + return gst_pad_set_caps (tag->srcpad, caps); } #define FLAC_MAGIC "fLaC" #define FLAC_MAGIC_SIZE (sizeof (FLAC_MAGIC) - 1) -static void -gst_flac_tag_chain (GstPad * pad, GstData * data) +static GstFlowReturn +gst_flac_tag_chain (GstPad * pad, GstBuffer * buffer) { - GstBuffer *buffer; GstFlacTag *tag; + GstFlowReturn ret; - if (GST_IS_EVENT (data)) { - g_print ("Unhandled event\n"); - return; - } - - buffer = GST_BUFFER (data); + ret = GST_FLOW_OK; tag = GST_FLAC_TAG (gst_pad_get_parent (pad)); - if (tag->buffer) { - GstBuffer *merge; - - merge = gst_buffer_merge (tag->buffer, buffer); - gst_buffer_unref (buffer); - gst_buffer_unref (tag->buffer); - tag->buffer = merge; - } else { - tag->buffer = buffer; - } - + gst_adapter_push (tag->adapter, buffer); /* Initial state, we don't even know if we are dealing with a flac file */ if (tag->state == GST_FLAC_TAG_STATE_INIT) { - if (!caps_nego (tag)) { - goto cleanup; - } + GstBuffer *id_buffer; - if (GST_BUFFER_SIZE (tag->buffer) < sizeof (FLAC_MAGIC)) { + if (gst_adapter_available (tag->adapter) < sizeof (FLAC_MAGIC)) goto cleanup; - } - if (strncmp (GST_BUFFER_DATA (tag->buffer), FLAC_MAGIC, - FLAC_MAGIC_SIZE) == 0) { - GstBuffer *sub; + id_buffer = gst_adapter_take_buffer (tag->adapter, FLAC_MAGIC_SIZE); + GST_DEBUG_OBJECT (tag, "looking for " FLAC_MAGIC " identifier"); + if (memcmp (GST_BUFFER_DATA (id_buffer), FLAC_MAGIC, FLAC_MAGIC_SIZE) == 0) { + + GST_DEBUG_OBJECT (tag, "pushing " FLAC_MAGIC " identifier buffer"); + gst_buffer_set_caps (id_buffer, GST_PAD_CAPS (tag->srcpad)); + ret = gst_pad_push (tag->srcpad, id_buffer); + if (ret != GST_FLOW_OK) + goto cleanup; tag->state = GST_FLAC_TAG_STATE_METADATA_BLOCKS; - sub = gst_buffer_create_sub (tag->buffer, 0, FLAC_MAGIC_SIZE); - - gst_pad_push (tag->srcpad, GST_DATA (sub)); - sub = - gst_buffer_create_sub (tag->buffer, FLAC_MAGIC_SIZE, - GST_BUFFER_SIZE (tag->buffer) - FLAC_MAGIC_SIZE); - gst_buffer_unref (tag->buffer); - /* We do a copy because we need a writable buffer, and _create_sub - * sets the buffer it uses to read-only - */ - tag->buffer = gst_buffer_copy (sub); - gst_buffer_unref (sub); } else { /* FIXME: does that work well with FLAC files containing ID3v2 tags ? */ + gst_buffer_unref (id_buffer); GST_ELEMENT_ERROR (tag, STREAM, WRONG_TYPE, (NULL), (NULL)); + ret = GST_FLOW_ERROR; } } @@ -325,8 +237,9 @@ gst_flac_tag_chain (GstPad * pad, GstData * data) guint size; guint type; gboolean is_last; + const guint8 *block_header; - g_assert (tag->metadata_bytes_remaining == 0); + g_assert (tag->metadata_block_size == 0); g_assert (tag->metadata_last_block == FALSE); /* The header of a flac metadata block is 4 bytes long: @@ -334,26 +247,25 @@ gst_flac_tag_chain (GstPad * pad, GstData * data) * 7 next bits: 4 if vorbis comment block * 24 next bits: size of the metadata to follow (big endian) */ - if (GST_BUFFER_SIZE (tag->buffer) < 4) { + if (gst_adapter_available (tag->adapter) < 4) goto cleanup; - } - is_last = (((GST_BUFFER_DATA (tag->buffer)[0]) & 0x80) == 0x80); - /* If we have metadata set on the element, the last metadata block - * will be the vorbis comment block which we will build ourselves - */ - if (is_last) { - (GST_BUFFER_DATA (tag->buffer)[0]) &= (~0x80); - } - type = (GST_BUFFER_DATA (tag->buffer)[0]) & 0x7F; - size = ((GST_BUFFER_DATA (tag->buffer)[1]) << 16) - | ((GST_BUFFER_DATA (tag->buffer)[2]) << 8) - | (GST_BUFFER_DATA (tag->buffer)[3]); + block_header = gst_adapter_peek (tag->adapter, 4); + + is_last = ((block_header[0] & 0x80) == 0x80); + type = block_header[0] & 0x7F; + size = (block_header[1] << 16) + | (block_header[2] << 8) + | block_header[3]; /* The 4 bytes long header isn't included in the metadata size */ - tag->metadata_bytes_remaining = size + 4; + tag->metadata_block_size = size + 4; tag->metadata_last_block = is_last; + GST_DEBUG_OBJECT (tag, + "got metadata block: %d bytes, type %d, is vorbiscomment: %d, is last: %d", + size, type, (type == 0x04), is_last); + /* Metadata blocks of type 4 are vorbis comment blocks */ if (type == 0x04) { tag->state = GST_FLAC_TAG_STATE_VC_METADATA_BLOCK; @@ -366,56 +278,29 @@ gst_flac_tag_chain (GstPad * pad, GstData * data) /* Reads a metadata block */ if ((tag->state == GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK) || (tag->state == GST_FLAC_TAG_STATE_VC_METADATA_BLOCK)) { - GstBuffer *sub; - guint bytes_to_push; + GstBuffer *metadata_buffer; - g_assert (tag->metadata_bytes_remaining != 0); + if (gst_adapter_available (tag->adapter) < tag->metadata_block_size) + goto cleanup; - bytes_to_push = min (tag->metadata_bytes_remaining, - GST_BUFFER_SIZE (tag->buffer)); - - sub = gst_buffer_create_sub (tag->buffer, 0, bytes_to_push); + metadata_buffer = gst_adapter_take_buffer (tag->adapter, + tag->metadata_block_size); + /* clear the is-last flag, as the last metadata block will + * be the vorbis comment block which we will build ourselves. + */ + GST_BUFFER_DATA (metadata_buffer)[0] &= (~0x80); if (tag->state == GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK) { - gst_pad_push (tag->srcpad, GST_DATA (sub)); + GST_DEBUG_OBJECT (tag, "pushing metadata block buffer"); + gst_buffer_set_caps (metadata_buffer, GST_PAD_CAPS (tag->srcpad)); + ret = gst_pad_push (tag->srcpad, metadata_buffer); + if (ret != GST_FLOW_OK) + goto cleanup; } else { - if (tag->vorbiscomment == NULL) { - tag->vorbiscomment = sub; - } else { - GstBuffer *merge; - - merge = gst_buffer_merge (tag->vorbiscomment, sub); - gst_buffer_unref (tag->vorbiscomment); - gst_buffer_unref (sub); - tag->vorbiscomment = merge; - } - } - - tag->metadata_bytes_remaining -= (bytes_to_push); - - if (GST_BUFFER_SIZE (tag->buffer) > bytes_to_push) { - GstBuffer *sub; - - sub = gst_buffer_create_sub (tag->buffer, bytes_to_push, - GST_BUFFER_SIZE (tag->buffer) - bytes_to_push); - gst_buffer_unref (tag->buffer); - - /* We make a copy because we need a writable buffer, and _create_sub - * sets the buffer it uses to read-only - */ - tag->buffer = gst_buffer_copy (sub); - gst_buffer_unref (sub); - - tag->state = GST_FLAC_TAG_STATE_METADATA_NEXT_BLOCK; - } else if (tag->metadata_bytes_remaining == 0) { - gst_buffer_unref (tag->buffer); - tag->buffer = NULL; - tag->state = GST_FLAC_TAG_STATE_METADATA_NEXT_BLOCK; - tag->buffer = NULL; - } else { - tag->state = GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK; - tag->buffer = NULL; + tag->vorbiscomment = metadata_buffer; } + tag->metadata_block_size = 0; + tag->state = GST_FLAC_TAG_STATE_METADATA_NEXT_BLOCK; } /* This state is mainly used to be able to stop as soon as we read @@ -428,36 +313,25 @@ gst_flac_tag_chain (GstPad * pad, GstData * data) */ if (tag->vorbiscomment != NULL) { /* We found some tags, try to parse them and notify the other elements - * that we encoutered some tags + * that we encountered some tags */ + GST_DEBUG_OBJECT (tag, "emitting vorbiscomment tags"); tag->tags = gst_tag_list_from_vorbiscomment_buffer (tag->vorbiscomment, GST_BUFFER_DATA (tag->vorbiscomment), 4, NULL); if (tag->tags != NULL) { - gst_element_found_tags (GST_ELEMENT (tag), tag->tags); + gst_element_found_tags (GST_ELEMENT (tag), + gst_tag_list_copy (tag->tags)); } gst_buffer_unref (tag->vorbiscomment); tag->vorbiscomment = NULL; - - if (tag->only_output_tags) { - send_eos (tag); - goto cleanup; - } } /* Skip to next state */ if (tag->metadata_last_block == FALSE) { tag->state = GST_FLAC_TAG_STATE_METADATA_BLOCKS; } else { - if (tag->only_output_tags) { - /* If we finished parsing the metadata blocks, we will never find any - * metadata, so just stop now - */ - send_eos (tag); - goto cleanup; - } else { - tag->state = GST_FLAC_TAG_STATE_ADD_VORBIS_COMMENT; - } + tag->state = GST_FLAC_TAG_STATE_ADD_VORBIS_COMMENT; } } @@ -471,18 +345,21 @@ gst_flac_tag_chain (GstPad * pad, GstData * data) const GstTagList *user_tags; GstTagList *merged_tags; - g_assert (tag->only_output_tags == FALSE); - + /* merge the tag lists */ user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (tag)); - merged_tags = gst_tag_list_merge (tag->tags, user_tags, - gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (tag))); + if (user_tags != NULL) { + merged_tags = gst_tag_list_merge (user_tags, tag->tags, + gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (tag))); + } else { + merged_tags = gst_tag_list_copy (tag->tags); + } if (merged_tags == NULL) { /* If we get a NULL list of tags, we must generate a padding block * which is marked as the last metadata block, otherwise we'll * end up with a corrupted flac file. */ - g_warning ("No tags found\n"); + GST_WARNING_OBJECT (tag, "No tags found"); buffer = gst_buffer_new_and_alloc (12); if (buffer == NULL) { GST_ELEMENT_ERROR (tag, CORE, TOO_LAZY, (NULL), @@ -501,6 +378,7 @@ gst_flac_tag_chain (GstPad * pad, GstData * data) */ buffer = gst_tag_list_to_vorbiscomment_buffer (merged_tags, header, sizeof (header), NULL); + GST_DEBUG_OBJECT (tag, "Writing tags %" GST_PTR_FORMAT, merged_tags); gst_tag_list_free (merged_tags); if (buffer == NULL) { GST_ELEMENT_ERROR (tag, CORE, TAG, (NULL), @@ -539,18 +417,30 @@ gst_flac_tag_chain (GstPad * pad, GstData * data) GST_BUFFER_DATA (buffer)[1] = ((size & 0xFF0000) >> 16); GST_BUFFER_DATA (buffer)[2] = ((size & 0x00FF00) >> 8); GST_BUFFER_DATA (buffer)[3] = (size & 0x0000FF); - gst_pad_push (tag->srcpad, GST_DATA (buffer)); + GST_DEBUG_OBJECT (tag, "pushing %d byte vorbiscomment buffer", + GST_BUFFER_SIZE (buffer)); + gst_buffer_set_caps (buffer, GST_PAD_CAPS (tag->srcpad)); + ret = gst_pad_push (tag->srcpad, buffer); + if (ret != GST_FLOW_OK) { + goto cleanup; + } tag->state = GST_FLAC_TAG_STATE_AUDIO_DATA; } /* The metadata blocks have been read, now we are reading audio data */ if (tag->state == GST_FLAC_TAG_STATE_AUDIO_DATA) { - gst_pad_push (tag->srcpad, GST_DATA (tag->buffer)); - tag->buffer = NULL; + GstBuffer *buffer; + buffer = + gst_adapter_take_buffer (tag->adapter, + gst_adapter_available (tag->adapter)); + gst_buffer_set_caps (buffer, GST_PAD_CAPS (tag->srcpad)); + ret = gst_pad_push (tag->srcpad, buffer); } cleanup: gst_object_unref (tag); + + return ret; } @@ -572,17 +462,17 @@ gst_flac_tag_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_PLAYING_TO_PAUSED: break; case GST_STATE_CHANGE_PAUSED_TO_READY: - if (tag->buffer) { - gst_buffer_unref (tag->buffer); - tag->buffer = NULL; - } + gst_adapter_clear (tag->adapter); if (tag->vorbiscomment) { gst_buffer_unref (tag->vorbiscomment); tag->vorbiscomment = NULL; } if (tag->tags) { gst_tag_list_free (tag->tags); + tag->tags = NULL; } + tag->metadata_block_size = 0; + tag->metadata_last_block = FALSE; tag->state = GST_FLAC_TAG_STATE_INIT; break; case GST_STATE_CHANGE_READY_TO_NULL: diff --git a/ext/flac/gstflactag.h b/ext/flac/gstflactag.h index 5107d1c319..a6f90f5e23 100644 --- a/ext/flac/gstflactag.h +++ b/ext/flac/gstflactag.h @@ -1,6 +1,78 @@ +/* GStreamer + * Copyright (C) 2003 Christophe Fergeau + * Copyright (C) 2008 Jonathan Matthew + * Copyright (C) 2008 Sebastian Dröge + * + * gstflactag.c: plug-in for reading/modifying vorbis comments in flac files + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + #ifndef GST_FLAC_TAG_H #define GST_FLAC_TAG_H +#include +#include + +#define GST_TYPE_FLAC_TAG (gst_flac_tag_get_type()) +#define GST_FLAC_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FLAC_TAG, GstFlacTag)) +#define GST_FLAC_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FLAC_TAG, GstFlacTag)) +#define GST_IS_FLAC_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FLAC_TAG)) +#define GST_IS_FLAC_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FLAC_TAG)) + +typedef struct _GstFlacTag GstFlacTag; +typedef struct _GstFlacTagClass GstFlacTagClass; + +typedef enum +{ + GST_FLAC_TAG_STATE_INIT, + GST_FLAC_TAG_STATE_METADATA_BLOCKS, + GST_FLAC_TAG_STATE_METADATA_NEXT_BLOCK, + GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK, + GST_FLAC_TAG_STATE_VC_METADATA_BLOCK, + GST_FLAC_TAG_STATE_ADD_VORBIS_COMMENT, + GST_FLAC_TAG_STATE_AUDIO_DATA +} +GstFlacTagState; + +struct _GstFlacTag +{ + GstElement element; + + /* < private > */ + + /* pads */ + GstPad *sinkpad; + GstPad *srcpad; + + GstFlacTagState state; + + GstAdapter *adapter; + GstBuffer *vorbiscomment; + GstTagList *tags; + + guint metadata_block_size; + gboolean metadata_last_block; +}; + +struct _GstFlacTagClass +{ + GstElementClass parent_class; +}; + GType gst_flac_tag_get_type (void); #endif /* GST_FLAC_TAG_H */