ext/flac/: Port flactag to 0.10, add documentation for it and clean it up a bit.
authorJonathan Matthew <notverysmart@gmail.com>
Wed, 6 Aug 2008 15:34:55 +0000 (15:34 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Wed, 6 Aug 2008 15:34:55 +0000 (15:34 +0000)
Original commit message from CVS:
Based on a patch by: Jonathan Matthew <notverysmart at gmail dot com>
* 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.

16 files changed:
ChangeLog
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/Makefile.am
ext/flac/gstflac.c
ext/flac/gstflacdec.c
ext/flac/gstflacdec.h
ext/flac/gstflacenc.c
ext/flac/gstflacenc.h
ext/flac/gstflactag.c
ext/flac/gstflactag.h

index 17664d4..3ed39f6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2008-08-06  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
+
+       Based on a patch by: Jonathan Matthew <notverysmart at gmail dot com>
+
+       * 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  <ensonic@users.sf.net>
 
        * gst/qtdemux/qtdemux.c:
index 2eebe76..b5cb41a 100644 (file)
@@ -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 \
index f54d133..72b54c5 100644 (file)
@@ -46,6 +46,8 @@
     <xi:include href="xml/element-equalizer-nbands.xml" />
     <xi:include href="xml/element-esdsink.xml" />
     <xi:include href="xml/element-flacdec.xml" />
+    <xi:include href="xml/element-flacenc.xml" />
+    <xi:include href="xml/element-flactag.xml" />
     <xi:include href="xml/element-gamma.xml" />
     <xi:include href="xml/element-gdkpixbufsink.xml" />
     <xi:include href="xml/element-goom.xml" />
index 60b3ba4..712c0c8 100644 (file)
@@ -539,6 +539,34 @@ LEGACY_FLAC
 </SECTION>
 
 <SECTION>
+<FILE>element-flacenc</FILE>
+<TITLE>flacenc</TITLE>
+GstFlacEnc
+<SUBSECTION Standard>
+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
+</SECTION>
+
+<SECTION>
+<FILE>element-flactag</FILE>
+<TITLE>flactag</TITLE>
+GstFlacTag
+<SUBSECTION Standard>
+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
+</SECTION>
+
+<SECTION>
 <FILE>element-gamma</FILE>
 <TITLE>gamma</TITLE>
 GstGamma
index ef19bd5..78d644e 100644 (file)
@@ -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
+  GstPropertyProbe
   GstImplementsInterface
-  GstColorBalance
+  GstMixer
+  GstTagSetter
   GstTuner
+  GstColorBalance
   GstVideoOrientation
-  GstPropertyProbe
-  GstMixer
index 252a2a3..c431d34 100644 (file)
@@ -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
-GstIirEqualizer GstChildProxy
-GstIirEqualizerNBands GstChildProxy
-GstIirEqualizer3Bands GstChildProxy
-GstIirEqualizer10Bands GstChildProxy
-GstVideoMixer GstChildProxy
-GstUDPSrc GstURIHandler
-GstV4l2Src GstImplementsInterface GstColorBalance GstTuner GstVideoOrientation GstPropertyProbe
-GstOssSrc GstImplementsInterface GstMixer
-GstPulseSrc GstImplementsInterface GstMixer
+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
-GstUDPSink GstURIHandler
-GstShout2send GstTagSetter
-GstOssMixerElement GstImplementsInterface GstMixer
+GstV4l2Src GstPropertyProbe GstImplementsInterface GstTuner GstColorBalance GstVideoOrientation
+GstUDPSrc GstURIHandler
+GstPulseMixer GstPropertyProbe GstImplementsInterface GstMixer
+GstFlacEnc GstTagSetter
+GstFlacTag GstTagSetter
+GstIirEqualizer GstChildProxy
+GstIirEqualizerNBands GstChildProxy
+GstIirEqualizer3Bands GstChildProxy
+GstIirEqualizer10Bands GstChildProxy
+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
index a33abde..eb1fa16 100644 (file)
@@ -1,7 +1,7 @@
 GstChildProxy GstObject
-GstTagSetter GstObject GstElement
 GstImplementsInterface GstObject GstElement
-GstColorBalance GstObject GstImplementsInterface GstElement
+GstMixer GstObject GstImplementsInterface GstElement
+GstTagSetter GstObject GstElement
 GstTuner GstObject GstImplementsInterface GstElement
+GstColorBalance GstObject GstImplementsInterface GstElement
 GstVideoOrientation GstObject GstImplementsInterface GstElement
-GstMixer GstObject GstImplementsInterface GstElement
index 616fbb5..ab534c1 100644 (file)
@@ -3,10 +3,10 @@
   <description>The FLAC Lossless compressor Codec</description>
   <filename>../../ext/flac/.libs/libgstflac.so</filename>
   <basename>libgstflac.so</basename>
-  <version>0.10.9</version>
+  <version>0.10.9.1</version>
   <license>LGPL</license>
   <source>gst-plugins-good</source>
-  <package>GStreamer Good Plug-ins source release</package>
+  <package>GStreamer Good Plug-ins CVS/prerelease</package>
   <origin>Unknown package origin</origin>
   <elements>
     <element>
       <author>Wim Taymans &lt;wim@fluendo.com&gt;</author>
       <pads>
         <caps>
-          <name>sink</name>
-          <direction>sink</direction>
+          <name>src</name>
+          <direction>source</direction>
           <presence>always</presence>
-          <details>audio/x-flac</details>
+          <details>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 ]</details>
         </caps>
         <caps>
