ext/flac/: Port flactag to 0.10, add documentation for it and clean it up a bit.

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.
This commit is contained in:
Jonathan Matthew 2008-08-06 15:34:55 +00:00 committed by Sebastian Dröge
parent dfd580b207
commit 8ced1b35ff
16 changed files with 499 additions and 459 deletions

View file

@ -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:

View 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 \

View 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" />

View file

@ -538,6 +538,34 @@ gst_flac_dec_get_type
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>

View 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
GstImplementsInterface
GstColorBalance
GstTuner
GstVideoOrientation
GstPropertyProbe
GstImplementsInterface
GstMixer
GstTagSetter
GstTuner
GstColorBalance
GstVideoOrientation

View 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
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

View file

@ -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

View 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>
@ -16,18 +16,18 @@
<description>Decodes FLAC lossless audio streams</description>
<author>Wim Taymans &lt;wim@fluendo.com&gt;</author>
<pads>
<caps>
<name>src</name>
<direction>source</direction>
<presence>always</presence>
<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>sink</name>
<direction>sink</direction>
<presence>always</presence>
<details>audio/x-flac</details>
</caps>
<caps>
<name>src</name>
<direction>source</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>
</caps>
</pads>
</element>
<element>
@ -36,6 +36,27 @@
<class>Codec/Encoder/Audio</class>
<description>Encodes audio with the FLAC lossless audio encoder</description>
<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>
@ -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>

View 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

View 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 ();

View 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");
}

View 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

View 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");

View file

@ -45,6 +45,8 @@ typedef struct _GstFlacEncClass GstFlacEncClass;
struct _GstFlacEnc {
GstElement element;
/* < private > */
GstPad *sinkpad;
GstPad *srcpad;

View 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
*
@ -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).
*
* <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 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 <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;
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:

View 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 */