mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-03 14:08:56 +00:00
merge in tagging
Original commit message from CVS: merge in tagging Includes: - gsttag.[ch] - The definition of GstTagList and tag registering/querying - gsttaginterface.[ch] - Interface for elements that can handle setting of tags - updates and merges to gststructure.[ch] and gstvalue.[ch] - testsuite/tags - some tests for tagging - bugfixes - updates to make make distcheck work - updates the version number to 0.7.2.1 Does not include: - including tagging stuff in docs - extensive tests
This commit is contained in:
parent
b4f14a29f6
commit
385b9ee5c4
66 changed files with 4299 additions and 562 deletions
|
@ -3,7 +3,7 @@ AC_CANONICAL_TARGET([])
|
|||
|
||||
dnl when going to/from release please set the nano (fourth number) right !
|
||||
dnl releases only do Wall, cvs and prerelease does Werror too
|
||||
AS_VERSION(gstreamer, GST_VERSION, 0, 7, 1, 1, GST_CVS="no", GST_CVS="yes")
|
||||
AS_VERSION(gstreamer, GST_VERSION, 0, 7, 2, 1, GST_CVS="no", GST_CVS="yes")
|
||||
|
||||
if test x$program_suffix = xNONE ; then
|
||||
program_suffix=-$GST_VERSION_MAJOR.$GST_VERSION_MINOR
|
||||
|
@ -615,6 +615,7 @@ testsuite/indexers/Makefile
|
|||
testsuite/parse/Makefile
|
||||
testsuite/plugin/Makefile
|
||||
testsuite/refcounting/Makefile
|
||||
testsuite/tags/Makefile
|
||||
testsuite/threads/Makefile
|
||||
examples/Makefile
|
||||
examples/autoplug/Makefile
|
||||
|
@ -630,15 +631,19 @@ examples/queue/Makefile
|
|||
examples/queue2/Makefile
|
||||
examples/queue3/Makefile
|
||||
examples/queue4/Makefile
|
||||
examples/retag/Makefile
|
||||
examples/thread/Makefile
|
||||
examples/typefind/Makefile
|
||||
examples/xml/Makefile
|
||||
tools/Makefile
|
||||
docs/Makefile
|
||||
docs/faq/Makefile
|
||||
docs/gst/Makefile
|
||||
docs/libs/Makefile
|
||||
docs/manual/Makefile
|
||||
docs/plugins/Makefile
|
||||
docs/plugins/gstreamer-plugins.types
|
||||
docs/pwg/Makefile
|
||||
docs/xsl/Makefile
|
||||
docs/version.entities
|
||||
pkgconfig/Makefile
|
||||
|
|
1
docs/.gitignore
vendored
1
docs/.gitignore
vendored
|
@ -5,3 +5,4 @@ Makefile.in
|
|||
*.la
|
||||
.deps
|
||||
.libs
|
||||
version.entities
|
||||
|
|
|
@ -6,7 +6,7 @@ SUBDIRS_PLUGINS =
|
|||
endif
|
||||
|
||||
if BUILD_DOCS
|
||||
SUBDIRS_DOCS = gst libs
|
||||
SUBDIRS_DOCS = faq manual pwg gst libs
|
||||
else
|
||||
SUBDIRS_DOCS =
|
||||
endif
|
||||
|
|
1
docs/gst/.gitignore
vendored
1
docs/gst/.gitignore
vendored
|
@ -12,6 +12,7 @@ gstreamer-unused.txt
|
|||
gstreamer-undocumented.txt
|
||||
gstreamer-decl-list.txt
|
||||
gstreamer-decl.txt
|
||||
gstreamer-presed-scan.c
|
||||
gstreamer-scan.c
|
||||
gstreamer-scan
|
||||
gstreamer.args
|
||||
|
|
|
@ -99,6 +99,14 @@ The autoplug object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstAutoplug::new-object ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstautoplug: the object which received the signal.
|
||||
@arg1:
|
||||
|
||||
<!-- ##### ENUM GstAutoplugFlags ##### -->
|
||||
<para>
|
||||
The type of the autoplugger.
|
||||
|
@ -141,11 +149,3 @@ The type of the autoplugger.
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstAutoplug::new-object ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstautoplug: the object which received the signal.
|
||||
@arg1:
|
||||
|
||||
|
|
|
@ -72,6 +72,34 @@ The GstBin object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstBin::element-added ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@arg1: the element that was added to the bin
|
||||
|
||||
<!-- ##### SIGNAL GstBin::element-removed ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@arg1: the element that was removed from the bin
|
||||
|
||||
<!-- ##### SIGNAL GstBin::iterate ##### -->
|
||||
<para>
|
||||
This signal is emitted when a bin iterates, either automatically or
|
||||
due to a #gst_bin_iterate() call. The return value is used to
|
||||
determine if the object method handler processed any data.
|
||||
In most normal cases, a user-provided signal handler should return
|
||||
FALSE.
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@Returns: TRUE if the state of the bin was advanced.
|
||||
|
||||
<!-- ##### USER_FUNCTION GstBinPrePostIterateFunction ##### -->
|
||||
<para>
|
||||
The signature of the callback for the post and pre iterate function as set with
|
||||
|
@ -224,31 +252,3 @@ gst_bin_set_pre_iterate_function() and gst_bin_set_post_iterate_function().
|
|||
@clock:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstBin::element-added ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@arg1: the element that was added to the bin
|
||||
|
||||
<!-- ##### SIGNAL GstBin::element-removed ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@arg1: the element that was removed from the bin
|
||||
|
||||
<!-- ##### SIGNAL GstBin::iterate ##### -->
|
||||
<para>
|
||||
This signal is emitted when a bin iterates, either automatically or
|
||||
due to a #gst_bin_iterate() call. The return value is used to
|
||||
determine if the object method handler processed any data.
|
||||
In most normal cases, a user-provided signal handler should return
|
||||
FALSE.
|
||||
</para>
|
||||
|
||||
@gstbin: the object which received the signal.
|
||||
@Returns: TRUE if the state of the bin was advanced.
|
||||
|
||||
|
|
|
@ -262,6 +262,7 @@ The basic structure of a buffer.
|
|||
@timestamp:
|
||||
@duration:
|
||||
@offset:
|
||||
@offset_end:
|
||||
@pool:
|
||||
@pool_private:
|
||||
|
||||
|
|
|
@ -406,24 +406,6 @@ The name used for tracing
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_caps_set_type_id ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@caps:
|
||||
@type_id:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_caps_get_type_id ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@caps:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_caps_set_mime ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -235,6 +235,16 @@ The GstClock object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### ARG GstClock:max-diff ##### -->
|
||||
<para>
|
||||
Maximum allowed diff for clock sync requests against the real time.
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstClock:stats ##### -->
|
||||
<para>
|
||||
Boolean property to activate stat generation on the clock.
|
||||
</para>
|
||||
|
||||
<!-- ##### FUNCTION gst_clock_set_speed ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -402,13 +412,3 @@ The GstClock object
|
|||
@id:
|
||||
|
||||
|
||||
<!-- ##### ARG GstClock:max-diff ##### -->
|
||||
<para>
|
||||
Maximum allowed diff for clock sync requests against the real time.
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstClock:stats ##### -->
|
||||
<para>
|
||||
Boolean property to activate stat generation on the clock.
|
||||
</para>
|
||||
|
||||
|
|
|
@ -108,13 +108,6 @@ If this is defined, the <link linkend="gstreamer-gstinfo">debugging subsystem
|
|||
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_DISABLE_TYPEFIND ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_DISABLE_URI ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -71,6 +71,58 @@ The element object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstElement::eos ##### -->
|
||||
<para>
|
||||
Signal emited when the element goes to PAUSED due to an end-of-stream
|
||||
condition.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
|
||||
<!-- ##### SIGNAL GstElement::error ##### -->
|
||||
<para>
|
||||
Is triggered whenever an error occured.
|
||||
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the error message
|
||||
@arg2:
|
||||
|
||||
<!-- ##### SIGNAL GstElement::found-tag ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
|
||||
<!-- ##### SIGNAL GstElement::new-pad ##### -->
|
||||
<para>
|
||||
Is triggered whenever a new pad is added to an element.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the new pad that was added
|
||||
|
||||
<!-- ##### SIGNAL GstElement::pad-removed ##### -->
|
||||
<para>
|
||||
Is triggered whenever a pad has been removed from the element.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: The pad that was removed.
|
||||
|
||||
<!-- ##### SIGNAL GstElement::state-change ##### -->
|
||||
<para>
|
||||
Is triggered whenever the state of an element changes.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the new state of the object
|
||||
@arg2:
|
||||
|
||||
<!-- ##### MACRO gst_element_get_name ##### -->
|
||||
<para>
|
||||
Gets the name of the element.
|
||||
|
@ -880,14 +932,6 @@ Queries if the Element is decoupled.
|
|||
@obj: a #GstElement to query
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_IS_EOS ##### -->
|
||||
<para>
|
||||
Query wether this element is in the End Of Stream state.
|
||||
</para>
|
||||
|
||||
@obj: a #GstElement to query
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_IS_EVENT_AWARE ##### -->
|
||||
<para>
|
||||
Query wether this element can handle events.
|
||||
|
@ -971,46 +1015,3 @@ Helper macro to create query type functions
|
|||
@...: list of query types.
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstElement::eos ##### -->
|
||||
<para>
|
||||
Signal emited when the element goes to PAUSED due to an end-of-stream
|
||||
condition.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
|
||||
<!-- ##### SIGNAL GstElement::error ##### -->
|
||||
<para>
|
||||
Is triggered whenever an error occured.
|
||||
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the error message
|
||||
@arg2:
|
||||
|
||||
<!-- ##### SIGNAL GstElement::new-pad ##### -->
|
||||
<para>
|
||||
Is triggered whenever a new pad is added to an element.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the new pad that was added
|
||||
|
||||
<!-- ##### SIGNAL GstElement::pad-removed ##### -->
|
||||
<para>
|
||||
Is triggered whenever a pad has been removed from the element.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: The pad that was removed.
|
||||
|
||||
<!-- ##### SIGNAL GstElement::state-change ##### -->
|
||||
<para>
|
||||
Is triggered whenever the state of an element changes.
|
||||
</para>
|
||||
|
||||
@gstelement: the object which received the signal.
|
||||
@arg1: the new state of the object
|
||||
@arg2:
|
||||
|
||||
|
|
|
@ -62,22 +62,8 @@ describes the element, mostly for the benefit of editors.
|
|||
|
||||
@longname:
|
||||
@klass:
|
||||
@license:
|
||||
@description:
|
||||
@version:
|
||||
@author:
|
||||
@copyright:
|
||||
|
||||
<!-- ##### FUNCTION gst_element_factory_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@name:
|
||||
@type:
|
||||
@details:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_element_factory_find ##### -->
|
||||
<para>
|
||||
|
@ -88,15 +74,6 @@ describes the element, mostly for the benefit of editors.
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_element_factory_add_pad_template ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@elementfactory:
|
||||
@templ:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_element_factory_can_src_caps ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -137,51 +114,3 @@ describes the element, mostly for the benefit of editors.
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_element_factory_make_or_warn ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@factoryname:
|
||||
@name:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### MACRO gst_element_factory_set_rank ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@factory:
|
||||
@rank:
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_RANK_MARGINAL ##### -->
|
||||
<para>
|
||||
The element is only marginally usefull for autoplugging
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_RANK_NONE ##### -->
|
||||
<para>
|
||||
The plugin may not be used in autoplugging
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_RANK_PRIMARY ##### -->
|
||||
<para>
|
||||
The plugin is well suited for autoplugging
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_RANK_SECONDARY ##### -->
|
||||
<para>
|
||||
The plugin is suited for autoplugging but only as a second
|
||||
candidate.
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ The different major types of events.
|
|||
@GST_EVENT_INTERRUPT: mainly used by _get based elements when they were interrupted
|
||||
while waiting for a buffer.
|
||||
@GST_EVENT_NAVIGATION:
|
||||
@GST_EVENT_TAG:
|
||||
|
||||
<!-- ##### MACRO GST_EVENT_TYPE ##### -->
|
||||
<para>
|
||||
|
|
|
@ -209,6 +209,19 @@ The GstIndex object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstIndex::entry-added ##### -->
|
||||
<para>
|
||||
Is emited when a new entry is added to the index.
|
||||
</para>
|
||||
|
||||
@gstindex: the object which received the signal.
|
||||
@arg1: The entry added to the index.
|
||||
|
||||
<!-- ##### ARG GstIndex:resolver ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### FUNCTION gst_index_new ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -401,16 +414,3 @@ The GstIndex object
|
|||
@id:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstIndex::entry-added ##### -->
|
||||
<para>
|
||||
Is emited when a new entry is added to the index.
|
||||
</para>
|
||||
|
||||
@gstindex: the object which received the signal.
|
||||
@arg1: The entry added to the index.
|
||||
|
||||
<!-- ##### ARG GstIndex:resolver ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
|
|
@ -233,21 +233,6 @@ default. If you want to define a default category, do it like this:
|
|||
@Varargs:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_debug_logv ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@category:
|
||||
@level:
|
||||
@file:
|
||||
@function:
|
||||
@line:
|
||||
@object:
|
||||
@format:
|
||||
@args:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_debug_log_default ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -40,6 +40,47 @@ The GstObject
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstObject::deep-notify ##### -->
|
||||
<para>
|
||||
The deep notify signal is used to be notified of property changes.
|
||||
it is typically attached to the toplevel bin to receive notifications
|
||||
from all the elements contained in that bin.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the object that originated the signal
|
||||
@arg2: the property that changed
|
||||
|
||||
<!-- ##### SIGNAL GstObject::object-saved ##### -->
|
||||
<para>
|
||||
Is trigered whenever a new object is saved to XML. You can connect to
|
||||
this signal to insert custom XML tags into the core XML.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the xmlNodePtr of the parent node
|
||||
|
||||
<!-- ##### SIGNAL GstObject::parent-set ##### -->
|
||||
<para>
|
||||
Is emitted when the parent of an object is set.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the new parent
|
||||
|
||||
<!-- ##### SIGNAL GstObject::parent-unset ##### -->
|
||||
<para>
|
||||
Is emitted when the parent of an object is unset.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the old parent
|
||||
|
||||
<!-- ##### ARG GstObject:name ##### -->
|
||||
<para>
|
||||
The name of the object
|
||||
</para>
|
||||
|
||||
<!-- ##### MACRO GST_FLAGS ##### -->
|
||||
<para>
|
||||
This macro returns the entire set of flags for the object.
|
||||
|
@ -290,44 +331,3 @@ Check if the object has been destroyed.
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstObject::deep-notify ##### -->
|
||||
<para>
|
||||
The deep notify signal is used to be notified of property changes.
|
||||
it is typically attached to the toplevel bin to receive notifications
|
||||
from all the elements contained in that bin.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the object that originated the signal
|
||||
@arg2: the property that changed
|
||||
|
||||
<!-- ##### SIGNAL GstObject::object-saved ##### -->
|
||||
<para>
|
||||
Is trigered whenever a new object is saved to XML. You can connect to
|
||||
this signal to insert custom XML tags into the core XML.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the xmlNodePtr of the parent node
|
||||
|
||||
<!-- ##### SIGNAL GstObject::parent-set ##### -->
|
||||
<para>
|
||||
Is emitted when the parent of an object is set.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the new parent
|
||||
|
||||
<!-- ##### SIGNAL GstObject::parent-unset ##### -->
|
||||
<para>
|
||||
Is emitted when the parent of an object is unset.
|
||||
</para>
|
||||
|
||||
@gstobject: the object which received the signal.
|
||||
@arg1: the old parent
|
||||
|
||||
<!-- ##### ARG GstObject:name ##### -->
|
||||
<para>
|
||||
The name of the object
|
||||
</para>
|
||||
|
||||
|
|
|
@ -87,6 +87,15 @@ The padtemplate object.
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstPadTemplate::pad-created ##### -->
|
||||
<para>
|
||||
This signal is fired when an element creates a pad from this
|
||||
template.
|
||||
</para>
|
||||
|
||||
@gstpadtemplate: the object which received the signal.
|
||||
@arg1: The pad that was created.
|
||||
|
||||
<!-- ##### ENUM GstPadTemplateFlags ##### -->
|
||||
<para>
|
||||
Flags for the padtemplate
|
||||
|
@ -199,12 +208,3 @@ Check if the properties of the padtemplate are fixed
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstPadTemplate::pad-created ##### -->
|
||||
<para>
|
||||
This signal is fired when an element creates a pad from this
|
||||
template.
|
||||
</para>
|
||||
|
||||
@gstpadtemplate: the object which received the signal.
|
||||
@arg1: The pad that was created.
|
||||
|
||||
|
|
|
@ -56,20 +56,19 @@ The plugin loading errors
|
|||
|
||||
@GST_PLUGIN_ERROR_MODULE: The plugin could not be loaded
|
||||
@GST_PLUGIN_ERROR_DEPENDENCIES: The plugin has unresolved dependencies
|
||||
@GST_PLUGIN_ERROR_NAME_MISMATCH:
|
||||
|
||||
<!-- ##### STRUCT GstPlugin ##### -->
|
||||
<para>
|
||||
The plugin object
|
||||
</para>
|
||||
|
||||
@name:
|
||||
@longname:
|
||||
@desc:
|
||||
@filename:
|
||||
@features:
|
||||
@numfeatures:
|
||||
@manager:
|
||||
@module:
|
||||
@init_called:
|
||||
|
||||
<!-- ##### USER_FUNCTION GstPluginInitFunc ##### -->
|
||||
<para>
|
||||
|
@ -77,9 +76,10 @@ A plugin should provide a pointer to a function of this type in the plugin_desc
|
|||
It will be called by the loader at statup.
|
||||
</para>
|
||||
|
||||
@module: The <classname>GModule</classname> it was loaded from
|
||||
@plugin: The plugin object that can be used to register stuff for this plugin.
|
||||
@Returns: A boolean indicating success or failure.
|
||||
<!-- # Unused Parameters # -->
|
||||
@module: The <classname>GModule</classname> it was loaded from
|
||||
|
||||
|
||||
<!-- ##### STRUCT GstPluginDesc ##### -->
|
||||
|
@ -91,50 +91,14 @@ loaded will use this variable to initialize the plugin.
|
|||
@major_version: The minor version of the gstreamer library this plugin was created with
|
||||
@minor_version: The minor version of the gstreamer library this plugin was created with
|
||||
@name: The name of the plugin
|
||||
@description:
|
||||
@plugin_init: The init function of this plugin.
|
||||
|
||||
<!-- ##### MACRO GST_PLUGIN_DESC ##### -->
|
||||
<para>
|
||||
A handy macro to define a plugin description. This macro handles with all the issues
|
||||
involved with the different linking methods for this plugin.
|
||||
</para>
|
||||
|
||||
@major: The major version of GStreamer this plugin was compiled against.
|
||||
@minor: The minor version of GStreamer this plugin was compiled against.
|
||||
@name: The name of the plugin.
|
||||
@init: The init function of this plugin.
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_PLUGIN_DESC_DYNAMIC ##### -->
|
||||
<para>
|
||||
The macro used to define dynamically loaded plugins.
|
||||
</para>
|
||||
|
||||
@major: The major version of GStreamer this plugin was compiled against.
|
||||
@minor: The minor version of GStreamer this plugin was compiled against.
|
||||
@name: The name of the plugin.
|
||||
@init: The init function of this plugin.
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_PLUGIN_DESC_STATIC ##### -->
|
||||
<para>
|
||||
A macro used to define a statically linked plugin.
|
||||
</para>
|
||||
|
||||
@major: The major version of GStreamer this plugin was compiled against.
|
||||
@minor: The minor version of GStreamer this plugin was compiled against.
|
||||
@name: The name of the plugin.
|
||||
@init: The init function of this plugin.
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filename:
|
||||
@Returns:
|
||||
|
||||
@plugin_exit:
|
||||
@version:
|
||||
@license:
|
||||
@copyright:
|
||||
@package:
|
||||
@origin:
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_set_name ##### -->
|
||||
<para>
|
||||
|
@ -163,15 +127,6 @@ A macro used to define a statically linked plugin.
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_set_longname ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@plugin:
|
||||
@longname:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_get_filename ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -210,16 +165,6 @@ A macro used to define a statically linked plugin.
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_load_plugin ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@plugin:
|
||||
@error:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_unload_plugin ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -1056,27 +1056,6 @@ Cache time and byteoffsets.
|
|||
GstTimeCache
|
||||
|
||||
|
||||
<!-- ##### SECTION ./tmpl/gsttypefind.sgml:Long_Description ##### -->
|
||||
<para>
|
||||
This element can be added to the pipeline and will notify the listener of
|
||||
the detected mime type of the stream. It is used in autoplugging.
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### SECTION ./tmpl/gsttypefind.sgml:See_Also ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### SECTION ./tmpl/gsttypefind.sgml:Short_Description ##### -->
|
||||
Detect the mime type of a media stream
|
||||
|
||||
|
||||
<!-- ##### SECTION ./tmpl/gsttypefind.sgml:Title ##### -->
|
||||
GstTypeFind
|
||||
|
||||
|
||||
<!-- ##### SECTION ./tmpl/gsttypes.sgml:Long_Description ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -1835,6 +1814,12 @@ to the current function, i.e. "('element')"
|
|||
@format: printf-style format string
|
||||
@args...: printf arguments
|
||||
|
||||
<!-- ##### MACRO GST_DISABLE_TYPEFIND ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_DISKSRC ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -1898,6 +1883,13 @@ Queries whether the cothread holding this element needs to be stopped.
|
|||
|
||||
@obj: The element to query
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_IS_EOS ##### -->
|
||||
<para>
|
||||
Query wether this element is in the End Of Stream state.
|
||||
</para>
|
||||
|
||||
@obj: a #GstElement to query
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_IS_MULTI_IN ##### -->
|
||||
<para>
|
||||
Query whether this object has multiple input pads.
|
||||
|
@ -1906,6 +1898,31 @@ Query whether this object has multiple input pads.
|
|||
|
||||
@obj: Element to query for multiple input pads.
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_RANK_MARGINAL ##### -->
|
||||
<para>
|
||||
The element is only marginally usefull for autoplugging
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_RANK_NONE ##### -->
|
||||
<para>
|
||||
The plugin may not be used in autoplugging
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_RANK_PRIMARY ##### -->
|
||||
<para>
|
||||
The plugin is well suited for autoplugging
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_ELEMENT_RANK_SECONDARY ##### -->
|
||||
<para>
|
||||
The plugin is suited for autoplugging but only as a second
|
||||
candidate.
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO GST_ESDSINK ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -2769,6 +2786,37 @@ Get the flag indicating the properties are fixed from the template.
|
|||
|
||||
@plugin:
|
||||
|
||||
<!-- ##### MACRO GST_PLUGIN_DESC ##### -->
|
||||
<para>
|
||||
A handy macro to define a plugin description. This macro handles with all the issues
|
||||
involved with the different linking methods for this plugin.
|
||||
</para>
|
||||
|
||||
@major: The major version of GStreamer this plugin was compiled against.
|
||||
@minor: The minor version of GStreamer this plugin was compiled against.
|
||||
@name: The name of the plugin.
|
||||
@init: The init function of this plugin.
|
||||
|
||||
<!-- ##### MACRO GST_PLUGIN_DESC_DYNAMIC ##### -->
|
||||
<para>
|
||||
The macro used to define dynamically loaded plugins.
|
||||
</para>
|
||||
|
||||
@major: The major version of GStreamer this plugin was compiled against.
|
||||
@minor: The minor version of GStreamer this plugin was compiled against.
|
||||
@name: The name of the plugin.
|
||||
@init: The init function of this plugin.
|
||||
|
||||
<!-- ##### MACRO GST_PLUGIN_DESC_STATIC ##### -->
|
||||
<para>
|
||||
A macro used to define a statically linked plugin.
|
||||
</para>
|
||||
|
||||
@major: The major version of GStreamer this plugin was compiled against.
|
||||
@minor: The minor version of GStreamer this plugin was compiled against.
|
||||
@name: The name of the plugin.
|
||||
@init: The init function of this plugin.
|
||||
|
||||
<!-- ##### MACRO GST_PROPS_BOOL_ID ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -5717,6 +5765,15 @@ Query the element for the current mime type
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstXML::object-loaded ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstxml: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
|
||||
<!-- ##### USER_FUNCTION GstXMLRegistryAddPathList ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -7704,6 +7761,14 @@ safely be modified.
|
|||
|
||||
@caps:
|
||||
|
||||
<!-- ##### FUNCTION gst_caps_get_type_id ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@caps:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### FUNCTION gst_caps_list_check_compatibility ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -7741,6 +7806,14 @@ safely be modified.
|
|||
@Returns:
|
||||
@count:
|
||||
|
||||
<!-- ##### FUNCTION gst_caps_set_type_id ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@caps:
|
||||
@type_id:
|
||||
|
||||
<!-- ##### FUNCTION gst_clock_activate ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -7915,6 +7988,20 @@ safely be modified.
|
|||
@data:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### FUNCTION gst_debug_logv ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@category:
|
||||
@level:
|
||||
@file:
|
||||
@function:
|
||||
@line:
|
||||
@object:
|
||||
@format:
|
||||
@args:
|
||||
|
||||
<!-- ##### FUNCTION gst_debug_print_stack_trace ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -7998,6 +8085,14 @@ of an element he doesn't need anymore.
|
|||
@a:
|
||||
@b:
|
||||
|
||||
<!-- ##### FUNCTION gst_element_factory_add_pad_template ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@elementfactory:
|
||||
@templ:
|
||||
|
||||
<!-- ##### FUNCTION gst_element_factory_add_sink ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -8054,6 +8149,25 @@ of an element he doesn't need anymore.
|
|||
@parent:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### FUNCTION gst_element_factory_make_or_warn ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@factoryname:
|
||||
@name:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### FUNCTION gst_element_factory_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@name:
|
||||
@type:
|
||||
@details:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### FUNCTION gst_element_factory_register ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -8070,6 +8184,14 @@ of an element he doesn't need anymore.
|
|||
@parent:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### MACRO gst_element_factory_set_rank ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@factory:
|
||||
@rank:
|
||||
|
||||
<!-- ##### FUNCTION gst_element_flags_get_type ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -9294,6 +9416,15 @@ Destroys the pipeline.
|
|||
@name:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_load_plugin ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@plugin:
|
||||
@error:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_load_thyself ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -9308,6 +9439,14 @@ Destroys the pipeline.
|
|||
|
||||
@mime:
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@filename:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_save_thyself ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -9316,6 +9455,14 @@ Destroys the pipeline.
|
|||
@parent:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_set_longname ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@plugin:
|
||||
@longname:
|
||||
|
||||
<!-- ##### FUNCTION gst_plugin_unload_all ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -10040,6 +10187,19 @@ Destroy the scheduler
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_type_find_factory_register ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@plugin:
|
||||
@name:
|
||||
@rank:
|
||||
@func:
|
||||
@extensions:
|
||||
@possible_caps:
|
||||
@data:
|
||||
|
||||
<!-- ##### FUNCTION gst_type_get_sink_to_src ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -34,15 +34,6 @@ The GstThread object
|
|||
</para>
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_thread_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@name:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstThread::shutdown ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -55,3 +46,12 @@ The GstThread object
|
|||
The thread priority
|
||||
</para>
|
||||
|
||||
<!-- ##### FUNCTION gst_thread_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@name:
|
||||
@Returns:
|
||||
|
||||
|
||||
|
|
|
@ -98,17 +98,3 @@ gst_type_find_factory_register()
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_type_find_factory_register ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@plugin:
|
||||
@name:
|
||||
@rank:
|
||||
@func:
|
||||
@extensions:
|
||||
@possible_caps:
|
||||
@data:
|
||||
|
||||
|
||||
|
|
|
@ -105,25 +105,3 @@ All GstElements can be serialized to an XML presentation and subsequently loaded
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### SIGNAL GstXML::object-loaded ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@:
|
||||
@:
|
||||
@:
|
||||
|
||||
@gstxml: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
|
||||
<!-- ##### SIGNAL GstXML::object-loaded ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@gstxml: the object which received the signal.
|
||||
@arg1:
|
||||
@arg2:
|
||||
|
||||
|
|
13
docs/libs/.gitignore
vendored
13
docs/libs/.gitignore
vendored
|
@ -1,12 +1,15 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.stamp
|
||||
html
|
||||
xml
|
||||
gstreamer-libs-unused.txt
|
||||
gstreamer-libs-undocumented.txt
|
||||
Makefile
|
||||
Makefile.in
|
||||
gstreamer-libs-decl.txt
|
||||
gstreamer-libs-decl-list.txt
|
||||
*.stamp
|
||||
gstreamer-libs-presed-scan.c
|
||||
gstreamer-libs-undocumented.txt
|
||||
gstreamer-libs-unused.txt
|
||||
gstreamer-libs.args
|
||||
gstreamer-libs.hierarchy
|
||||
gstreamer-libs.interfaces
|
||||
gstreamer-libs.prerequisites
|
||||
gstreamer-libs.signals
|
||||
|
|
|
@ -10,13 +10,39 @@ else
|
|||
GST_AUTOPLUG_DIRS = autoplug helloworld2
|
||||
endif
|
||||
|
||||
SUBDIRS = $(GST_AUTOPLUG_DIRS) $(GST_LOADSAVE_DIRS) \
|
||||
helloworld \
|
||||
queue queue2 queue3 queue4 \
|
||||
launch thread plugins mixer cutter pingpong manual
|
||||
SUBDIRS = \
|
||||
helloworld \
|
||||
queue \
|
||||
queue2 \
|
||||
queue3 \
|
||||
queue4 \
|
||||
launch \
|
||||
thread \
|
||||
plugins \
|
||||
mixer \
|
||||
cutter \
|
||||
pingpong \
|
||||
manual \
|
||||
retag \
|
||||
$(GST_LOADSAVE_DIRS) \
|
||||
$(GST_AUTOPLUG_DIRS)
|
||||
|
||||
DIST_SUBDIRS = autoplug \
|
||||
helloworld helloworld2 \
|
||||
queue queue2 queue3 queue4 \
|
||||
launch thread xml plugins typefind mixer cutter pingpong manual
|
||||
|
||||
DIST_SUBDIRS = autoplug \
|
||||
helloworld \
|
||||
helloworld2 \
|
||||
queue \
|
||||
queue2 \
|
||||
queue3 \
|
||||
queue4 \
|
||||
launch \
|
||||
thread \
|
||||
plugins \
|
||||
mixer \
|
||||
cutter \
|
||||
pingpong \
|
||||
manual \
|
||||
xml \
|
||||
typefind \
|
||||
retag
|
||||
|
||||
|
|
2
examples/retag/.gitignore
vendored
Normal file
2
examples/retag/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
retag
|
||||
transcode
|
7
examples/retag/Makefile.am
Normal file
7
examples/retag/Makefile.am
Normal file
|
@ -0,0 +1,7 @@
|
|||
noinst_PROGRAMS = retag transcode
|
||||
|
||||
retag_LDADD = $(GST_LIBS)
|
||||
retag_CFLAGS = $(GST_CFLAGS)
|
||||
|
||||
transcode_LDADD = $(GST_LIBS)
|
||||
transcode_CFLAGS = $(GST_CFLAGS)
|
103
examples/retag/retag.c
Normal file
103
examples/retag/retag.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* This example shows how to use interfaces and the tag subsystem.
|
||||
* It takes an mp3 file as input, and makes an ogg file out of it. While doing
|
||||
* this, it parses the filename and sets artist and title in the ogg file.
|
||||
* It assumes the filename to be "<artist> - <title>.mp3"
|
||||
*
|
||||
* Run the program as "retag <mp3 file>"
|
||||
*
|
||||
* To run this program, you need to have the gst-plugins package (specifically
|
||||
* the vorbis and mad plugins) installed.
|
||||
*/
|
||||
|
||||
/* main header */
|
||||
#include <gst/gst.h>
|
||||
/* and a header we need for the string manipulation */
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *bin, *filesrc, *tag_changer, *filesink;
|
||||
gchar *artist, *title, *ext, *filename;
|
||||
|
||||
/* check that the argument is there */
|
||||
if (argc != 2) {
|
||||
g_print ("usage: %s <mp3 file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* initialize GStreamer */
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
/* parse the mp3 name */
|
||||
artist = strrchr (argv[1], '/');
|
||||
if (artist == NULL)
|
||||
artist = argv[1];
|
||||
artist = g_strdup (artist);
|
||||
ext = strrchr (artist, '.');
|
||||
if (ext) *ext = '\0';
|
||||
title = strstr (artist, " - ");
|
||||
if (title == NULL) {
|
||||
g_print ("The format of the mp3 file is invalid.\n");
|
||||
return 1;
|
||||
}
|
||||
*title = '\0';
|
||||
title += 3;
|
||||
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_pipeline_new ("pipeline");
|
||||
g_assert (bin);
|
||||
|
||||
/* create a file reader */
|
||||
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
||||
g_assert (filesrc);
|
||||
|
||||
/* now it's time to get the tag_changer */
|
||||
tag_changer = gst_element_factory_make ("id3tag", "tag_changer");
|
||||
if (!tag_changer) {
|
||||
g_print ("could not find plugin \"mad\"");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* and a file writer */
|
||||
filesink = gst_element_factory_make ("filesink", "filesink");
|
||||
g_assert (filesink);
|
||||
|
||||
/* set the filenames */
|
||||
filename = g_strdup_printf ("%s.temp", argv[1]); /* easy solution */
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
g_object_set (G_OBJECT (filesink), "location", filename, NULL);
|
||||
|
||||
/* make sure the tag setter uses our stuff
|
||||
(though that should already be default) */
|
||||
gst_tag_setter_set_merge_mode (GST_TAG_SETTER (tag_changer), GST_TAG_MERGE_KEEP);
|
||||
/* set the tagging information */
|
||||
gst_tag_setter_add (GST_TAG_SETTER (tag_changer), GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_ARTIST, artist,
|
||||
GST_TAG_TITLE, title,
|
||||
NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add_many (GST_BIN (bin), filesrc, tag_changer, filesink, NULL);
|
||||
|
||||
/* link the elements */
|
||||
gst_element_link_many (filesrc, tag_changer, filesink, NULL);
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state (bin, GST_STATE_PLAYING);
|
||||
|
||||
while (gst_bin_iterate (GST_BIN (bin)));
|
||||
|
||||
/* stop the bin */
|
||||
gst_element_set_state (bin, GST_STATE_NULL);
|
||||
|
||||
/* rename the file to the correct name and remove the old one */
|
||||
remove (argv[1]);
|
||||
rename (filename, argv[1]);
|
||||
g_free (filename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
106
examples/retag/transcode.c
Normal file
106
examples/retag/transcode.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* This example shows how to use interfaces and the tag subsystem.
|
||||
* It takes an mp3 file as input, and makes an ogg file out of it. While doing
|
||||
* this, it parses the filename and sets artist and title in the ogg file.
|
||||
* It assumes the filename to be "<artist> - <title>.mp3"
|
||||
*
|
||||
* Run the program as "retag <mp3 file>"
|
||||
*
|
||||
* To run this program, you need to have the gst-plugins package (specifically
|
||||
* the vorbis and mad plugins) installed.
|
||||
*/
|
||||
|
||||
/* main header */
|
||||
#include <gst/gst.h>
|
||||
/* and a header we need for the string manipulation */
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *bin, *filesrc, *decoder, *encoder, *filesink;
|
||||
gchar *artist, *title, *ext, *filename;
|
||||
|
||||
/* initialize GStreamer */
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
/* check that the argument is there */
|
||||
if (argc != 2) {
|
||||
g_print ("usage: %s <mp3 file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* parse the mp3 name */
|
||||
artist = strrchr (argv[1], '/');
|
||||
if (artist == NULL)
|
||||
artist = argv[1];
|
||||
artist = g_strdup (artist);
|
||||
ext = strrchr (artist, '.');
|
||||
if (ext) *ext = '\0';
|
||||
title = strstr (artist, " - ");
|
||||
if (title == NULL) {
|
||||
g_print ("The format of the mp3 file is invalid.\n");
|
||||
return 1;
|
||||
}
|
||||
*title = '\0';
|
||||
title += 3;
|
||||
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_pipeline_new ("pipeline");
|
||||
g_assert (bin);
|
||||
|
||||
/* create a file reader */
|
||||
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
||||
g_assert (filesrc);
|
||||
|
||||
/* now it's time to get the decoder */
|
||||
decoder = gst_element_factory_make ("mad", "decode");
|
||||
if (!decoder) {
|
||||
g_print ("could not find plugin \"mad\"");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create the encoder */
|
||||
encoder = gst_element_factory_make ("vorbisenc", "encoder");
|
||||
if (!encoder) {
|
||||
g_print ("cound not find plugin \"vorbisenc\"");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* and a file writer */
|
||||
filesink = gst_element_factory_make ("filesink", "filesink");
|
||||
g_assert (filesink);
|
||||
|
||||
/* set the filenames */
|
||||
filename = g_strdup_printf ("%s.ogg", argv[1]); /* easy solution */
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
g_object_set (G_OBJECT (filesink), "location", filename, NULL);
|
||||
g_free (filename);
|
||||
|
||||
/* make sure the tag setter uses our stuff
|
||||
(though that should already be default) */
|
||||
gst_tag_setter_set_merge_mode (GST_TAG_SETTER (encoder), GST_TAG_MERGE_KEEP);
|
||||
/* set the tagging information */
|
||||
gst_tag_setter_add (GST_TAG_SETTER (encoder), GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_ARTIST, artist,
|
||||
GST_TAG_TITLE, title,
|
||||
NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add_many (GST_BIN (bin), filesrc, decoder, encoder, filesink, NULL);
|
||||
|
||||
/* link the elements */
|
||||
gst_element_link_many (filesrc, decoder, encoder, filesink, NULL);
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state (bin, GST_STATE_PLAYING);
|
||||
|
||||
while (gst_bin_iterate (GST_BIN (bin)));
|
||||
|
||||
/* stop the bin */
|
||||
gst_element_set_state (bin, GST_STATE_NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -114,6 +114,8 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
|
|||
gstscheduler.c \
|
||||
gststructure.c \
|
||||
gstsystemclock.c \
|
||||
gsttag.c \
|
||||
gsttaginterface.c \
|
||||
gstthread.c \
|
||||
gstthreaddummy.c \
|
||||
$(GST_TRACE_SRC) \
|
||||
|
@ -131,6 +133,8 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \
|
|||
|
||||
|
||||
BUILT_SOURCES = gstversion.h gstconfig.h gstmarshal.h gstmarshal.c gstenumtypes.h $(GST_ENUMTYPES_SRC)
|
||||
CLEANFILES = gstmarshal.h gstmarshal.c gstenumtypes.h $(GST_ENUMTYPES_SRC)
|
||||
DISTCLEANFILES = gstversion.h gstconfig.h
|
||||
|
||||
libgstreamer_@GST_MAJORMINOR@_la_CFLAGS = -D_GNU_SOURCE \
|
||||
$(GST_CFLAGS) \
|
||||
|
@ -176,6 +180,8 @@ gst_headers = \
|
|||
gstscheduler.h \
|
||||
gststructure.h \
|
||||
gstsystemclock.h \
|
||||
gsttag.h \
|
||||
gsttaginterface.h \
|
||||
gstthread.h \
|
||||
gsttrace.h \
|
||||
gsttrashstack.h \
|
||||
|
@ -238,12 +244,4 @@ gstenumtypes.c: $(gst_headers)
|
|||
--vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \
|
||||
$^ > gstenumtypes.c
|
||||
|
||||
# Don't want the generated marshal files in the dist
|
||||
dist-hook:
|
||||
rm -f $(distdir)/gstmarshal.c $(distdir)/gstmarshal.h
|
||||
|
||||
# Clean generated files
|
||||
distclean-local:
|
||||
rm -f $(top_builddir)/gst/gstmarshal.c $(top_builddir)/gst/gstmarshal.h
|
||||
|
||||
EXTRA_DIST = ROADMAP
|
||||
|
|
|
@ -537,6 +537,7 @@ init_post (void)
|
|||
_gst_plugin_initialize ();
|
||||
_gst_event_initialize ();
|
||||
_gst_buffer_initialize ();
|
||||
_gst_tag_initialize ();
|
||||
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
if (!_gst_registry_fixed) {
|
||||
|
|
40
gst/gst.h
40
gst/gst.h
|
@ -27,42 +27,44 @@
|
|||
#include <glib.h>
|
||||
#include <popt.h>
|
||||
|
||||
#include <gst/gstversion.h>
|
||||
#include <gst/gstenumtypes.h>
|
||||
#include <gst/gsttypes.h>
|
||||
#include <gst/gstversion.h>
|
||||
|
||||
#include <gst/gstinfo.h>
|
||||
#include <gst/gstobject.h>
|
||||
#include <gst/gstpad.h>
|
||||
#include <gst/gstautoplug.h>
|
||||
#include <gst/gstbin.h>
|
||||
#include <gst/gstbuffer.h>
|
||||
#include <gst/gstbufferpool-default.h>
|
||||
#include <gst/gstcaps.h>
|
||||
#include <gst/gstclock.h>
|
||||
#include <gst/gstcpu.h>
|
||||
#include <gst/gstelement.h>
|
||||
#include <gst/gstbin.h>
|
||||
#include <gst/gstevent.h>
|
||||
#include <gst/gstindex.h>
|
||||
#include <gst/gstinfo.h>
|
||||
#include <gst/gstinterface.h>
|
||||
#include <gst/gstobject.h>
|
||||
#include <gst/gstpad.h>
|
||||
#include <gst/gstpipeline.h>
|
||||
#include <gst/gstthread.h>
|
||||
#include <gst/gsttypefind.h>
|
||||
#include <gst/gstautoplug.h>
|
||||
#include <gst/gstcaps.h>
|
||||
#include <gst/gststructure.h>
|
||||
#include <gst/gstprops.h>
|
||||
#include <gst/gstplugin.h>
|
||||
#include <gst/gstprops.h>
|
||||
#include <gst/gstscheduler.h>
|
||||
#include <gst/gststructure.h>
|
||||
#include <gst/gstsystemclock.h>
|
||||
#include <gst/gsttag.h>
|
||||
#include <gst/gsttaginterface.h>
|
||||
#include <gst/gstthread.h>
|
||||
#include <gst/gsttrace.h>
|
||||
#include <gst/gsttypefind.h>
|
||||
#include <gst/gsturi.h>
|
||||
#include <gst/gsturitype.h>
|
||||
#include <gst/gstutils.h>
|
||||
#include <gst/gsttrace.h>
|
||||
#include <gst/gstxml.h>
|
||||
#include <gst/gstscheduler.h>
|
||||
#include <gst/gstevent.h>
|
||||
#include <gst/gstclock.h>
|
||||
#include <gst/gstsystemclock.h>
|
||||
#include <gst/gstinterface.h>
|
||||
#include <gst/gstvalue.h>
|
||||
#include <gst/gstxml.h>
|
||||
|
||||
#include <gst/gstparse.h>
|
||||
#include <gst/gstregistry.h>
|
||||
#include <gst/gstregistrypool.h>
|
||||
#include <gst/gstenumtypes.h>
|
||||
|
||||
/* API compatibility stuff */
|
||||
#include <gst/gstcompat.h>
|
||||
|
|
|
@ -167,6 +167,7 @@ gst_buffer_default_copy (GstBuffer *buffer)
|
|||
GST_BUFFER_TIMESTAMP (copy) = GST_BUFFER_TIMESTAMP (buffer);
|
||||
GST_BUFFER_DURATION (copy) = GST_BUFFER_DURATION (buffer);
|
||||
GST_BUFFER_OFFSET (copy) = GST_BUFFER_OFFSET (buffer);
|
||||
GST_BUFFER_OFFSET_END (copy) = GST_BUFFER_OFFSET_END (buffer);
|
||||
GST_BUFFER_BUFFERPOOL (copy) = NULL;
|
||||
GST_BUFFER_POOL_PRIVATE (copy) = NULL;
|
||||
|
||||
|
@ -204,6 +205,7 @@ gst_buffer_new (void)
|
|||
GST_BUFFER_TIMESTAMP (newbuf) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_DURATION (newbuf) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET_NONE;
|
||||
GST_BUFFER_OFFSET_END (newbuf) = GST_BUFFER_OFFSET_NONE;
|
||||
GST_BUFFER_BUFFERPOOL (newbuf) = NULL;
|
||||
GST_BUFFER_POOL_PRIVATE (newbuf) = NULL;
|
||||
|
||||
|
@ -335,8 +337,9 @@ gst_buffer_create_sub (GstBuffer *parent, guint offset, guint size)
|
|||
GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
|
||||
}
|
||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||
|
||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;
|
||||
/* make sure nobody overwrites data as it would overwrite in the parent.
|
||||
* data in parent cannot be overwritten because we hold a ref */
|
||||
GST_DATA_FLAG_SET (parent, GST_DATA_READONLY);
|
||||
|
@ -453,13 +456,17 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
|||
/* if we completely merged the two buffers (appended), we can
|
||||
* calculate the duration too. Also make sure we's not messing with
|
||||
* invalid DURATIONS */
|
||||
if (offset == 0 && buf1->size + buf2->size == len &&
|
||||
GST_BUFFER_DURATION_IS_VALID (buf1) &&
|
||||
GST_BUFFER_DURATION_IS_VALID (buf2))
|
||||
{
|
||||
/* add duration */
|
||||
GST_BUFFER_DURATION (newbuf) = GST_BUFFER_DURATION (buf1) +
|
||||
GST_BUFFER_DURATION (buf2);
|
||||
if (offset == 0 && buf1->size + buf2->size == len) {
|
||||
if (GST_BUFFER_DURATION_IS_VALID (buf1) &&
|
||||
GST_BUFFER_DURATION_IS_VALID (buf2)) {
|
||||
/* add duration */
|
||||
GST_BUFFER_DURATION (newbuf) = GST_BUFFER_DURATION (buf1) +
|
||||
GST_BUFFER_DURATION (buf2);
|
||||
}
|
||||
if (GST_BUFFER_OFFSET_END_IS_VALID (buf2)) {
|
||||
/* add offset_end */
|
||||
GST_BUFFER_OFFSET_END (newbuf) = GST_BUFFER_OFFSET_END (buf2);
|
||||
}
|
||||
}
|
||||
|
||||
return newbuf;
|
||||
|
|
|
@ -63,6 +63,7 @@ extern GType _gst_buffer_pool_type;
|
|||
#define GST_BUFFER_DURATION(buf) (GST_BUFFER(buf)->duration)
|
||||
#define GST_BUFFER_FORMAT(buf) (GST_BUFFER(buf)->format)
|
||||
#define GST_BUFFER_OFFSET(buf) (GST_BUFFER(buf)->offset)
|
||||
#define GST_BUFFER_OFFSET_END(buf) (GST_BUFFER(buf)->offset_end)
|
||||
#define GST_BUFFER_BUFFERPOOL(buf) (GST_BUFFER(buf)->pool)
|
||||
#define GST_BUFFER_POOL_PRIVATE(buf) (GST_BUFFER(buf)->pool_private)
|
||||
|
||||
|
@ -72,6 +73,7 @@ extern GType _gst_buffer_pool_type;
|
|||
#define GST_BUFFER_DURATION_IS_VALID(buffer) (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)))
|
||||
#define GST_BUFFER_TIMESTAMP_IS_VALID(buffer) (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)))
|
||||
#define GST_BUFFER_OFFSET_IS_VALID(buffer) (GST_BUFFER_OFFSET (buffer) != GST_BUFFER_OFFSET_NONE)
|
||||
#define GST_BUFFER_OFFSET_END_IS_VALID(buffer) (GST_BUFFER_OFFSET_END (buffer) != GST_BUFFER_OFFSET_NONE)
|
||||
#define GST_BUFFER_MAXSIZE_IS_VALID(buffer) (GST_BUFFER_MAXSIZE (buffer) != GST_BUFFER_MAXSIZE_NONE)
|
||||
|
||||
typedef enum {
|
||||
|
@ -101,8 +103,11 @@ struct _GstBuffer {
|
|||
* for video frames, this could be the number of frames,
|
||||
* for audio data, this could be the number of audio samples,
|
||||
* for file data or compressed data, this could be the number of bytes
|
||||
* offset_end is the last offset contained in the buffer. The format specifies
|
||||
* the meaning of both of them exactly.
|
||||
*/
|
||||
guint64 offset;
|
||||
guint64 offset_end;
|
||||
|
||||
/* this is a pointer to the buffer pool (if any) */
|
||||
GstBufferPool *pool;
|
||||
|
|
|
@ -39,6 +39,8 @@ enum {
|
|||
PAD_REMOVED,
|
||||
ERROR,
|
||||
EOS,
|
||||
FOUND_TAG,
|
||||
/* add more above */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -65,6 +67,7 @@ static void gst_element_dispose (GObject *object);
|
|||
|
||||
static GstElementStateReturn gst_element_change_state (GstElement *element);
|
||||
static void gst_element_error_func (GstElement* element, GstElement *source, gchar *errormsg);
|
||||
static void gst_element_found_tag_func (GstElement* element, GstElement *source, GstTagList *tag_list);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
static xmlNodePtr gst_element_save_thyself (GstObject *object, xmlNodePtr parent);
|
||||
|
@ -127,11 +130,16 @@ gst_element_class_init (GstElementClass *klass)
|
|||
g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
|
||||
gst_marshal_VOID__OBJECT_STRING, G_TYPE_NONE, 2,
|
||||
G_TYPE_OBJECT, G_TYPE_STRING);
|
||||
GST_TYPE_ELEMENT, G_TYPE_STRING);
|
||||
gst_element_signals[EOS] =
|
||||
g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL,
|
||||
G_STRUCT_OFFSET (GstElementClass, eos), NULL, NULL,
|
||||
gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
gst_element_signals[FOUND_TAG] =
|
||||
g_signal_new ("found-tag", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstElementClass, found_tag), NULL, NULL,
|
||||
gst_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2,
|
||||
GST_TYPE_ELEMENT, G_TYPE_POINTER);
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_element_real_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_element_real_get_property);
|
||||
|
@ -145,6 +153,7 @@ gst_element_class_init (GstElementClass *klass)
|
|||
|
||||
klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state);
|
||||
klass->error = GST_DEBUG_FUNCPTR (gst_element_error_func);
|
||||
klass->found_tag = GST_DEBUG_FUNCPTR (gst_element_found_tag_func);
|
||||
klass->padtemplates = NULL;
|
||||
klass->numpadtemplates = 0;
|
||||
|
||||
|
@ -931,7 +940,9 @@ gst_element_remove_pad (GstElement *element, GstPad *pad)
|
|||
/* FIXME: what if someone calls _remove_pad instead of
|
||||
_remove_ghost_pad? */
|
||||
if (GST_IS_REAL_PAD (pad)) {
|
||||
g_return_if_fail (GST_RPAD_PEER (pad) == NULL);
|
||||
if (GST_RPAD_PEER (pad) != NULL) {
|
||||
gst_pad_unlink (pad, GST_PAD (GST_RPAD_PEER (pad)));
|
||||
}
|
||||
}
|
||||
|
||||
/* remove it from the list */
|
||||
|
@ -2924,6 +2935,71 @@ gst_element_set_loop_function (GstElement *element,
|
|||
}
|
||||
}
|
||||
}
|
||||
static inline void
|
||||
gst_element_emit_found_tag (GstElement* element, GstElement *source, GstTagList *tag_list)
|
||||
{
|
||||
gst_object_ref (GST_OBJECT (element));
|
||||
g_signal_emit (element, gst_element_signals[FOUND_TAG], 0, source, tag_list);
|
||||
gst_object_unref (GST_OBJECT (element));
|
||||
}
|
||||
static void
|
||||
gst_element_found_tag_func (GstElement* element, GstElement *source, GstTagList *tag_list)
|
||||
{
|
||||
/* tell the parent */
|
||||
if (GST_OBJECT_PARENT (element)) {
|
||||
GST_CAT_LOG_OBJECT (GST_CAT_EVENT, element, "forwarding tag event to %s",
|
||||
GST_OBJECT_NAME (GST_OBJECT_PARENT (element)));
|
||||
gst_element_emit_found_tag (GST_ELEMENT (GST_OBJECT_PARENT (element)), source, tag_list);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* gst_element_found_tags:
|
||||
* @element: the element that found the tags
|
||||
* @tag_list: the found tags
|
||||
*
|
||||
* This function emits the found_tags signal. This is a recursive signal, so
|
||||
* every parent will emit that signal, too, before this function returns.
|
||||
* Only emit this signal, when you extracted these tags out of the data stream,
|
||||
* not when you handle an event.
|
||||
*/
|
||||
void
|
||||
gst_element_found_tags (GstElement *element, GstTagList *tag_list)
|
||||
{
|
||||
gst_element_emit_found_tag (element, element, tag_list);
|
||||
}
|
||||
/**
|
||||
* gst_element_found_tags_for_pad:
|
||||
* @element: element that found the tag
|
||||
* @pad: src pad the tags correspond to
|
||||
* @timestamp: time the tags were found
|
||||
* @list: the taglist
|
||||
*
|
||||
* This is a convenience routine for tag finding. Most of the time you only
|
||||
* want to push the found tags down one pad, in that case this function is for
|
||||
* you. It takes ownership of the taglist, emits the found-tag signal and pushes
|
||||
* a tag event down the pad.
|
||||
*/
|
||||
void
|
||||
gst_element_found_tags_for_pad (GstElement *element, GstPad *pad, GstClockTime timestamp,
|
||||
GstTagList *list)
|
||||
{
|
||||
GstEvent *tag_event;
|
||||
|
||||
g_return_if_fail (GST_IS_ELEMENT (element));
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC);
|
||||
g_return_if_fail (element == GST_PAD_PARENT (pad));
|
||||
g_return_if_fail (list != NULL);
|
||||
|
||||
tag_event = gst_event_new_tag (list);
|
||||
GST_EVENT_TIMESTAMP (tag_event) = timestamp;
|
||||
gst_element_found_tags (element, gst_event_tag_get_list (tag_event));
|
||||
if (GST_PAD_IS_USABLE (pad)) {
|
||||
gst_pad_push (pad, GST_DATA (tag_event));
|
||||
} else {
|
||||
gst_data_unref (GST_DATA (tag_event));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
gst_element_set_eos_recursive (GstElement *element)
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <gst/gstplugin.h>
|
||||
#include <gst/gstpluginfeature.h>
|
||||
#include <gst/gstindex.h>
|
||||
#include <gst/gsttag.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -137,7 +138,6 @@ typedef enum {
|
|||
} GstElementFlags;
|
||||
|
||||
#define GST_ELEMENT_IS_THREAD_SUGGESTED(obj) (GST_FLAG_IS_SET(obj,GST_ELEMENT_THREAD_SUGGESTED))
|
||||
#define GST_ELEMENT_IS_EOS(obj) (GST_FLAG_IS_SET(obj,GST_ELEMENT_EOS))
|
||||
#define GST_ELEMENT_IS_EVENT_AWARE(obj) (GST_FLAG_IS_SET(obj,GST_ELEMENT_EVENT_AWARE))
|
||||
#define GST_ELEMENT_IS_DECOUPLED(obj) (GST_FLAG_IS_SET(obj,GST_ELEMENT_DECOUPLED))
|
||||
|
||||
|
@ -206,6 +206,7 @@ struct _GstElementClass {
|
|||
void (*pad_removed) (GstElement *element, GstPad *pad);
|
||||
void (*error) (GstElement *element, GstElement *source, gchar *error);
|
||||
void (*eos) (GstElement *element);
|
||||
void (*found_tag) (GstElement *element, GstElement *source, GstTagList *tag_list);
|
||||
|
||||
/* local pointers for get/set */
|
||||
void (*set_property) (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
|
@ -254,7 +255,6 @@ void gst_element_class_set_details (GstElementClass *klass,
|
|||
void gst_element_default_error (GObject *object, GstObject *orig, gchar *error);
|
||||
|
||||
GType gst_element_get_type (void);
|
||||
|
||||
void gst_element_set_loop_function (GstElement *element,
|
||||
GstElementLoopFunction loop);
|
||||
|
||||
|
@ -350,6 +350,10 @@ gboolean gst_element_convert (GstElement *element,
|
|||
GstFormat src_format, gint64 src_value,
|
||||
GstFormat *dest_format, gint64 *dest_value);
|
||||
|
||||
void gst_element_found_tags (GstElement *element, GstTagList *tag_list);
|
||||
void gst_element_found_tags_for_pad (GstElement *element, GstPad *pad, GstClockTime timestamp,
|
||||
GstTagList *list);
|
||||
|
||||
void gst_element_set_eos (GstElement *element);
|
||||
|
||||
void gst_element_error (GstElement *element, const gchar *error, ...);
|
||||
|
@ -394,6 +398,8 @@ struct _GstElementFactory {
|
|||
GList * padtemplates;
|
||||
guint numpadtemplates;
|
||||
|
||||
GList *interfaces; /* interfaces this element implements */
|
||||
|
||||
GST_OBJECT_PADDING
|
||||
};
|
||||
|
||||
|
@ -431,6 +437,8 @@ gboolean gst_element_factory_can_sink_caps (GstElementFactory *factory,
|
|||
|
||||
void __gst_element_factory_add_pad_template (GstElementFactory *elementfactory,
|
||||
GstPadTemplate *templ);
|
||||
void __gst_element_factory_add_interface (GstElementFactory *elementfactory,
|
||||
const gchar *interfacename);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -84,6 +84,8 @@ gst_element_factory_init (GstElementFactory *factory)
|
|||
{
|
||||
factory->padtemplates = NULL;
|
||||
factory->numpadtemplates = 0;
|
||||
|
||||
factory->interfaces = NULL;
|
||||
}
|
||||
/**
|
||||
* gst_element_factory_find:
|
||||
|
@ -148,6 +150,10 @@ gst_element_factory_cleanup (GstElementFactory *factory)
|
|||
g_list_free (factory->padtemplates);
|
||||
factory->padtemplates = NULL;
|
||||
factory->numpadtemplates = 0;
|
||||
|
||||
g_list_foreach (factory->interfaces, (GFunc) g_free, NULL);
|
||||
g_list_free (factory->interfaces);
|
||||
factory->interfaces = NULL;
|
||||
}
|
||||
/**
|
||||
* gst_element_register:
|
||||
|
@ -165,6 +171,8 @@ gboolean
|
|||
gst_element_register (GstPlugin *plugin, const gchar *name, guint rank, GType type)
|
||||
{
|
||||
GstElementFactory *factory;
|
||||
GType *interfaces;
|
||||
guint n_interfaces, i;
|
||||
GstElementClass *klass;
|
||||
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
|
@ -190,6 +198,12 @@ gst_element_register (GstPlugin *plugin, const gchar *name, guint rank, GType ty
|
|||
g_list_foreach (factory->padtemplates, (GFunc) g_object_ref, NULL);
|
||||
factory->numpadtemplates = klass->numpadtemplates;
|
||||
|
||||
interfaces = g_type_interfaces (type, &n_interfaces);
|
||||
for (i = 0; i < n_interfaces; i++) {
|
||||
__gst_element_factory_add_interface (factory, g_type_name (interfaces[i]));
|
||||
}
|
||||
g_free (interfaces);
|
||||
|
||||
gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
|
||||
|
||||
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
|
||||
|
@ -387,6 +401,23 @@ gst_element_factory_get_num_pad_templates (GstElementFactory *factory)
|
|||
|
||||
return factory->numpadtemplates;
|
||||
}
|
||||
/**
|
||||
* __gst_element_factory_add_interface:
|
||||
* @elementfactory: The elementfactory to add the interface to
|
||||
* @interfacename: Name of the interface
|
||||
*
|
||||
* Adds the given interfacename to the list of implemented interfaces of the
|
||||
* element.
|
||||
*/
|
||||
void
|
||||
__gst_element_factory_add_interface (GstElementFactory *elementfactory, const gchar *interfacename)
|
||||
{
|
||||
g_return_if_fail (GST_IS_ELEMENT_FACTORY (elementfactory));
|
||||
g_return_if_fail (interfacename != NULL);
|
||||
g_return_if_fail (interfacename[0] != '\0'); /* no empty string */
|
||||
|
||||
elementfactory->interfaces = g_list_prepend (elementfactory->interfaces, g_strdup (interfacename));
|
||||
}
|
||||
/**
|
||||
* gst_element_factory_get_pad_templates:
|
||||
* @factory: a #GstElementFactory
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include "gstmemchunk.h"
|
||||
#include "gstevent.h"
|
||||
#include "gstlog.h"
|
||||
#include "gsttag.h"
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
/* #define GST_WITH_ALLOC_TRACE */
|
||||
#include "gsttrace.h"
|
||||
|
@ -70,6 +72,12 @@ _gst_event_copy (GstEvent *event)
|
|||
memcpy (copy, event, sizeof (GstEvent));
|
||||
|
||||
/* FIXME copy/ref additional fields */
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_TAG:
|
||||
copy->event_data.structure.structure = gst_structure_copy (event->event_data.structure.structure);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
@ -83,6 +91,8 @@ _gst_event_free (GstEvent* event)
|
|||
gst_object_unref (GST_EVENT_SRC (event));
|
||||
}
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_TAG:
|
||||
gst_tag_list_free (event->event_data.structure.structure);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,8 @@ typedef enum {
|
|||
GST_EVENT_FILLER = 12,
|
||||
GST_EVENT_TS_OFFSET = 13,
|
||||
GST_EVENT_INTERRUPT = 14,
|
||||
GST_EVENT_NAVIGATION = 15
|
||||
GST_EVENT_NAVIGATION = 15,
|
||||
GST_EVENT_TAG = 16
|
||||
} GstEventType;
|
||||
|
||||
extern GType _gst_event_type;
|
||||
|
|
|
@ -258,11 +258,11 @@ void gst_debug_log (GstDebugCategory *category, GstDebugLevel level,
|
|||
va_list var_args;
|
||||
|
||||
va_start (var_args, format);
|
||||
gst_debug_logv (category, level, file, function, line, object, format, var_args);
|
||||
gst_debug_log_valist (category, level, file, function, line, object, format, var_args);
|
||||
va_end (var_args);
|
||||
}
|
||||
/**
|
||||
* gst_debug_logv:
|
||||
* gst_debug_log_valist:
|
||||
* @category: category to log
|
||||
* @level: level of the message is in
|
||||
* @file: the file that emitted the message, usually the __FILE__ identifier
|
||||
|
@ -274,9 +274,9 @@ void gst_debug_log (GstDebugCategory *category, GstDebugLevel level,
|
|||
*
|
||||
* Logs the given message using the currently registered debugging handlers.
|
||||
*/
|
||||
void gst_debug_logv (GstDebugCategory *category, GstDebugLevel level,
|
||||
const gchar *file, const gchar *function, gint line,
|
||||
GObject *object, gchar *format, va_list args)
|
||||
void gst_debug_log_valist (GstDebugCategory *category, GstDebugLevel level,
|
||||
const gchar *file, const gchar *function, gint line,
|
||||
GObject *object, gchar *format, va_list args)
|
||||
{
|
||||
gchar *message;
|
||||
LogFuncEntry *entry;
|
||||
|
|
|
@ -162,7 +162,7 @@ void gst_debug_log (GstDebugCategory * category,
|
|||
GObject * object,
|
||||
gchar * format,
|
||||
...) G_GNUC_PRINTF (7, 8) G_GNUC_NO_INSTRUMENT;
|
||||
void gst_debug_logv (GstDebugCategory * category,
|
||||
void gst_debug_log_valist (GstDebugCategory * category,
|
||||
GstDebugLevel level,
|
||||
const gchar * file,
|
||||
const gchar * function,
|
||||
|
@ -388,7 +388,7 @@ const gchar* _gst_debug_nameof_funcptr (void * ptr);
|
|||
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC poison gst_debug_log
|
||||
# pragma GCC poison gst_debug_logv
|
||||
# pragma GCC poison gst_debug_log_valist
|
||||
# pragma GCC poison gst_debug_log_default
|
||||
# pragma GCC poison _gst_debug_category_new
|
||||
#endif
|
||||
|
|
|
@ -48,7 +48,7 @@ GType gst_structure_get_type(void)
|
|||
|
||||
void _gst_structure_initialize(void)
|
||||
{
|
||||
static GTypeValueTable type_value_table = {
|
||||
static const GTypeValueTable type_value_table = {
|
||||
_gst_structure_value_init,
|
||||
_gst_structure_value_free,
|
||||
_gst_structure_value_copy,
|
||||
|
@ -58,7 +58,7 @@ void _gst_structure_initialize(void)
|
|||
NULL,
|
||||
NULL,
|
||||
};
|
||||
static GTypeInfo structure_info = {
|
||||
static const GTypeInfo structure_info = {
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
|
@ -83,6 +83,27 @@ void _gst_structure_initialize(void)
|
|||
_gst_structure_transform_to_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_structure_id_empty_new:
|
||||
* @name: name of new structure
|
||||
*
|
||||
* Creates a new, empty #GstStructure with the given name.
|
||||
*
|
||||
* Returns: a new, empty #GstStructure
|
||||
*/
|
||||
GstStructure *gst_structure_id_empty_new(GQuark quark)
|
||||
{
|
||||
GstStructure *structure;
|
||||
|
||||
g_return_val_if_fail(quark != 0, NULL);
|
||||
|
||||
structure = g_new0(GstStructure, 1);
|
||||
structure->name = quark;
|
||||
structure->fields = g_array_new(FALSE,TRUE,sizeof(GstStructureField));
|
||||
|
||||
return structure;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_structure_empty_new:
|
||||
* @name: name of new structure
|
||||
|
@ -262,15 +283,15 @@ void gst_structure_set_name(GstStructure *structure, const gchar *name)
|
|||
* value is freed.
|
||||
*/
|
||||
void gst_structure_id_set_value(GstStructure *structure, GQuark fieldname,
|
||||
GValue *value)
|
||||
const GValue *value)
|
||||
{
|
||||
GstStructureField field = { 0 };
|
||||
GstStructureField field = { 0, { 0, } };
|
||||
|
||||
g_return_if_fail(structure != NULL);
|
||||
g_return_if_fail(G_IS_VALUE(value));
|
||||
|
||||
field.name = fieldname;
|
||||
g_value_init(&field.value, G_TYPE_INT);
|
||||
g_value_init(&field.value, G_VALUE_TYPE (value));
|
||||
g_value_copy(value, &field.value);
|
||||
|
||||
gst_structure_set_field(structure, &field);
|
||||
|
@ -287,7 +308,7 @@ void gst_structure_id_set_value(GstStructure *structure, GQuark fieldname,
|
|||
* value is freed.
|
||||
*/
|
||||
void gst_structure_set_value(GstStructure *structure, const gchar *field,
|
||||
GValue *value)
|
||||
const GValue *value)
|
||||
{
|
||||
g_return_if_fail(structure != NULL);
|
||||
g_return_if_fail(field != NULL);
|
||||
|
@ -355,13 +376,6 @@ void gst_structure_set_valist(GstStructure *structure, const gchar *fieldname,
|
|||
g_value_init(&field.value, G_TYPE_DOUBLE);
|
||||
g_value_set_double(&field.value, d);
|
||||
break;
|
||||
#if 0
|
||||
case GST_TYPE_FOURCC:
|
||||
i = va_arg(varargs, int);
|
||||
g_value_init(&field.value, G_TYPE_FOURCC);
|
||||
gst_value_set_fourcc(&field.value, i);
|
||||
break;
|
||||
#endif
|
||||
case G_TYPE_BOOLEAN:
|
||||
i = va_arg(varargs, int);
|
||||
g_value_init(&field.value, G_TYPE_BOOLEAN);
|
||||
|
@ -373,7 +387,14 @@ void gst_structure_set_valist(GstStructure *structure, const gchar *fieldname,
|
|||
g_value_set_string(&field.value, s);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
if(type == GST_TYPE_FOURCC){
|
||||
i = va_arg(varargs, int);
|
||||
g_value_init(&field.value, GST_TYPE_FOURCC);
|
||||
gst_value_set_fourcc(&field.value, i);
|
||||
break;
|
||||
}else{
|
||||
g_critical("unimplemented vararg field type %d\n", (int)type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -383,6 +404,32 @@ void gst_structure_set_valist(GstStructure *structure, const gchar *fieldname,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_structure_set_field_copy:
|
||||
* @structure: a #GstStructure
|
||||
* @field: the #GstStructureField to set
|
||||
*
|
||||
* Sets a field in the structure. If the structure currently contains
|
||||
* a field with the same name, it is replaced with the provided field.
|
||||
* Otherwise, the field is added to the structure. The field's value
|
||||
* is deeply copied.
|
||||
*
|
||||
* This function is intended mainly for internal use. The function
|
||||
* #gst_structure_set() is recommended instead of this one.
|
||||
*/
|
||||
void gst_structure_set_field_copy (GstStructure *structure,
|
||||
const GstStructureField *field)
|
||||
{
|
||||
GstStructureField f = { 0 };
|
||||
GType type = G_VALUE_TYPE (&field->value);
|
||||
|
||||
f.name = field->name;
|
||||
g_value_init (&f.value, type);
|
||||
g_value_copy (&field->value, &f.value);
|
||||
|
||||
gst_structure_set_field (structure, &f);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_structure_set_field:
|
||||
* @structure: a #GstStructure
|
||||
|
@ -424,7 +471,7 @@ void gst_structure_set_field(GstStructure *structure, GstStructureField *field)
|
|||
*
|
||||
* Returns: the #GstStructureField with the given ID
|
||||
*/
|
||||
GstStructureField *gst_structure_id_get_field(GstStructure *structure,
|
||||
GstStructureField *gst_structure_id_get_field(const GstStructure *structure,
|
||||
GQuark field_id)
|
||||
{
|
||||
GstStructureField *field;
|
||||
|
@ -452,7 +499,7 @@ GstStructureField *gst_structure_id_get_field(GstStructure *structure,
|
|||
* Returns: the #GstStructureField with the given name
|
||||
*/
|
||||
GstStructureField *
|
||||
gst_structure_get_field(GstStructure *structure, const gchar *fieldname)
|
||||
gst_structure_get_field(const GstStructure *structure, const gchar *fieldname)
|
||||
{
|
||||
g_return_val_if_fail(structure != NULL, NULL);
|
||||
g_return_val_if_fail(fieldname != NULL, NULL);
|
||||
|
@ -471,7 +518,7 @@ gst_structure_get_field(GstStructure *structure, const gchar *fieldname)
|
|||
* Returns: the #GValue corresponding to the field with the given name.
|
||||
*/
|
||||
const GValue *
|
||||
gst_structure_get_value(GstStructure *structure, const gchar *fieldname)
|
||||
gst_structure_get_value(const GstStructure *structure, const gchar *fieldname)
|
||||
{
|
||||
GstStructureField *field;
|
||||
|
||||
|
@ -524,6 +571,30 @@ gst_structure_remove_field(GstStructure *structure, const gchar *fieldname)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_structure_remove_all_fields:
|
||||
* @structure: a #GstStructure
|
||||
*
|
||||
* Removes all fields in a GstStructure.
|
||||
*/
|
||||
void
|
||||
gst_structure_remove_all_fields(GstStructure *structure)
|
||||
{
|
||||
GstStructureField *field;
|
||||
int i;
|
||||
|
||||
g_return_if_fail(structure != NULL);
|
||||
|
||||
for (i = structure->fields->len - 1; i >= 0; i-- ) {
|
||||
field = GST_STRUCTURE_FIELD(structure, i);
|
||||
|
||||
if (G_IS_VALUE (&field->value)) {
|
||||
g_value_unset(&field->value);
|
||||
}
|
||||
structure->fields = g_array_remove_index (structure->fields, i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_structure_get_field_type:
|
||||
* @structure: a #GstStructure
|
||||
|
@ -536,7 +607,7 @@ gst_structure_remove_field(GstStructure *structure, const gchar *fieldname)
|
|||
* Returns: the #GValue of the field
|
||||
*/
|
||||
GType
|
||||
gst_structure_get_field_type(GstStructure *structure, const gchar *fieldname)
|
||||
gst_structure_get_field_type(const GstStructure *structure, const gchar *fieldname)
|
||||
{
|
||||
GstStructureField *field;
|
||||
|
||||
|
@ -558,7 +629,7 @@ gst_structure_get_field_type(GstStructure *structure, const gchar *fieldname)
|
|||
* Returns: the number of fields in the structure
|
||||
*/
|
||||
gint
|
||||
gst_structure_n_fields(GstStructure *structure)
|
||||
gst_structure_n_fields(const GstStructure *structure)
|
||||
{
|
||||
g_return_val_if_fail(structure != NULL, 0);
|
||||
|
||||
|
@ -597,7 +668,7 @@ gst_structure_field_foreach (GstStructure *structure,
|
|||
* Returns: TRUE if the structure contains a field with the given name
|
||||
*/
|
||||
gboolean
|
||||
gst_structure_has_field(GstStructure *structure, const gchar *fieldname)
|
||||
gst_structure_has_field(const GstStructure *structure, const gchar *fieldname)
|
||||
{
|
||||
GstStructureField *field;
|
||||
|
||||
|
@ -620,7 +691,7 @@ gst_structure_has_field(GstStructure *structure, const gchar *fieldname)
|
|||
* Returns: TRUE if the structure contains a field with the given name and type
|
||||
*/
|
||||
gboolean
|
||||
gst_structure_has_field_typed(GstStructure *structure, const gchar *fieldname,
|
||||
gst_structure_has_field_typed(const GstStructure *structure, const gchar *fieldname,
|
||||
GType type)
|
||||
{
|
||||
GstStructureField *field;
|
||||
|
@ -650,7 +721,7 @@ gst_structure_has_field_typed(GstStructure *structure, const gchar *fieldname,
|
|||
* Returns: TRUE if the value could be set correctly
|
||||
*/
|
||||
gboolean
|
||||
gst_structure_get_boolean(GstStructure *structure, const gchar *fieldname,
|
||||
gst_structure_get_boolean(const GstStructure *structure, const gchar *fieldname,
|
||||
gboolean *value)
|
||||
{
|
||||
GstStructureField *field;
|
||||
|
@ -681,7 +752,7 @@ gst_structure_get_boolean(GstStructure *structure, const gchar *fieldname,
|
|||
* Returns: TRUE if the value could be set correctly
|
||||
*/
|
||||
gboolean
|
||||
gst_structure_get_int(GstStructure *structure, const gchar *fieldname,
|
||||
gst_structure_get_int(const GstStructure *structure, const gchar *fieldname,
|
||||
gint *value)
|
||||
{
|
||||
GstStructureField *field;
|
||||
|
@ -713,7 +784,7 @@ gst_structure_get_int(GstStructure *structure, const gchar *fieldname,
|
|||
* Returns: TRUE if the value could be set correctly
|
||||
*/
|
||||
gboolean
|
||||
gst_structure_get_fourcc(GstStructure *structure, const gchar *fieldname,
|
||||
gst_structure_get_fourcc(const GstStructure *structure, const gchar *fieldname,
|
||||
guint32 *value)
|
||||
{
|
||||
GstStructureField *field;
|
||||
|
@ -744,7 +815,7 @@ gst_structure_get_fourcc(GstStructure *structure, const gchar *fieldname,
|
|||
*
|
||||
* Returns: TRUE if the value could be set correctly
|
||||
*/
|
||||
gboolean gst_structure_get_double(GstStructure *structure,
|
||||
gboolean gst_structure_get_double(const GstStructure *structure,
|
||||
const gchar *fieldname, gdouble *value)
|
||||
{
|
||||
GstStructureField *field;
|
||||
|
@ -779,7 +850,7 @@ gboolean gst_structure_get_double(GstStructure *structure,
|
|||
* Returns: a pointer to the string
|
||||
*/
|
||||
const gchar *
|
||||
gst_structure_get_string(GstStructure *structure, const gchar *fieldname)
|
||||
gst_structure_get_string(const GstStructure *structure, const gchar *fieldname)
|
||||
{
|
||||
GstStructureField *field;
|
||||
|
||||
|
@ -803,7 +874,7 @@ gst_structure_get_string(GstStructure *structure, const gchar *fieldname)
|
|||
* Returns: a pointer to string allocated by g_malloc()
|
||||
*/
|
||||
gchar *
|
||||
gst_structure_to_string(GstStructure *structure)
|
||||
gst_structure_to_string(const GstStructure *structure)
|
||||
{
|
||||
GstStructureField *field;
|
||||
GString *s;
|
||||
|
|
|
@ -51,6 +51,7 @@ GType gst_structure_get_type(void);
|
|||
void _gst_structure_initialize(void);
|
||||
|
||||
GstStructure *gst_structure_empty_new(const gchar *name);
|
||||
GstStructure *gst_structure_id_empty_new(GQuark quark);
|
||||
GstStructure *gst_structure_new(const gchar *name,
|
||||
const gchar *firstfield, ...);
|
||||
GstStructure *gst_structure_new_valist(const gchar *name,
|
||||
|
@ -60,46 +61,49 @@ void gst_structure_free(GstStructure *structure);
|
|||
|
||||
const gchar *gst_structure_get_name(GstStructure *structure);
|
||||
void gst_structure_set_name(GstStructure *structure, const gchar *name);
|
||||
void gst_structure_set_field(GstStructure *structure,
|
||||
void gst_structure_set_field_copy (GstStructure *structure,
|
||||
const GstStructureField *field);
|
||||
void gst_structure_set_field (GstStructure *structure,
|
||||
GstStructureField *field);
|
||||
|
||||
void gst_structure_id_set_value(GstStructure *structure, GQuark field,
|
||||
GValue *value);
|
||||
const GValue *value);
|
||||
void gst_structure_set_value(GstStructure *structure, const gchar *field,
|
||||
GValue *value);
|
||||
const GValue *value);
|
||||
void gst_structure_set(GstStructure *structure, const gchar *field, ...);
|
||||
void gst_structure_set_valist(GstStructure *structure, const gchar *field,
|
||||
va_list varargs);
|
||||
const GValue *gst_structure_get_value(GstStructure *structure, const gchar *field);
|
||||
GstStructureField *gst_structure_get_field(GstStructure *structure,
|
||||
const GValue *gst_structure_get_value(const GstStructure *structure, const gchar *field);
|
||||
GstStructureField *gst_structure_get_field(const GstStructure *structure,
|
||||
const gchar *fieldname);
|
||||
GstStructureField *gst_structure_id_get_field(GstStructure *structure,
|
||||
GstStructureField *gst_structure_id_get_field(const GstStructure *structure,
|
||||
GQuark fieldname);
|
||||
void gst_structure_remove_field(GstStructure *structure, const gchar *field);
|
||||
void gst_structure_remove_all_fields(GstStructure *structure);
|
||||
|
||||
GType gst_structure_get_field_type(GstStructure *structure,
|
||||
GType gst_structure_get_field_type(const GstStructure *structure,
|
||||
const gchar *field);
|
||||
void gst_structure_field_foreach (GstStructure *structure,
|
||||
GstStructureForeachFunc func, gpointer user_data);
|
||||
gint gst_structure_n_fields(GstStructure *structure);
|
||||
gboolean gst_structure_has_field(GstStructure *structure, const gchar *field);
|
||||
gboolean gst_structure_has_field_typed(GstStructure *structure,
|
||||
gint gst_structure_n_fields(const GstStructure *structure);
|
||||
gboolean gst_structure_has_field(const GstStructure *structure, const gchar *field);
|
||||
gboolean gst_structure_has_field_typed(const GstStructure *structure,
|
||||
const gchar *field, GType type);
|
||||
|
||||
/* utility functions */
|
||||
|
||||
gboolean gst_structure_get_boolean(GstStructure *structure, const gchar *field,
|
||||
gboolean gst_structure_get_boolean(const GstStructure *structure, const gchar *field,
|
||||
gboolean *value);
|
||||
gboolean gst_structure_get_int(GstStructure *structure, const gchar *field,
|
||||
gboolean gst_structure_get_int(const GstStructure *structure, const gchar *field,
|
||||
gint *value);
|
||||
gboolean gst_structure_get_fourcc(GstStructure *structure, const gchar *field,
|
||||
gboolean gst_structure_get_fourcc(const GstStructure *structure, const gchar *field,
|
||||
guint32 *value);
|
||||
gboolean gst_structure_get_double(GstStructure *structure, const gchar *field,
|
||||
gboolean gst_structure_get_double(const GstStructure *structure, const gchar *field,
|
||||
gdouble *value);
|
||||
const gchar *gst_structure_get_string(GstStructure *structure,
|
||||
const gchar *gst_structure_get_string(const GstStructure *structure,
|
||||
const gchar *field);
|
||||
|
||||
gchar * gst_structure_to_string(GstStructure *structure);
|
||||
gchar * gst_structure_to_string(const GstStructure *structure);
|
||||
GstStructure * gst_structure_from_string (const gchar *string);
|
||||
|
||||
|
||||
|
|
831
gst/gsttag.c
Normal file
831
gst/gsttag.c
Normal file
|
@ -0,0 +1,831 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
*
|
||||
* gsttag.c: tag support (aka metadata)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gst_private.h"
|
||||
#include "gsttag.h"
|
||||
#include "gstinfo.h"
|
||||
#include "gstvalue.h"
|
||||
|
||||
#include <gobject/gvaluecollector.h>
|
||||
#include <string.h>
|
||||
|
||||
#define GST_TAG_IS_VALID(tag) (gst_tag_get_info (tag) != NULL)
|
||||
|
||||
typedef struct {
|
||||
GType type; /* type the data is in */
|
||||
|
||||
gchar * nick; /* translated name */
|
||||
gchar * blurb; /* translated description of type */
|
||||
|
||||
GstTagMergeFunc merge_func; /* functions to merge the values */
|
||||
} GstTagInfo;
|
||||
|
||||
#define TAGLIST "taglist"
|
||||
static GQuark gst_tag_list_quark;
|
||||
static GMutex *__tag_mutex;
|
||||
static GHashTable *__tags;
|
||||
#define TAG_LOCK g_mutex_lock (__tag_mutex)
|
||||
#define TAG_UNLOCK g_mutex_unlock (__tag_mutex)
|
||||
|
||||
void
|
||||
_gst_tag_initialize (void)
|
||||
{
|
||||
gst_tag_list_quark = g_quark_from_static_string (TAGLIST);
|
||||
__tag_mutex = g_mutex_new ();
|
||||
__tags = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
gst_tag_register (GST_TAG_TITLE,
|
||||
G_TYPE_STRING,
|
||||
_("title"),
|
||||
_("commonly used title"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_ARTIST,
|
||||
G_TYPE_STRING,
|
||||
_("artist"),
|
||||
_("person(s) resposible for the recording"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_ALBUM,
|
||||
G_TYPE_STRING,
|
||||
_("album"),
|
||||
_("album containing this data"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_DATE,
|
||||
G_TYPE_UINT, /* FIXME: own data type for dates? */
|
||||
_("date"),
|
||||
_("date the data was created in julien days"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_GENRE,
|
||||
G_TYPE_STRING,
|
||||
_("genre"),
|
||||
_("genre this data belongs to"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_COMMENT,
|
||||
G_TYPE_STRING,
|
||||
_("comment"),
|
||||
_("free text commenting the data"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_TRACK_NUMBER,
|
||||
G_TYPE_UINT,
|
||||
_("track number"),
|
||||
_("track number inside a collection"),
|
||||
gst_tag_merge_use_first);
|
||||
gst_tag_register (GST_TAG_TRACK_COUNT,
|
||||
G_TYPE_STRING,
|
||||
_("track count"),
|
||||
_("count of tracks inside collection this track belongs to"),
|
||||
gst_tag_merge_use_first);
|
||||
gst_tag_register (GST_TAG_LOCATION,
|
||||
G_TYPE_STRING,
|
||||
_("loccation"),
|
||||
_("original location of file as a URI"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_DESCRIPTION,
|
||||
G_TYPE_STRING,
|
||||
_("description"),
|
||||
_("short text describing the content of the data"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_VERSION,
|
||||
G_TYPE_STRING,
|
||||
_("version"),
|
||||
_("version of this data"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_ISRC,
|
||||
G_TYPE_STRING,
|
||||
_("ISRC"),
|
||||
_("International Standard Recording Code - see http://www.ifpi.org/isrc/"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_ORGANIZATION,
|
||||
G_TYPE_STRING,
|
||||
_("organization"),
|
||||
_("organization"), /* FIXME */
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_COPYRIGHT,
|
||||
G_TYPE_STRING,
|
||||
_("copyright"),
|
||||
_("copyright notice of the data"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_CONTACT,
|
||||
G_TYPE_STRING,
|
||||
_("contact"),
|
||||
_("contact information"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_LICENSE,
|
||||
G_TYPE_STRING,
|
||||
_("license"),
|
||||
_("license of data"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_PERFORMER,
|
||||
G_TYPE_STRING,
|
||||
_("performer"),
|
||||
_("person(s) performing"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_DURATION,
|
||||
G_TYPE_UINT64,
|
||||
_("duration"),
|
||||
_("length in GStreamer time units (nanoseconds)"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_CODEC,
|
||||
G_TYPE_STRING,
|
||||
_("codec"),
|
||||
_("codec the data is stored in"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_MINIMUM_BITRATE,
|
||||
G_TYPE_UINT,
|
||||
_("minimum bitrate"),
|
||||
_("minimum bitrate in bits/s"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_BITRATE,
|
||||
G_TYPE_UINT,
|
||||
_("bitrate"),
|
||||
_("exact or average bitrate in bits/s"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_MAXIMUM_BITRATE,
|
||||
G_TYPE_UINT,
|
||||
_("maximum bitrate"),
|
||||
_("maximum bitrate in bits/s"),
|
||||
NULL);
|
||||
}
|
||||
/**
|
||||
* gst_tag_merge_use_first:
|
||||
* @dest: uninitialized GValue to store result in
|
||||
* @src: GValue to copy from
|
||||
*
|
||||
* This is a convenience function for the func argument of gst_tag_register().
|
||||
* It creates a copy of the first value from the list.
|
||||
*/
|
||||
void
|
||||
gst_tag_merge_use_first (GValue *dest, const GValue *src)
|
||||
{
|
||||
const GValue *ret = gst_value_list_get_value (src, 0);
|
||||
|
||||
g_value_init (dest, G_VALUE_TYPE (ret));
|
||||
g_value_copy (ret, dest);
|
||||
}
|
||||
/**
|
||||
* gst_tag_merge_strings_with_comma:
|
||||
* @dest: uninitialized GValue to store result in
|
||||
* @src: GValue to copy from
|
||||
*
|
||||
* This is a convenience function for the func argument of gst_tag_register().
|
||||
* It concatenates all given strings using a comma. The tag must be registered
|
||||
* as a G_TYPE_STRING or this function will fail.
|
||||
*/
|
||||
void
|
||||
gst_tag_merge_strings_with_comma (GValue *dest, const GValue *src)
|
||||
{
|
||||
GString *str;
|
||||
gint i, count;
|
||||
|
||||
count = gst_value_list_get_size (src);
|
||||
str = g_string_new (g_value_get_string (gst_value_list_get_value (src, 0)));
|
||||
for (i = 1; i < count; i++) {
|
||||
/* seperator between two string */
|
||||
str = g_string_append (str, _(", "));
|
||||
str = g_string_append (str, g_value_get_string (gst_value_list_get_value (src, 1)));
|
||||
}
|
||||
|
||||
g_value_init (dest, G_TYPE_STRING);
|
||||
g_value_take_string (dest, str->str);
|
||||
g_string_free (str, FALSE);
|
||||
}
|
||||
static GstTagInfo *
|
||||
gst_tag_lookup (GQuark entry)
|
||||
{
|
||||
GstTagInfo *ret;
|
||||
|
||||
TAG_LOCK;
|
||||
ret = g_hash_table_lookup (__tags, GUINT_TO_POINTER (entry));
|
||||
TAG_UNLOCK;
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* gst_tag_register:
|
||||
* @name: the name or identifier string
|
||||
* @type: the type this data is in
|
||||
* @nick: human-readable name
|
||||
* @blurb: a human-readable description about this tag
|
||||
* @func: function for merging multiple values of this tag
|
||||
*
|
||||
* Registers a new tag type for the use with GStreamer's type system. If a type
|
||||
* with that name is already registered, that one is used.
|
||||
* The old registration may have used a different type however. So don't rely
|
||||
* on youre supplied values.
|
||||
* If you know the type is already registered, use gst_tag_lookup instead.
|
||||
* This function takes ownership of all supplied variables.
|
||||
*/
|
||||
void
|
||||
gst_tag_register (gchar *name, GType type, gchar *nick, gchar *blurb,
|
||||
GstTagMergeFunc func)
|
||||
{
|
||||
GQuark key;
|
||||
GstTagInfo *info;
|
||||
|
||||
g_return_if_fail (name != NULL);
|
||||
g_return_if_fail (nick != NULL);
|
||||
g_return_if_fail (blurb != NULL);
|
||||
g_return_if_fail (type != 0 && type != GST_VALUE_TYPE_LIST);
|
||||
|
||||
key = g_quark_from_string (name);
|
||||
info = gst_tag_lookup (key);
|
||||
g_return_if_fail (info == NULL);
|
||||
|
||||
info = g_new (GstTagInfo, 1);
|
||||
info->type = type;
|
||||
info->nick = nick;
|
||||
info->blurb = blurb;
|
||||
info->merge_func = func;
|
||||
|
||||
TAG_LOCK;
|
||||
g_hash_table_insert (__tags, GUINT_TO_POINTER (key), info);
|
||||
TAG_UNLOCK;
|
||||
}
|
||||
/**
|
||||
* gst_tag_exists:
|
||||
* @tag: name of the tag
|
||||
*
|
||||
* Checks if the given type is already registered.
|
||||
*
|
||||
* Returns: TRUE if the type is already registered
|
||||
*/
|
||||
gboolean
|
||||
gst_tag_exists (const gchar *tag)
|
||||
{
|
||||
g_return_val_if_fail (tag != NULL, FALSE);
|
||||
|
||||
return gst_tag_lookup (g_quark_from_string (tag)) != NULL;
|
||||
}
|
||||
/**
|
||||
* gst_tag_get_type:
|
||||
* @tag: the tag
|
||||
*
|
||||
* Gets the #GType used for this tag.
|
||||
*
|
||||
* Returns: the #GType of this tag
|
||||
*/
|
||||
GType
|
||||
gst_tag_get_type (const gchar *tag)
|
||||
{
|
||||
GstTagInfo *info;
|
||||
|
||||
g_return_val_if_fail (tag != NULL, 0);
|
||||
info = gst_tag_lookup (g_quark_from_string (tag));
|
||||
g_return_val_if_fail (info != NULL, 0);
|
||||
|
||||
return info->type;
|
||||
}
|
||||
/**
|
||||
* gst_tag_get_nick
|
||||
* @tag: the tag
|
||||
*
|
||||
* Returns the human-readable name of this tag, You must not change or free
|
||||
* this string.
|
||||
*
|
||||
* Returns: the human-readable name of this tag
|
||||
*/
|
||||
const gchar *
|
||||
gst_tag_get_nick (const gchar *tag)
|
||||
{
|
||||
GstTagInfo *info;
|
||||
|
||||
g_return_val_if_fail (tag != NULL, NULL);
|
||||
info = gst_tag_lookup (g_quark_from_string (tag));
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->nick;
|
||||
}
|
||||
/**
|
||||
* gst_tag_get_description:
|
||||
* @tag: the tag
|
||||
*
|
||||
* Returns the human-readable description of this tag, You must not change or
|
||||
* free this string.
|
||||
*
|
||||
* Return the human-readable description of this tag
|
||||
*/
|
||||
const gchar *
|
||||
gst_tag_get_description (const gchar *tag)
|
||||
{
|
||||
GstTagInfo *info;
|
||||
|
||||
g_return_val_if_fail (tag != NULL, NULL);
|
||||
info = gst_tag_lookup (g_quark_from_string (tag));
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->blurb;
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_is_fixed:
|
||||
* @tag: tag to check
|
||||
*
|
||||
* Checks if the given tag is fixed. A fixed tag can only contain one value.
|
||||
* Unfixed tags can contain lists of values.
|
||||
*
|
||||
* Returns: TRUE, if the given tag is fixed.
|
||||
*/
|
||||
gboolean
|
||||
gst_tag_is_fixed (const gchar *tag)
|
||||
{
|
||||
GstTagInfo *info;
|
||||
|
||||
g_return_val_if_fail (tag != NULL, FALSE);
|
||||
info = gst_tag_lookup (g_quark_from_string (tag));
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
|
||||
return info->merge_func == NULL;
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_new:
|
||||
*
|
||||
* Creates a new empty GstTagList.
|
||||
*
|
||||
* Returns: An empty tag list
|
||||
*/
|
||||
GstTagList *
|
||||
gst_tag_list_new (void)
|
||||
{
|
||||
return GST_TAG_LIST (gst_structure_new (TAGLIST, NULL));
|
||||
}
|
||||
/**
|
||||
* gst_is_tag_list:
|
||||
* @p: Object that might be a taglist
|
||||
*
|
||||
* Checks if the given pointer is a taglist.
|
||||
*
|
||||
* Returns: TRUE, if the given pointer is a taglist
|
||||
*/
|
||||
gboolean
|
||||
gst_is_tag_list (gconstpointer p)
|
||||
{
|
||||
g_return_val_if_fail (p != NULL, FALSE);
|
||||
|
||||
return ((GstStructure *) p)->name == gst_tag_list_quark;
|
||||
}
|
||||
typedef struct {
|
||||
GstStructure * list;
|
||||
GstTagMergeMode mode;
|
||||
} GstTagCopyData;
|
||||
static void
|
||||
gst_tag_list_add_value_internal (GstStructure *list, GstTagMergeMode mode, GQuark tag, GValue *value)
|
||||
{
|
||||
GstTagInfo *info = gst_tag_lookup (tag);
|
||||
GstStructureField *field;
|
||||
|
||||
g_assert (info != NULL);
|
||||
|
||||
if (info->merge_func && (field = gst_structure_id_get_field (list, tag)) != NULL) {
|
||||
GValue value2 = { 0, };
|
||||
switch (mode) {
|
||||
case GST_TAG_MERGE_REPLACE_ALL:
|
||||
case GST_TAG_MERGE_REPLACE:
|
||||
gst_structure_id_set_value (list, tag, value);
|
||||
break;
|
||||
case GST_TAG_MERGE_PREPEND:
|
||||
gst_value_list_concat (&value2, value, &field->value);
|
||||
gst_structure_id_set_value (list, tag, &value2);
|
||||
g_value_unset (&value2);
|
||||
break;
|
||||
case GST_TAG_MERGE_APPEND:
|
||||
gst_value_list_concat (&value2, &field->value, value);
|
||||
gst_structure_id_set_value (list, tag, &value2);
|
||||
g_value_unset (&value2);
|
||||
break;
|
||||
case GST_TAG_MERGE_KEEP:
|
||||
case GST_TAG_MERGE_KEEP_ALL:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (mode) {
|
||||
case GST_TAG_MERGE_APPEND:
|
||||
case GST_TAG_MERGE_KEEP:
|
||||
if (gst_structure_id_get_field (list, tag) != NULL)
|
||||
break;
|
||||
/* fall through */
|
||||
case GST_TAG_MERGE_REPLACE_ALL:
|
||||
case GST_TAG_MERGE_REPLACE:
|
||||
case GST_TAG_MERGE_PREPEND:
|
||||
gst_structure_id_set_value (list, tag, value);
|
||||
break;
|
||||
case GST_TAG_MERGE_KEEP_ALL:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void
|
||||
gst_tag_list_copy_foreach (GstStructure *structure, GQuark tag, GValue *value, gpointer user_data)
|
||||
{
|
||||
GstTagCopyData *copy = (GstTagCopyData *) user_data;
|
||||
|
||||
gst_tag_list_add_value_internal (copy->list, copy->mode, tag, value);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_insert:
|
||||
* @into: list to merge into
|
||||
* @from: list to merge from
|
||||
* @mode: the mode to use
|
||||
*
|
||||
* Inserts the tags of the second list into the first list using the given mode.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_insert (GstTagList *into, const GstTagList *from, GstTagMergeMode mode)
|
||||
{
|
||||
GstTagCopyData data;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_LIST (into));
|
||||
g_return_if_fail (GST_IS_TAG_LIST (from));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
|
||||
data.list = (GstStructure *) into;
|
||||
data.mode = mode;
|
||||
if (mode == GST_TAG_MERGE_REPLACE_ALL) {
|
||||
gst_structure_remove_all_fields (data.list);
|
||||
}
|
||||
gst_structure_field_foreach ((GstStructure *) from, gst_tag_list_copy_foreach, &data);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_copy:
|
||||
* @list: list to copy
|
||||
*
|
||||
* Copies a given #GstTagList.
|
||||
*
|
||||
* Returns: copy of the given list
|
||||
*/
|
||||
GstTagList *
|
||||
gst_tag_list_copy (const GstTagList *list)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
|
||||
|
||||
return GST_TAG_LIST (gst_structure_copy ((GstStructure *) list));
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_merge:
|
||||
* @list1: first list to merge
|
||||
* @list2: second list to merge
|
||||
* @mode: the mode to use
|
||||
*
|
||||
* Merges the two given lists into a new list. If one of the lists is NULL, a
|
||||
* copy of the other is returned. If both lists are NULL, NULL is returned.
|
||||
*
|
||||
* Returns: the new list
|
||||
*/
|
||||
GstTagList *
|
||||
gst_tag_list_merge (const GstTagList *list1, const GstTagList *list2, GstTagMergeMode mode)
|
||||
{
|
||||
g_return_val_if_fail (list1 == NULL || GST_IS_TAG_LIST (list1), NULL);
|
||||
g_return_val_if_fail (list2 == NULL || GST_IS_TAG_LIST (list2), NULL);
|
||||
g_return_val_if_fail (GST_TAG_MODE_IS_VALID (mode), NULL);
|
||||
|
||||
if (!list1 && !list2) {
|
||||
return NULL;
|
||||
} else if (!list1) {
|
||||
return gst_tag_list_copy (list2);
|
||||
} else if (!list2) {
|
||||
return gst_tag_list_copy (list1);
|
||||
} else {
|
||||
GstTagList *ret;
|
||||
|
||||
ret = gst_tag_list_copy (list1);
|
||||
gst_tag_list_insert (ret, list2, mode);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_free:
|
||||
* @list: the list to free
|
||||
*
|
||||
* Frees the given list and all associated values.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_free (GstTagList *list)
|
||||
{
|
||||
g_return_if_fail (GST_IS_TAG_LIST (list));
|
||||
gst_structure_free ((GstStructure *) list);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_get_tag_size:
|
||||
* @list: a taglist
|
||||
* @tag: the tag to query
|
||||
*
|
||||
* Checks how many value are stored in this tag list for the given tag.
|
||||
*
|
||||
* Returns: The number of tags stored
|
||||
*/
|
||||
guint
|
||||
gst_tag_list_get_tag_size (const GstTagList *list, const gchar *tag)
|
||||
{
|
||||
const GValue *value;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
|
||||
|
||||
value = gst_structure_get_value ((GstStructure *) list, tag);
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
if (G_VALUE_TYPE (value) != GST_VALUE_TYPE_LIST)
|
||||
return 1;
|
||||
|
||||
return gst_value_list_get_size (value);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_add:
|
||||
* @list: list to set tags in
|
||||
* @mode: the mode to use
|
||||
* @tag: tag
|
||||
* @...: values to set
|
||||
*
|
||||
* Sets the values for the given tags using the specified mode.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_add (GstTagList *list, GstTagMergeMode mode, const gchar *tag, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_LIST (list));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
g_return_if_fail (tag != NULL);
|
||||
|
||||
va_start (args, tag);
|
||||
gst_tag_list_add_valist (list, mode, tag, args);
|
||||
va_end (args);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_add_valist:
|
||||
* @list: list to set tags in
|
||||
* @mode: the mode to use
|
||||
* @tag: tag
|
||||
* @var_args: tag / value pairs to set
|
||||
*
|
||||
* Sets the values for the given tags using the specified mode.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_add_valist (GstTagList *list, GstTagMergeMode mode, const gchar *tag, va_list var_args)
|
||||
{
|
||||
GstTagInfo *info;
|
||||
GQuark quark;
|
||||
gchar *error = NULL;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_LIST (list));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
g_return_if_fail (tag != NULL);
|
||||
|
||||
while (tag != NULL) {
|
||||
GValue value = { 0, };
|
||||
quark = g_quark_from_string (tag);
|
||||
info = gst_tag_lookup (quark);
|
||||
g_return_if_fail (info != NULL);
|
||||
g_value_init (&value, info->type);
|
||||
G_VALUE_COLLECT (&value, var_args, 0, &error);
|
||||
if (error) {
|
||||
g_warning ("%s: %s", G_STRLOC, error);
|
||||
g_free (error);
|
||||
/* we purposely leak the value here, it might not be
|
||||
* in a sane state if an error condition occoured
|
||||
*/
|
||||
return;
|
||||
}
|
||||
gst_tag_list_add_value_internal (list, mode, quark, &value);
|
||||
g_value_unset (&value);
|
||||
tag = va_arg (var_args, gchar *);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_remove_tag:
|
||||
* @list: list to remove tag from
|
||||
* @tag: tag to remove
|
||||
*
|
||||
* Removes the goven tag from the taglist.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_remove_tag (GstTagList *list, const gchar *tag)
|
||||
{
|
||||
g_return_if_fail (GST_IS_TAG_LIST (list));
|
||||
g_return_if_fail (tag != NULL);
|
||||
|
||||
gst_structure_remove_field ((GstStructure *) list, tag);
|
||||
}
|
||||
typedef struct {
|
||||
GstTagForeachFunc func;
|
||||
gpointer data;
|
||||
} TagForeachData;
|
||||
static void
|
||||
structure_foreach_wrapper (GstStructure *structure, GQuark field_id,
|
||||
GValue *value, gpointer user_data)
|
||||
{
|
||||
TagForeachData *data = (TagForeachData *) user_data;
|
||||
data->func (GST_TAG_LIST (structure), g_quark_to_string (field_id), data->data);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_foreach:
|
||||
* @list: list to iterate over
|
||||
* @func: function to be called for each tag
|
||||
* @user_data: user specified data
|
||||
*
|
||||
* Calls the given function for each tag inside the tag list. Note that if there
|
||||
* is no tag, the function won't be called at all.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_foreach (GstTagList *list, GstTagForeachFunc func, gpointer user_data)
|
||||
{
|
||||
TagForeachData data;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_LIST (list));
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
data.func = func;
|
||||
data.data = user_data;
|
||||
gst_structure_field_foreach ((GstStructure *) list, structure_foreach_wrapper, &data);
|
||||
}
|
||||
|
||||
/***** tag events *****/
|
||||
|
||||
/**
|
||||
* gst_event_new_tag:
|
||||
* @list: the tag list to put into the event or NULL for an empty list
|
||||
*
|
||||
* Creates a new tag event with the given list and takes ownership of it.
|
||||
*
|
||||
* Returns: a new tag event
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_tag (GstTagList *list)
|
||||
{
|
||||
GstEvent *ret;
|
||||
|
||||
g_return_val_if_fail (list == NULL || GST_IS_TAG_LIST (list), NULL);
|
||||
|
||||
ret = gst_event_new (GST_EVENT_TAG);
|
||||
if (!list)
|
||||
list = gst_tag_list_new ();
|
||||
ret->event_data.structure.structure = (GstStructure *) list;
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* get_event_tag_get_list:
|
||||
* @tag_event: a tagging #GstEvent
|
||||
*
|
||||
* Gets the taglist from a given tagging event.
|
||||
*
|
||||
* Returns: The #GstTagList of the event
|
||||
*/
|
||||
GstTagList *
|
||||
gst_event_tag_get_list (GstEvent *tag_event)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_EVENT (tag_event), NULL);
|
||||
g_return_val_if_fail (GST_EVENT_TYPE (tag_event) == GST_EVENT_TAG, NULL);
|
||||
|
||||
return GST_TAG_LIST (tag_event->event_data.structure.structure);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_tag_list_get_value_index:
|
||||
* @list: a #GStTagList
|
||||
* @tag: tag to read out
|
||||
* @index: number of entry to read out
|
||||
*
|
||||
* Gets the value that is at the given index for the given tag in the given
|
||||
* list.
|
||||
*
|
||||
* Returns: The GValue for the specified entry or NULL if the tag wasn't available
|
||||
* or the tag doesn't have as many entries
|
||||
*/
|
||||
G_CONST_RETURN GValue *
|
||||
gst_tag_list_get_value_index (const GstTagList *list, const gchar *tag, guint index)
|
||||
{
|
||||
const GValue *value;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
|
||||
g_return_val_if_fail (tag != NULL, NULL);
|
||||
|
||||
value = gst_structure_get_value ((GstStructure *) list, tag);
|
||||
if (value == NULL) return NULL;
|
||||
|
||||
if (GST_VALUE_HOLDS_LIST (value)) {
|
||||
if (index >= gst_value_list_get_size (value)) return NULL;
|
||||
return gst_value_list_get_value (value, index);
|
||||
} else {
|
||||
if (index > 0) return NULL;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_tag_list_copy_value:
|
||||
* @dest: uninitialized #GValue to copy into
|
||||
* @list: list to get the tag from
|
||||
* @tag: tag to read out
|
||||
*
|
||||
* Copies the contents for the given tag into the value, merging multiple values
|
||||
* into one if multiple values are associated with the tag.
|
||||
* You must g_value_unset() the value after use.
|
||||
*
|
||||
* Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
|
||||
* given list.
|
||||
*/
|
||||
gboolean
|
||||
gst_tag_list_copy_value (GValue *dest, const GstTagList *list, const gchar *tag)
|
||||
{
|
||||
const GValue *src;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
|
||||
g_return_val_if_fail (tag != NULL, FALSE);
|
||||
g_return_val_if_fail (dest != NULL, FALSE);
|
||||
g_return_val_if_fail (G_VALUE_TYPE (dest) == 0, FALSE);
|
||||
|
||||
src = gst_structure_get_value ((GstStructure *) list, tag);
|
||||
if (!src) return FALSE;
|
||||
|
||||
if (G_VALUE_TYPE (src) == GST_VALUE_TYPE_LIST) {
|
||||
GstTagInfo *info = gst_tag_lookup (g_quark_from_string (tag));
|
||||
/* must be there or lists aren't allowed */
|
||||
g_assert (info->merge_func);
|
||||
info->merge_func (dest, src);
|
||||
} else {
|
||||
g_value_init (dest, G_VALUE_TYPE (src));
|
||||
g_value_copy (src, dest);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***** evil macros to get all the gst_tag_list_get_*() functions right *****/
|
||||
|
||||
#define TAG_MERGE_FUNCS(name,type) \
|
||||
gboolean \
|
||||
gst_tag_list_get_ ## name (const GstTagList *list, const gchar *tag, \
|
||||
type *value) \
|
||||
{ \
|
||||
GValue v = { 0, }; \
|
||||
\
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); \
|
||||
g_return_val_if_fail (tag != NULL, FALSE); \
|
||||
g_return_val_if_fail (value != NULL, FALSE); \
|
||||
\
|
||||
if (!gst_tag_list_copy_value (&v, list, tag)) \
|
||||
return FALSE; \
|
||||
*value = COPY_FUNC (g_value_get_ ## name (&v)); \
|
||||
g_value_unset (&v); \
|
||||
return TRUE; \
|
||||
} \
|
||||
\
|
||||
gboolean \
|
||||
gst_tag_list_get_ ## name ## _index (const GstTagList *list, const gchar *tag, \
|
||||
guint index, type *value) \
|
||||
{ \
|
||||
const GValue *v; \
|
||||
\
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); \
|
||||
g_return_val_if_fail (tag != NULL, FALSE); \
|
||||
g_return_val_if_fail (value != NULL, FALSE); \
|
||||
\
|
||||
if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL) \
|
||||
return FALSE; \
|
||||
*value = COPY_FUNC (g_value_get_ ## name (v)); \
|
||||
return TRUE; \
|
||||
}
|
||||
|
||||
#define COPY_FUNC /**/
|
||||
TAG_MERGE_FUNCS (char, gchar)
|
||||
TAG_MERGE_FUNCS (uchar, guchar)
|
||||
TAG_MERGE_FUNCS (boolean, gboolean)
|
||||
TAG_MERGE_FUNCS (int, gint)
|
||||
TAG_MERGE_FUNCS (uint, guint)
|
||||
TAG_MERGE_FUNCS (long, glong)
|
||||
TAG_MERGE_FUNCS (ulong, gulong)
|
||||
TAG_MERGE_FUNCS (int64, gint64)
|
||||
TAG_MERGE_FUNCS (uint64, guint64)
|
||||
TAG_MERGE_FUNCS (float, gfloat)
|
||||
TAG_MERGE_FUNCS (double, gdouble)
|
||||
#undef COPY_FUNC
|
||||
|
||||
#define COPY_FUNC g_strdup
|
||||
TAG_MERGE_FUNCS (string, gchar *)
|
||||
|
||||
|
||||
|
||||
|
232
gst/gsttag.h
Normal file
232
gst/gsttag.h
Normal file
|
@ -0,0 +1,232 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
*
|
||||
* gsttag.h: Header for tag support
|
||||
*
|
||||
* 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_TAG_H__
|
||||
#define __GST_TAG_H__
|
||||
|
||||
#include <gst/gststructure.h>
|
||||
#include <gst/gstevent.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GST_TAG_MERGE_UNDEFINED,
|
||||
GST_TAG_MERGE_REPLACE_ALL,
|
||||
GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_MERGE_APPEND,
|
||||
GST_TAG_MERGE_PREPEND,
|
||||
GST_TAG_MERGE_KEEP,
|
||||
GST_TAG_MERGE_KEEP_ALL,
|
||||
/* add more */
|
||||
GST_TAG_MERGE_COUNT
|
||||
} GstTagMergeMode;
|
||||
#define GST_TAG_MODE_IS_VALID(mode) (((mode) > GST_TAG_MERGE_UNDEFINED) && ((mode) < GST_TAG_MERGE_COUNT))
|
||||
|
||||
typedef GstStructure GstTagList;
|
||||
#define GST_TAG_LIST(x) ((GstTagList *) (x))
|
||||
#define GST_IS_TAG_LIST(x) (gst_is_tag_list (GST_TAG_LIST (x)))
|
||||
|
||||
typedef void (* GstTagForeachFunc) (const GstTagList *list, const gchar *tag, gpointer user_data);
|
||||
typedef void (* GstTagMergeFunc) (GValue *dest, const GValue *src);
|
||||
|
||||
/* initialize tagging system */
|
||||
void _gst_tag_initialize (void);
|
||||
|
||||
void gst_tag_register (gchar * name,
|
||||
GType type,
|
||||
gchar * nick,
|
||||
gchar * blurb,
|
||||
GstTagMergeFunc func);
|
||||
/* some default merging functions */
|
||||
void gst_tag_merge_use_first (GValue * dest,
|
||||
const GValue * values);
|
||||
void gst_tag_merge_strings_with_comma (GValue * dest,
|
||||
const GValue * values);
|
||||
|
||||
/* basic tag support */
|
||||
gboolean gst_tag_exists (const gchar * tag);
|
||||
GType gst_tag_get_type (const gchar * tag);
|
||||
const gchar * gst_tag_get_nick (const gchar * tag);
|
||||
const gchar * gst_tag_get_description (const gchar * tag);
|
||||
gboolean gst_tag_is_fixed (const gchar * tag);
|
||||
|
||||
/* tag lists */
|
||||
GstTagList * gst_tag_list_new (void);
|
||||
gboolean gst_is_tag_list (gconstpointer p);
|
||||
GstTagList * gst_tag_list_copy (const GstTagList * list);
|
||||
void gst_tag_list_insert (GstTagList * into,
|
||||
const GstTagList * from,
|
||||
GstTagMergeMode mode);
|
||||
GstTagList * gst_tag_list_merge (const GstTagList * list1,
|
||||
const GstTagList * list2,
|
||||
GstTagMergeMode mode);
|
||||
void gst_tag_list_free (GstTagList * list);
|
||||
guint gst_tag_list_get_tag_size (const GstTagList * list,
|
||||
const gchar * tag);
|
||||
void gst_tag_list_add (GstTagList * list,
|
||||
GstTagMergeMode mode,
|
||||
const gchar * tag,
|
||||
...);
|
||||
void gst_tag_list_add_valist (GstTagList * list,
|
||||
GstTagMergeMode mode,
|
||||
const gchar * tag,
|
||||
va_list var_args);
|
||||
void gst_tag_list_remove_tag (GstTagList * list,
|
||||
const gchar * tag);
|
||||
void gst_tag_list_foreach (GstTagList * list,
|
||||
GstTagForeachFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
G_CONST_RETURN GValue *
|
||||
gst_tag_list_get_value_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index);
|
||||
gboolean gst_tag_list_copy_value (GValue * dest,
|
||||
const GstTagList * list,
|
||||
const gchar * tag);
|
||||
|
||||
/* simplifications (FIXME: do we want them?) */
|
||||
gboolean gst_tag_list_get_char (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gchar * value);
|
||||
gboolean gst_tag_list_get_char_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gchar * value);
|
||||
gboolean gst_tag_list_get_uchar (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guchar * value);
|
||||
gboolean gst_tag_list_get_uchar_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
guchar * value);
|
||||
gboolean gst_tag_list_get_boolean (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gboolean * value);
|
||||
gboolean gst_tag_list_get_boolean_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gboolean * value);
|
||||
gboolean gst_tag_list_get_int (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gint * value);
|
||||
gboolean gst_tag_list_get_int_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gint * value);
|
||||
gboolean gst_tag_list_get_uint (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint * value);
|
||||
gboolean gst_tag_list_get_uint_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
guint * value);
|
||||
gboolean gst_tag_list_get_long (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
glong * value);
|
||||
gboolean gst_tag_list_get_long_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
glong * value);
|
||||
gboolean gst_tag_list_get_ulong (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gulong * value);
|
||||
gboolean gst_tag_list_get_ulong_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gulong * value);
|
||||
gboolean gst_tag_list_get_int64 (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gint64 * value);
|
||||
gboolean gst_tag_list_get_int64_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gint64 * value);
|
||||
gboolean gst_tag_list_get_uint64 (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint64 * value);
|
||||
gboolean gst_tag_list_get_uint64_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
guint64 * value);
|
||||
gboolean gst_tag_list_get_float (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gfloat * value);
|
||||
gboolean gst_tag_list_get_float_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gfloat * value);
|
||||
gboolean gst_tag_list_get_double (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gdouble * value);
|
||||
gboolean gst_tag_list_get_double_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gdouble * value);
|
||||
gboolean gst_tag_list_get_string (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gchar ** value);
|
||||
gboolean gst_tag_list_get_string_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gchar ** value);
|
||||
gboolean gst_tag_list_get_pointer (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gpointer * value);
|
||||
gboolean gst_tag_list_get_pointer_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gpointer * value);
|
||||
|
||||
/* tag events */
|
||||
GstEvent * gst_event_new_tag (GstTagList * list);
|
||||
GstTagList * gst_event_tag_get_list (GstEvent * tag_event);
|
||||
|
||||
|
||||
/* GStreamer core tags (need to be discussed) */
|
||||
#define GST_TAG_TITLE "title"
|
||||
#define GST_TAG_ARTIST "artist"
|
||||
#define GST_TAG_ALBUM "album"
|
||||
#define GST_TAG_DATE "date"
|
||||
#define GST_TAG_GENRE "genre"
|
||||
#define GST_TAG_COMMENT "comment"
|
||||
#define GST_TAG_TRACK_NUMBER "track-number"
|
||||
#define GST_TAG_TRACK_COUNT "track-count"
|
||||
#define GST_TAG_LOCATION "location"
|
||||
#define GST_TAG_DESCRIPTION "description"
|
||||
#define GST_TAG_VERSION "version"
|
||||
#define GST_TAG_ISRC "isrc"
|
||||
#define GST_TAG_ORGANIZATION "organization"
|
||||
#define GST_TAG_COPYRIGHT "copyright"
|
||||
#define GST_TAG_CONTACT "contact"
|
||||
#define GST_TAG_LICENSE "license"
|
||||
#define GST_TAG_PERFORMER "performer"
|
||||
#define GST_TAG_DURATION "duration"
|
||||
#define GST_TAG_CODEC "codec"
|
||||
#define GST_TAG_BITRATE "bitrate"
|
||||
#define GST_TAG_MINIMUM_BITRATE "minimum-bitrate"
|
||||
#define GST_TAG_MAXIMUM_BITRATE "maximum-bitrate"
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_EVENT_H__ */
|
214
gst/gsttaginterface.c
Normal file
214
gst/gsttaginterface.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
*
|
||||
* gsttaginterface.c: interface for tag setting on elements
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gsttaginterface.h"
|
||||
#include <gobject/gvaluecollector.h>
|
||||
#include <string.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_tag_interface_debug);
|
||||
#define GST_CAT_DEFAULT tag_tag_interface_debug
|
||||
|
||||
static GQuark gst_tag_key;
|
||||
|
||||
typedef struct {
|
||||
GstTagMergeMode mode;
|
||||
GstTagList * list;
|
||||
} GstTagData;
|
||||
|
||||
GType
|
||||
gst_tag_setter_get_type (void)
|
||||
{
|
||||
static GType tag_setter_type = 0;
|
||||
|
||||
if (! tag_setter_type) {
|
||||
static const GTypeInfo tag_setter_info = {
|
||||
sizeof (GstTagSetterIFace), /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
NULL,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0,
|
||||
0,
|
||||
NULL
|
||||
};
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_tag_interface_debug, "GstTagInterface", 0, "interfaces for tagging");
|
||||
|
||||
tag_setter_type = g_type_register_static (G_TYPE_INTERFACE, "GstTagSetter",
|
||||
&tag_setter_info, 0);
|
||||
|
||||
g_type_interface_add_prerequisite (tag_setter_type, GST_TYPE_ELEMENT);
|
||||
|
||||
gst_tag_key = g_quark_from_static_string ("GST_TAG_SETTER");
|
||||
}
|
||||
|
||||
return tag_setter_type;
|
||||
}
|
||||
static void
|
||||
gst_tag_data_free (gpointer p)
|
||||
{
|
||||
GstTagData *data = (GstTagData *) p;
|
||||
|
||||
if (data->list)
|
||||
gst_tag_list_free (data->list);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
static GstTagData *
|
||||
gst_tag_setter_get_data (GstTagSetter *setter)
|
||||
{
|
||||
GstTagData *data;
|
||||
|
||||
data = g_object_get_qdata (G_OBJECT (setter), gst_tag_key);
|
||||
if (!data) {
|
||||
data = g_new (GstTagData, 1);
|
||||
data->list = NULL;
|
||||
data->mode = GST_TAG_MERGE_KEEP;
|
||||
g_object_set_qdata_full (G_OBJECT (setter), gst_tag_key, data, gst_tag_data_free);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_merge:
|
||||
* @setter: a #GstTagSetter
|
||||
* @list: a tag list to merge from
|
||||
* @mode: the mode to merge with
|
||||
*
|
||||
* Merges the given list into the setter's list using the given mode.
|
||||
*/
|
||||
void
|
||||
gst_tag_setter_merge (GstTagSetter *setter, const GstTagList *list, GstTagMergeMode mode)
|
||||
{
|
||||
GstTagData *data;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_SETTER (setter));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
|
||||
data = gst_tag_setter_get_data (setter);
|
||||
if (!data->list) {
|
||||
data->list = gst_tag_list_copy (list);
|
||||
} else {
|
||||
gst_tag_list_merge (data->list, list, mode);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_add:
|
||||
* @setter: a #GstTagSetter
|
||||
* @mode: the mode to use
|
||||
* @tag: tag to set
|
||||
* @...: more tag / value pairs to set
|
||||
*
|
||||
* Adds the given tag / value pairs on the setter using the given merge mode.
|
||||
* The list must be terminated with GST_TAG_INVALID.
|
||||
*/
|
||||
void
|
||||
gst_tag_setter_add (GstTagSetter *setter, GstTagMergeMode mode, const gchar *tag, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_SETTER (setter));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
|
||||
va_start (args, tag);
|
||||
gst_tag_setter_add_valist (setter, mode, tag, args);
|
||||
va_end (args);
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_add_valist:
|
||||
* @setter: a #GstTagSetter
|
||||
* @mode: the mode to use
|
||||
* @tag: tag to set
|
||||
* @var_args: tag / value pairs to set
|
||||
*
|
||||
* Adds the given tag / value pairs on the setter using the given merge mode.
|
||||
* The list must be terminated with GST_TAG_INVALID.
|
||||
*/
|
||||
void
|
||||
gst_tag_setter_add_valist (GstTagSetter *setter, GstTagMergeMode mode, const gchar *tag, va_list var_args)
|
||||
{
|
||||
GstTagData *data;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_SETTER (setter));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
|
||||
data = gst_tag_setter_get_data (setter);
|
||||
if (!data->list)
|
||||
data->list = gst_tag_list_new ();
|
||||
|
||||
gst_tag_list_add_valist (data->list, mode, tag, var_args);
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_get_list:
|
||||
* @setter: a #GstTagSetter
|
||||
*
|
||||
* Retrieves a copy of the current list of tags the setter uses.
|
||||
* You need to gst_tag_list_free() the list after use.
|
||||
*
|
||||
* Returns: a current snapshot of the taglist used in the setter
|
||||
* or NULL if none is used.
|
||||
*/
|
||||
const GstTagList *
|
||||
gst_tag_setter_get_list (GstTagSetter *setter)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_TAG_SETTER (setter), NULL);
|
||||
|
||||
return gst_tag_setter_get_data (setter)->list;
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_set_merge_mode:
|
||||
* @setter: a #GstTagSetter
|
||||
* @overwrite: The mode with which tags are added
|
||||
*
|
||||
* Sets the given merge mode that is used for adding tags from events to tags
|
||||
* specified by this interface. The default is #GST_TAG_MERGE_KEEP, which keeps
|
||||
* the tags by this interface and discards tags from events.
|
||||
*/
|
||||
void
|
||||
gst_tag_setter_set_merge_mode (GstTagSetter *setter, GstTagMergeMode mode)
|
||||
{
|
||||
g_return_if_fail (GST_IS_TAG_SETTER (setter));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
|
||||
gst_tag_setter_get_data (setter)->mode = mode;
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_get_merge_mode:
|
||||
* @setter: a #GstTagSetter
|
||||
*
|
||||
* Queries the mode by which tags inside the setter are overwritten by tags
|
||||
* from events
|
||||
*
|
||||
* Returns: the merge mode used inside the element.
|
||||
*/
|
||||
GstTagMergeMode
|
||||
gst_tag_setter_get_merge_mode (GstTagSetter *setter)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_TAG_SETTER (setter), FALSE);
|
||||
|
||||
return gst_tag_setter_get_data (setter)->mode;
|
||||
}
|
70
gst/gsttaginterface.h
Normal file
70
gst/gsttaginterface.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
*
|
||||
* gsttaginterface.h: Interfaces for tagging
|
||||
*
|
||||
* 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_TAG_INTERFACE_H__
|
||||
#define __GST_TAG_INTERFACE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_TAG_SETTER (gst_tag_setter_get_type ())
|
||||
#define GST_TAG_SETTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TAG_SETTER, GstTagSetter))
|
||||
#define GST_TAG_SETTER_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GST_TYPE_TAG_SETTER, GstTagSetter))
|
||||
#define GST_IS_TAG_SETTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TAG_SETTER))
|
||||
#define GST_TAG_SETTER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_TAG_SETTER, GstTagSetterIFace))
|
||||
|
||||
typedef struct _GstTagSetter GstTagSetter; /* Dummy typedef */
|
||||
typedef struct _GstTagSetterIFace GstTagSetterIFace;
|
||||
|
||||
/* use an empty interface here to allow detection of elements using user-set
|
||||
tags */
|
||||
struct _GstTagSetterIFace
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
|
||||
/* signals */
|
||||
|
||||
/* virtual table */
|
||||
};
|
||||
|
||||
GType gst_tag_setter_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void gst_tag_setter_merge (GstTagSetter * setter,
|
||||
const GstTagList * list,
|
||||
GstTagMergeMode mode);
|
||||
void gst_tag_setter_add (GstTagSetter * setter,
|
||||
GstTagMergeMode mode,
|
||||
const gchar * tag,
|
||||
...);
|
||||
void gst_tag_setter_add_valist (GstTagSetter * setter,
|
||||
GstTagMergeMode mode,
|
||||
const gchar * tag,
|
||||
va_list var_args);
|
||||
const GstTagList *gst_tag_setter_get_list (GstTagSetter * setter);
|
||||
|
||||
void gst_tag_setter_set_merge_mode (GstTagSetter * setter,
|
||||
GstTagMergeMode mode);
|
||||
GstTagMergeMode gst_tag_setter_get_merge_mode (GstTagSetter * setter);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_TAG_INTERFACE_H__ */
|
831
gst/gsttaglist.c
Normal file
831
gst/gsttaglist.c
Normal file
|
@ -0,0 +1,831 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
*
|
||||
* gsttag.c: tag support (aka metadata)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gst_private.h"
|
||||
#include "gsttag.h"
|
||||
#include "gstinfo.h"
|
||||
#include "gstvalue.h"
|
||||
|
||||
#include <gobject/gvaluecollector.h>
|
||||
#include <string.h>
|
||||
|
||||
#define GST_TAG_IS_VALID(tag) (gst_tag_get_info (tag) != NULL)
|
||||
|
||||
typedef struct {
|
||||
GType type; /* type the data is in */
|
||||
|
||||
gchar * nick; /* translated name */
|
||||
gchar * blurb; /* translated description of type */
|
||||
|
||||
GstTagMergeFunc merge_func; /* functions to merge the values */
|
||||
} GstTagInfo;
|
||||
|
||||
#define TAGLIST "taglist"
|
||||
static GQuark gst_tag_list_quark;
|
||||
static GMutex *__tag_mutex;
|
||||
static GHashTable *__tags;
|
||||
#define TAG_LOCK g_mutex_lock (__tag_mutex)
|
||||
#define TAG_UNLOCK g_mutex_unlock (__tag_mutex)
|
||||
|
||||
void
|
||||
_gst_tag_initialize (void)
|
||||
{
|
||||
gst_tag_list_quark = g_quark_from_static_string (TAGLIST);
|
||||
__tag_mutex = g_mutex_new ();
|
||||
__tags = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
gst_tag_register (GST_TAG_TITLE,
|
||||
G_TYPE_STRING,
|
||||
_("title"),
|
||||
_("commonly used title"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_ARTIST,
|
||||
G_TYPE_STRING,
|
||||
_("artist"),
|
||||
_("person(s) resposible for the recording"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_ALBUM,
|
||||
G_TYPE_STRING,
|
||||
_("album"),
|
||||
_("album containing this data"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_DATE,
|
||||
G_TYPE_UINT, /* FIXME: own data type for dates? */
|
||||
_("date"),
|
||||
_("date the data was created in julien days"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_GENRE,
|
||||
G_TYPE_STRING,
|
||||
_("genre"),
|
||||
_("genre this data belongs to"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_COMMENT,
|
||||
G_TYPE_STRING,
|
||||
_("comment"),
|
||||
_("free text commenting the data"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_TRACK_NUMBER,
|
||||
G_TYPE_UINT,
|
||||
_("track number"),
|
||||
_("track number inside a collection"),
|
||||
gst_tag_merge_use_first);
|
||||
gst_tag_register (GST_TAG_TRACK_COUNT,
|
||||
G_TYPE_STRING,
|
||||
_("track count"),
|
||||
_("count of tracks inside collection this track belongs to"),
|
||||
gst_tag_merge_use_first);
|
||||
gst_tag_register (GST_TAG_LOCATION,
|
||||
G_TYPE_STRING,
|
||||
_("loccation"),
|
||||
_("original location of file as a URI"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_DESCRIPTION,
|
||||
G_TYPE_STRING,
|
||||
_("description"),
|
||||
_("short text describing the content of the data"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_VERSION,
|
||||
G_TYPE_STRING,
|
||||
_("version"),
|
||||
_("version of this data"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_ISRC,
|
||||
G_TYPE_STRING,
|
||||
_("ISRC"),
|
||||
_("International Standard Recording Code - see http://www.ifpi.org/isrc/"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_ORGANIZATION,
|
||||
G_TYPE_STRING,
|
||||
_("organization"),
|
||||
_("organization"), /* FIXME */
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_COPYRIGHT,
|
||||
G_TYPE_STRING,
|
||||
_("copyright"),
|
||||
_("copyright notice of the data"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_CONTACT,
|
||||
G_TYPE_STRING,
|
||||
_("contact"),
|
||||
_("contact information"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_LICENSE,
|
||||
G_TYPE_STRING,
|
||||
_("license"),
|
||||
_("license of data"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_PERFORMER,
|
||||
G_TYPE_STRING,
|
||||
_("performer"),
|
||||
_("person(s) performing"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_DURATION,
|
||||
G_TYPE_UINT64,
|
||||
_("duration"),
|
||||
_("length in GStreamer time units (nanoseconds)"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_CODEC,
|
||||
G_TYPE_STRING,
|
||||
_("codec"),
|
||||
_("codec the data is stored in"),
|
||||
gst_tag_merge_strings_with_comma);
|
||||
gst_tag_register (GST_TAG_MINIMUM_BITRATE,
|
||||
G_TYPE_UINT,
|
||||
_("minimum bitrate"),
|
||||
_("minimum bitrate in bits/s"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_BITRATE,
|
||||
G_TYPE_UINT,
|
||||
_("bitrate"),
|
||||
_("exact or average bitrate in bits/s"),
|
||||
NULL);
|
||||
gst_tag_register (GST_TAG_MAXIMUM_BITRATE,
|
||||
G_TYPE_UINT,
|
||||
_("maximum bitrate"),
|
||||
_("maximum bitrate in bits/s"),
|
||||
NULL);
|
||||
}
|
||||
/**
|
||||
* gst_tag_merge_use_first:
|
||||
* @dest: uninitialized GValue to store result in
|
||||
* @src: GValue to copy from
|
||||
*
|
||||
* This is a convenience function for the func argument of gst_tag_register().
|
||||
* It creates a copy of the first value from the list.
|
||||
*/
|
||||
void
|
||||
gst_tag_merge_use_first (GValue *dest, const GValue *src)
|
||||
{
|
||||
const GValue *ret = gst_value_list_get_value (src, 0);
|
||||
|
||||
g_value_init (dest, G_VALUE_TYPE (ret));
|
||||
g_value_copy (ret, dest);
|
||||
}
|
||||
/**
|
||||
* gst_tag_merge_strings_with_comma:
|
||||
* @dest: uninitialized GValue to store result in
|
||||
* @src: GValue to copy from
|
||||
*
|
||||
* This is a convenience function for the func argument of gst_tag_register().
|
||||
* It concatenates all given strings using a comma. The tag must be registered
|
||||
* as a G_TYPE_STRING or this function will fail.
|
||||
*/
|
||||
void
|
||||
gst_tag_merge_strings_with_comma (GValue *dest, const GValue *src)
|
||||
{
|
||||
GString *str;
|
||||
gint i, count;
|
||||
|
||||
count = gst_value_list_get_size (src);
|
||||
str = g_string_new (g_value_get_string (gst_value_list_get_value (src, 0)));
|
||||
for (i = 1; i < count; i++) {
|
||||
/* seperator between two string */
|
||||
str = g_string_append (str, _(", "));
|
||||
str = g_string_append (str, g_value_get_string (gst_value_list_get_value (src, 1)));
|
||||
}
|
||||
|
||||
g_value_init (dest, G_TYPE_STRING);
|
||||
g_value_take_string (dest, str->str);
|
||||
g_string_free (str, FALSE);
|
||||
}
|
||||
static GstTagInfo *
|
||||
gst_tag_lookup (GQuark entry)
|
||||
{
|
||||
GstTagInfo *ret;
|
||||
|
||||
TAG_LOCK;
|
||||
ret = g_hash_table_lookup (__tags, GUINT_TO_POINTER (entry));
|
||||
TAG_UNLOCK;
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* gst_tag_register:
|
||||
* @name: the name or identifier string
|
||||
* @type: the type this data is in
|
||||
* @nick: human-readable name
|
||||
* @blurb: a human-readable description about this tag
|
||||
* @func: function for merging multiple values of this tag
|
||||
*
|
||||
* Registers a new tag type for the use with GStreamer's type system. If a type
|
||||
* with that name is already registered, that one is used.
|
||||
* The old registration may have used a different type however. So don't rely
|
||||
* on youre supplied values.
|
||||
* If you know the type is already registered, use gst_tag_lookup instead.
|
||||
* This function takes ownership of all supplied variables.
|
||||
*/
|
||||
void
|
||||
gst_tag_register (gchar *name, GType type, gchar *nick, gchar *blurb,
|
||||
GstTagMergeFunc func)
|
||||
{
|
||||
GQuark key;
|
||||
GstTagInfo *info;
|
||||
|
||||
g_return_if_fail (name != NULL);
|
||||
g_return_if_fail (nick != NULL);
|
||||
g_return_if_fail (blurb != NULL);
|
||||
g_return_if_fail (type != 0 && type != GST_VALUE_TYPE_LIST);
|
||||
|
||||
key = g_quark_from_string (name);
|
||||
info = gst_tag_lookup (key);
|
||||
g_return_if_fail (info == NULL);
|
||||
|
||||
info = g_new (GstTagInfo, 1);
|
||||
info->type = type;
|
||||
info->nick = nick;
|
||||
info->blurb = blurb;
|
||||
info->merge_func = func;
|
||||
|
||||
TAG_LOCK;
|
||||
g_hash_table_insert (__tags, GUINT_TO_POINTER (key), info);
|
||||
TAG_UNLOCK;
|
||||
}
|
||||
/**
|
||||
* gst_tag_exists:
|
||||
* @tag: name of the tag
|
||||
*
|
||||
* Checks if the given type is already registered.
|
||||
*
|
||||
* Returns: TRUE if the type is already registered
|
||||
*/
|
||||
gboolean
|
||||
gst_tag_exists (const gchar *tag)
|
||||
{
|
||||
g_return_val_if_fail (tag != NULL, FALSE);
|
||||
|
||||
return gst_tag_lookup (g_quark_from_string (tag)) != NULL;
|
||||
}
|
||||
/**
|
||||
* gst_tag_get_type:
|
||||
* @tag: the tag
|
||||
*
|
||||
* Gets the #GType used for this tag.
|
||||
*
|
||||
* Returns: the #GType of this tag
|
||||
*/
|
||||
GType
|
||||
gst_tag_get_type (const gchar *tag)
|
||||
{
|
||||
GstTagInfo *info;
|
||||
|
||||
g_return_val_if_fail (tag != NULL, 0);
|
||||
info = gst_tag_lookup (g_quark_from_string (tag));
|
||||
g_return_val_if_fail (info != NULL, 0);
|
||||
|
||||
return info->type;
|
||||
}
|
||||
/**
|
||||
* gst_tag_get_nick
|
||||
* @tag: the tag
|
||||
*
|
||||
* Returns the human-readable name of this tag, You must not change or free
|
||||
* this string.
|
||||
*
|
||||
* Returns: the human-readable name of this tag
|
||||
*/
|
||||
const gchar *
|
||||
gst_tag_get_nick (const gchar *tag)
|
||||
{
|
||||
GstTagInfo *info;
|
||||
|
||||
g_return_val_if_fail (tag != NULL, NULL);
|
||||
info = gst_tag_lookup (g_quark_from_string (tag));
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->nick;
|
||||
}
|
||||
/**
|
||||
* gst_tag_get_description:
|
||||
* @tag: the tag
|
||||
*
|
||||
* Returns the human-readable description of this tag, You must not change or
|
||||
* free this string.
|
||||
*
|
||||
* Return the human-readable description of this tag
|
||||
*/
|
||||
const gchar *
|
||||
gst_tag_get_description (const gchar *tag)
|
||||
{
|
||||
GstTagInfo *info;
|
||||
|
||||
g_return_val_if_fail (tag != NULL, NULL);
|
||||
info = gst_tag_lookup (g_quark_from_string (tag));
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->blurb;
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_is_fixed:
|
||||
* @tag: tag to check
|
||||
*
|
||||
* Checks if the given tag is fixed. A fixed tag can only contain one value.
|
||||
* Unfixed tags can contain lists of values.
|
||||
*
|
||||
* Returns: TRUE, if the given tag is fixed.
|
||||
*/
|
||||
gboolean
|
||||
gst_tag_is_fixed (const gchar *tag)
|
||||
{
|
||||
GstTagInfo *info;
|
||||
|
||||
g_return_val_if_fail (tag != NULL, FALSE);
|
||||
info = gst_tag_lookup (g_quark_from_string (tag));
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
|
||||
return info->merge_func == NULL;
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_new:
|
||||
*
|
||||
* Creates a new empty GstTagList.
|
||||
*
|
||||
* Returns: An empty tag list
|
||||
*/
|
||||
GstTagList *
|
||||
gst_tag_list_new (void)
|
||||
{
|
||||
return GST_TAG_LIST (gst_structure_new (TAGLIST, NULL));
|
||||
}
|
||||
/**
|
||||
* gst_is_tag_list:
|
||||
* @p: Object that might be a taglist
|
||||
*
|
||||
* Checks if the given pointer is a taglist.
|
||||
*
|
||||
* Returns: TRUE, if the given pointer is a taglist
|
||||
*/
|
||||
gboolean
|
||||
gst_is_tag_list (gconstpointer p)
|
||||
{
|
||||
g_return_val_if_fail (p != NULL, FALSE);
|
||||
|
||||
return ((GstStructure *) p)->name == gst_tag_list_quark;
|
||||
}
|
||||
typedef struct {
|
||||
GstStructure * list;
|
||||
GstTagMergeMode mode;
|
||||
} GstTagCopyData;
|
||||
static void
|
||||
gst_tag_list_add_value_internal (GstStructure *list, GstTagMergeMode mode, GQuark tag, GValue *value)
|
||||
{
|
||||
GstTagInfo *info = gst_tag_lookup (tag);
|
||||
GstStructureField *field;
|
||||
|
||||
g_assert (info != NULL);
|
||||
|
||||
if (info->merge_func && (field = gst_structure_id_get_field (list, tag)) != NULL) {
|
||||
GValue value2 = { 0, };
|
||||
switch (mode) {
|
||||
case GST_TAG_MERGE_REPLACE_ALL:
|
||||
case GST_TAG_MERGE_REPLACE:
|
||||
gst_structure_id_set_value (list, tag, value);
|
||||
break;
|
||||
case GST_TAG_MERGE_PREPEND:
|
||||
gst_value_list_concat (&value2, value, &field->value);
|
||||
gst_structure_id_set_value (list, tag, &value2);
|
||||
g_value_unset (&value2);
|
||||
break;
|
||||
case GST_TAG_MERGE_APPEND:
|
||||
gst_value_list_concat (&value2, &field->value, value);
|
||||
gst_structure_id_set_value (list, tag, &value2);
|
||||
g_value_unset (&value2);
|
||||
break;
|
||||
case GST_TAG_MERGE_KEEP:
|
||||
case GST_TAG_MERGE_KEEP_ALL:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (mode) {
|
||||
case GST_TAG_MERGE_APPEND:
|
||||
case GST_TAG_MERGE_KEEP:
|
||||
if (gst_structure_id_get_field (list, tag) != NULL)
|
||||
break;
|
||||
/* fall through */
|
||||
case GST_TAG_MERGE_REPLACE_ALL:
|
||||
case GST_TAG_MERGE_REPLACE:
|
||||
case GST_TAG_MERGE_PREPEND:
|
||||
gst_structure_id_set_value (list, tag, value);
|
||||
break;
|
||||
case GST_TAG_MERGE_KEEP_ALL:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void
|
||||
gst_tag_list_copy_foreach (GstStructure *structure, GQuark tag, GValue *value, gpointer user_data)
|
||||
{
|
||||
GstTagCopyData *copy = (GstTagCopyData *) user_data;
|
||||
|
||||
gst_tag_list_add_value_internal (copy->list, copy->mode, tag, value);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_insert:
|
||||
* @into: list to merge into
|
||||
* @from: list to merge from
|
||||
* @mode: the mode to use
|
||||
*
|
||||
* Inserts the tags of the second list into the first list using the given mode.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_insert (GstTagList *into, const GstTagList *from, GstTagMergeMode mode)
|
||||
{
|
||||
GstTagCopyData data;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_LIST (into));
|
||||
g_return_if_fail (GST_IS_TAG_LIST (from));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
|
||||
data.list = (GstStructure *) into;
|
||||
data.mode = mode;
|
||||
if (mode == GST_TAG_MERGE_REPLACE_ALL) {
|
||||
gst_structure_remove_all_fields (data.list);
|
||||
}
|
||||
gst_structure_field_foreach ((GstStructure *) from, gst_tag_list_copy_foreach, &data);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_copy:
|
||||
* @list: list to copy
|
||||
*
|
||||
* Copies a given #GstTagList.
|
||||
*
|
||||
* Returns: copy of the given list
|
||||
*/
|
||||
GstTagList *
|
||||
gst_tag_list_copy (const GstTagList *list)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
|
||||
|
||||
return GST_TAG_LIST (gst_structure_copy ((GstStructure *) list));
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_merge:
|
||||
* @list1: first list to merge
|
||||
* @list2: second list to merge
|
||||
* @mode: the mode to use
|
||||
*
|
||||
* Merges the two given lists into a new list. If one of the lists is NULL, a
|
||||
* copy of the other is returned. If both lists are NULL, NULL is returned.
|
||||
*
|
||||
* Returns: the new list
|
||||
*/
|
||||
GstTagList *
|
||||
gst_tag_list_merge (const GstTagList *list1, const GstTagList *list2, GstTagMergeMode mode)
|
||||
{
|
||||
g_return_val_if_fail (list1 == NULL || GST_IS_TAG_LIST (list1), NULL);
|
||||
g_return_val_if_fail (list2 == NULL || GST_IS_TAG_LIST (list2), NULL);
|
||||
g_return_val_if_fail (GST_TAG_MODE_IS_VALID (mode), NULL);
|
||||
|
||||
if (!list1 && !list2) {
|
||||
return NULL;
|
||||
} else if (!list1) {
|
||||
return gst_tag_list_copy (list2);
|
||||
} else if (!list2) {
|
||||
return gst_tag_list_copy (list1);
|
||||
} else {
|
||||
GstTagList *ret;
|
||||
|
||||
ret = gst_tag_list_copy (list1);
|
||||
gst_tag_list_insert (ret, list2, mode);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_free:
|
||||
* @list: the list to free
|
||||
*
|
||||
* Frees the given list and all associated values.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_free (GstTagList *list)
|
||||
{
|
||||
g_return_if_fail (GST_IS_TAG_LIST (list));
|
||||
gst_structure_free ((GstStructure *) list);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_get_tag_size:
|
||||
* @list: a taglist
|
||||
* @tag: the tag to query
|
||||
*
|
||||
* Checks how many value are stored in this tag list for the given tag.
|
||||
*
|
||||
* Returns: The number of tags stored
|
||||
*/
|
||||
guint
|
||||
gst_tag_list_get_tag_size (const GstTagList *list, const gchar *tag)
|
||||
{
|
||||
const GValue *value;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), 0);
|
||||
|
||||
value = gst_structure_get_value ((GstStructure *) list, tag);
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
if (G_VALUE_TYPE (value) != GST_VALUE_TYPE_LIST)
|
||||
return 1;
|
||||
|
||||
return gst_value_list_get_size (value);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_add:
|
||||
* @list: list to set tags in
|
||||
* @mode: the mode to use
|
||||
* @tag: tag
|
||||
* @...: values to set
|
||||
*
|
||||
* Sets the values for the given tags using the specified mode.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_add (GstTagList *list, GstTagMergeMode mode, const gchar *tag, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_LIST (list));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
g_return_if_fail (tag != NULL);
|
||||
|
||||
va_start (args, tag);
|
||||
gst_tag_list_add_valist (list, mode, tag, args);
|
||||
va_end (args);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_add_valist:
|
||||
* @list: list to set tags in
|
||||
* @mode: the mode to use
|
||||
* @tag: tag
|
||||
* @var_args: tag / value pairs to set
|
||||
*
|
||||
* Sets the values for the given tags using the specified mode.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_add_valist (GstTagList *list, GstTagMergeMode mode, const gchar *tag, va_list var_args)
|
||||
{
|
||||
GstTagInfo *info;
|
||||
GQuark quark;
|
||||
gchar *error = NULL;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_LIST (list));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
g_return_if_fail (tag != NULL);
|
||||
|
||||
while (tag != NULL) {
|
||||
GValue value = { 0, };
|
||||
quark = g_quark_from_string (tag);
|
||||
info = gst_tag_lookup (quark);
|
||||
g_return_if_fail (info != NULL);
|
||||
g_value_init (&value, info->type);
|
||||
G_VALUE_COLLECT (&value, var_args, 0, &error);
|
||||
if (error) {
|
||||
g_warning ("%s: %s", G_STRLOC, error);
|
||||
g_free (error);
|
||||
/* we purposely leak the value here, it might not be
|
||||
* in a sane state if an error condition occoured
|
||||
*/
|
||||
return;
|
||||
}
|
||||
gst_tag_list_add_value_internal (list, mode, quark, &value);
|
||||
g_value_unset (&value);
|
||||
tag = va_arg (var_args, gchar *);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_remove_tag:
|
||||
* @list: list to remove tag from
|
||||
* @tag: tag to remove
|
||||
*
|
||||
* Removes the goven tag from the taglist.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_remove_tag (GstTagList *list, const gchar *tag)
|
||||
{
|
||||
g_return_if_fail (GST_IS_TAG_LIST (list));
|
||||
g_return_if_fail (tag != NULL);
|
||||
|
||||
gst_structure_remove_field ((GstStructure *) list, tag);
|
||||
}
|
||||
typedef struct {
|
||||
GstTagForeachFunc func;
|
||||
gpointer data;
|
||||
} TagForeachData;
|
||||
static void
|
||||
structure_foreach_wrapper (GstStructure *structure, GQuark field_id,
|
||||
GValue *value, gpointer user_data)
|
||||
{
|
||||
TagForeachData *data = (TagForeachData *) user_data;
|
||||
data->func (GST_TAG_LIST (structure), g_quark_to_string (field_id), data->data);
|
||||
}
|
||||
/**
|
||||
* gst_tag_list_foreach:
|
||||
* @list: list to iterate over
|
||||
* @func: function to be called for each tag
|
||||
* @user_data: user specified data
|
||||
*
|
||||
* Calls the given function for each tag inside the tag list. Note that if there
|
||||
* is no tag, the function won't be called at all.
|
||||
*/
|
||||
void
|
||||
gst_tag_list_foreach (GstTagList *list, GstTagForeachFunc func, gpointer user_data)
|
||||
{
|
||||
TagForeachData data;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_LIST (list));
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
data.func = func;
|
||||
data.data = user_data;
|
||||
gst_structure_field_foreach ((GstStructure *) list, structure_foreach_wrapper, &data);
|
||||
}
|
||||
|
||||
/***** tag events *****/
|
||||
|
||||
/**
|
||||
* gst_event_new_tag:
|
||||
* @list: the tag list to put into the event or NULL for an empty list
|
||||
*
|
||||
* Creates a new tag event with the given list and takes ownership of it.
|
||||
*
|
||||
* Returns: a new tag event
|
||||
*/
|
||||
GstEvent *
|
||||
gst_event_new_tag (GstTagList *list)
|
||||
{
|
||||
GstEvent *ret;
|
||||
|
||||
g_return_val_if_fail (list == NULL || GST_IS_TAG_LIST (list), NULL);
|
||||
|
||||
ret = gst_event_new (GST_EVENT_TAG);
|
||||
if (!list)
|
||||
list = gst_tag_list_new ();
|
||||
ret->event_data.structure.structure = (GstStructure *) list;
|
||||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* get_event_tag_get_list:
|
||||
* @tag_event: a tagging #GstEvent
|
||||
*
|
||||
* Gets the taglist from a given tagging event.
|
||||
*
|
||||
* Returns: The #GstTagList of the event
|
||||
*/
|
||||
GstTagList *
|
||||
gst_event_tag_get_list (GstEvent *tag_event)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_EVENT (tag_event), NULL);
|
||||
g_return_val_if_fail (GST_EVENT_TYPE (tag_event) == GST_EVENT_TAG, NULL);
|
||||
|
||||
return GST_TAG_LIST (tag_event->event_data.structure.structure);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_tag_list_get_value_index:
|
||||
* @list: a #GStTagList
|
||||
* @tag: tag to read out
|
||||
* @index: number of entry to read out
|
||||
*
|
||||
* Gets the value that is at the given index for the given tag in the given
|
||||
* list.
|
||||
*
|
||||
* Returns: The GValue for the specified entry or NULL if the tag wasn't available
|
||||
* or the tag doesn't have as many entries
|
||||
*/
|
||||
G_CONST_RETURN GValue *
|
||||
gst_tag_list_get_value_index (const GstTagList *list, const gchar *tag, guint index)
|
||||
{
|
||||
const GValue *value;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL);
|
||||
g_return_val_if_fail (tag != NULL, NULL);
|
||||
|
||||
value = gst_structure_get_value ((GstStructure *) list, tag);
|
||||
if (value == NULL) return NULL;
|
||||
|
||||
if (GST_VALUE_HOLDS_LIST (value)) {
|
||||
if (index >= gst_value_list_get_size (value)) return NULL;
|
||||
return gst_value_list_get_value (value, index);
|
||||
} else {
|
||||
if (index > 0) return NULL;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_tag_list_copy_value:
|
||||
* @dest: uninitialized #GValue to copy into
|
||||
* @list: list to get the tag from
|
||||
* @tag: tag to read out
|
||||
*
|
||||
* Copies the contents for the given tag into the value, merging multiple values
|
||||
* into one if multiple values are associated with the tag.
|
||||
* You must g_value_unset() the value after use.
|
||||
*
|
||||
* Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the
|
||||
* given list.
|
||||
*/
|
||||
gboolean
|
||||
gst_tag_list_copy_value (GValue *dest, const GstTagList *list, const gchar *tag)
|
||||
{
|
||||
const GValue *src;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE);
|
||||
g_return_val_if_fail (tag != NULL, FALSE);
|
||||
g_return_val_if_fail (dest != NULL, FALSE);
|
||||
g_return_val_if_fail (G_VALUE_TYPE (dest) == 0, FALSE);
|
||||
|
||||
src = gst_structure_get_value ((GstStructure *) list, tag);
|
||||
if (!src) return FALSE;
|
||||
|
||||
if (G_VALUE_TYPE (src) == GST_VALUE_TYPE_LIST) {
|
||||
GstTagInfo *info = gst_tag_lookup (g_quark_from_string (tag));
|
||||
/* must be there or lists aren't allowed */
|
||||
g_assert (info->merge_func);
|
||||
info->merge_func (dest, src);
|
||||
} else {
|
||||
g_value_init (dest, G_VALUE_TYPE (src));
|
||||
g_value_copy (src, dest);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***** evil macros to get all the gst_tag_list_get_*() functions right *****/
|
||||
|
||||
#define TAG_MERGE_FUNCS(name,type) \
|
||||
gboolean \
|
||||
gst_tag_list_get_ ## name (const GstTagList *list, const gchar *tag, \
|
||||
type *value) \
|
||||
{ \
|
||||
GValue v = { 0, }; \
|
||||
\
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); \
|
||||
g_return_val_if_fail (tag != NULL, FALSE); \
|
||||
g_return_val_if_fail (value != NULL, FALSE); \
|
||||
\
|
||||
if (!gst_tag_list_copy_value (&v, list, tag)) \
|
||||
return FALSE; \
|
||||
*value = COPY_FUNC (g_value_get_ ## name (&v)); \
|
||||
g_value_unset (&v); \
|
||||
return TRUE; \
|
||||
} \
|
||||
\
|
||||
gboolean \
|
||||
gst_tag_list_get_ ## name ## _index (const GstTagList *list, const gchar *tag, \
|
||||
guint index, type *value) \
|
||||
{ \
|
||||
const GValue *v; \
|
||||
\
|
||||
g_return_val_if_fail (GST_IS_TAG_LIST (list), FALSE); \
|
||||
g_return_val_if_fail (tag != NULL, FALSE); \
|
||||
g_return_val_if_fail (value != NULL, FALSE); \
|
||||
\
|
||||
if ((v = gst_tag_list_get_value_index (list, tag, index)) == NULL) \
|
||||
return FALSE; \
|
||||
*value = COPY_FUNC (g_value_get_ ## name (v)); \
|
||||
return TRUE; \
|
||||
}
|
||||
|
||||
#define COPY_FUNC /**/
|
||||
TAG_MERGE_FUNCS (char, gchar)
|
||||
TAG_MERGE_FUNCS (uchar, guchar)
|
||||
TAG_MERGE_FUNCS (boolean, gboolean)
|
||||
TAG_MERGE_FUNCS (int, gint)
|
||||
TAG_MERGE_FUNCS (uint, guint)
|
||||
TAG_MERGE_FUNCS (long, glong)
|
||||
TAG_MERGE_FUNCS (ulong, gulong)
|
||||
TAG_MERGE_FUNCS (int64, gint64)
|
||||
TAG_MERGE_FUNCS (uint64, guint64)
|
||||
TAG_MERGE_FUNCS (float, gfloat)
|
||||
TAG_MERGE_FUNCS (double, gdouble)
|
||||
#undef COPY_FUNC
|
||||
|
||||
#define COPY_FUNC g_strdup
|
||||
TAG_MERGE_FUNCS (string, gchar *)
|
||||
|
||||
|
||||
|
||||
|
232
gst/gsttaglist.h
Normal file
232
gst/gsttaglist.h
Normal file
|
@ -0,0 +1,232 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
*
|
||||
* gsttag.h: Header for tag support
|
||||
*
|
||||
* 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_TAG_H__
|
||||
#define __GST_TAG_H__
|
||||
|
||||
#include <gst/gststructure.h>
|
||||
#include <gst/gstevent.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GST_TAG_MERGE_UNDEFINED,
|
||||
GST_TAG_MERGE_REPLACE_ALL,
|
||||
GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_MERGE_APPEND,
|
||||
GST_TAG_MERGE_PREPEND,
|
||||
GST_TAG_MERGE_KEEP,
|
||||
GST_TAG_MERGE_KEEP_ALL,
|
||||
/* add more */
|
||||
GST_TAG_MERGE_COUNT
|
||||
} GstTagMergeMode;
|
||||
#define GST_TAG_MODE_IS_VALID(mode) (((mode) > GST_TAG_MERGE_UNDEFINED) && ((mode) < GST_TAG_MERGE_COUNT))
|
||||
|
||||
typedef GstStructure GstTagList;
|
||||
#define GST_TAG_LIST(x) ((GstTagList *) (x))
|
||||
#define GST_IS_TAG_LIST(x) (gst_is_tag_list (GST_TAG_LIST (x)))
|
||||
|
||||
typedef void (* GstTagForeachFunc) (const GstTagList *list, const gchar *tag, gpointer user_data);
|
||||
typedef void (* GstTagMergeFunc) (GValue *dest, const GValue *src);
|
||||
|
||||
/* initialize tagging system */
|
||||
void _gst_tag_initialize (void);
|
||||
|
||||
void gst_tag_register (gchar * name,
|
||||
GType type,
|
||||
gchar * nick,
|
||||
gchar * blurb,
|
||||
GstTagMergeFunc func);
|
||||
/* some default merging functions */
|
||||
void gst_tag_merge_use_first (GValue * dest,
|
||||
const GValue * values);
|
||||
void gst_tag_merge_strings_with_comma (GValue * dest,
|
||||
const GValue * values);
|
||||
|
||||
/* basic tag support */
|
||||
gboolean gst_tag_exists (const gchar * tag);
|
||||
GType gst_tag_get_type (const gchar * tag);
|
||||
const gchar * gst_tag_get_nick (const gchar * tag);
|
||||
const gchar * gst_tag_get_description (const gchar * tag);
|
||||
gboolean gst_tag_is_fixed (const gchar * tag);
|
||||
|
||||
/* tag lists */
|
||||
GstTagList * gst_tag_list_new (void);
|
||||
gboolean gst_is_tag_list (gconstpointer p);
|
||||
GstTagList * gst_tag_list_copy (const GstTagList * list);
|
||||
void gst_tag_list_insert (GstTagList * into,
|
||||
const GstTagList * from,
|
||||
GstTagMergeMode mode);
|
||||
GstTagList * gst_tag_list_merge (const GstTagList * list1,
|
||||
const GstTagList * list2,
|
||||
GstTagMergeMode mode);
|
||||
void gst_tag_list_free (GstTagList * list);
|
||||
guint gst_tag_list_get_tag_size (const GstTagList * list,
|
||||
const gchar * tag);
|
||||
void gst_tag_list_add (GstTagList * list,
|
||||
GstTagMergeMode mode,
|
||||
const gchar * tag,
|
||||
...);
|
||||
void gst_tag_list_add_valist (GstTagList * list,
|
||||
GstTagMergeMode mode,
|
||||
const gchar * tag,
|
||||
va_list var_args);
|
||||
void gst_tag_list_remove_tag (GstTagList * list,
|
||||
const gchar * tag);
|
||||
void gst_tag_list_foreach (GstTagList * list,
|
||||
GstTagForeachFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
G_CONST_RETURN GValue *
|
||||
gst_tag_list_get_value_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index);
|
||||
gboolean gst_tag_list_copy_value (GValue * dest,
|
||||
const GstTagList * list,
|
||||
const gchar * tag);
|
||||
|
||||
/* simplifications (FIXME: do we want them?) */
|
||||
gboolean gst_tag_list_get_char (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gchar * value);
|
||||
gboolean gst_tag_list_get_char_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gchar * value);
|
||||
gboolean gst_tag_list_get_uchar (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guchar * value);
|
||||
gboolean gst_tag_list_get_uchar_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
guchar * value);
|
||||
gboolean gst_tag_list_get_boolean (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gboolean * value);
|
||||
gboolean gst_tag_list_get_boolean_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gboolean * value);
|
||||
gboolean gst_tag_list_get_int (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gint * value);
|
||||
gboolean gst_tag_list_get_int_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gint * value);
|
||||
gboolean gst_tag_list_get_uint (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint * value);
|
||||
gboolean gst_tag_list_get_uint_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
guint * value);
|
||||
gboolean gst_tag_list_get_long (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
glong * value);
|
||||
gboolean gst_tag_list_get_long_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
glong * value);
|
||||
gboolean gst_tag_list_get_ulong (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gulong * value);
|
||||
gboolean gst_tag_list_get_ulong_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gulong * value);
|
||||
gboolean gst_tag_list_get_int64 (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gint64 * value);
|
||||
gboolean gst_tag_list_get_int64_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gint64 * value);
|
||||
gboolean gst_tag_list_get_uint64 (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint64 * value);
|
||||
gboolean gst_tag_list_get_uint64_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
guint64 * value);
|
||||
gboolean gst_tag_list_get_float (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gfloat * value);
|
||||
gboolean gst_tag_list_get_float_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gfloat * value);
|
||||
gboolean gst_tag_list_get_double (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gdouble * value);
|
||||
gboolean gst_tag_list_get_double_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gdouble * value);
|
||||
gboolean gst_tag_list_get_string (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gchar ** value);
|
||||
gboolean gst_tag_list_get_string_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gchar ** value);
|
||||
gboolean gst_tag_list_get_pointer (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
gpointer * value);
|
||||
gboolean gst_tag_list_get_pointer_index (const GstTagList * list,
|
||||
const gchar * tag,
|
||||
guint index,
|
||||
gpointer * value);
|
||||
|
||||
/* tag events */
|
||||
GstEvent * gst_event_new_tag (GstTagList * list);
|
||||
GstTagList * gst_event_tag_get_list (GstEvent * tag_event);
|
||||
|
||||
|
||||
/* GStreamer core tags (need to be discussed) */
|
||||
#define GST_TAG_TITLE "title"
|
||||
#define GST_TAG_ARTIST "artist"
|
||||
#define GST_TAG_ALBUM "album"
|
||||
#define GST_TAG_DATE "date"
|
||||
#define GST_TAG_GENRE "genre"
|
||||
#define GST_TAG_COMMENT "comment"
|
||||
#define GST_TAG_TRACK_NUMBER "track-number"
|
||||
#define GST_TAG_TRACK_COUNT "track-count"
|
||||
#define GST_TAG_LOCATION "location"
|
||||
#define GST_TAG_DESCRIPTION "description"
|
||||
#define GST_TAG_VERSION "version"
|
||||
#define GST_TAG_ISRC "isrc"
|
||||
#define GST_TAG_ORGANIZATION "organization"
|
||||
#define GST_TAG_COPYRIGHT "copyright"
|
||||
#define GST_TAG_CONTACT "contact"
|
||||
#define GST_TAG_LICENSE "license"
|
||||
#define GST_TAG_PERFORMER "performer"
|
||||
#define GST_TAG_DURATION "duration"
|
||||
#define GST_TAG_CODEC "codec"
|
||||
#define GST_TAG_BITRATE "bitrate"
|
||||
#define GST_TAG_MINIMUM_BITRATE "minimum-bitrate"
|
||||
#define GST_TAG_MAXIMUM_BITRATE "maximum-bitrate"
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_EVENT_H__ */
|
214
gst/gsttagsetter.c
Normal file
214
gst/gsttagsetter.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
*
|
||||
* gsttaginterface.c: interface for tag setting on elements
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gsttaginterface.h"
|
||||
#include <gobject/gvaluecollector.h>
|
||||
#include <string.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_tag_interface_debug);
|
||||
#define GST_CAT_DEFAULT tag_tag_interface_debug
|
||||
|
||||
static GQuark gst_tag_key;
|
||||
|
||||
typedef struct {
|
||||
GstTagMergeMode mode;
|
||||
GstTagList * list;
|
||||
} GstTagData;
|
||||
|
||||
GType
|
||||
gst_tag_setter_get_type (void)
|
||||
{
|
||||
static GType tag_setter_type = 0;
|
||||
|
||||
if (! tag_setter_type) {
|
||||
static const GTypeInfo tag_setter_info = {
|
||||
sizeof (GstTagSetterIFace), /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
NULL,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0,
|
||||
0,
|
||||
NULL
|
||||
};
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_tag_interface_debug, "GstTagInterface", 0, "interfaces for tagging");
|
||||
|
||||
tag_setter_type = g_type_register_static (G_TYPE_INTERFACE, "GstTagSetter",
|
||||
&tag_setter_info, 0);
|
||||
|
||||
g_type_interface_add_prerequisite (tag_setter_type, GST_TYPE_ELEMENT);
|
||||
|
||||
gst_tag_key = g_quark_from_static_string ("GST_TAG_SETTER");
|
||||
}
|
||||
|
||||
return tag_setter_type;
|
||||
}
|
||||
static void
|
||||
gst_tag_data_free (gpointer p)
|
||||
{
|
||||
GstTagData *data = (GstTagData *) p;
|
||||
|
||||
if (data->list)
|
||||
gst_tag_list_free (data->list);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
static GstTagData *
|
||||
gst_tag_setter_get_data (GstTagSetter *setter)
|
||||
{
|
||||
GstTagData *data;
|
||||
|
||||
data = g_object_get_qdata (G_OBJECT (setter), gst_tag_key);
|
||||
if (!data) {
|
||||
data = g_new (GstTagData, 1);
|
||||
data->list = NULL;
|
||||
data->mode = GST_TAG_MERGE_KEEP;
|
||||
g_object_set_qdata_full (G_OBJECT (setter), gst_tag_key, data, gst_tag_data_free);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_merge:
|
||||
* @setter: a #GstTagSetter
|
||||
* @list: a tag list to merge from
|
||||
* @mode: the mode to merge with
|
||||
*
|
||||
* Merges the given list into the setter's list using the given mode.
|
||||
*/
|
||||
void
|
||||
gst_tag_setter_merge (GstTagSetter *setter, const GstTagList *list, GstTagMergeMode mode)
|
||||
{
|
||||
GstTagData *data;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_SETTER (setter));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
|
||||
data = gst_tag_setter_get_data (setter);
|
||||
if (!data->list) {
|
||||
data->list = gst_tag_list_copy (list);
|
||||
} else {
|
||||
gst_tag_list_merge (data->list, list, mode);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_add:
|
||||
* @setter: a #GstTagSetter
|
||||
* @mode: the mode to use
|
||||
* @tag: tag to set
|
||||
* @...: more tag / value pairs to set
|
||||
*
|
||||
* Adds the given tag / value pairs on the setter using the given merge mode.
|
||||
* The list must be terminated with GST_TAG_INVALID.
|
||||
*/
|
||||
void
|
||||
gst_tag_setter_add (GstTagSetter *setter, GstTagMergeMode mode, const gchar *tag, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_SETTER (setter));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
|
||||
va_start (args, tag);
|
||||
gst_tag_setter_add_valist (setter, mode, tag, args);
|
||||
va_end (args);
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_add_valist:
|
||||
* @setter: a #GstTagSetter
|
||||
* @mode: the mode to use
|
||||
* @tag: tag to set
|
||||
* @var_args: tag / value pairs to set
|
||||
*
|
||||
* Adds the given tag / value pairs on the setter using the given merge mode.
|
||||
* The list must be terminated with GST_TAG_INVALID.
|
||||
*/
|
||||
void
|
||||
gst_tag_setter_add_valist (GstTagSetter *setter, GstTagMergeMode mode, const gchar *tag, va_list var_args)
|
||||
{
|
||||
GstTagData *data;
|
||||
|
||||
g_return_if_fail (GST_IS_TAG_SETTER (setter));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
|
||||
data = gst_tag_setter_get_data (setter);
|
||||
if (!data->list)
|
||||
data->list = gst_tag_list_new ();
|
||||
|
||||
gst_tag_list_add_valist (data->list, mode, tag, var_args);
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_get_list:
|
||||
* @setter: a #GstTagSetter
|
||||
*
|
||||
* Retrieves a copy of the current list of tags the setter uses.
|
||||
* You need to gst_tag_list_free() the list after use.
|
||||
*
|
||||
* Returns: a current snapshot of the taglist used in the setter
|
||||
* or NULL if none is used.
|
||||
*/
|
||||
const GstTagList *
|
||||
gst_tag_setter_get_list (GstTagSetter *setter)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_TAG_SETTER (setter), NULL);
|
||||
|
||||
return gst_tag_setter_get_data (setter)->list;
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_set_merge_mode:
|
||||
* @setter: a #GstTagSetter
|
||||
* @overwrite: The mode with which tags are added
|
||||
*
|
||||
* Sets the given merge mode that is used for adding tags from events to tags
|
||||
* specified by this interface. The default is #GST_TAG_MERGE_KEEP, which keeps
|
||||
* the tags by this interface and discards tags from events.
|
||||
*/
|
||||
void
|
||||
gst_tag_setter_set_merge_mode (GstTagSetter *setter, GstTagMergeMode mode)
|
||||
{
|
||||
g_return_if_fail (GST_IS_TAG_SETTER (setter));
|
||||
g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
|
||||
|
||||
gst_tag_setter_get_data (setter)->mode = mode;
|
||||
}
|
||||
/**
|
||||
* gst_tag_setter_get_merge_mode:
|
||||
* @setter: a #GstTagSetter
|
||||
*
|
||||
* Queries the mode by which tags inside the setter are overwritten by tags
|
||||
* from events
|
||||
*
|
||||
* Returns: the merge mode used inside the element.
|
||||
*/
|
||||
GstTagMergeMode
|
||||
gst_tag_setter_get_merge_mode (GstTagSetter *setter)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_TAG_SETTER (setter), FALSE);
|
||||
|
||||
return gst_tag_setter_get_data (setter)->mode;
|
||||
}
|
70
gst/gsttagsetter.h
Normal file
70
gst/gsttagsetter.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||
*
|
||||
* gsttaginterface.h: Interfaces for tagging
|
||||
*
|
||||
* 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_TAG_INTERFACE_H__
|
||||
#define __GST_TAG_INTERFACE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_TAG_SETTER (gst_tag_setter_get_type ())
|
||||
#define GST_TAG_SETTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TAG_SETTER, GstTagSetter))
|
||||
#define GST_TAG_SETTER_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GST_TYPE_TAG_SETTER, GstTagSetter))
|
||||
#define GST_IS_TAG_SETTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TAG_SETTER))
|
||||
#define GST_TAG_SETTER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_TAG_SETTER, GstTagSetterIFace))
|
||||
|
||||
typedef struct _GstTagSetter GstTagSetter; /* Dummy typedef */
|
||||
typedef struct _GstTagSetterIFace GstTagSetterIFace;
|
||||
|
||||
/* use an empty interface here to allow detection of elements using user-set
|
||||
tags */
|
||||
struct _GstTagSetterIFace
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
|
||||
/* signals */
|
||||
|
||||
/* virtual table */
|
||||
};
|
||||
|
||||
GType gst_tag_setter_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void gst_tag_setter_merge (GstTagSetter * setter,
|
||||
const GstTagList * list,
|
||||
GstTagMergeMode mode);
|
||||
void gst_tag_setter_add (GstTagSetter * setter,
|
||||
GstTagMergeMode mode,
|
||||
const gchar * tag,
|
||||
...);
|
||||
void gst_tag_setter_add_valist (GstTagSetter * setter,
|
||||
GstTagMergeMode mode,
|
||||
const gchar * tag,
|
||||
va_list var_args);
|
||||
const GstTagList *gst_tag_setter_get_list (GstTagSetter * setter);
|
||||
|
||||
void gst_tag_setter_set_merge_mode (GstTagSetter * setter,
|
||||
GstTagMergeMode mode);
|
||||
GstTagMergeMode gst_tag_setter_get_merge_mode (GstTagSetter * setter);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_TAG_INTERFACE_H__ */
|
318
gst/gstvalue.c
318
gst/gstvalue.c
|
@ -48,11 +48,175 @@ struct _GstValueIntersectInfo {
|
|||
GType gst_type_fourcc;
|
||||
GType gst_type_int_range;
|
||||
GType gst_type_double_range;
|
||||
GType gst_value_type_list;
|
||||
|
||||
GArray *gst_value_compare_funcs;
|
||||
GArray *gst_value_union_funcs;
|
||||
GArray *gst_value_intersect_funcs;
|
||||
|
||||
/* list */
|
||||
|
||||
static void
|
||||
gst_value_init_list (GValue *value)
|
||||
{
|
||||
value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof(GValue));
|
||||
}
|
||||
|
||||
static GArray *
|
||||
gst_value_list_array_copy (const GArray *src)
|
||||
{
|
||||
GArray *dest;
|
||||
gint i;
|
||||
|
||||
dest = g_array_sized_new (FALSE, TRUE, sizeof(GValue), src->len);
|
||||
g_array_set_size (dest, src->len);
|
||||
for (i = 0; i < src->len; i++) {
|
||||
g_value_init (&g_array_index(dest, GValue, i), G_VALUE_TYPE (&g_array_index(src, GValue, i)));
|
||||
g_value_copy (&g_array_index(src, GValue, i), &g_array_index(dest, GValue, i));
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_value_copy_list (const GValue *src_value, GValue *dest_value)
|
||||
{
|
||||
dest_value->data[0].v_pointer = gst_value_list_array_copy ((GArray *) src_value->data[0].v_pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_value_free_list (GValue *value)
|
||||
{
|
||||
gint i;
|
||||
GArray *src = (GArray *) value->data[0].v_pointer;
|
||||
|
||||
if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
|
||||
for (i = 0; i < src->len; i++) {
|
||||
g_value_unset (&g_array_index(src, GValue, i));
|
||||
}
|
||||
g_array_free (src, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gst_value_list_peek_pointer (const GValue *value)
|
||||
{
|
||||
return value->data[0].v_pointer;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
gst_value_collect_list (GValue *value, guint n_collect_values,
|
||||
GTypeCValue *collect_values, guint collect_flags)
|
||||
{
|
||||
if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
|
||||
value->data[0].v_pointer = collect_values[0].v_pointer;
|
||||
value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
|
||||
} else {
|
||||
value->data[0].v_pointer = gst_value_list_array_copy ((GArray *) collect_values[0].v_pointer);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
gst_value_lcopy_list (const GValue *value, guint n_collect_values,
|
||||
GTypeCValue *collect_values, guint collect_flags)
|
||||
{
|
||||
GArray **dest = collect_values[0].v_pointer;
|
||||
if (!dest)
|
||||
return g_strdup_printf ("value location for `%s' passed as NULL",
|
||||
G_VALUE_TYPE_NAME (value));
|
||||
if (!value->data[0].v_pointer)
|
||||
return g_strdup_printf ("invalid value given for `%s'",
|
||||
G_VALUE_TYPE_NAME (value));
|
||||
if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
|
||||
*dest = (GArray *) value->data[0].v_pointer;
|
||||
} else {
|
||||
*dest = gst_value_list_array_copy ((GArray *) value->data[0].v_pointer);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gst_value_list_prepend_value (GValue *value, const GValue *prepend_value)
|
||||
{
|
||||
g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
|
||||
|
||||
g_array_prepend_vals ((GArray *) value->data[0].v_pointer, prepend_value, 1);
|
||||
}
|
||||
|
||||
void
|
||||
gst_value_list_append_value (GValue *value, const GValue *append_value)
|
||||
{
|
||||
g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
|
||||
|
||||
g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
|
||||
}
|
||||
|
||||
guint
|
||||
gst_value_list_get_size (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0);
|
||||
|
||||
return ((GArray *) value->data[0].v_pointer)->len;
|
||||
}
|
||||
|
||||
const GValue *
|
||||
gst_value_list_get_value (const GValue *value, guint index)
|
||||
{
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL);
|
||||
g_return_val_if_fail (index < gst_value_list_get_size (value), NULL);
|
||||
|
||||
return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer, GValue, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_value_list_concat:
|
||||
* @dest: an uninitialized #GValue to take the result
|
||||
* @value1: first value to put into the union
|
||||
* @value2: second value to put into the union
|
||||
*
|
||||
* Concatenates copies of value1 and value2 into a list. dest will be
|
||||
* initialized to the type GST_VALUE_TYPE_LIST.
|
||||
*/
|
||||
void
|
||||
gst_value_list_concat (GValue *dest, const GValue *value1, const GValue *value2)
|
||||
{
|
||||
guint i, value1_length, value2_length;
|
||||
GArray *array;
|
||||
|
||||
g_return_if_fail (dest != NULL);
|
||||
g_return_if_fail (G_VALUE_TYPE (dest) == 0);
|
||||
g_return_if_fail (G_IS_VALUE (value1));
|
||||
g_return_if_fail (G_IS_VALUE (value2));
|
||||
|
||||
value1_length = (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1);
|
||||
value2_length = (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1);
|
||||
g_value_init (dest, GST_VALUE_TYPE_LIST);
|
||||
array = (GArray *) dest->data[0].v_pointer;
|
||||
g_array_set_size (array, value1_length + value2_length);
|
||||
|
||||
if (GST_VALUE_HOLDS_LIST (value1)) {
|
||||
for (i = 0; i < value1_length; i++) {
|
||||
g_value_init (&g_array_index(array, GValue, i), G_VALUE_TYPE (gst_value_list_get_value (value1, i)));
|
||||
g_value_copy (gst_value_list_get_value (value1, i), &g_array_index(array, GValue, i));
|
||||
}
|
||||
} else {
|
||||
g_value_init (&g_array_index(array, GValue, 0), G_VALUE_TYPE (value1));
|
||||
g_value_copy (value1, &g_array_index(array, GValue, 0));
|
||||
}
|
||||
|
||||
if (GST_VALUE_HOLDS_LIST (value2)) {
|
||||
for (i = 0; i < value2_length; i++) {
|
||||
g_value_init (&g_array_index(array, GValue, i + value1_length), G_VALUE_TYPE (gst_value_list_get_value (value2, i)));
|
||||
g_value_copy (gst_value_list_get_value (value2, i), &g_array_index(array, GValue, i + value1_length));
|
||||
}
|
||||
} else {
|
||||
g_value_init (&g_array_index(array, GValue, value1_length), G_VALUE_TYPE (value2));
|
||||
g_value_copy (value2, &g_array_index(array, GValue, value1_length));
|
||||
}
|
||||
}
|
||||
|
||||
/* fourcc */
|
||||
|
||||
static void
|
||||
gst_value_init_fourcc (GValue *value)
|
||||
|
@ -147,7 +311,7 @@ gst_value_lcopy_int_range (const GValue *value, guint n_collect_values,
|
|||
void
|
||||
gst_value_set_int_range (GValue *value, int start, int end)
|
||||
{
|
||||
g_return_if_fail (GST_VALUE_HOLDS_FOURCC (value));
|
||||
g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
|
||||
|
||||
value->data[0].v_long = start;
|
||||
value->data[1].v_long = end;
|
||||
|
@ -156,7 +320,7 @@ gst_value_set_int_range (GValue *value, int start, int end)
|
|||
int
|
||||
gst_value_get_int_range_min (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0);
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
|
||||
|
||||
return value->data[0].v_long;
|
||||
}
|
||||
|
@ -164,11 +328,82 @@ gst_value_get_int_range_min (const GValue *value)
|
|||
int
|
||||
gst_value_get_int_range_max (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0);
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
|
||||
|
||||
return value->data[1].v_long;
|
||||
}
|
||||
|
||||
/* double range */
|
||||
|
||||
static void
|
||||
gst_value_init_double_range (GValue *value)
|
||||
{
|
||||
value->data[0].v_double = 0;
|
||||
value->data[1].v_double = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_value_copy_double_range (const GValue *src_value, GValue *dest_value)
|
||||
{
|
||||
dest_value->data[0].v_double = src_value->data[0].v_double;
|
||||
dest_value->data[1].v_double = src_value->data[1].v_double;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
gst_value_collect_double_range (GValue *value, guint n_collect_values,
|
||||
GTypeCValue *collect_values, guint collect_flags)
|
||||
{
|
||||
/* FIXME */
|
||||
value->data[0].v_double = collect_values[0].v_double;
|
||||
value->data[1].v_double = collect_values[1].v_double;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
gst_value_lcopy_double_range (const GValue *value, guint n_collect_values,
|
||||
GTypeCValue *collect_values, guint collect_flags)
|
||||
{
|
||||
guint32 *double_range_p = collect_values[0].v_pointer;
|
||||
|
||||
/* FIXME */
|
||||
|
||||
if (!double_range_p)
|
||||
return g_strdup_printf ("value location for `%s' passed as NULL",
|
||||
G_VALUE_TYPE_NAME (value));
|
||||
|
||||
*double_range_p = value->data[0].v_double;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gst_value_set_double_range (GValue *value, double start, double end)
|
||||
{
|
||||
g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
|
||||
|
||||
value->data[0].v_double = start;
|
||||
value->data[1].v_double = end;
|
||||
}
|
||||
|
||||
double
|
||||
gst_value_get_double_range_min (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
|
||||
|
||||
return value->data[0].v_double;
|
||||
}
|
||||
|
||||
double
|
||||
gst_value_get_double_range_max (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
|
||||
|
||||
return value->data[1].v_double;
|
||||
}
|
||||
|
||||
/* fourcc */
|
||||
|
||||
static void
|
||||
gst_value_transform_fourcc_string (const GValue *src_value,
|
||||
GValue *dest_value)
|
||||
|
@ -190,26 +425,39 @@ gst_value_transform_int_range_string (const GValue *src_value,
|
|||
static int
|
||||
gst_value_compare_int (const GValue *value1, const GValue *value2)
|
||||
{
|
||||
return value2->data[0].v_int - value1->data[0].v_int;
|
||||
if (value1->data[0].v_int > value2->data[0].v_int)
|
||||
return GST_VALUE_GREATER_THAN;
|
||||
if (value1->data[0].v_int < value2->data[0].v_int)
|
||||
return GST_VALUE_LESS_THAN;
|
||||
return GST_VALUE_EQUAL;
|
||||
}
|
||||
|
||||
static int
|
||||
gst_value_compare_double (const GValue *value1, const GValue *value2)
|
||||
{
|
||||
return (value2->data[0].v_double > value1->data[0].v_double) -
|
||||
(value2->data[0].v_double < value1->data[0].v_double);
|
||||
if (value1->data[0].v_double > value2->data[0].v_double)
|
||||
return GST_VALUE_GREATER_THAN;
|
||||
if (value1->data[0].v_double < value2->data[0].v_double)
|
||||
return GST_VALUE_LESS_THAN;
|
||||
if (value1->data[0].v_double == value2->data[0].v_double)
|
||||
return GST_VALUE_EQUAL;
|
||||
return GST_VALUE_UNORDERED;
|
||||
}
|
||||
|
||||
static int
|
||||
gst_value_compare_string (const GValue *value1, const GValue *value2)
|
||||
{
|
||||
return strcmp(value1->data[0].v_pointer, value2->data[0].v_pointer);
|
||||
int x = strcmp(value1->data[0].v_pointer, value2->data[0].v_pointer);
|
||||
if(x<0) return GST_VALUE_LESS_THAN;
|
||||
if(x>0) return GST_VALUE_GREATER_THAN;
|
||||
return GST_VALUE_EQUAL;
|
||||
}
|
||||
|
||||
static int
|
||||
gst_value_compare_fourcc (const GValue *value1, const GValue *value2)
|
||||
{
|
||||
return value2->data[0].v_int - value1->data[0].v_int;
|
||||
if (value2->data[0].v_int == value1->data[0].v_int) return GST_VALUE_EQUAL;
|
||||
return GST_VALUE_UNORDERED;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -243,8 +491,8 @@ gst_value_compare (const GValue *value1, const GValue *value2)
|
|||
return compare_info->func(value1, value2);
|
||||
}
|
||||
|
||||
g_return_val_if_fail(0 /* type not found */, 0);
|
||||
return 0;
|
||||
g_return_val_if_fail(0 /* type not found */, GST_VALUE_UNORDERED);
|
||||
return GST_VALUE_UNORDERED;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -275,7 +523,7 @@ gst_value_can_union (const GValue *value1, const GValue *value2)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gboolean
|
||||
gst_value_union (GValue *dest, const GValue *value1, const GValue *value2)
|
||||
{
|
||||
GstValueUnionInfo *union_info;
|
||||
|
@ -285,10 +533,11 @@ gst_value_union (GValue *dest, const GValue *value1, const GValue *value2)
|
|||
union_info = &g_array_index(gst_value_union_funcs, GstValueUnionInfo, i);
|
||||
if(union_info->type1 == G_VALUE_TYPE(value1) &&
|
||||
union_info->type2 == G_VALUE_TYPE(value2)) {
|
||||
union_info->func(dest, value1, value2);
|
||||
return;
|
||||
return union_info->func(dest, value1, value2);
|
||||
}
|
||||
}
|
||||
gst_value_list_concat (dest, value1, value2);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -364,7 +613,7 @@ gst_value_can_intersect (const GValue *value1, const GValue *value2)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gboolean
|
||||
gst_value_intersect (GValue *dest, const GValue *value1, const GValue *value2)
|
||||
{
|
||||
GstValueIntersectInfo *intersect_info;
|
||||
|
@ -375,10 +624,17 @@ gst_value_intersect (GValue *dest, const GValue *value1, const GValue *value2)
|
|||
GstValueIntersectInfo, i);
|
||||
if(intersect_info->type1 == G_VALUE_TYPE(value1) &&
|
||||
intersect_info->type2 == G_VALUE_TYPE(value2)) {
|
||||
intersect_info->func(dest, value1, value2);
|
||||
return;
|
||||
return intersect_info->func(dest, value1, value2);
|
||||
}
|
||||
}
|
||||
|
||||
if(gst_value_compare(value1, value2) == GST_VALUE_EQUAL){
|
||||
g_value_init(dest, G_VALUE_TYPE(value1));
|
||||
g_value_copy(value1, dest);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -441,6 +697,36 @@ _gst_value_initialize (void)
|
|||
gst_type_int_range = g_type_register_static (G_TYPE_BOXED, "GstIntRange", &info, 0);
|
||||
}
|
||||
|
||||
{
|
||||
static const GTypeValueTable value_table = {
|
||||
gst_value_init_double_range,
|
||||
NULL,
|
||||
gst_value_copy_double_range,
|
||||
NULL,
|
||||
"i",
|
||||
gst_value_collect_double_range,
|
||||
"p",
|
||||
gst_value_lcopy_double_range
|
||||
};
|
||||
info.value_table = &value_table;
|
||||
gst_type_double_range = g_type_register_static (G_TYPE_BOXED, "GstDoubleRange", &info, 0);
|
||||
}
|
||||
|
||||
{
|
||||
static const GTypeValueTable value_table = {
|
||||
gst_value_init_list,
|
||||
gst_value_free_list,
|
||||
gst_value_copy_list,
|
||||
gst_value_list_peek_pointer,
|
||||
"p",
|
||||
gst_value_collect_list,
|
||||
"p",
|
||||
gst_value_lcopy_list
|
||||
};
|
||||
info.value_table = &value_table;
|
||||
gst_value_type_list = g_type_register_static (G_TYPE_BOXED, "GstValueList", &info, 0);
|
||||
}
|
||||
|
||||
g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING,
|
||||
gst_value_transform_fourcc_string);
|
||||
g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
|
||||
|
|
|
@ -31,15 +31,36 @@ typedef int (* GstValueUnionFunc) (GValue *dest, const GValue *value1,
|
|||
typedef int (* GstValueIntersectFunc) (GValue *dest, const GValue *value1,
|
||||
const GValue *value2);
|
||||
|
||||
#define GST_VALUE_HOLDS_FOURCC(x) TRUE
|
||||
#define GST_MAKE_FOURCC(a,b,c,d) (guint32)((a)|(b)<<8|(c)<<16|(d)<<24)
|
||||
#define GST_STR_FOURCC(f) (guint32)(((f)[0])|((f)[1]<<8)|((f)[2]<<16)|((f)[3]<<24))
|
||||
|
||||
#define GST_FOURCC_FORMAT "%c%c%c%c"
|
||||
#define GST_FOURCC_ARGS(fourcc) \
|
||||
((gchar) ((fourcc) &0xff)), \
|
||||
((gchar) (((fourcc)>>8 )&0xff)), \
|
||||
((gchar) (((fourcc)>>16)&0xff)), \
|
||||
((gchar) (((fourcc)>>24)&0xff))
|
||||
|
||||
#define GST_TYPE_FOURCC gst_type_fourcc
|
||||
#define GST_TYPE_INT_RANGE gst_type_int_range
|
||||
#define GST_TYPE_DOUBLE_RANGE gst_type_double_range
|
||||
#define GST_VALUE_TYPE_LIST gst_value_type_list
|
||||
|
||||
#define GST_VALUE_HOLDS_FOURCC(x) (G_VALUE_TYPE(x) == gst_type_fourcc)
|
||||
#define GST_VALUE_HOLDS_INT_RANGE(x) (G_VALUE_TYPE(x) == gst_type_int_range)
|
||||
#define GST_VALUE_HOLDS_DOUBLE_RANGE(x) (G_VALUE_TYPE(x) == gst_type_double_range)
|
||||
#define GST_VALUE_HOLDS_LIST(x) (G_VALUE_TYPE(x) == GST_VALUE_TYPE_LIST)
|
||||
#define GST_VALUE_HOLDS_CAPS(x) TRUE /* FIXME */
|
||||
|
||||
#define GST_VALUE_LESS_THAN (-1)
|
||||
#define GST_VALUE_EQUAL 0
|
||||
#define GST_VALUE_GREATER_THAN 1
|
||||
#define GST_VALUE_UNORDERED 2
|
||||
|
||||
extern GType gst_type_fourcc;
|
||||
extern GType gst_type_int_range;
|
||||
extern GType gst_type_double_range;
|
||||
extern GType gst_value_type_list;
|
||||
|
||||
void gst_value_set_fourcc (GValue *value, guint32 fourcc);
|
||||
guint32 gst_value_get_fourcc (const GValue *value);
|
||||
|
@ -49,11 +70,21 @@ int gst_value_get_int_range_min (const GValue *value);
|
|||
int gst_value_get_int_range_max (const GValue *value);
|
||||
|
||||
void gst_value_set_double_range (GValue *value, double start, double end);
|
||||
double gst_value_get_double_range_start (const GValue *value);
|
||||
double gst_value_get_double_range_end (const GValue *value);
|
||||
double gst_value_get_double_range_min (const GValue *value);
|
||||
double gst_value_get_double_range_max (const GValue *value);
|
||||
|
||||
void gst_value_list_prepend_value (GValue *value, const GValue *prepend_value);
|
||||
void gst_value_list_append_value (GValue *value, const GValue *prepend_value);
|
||||
guint gst_value_list_get_size (const GValue *value);
|
||||
const GValue *gst_value_list_get_value (const GValue *value, guint index);
|
||||
void gst_value_list_concat (GValue *dest, const GValue *value1, const GValue *value2);
|
||||
|
||||
void _gst_value_initialize (void);
|
||||
|
||||
int gst_value_compare (const GValue *src1, const GValue *src2);
|
||||
gboolean gst_value_intersect (GValue *dest, const GValue *src1, const GValue *src2);
|
||||
gboolean gst_value_union (GValue *dest, const GValue *src1, const GValue *src2);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
|
@ -687,8 +687,9 @@ gst_xml_registry_parse_element_factory (GMarkupParseContext *context, const gcha
|
|||
GstElementFactory *factory = GST_ELEMENT_FACTORY (registry->current_feature);
|
||||
|
||||
if (!strcmp (tag, "name")) {
|
||||
g_free (registry->current_feature->name);
|
||||
registry->current_feature->name = g_strndup (text, text_len);
|
||||
gchar *name = g_strndup (text, text_len);
|
||||
gst_plugin_feature_set_name (registry->current_feature, name);
|
||||
g_free (name);
|
||||
}
|
||||
else if (!strcmp (tag, "longname")) {
|
||||
g_free (factory->details.longname);
|
||||
|
@ -709,12 +710,18 @@ gst_xml_registry_parse_element_factory (GMarkupParseContext *context, const gcha
|
|||
else if (!strcmp(tag, "rank")) {
|
||||
gint rank;
|
||||
gchar *ret;
|
||||
rank = strtol (text, &ret, 0);
|
||||
|
||||
rank = strtol (text, &ret, 0);
|
||||
if (ret == text + text_len) {
|
||||
gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strcmp(tag, "interface")) {
|
||||
gchar *tmp = g_strndup (text, text_len);
|
||||
__gst_element_factory_add_interface (factory, tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1464,23 +1471,29 @@ gst_xml_registry_save_feature (GstXMLRegistry *xmlregistry, GstPluginFeature *fe
|
|||
|
||||
if (GST_IS_ELEMENT_FACTORY (feature)) {
|
||||
GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
|
||||
GList *templates;
|
||||
GList *walk;
|
||||
|
||||
PUT_ESCAPED ("longname", factory->details.longname);
|
||||
PUT_ESCAPED ("class", factory->details.klass);
|
||||
PUT_ESCAPED ("description", factory->details.description);
|
||||
PUT_ESCAPED ("author", factory->details.author);
|
||||
|
||||
templates = factory->padtemplates;
|
||||
walk = factory->padtemplates;
|
||||
|
||||
while (templates) {
|
||||
GstPadTemplate *template = GST_PAD_TEMPLATE (templates->data);
|
||||
while (walk) {
|
||||
GstPadTemplate *template = GST_PAD_TEMPLATE (walk->data);
|
||||
|
||||
CLASS (xmlregistry)->save_func (xmlregistry, "<padtemplate>\n");
|
||||
gst_xml_registry_save_pad_template (xmlregistry, template);
|
||||
CLASS (xmlregistry)->save_func (xmlregistry, "</padtemplate>\n");
|
||||
|
||||
templates = g_list_next (templates);
|
||||
walk = g_list_next (walk);
|
||||
}
|
||||
|
||||
walk = factory->interfaces;
|
||||
while (walk) {
|
||||
PUT_ESCAPED ("interface", (gchar *) walk->data);
|
||||
walk = g_list_next (walk);
|
||||
}
|
||||
}
|
||||
else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
SUBDIRS = control getbits bytestream
|
||||
SUBDIRS = bytestream control getbits
|
||||
|
||||
DIST_SUBDIRS = control getbits bytestream
|
||||
DIST_SUBDIRS = bytestream control getbits
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
### all of the standard pc files we need to generate
|
||||
pcfiles = \
|
||||
gstreamer-@GST_MAJORMINOR@.pc \
|
||||
pcfiles = \
|
||||
gstreamer-@GST_MAJORMINOR@.pc \
|
||||
gstreamer-control-@GST_MAJORMINOR@.pc
|
||||
|
||||
pcfiles_uninstalled = \
|
||||
gstreamer-@GST_MAJORMINOR@-uninstalled.pc \
|
||||
pcfiles_uninstalled = \
|
||||
gstreamer-@GST_MAJORMINOR@-uninstalled.pc \
|
||||
gstreamer-control-@GST_MAJORMINOR@-uninstalled.pc
|
||||
|
||||
all-local: $(pcfiles) $(pcfiles_uninstalled)
|
||||
|
@ -18,10 +18,10 @@ $(pcfiles_uninstalled): %-@GST_MAJORMINOR@-uninstalled.pc: %-uninstalled.pc
|
|||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = $(pcfiles)
|
||||
|
||||
EXTRA_DIST = \
|
||||
gstreamer.pc.in \
|
||||
gstreamer-uninstalled.pc.in \
|
||||
gstreamer-control.pc.in \
|
||||
EXTRA_DIST = \
|
||||
gstreamer.pc.in \
|
||||
gstreamer-uninstalled.pc.in \
|
||||
gstreamer-control.pc.in \
|
||||
gstreamer-control-uninstalled.pc.in
|
||||
|
||||
CLEANFILES = $(pcfiles) $(pcfiles_uninstalled)
|
||||
|
|
6
po/.gitignore
vendored
Normal file
6
po/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
*.gmo
|
||||
remove-potcdate.sed
|
||||
stamp-po
|
||||
POTFILES
|
||||
cat-id-tbl.c
|
||||
gstreamer-0.7.pot
|
|
@ -10,13 +10,39 @@ else
|
|||
GST_AUTOPLUG_DIRS = autoplug helloworld2
|
||||
endif
|
||||
|
||||
SUBDIRS = $(GST_AUTOPLUG_DIRS) $(GST_LOADSAVE_DIRS) \
|
||||
helloworld \
|
||||
queue queue2 queue3 queue4 \
|
||||
launch thread plugins mixer cutter pingpong manual
|
||||
SUBDIRS = \
|
||||
helloworld \
|
||||
queue \
|
||||
queue2 \
|
||||
queue3 \
|
||||
queue4 \
|
||||
launch \
|
||||
thread \
|
||||
plugins \
|
||||
mixer \
|
||||
cutter \
|
||||
pingpong \
|
||||
manual \
|
||||
retag \
|
||||
$(GST_LOADSAVE_DIRS) \
|
||||
$(GST_AUTOPLUG_DIRS)
|
||||
|
||||
DIST_SUBDIRS = autoplug \
|
||||
helloworld helloworld2 \
|
||||
queue queue2 queue3 queue4 \
|
||||
launch thread xml plugins typefind mixer cutter pingpong manual
|
||||
|
||||
DIST_SUBDIRS = autoplug \
|
||||
helloworld \
|
||||
helloworld2 \
|
||||
queue \
|
||||
queue2 \
|
||||
queue3 \
|
||||
queue4 \
|
||||
launch \
|
||||
thread \
|
||||
plugins \
|
||||
mixer \
|
||||
cutter \
|
||||
pingpong \
|
||||
manual \
|
||||
xml \
|
||||
typefind \
|
||||
retag
|
||||
|
||||
|
|
2
tests/old/examples/retag/.gitignore
vendored
Normal file
2
tests/old/examples/retag/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
retag
|
||||
transcode
|
7
tests/old/examples/retag/Makefile.am
Normal file
7
tests/old/examples/retag/Makefile.am
Normal file
|
@ -0,0 +1,7 @@
|
|||
noinst_PROGRAMS = retag transcode
|
||||
|
||||
retag_LDADD = $(GST_LIBS)
|
||||
retag_CFLAGS = $(GST_CFLAGS)
|
||||
|
||||
transcode_LDADD = $(GST_LIBS)
|
||||
transcode_CFLAGS = $(GST_CFLAGS)
|
103
tests/old/examples/retag/retag.c
Normal file
103
tests/old/examples/retag/retag.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* This example shows how to use interfaces and the tag subsystem.
|
||||
* It takes an mp3 file as input, and makes an ogg file out of it. While doing
|
||||
* this, it parses the filename and sets artist and title in the ogg file.
|
||||
* It assumes the filename to be "<artist> - <title>.mp3"
|
||||
*
|
||||
* Run the program as "retag <mp3 file>"
|
||||
*
|
||||
* To run this program, you need to have the gst-plugins package (specifically
|
||||
* the vorbis and mad plugins) installed.
|
||||
*/
|
||||
|
||||
/* main header */
|
||||
#include <gst/gst.h>
|
||||
/* and a header we need for the string manipulation */
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *bin, *filesrc, *tag_changer, *filesink;
|
||||
gchar *artist, *title, *ext, *filename;
|
||||
|
||||
/* check that the argument is there */
|
||||
if (argc != 2) {
|
||||
g_print ("usage: %s <mp3 file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* initialize GStreamer */
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
/* parse the mp3 name */
|
||||
artist = strrchr (argv[1], '/');
|
||||
if (artist == NULL)
|
||||
artist = argv[1];
|
||||
artist = g_strdup (artist);
|
||||
ext = strrchr (artist, '.');
|
||||
if (ext) *ext = '\0';
|
||||
title = strstr (artist, " - ");
|
||||
if (title == NULL) {
|
||||
g_print ("The format of the mp3 file is invalid.\n");
|
||||
return 1;
|
||||
}
|
||||
*title = '\0';
|
||||
title += 3;
|
||||
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_pipeline_new ("pipeline");
|
||||
g_assert (bin);
|
||||
|
||||
/* create a file reader */
|
||||
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
||||
g_assert (filesrc);
|
||||
|
||||
/* now it's time to get the tag_changer */
|
||||
tag_changer = gst_element_factory_make ("id3tag", "tag_changer");
|
||||
if (!tag_changer) {
|
||||
g_print ("could not find plugin \"mad\"");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* and a file writer */
|
||||
filesink = gst_element_factory_make ("filesink", "filesink");
|
||||
g_assert (filesink);
|
||||
|
||||
/* set the filenames */
|
||||
filename = g_strdup_printf ("%s.temp", argv[1]); /* easy solution */
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
g_object_set (G_OBJECT (filesink), "location", filename, NULL);
|
||||
|
||||
/* make sure the tag setter uses our stuff
|
||||
(though that should already be default) */
|
||||
gst_tag_setter_set_merge_mode (GST_TAG_SETTER (tag_changer), GST_TAG_MERGE_KEEP);
|
||||
/* set the tagging information */
|
||||
gst_tag_setter_add (GST_TAG_SETTER (tag_changer), GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_ARTIST, artist,
|
||||
GST_TAG_TITLE, title,
|
||||
NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add_many (GST_BIN (bin), filesrc, tag_changer, filesink, NULL);
|
||||
|
||||
/* link the elements */
|
||||
gst_element_link_many (filesrc, tag_changer, filesink, NULL);
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state (bin, GST_STATE_PLAYING);
|
||||
|
||||
while (gst_bin_iterate (GST_BIN (bin)));
|
||||
|
||||
/* stop the bin */
|
||||
gst_element_set_state (bin, GST_STATE_NULL);
|
||||
|
||||
/* rename the file to the correct name and remove the old one */
|
||||
remove (argv[1]);
|
||||
rename (filename, argv[1]);
|
||||
g_free (filename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
106
tests/old/examples/retag/transcode.c
Normal file
106
tests/old/examples/retag/transcode.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* This example shows how to use interfaces and the tag subsystem.
|
||||
* It takes an mp3 file as input, and makes an ogg file out of it. While doing
|
||||
* this, it parses the filename and sets artist and title in the ogg file.
|
||||
* It assumes the filename to be "<artist> - <title>.mp3"
|
||||
*
|
||||
* Run the program as "retag <mp3 file>"
|
||||
*
|
||||
* To run this program, you need to have the gst-plugins package (specifically
|
||||
* the vorbis and mad plugins) installed.
|
||||
*/
|
||||
|
||||
/* main header */
|
||||
#include <gst/gst.h>
|
||||
/* and a header we need for the string manipulation */
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *bin, *filesrc, *decoder, *encoder, *filesink;
|
||||
gchar *artist, *title, *ext, *filename;
|
||||
|
||||
/* initialize GStreamer */
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
/* check that the argument is there */
|
||||
if (argc != 2) {
|
||||
g_print ("usage: %s <mp3 file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* parse the mp3 name */
|
||||
artist = strrchr (argv[1], '/');
|
||||
if (artist == NULL)
|
||||
artist = argv[1];
|
||||
artist = g_strdup (artist);
|
||||
ext = strrchr (artist, '.');
|
||||
if (ext) *ext = '\0';
|
||||
title = strstr (artist, " - ");
|
||||
if (title == NULL) {
|
||||
g_print ("The format of the mp3 file is invalid.\n");
|
||||
return 1;
|
||||
}
|
||||
*title = '\0';
|
||||
title += 3;
|
||||
|
||||
|
||||
/* create a new bin to hold the elements */
|
||||
bin = gst_pipeline_new ("pipeline");
|
||||
g_assert (bin);
|
||||
|
||||
/* create a file reader */
|
||||
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
||||
g_assert (filesrc);
|
||||
|
||||
/* now it's time to get the decoder */
|
||||
decoder = gst_element_factory_make ("mad", "decode");
|
||||
if (!decoder) {
|
||||
g_print ("could not find plugin \"mad\"");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create the encoder */
|
||||
encoder = gst_element_factory_make ("vorbisenc", "encoder");
|
||||
if (!encoder) {
|
||||
g_print ("cound not find plugin \"vorbisenc\"");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* and a file writer */
|
||||
filesink = gst_element_factory_make ("filesink", "filesink");
|
||||
g_assert (filesink);
|
||||
|
||||
/* set the filenames */
|
||||
filename = g_strdup_printf ("%s.ogg", argv[1]); /* easy solution */
|
||||
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
||||
g_object_set (G_OBJECT (filesink), "location", filename, NULL);
|
||||
g_free (filename);
|
||||
|
||||
/* make sure the tag setter uses our stuff
|
||||
(though that should already be default) */
|
||||
gst_tag_setter_set_merge_mode (GST_TAG_SETTER (encoder), GST_TAG_MERGE_KEEP);
|
||||
/* set the tagging information */
|
||||
gst_tag_setter_add (GST_TAG_SETTER (encoder), GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_ARTIST, artist,
|
||||
GST_TAG_TITLE, title,
|
||||
NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add_many (GST_BIN (bin), filesrc, decoder, encoder, filesink, NULL);
|
||||
|
||||
/* link the elements */
|
||||
gst_element_link_many (filesrc, decoder, encoder, filesink, NULL);
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state (bin, GST_STATE_PLAYING);
|
||||
|
||||
while (gst_bin_iterate (GST_BIN (bin)));
|
||||
|
||||
/* stop the bin */
|
||||
gst_element_set_state (bin, GST_STATE_NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -14,11 +14,11 @@ GST_DEBUG_DIRS = debug
|
|||
endif
|
||||
|
||||
SUBDIRS = bytestream cleanup dynparams \
|
||||
caps plugin elements clock refcounting threads \
|
||||
caps plugin elements clock refcounting tags threads \
|
||||
indexers debug $(GST_PARSE_DIRS) $(GST_DEBUG_DIRS)
|
||||
|
||||
DIST_SUBDIRS = bytestream caps cleanup clock dynparams elements indexers \
|
||||
plugin refcounting threads parse debug
|
||||
plugin refcounting tags threads parse debug
|
||||
|
||||
tests_pass = test_gst_init
|
||||
tests_fail =
|
||||
|
|
|
@ -76,7 +76,7 @@ main (gint argc, gchar *argv[])
|
|||
gst_element_set_state (thread, GST_STATE_PLAYING);
|
||||
g_print ("SLEEPING 1 sec\n");
|
||||
sleep (1);
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
gst_bin_sync_children_state (GST_BIN (pipeline));
|
||||
g_print ("SLEEPING 2 sec\n");
|
||||
sleep (2);
|
||||
|
||||
|
|
|
@ -14,11 +14,11 @@ GST_DEBUG_DIRS = debug
|
|||
endif
|
||||
|
||||
SUBDIRS = bytestream cleanup dynparams \
|
||||
caps plugin elements clock refcounting threads \
|
||||
caps plugin elements clock refcounting tags threads \
|
||||
indexers debug $(GST_PARSE_DIRS) $(GST_DEBUG_DIRS)
|
||||
|
||||
DIST_SUBDIRS = bytestream caps cleanup clock dynparams elements indexers \
|
||||
plugin refcounting threads parse debug
|
||||
plugin refcounting tags threads parse debug
|
||||
|
||||
tests_pass = test_gst_init
|
||||
tests_fail =
|
||||
|
|
|
@ -76,7 +76,7 @@ main (gint argc, gchar *argv[])
|
|||
gst_element_set_state (thread, GST_STATE_PLAYING);
|
||||
g_print ("SLEEPING 1 sec\n");
|
||||
sleep (1);
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
gst_bin_sync_children_state (GST_BIN (pipeline));
|
||||
g_print ("SLEEPING 2 sec\n");
|
||||
sleep (2);
|
||||
|
||||
|
|
|
@ -221,6 +221,34 @@ fault_setup (void)
|
|||
sigaction (SIGQUIT, &action, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
print_tag (const GstTagList *list, const gchar *tag, gpointer unused)
|
||||
{
|
||||
gint i, count;
|
||||
|
||||
count = gst_tag_list_get_tag_size (list, tag);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
||||
gchar *str = g_strdup_value_contents (
|
||||
gst_tag_list_get_value_index (list, tag, i));
|
||||
|
||||
if (i == 0) {
|
||||
g_print ("%15s: %s\n", gst_tag_get_nick (tag), str);
|
||||
} else {
|
||||
g_print (" : %s\n", str);
|
||||
}
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
}
|
||||
static void
|
||||
found_tag (GObject *pipeline, GstElement *source, GstTagList *tags)
|
||||
{
|
||||
g_print ("FOUND TAG : element \"%s\"\n", GST_STR_NULL (GST_ELEMENT_NAME (source)));
|
||||
gst_tag_list_foreach (tags, print_tag, NULL);
|
||||
}
|
||||
|
||||
/* we only use sighandler here because the registers are not important */
|
||||
static void
|
||||
sigint_handler_sighandler (int signum)
|
||||
|
@ -286,11 +314,14 @@ main(int argc, char *argv[])
|
|||
gint i, j;
|
||||
/* options */
|
||||
gboolean verbose = FALSE;
|
||||
gboolean tags = FALSE;
|
||||
gboolean no_fault = FALSE;
|
||||
gboolean trace = FALSE;
|
||||
gchar *savefile = NULL;
|
||||
gchar *exclude_args = NULL;
|
||||
struct poptOption options[] = {
|
||||
{"tags", 't', POPT_ARG_NONE|POPT_ARGFLAG_STRIP, &tags, 0,
|
||||
"output tags (also known as metadata)", NULL},
|
||||
{"verbose", 'v', POPT_ARG_NONE|POPT_ARGFLAG_STRIP, &verbose, 0,
|
||||
"output status information and property notifications", NULL},
|
||||
{"exclude", 'X', POPT_ARG_STRING|POPT_ARGFLAG_STRIP, &exclude_args, 0,
|
||||
|
@ -301,7 +332,7 @@ main(int argc, char *argv[])
|
|||
#endif
|
||||
{"no-fault", 'f', POPT_ARG_NONE|POPT_ARGFLAG_STRIP, &no_fault, 0,
|
||||
"Do not install a fault handler", NULL},
|
||||
{"trace", 't', POPT_ARG_NONE|POPT_ARGFLAG_STRIP, &trace, 0,
|
||||
{"trace", 'T', POPT_ARG_NONE|POPT_ARGFLAG_STRIP, &trace, 0,
|
||||
"print alloc trace if enabled at compile time", NULL},
|
||||
{"iterations",'i',POPT_ARG_INT|POPT_ARGFLAG_STRIP, &max_iterations, 0,
|
||||
"number of times to iterate pipeline", NULL},
|
||||
|
@ -382,6 +413,9 @@ main(int argc, char *argv[])
|
|||
gchar **exclude_list = exclude_args ? g_strsplit (exclude_args, ",", 0) : NULL;
|
||||
g_signal_connect (pipeline, "deep_notify", G_CALLBACK (gst_element_default_deep_notify), exclude_list);
|
||||
}
|
||||
if (tags) {
|
||||
g_signal_connect (pipeline, "found-tag", G_CALLBACK (found_tag), NULL);
|
||||
}
|
||||
g_signal_connect (pipeline, "error", G_CALLBACK (gst_element_default_error), NULL);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
|
|
Loading…
Reference in a new issue