-          <name>src</name>
-          <direction>source</direction>
+          <name>sink</name>
+          <direction>sink</direction>
           <presence>always</presence>
-          <details>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 ]</details>
+          <details>audio/x-flac</details>
         </caps>
       </pads>
     </element>
       <author>Wim Taymans &lt;wim.taymans@chello.be&gt;</author>
       <pads>
         <caps>
+          <name>sink</name>
+          <direction>sink</direction>
+          <presence>always</presence>
+          <details>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 ]</details>
+        </caps>
+        <caps>
+          <name>src</name>
+          <direction>source</direction>
+          <presence>always</presence>
+          <details>audio/x-flac</details>
+        </caps>
+      </pads>
+    </element>
+    <element>
+      <name>flactag</name>
+      <longname>FLAC tagger</longname>
+      <class>Formatter/Metadata</class>
+      <description>Rewrite tags in a FLAC file</description>
+      <author>Christophe Fergeau &lt;teuf@gnome.org&gt;</author>
+      <pads>
+        <caps>
           <name>src</name>
           <direction>source</direction>
           <presence>always</presence>
@@ -47,7 +68,7 @@
           <name>sink</name>
           <direction>sink</direction>
           <presence>always</presence>
-          <details>audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]</details>
+          <details>audio/x-flac</details>
         </caps>
       </pads>
     </element>
index 2723680..0e7d41a 100644 (file)
@@ -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
index d07ec47..7d76a41 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "gstflacenc.h"
 #include "gstflacdec.h"
-/* #include "gstflactag.h" */
+#include "gstflactag.h"
 
 #include <gst/tag/tag.h>
 #include <gst/gst-i18n-plugin.h>
@@ -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 ();
 
index 7b8e381..66d6c14 100644 (file)
@@ -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 <wim@fluendo.com>");
-
-
 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 <wim@fluendo.com>");
 
   GST_DEBUG_CATEGORY_INIT (flacdec_debug, "flacdec", 0, "flac decoder");
 }
index b68986d..100c4e0 100644 (file)
@@ -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
index 1a2a34b..1e29343 100644 (file)
@@ -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 <wim.taymans@chello.be>");
-
 #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 <wim.taymans@chello.be>");
 
   GST_DEBUG_CATEGORY_INIT (flacenc_debug, "flacenc", 0,
       "Flac encoding element");
index 016a56b..1c6a6c6 100644 (file)
@@ -45,6 +45,8 @@ typedef struct _GstFlacEncClass GstFlacEncClass;
 struct _GstFlacEnc {
   GstElement     element;
 
+  /* < private > */
+
   GstPad        *sinkpad;
   GstPad        *srcpad;
 
index 247e1de..d7ca61c 100644 (file)
@@ -1,6 +1,7 @@
-
 /* GStreamer
  * Copyright (C) 2003 Christophe Fergeau <teuf@gnome.org>
+ * Copyright (C) 2008 Jonathan Matthew <jonathan@d14n.org>
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
  *
  * gstflactag.c: plug-in for reading/modifying vorbis comments in flac files
  *
  * 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).
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * 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.
+ * </refsect2>
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+
+#include <gst/gst.h>
 #include <gst/gsttagsetter.h>
+#include <gst/base/gstadapter.h>
 #include <gst/tag/tag.h>
 #include <string.h>
 
-#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 <teuf@gnome.org>");
+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 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_dispose (GObject * object);
 
-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;
-
-  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);
+  static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
 
-  }
-  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 <teuf@gnome.org>");
 
   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;
-
-    g_assert (tag->metadata_bytes_remaining != 0);
+    GstBuffer *metadata_buffer;
 
-    bytes_to_push = min (tag->metadata_bytes_remaining,
-        GST_BUFFER_SIZE (tag->buffer));
+    if (gst_adapter_available (tag->adapter) < tag->metadata_block_size)
+      goto cleanup;
 
-    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));
-    } 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;
+      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 {
-      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:
index 5107d1c..a6f90f5 100644 (file)
@@ -1,6 +1,78 @@
+/* GStreamer
+ * Copyright (C) 2003 Christophe Fergeau <teuf@gnome.org>
+ * Copyright (C) 2008 Jonathan Matthew <jonathan@d14n.org>
+ * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * 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 <gst/gst.h>
+#include <gst/base/gstadapter.h>
+
+#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 */