diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2014-06-22 17:16:06 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2014-06-22 17:16:06 +0200 |
commit | 5254e8378f4c28705a571d7bfbbad5fbd1adb3d3 (patch) | |
tree | 3f6cac985731dee5f68347ea99ad30ed19462168 /gst | |
parent | 1adbba7bfff7853fca8b02aec57dbe1850d4a55c (diff) |
Imported Upstream version 1.3.3
Diffstat (limited to 'gst')
117 files changed, 6349 insertions, 1974 deletions
diff --git a/gst/Makefile.am b/gst/Makefile.am index b6cf720..86d226e 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -71,12 +71,16 @@ libgstreamer_@GST_API_VERSION@_la_SOURCES = \ gstcontrolsource.c \ gstdatetime.c \ gstdebugutils.c \ + gstdevice.c \ + gstdevicemonitor.c \ + gstdevicemonitorfactory.c \ gstelement.c \ gstelementfactory.c \ gsterror.c \ gstevent.c \ gstformat.c \ gstghostpad.c \ + gstglobaldevicemonitor.c \ gstinfo.c \ gstiterator.c \ gstatomicqueue.c \ @@ -172,11 +176,15 @@ gst_headers = \ gstdebugutils.h \ gstelement.h \ gstelementmetadata.h \ + gstdevice.h \ + gstdevicemonitor.h \ + gstdevicemonitorfactory.h \ gstelementfactory.h \ gsterror.h \ gstevent.h \ gstformat.h \ gstghostpad.h \ + gstglobaldevicemonitor.h \ gstinfo.h \ gstiterator.h \ gstatomicqueue.h \ @@ -274,6 +282,7 @@ BUILT_GIRSOURCES = Gst-@GST_API_VERSION@.gir gir_headers=$(patsubst %,$(srcdir)/%, $(libgstreamer_@GST_API_VERSION@include_HEADERS)) gir_headers+=$(patsubst %,$(builddir)/%, $(built_header_make)) +gir_headers+=$(patsubst %,$(builddir)/%, gstversion.h) gir_sources=$(patsubst %,$(srcdir)/%, $(libgstreamer_@GST_API_VERSION@_la_SOURCES)) gir_sources+=$(patsubst %,$(builddir)/%, $(built_source_make)) @@ -290,7 +299,7 @@ Gst-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstreamer-@GST_API_VERSIO --include=GLib-2.0 \ --include=GObject-2.0 \ --include=GModule-2.0 \ - --libtool="$(top_builddir)/libtool" \ + --libtool="${LIBTOOL}" \ --pkg glib-2.0 \ --pkg gobject-2.0 \ --pkg gmodule-no-export-2.0 \ diff --git a/gst/Makefile.in b/gst/Makefile.in index a074240..eb59429 100644 --- a/gst/Makefile.in +++ b/gst/Makefile.in @@ -94,7 +94,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ $(top_srcdir)/common/m4/as-compiler-flag.m4 \ $(top_srcdir)/common/m4/as-docbook.m4 \ $(top_srcdir)/common/m4/as-libtool.m4 \ - $(top_srcdir)/common/m4/as-scrub-include.m4 \ $(top_srcdir)/common/m4/as-version.m4 \ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ $(top_srcdir)/common/m4/gst-arch.m4 \ @@ -175,17 +174,19 @@ am__libgstreamer_@GST_API_VERSION@_la_SOURCES_DIST = gst.c gstobject.c \ gstallocator.c gstbin.c gstbuffer.c gstbufferlist.c \ gstbufferpool.c gstbus.c gstcaps.c gstcapsfeatures.c \ gstchildproxy.c gstclock.c gstcontext.c gstcontrolbinding.c \ - gstcontrolsource.c gstdatetime.c gstdebugutils.c gstelement.c \ + gstcontrolsource.c gstdatetime.c gstdebugutils.c gstdevice.c \ + gstdevicemonitor.c gstdevicemonitorfactory.c gstelement.c \ gstelementfactory.c gsterror.c gstevent.c gstformat.c \ - gstghostpad.c gstinfo.c gstiterator.c gstatomicqueue.c \ - gstmessage.c gstmeta.c gstmemory.c gstminiobject.c gstpad.c \ - gstpadtemplate.c gstparamspecs.c gstpipeline.c gstplugin.c \ - gstpluginfeature.c gstpluginloader.c gstpoll.c gstpreset.c \ - gstquark.c gstquery.c gstregistry.c gstregistrychunks.c \ - gstsample.c gstsegment.c gststructure.c gstsystemclock.c \ - gsttaglist.c gsttagsetter.c gsttask.c gsttaskpool.c gsttoc.c \ - gsttocsetter.c gsttrace.c gsttypefind.c gsttypefindfactory.c \ - gsturi.c gstutils.c gstvalue.c gstparse.c gstregistrybinary.c + gstghostpad.c gstglobaldevicemonitor.c gstinfo.c gstiterator.c \ + gstatomicqueue.c gstmessage.c gstmeta.c gstmemory.c \ + gstminiobject.c gstpad.c gstpadtemplate.c gstparamspecs.c \ + gstpipeline.c gstplugin.c gstpluginfeature.c gstpluginloader.c \ + gstpoll.c gstpreset.c gstquark.c gstquery.c gstregistry.c \ + gstregistrychunks.c gstsample.c gstsegment.c gststructure.c \ + gstsystemclock.c gsttaglist.c gsttagsetter.c gsttask.c \ + gsttaskpool.c gsttoc.c gsttocsetter.c gsttrace.c gsttypefind.c \ + gsttypefindfactory.c gsturi.c gstutils.c gstvalue.c gstparse.c \ + gstregistrybinary.c @GST_DISABLE_TRACE_FALSE@am__objects_1 = libgstreamer_@GST_API_VERSION@_la-gsttrace.lo @GST_DISABLE_REGISTRY_FALSE@am__objects_2 = libgstreamer_@GST_API_VERSION@_la-gstregistrybinary.lo am_libgstreamer_@GST_API_VERSION@_la_OBJECTS = \ @@ -206,12 +207,16 @@ am_libgstreamer_@GST_API_VERSION@_la_OBJECTS = \ libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.lo \ libgstreamer_@GST_API_VERSION@_la-gstdatetime.lo \ libgstreamer_@GST_API_VERSION@_la-gstdebugutils.lo \ + libgstreamer_@GST_API_VERSION@_la-gstdevice.lo \ + libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo \ + libgstreamer_@GST_API_VERSION@_la-gstdevicemonitorfactory.lo \ libgstreamer_@GST_API_VERSION@_la-gstelement.lo \ libgstreamer_@GST_API_VERSION@_la-gstelementfactory.lo \ libgstreamer_@GST_API_VERSION@_la-gsterror.lo \ libgstreamer_@GST_API_VERSION@_la-gstevent.lo \ libgstreamer_@GST_API_VERSION@_la-gstformat.lo \ libgstreamer_@GST_API_VERSION@_la-gstghostpad.lo \ + libgstreamer_@GST_API_VERSION@_la-gstglobaldevicemonitor.lo \ libgstreamer_@GST_API_VERSION@_la-gstinfo.lo \ libgstreamer_@GST_API_VERSION@_la-gstiterator.lo \ libgstreamer_@GST_API_VERSION@_la-gstatomicqueue.lo \ @@ -695,12 +700,16 @@ libgstreamer_@GST_API_VERSION@_la_SOURCES = \ gstcontrolsource.c \ gstdatetime.c \ gstdebugutils.c \ + gstdevice.c \ + gstdevicemonitor.c \ + gstdevicemonitorfactory.c \ gstelement.c \ gstelementfactory.c \ gsterror.c \ gstevent.c \ gstformat.c \ gstghostpad.c \ + gstglobaldevicemonitor.c \ gstinfo.c \ gstiterator.c \ gstatomicqueue.c \ @@ -798,11 +807,15 @@ gst_headers = \ gstdebugutils.h \ gstelement.h \ gstelementmetadata.h \ + gstdevice.h \ + gstdevicemonitor.h \ + gstdevicemonitorfactory.h \ gstelementfactory.h \ gsterror.h \ gstevent.h \ gstformat.h \ gstghostpad.h \ + gstglobaldevicemonitor.h \ gstinfo.h \ gstiterator.h \ gstatomicqueue.h \ @@ -859,7 +872,8 @@ noinst_HEADERS = \ @HAVE_INTROSPECTION_TRUE@gir_headers = $(patsubst %,$(srcdir)/%, \ @HAVE_INTROSPECTION_TRUE@ $(libgstreamer_@GST_API_VERSION@include_HEADERS)) \ @HAVE_INTROSPECTION_TRUE@ $(patsubst %,$(builddir)/%, \ -@HAVE_INTROSPECTION_TRUE@ $(built_header_make)) +@HAVE_INTROSPECTION_TRUE@ $(built_header_make)) $(patsubst \ +@HAVE_INTROSPECTION_TRUE@ %,$(builddir)/%, gstversion.h) @HAVE_INTROSPECTION_TRUE@gir_sources = $(patsubst %,$(srcdir)/%, \ @HAVE_INTROSPECTION_TRUE@ $(libgstreamer_@GST_API_VERSION@_la_SOURCES)) \ @HAVE_INTROSPECTION_TRUE@ $(patsubst %,$(builddir)/%, \ @@ -972,6 +986,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstcontrolsource.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdatetime.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdebugutils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevice.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitorfactory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelement.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelementfactory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstenumtypes.Plo@am__quote@ @@ -979,6 +996,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstevent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstformat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstghostpad.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstglobaldevicemonitor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstiterator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstmemory.Plo@am__quote@ @@ -1161,6 +1179,27 @@ libgstreamer_@GST_API_VERSION@_la-gstdebugutils.lo: gstdebugutils.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdebugutils.lo `test -f 'gstdebugutils.c' || echo '$(srcdir)/'`gstdebugutils.c +libgstreamer_@GST_API_VERSION@_la-gstdevice.lo: gstdevice.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstdevice.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevice.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstdevice.lo `test -f 'gstdevice.c' || echo '$(srcdir)/'`gstdevice.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevice.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevice.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdevice.c' object='libgstreamer_@GST_API_VERSION@_la-gstdevice.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdevice.lo `test -f 'gstdevice.c' || echo '$(srcdir)/'`gstdevice.c + +libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo: gstdevicemonitor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo `test -f 'gstdevicemonitor.c' || echo '$(srcdir)/'`gstdevicemonitor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdevicemonitor.c' object='libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdevicemonitor.lo `test -f 'gstdevicemonitor.c' || echo '$(srcdir)/'`gstdevicemonitor.c + +libgstreamer_@GST_API_VERSION@_la-gstdevicemonitorfactory.lo: gstdevicemonitorfactory.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstdevicemonitorfactory.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitorfactory.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstdevicemonitorfactory.lo `test -f 'gstdevicemonitorfactory.c' || echo '$(srcdir)/'`gstdevicemonitorfactory.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitorfactory.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstdevicemonitorfactory.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstdevicemonitorfactory.c' object='libgstreamer_@GST_API_VERSION@_la-gstdevicemonitorfactory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstdevicemonitorfactory.lo `test -f 'gstdevicemonitorfactory.c' || echo '$(srcdir)/'`gstdevicemonitorfactory.c + libgstreamer_@GST_API_VERSION@_la-gstelement.lo: gstelement.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstelement.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelement.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstelement.lo `test -f 'gstelement.c' || echo '$(srcdir)/'`gstelement.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelement.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstelement.Plo @@ -1203,6 +1242,13 @@ libgstreamer_@GST_API_VERSION@_la-gstghostpad.lo: gstghostpad.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstghostpad.lo `test -f 'gstghostpad.c' || echo '$(srcdir)/'`gstghostpad.c +libgstreamer_@GST_API_VERSION@_la-gstglobaldevicemonitor.lo: gstglobaldevicemonitor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstglobaldevicemonitor.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstglobaldevicemonitor.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstglobaldevicemonitor.lo `test -f 'gstglobaldevicemonitor.c' || echo '$(srcdir)/'`gstglobaldevicemonitor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstglobaldevicemonitor.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstglobaldevicemonitor.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstglobaldevicemonitor.c' object='libgstreamer_@GST_API_VERSION@_la-gstglobaldevicemonitor.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstreamer_@GST_API_VERSION@_la-gstglobaldevicemonitor.lo `test -f 'gstglobaldevicemonitor.c' || echo '$(srcdir)/'`gstglobaldevicemonitor.c + libgstreamer_@GST_API_VERSION@_la-gstinfo.lo: gstinfo.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstreamer_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstreamer_@GST_API_VERSION@_la-gstinfo.lo -MD -MP -MF $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstinfo.Tpo -c -o libgstreamer_@GST_API_VERSION@_la-gstinfo.lo `test -f 'gstinfo.c' || echo '$(srcdir)/'`gstinfo.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstinfo.Tpo $(DEPDIR)/libgstreamer_@GST_API_VERSION@_la-gstinfo.Plo @@ -1919,7 +1965,7 @@ Android.mk: Makefile.am @HAVE_INTROSPECTION_TRUE@ --include=GLib-2.0 \ @HAVE_INTROSPECTION_TRUE@ --include=GObject-2.0 \ @HAVE_INTROSPECTION_TRUE@ --include=GModule-2.0 \ -@HAVE_INTROSPECTION_TRUE@ --libtool="$(top_builddir)/libtool" \ +@HAVE_INTROSPECTION_TRUE@ --libtool="${LIBTOOL}" \ @HAVE_INTROSPECTION_TRUE@ --pkg glib-2.0 \ @HAVE_INTROSPECTION_TRUE@ --pkg gobject-2.0 \ @HAVE_INTROSPECTION_TRUE@ --pkg gmodule-no-export-2.0 \ @@ -53,7 +53,7 @@ * </programlisting> * </example> * - * It's allowed to pass two NULL pointers to gst_init() in case you don't want + * It's allowed to pass two %NULL pointers to gst_init() in case you don't want * to pass the command line args to GStreamer. * * You can also use GOption to initialize your own parameters as shown in @@ -91,8 +91,6 @@ * The gst_deinit() call is used to clean up all internal resources used * by <application>GStreamer</application>. It is mostly used in unit tests * to check for leaks. - * - * Last reviewed on 2006-08-11 (0.10.10) */ #include "gst_private.h" @@ -377,7 +375,7 @@ gst_init_check (int *argc, char **argv[], GError ** err) * </para></note> * * WARNING: This function does not work in the same way as corresponding - * functions in other glib-style libraries, such as gtk_init(). In + * functions in other glib-style libraries, such as gtk_init\(\). In * particular, unknown command line options cause this function to * abort program execution. */ @@ -402,7 +400,7 @@ gst_init (int *argc, char **argv[]) * Use this function to check if GStreamer has been initialized with gst_init() * or gst_init_check(). * - * Returns: TRUE if initialization has been done, FALSE otherwise. + * Returns: %TRUE if initialization has been done, %FALSE otherwise. */ gboolean gst_is_initialized (void) @@ -461,6 +459,7 @@ static gboolean init_pre (GOptionContext * context, GOptionGroup * group, gpointer data, GError ** error) { + gchar *libdir; if (gst_initialized) { GST_DEBUG ("already initialized"); return TRUE; @@ -471,6 +470,7 @@ init_pre (GOptionContext * context, GOptionGroup * group, gpointer data, #ifndef GST_DISABLE_GST_DEBUG _priv_gst_debug_init (); + priv_gst_dump_dot_dir = g_getenv ("GST_DEBUG_DUMP_DOT_DIR"); #endif #ifdef ENABLE_NLS @@ -478,29 +478,27 @@ init_pre (GOptionContext * context, GOptionGroup * group, gpointer data, bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); #endif /* ENABLE_NLS */ -#ifndef GST_DISABLE_GST_DEBUG + /* This is the earliest we can make stuff show up in the logs. + * So give some useful info about GStreamer here */ +#ifdef G_OS_WIN32 { - const gchar *debug_list; - const gchar *color_mode; - - if (g_getenv ("GST_DEBUG_NO_COLOR") != NULL) - gst_debug_set_color_mode (GST_DEBUG_COLOR_MODE_OFF); - color_mode = g_getenv ("GST_DEBUG_COLOR_MODE"); - if (color_mode) - gst_debug_set_color_mode_from_string (color_mode); - - debug_list = g_getenv ("GST_DEBUG"); - if (debug_list) { - gst_debug_set_threshold_from_string (debug_list, FALSE); - } - } + gchar *basedir = + g_win32_get_package_installation_directory_of_module + (_priv_gst_dll_handle); - priv_gst_dump_dot_dir = g_getenv ("GST_DEBUG_DUMP_DOT_DIR"); + libdir = g_build_filename (basedir, +#ifdef _DEBUG + "debug" +#endif + "lib", NULL); + g_free (basedir); + } +#else + libdir = g_strdup (LIBDIR); #endif - /* This is the earliest we can make stuff show up in the logs. - * So give some useful info about GStreamer here */ GST_INFO ("Initializing GStreamer Core Library version %s", VERSION); - GST_INFO ("Using library installed in %s", LIBDIR); + GST_INFO ("Using library installed in %s", libdir); + g_free (libdir); /* Print some basic system details if possible (OS/architecture) */ #ifdef HAVE_SYS_UTSNAME_H @@ -568,6 +566,7 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data, _priv_gst_mini_object_initialize (); _priv_gst_quarks_initialize (); + _priv_gst_allocator_initialize (); _priv_gst_memory_initialize (); _priv_gst_format_initialize (); _priv_gst_query_initialize (); @@ -575,6 +574,7 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data, _priv_gst_caps_initialize (); _priv_gst_caps_features_initialize (); _priv_gst_meta_initialize (); + _priv_gst_message_initialize (); g_type_class_ref (gst_object_get_type ()); g_type_class_ref (gst_pad_get_type ()); @@ -663,6 +663,7 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data, g_type_class_ref (gst_meta_flags_get_type ()); g_type_class_ref (gst_toc_entry_type_get_type ()); g_type_class_ref (gst_toc_scope_get_type ()); + g_type_class_ref (gst_toc_loop_type_get_type ()); g_type_class_ref (gst_control_binding_get_type ()); g_type_class_ref (gst_control_source_get_type ()); g_type_class_ref (gst_lock_flags_get_type ()); @@ -671,11 +672,12 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data, _priv_gst_event_initialize (); _priv_gst_buffer_initialize (); - _priv_gst_message_initialize (); _priv_gst_buffer_list_initialize (); _priv_gst_sample_initialize (); - _priv_gst_value_initialize (); _priv_gst_context_initialize (); + _priv_gst_date_time_initialize (); + _priv_gst_toc_initialize (); + _priv_gst_value_initialize (); g_type_class_ref (gst_param_spec_fraction_get_type ()); _priv_gst_tag_initialize (); @@ -694,7 +696,7 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data, * gstreamer as being initialized, since it is the case from a plugin point of * view. * - * If anything fails, it will be put back to FALSE in gst_init_check(). + * If anything fails, it will be put back to %FALSE in gst_init_check(). * This allows some special plugins that would call gst_init() to not cause a * looping effect (i.e. initializing GStreamer twice). */ @@ -1059,6 +1061,7 @@ gst_deinit (void) g_type_class_unref (g_type_class_peek (gst_control_binding_get_type ())); g_type_class_unref (g_type_class_peek (gst_control_source_get_type ())); g_type_class_unref (g_type_class_peek (gst_toc_entry_type_get_type ())); + g_type_class_unref (g_type_class_peek (gst_toc_loop_type_get_type ())); g_type_class_unref (g_type_class_peek (gst_lock_flags_get_type ())); g_type_class_unref (g_type_class_peek (gst_allocator_flags_get_type ())); g_type_class_unref (g_type_class_peek (gst_stream_flags_get_type ())); @@ -42,11 +42,14 @@ #include <gst/gstcontrolsource.h> #include <gst/gstdatetime.h> #include <gst/gstdebugutils.h> +#include <gst/gstdevice.h> +#include <gst/gstdevicemonitor.h> #include <gst/gstelement.h> #include <gst/gstelementmetadata.h> #include <gst/gsterror.h> #include <gst/gstevent.h> #include <gst/gstghostpad.h> +#include <gst/gstglobaldevicemonitor.h> #include <gst/gstinfo.h> #include <gst/gstiterator.h> #include <gst/gstmessage.h> diff --git a/gst/gst_private.h b/gst/gst_private.h index 61762b2..e85d5c5 100644 --- a/gst/gst_private.h +++ b/gst/gst_private.h @@ -54,6 +54,9 @@ extern const char g_log_domain_gstreamer[]; /* for GstElement */ #include "gstelement.h" +/* for GstDeviceMonitor */ +#include "gstdevicemonitor.h" + /* for GstToc */ #include "gsttoc.h" @@ -101,6 +104,8 @@ G_GNUC_INTERNAL gboolean _priv_gst_in_valgrind (void); /* init functions called from gst_init(). */ G_GNUC_INTERNAL void _priv_gst_quarks_initialize (void); G_GNUC_INTERNAL void _priv_gst_mini_object_initialize (void); +G_GNUC_INTERNAL void _priv_gst_memory_initialize (void); +G_GNUC_INTERNAL void _priv_gst_allocator_initialize (void); G_GNUC_INTERNAL void _priv_gst_buffer_initialize (void); G_GNUC_INTERNAL void _priv_gst_buffer_list_initialize (void); G_GNUC_INTERNAL void _priv_gst_structure_initialize (void); @@ -109,7 +114,6 @@ G_GNUC_INTERNAL void _priv_gst_caps_features_initialize (void); G_GNUC_INTERNAL void _priv_gst_event_initialize (void); G_GNUC_INTERNAL void _priv_gst_format_initialize (void); G_GNUC_INTERNAL void _priv_gst_message_initialize (void); -G_GNUC_INTERNAL void _priv_gst_memory_initialize (void); G_GNUC_INTERNAL void _priv_gst_meta_initialize (void); G_GNUC_INTERNAL void _priv_gst_plugin_initialize (void); G_GNUC_INTERNAL void _priv_gst_query_initialize (void); @@ -118,6 +122,8 @@ G_GNUC_INTERNAL void _priv_gst_tag_initialize (void); G_GNUC_INTERNAL void _priv_gst_value_initialize (void); G_GNUC_INTERNAL void _priv_gst_debug_init (void); G_GNUC_INTERNAL void _priv_gst_context_initialize (void); +G_GNUC_INTERNAL void _priv_gst_toc_initialize (void); +G_GNUC_INTERNAL void _priv_gst_date_time_initialize (void); /* Private registry functions */ G_GNUC_INTERNAL @@ -352,7 +358,7 @@ struct _GstTypeFindFactory { GstTypeFindFunction function; gchar ** extensions; - GstCaps * caps; /* FIXME: not yet saved in registry */ + GstCaps * caps; gpointer user_data; GDestroyNotify user_data_notify; @@ -393,5 +399,24 @@ struct _GstElementFactoryClass { gpointer _gst_reserved[GST_PADDING]; }; +struct _GstDeviceMonitorFactory { + GstPluginFeature feature; + /* <private> */ + + GType type; /* unique GType the device factory or 0 if not loaded */ + + volatile GstDeviceMonitor *monitor; + gpointer metadata; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstDeviceMonitorFactoryClass { + GstPluginFeatureClass parent; + /* <private> */ + + gpointer _gst_reserved[GST_PADDING]; +}; + G_END_DECLS #endif /* __GST_PRIVATE_H__ */ diff --git a/gst/gstallocator.c b/gst/gstallocator.c index f117d98..cbcb1e4 100644 --- a/gst/gstallocator.c +++ b/gst/gstallocator.c @@ -25,7 +25,7 @@ * @see_also: #GstMemory * * Memory is usually created by allocators with a gst_allocator_alloc() - * method call. When NULL is used as the allocator, the default allocator will + * method call. When %NULL is used as the allocator, the default allocator will * be used. * * New allocators can be registered with gst_allocator_register(). @@ -35,8 +35,6 @@ * * New memory can be created with gst_memory_new_wrapped() that wraps the memory * allocated elsewhere. - * - * Last reviewed on 2012-07-09 (0.11.3) */ #ifdef HAVE_CONFIG_H @@ -220,10 +218,10 @@ gst_allocator_register (const gchar * name, GstAllocator * allocator) * gst_allocator_find: * @name: (allow-none): the name of the allocator * - * Find a previously registered allocator with @name. When @name is NULL, the + * Find a previously registered allocator with @name. When @name is %NULL, the * default allocator will be returned. * - * Returns: (transfer full): a #GstAllocator or NULL when the allocator with @name was not + * Returns: (transfer full): a #GstAllocator or %NULL when the allocator with @name was not * registered. Use gst_object_unref() to release the allocator after usage. */ GstAllocator * @@ -276,13 +274,13 @@ gst_allocator_set_default (GstAllocator * allocator) * @size big. * * The optional @params can specify the prefix and padding for the memory. If - * NULL is passed, no flags, no extra prefix/padding and a default alignment is + * %NULL is passed, no flags, no extra prefix/padding and a default alignment is * used. * * The prefix/padding will be filled with 0 if flags contains * #GST_MEMORY_FLAG_ZERO_PREFIXED and #GST_MEMORY_FLAG_ZERO_PADDED respectively. * - * When @allocator is NULL, the default allocator will be used. + * When @allocator is %NULL, the default allocator will be used. * * The alignment in @params is given as a bitmask so that @align + 1 equals * the amount of bytes to align to. For example, to align to 8 bytes, @@ -571,7 +569,7 @@ gst_allocator_sysmem_init (GstAllocatorSysmem * allocator) } void -_priv_gst_memory_initialize (void) +_priv_gst_allocator_initialize (void) { g_rw_lock_init (&lock); allocators = g_hash_table_new (g_str_hash, g_str_equal); diff --git a/gst/gstallocator.h b/gst/gstallocator.h index 2337855..99deee2 100644 --- a/gst/gstallocator.h +++ b/gst/gstallocator.h @@ -92,8 +92,6 @@ typedef enum { /** * GstAllocator: - * @object: parent structure - * @mem_type: the memory type this allocator provides * @mem_map: the implementation of the GstMemoryMapFunction * @mem_unmap: the implementation of the GstMemoryUnmapFunction * @mem_copy: the implementation of the GstMemoryCopyFunction @@ -108,6 +106,7 @@ struct _GstAllocator const gchar *mem_type; + /*< public >*/ GstMemoryMapFunction mem_map; GstMemoryUnmapFunction mem_unmap; @@ -121,9 +120,18 @@ struct _GstAllocator GstAllocatorPrivate *priv; }; +/** + * GstAllocatorClass: + * @object_class: Object parent class + * @alloc: implementation that acquires memory + * @free: implementation that releases memory + * + * The #GstAllocator is used to create new memory. + */ struct _GstAllocatorClass { GstObjectClass object_class; + /*< public >*/ GstMemory * (*alloc) (GstAllocator *allocator, gsize size, GstAllocationParams *params); void (*free) (GstAllocator *allocator, GstMemory *memory); diff --git a/gst/gstatomicqueue.c b/gst/gstatomicqueue.c index 89bbb33..72ad2e3 100644 --- a/gst/gstatomicqueue.c +++ b/gst/gstatomicqueue.c @@ -214,7 +214,7 @@ gst_atomic_queue_unref (GstAtomicQueue * queue) * * Peek the head element of the queue without removing it from the queue. * - * Returns: (transfer none): the head element of @queue or NULL when + * Returns: (transfer none): the head element of @queue or %NULL when * the queue is empty. */ gpointer @@ -264,7 +264,7 @@ gst_atomic_queue_peek (GstAtomicQueue * queue) * * Get the head element of the queue. * - * Returns: (transfer full): the head element of @queue or NULL when + * Returns: (transfer full): the head element of @queue or %NULL when * the queue is empty. */ gpointer diff --git a/gst/gstatomicqueue.h b/gst/gstatomicqueue.h index 1b9c63a..a176c1b 100644 --- a/gst/gstatomicqueue.h +++ b/gst/gstatomicqueue.h @@ -34,7 +34,7 @@ G_BEGIN_DECLS * * Opaque atomic data queue. * - * Use the acessor functions to get the stored values. + * Use the accessor functions to get the stored values. */ typedef struct _GstAtomicQueue GstAtomicQueue; diff --git a/gst/gstbin.c b/gst/gstbin.c index 581b251..77bbc3e 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -148,13 +148,11 @@ * </variablelist> * * A #GstBin will by default forward any event sent to it to all sink elements. - * If all the sinks return TRUE, the bin will also return TRUE, else FALSE is - * returned. If no sinks are in the bin, the event handler will return TRUE. + * If all the sinks return %TRUE, the bin will also return %TRUE, else %FALSE is + * returned. If no sinks are in the bin, the event handler will return %TRUE. * * </para> * </refsect2> - * - * Last reviewed on 2012-03-28 (0.11.3) */ #include "gst_private.h" @@ -198,6 +196,7 @@ struct _GstBinPrivate gboolean message_forward; gboolean posted_eos; + gboolean posted_playing; GList *contexts; }; @@ -218,8 +217,7 @@ static void gst_bin_get_property (GObject * object, guint prop_id, static GstStateChangeReturn gst_bin_change_state_func (GstElement * element, GstStateChange transition); -static void gst_bin_state_changed (GstElement * element, GstState oldstate, - GstState newstate, GstState pending); +static gboolean gst_bin_post_message (GstElement * element, GstMessage * msg); static GstStateChangeReturn gst_bin_get_state_func (GstElement * element, GstState * state, GstState * pending, GstClockTime timeout); static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret, @@ -372,7 +370,7 @@ gst_bin_class_init (GstBinClass * klass) /** * GstBin:async-handling: * - * If set to #TRUE, the bin will handle asynchronous state changes. + * If set to %TRUE, the bin will handle asynchronous state changes. * This should be used only if the bin subclass is modifying the state * of its children on its own. */ @@ -408,7 +406,7 @@ gst_bin_class_init (GstBinClass * klass) * @bin: the #GstBin * * Will be emitted when the bin needs to perform latency calculations. This - * signal is only emited for toplevel bins or when async-handling is + * signal is only emitted for toplevel bins or when async-handling is * enabled. * * Only one signal handler is invoked. If no signals are connected, the @@ -452,7 +450,7 @@ gst_bin_class_init (GstBinClass * klass) gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state_func); - gstelement_class->state_changed = GST_DEBUG_FUNCPTR (gst_bin_state_changed); + gstelement_class->post_message = GST_DEBUG_FUNCPTR (gst_bin_post_message); gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state_func); #if 0 gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_bin_get_index_func); @@ -888,8 +886,8 @@ find_message (GstBin * bin, GstObject * src, GstMessageType types) guint i; for (i = 0; i < 32; i++) - if (types & (1 << i)) - GST_DEBUG_OBJECT (bin, " %s", gst_message_type_get_name (1 << i)); + if (types & (1U << i)) + GST_DEBUG_OBJECT (bin, " %s", gst_message_type_get_name (1U << i)); } #endif } @@ -1281,7 +1279,7 @@ had_parent: * * MT safe. * - * Returns: TRUE if the element could be added, FALSE if + * Returns: %TRUE if the element could be added, %FALSE if * the bin does not want to accept the element. */ gboolean @@ -1594,7 +1592,7 @@ not_in_bin: * * MT safe. * - * Returns: TRUE if the element could be removed, FALSE if + * Returns: %TRUE if the element could be removed, %FALSE if * the bin does not want to remove the element. */ gboolean @@ -1635,7 +1633,7 @@ no_function: * * MT safe. Caller owns returned value. * - * Returns: (transfer full): a #GstIterator of #GstElement, or NULL + * Returns: (transfer full): a #GstIterator of #GstElement, or %NULL */ GstIterator * gst_bin_iterate_elements (GstBin * bin) @@ -1675,7 +1673,7 @@ iterate_child_recurse (GstIterator * it, const GValue * item) * * MT safe. Caller owns returned value. * - * Returns: (transfer full): a #GstIterator of #GstElement, or NULL + * Returns: (transfer full): a #GstIterator of #GstElement, or %NULL */ GstIterator * gst_bin_iterate_recurse (GstBin * bin) @@ -1732,7 +1730,7 @@ sink_iterator_filter (const GValue * vchild, GValue * vbin) * * MT safe. Caller owns returned value. * - * Returns: (transfer full): a #GstIterator of #GstElement, or NULL + * Returns: (transfer full): a #GstIterator of #GstElement, or %NULL */ GstIterator * gst_bin_iterate_sinks (GstBin * bin) @@ -1792,7 +1790,7 @@ src_iterator_filter (const GValue * vchild, GValue * vbin) * * MT safe. Caller owns returned value. * - * Returns: (transfer full): a #GstIterator of #GstElement, or NULL + * Returns: (transfer full): a #GstIterator of #GstElement, or %NULL */ GstIterator * gst_bin_iterate_sources (GstBin * bin) @@ -2168,7 +2166,7 @@ gst_bin_sort_iterator_new (GstBin * bin) * * MT safe. Caller owns returned value. * - * Returns: (transfer full): a #GstIterator of #GstElement, or NULL + * Returns: (transfer full): a #GstIterator of #GstElement, or %NULL */ GstIterator * gst_bin_iterate_sorted (GstBin * bin) @@ -2511,17 +2509,30 @@ gst_bin_do_latency_func (GstBin * bin) return res; } -static void -gst_bin_state_changed (GstElement * element, GstState oldstate, - GstState newstate, GstState pending) +static gboolean +gst_bin_post_message (GstElement * element, GstMessage * msg) { GstElementClass *pklass = (GstElementClass *) parent_class; + gboolean ret; + + ret = pklass->post_message (element, gst_message_ref (msg)); + + if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STATE_CHANGED && + GST_MESSAGE_SRC (msg) == GST_OBJECT_CAST (element)) { + GstState newstate, pending; + + gst_message_parse_state_changed (msg, NULL, &newstate, &pending); + if (newstate == GST_STATE_PLAYING && pending == GST_STATE_VOID_PENDING) { + GST_BIN_CAST (element)->priv->posted_playing = TRUE; + bin_do_eos (GST_BIN_CAST (element)); + } else { + GST_BIN_CAST (element)->priv->posted_playing = FALSE; + } + } - if (newstate == GST_STATE_PLAYING && pending == GST_STATE_VOID_PENDING) - bin_do_eos (GST_BIN_CAST (element)); + gst_message_unref (msg); - if (pklass->state_changed) - pklass->state_changed (element, oldstate, newstate, pending); + return ret; } static GstStateChangeReturn @@ -2579,9 +2590,10 @@ gst_bin_change_state_func (GstElement * element, GstStateChange transition) GST_DEBUG_OBJECT (element, "clearing all cached messages"); bin_remove_messages (bin, NULL, GST_MESSAGE_ANY); GST_OBJECT_UNLOCK (bin); - if (current == GST_STATE_PAUSED) - if (!(gst_bin_src_pads_activate (bin, FALSE))) - goto activate_failure; + /* We might not have reached PAUSED yet due to async errors, + * make sure to always deactivate the pads nonetheless */ + if (!(gst_bin_src_pads_activate (bin, FALSE))) + goto activate_failure; break; case GST_STATE_NULL: if (current == GST_STATE_READY) { @@ -3214,7 +3226,7 @@ bin_do_eos (GstBin * bin) */ eos = GST_STATE (bin) == GST_STATE_PLAYING && GST_STATE_PENDING (bin) == GST_STATE_VOID_PENDING - && is_eos (bin, &seqnum); + && bin->priv->posted_playing && is_eos (bin, &seqnum); GST_OBJECT_UNLOCK (bin); if (eos @@ -3273,8 +3285,7 @@ bin_do_stream_start (GstBin * bin) } } -/* must be called with the object lock. This function releases the lock to post - * the message. */ +/* must be called without the object lock as it posts messages */ static void bin_do_message_forward (GstBin * bin, GstMessage * message) { @@ -3283,7 +3294,6 @@ bin_do_message_forward (GstBin * bin, GstMessage * message) GST_DEBUG_OBJECT (bin, "pass %s message upward", GST_MESSAGE_TYPE_NAME (message)); - GST_OBJECT_UNLOCK (bin); /* we need to convert these messages to element messages so that our parent * bin can easily ignore them and so that the application can easily @@ -3293,8 +3303,6 @@ bin_do_message_forward (GstBin * bin, GstMessage * message) "message", GST_TYPE_MESSAGE, message, NULL)); gst_element_post_message (GST_ELEMENT_CAST (bin), forwarded); - - GST_OBJECT_LOCK (bin); } } @@ -3411,8 +3419,8 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message) { /* collect all eos messages from the children */ - GST_OBJECT_LOCK (bin); bin_do_message_forward (bin, message); + GST_OBJECT_LOCK (bin); /* ref message for future use */ bin_replace_message (bin, message, GST_MESSAGE_EOS); GST_OBJECT_UNLOCK (bin); @@ -3448,8 +3456,9 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message) gst_message_parse_segment_start (message, &format, &position); seqnum = gst_message_get_seqnum (message); - GST_OBJECT_LOCK (bin); bin_do_message_forward (bin, message); + + GST_OBJECT_LOCK (bin); /* if this is the first segment-start, post to parent but not to the * application */ if (!find_message (bin, NULL, GST_MESSAGE_SEGMENT_START) && @@ -3481,8 +3490,9 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message) gst_message_parse_segment_done (message, &format, &position); seqnum = gst_message_get_seqnum (message); - GST_OBJECT_LOCK (bin); bin_do_message_forward (bin, message); + + GST_OBJECT_LOCK (bin); bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START); /* if there are no more segment_start messages, everybody posted * a segment_done and we can post one on the bus. */ @@ -3583,9 +3593,9 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message) GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message, src ? GST_OBJECT_NAME (src) : "(NULL)"); - GST_OBJECT_LOCK (bin); bin_do_message_forward (bin, message); + GST_OBJECT_LOCK (bin); /* we ignore the message if we are going to <= READY */ if ((target = GST_STATE_TARGET (bin)) <= GST_STATE_READY) goto ignore_start_message; @@ -3616,9 +3626,9 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message) gst_message_parse_async_done (message, &running_time); - GST_OBJECT_LOCK (bin); bin_do_message_forward (bin, message); + GST_OBJECT_LOCK (bin); /* ignore messages if we are shutting down */ if ((target = GST_STATE_TARGET (bin)) <= GST_STATE_READY) goto ignore_done_message; @@ -4112,11 +4122,11 @@ compare_name (const GValue * velement, const gchar * name) * Gets the element with the given name from a bin. This * function recurses into child bins. * - * Returns NULL if no element with the given name is found in the bin. + * Returns %NULL if no element with the given name is found in the bin. * * MT safe. Caller owns returned reference. * - * Returns: (transfer full): the #GstElement with the given name, or NULL + * Returns: (transfer full): the #GstElement with the given name, or %NULL */ GstElement * gst_bin_get_by_name (GstBin * bin, const gchar * name) @@ -4154,12 +4164,12 @@ gst_bin_get_by_name (GstBin * bin, const gchar * name) * Gets the element with the given name from this bin. If the * element is not found, a recursion is performed on the parent bin. * - * Returns NULL if: + * Returns %NULL if: * - no element with the given name is found in the bin * * MT safe. Caller owns returned reference. * - * Returns: (transfer full): the #GstElement with the given name, or NULL + * Returns: (transfer full): the #GstElement with the given name, or %NULL */ GstElement * gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name) @@ -4260,7 +4270,7 @@ gst_bin_get_by_interface (GstBin * bin, GType iface) * MT safe. Caller owns returned value. * * Returns: (transfer full): a #GstIterator of #GstElement for all elements - * in the bin implementing the given interface, or NULL + * in the bin implementing the given interface, or %NULL */ GstIterator * gst_bin_iterate_all_by_interface (GstBin * bin, GType iface) diff --git a/gst/gstbin.h b/gst/gstbin.h index 17d1441..33c8d98 100644 --- a/gst/gstbin.h +++ b/gst/gstbin.h @@ -41,7 +41,7 @@ G_BEGIN_DECLS /** * GstBinFlags: * @GST_BIN_FLAG_NO_RESYNC: don't resync a state change when elements are - * added or linked in the bin. + * added or linked in the bin (Since 1.0.5) * @GST_BIN_FLAG_LAST: the last enum in the series of flags for bins. * Derived classes can use this as first value in a list of flags. * @@ -62,7 +62,7 @@ typedef enum { * Check if @bin will resync its state change when elements are added and * removed. * - * Since: 1.1.1 + * Since: 1.0.5 */ #define GST_BIN_IS_NO_RESYNC(bin) (GST_OBJECT_FLAG_IS_SET(bin,GST_BIN_FLAG_NO_RESYNC)) diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 5c1d8f8..8aef1c2 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -33,9 +33,7 @@ * created one will typically allocate memory for it and add it to the buffer. * The following example creates a buffer that can hold a given video frame * with a given width, height and bits per plane. - * <example> - * <title>Creating a buffer for a video frame</title> - * <programlisting> + * |[ * GstBuffer *buffer; * GstMemory *memory; * gint size, width, height, bpp; @@ -45,11 +43,10 @@ * memory = gst_allocator_alloc (NULL, size, NULL); * gst_buffer_insert_memory (buffer, -1, memory); * ... - * </programlisting> - * </example> + * ]| * - * Alternatively, use gst_buffer_new_allocate() - * to create a buffer with preallocated data of a given size. + * Alternatively, use gst_buffer_new_allocate() to create a buffer with + * preallocated data of a given size. * * Buffers can contain a list of #GstMemory objects. You can retrieve how many * memory objects with gst_buffer_n_memory() and you can get a pointer @@ -71,7 +68,7 @@ * produced so far. For compressed data, it could be the byte offset in a * source or destination file. Likewise, the end offset will be the offset of * the end of the buffer. These can only be meaningfully interpreted if you - * know the media type of the buffer (the preceeding CAPS event). Either or both + * know the media type of the buffer (the preceding CAPS event). Either or both * can be set to #GST_BUFFER_OFFSET_NONE. * * gst_buffer_ref() is used to increase the refcount of a buffer. This must be @@ -91,7 +88,7 @@ * * Several flags of the buffer can be set and unset with the * GST_BUFFER_FLAG_SET() and GST_BUFFER_FLAG_UNSET() macros. Use - * GST_BUFFER_FLAG_IS_SET() to test if a certain #GstBufferFlag is set. + * GST_BUFFER_FLAG_IS_SET() to test if a certain #GstBufferFlags flag is set. * * Buffers can be efficiently merged into a larger buffer with * gst_buffer_append(). Copying of memory will only be done when absolutely @@ -107,8 +104,6 @@ * the refcount drops to 0, any memory and metadata pointed to by the buffer is * unreffed as well. Buffers allocated from a #GstBufferPool will be returned to * the pool when the refcount drops to 0. - * - * Last reviewed on 2012-03-28 (0.11.3) */ #include "gst_private.h" @@ -282,10 +277,11 @@ _replace_memory (GstBuffer * buffer, guint len, guint idx, guint length, } if (end < len) { - g_memmove (&GST_BUFFER_MEM_PTR (buffer, idx), + memmove (&GST_BUFFER_MEM_PTR (buffer, idx), &GST_BUFFER_MEM_PTR (buffer, end), (len - end) * sizeof (gpointer)); } GST_BUFFER_MEM_LEN (buffer) = len - length; + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY); } static inline void @@ -320,6 +316,8 @@ _memory_add (GstBuffer * buffer, gint idx, GstMemory * mem, gboolean lock) gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE); GST_BUFFER_MEM_PTR (buffer, idx) = mem; GST_BUFFER_MEM_LEN (buffer) = len + 1; + + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY); } GST_DEFINE_MINI_OBJECT_TYPE (GstBuffer, gst_buffer); @@ -341,7 +339,7 @@ _priv_gst_buffer_initialize (void) * * Returns: the maximum amount of memory blocks that a buffer can hold. * - * Since: 1.2.0 + * Since: 1.2 */ guint gst_buffer_get_max_memory (void) @@ -519,6 +517,9 @@ _gst_buffer_copy (GstBuffer * buffer) if (!gst_buffer_copy_into (copy, buffer, GST_BUFFER_COPY_ALL, 0, -1)) gst_buffer_replace (©, NULL); + if (copy) + GST_BUFFER_FLAG_UNSET (copy, GST_BUFFER_FLAG_TAG_MEMORY); + return copy; } @@ -634,22 +635,22 @@ gst_buffer_new (void) /** * gst_buffer_new_allocate: - * @allocator: (transfer none) (allow-none): the #GstAllocator to use, or NULL to use the + * @allocator: (transfer none) (allow-none): the #GstAllocator to use, or %NULL to use the * default allocator * @size: the size in bytes of the new buffer's data. * @params: (transfer none) (allow-none): optional parameters * * Tries to create a newly allocated buffer with data of the given size and * extra parameters from @allocator. If the requested amount of memory can't be - * allocated, NULL will be returned. The allocated buffer memory is not cleared. + * allocated, %NULL will be returned. The allocated buffer memory is not cleared. * - * When @allocator is NULL, the default memory allocator will be used. + * When @allocator is %NULL, the default memory allocator will be used. * * Note that when @size == 0, the buffer will not have memory associated with it. * * MT safe. * - * Returns: (transfer full): a new #GstBuffer, or NULL if the memory couldn't + * Returns: (transfer full): a new #GstBuffer, or %NULL if the memory couldn't * be allocated. */ GstBuffer * @@ -723,6 +724,7 @@ gst_buffer_new_allocate (GstAllocator * allocator, gsize size, if (size > 0) _memory_add (newbuf, -1, gst_memory_ref (mem), TRUE); #endif + GST_BUFFER_FLAG_UNSET (newbuf, GST_BUFFER_FLAG_TAG_MEMORY); return newbuf; @@ -769,6 +771,7 @@ gst_buffer_new_wrapped_full (GstMemoryFlags flags, gpointer data, gst_memory_new_wrapped (flags, data, maxsize, offset, size, user_data, notify); _memory_add (newbuf, -1, mem, TRUE); + GST_BUFFER_FLAG_UNSET (newbuf, GST_BUFFER_FLAG_TAG_MEMORY); return newbuf; } @@ -883,6 +886,7 @@ _get_mapped (GstBuffer * buffer, guint idx, GstMapInfo * info, GST_BUFFER_MEM_PTR (buffer, idx) = mapped; /* unlock old memory */ gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY); } gst_memory_unref (mem); @@ -1167,6 +1171,68 @@ gst_buffer_find_memory (GstBuffer * buffer, gsize offset, gsize size, } /** + * gst_buffer_is_memory_range_writable: + * @buffer: a #GstBuffer. + * @idx: an index + * @length: a length should not be 0 + * + * Check if @length memory blocks in @buffer starting from @idx are writable. + * + * @length can be -1 to check all the memory blocks after @idx. + * + * Note that this function does not check if @buffer is writable, use + * gst_buffer_is_writable() to check that if needed. + * + * Returns: %TRUE if the memory range is writable + * + * Since: 1.4 + */ +gboolean +gst_buffer_is_memory_range_writable (GstBuffer * buffer, guint idx, gint length) +{ + guint i, len; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + + GST_CAT_DEBUG (GST_CAT_BUFFER, "idx %u, length %d", idx, length); + + len = GST_BUFFER_MEM_LEN (buffer); + g_return_val_if_fail ((len == 0 && idx == 0 && length == -1) || + (length == -1 && idx < len) || (length > 0 && length + idx <= len), + FALSE); + + if (length == -1) + len -= idx; + else + len = length; + + for (i = 0; i < len; i++) { + if (!gst_memory_is_writable (GST_BUFFER_MEM_PTR (buffer, i + idx))) + return FALSE; + } + return TRUE; +} + +/** + * gst_buffer_is_all_memory_writable: + * @buffer: a #GstBuffer. + * + * Check if all memory blocks in @buffer are writable. + * + * Note that this function does not check if @buffer is writable, use + * gst_buffer_is_writable() to check that if needed. + * + * Returns: %TRUE if all memory blocks in @buffer are writable + * + * Since: 1.4 + */ +gboolean +gst_buffer_is_all_memory_writable (GstBuffer * buffer) +{ + return gst_buffer_is_memory_range_writable (buffer, 0, -1); +} + +/** * gst_buffer_get_sizes: * @buffer: a #GstBuffer. * @offset: (out): a pointer to the offset @@ -1277,7 +1343,7 @@ gst_buffer_get_sizes_range (GstBuffer * buffer, guint idx, gint length, /** * gst_buffer_resize: * @buffer: a #GstBuffer. - * @offset: the offset adjustement + * @offset: the offset adjustment * @size: the new size or -1 to just adjust the offset * * Set the offset and total size of the memory blocks in @buffer. @@ -1306,7 +1372,7 @@ gst_buffer_set_size (GstBuffer * buffer, gssize size) * @buffer: a #GstBuffer. * @idx: an index * @length: a length - * @offset: the offset adjustement + * @offset: the offset adjustment * @size: the new size or -1 to just adjust the offset * * Set the total size of the @length memory blocks starting at @idx in @@ -1393,6 +1459,8 @@ gst_buffer_resize_range (GstBuffer * buffer, guint idx, gint length, GST_BUFFER_MEM_PTR (buffer, i) = newmem; gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE); gst_memory_unref (mem); + + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY); } } @@ -1513,21 +1581,20 @@ not_writable: { GST_WARNING_OBJECT (buffer, "write map requested on non-writable buffer"); g_critical ("write map requested on non-writable buffer"); + memset (info, 0, sizeof (GstMapInfo)); return FALSE; } no_memory: { /* empty buffer, we need to return NULL */ GST_DEBUG_OBJECT (buffer, "can't get buffer memory"); - info->memory = NULL; - info->data = NULL; - info->size = 0; - info->maxsize = 0; + memset (info, 0, sizeof (GstMapInfo)); return TRUE; } cannot_map: { GST_DEBUG_OBJECT (buffer, "cannot map memory"); + memset (info, 0, sizeof (GstMapInfo)); return FALSE; } } @@ -1775,7 +1842,7 @@ gst_buffer_memset (GstBuffer * buffer, gsize offset, guint8 val, gsize size) * * MT safe. * - * Returns: (transfer full): the new #GstBuffer or NULL if the arguments were + * Returns: (transfer full): the new #GstBuffer or %NULL if the arguments were * invalid. */ GstBuffer * @@ -1853,6 +1920,7 @@ gst_buffer_append_region (GstBuffer * buf1, GstBuffer * buf2, gssize offset, } GST_BUFFER_MEM_LEN (buf2) = 0; + GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_TAG_MEMORY); gst_buffer_unref (buf2); return buf1; @@ -1864,7 +1932,7 @@ gst_buffer_append_region (GstBuffer * buf1, GstBuffer * buf2, gssize offset, * @api: the #GType of an API * * Get the metadata for @api on buffer. When there is no such - * metadata, NULL is returned. + * metadata, %NULL is returned. * * Returns: (transfer none): the metadata for @api on @buffer. */ @@ -1993,7 +2061,7 @@ gst_buffer_remove_meta (GstBuffer * buffer, GstMeta * meta) * Retrieve the next #GstMeta after @current. If @state points * to %NULL, the first metadata is returned. * - * @state will be updated with an opage state pointer + * @state will be updated with an opaque state pointer * * Returns: (transfer none): The next #GstMeta or %NULL when there are * no more items. diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index c241792..0ebf142 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -44,13 +44,13 @@ typedef struct _GstBufferPool GstBufferPool; * GST_BUFFER_FLAGS: * @buf: a #GstBuffer. * - * A flags word containing #GstBufferFlag flags set on this buffer. + * A flags word containing #GstBufferFlags flags set on this buffer. */ #define GST_BUFFER_FLAGS(buf) GST_MINI_OBJECT_FLAGS(buf) /** * GST_BUFFER_FLAG_IS_SET: * @buf: a #GstBuffer. - * @flag: the #GstBufferFlag to check. + * @flag: the #GstBufferFlags flag to check. * * Gives the status of a specific flag on a buffer. */ @@ -58,7 +58,7 @@ typedef struct _GstBufferPool GstBufferPool; /** * GST_BUFFER_FLAG_SET: * @buf: a #GstBuffer. - * @flag: the #GstBufferFlag to set. + * @flag: the #GstBufferFlags flag to set. * * Sets a buffer flag on a buffer. */ @@ -66,7 +66,7 @@ typedef struct _GstBufferPool GstBufferPool; /** * GST_BUFFER_FLAG_UNSET: * @buf: a #GstBuffer. - * @flag: the #GstBufferFlag to clear. + * @flag: the #GstBufferFlags flag to clear. * * Clears a buffer flag. */ @@ -192,6 +192,8 @@ typedef struct _GstBufferPool GstBufferPool; * @GST_BUFFER_FLAG_DROPPABLE: the buffer can be dropped without breaking the * stream, for example to reduce bandwidth. * @GST_BUFFER_FLAG_DELTA_UNIT: this unit cannot be decoded independently. + * @GST_BUFFER_FLAG_TAG_MEMORY: this flag is set when memory of the buffer + * is added/removed * @GST_BUFFER_FLAG_LAST: additional media specific flags can be added starting from * this flag. * @@ -208,6 +210,7 @@ typedef enum { GST_BUFFER_FLAG_GAP = (GST_MINI_OBJECT_FLAG_LAST << 7), GST_BUFFER_FLAG_DROPPABLE = (GST_MINI_OBJECT_FLAG_LAST << 8), GST_BUFFER_FLAG_DELTA_UNIT = (GST_MINI_OBJECT_FLAG_LAST << 9), + GST_BUFFER_FLAG_TAG_MEMORY = (GST_MINI_OBJECT_FLAG_LAST << 10), GST_BUFFER_FLAG_LAST = (GST_MINI_OBJECT_FLAG_LAST << 16) } GstBufferFlags; @@ -284,6 +287,9 @@ void gst_buffer_remove_all_memory (GstBuffer *buffer); gboolean gst_buffer_find_memory (GstBuffer *buffer, gsize offset, gsize size, guint *idx, guint *length, gsize *skip); +gboolean gst_buffer_is_memory_range_writable (GstBuffer *buffer, guint idx, gint length); +gboolean gst_buffer_is_all_memory_writable (GstBuffer *buffer); + gsize gst_buffer_fill (GstBuffer *buffer, gsize offset, gconstpointer src, gsize size); gsize gst_buffer_extract (GstBuffer *buffer, gsize offset, @@ -319,7 +325,7 @@ void gst_buffer_extract_dup (GstBuffer *buffer, gsize offset, * * Increases the refcount of the given buffer by one. * - * Note that the refcount affects the writeability + * Note that the refcount affects the writability * of @buf and its metadata, see gst_buffer_is_writable(). * It is important to note that keeping additional references to * GstBuffer instances can potentially increase the number @@ -461,9 +467,9 @@ gboolean gst_buffer_copy_into (GstBuffer *dest, GstBuffer *src * in some cases), and the reference counts are updated appropriately (the old * buffer is unreffed, the new is reffed). * - * Either @nbuf or the #GstBuffer pointed to by @obuf may be NULL. + * Either @nbuf or the #GstBuffer pointed to by @obuf may be %NULL. * - * Returns: TRUE when @obuf was different from @nbuf. + * Returns: %TRUE when @obuf was different from @nbuf. */ #ifdef _FOOL_GTK_DOC_ G_INLINE_FUNC gboolean gst_buffer_replace (GstBuffer **obuf, GstBuffer *nbuf); @@ -501,7 +507,7 @@ GstBuffer* gst_buffer_append (GstBuffer *buf1, GstBuffer *buf * When this function returns %TRUE, the next meta will be * returned. When %FALSE is returned, gst_buffer_foreach_meta() will return. * - * When @meta is set to NULL, the item will be removed from the buffer. + * When @meta is set to %NULL, the item will be removed from the buffer. * * Returns: %FALSE when gst_buffer_foreach_meta() should stop */ diff --git a/gst/gstbufferlist.c b/gst/gstbufferlist.c index 565ed5b..dca866c 100644 --- a/gst/gstbufferlist.c +++ b/gst/gstbufferlist.c @@ -33,8 +33,6 @@ * Buffer lists can be pushed on a srcpad with gst_pad_push_list(). This is * interesting when multiple buffers need to be pushed in one go because it * can reduce the amount of overhead for pushing each buffer individually. - * - * Last reviewed on 2012-03-28 (0.11.3) */ #include "gst_private.h" @@ -229,7 +227,7 @@ gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func, * * Get the buffer at @idx. * - * Returns: (transfer none): the buffer at @idx in @group or NULL when there + * Returns: (transfer none): the buffer at @idx in @group or %NULL when there * is no buffer. The buffer remains valid as long as @list is valid. */ GstBuffer * @@ -283,14 +281,21 @@ gst_buffer_list_insert (GstBufferList * list, gint idx, GstBuffer * buffer) * @idx: the index * @length: the amount to remove * - * Remove @length buffers starting from @idx in @list. The following buffers are - * moved to close the gap. + * Remove @length buffers starting from @idx in @list. The following buffers + * are moved to close the gap. */ void gst_buffer_list_remove (GstBufferList * list, guint idx, guint length) { + GstBuffer *buf; + gint i; + g_return_if_fail (GST_IS_BUFFER_LIST (list)); g_return_if_fail (idx < list->array->len); + for (i = idx; i < idx + length; ++i) { + buf = g_array_index (list->array, GstBuffer *, i); + gst_buffer_unref (buf); + } g_array_remove_range (list->array, idx, length); } diff --git a/gst/gstbufferlist.h b/gst/gstbufferlist.h index 4a6a99f..df8c455 100644 --- a/gst/gstbufferlist.h +++ b/gst/gstbufferlist.h @@ -48,7 +48,7 @@ typedef struct _GstBufferList GstBufferList; * When this function returns %TRUE, the next buffer will be * returned. When %FALSE is returned, gst_buffer_list_foreach() will return. * - * When @buffer is set to NULL, the item will be removed from the bufferlist. + * When @buffer is set to %NULL, the item will be removed from the bufferlist. * When @buffer has been made writable, the new buffer reference can be assigned * to @buffer. This function is responsible for unreffing the old buffer when * removing or modifying. @@ -66,7 +66,7 @@ typedef gboolean (*GstBufferListFunc) (GstBuffer **buffer, guint idx, * * Increases the refcount of the given buffer list by one. * - * Note that the refcount affects the writeability of @list and its data, see + * Note that the refcount affects the writability of @list and its data, see * gst_buffer_list_make_writable(). It is important to note that keeping * additional references to GstBufferList instances can potentially increase * the number of memcpy operations in a pipeline. diff --git a/gst/gstbufferpool.c b/gst/gstbufferpool.c index cdd3b2b..6c14ce4 100644 --- a/gst/gstbufferpool.c +++ b/gst/gstbufferpool.c @@ -24,17 +24,17 @@ * @short_description: Pool for buffers * @see_also: #GstBuffer * - * a #GstBufferPool is an object that can be used to pre-allocate and recycle + * A #GstBufferPool is an object that can be used to pre-allocate and recycle * buffers of the same size and with the same properties. * * A #GstBufferPool is created with gst_buffer_pool_new(). * - * After the buffer is created, it needs to be configured. - * gst_buffer_pool_get_config() get the current configuration structure from the - * pool. With gst_buffer_pool_config_set_params() and - * gst_buffer_pool_config_set_allocator() the bufferpool parameters and allocator - * can be configured. Other properties can be configured in the pool depending - * on the pool implementation. + * Once a pool is created, it needs to be configured. A call to + * gst_buffer_pool_get_config() returns the current configuration structure from + * the pool. With gst_buffer_pool_config_set_params() and + * gst_buffer_pool_config_set_allocator() the bufferpool parameters and + * allocator can be configured. Other properties can be configured in the pool + * depending on the pool implementation. * * A bufferpool can have extra options that can be enabled with * gst_buffer_pool_config_add_option(). The available options can be retrieved @@ -52,8 +52,8 @@ * When the pool is active, gst_buffer_pool_acquire_buffer() can be used to * retrieve a buffer from the pool. * - * Buffer allocated from a bufferpool will automatically be returned to the pool - * with gst_buffer_pool_release_buffer() when their refcount drops to 0. + * Buffers allocated from a bufferpool will automatically be returned to the + * pool with gst_buffer_pool_release_buffer() when their refcount drops to 0. * * The bufferpool can be deactivated again with gst_buffer_pool_set_active(). * All further gst_buffer_pool_acquire_buffer() calls will return an error. When @@ -61,8 +61,6 @@ * * Use gst_object_unref() to release the reference to a bufferpool. If the * refcount of the pool reaches 0, the pool will be freed. - * - * Last reviewed on 2012-03-28 (0.11.3) */ #include "gst_private.h" @@ -100,7 +98,7 @@ struct _GstBufferPoolPrivate gboolean started; gboolean active; - gint outstanding; + gint outstanding; /* number of buffers that are in use */ gboolean configured; GstStructure *config; @@ -113,12 +111,6 @@ struct _GstBufferPoolPrivate GstAllocationParams params; }; -enum -{ - /* add more above */ - LAST_SIGNAL -}; - static void gst_buffer_pool_finalize (GObject * object); G_DEFINE_TYPE (GstBufferPool, gst_buffer_pool, GST_TYPE_OBJECT); @@ -167,7 +159,7 @@ gst_buffer_pool_init (GstBufferPool * pool) g_rec_mutex_init (&priv->rec_lock); priv->poll = gst_poll_new_timer (); - priv->queue = gst_atomic_queue_new (10); + priv->queue = gst_atomic_queue_new (16); pool->flushing = 1; priv->active = FALSE; priv->configured = FALSE; @@ -178,6 +170,9 @@ gst_buffer_pool_init (GstBufferPool * pool) gst_allocation_params_init (&priv->params); gst_buffer_pool_config_set_allocator (priv->config, priv->allocator, &priv->params); + /* 1 control write for flushing */ + gst_poll_write_control (priv->poll); + /* 1 control write for marking that we are not waiting for poll */ gst_poll_write_control (priv->poll); GST_DEBUG_OBJECT (pool, "created"); @@ -210,7 +205,7 @@ gst_buffer_pool_finalize (GObject * object) * * Creates a new #GstBufferPool instance. * - * Returns: (transfer full): a new #GstBufferPool instance + * Returns: (transfer floating): a new #GstBufferPool instance */ GstBufferPool * gst_buffer_pool_new (void) @@ -273,10 +268,17 @@ do_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer, if (G_UNLIKELY (result != GST_FLOW_OK)) goto alloc_failed; + /* lock all metadata and mark as pooled, we want this to remain on + * the buffer and we want to remove any other metadata that gets added + * later */ gst_buffer_foreach_meta (*buffer, mark_meta_pooled, pool); + /* un-tag memory, this is how we expect the buffer when it is + * released again */ + GST_BUFFER_FLAG_UNSET (*buffer, GST_BUFFER_FLAG_TAG_MEMORY); + GST_LOG_OBJECT (pool, "allocated buffer %d/%d, %p", cur_buffers, - max_buffers, buffer); + max_buffers, *buffer); return result; @@ -300,8 +302,7 @@ alloc_failed: } } -/* the default implementation for preallocating the buffers - * in the pool */ +/* the default implementation for preallocating the buffers in the pool */ static gboolean default_start (GstBufferPool * pool) { @@ -356,34 +357,42 @@ do_start (GstBufferPool * pool) return TRUE; } - static void default_free_buffer (GstBufferPool * pool, GstBuffer * buffer) { gst_buffer_unref (buffer); } +static void +do_free_buffer (GstBufferPool * pool, GstBuffer * buffer) +{ + GstBufferPoolPrivate *priv; + GstBufferPoolClass *pclass; + + priv = pool->priv; + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + g_atomic_int_add (&priv->cur_buffers, -1); + GST_LOG_OBJECT (pool, "freeing buffer %p (%u left)", buffer, + priv->cur_buffers); + + if (G_LIKELY (pclass->free_buffer)) + pclass->free_buffer (pool, buffer); +} + /* must be called with the lock */ static gboolean default_stop (GstBufferPool * pool) { GstBufferPoolPrivate *priv = pool->priv; GstBuffer *buffer; - GstBufferPoolClass *pclass; - - pclass = GST_BUFFER_POOL_GET_CLASS (pool); /* clear the pool */ while ((buffer = gst_atomic_queue_pop (priv->queue))) { - GST_LOG_OBJECT (pool, "freeing %p", buffer); gst_poll_read_control (priv->poll); - - if (G_LIKELY (pclass->free_buffer)) - pclass->free_buffer (pool, buffer); + do_free_buffer (pool, buffer); } - priv->cur_buffers = 0; - - return TRUE; + return priv->cur_buffers == 0; } /* must be called with the lock */ @@ -407,13 +416,40 @@ do_stop (GstBufferPool * pool) return TRUE; } +/* must be called with the lock */ +static void +do_set_flushing (GstBufferPool * pool, gboolean flushing) +{ + GstBufferPoolPrivate *priv = pool->priv; + GstBufferPoolClass *pclass; + + pclass = GST_BUFFER_POOL_GET_CLASS (pool); + + if (GST_BUFFER_POOL_IS_FLUSHING (pool) == flushing) + return; + + if (flushing) { + g_atomic_int_set (&pool->flushing, 1); + gst_poll_write_control (priv->poll); + + if (pclass->flush_start) + pclass->flush_start (pool); + } else { + if (pclass->flush_stop) + pclass->flush_stop (pool); + + gst_poll_read_control (priv->poll); + g_atomic_int_set (&pool->flushing, 0); + } +} + /** * gst_buffer_pool_set_active: * @pool: a #GstBufferPool * @active: the new active state * * Control the active state of @pool. When the pool is inactive, new calls to - * gst_buffer_pool_acquire_buffer() will return with #GST_FLOW_FLUSHING. + * gst_buffer_pool_acquire_buffer() will return with %GST_FLOW_FLUSHING. * * Activating the bufferpool will preallocate all resources in the pool based on * the configuration of the pool. @@ -450,15 +486,17 @@ gst_buffer_pool_set_active (GstBufferPool * pool, gboolean active) if (!do_start (pool)) goto start_failed; + /* flush_stop my release buffers, setting to active to avoid running + * do_stop while activating the pool */ + priv->active = TRUE; + /* unset the flushing state now */ - gst_poll_read_control (priv->poll); - g_atomic_int_set (&pool->flushing, 0); + do_set_flushing (pool, FALSE); } else { gint outstanding; /* set to flushing first */ - g_atomic_int_set (&pool->flushing, 1); - gst_poll_write_control (priv->poll); + do_set_flushing (pool, TRUE); /* when all buffers are in the pool, free them. Else they will be * freed when they are released */ @@ -468,8 +506,9 @@ gst_buffer_pool_set_active (GstBufferPool * pool, gboolean active) if (!do_stop (pool)) goto stop_failed; } + + priv->active = FALSE; } - priv->active = active; GST_BUFFER_POOL_UNLOCK (pool); return res; @@ -565,9 +604,11 @@ wrong_config: * @pool: a #GstBufferPool * @config: (transfer full): a #GstStructure * - * Set the configuration of the pool. The pool must be inactive and all buffers - * allocated form this pool must be returned or else this function will do - * nothing and return FALSE. + * Set the configuration of the pool. If the pool is already configured, and + * the configuration haven't change, this function will return %TRUE. If the + * pool is active, this function will try deactivating it. Buffers allocated + * form this pool must be returned or else this function will do nothing and + * return %FALSE. * * @config is a #GstStructure that contains the configuration parameters for * the pool. A default and mandatory set of parameters can be configured with @@ -575,12 +616,12 @@ wrong_config: * and gst_buffer_pool_config_add_option(). * * If the parameters in @config can not be set exactly, this function returns - * FALSE and will try to update as much state as possible. The new state can + * %FALSE and will try to update as much state as possible. The new state can * then be retrieved and refined with gst_buffer_pool_get_config(). * * This function takes ownership of @config. * - * Returns: TRUE when the configuration could be set. + * Returns: %TRUE when the configuration could be set. */ gboolean gst_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) @@ -595,9 +636,24 @@ gst_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) priv = pool->priv; GST_BUFFER_POOL_LOCK (pool); + + /* nothing to do if config is unchanged */ + if (priv->configured && gst_structure_is_equal (config, priv->config)) + goto config_unchanged; + /* can't change the settings when active */ - if (priv->active) - goto was_active; + if (priv->active) { + GST_BUFFER_POOL_UNLOCK (pool); + if (!gst_buffer_pool_set_active (pool, FALSE)) { + GST_BUFFER_POOL_LOCK (pool); + goto was_active; + } + GST_BUFFER_POOL_LOCK (pool); + + /* not likely but as we released the lock */ + if (priv->active) + goto was_active; + } /* we can't change when outstanding buffers */ if (g_atomic_int_get (&priv->outstanding) != 0) @@ -611,20 +667,26 @@ gst_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) else result = FALSE; - if (result) { - if (priv->config) - gst_structure_free (priv->config); - priv->config = config; + /* save the config regardless of the result so user can read back the + * modified config and evaluate if the changes are acceptable */ + if (priv->config) + gst_structure_free (priv->config); + priv->config = config; + if (result) { /* now we are configured */ priv->configured = TRUE; - } else { - gst_structure_free (config); } GST_BUFFER_POOL_UNLOCK (pool); return result; +config_unchanged: + { + gst_structure_free (config); + GST_BUFFER_POOL_UNLOCK (pool); + return TRUE; + } /* ERRORS */ was_active: { @@ -673,11 +735,12 @@ static const gchar *empty_option[] = { NULL }; * gst_buffer_pool_get_options: * @pool: a #GstBufferPool * - * Get a NULL terminated array of string with supported bufferpool options for + * Get a %NULL terminated array of string with supported bufferpool options for * @pool. An option would typically be enabled with * gst_buffer_pool_config_add_option(). * - * Returns: (array zero-terminated=1) (transfer none): a NULL terminated array of strings. + * Returns: (array zero-terminated=1) (transfer none): a %NULL terminated array + * of strings. */ const gchar ** gst_buffer_pool_get_options (GstBufferPool * pool) @@ -712,7 +775,7 @@ invalid_result: * * Check if the bufferpool supports @option. * - * Returns: a NULL terminated array of strings. + * Returns: %TRUE if the buffer pool contains @option. */ gboolean gst_buffer_pool_has_option (GstBufferPool * pool, const gchar * option) @@ -765,10 +828,10 @@ gst_buffer_pool_config_set_params (GstStructure * config, GstCaps * caps, * * Set the @allocator and @params on @config. * - * One of @allocator and @params can be NULL, but not both. When @allocator - * is NULL, the default allocator of the pool will use the values in @param - * to perform its allocation. When @param is NULL, the pool will use the - * provided allocator with its default #GstAllocationParams. + * One of @allocator and @params can be %NULL, but not both. When @allocator + * is %NULL, the default allocator of the pool will use the values in @param + * to perform its allocation. When @param is %NULL, the pool will use the + * provided @allocator with its default #GstAllocationParams. * * A call to gst_buffer_pool_set_config() can update the allocator and params * with the values that it is able to do. Some pools are, for example, not able @@ -832,8 +895,8 @@ gst_buffer_pool_config_add_option (GstStructure * config, const gchar * option) * gst_buffer_pool_config_n_options: * @config: a #GstBufferPool configuration * - * Retrieve the number of values currently stored in the - * options array of the @config structure. + * Retrieve the number of values currently stored in the options array of the + * @config structure. * * Returns: the options array size as a #guint. */ @@ -857,8 +920,8 @@ gst_buffer_pool_config_n_options (GstStructure * config) * @config: a #GstBufferPool configuration * @index: position in the option array to read * - * Parse an available @config and get the option - * at @index of the options API array. + * Parse an available @config and get the option at @index of the options API + * array. * * Returns: a #gchar of the option at @index. */ @@ -886,9 +949,9 @@ gst_buffer_pool_config_get_option (GstStructure * config, guint index) * @config: a #GstBufferPool configuration * @option: an option * - * Check if @config contains @option + * Check if @config contains @option. * - * Returns: TRUE if the options array contains @option. + * Returns: %TRUE if the options array contains @option. */ gboolean gst_buffer_pool_config_has_option (GstStructure * config, const gchar * option) @@ -945,7 +1008,9 @@ gst_buffer_pool_config_get_params (GstStructure * config, GstCaps ** caps, * @allocator: (transfer none): a #GstAllocator * @params: #GstAllocationParams * - * Get the allocator and params from @config. + * Get the @allocator and @params from @config. + * + * Returns: %TRUE, if the values are set. */ gboolean gst_buffer_pool_config_get_allocator (GstStructure * config, @@ -970,6 +1035,44 @@ gst_buffer_pool_config_get_allocator (GstStructure * config, return TRUE; } +/** + * gst_buffer_pool_config_validate_params: + * @config: (transfer none): a #GstBufferPool configuration + * @caps: (transfer none): the excepted caps of buffers + * @size: the expected size of each buffer, not including prefix and padding + * @min_buffers: the expected minimum amount of buffers to allocate. + * @max_buffers: the expect maximum amount of buffers to allocate or 0 for unlimited. + * + * Validate that changes made to @config are still valid in the context of the + * expected parameters. This function is a helper that can be used to validate + * changes made by a pool to a config when gst_buffer_pool_set_config() + * returns %FALSE. This expects that @caps and @size haven't changed, and that + * @min_buffers aren't lower then what we initially expected. This does not check + * if options or allocator parameters. + * + * Since: 1.4 + * + * Returns: %TRUE, if the parameters are valid in this context. + */ +gboolean +gst_buffer_pool_config_validate_params (GstStructure * config, GstCaps * caps, + guint size, guint min_buffers, G_GNUC_UNUSED guint max_buffers) +{ + GstCaps *newcaps; + guint newsize, newmin; + gboolean ret = FALSE; + + g_return_val_if_fail (config != NULL, FALSE); + + gst_buffer_pool_config_get_params (config, &newcaps, &newsize, &newmin, NULL); + + if (gst_caps_is_equal (caps, newcaps) && (size == newsize) + && (newmin >= min_buffers)) + ret = TRUE; + + return ret; +} + static GstFlowReturn default_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer, GstBufferPoolAcquireParams * params) @@ -1007,9 +1110,12 @@ default_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer, break; } - /* now wait */ - GST_LOG_OBJECT (pool, "waiting for free buffers"); + /* now we release the control socket, we wait for a buffer release or + * flushing */ + gst_poll_read_control (pool->priv->poll); + GST_LOG_OBJECT (pool, "waiting for free buffers or flushing"); gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE); + gst_poll_write_control (pool->priv->poll); } return result; @@ -1030,9 +1136,9 @@ dec_outstanding (GstBufferPool * pool) if (GST_BUFFER_POOL_IS_FLUSHING (pool)) { /* take the lock so that set_active is not run concurrently */ GST_BUFFER_POOL_LOCK (pool); - /* recheck the flushing state in the lock, the pool could have been - * set to active again */ - if (GST_BUFFER_POOL_IS_FLUSHING (pool)) + /* now that we have the lock, check if we have been de-activated with + * outstanding buffers */ + if (!pool->priv->active) do_stop (pool); GST_BUFFER_POOL_UNLOCK (pool); @@ -1053,7 +1159,7 @@ remove_meta_unpooled (GstBuffer * buffer, GstMeta ** meta, gpointer user_data) static void default_reset_buffer (GstBufferPool * pool, GstBuffer * buffer) { - GST_BUFFER_FLAGS (buffer) = 0; + GST_BUFFER_FLAGS (buffer) &= GST_BUFFER_FLAG_TAG_MEMORY; GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE; GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE; @@ -1074,9 +1180,10 @@ default_reset_buffer (GstBufferPool * pool, GstBuffer * buffer) * Acquire a buffer from @pool. @buffer should point to a memory location that * can hold a pointer to the new buffer. * - * @params can be NULL or contain optional parameters to influence the allocation. + * @params can be %NULL or contain optional parameters to influence the + * allocation. * - * Returns: a #GstFlowReturn such as GST_FLOW_FLUSHING when the pool is + * Returns: a #GstFlowReturn such as %GST_FLOW_FLUSHING when the pool is * inactive. */ GstFlowReturn @@ -1114,10 +1221,33 @@ gst_buffer_pool_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer, static void default_release_buffer (GstBufferPool * pool, GstBuffer * buffer) { + GST_LOG_OBJECT (pool, "released buffer %p %d", buffer, + GST_MINI_OBJECT_FLAGS (buffer)); + + /* memory should be untouched */ + if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY)) + goto discard; + + /* size should have been reset. This is not a catch all, pool with + * size requirement per memory should do their own check. */ + if (gst_buffer_get_size (buffer) != pool->priv->size) + goto discard; + + /* all memory should be exclusive to this buffer (and thus be writable) */ + if (!gst_buffer_is_all_memory_writable (buffer)) + goto discard; + /* keep it around in our queue */ - GST_LOG_OBJECT (pool, "released buffer %p", buffer); gst_atomic_queue_push (pool->priv->queue, buffer); gst_poll_write_control (pool->priv->poll); + + return; + +discard: + { + do_free_buffer (pool, buffer); + return; + } } /** @@ -1158,3 +1288,37 @@ gst_buffer_pool_release_buffer (GstBufferPool * pool, GstBuffer * buffer) /* decrease the refcount that the buffer had to us */ gst_object_unref (pool); } + +/** + * gst_buffer_pool_set_flushing: + * @pool: a #GstBufferPool + * @flushing: whether to start or stop flushing + * + * Enabled or disable the flushing state of a @pool without freeing or + * allocating buffers. + * + * Since: 1.4 + */ +void +gst_buffer_pool_set_flushing (GstBufferPool * pool, gboolean flushing) +{ + GstBufferPoolPrivate *priv; + + g_return_if_fail (GST_IS_BUFFER_POOL (pool)); + + GST_LOG_OBJECT (pool, "flushing %d", flushing); + + priv = pool->priv; + + GST_BUFFER_POOL_LOCK (pool); + + if (!priv->active) { + GST_WARNING_OBJECT (pool, "can't change flushing state of inactive pool"); + goto done; + } + + do_set_flushing (pool, flushing); + +done: + GST_BUFFER_POOL_UNLOCK (pool); +} diff --git a/gst/gstbufferpool.h b/gst/gstbufferpool.h index 9806a6d..5427cb1 100644 --- a/gst/gstbufferpool.h +++ b/gst/gstbufferpool.h @@ -98,7 +98,6 @@ struct _GstBufferPoolAcquireParams { /** * GstBufferPool: - * @object: the parent structure * * The structure of a #GstBufferPool. Use the associated macros to access the public * variables. @@ -133,22 +132,29 @@ struct _GstBufferPool { * buffers from the configured memory allocator and with the configured * parameters. All metadata that is present on the allocated buffer will * be marked as #GST_META_FLAG_POOLED and #GST_META_FLAG_LOCKED and will - * not be removed from the buffer in @reset_buffer. + * not be removed from the buffer in @reset_buffer. The buffer should + * have the GST_BUFFER_FLAG_TAG_MEMORY cleared. * @reset_buffer: reset the buffer to its state when it was freshly allocated. * The default implementation will clear the flags, timestamps and * will remove the metadata without the #GST_META_FLAG_POOLED flag (even - * the metadata with #GST_META_FLAG_LOCKED). + * the metadata with #GST_META_FLAG_LOCKED). If the + * #GST_BUFFER_FLAG_TAG_MEMORY was set, this function can also try to + * restore the memory and clear the #GST_BUFFER_FLAG_TAG_MEMORY again. * @release_buffer: release a buffer back in the pool. The default * implementation will put the buffer back in the queue and notify any - * blocking acquire_buffer calls. + * blocking acquire_buffer calls when the #GST_BUFFER_FLAG_TAG_MEMORY + * is not set on the buffer. If #GST_BUFFER_FLAG_TAG_MEMORY is set, the + * buffer will be freed with @free_buffer. * @free_buffer: free a buffer. The default implementation unrefs the buffer. + * @flush_start: enter the flushing state. Since: 1.4 + * @flush_stop: leave the flushign state. Since: 1.4 * * The GstBufferPool class. */ struct _GstBufferPoolClass { GstObjectClass object_class; - /* vmethods */ + /*< public >*/ const gchar ** (*get_options) (GstBufferPool *pool); gboolean (*set_config) (GstBufferPool *pool, GstStructure *config); @@ -162,9 +168,11 @@ struct _GstBufferPoolClass { void (*reset_buffer) (GstBufferPool *pool, GstBuffer *buffer); void (*release_buffer) (GstBufferPool *pool, GstBuffer *buffer); void (*free_buffer) (GstBufferPool *pool, GstBuffer *buffer); + void (*flush_start) (GstBufferPool *pool); + void (*flush_stop) (GstBufferPool *pool); /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; + gpointer _gst_reserved[GST_PADDING - 2]; }; GType gst_buffer_pool_get_type (void); @@ -182,6 +190,8 @@ GstStructure * gst_buffer_pool_get_config (GstBufferPool *pool); const gchar ** gst_buffer_pool_get_options (GstBufferPool *pool); gboolean gst_buffer_pool_has_option (GstBufferPool *pool, const gchar *option); +void gst_buffer_pool_set_flushing (GstBufferPool *pool, gboolean flushing); + /* helpers for configuring the config structure */ void gst_buffer_pool_config_set_params (GstStructure *config, GstCaps *caps, guint size, guint min_buffers, guint max_buffers); @@ -197,6 +207,8 @@ guint gst_buffer_pool_config_n_options (GstStructure *config); void gst_buffer_pool_config_add_option (GstStructure *config, const gchar *option); const gchar * gst_buffer_pool_config_get_option (GstStructure *config, guint index); gboolean gst_buffer_pool_config_has_option (GstStructure *config, const gchar *option); +gboolean gst_buffer_pool_config_validate_params (GstStructure *config, GstCaps *caps, + guint size, guint min_buffers, guint max_buffers); /* buffer management */ GstFlowReturn gst_buffer_pool_acquire_buffer (GstBufferPool *pool, GstBuffer **buffer, diff --git a/gst/gstbus.c b/gst/gstbus.c index b5343ab..69cf6b9 100644 --- a/gst/gstbus.c +++ b/gst/gstbus.c @@ -63,8 +63,6 @@ * * Note that a #GstPipeline will set its bus into flushing state when changing * from READY to NULL state. - * - * Last reviewed on 2012-03-28 (0.11.3) */ #include "gst_private.h" @@ -293,7 +291,7 @@ gst_bus_new (void) * Post a message on the given bus. Ownership of the message * is taken by the bus. * - * Returns: TRUE if the message could be posted, FALSE if the bus is flushing. + * Returns: %TRUE if the message could be posted, %FALSE if the bus is flushing. * * MT safe. */ @@ -404,7 +402,7 @@ is_flushing: * Check if there are pending messages on the bus that * should be handled. * - * Returns: TRUE if there are messages on the bus to be handled, FALSE + * Returns: %TRUE if there are messages on the bus to be handled, %FALSE * otherwise. * * MT safe. @@ -429,7 +427,7 @@ gst_bus_have_pending (GstBus * bus) * * If @flushing, flush out and unref any messages queued in the bus. Releases * references to the message origin objects. Will flush future messages until - * gst_bus_set_flushing() sets @flushing to #FALSE. + * gst_bus_set_flushing() sets @flushing to %FALSE. * * MT safe. */ @@ -470,7 +468,7 @@ gst_bus_set_flushing (GstBus * bus, gboolean flushing) * matching message was posted on the bus. * * Returns: (transfer full): a #GstMessage matching the filter in @types, - * or NULL if no matching message was found on the bus until the timeout + * or %NULL if no matching message was found on the bus until the timeout * expired. The message is taken from the bus and needs to be unreffed * with gst_message_unref() after usage. * @@ -505,13 +503,18 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout, message, GST_MESSAGE_TYPE_NAME (message), GST_MESSAGE_SRC_NAME (message), (guint) types); if ((GST_MESSAGE_TYPE (message) & types) != 0) { - /* exit the loop, we have a message */ - goto beach; - } else { - GST_DEBUG_OBJECT (bus, "discarding message, does not match mask"); - gst_message_unref (message); - message = NULL; + /* Extra check to ensure extended types don't get matched unless + * asked for */ + if ((GST_MESSAGE_TYPE_IS_EXTENDED (message) == FALSE) + || (types & GST_MESSAGE_EXTENDED)) { + /* exit the loop, we have a message */ + goto beach; + } } + + GST_DEBUG_OBJECT (bus, "discarding message, does not match mask"); + gst_message_unref (message); + message = NULL; } /* no need to wait, exit loop */ @@ -566,7 +569,7 @@ beach: * posted on the bus. * * Returns: (transfer full): the #GstMessage that is on the bus after the - * specified timeout or NULL if the bus is empty after the timeout expired. + * specified timeout or %NULL if the bus is empty after the timeout expired. * The message is taken from the bus and needs to be unreffed with * gst_message_unref() after usage. * @@ -588,10 +591,11 @@ gst_bus_timed_pop (GstBus * bus, GstClockTime timeout) * Get a message matching @type from the bus. Will discard all messages on * the bus that do not match @type and that have been posted before the first * message that does match @type. If there is no message matching @type on - * the bus, all messages will be discarded. + * the bus, all messages will be discarded. It is not possible to use message + * enums beyond #GST_MESSAGE_EXTENDED in the @events mask. * * Returns: (transfer full): the next #GstMessage matching @type that is on - * the bus, or NULL if the bus is empty or there is no message matching + * the bus, or %NULL if the bus is empty or there is no message matching * @type. The message is taken from the bus and needs to be unreffed with * gst_message_unref() after usage. * @@ -612,7 +616,7 @@ gst_bus_pop_filtered (GstBus * bus, GstMessageType types) * * Get a message from the bus. * - * Returns: (transfer full): the #GstMessage that is on the bus, or NULL if the + * Returns: (transfer full): the #GstMessage that is on the bus, or %NULL if the * bus is empty. The message is taken from the bus and needs to be unreffed * with gst_message_unref() after usage. * @@ -634,7 +638,7 @@ gst_bus_pop (GstBus * bus) * on the bus' message queue. A reference is returned, and needs to be unreffed * by the caller. * - * Returns: (transfer full): the #GstMessage that is on the bus, or NULL if the + * Returns: (transfer full): the #GstMessage that is on the bus, or %NULL if the * bus is empty. * * MT safe. @@ -671,7 +675,7 @@ gst_bus_peek (GstBus * bus) * should handle messages asynchronously using the gst_bus watch and poll * functions. * - * You cannot replace an existing sync_handler. You can pass NULL to this + * You cannot replace an existing sync_handler. You can pass %NULL to this * function, which will clear the existing handler. */ void @@ -892,7 +896,7 @@ gst_bus_add_watch_full_unlocked (GstBus * bus, gint priority, * When @func is called, the message belongs to the caller; if you want to * keep a copy of it, call gst_message_ref() before leaving @func. * - * The watch can be removed using g_source_remove() or by returning FALSE + * The watch can be removed using g_source_remove() or by returning %FALSE * from @func. * * MT safe. @@ -931,7 +935,7 @@ gst_bus_add_watch_full (GstBus * bus, gint priority, * There can only be a single bus watch per bus, you must remove it before you * can set a new one. * - * The watch can be removed using g_source_remove() or by returning FALSE + * The watch can be removed using g_source_remove() or by returning %FALSE * from @func. * * Returns: The event source id. @@ -1012,7 +1016,7 @@ poll_destroy_timeout (GstBusPollData * poll_data) * gst_bus_poll: * @bus: a #GstBus * @events: a mask of #GstMessageType, representing the set of message types to - * poll for. + * poll for (note special handling of extended message types below) * @timeout: the poll timeout, as a #GstClockTime, or #GST_CLOCK_TIME_NONE to poll * indefinitely. * @@ -1021,6 +1025,8 @@ poll_destroy_timeout (GstBusPollData * poll_data) * @timeout is negative, this function will block indefinitely. * * All messages not in @events will be popped off the bus and will be ignored. + * It is not possible to use message enums beyond #GST_MESSAGE_EXTENDED in the + * @events mask * * Because poll is implemented using the "message" signal enabled by * gst_bus_add_signal_watch(), calling gst_bus_poll() will cause the "message" @@ -1048,7 +1054,7 @@ poll_destroy_timeout (GstBusPollData * poll_data) * better handled by setting up an asynchronous bus watch and doing things * from there. * - * Returns: (transfer full): the message that was received, or NULL if the + * Returns: (transfer full): the message that was received, or %NULL if the * poll timed out. The message is taken from the bus and needs to be * unreffed with gst_message_unref() after usage. */ @@ -1107,7 +1113,7 @@ gst_bus_poll (GstBus * bus, GstMessageType events, GstClockTime timeout) * A helper #GstBusFunc that can be used to convert all asynchronous messages * into signals. * - * Returns: TRUE + * Returns: %TRUE */ gboolean gst_bus_async_signal_func (GstBus * bus, GstMessage * message, gpointer data) diff --git a/gst/gstbus.h b/gst/gstbus.h index 5821770..92d2160 100644 --- a/gst/gstbus.h +++ b/gst/gstbus.h @@ -99,7 +99,7 @@ typedef GstBusSyncReply (*GstBusSyncHandler) (GstBus * bus, GstMessage * mess * function so it should not be freed in the function. * * Note that this function is used as a GSourceFunc which means that returning - * FALSE will remove the GSource from the mainloop. + * %FALSE will remove the GSource from the mainloop. * * Returns: %FALSE if the event source should be removed. */ diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 7e10a2a..4525ead 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -34,20 +34,15 @@ * handle or produce at runtime. * * A #GstCaps can be constructed with the following code fragment: - * - * <example> - * <title>Creating caps</title> - * <programlisting> - * GstCaps *caps; - * caps = gst_caps_new_simple ("video/x-raw", - * "format", G_TYPE_STRING, "I420", - * "framerate", GST_TYPE_FRACTION, 25, 1, - * "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, - * "width", G_TYPE_INT, 320, - * "height", G_TYPE_INT, 240, - * NULL); - * </programlisting> - * </example> + * |[ + * GstCaps *caps = gst_caps_new_simple ("video/x-raw", + * "format", G_TYPE_STRING, "I420", + * "framerate", GST_TYPE_FRACTION, 25, 1, + * "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, + * "width", G_TYPE_INT, 320, + * "height", G_TYPE_INT, 240, + * NULL); + * ]| * * A #GstCaps is fixed when it has no properties with ranges or lists. Use * gst_caps_is_fixed() to test for fixed caps. Fixed caps can be used in a @@ -56,7 +51,11 @@ * Various methods exist to work with the media types such as subtracting * or intersecting. * - * Last reviewed on 2011-03-28 (0.11.3) + * Be aware that the current #GstCaps / #GstStructure serialization into string + * has limited support for nested #GstCaps / #GstStructure fields. It can only + * support one level of nesting. Using more levels will lead to unexpected + * behavior when using serialization features, such as gst_caps_to_string() or + * gst_value_serialize() and their counterparts. */ #ifdef HAVE_CONFIG_H @@ -93,7 +92,7 @@ typedef struct _GstCapsImpl /* same as gst_caps_is_any () */ #define CAPS_IS_ANY(caps) \ - (GST_CAPS_FLAGS(caps) & GST_CAPS_FLAG_ANY) + (!!(GST_CAPS_FLAGS(caps) & GST_CAPS_FLAG_ANY)) /* same as gst_caps_is_empty () */ #define CAPS_IS_EMPTY(caps) \ @@ -108,8 +107,10 @@ typedef struct _GstCapsImpl * length check */ #define gst_caps_get_structure_unchecked(caps, index) \ (g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, (index)).structure) +#define gst_caps_get_features_storage_unchecked(caps, index) \ + (&g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, (index)).features) #define gst_caps_get_features_unchecked(caps, index) \ - (g_array_index (GST_CAPS_ARRAY (caps), GstCapsArrayElement, (index)).features) + (g_atomic_pointer_get (gst_caps_get_features_storage_unchecked (caps, index))) /* quick way to append a structure without checking the args */ #define gst_caps_append_structure_unchecked(caps, s, f) G_STMT_START{\ GstCapsArrayElement __e={s, f}; \ @@ -326,7 +327,7 @@ gst_caps_new_simple (const char *media_type, const char *fieldname, ...) * @...: additional structures to add * * Creates a new #GstCaps and adds all the structures listed as - * arguments. The list must be NULL-terminated. The structures + * arguments. The list must be %NULL-terminated. The structures * are not copied; the returned #GstCaps owns the structures. * * Returns: (transfer full): the new #GstCaps @@ -350,7 +351,7 @@ gst_caps_new_full (GstStructure * struct1, ...) * @var_args: additional structures to add * * Creates a new #GstCaps and adds all the structures listed as - * arguments. The list must be NULL-terminated. The structures + * arguments. The list must be %NULL-terminated. The structures * are not copied; the returned #GstCaps owns the structures. * * Returns: (transfer full): the new #GstCaps @@ -644,7 +645,7 @@ gst_caps_append_structure_full (GstCaps * caps, GstStructure * structure, * @caps: the #GstCaps to remove from * @idx: Index of the structure to remove * - * removes the stucture with the given index from the list of structures + * removes the structure with the given index from the list of structures * contained in @caps. */ void @@ -850,8 +851,25 @@ gst_caps_get_features (const GstCaps * caps, guint index) g_return_val_if_fail (index < GST_CAPS_LEN (caps), NULL); features = gst_caps_get_features_unchecked (caps, index); - if (!features) - features = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; + if (!features) { + GstCapsFeatures **storage; + + /* We have to do some atomic pointer magic here as the caps + * might not be writable and someone else calls this function + * at the very same time */ + features = gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY); + gst_caps_features_set_parent_refcount (features, &GST_CAPS_REFCOUNT (caps)); + + storage = gst_caps_get_features_storage_unchecked (caps, index); + if (!g_atomic_pointer_compare_and_exchange (storage, NULL, features)) { + /* Someone did the same we just tried in the meantime */ + gst_caps_features_set_parent_refcount (features, NULL); + gst_caps_features_free (features); + + features = gst_caps_get_features_unchecked (caps, index); + g_assert (features != NULL); + } + } return features; } @@ -860,7 +878,7 @@ gst_caps_get_features (const GstCaps * caps, guint index) * gst_caps_set_features: * @caps: a #GstCaps * @index: the index of the structure - * @features: (allow-none) (transfer full): the #GstFeatures to set + * @features: (allow-none) (transfer full): the #GstCapsFeatures to set * * Sets the #GstCapsFeatures @features for the structure at @index. * @@ -875,9 +893,10 @@ gst_caps_set_features (GstCaps * caps, guint index, GstCapsFeatures * features) g_return_if_fail (index <= gst_caps_get_size (caps)); g_return_if_fail (IS_WRITABLE (caps)); - storage = &gst_caps_get_features_unchecked (caps, index); - old = *storage; - *storage = features; + storage = gst_caps_get_features_storage_unchecked (caps, index); + /* Not much problem here as caps are writable */ + old = g_atomic_pointer_get (storage); + g_atomic_pointer_set (storage, features); if (features) gst_caps_features_set_parent_refcount (features, &GST_CAPS_REFCOUNT (caps)); @@ -980,7 +999,7 @@ gst_caps_set_value (GstCaps * caps, const char *field, const GValue * value) * @varargs: additional parameters * * Sets fields in a #GstCaps. The arguments must be passed in the same - * manner as gst_structure_set(), and be NULL-terminated. + * manner as gst_structure_set(), and be %NULL-terminated. */ void gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs) @@ -1017,7 +1036,7 @@ gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs) * @...: additional parameters * * Sets fields in a #GstCaps. The arguments must be passed in the same - * manner as gst_structure_set(), and be NULL-terminated. + * manner as gst_structure_set(), and be %NULL-terminated. */ void gst_caps_set_simple (GstCaps * caps, const char *field, ...) @@ -1040,7 +1059,7 @@ gst_caps_set_simple (GstCaps * caps, const char *field, ...) * * Determines if @caps represents any media format. * - * Returns: TRUE if @caps represents any format. + * Returns: %TRUE if @caps represents any format. */ gboolean gst_caps_is_any (const GstCaps * caps) @@ -1056,7 +1075,7 @@ gst_caps_is_any (const GstCaps * caps) * * Determines if @caps represents no media formats. * - * Returns: TRUE if @caps represents no formats. + * Returns: %TRUE if @caps represents no formats. */ gboolean gst_caps_is_empty (const GstCaps * caps) @@ -1084,7 +1103,7 @@ gst_caps_is_fixed_foreach (GQuark field_id, const GValue * value, * one structure, and each field in the structure describes a fixed type. * Examples of non-fixed types are GST_TYPE_INT_RANGE and GST_TYPE_LIST. * - * Returns: TRUE if @caps is fixed + * Returns: %TRUE if @caps is fixed */ gboolean gst_caps_is_fixed (const GstCaps * caps) @@ -1097,7 +1116,7 @@ gst_caps_is_fixed (const GstCaps * caps) if (GST_CAPS_LEN (caps) != 1) return FALSE; - features = gst_caps_get_features (caps, 0); + features = gst_caps_get_features_unchecked (caps, 0); if (features && gst_caps_features_is_any (features)) return FALSE; @@ -1114,7 +1133,7 @@ gst_caps_is_fixed (const GstCaps * caps) * Tests if two #GstCaps are equal. This function only works on fixed * #GstCaps. * - * Returns: TRUE if the arguments represent the same format + * Returns: %TRUE if the arguments represent the same format */ gboolean gst_caps_is_equal_fixed (const GstCaps * caps1, const GstCaps * caps2) @@ -1147,7 +1166,7 @@ gst_caps_is_equal_fixed (const GstCaps * caps1, const GstCaps * caps2) * every media format that is in the first is also contained in the * second. That is, @caps1 is a subset of @caps2. * - * Returns: TRUE if @caps1 is a subset of @caps2. + * Returns: %TRUE if @caps1 is a subset of @caps2. */ gboolean gst_caps_is_always_compatible (const GstCaps * caps1, const GstCaps * caps2) @@ -1303,7 +1322,7 @@ gst_caps_is_subset_structure_full (const GstCaps * caps, * * Checks if the given caps represent the same set of caps. * - * Returns: TRUE if both caps are equal. + * Returns: %TRUE if both caps are equal. */ gboolean gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2) @@ -1327,7 +1346,7 @@ gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2) * * Checks if the given caps are exactly the same set of caps. * - * Returns: TRUE if both caps are strictly equal. + * Returns: %TRUE if both caps are strictly equal. */ gboolean gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2) @@ -2105,7 +2124,7 @@ gst_caps_fixate (GstCaps * caps) gst_structure_fixate (s); /* Set features to sysmem if they're still ANY */ - f = gst_caps_get_features (caps, 0); + f = gst_caps_get_features_unchecked (caps, 0); if (f && gst_caps_features_is_any (f)) { f = gst_caps_features_new_empty (); gst_caps_set_features (caps, 0, f); @@ -2129,6 +2148,9 @@ gst_caps_fixate (GstCaps * caps) * ]| * This prints the caps in human readable form. * + * The current implementation of serialization will lead to unexpected results + * when there are nested #GstCaps / #GstStructure deeper than one level. + * * Returns: (transfer full): a newly allocated string representing @caps. */ gchar * @@ -2277,12 +2299,15 @@ gst_caps_from_string_inplace (GstCaps * caps, const gchar * string) if (!priv_gst_structure_parse_fields (s, &s, structure)) { gst_structure_free (structure); + if (features) + gst_caps_features_free (features); g_free (copy); return FALSE; } append: gst_caps_append_structure_unchecked (caps, structure, features); + features = NULL; if (*s == '\0') break; } while (TRUE); @@ -2298,6 +2323,9 @@ gst_caps_from_string_inplace (GstCaps * caps, const gchar * string) * * Converts @caps from a string representation. * + * The current implementation of serialization will lead to unexpected results + * when there are nested #GstCaps / #GstStructure deeper than one level. + * * Returns: (transfer full): a newly allocated #GstCaps */ GstCaps * diff --git a/gst/gstcaps.h b/gst/gstcaps.h index 8df2499..e29da34 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -298,9 +298,9 @@ gst_caps_copy (const GstCaps * caps) * in some cases), and the reference counts are updated appropriately (the old * caps is unreffed, the new is reffed). * - * Either @ncaps or the #GstCaps pointed to by @ocaps may be NULL. + * Either @ncaps or the #GstCaps pointed to by @ocaps may be %NULL. * - * Returns: TRUE if @new_caps was different from @old_caps + * Returns: %TRUE if @new_caps was different from @old_caps */ #ifdef _FOOL_GTK_DOC_ G_INLINE_FUNC gboolean gst_caps_replace (GstCaps **old_caps, GstCaps *new_caps); @@ -323,7 +323,7 @@ gst_caps_replace (GstCaps **old_caps, GstCaps *new_caps) * function is similar to gst_caps_replace() except that it takes ownership * of @new_caps. * - * Returns: TRUE if @new_caps was different from @old_caps + * Returns: %TRUE if @new_caps was different from @old_caps */ #ifdef _FOOL_GTK_DOC_ G_INLINE_FUNC gboolean gst_caps_take (GstCaps **old_caps, GstCaps *new_caps); diff --git a/gst/gstcapsfeatures.c b/gst/gstcapsfeatures.c index b64240e..e1e8f90 100644 --- a/gst/gstcapsfeatures.c +++ b/gst/gstcapsfeatures.c @@ -66,6 +66,7 @@ struct _GstCapsFeatures }; GType _gst_caps_features_type = 0; +static gint static_caps_features_parent_refcount = G_MAXINT; GstCapsFeatures *_gst_caps_features_any = NULL; GstCapsFeatures *_gst_caps_features_memory_system_memory = NULL; static GQuark _gst_caps_feature_memory_system_memory = 0; @@ -95,8 +96,13 @@ _priv_gst_caps_features_initialize (void) gst_caps_features_transform_to_string); _gst_caps_features_any = gst_caps_features_new_any (); + gst_caps_features_set_parent_refcount (_gst_caps_features_any, + &static_caps_features_parent_refcount); _gst_caps_features_memory_system_memory = gst_caps_features_new_id (_gst_caps_feature_memory_system_memory, 0); + gst_caps_features_set_parent_refcount + (_gst_caps_features_memory_system_memory, + &static_caps_features_parent_refcount); } gboolean @@ -197,7 +203,7 @@ gst_caps_features_new_any (void) * @...: additional features * * Creates a new #GstCapsFeatures with the given features. - * The last argument must be NULL. + * The last argument must be %NULL. * * Free-function: gst_caps_features_free * @@ -411,7 +417,7 @@ gst_caps_features_free (GstCapsFeatures * features) * |[ * GST_LOG ("features is %" GST_PTR_FORMAT, features); * ]| - * This prints the features in human readble form. + * This prints the features in human readable form. * * Free-function: g_free * @@ -465,7 +471,7 @@ priv_gst_caps_features_append_to_gstring (const GstCapsFeatures * features, * * Free-function: gst_caps_features_free * - * Returns: (transfer full): a new #GstCapsFeatures or NULL when the string could + * Returns: (transfer full): a new #GstCapsFeatures or %NULL when the string could * not be parsed. Free with gst_caps_features_free() after use. * * Since: 1.2 diff --git a/gst/gstcapsfeatures.h b/gst/gstcapsfeatures.h index 62d9e3c..441e1a1 100644 --- a/gst/gstcapsfeatures.h +++ b/gst/gstcapsfeatures.h @@ -28,7 +28,9 @@ G_BEGIN_DECLS typedef struct _GstCapsFeatures GstCapsFeatures; -#define GST_TYPE_CAPS_FEATURES (gst_caps_features_get_type ()) +GST_EXPORT GType _gst_caps_features_type; + +#define GST_TYPE_CAPS_FEATURES (_gst_caps_features_type) #define GST_IS_CAPS_FEATURES(object) (gst_is_caps_features(object)) #define GST_CAPS_FEATURES_CAST(object) ((GstCapsFeatures *)(object)) #define GST_CAPS_FEATURES(object) (GST_CAPS_FEATURES_CAST(object)) diff --git a/gst/gstchildproxy.c b/gst/gstchildproxy.c index 8ce03c9..a83356a 100644 --- a/gst/gstchildproxy.c +++ b/gst/gstchildproxy.c @@ -100,7 +100,7 @@ gst_child_proxy_default_get_child_by_name (GstChildProxy * parent, /** * gst_child_proxy_get_child_by_name: * @parent: the parent object to get the child from - * @name: the childs name + * @name: the child's name * * Looks up a child element by the given name. * @@ -125,7 +125,7 @@ gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name) /** * gst_child_proxy_get_child_by_index: * @parent: the parent object to get the child from - * @index: the childs position in the child list + * @index: the child's position in the child list * * Fetches a child by its number. * @@ -174,7 +174,7 @@ gst_child_proxy_get_children_count (GstChildProxy * parent) * * MT safe. * - * Returns: TRUE if @target and @pspec could be found. FALSE otherwise. In that + * Returns: %TRUE if @target and @pspec could be found. %FALSE otherwise. In that * case the values for @pspec and @target are not modified. Unref @target after * usage. For plain GObjects @target is the same as @object. */ @@ -274,7 +274,7 @@ not_found: * gst_child_proxy_get_valist: * @object: the object to query * @first_property_name: name of the first property to get - * @var_args: return location for the first property, followed optionally by more name/return location pairs, followed by NULL + * @var_args: return location for the first property, followed optionally by more name/return location pairs, followed by %NULL * * Gets properties of the parent object and its children. */ @@ -328,7 +328,7 @@ cant_copy: * gst_child_proxy_get: * @object: the parent object * @first_property_name: name of the first property to get - * @...: return location for the first property, followed optionally by more name/return location pairs, followed by NULL + * @...: return location for the first property, followed optionally by more name/return location pairs, followed by %NULL * * Gets properties of the parent object and its children. */ @@ -383,7 +383,7 @@ not_found: * gst_child_proxy_set_valist: * @object: the parent object * @first_property_name: name of the first property to set - * @var_args: value for the first property, followed optionally by more name/value pairs, followed by NULL + * @var_args: value for the first property, followed optionally by more name/value pairs, followed by %NULL * * Sets properties of the parent object and its children. */ @@ -440,7 +440,7 @@ cant_copy: * gst_child_proxy_set: * @object: the parent object * @first_property_name: name of the first property to set - * @...: value for the first property, followed optionally by more name/value pairs, followed by NULL + * @...: value for the first property, followed optionally by more name/value pairs, followed by %NULL * * Sets properties of the parent object and its children. */ diff --git a/gst/gstclock.c b/gst/gstclock.c index 4666b84..9f5b6fd 100644 --- a/gst/gstclock.c +++ b/gst/gstclock.c @@ -98,8 +98,6 @@ * clock and run the calibration functions. #GstClock:window-size defines the * number of samples to use when calibrating and #GstClock:window-threshold * defines the minimum number of samples before the calibration is performed. - * - * Last reviewed on 2012-03-28 (0.11.3) */ diff --git a/gst/gstconfig.h.in b/gst/gstconfig.h.in index e6ea08d..8460281 100644 --- a/gst/gstconfig.h.in +++ b/gst/gstconfig.h.in @@ -33,7 +33,7 @@ * If a subsystem is disabled, most of this changes are done in an API * compatible way, so you don't need to adapt your code in most cases. It is * never done in an ABI compatible way though. So if you want to disable a - * suybsystem, you have to rebuild all programs depending on GStreamer, too. + * subsystem, you have to rebuild all programs depending on GStreamer, too. * * If a subsystem is disabled in GStreamer, a value is defined in * <gst/gst.h>. You can check this if you do subsystem-specific stuff. @@ -81,14 +81,14 @@ /** * GST_DISABLE_PARSE: * - * Configures the inclusion of the gst-lauch parser + * Configures the inclusion of the gst-launch parser */ @GST_DISABLE_PARSE_DEFINE@ /** * GST_DISABLE_TRACE: * - * Configures the inclusion of a resource tracing facillity + * Configures the inclusion of a resource tracing facility * (seems to be unused) */ @GST_DISABLE_TRACE_DEFINE@ diff --git a/gst/gstcontext.c b/gst/gstcontext.c index 75a1c3f..b535574 100644 --- a/gst/gstcontext.c +++ b/gst/gstcontext.c @@ -32,17 +32,17 @@ * * Applications can set a context on a complete pipeline by using * gst_element_set_context(), which will then be propagated to all - * child elements. Elements can handle these in GstElement::set_context() + * child elements. Elements can handle these in #GstElementClass.set_context() * and merge them with the context information they already have. * * When an element needs a context it will do the following actions in this * order until one step succeeds: - * 1) Check if the element already has a context - * 2) Query downstream with GST_QUERY_CONTEXT for the context - * 2) Query upstream with GST_QUERY_CONTEXT for the context - * 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with the required + * 1. Check if the element already has a context + * 2. Query downstream with GST_QUERY_CONTEXT for the context + * 3. Query upstream with GST_QUERY_CONTEXT for the context + * 4. Post a GST_MESSAGE_NEED_CONTEXT message on the bus with the required * context types and afterwards check if a usable context was set now - * 4) Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT message + * 5. Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT message * on the bus. * * Bins will catch GST_MESSAGE_NEED_CONTEXT messages and will set any previously @@ -68,7 +68,7 @@ struct _GstContext #define GST_CONTEXT_STRUCTURE(c) (((GstContext *)(c))->structure) -static GType _gst_context_type = 0; +GType _gst_context_type = 0; GST_DEFINE_MINI_OBJECT_TYPE (GstContext, gst_context); void @@ -141,6 +141,7 @@ gst_context_init (GstContext * context) /** * gst_context_new: + * @context_type: Context type * @persistent: Persistent context * * Create a new context. diff --git a/gst/gstcontext.h b/gst/gstcontext.h index 9dd0914..0883f0d 100644 --- a/gst/gstcontext.h +++ b/gst/gstcontext.h @@ -31,7 +31,9 @@ typedef struct _GstContext GstContext; #include <gst/gstminiobject.h> #include <gst/gststructure.h> -#define GST_TYPE_CONTEXT (gst_context_get_type()) +GST_EXPORT GType _gst_context_type; + +#define GST_TYPE_CONTEXT (_gst_context_type) #define GST_IS_CONTEXT(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_CONTEXT)) #define GST_CONTEXT_CAST(obj) ((GstContext*)(obj)) #define GST_CONTEXT(obj) (GST_CONTEXT_CAST(obj)) @@ -130,9 +132,9 @@ gst_context_copy (const GstContext * context) * in some cases), and the reference counts are updated appropriately (the old * context is unreffed, the new one is reffed). * - * Either @new_context or the #GstContext pointed to by @old_context may be NULL. + * Either @new_context or the #GstContext pointed to by @old_context may be %NULL. * - * Returns: TRUE if @new_context was different from @old_context + * Returns: %TRUE if @new_context was different from @old_context */ #ifdef _FOOL_GTK_DOC_ G_INLINE_FUNC gboolean gst_context_replace (GstContext **old_context, GstContext *new_context); diff --git a/gst/gstcontrolbinding.c b/gst/gstcontrolbinding.c index 458151a..4981c89 100644 --- a/gst/gstcontrolbinding.c +++ b/gst/gstcontrolbinding.c @@ -283,12 +283,12 @@ gst_control_binding_get_value (GstControlBinding * binding, } /** - * gst_control_binding_get_value_array: + * gst_control_binding_get_value_array: (skip) * @binding: the control binding * @timestamp: the time that should be processed * @interval: the time spacing between subsequent values * @n_values: the number of values - * @values: array to put control-values in + * @values: (array length=n_values): array to put control-values in * * Gets a number of values for the given controlled property starting at the * requested time. The array @values need to hold enough space for @n_values of @@ -347,7 +347,7 @@ gst_control_binding_get_value_array (GstControlBinding * binding, * @timestamp: the time that should be processed * @interval: the time spacing between subsequent values * @n_values: the number of values - * @values: array to put control-values in + * @values: (array length=n_values): array to put control-values in * * Gets a number of #GValues for the given controlled property starting at the * requested time. The array @values need to hold enough space for @n_values of diff --git a/gst/gstcontrolbinding.h b/gst/gstcontrolbinding.h index 170fce3..f870d34 100644 --- a/gst/gstcontrolbinding.h +++ b/gst/gstcontrolbinding.h @@ -75,6 +75,11 @@ struct _GstControlBinding { /** * GstControlBindingClass: * @parent_class: Parent class + * @sync_values: implementation for updating the target values + * @get_value: implementation to fetch a single control-value + * @get_value_array: implementation to fetch a series of control-values + * @get_g_value_array: implementation to fetch a series of control-values + * as g_values * * The class structure of #GstControlBinding. */ @@ -83,7 +88,7 @@ struct _GstControlBindingClass { GstObjectClass parent_class; - /* virtual methods */ + /*< public >*/ gboolean (* sync_values) (GstControlBinding *binding, GstObject *object, GstClockTime timestamp, GstClockTime last_sync); GValue * (* get_value) (GstControlBinding *binding, GstClockTime timestamp); gboolean (* get_value_array) (GstControlBinding *binding, GstClockTime timestamp,GstClockTime interval, guint n_values, gpointer values); diff --git a/gst/gstcontrolsource.c b/gst/gstcontrolsource.c index c7b134d..be4816d 100644 --- a/gst/gstcontrolsource.c +++ b/gst/gstcontrolsource.c @@ -25,8 +25,8 @@ * @short_description: base class for control source sources * * The #GstControlSource is a base class for control value sources that could - * be used by #GstController to get timestamp-value pairs. A control source - * essentially is a function over time, returning gloat values between 0.0 and 1.0. + * be used to get timestamp-value pairs. A control source essentially is a + * function over time, returning float values between 0.0 and 1.0. * * A #GstControlSource is used by first getting an instance of a specific * control-source, creating a binding for the control-source to the target property @@ -96,7 +96,7 @@ gst_control_source_constructor (GType type, guint n_construct_params, * * Gets the value for this #GstControlSource at a given timestamp. * - * Returns: FALSE if the value couldn't be returned, TRUE otherwise. + * Returns: %FALSE if the value couldn't be returned, %TRUE otherwise. */ gboolean gst_control_source_get_value (GstControlSource * self, GstClockTime timestamp, @@ -118,7 +118,7 @@ gst_control_source_get_value (GstControlSource * self, GstClockTime timestamp, * @timestamp: the first timestamp * @interval: the time steps * @n_values: the number of values to fetch - * @values: array to put control-values in + * @values: (array length=n_values): array to put control-values in * * Gets an array of values for for this #GstControlSource. Values that are * undefined contain NANs. diff --git a/gst/gstcontrolsource.h b/gst/gstcontrolsource.h index b0cd92a..655205b 100644 --- a/gst/gstcontrolsource.h +++ b/gst/gstcontrolsource.h @@ -113,7 +113,6 @@ struct _GstControlSource { /** * GstControlSourceClass: * @parent_class: Parent class - * @bind: Class method for binding the #GstControlSource to a specific GParamSpec * * The class structure of #GstControlSource. */ diff --git a/gst/gstdatetime.c b/gst/gstdatetime.c index 003b0e6..d21cca4 100644 --- a/gst/gstdatetime.c +++ b/gst/gstdatetime.c @@ -56,12 +56,18 @@ typedef enum struct _GstDateTime { + GstMiniObject mini_object; + GDateTime *datetime; GstDateTimeFields fields; - volatile gint ref_count; }; +GType _gst_date_time_type = 0; +GST_DEFINE_MINI_OBJECT_TYPE (GstDateTime, gst_date_time); + +static void gst_date_time_free (GstDateTime * datetime); + /** * gst_date_time_new_from_g_date_time: * @dt: (transfer full): the #GDateTime. The new #GstDateTime takes ownership. @@ -70,7 +76,7 @@ struct _GstDateTime * * Free-function: gst_date_time_unref * - * Returns: (transfer full): a newly created #GstDateTime, or NULL on error + * Returns: (transfer full): a newly created #GstDateTime, or %NULL on error */ GstDateTime * gst_date_time_new_from_g_date_time (GDateTime * dt) @@ -81,9 +87,12 @@ gst_date_time_new_from_g_date_time (GDateTime * dt) return NULL; gst_dt = g_slice_new (GstDateTime); + + gst_mini_object_init (GST_MINI_OBJECT_CAST (gst_dt), 0, GST_TYPE_DATE_TIME, + NULL, NULL, (GstMiniObjectFreeFunction) gst_date_time_free); + gst_dt->datetime = dt; gst_dt->fields = GST_DATE_TIME_FIELDS_YMD_HMS; - gst_dt->ref_count = 1; return gst_dt; } @@ -95,7 +104,7 @@ gst_date_time_new_from_g_date_time (GDateTime * dt) * * Free-function: g_date_time_unref * - * Returns: (transfer full): a newly created #GDateTime, or NULL on error + * Returns: (transfer full): a newly created #GDateTime, or %NULL on error */ GDateTime * gst_date_time_to_g_date_time (GstDateTime * datetime) @@ -112,8 +121,8 @@ gst_date_time_to_g_date_time (GstDateTime * datetime) * gst_date_time_has_year: * @datetime: a #GstDateTime * - * Returns: TRUE if @datetime<!-- -->'s year field is set (which should always - * be the case), otherwise FALSE + * Returns: %TRUE if @datetime<!-- -->'s year field is set (which should always + * be the case), otherwise %FALSE */ gboolean gst_date_time_has_year (const GstDateTime * datetime) @@ -127,7 +136,7 @@ gst_date_time_has_year (const GstDateTime * datetime) * gst_date_time_has_month: * @datetime: a #GstDateTime * - * Returns: TRUE if @datetime<!-- -->'s month field is set, otherwise FALSE + * Returns: %TRUE if @datetime<!-- -->'s month field is set, otherwise %FALSE */ gboolean gst_date_time_has_month (const GstDateTime * datetime) @@ -141,7 +150,7 @@ gst_date_time_has_month (const GstDateTime * datetime) * gst_date_time_has_day: * @datetime: a #GstDateTime * - * Returns: TRUE if @datetime<!-- -->'s day field is set, otherwise FALSE + * Returns: %TRUE if @datetime<!-- -->'s day field is set, otherwise %FALSE */ gboolean gst_date_time_has_day (const GstDateTime * datetime) @@ -155,8 +164,8 @@ gst_date_time_has_day (const GstDateTime * datetime) * gst_date_time_has_time: * @datetime: a #GstDateTime * - * Returns: TRUE if @datetime<!-- -->'s hour and minute fields are set, - * otherwise FALSE + * Returns: %TRUE if @datetime<!-- -->'s hour and minute fields are set, + * otherwise %FALSE */ gboolean gst_date_time_has_time (const GstDateTime * datetime) @@ -170,7 +179,7 @@ gst_date_time_has_time (const GstDateTime * datetime) * gst_date_time_has_second: * @datetime: a #GstDateTime * - * Returns: TRUE if @datetime<!-- -->'s second field is set, otherwise FALSE + * Returns: %TRUE if @datetime<!-- -->'s second field is set, otherwise %FALSE */ gboolean gst_date_time_has_second (const GstDateTime * datetime) @@ -587,7 +596,7 @@ __gst_date_time_compare (const GstDateTime * dt1, const GstDateTime * dt2) * * Note that @tzoffset is a float and was chosen so for being able to handle * some fractional timezones, while it still keeps the readability of - * represeting it in hours for most timezones. + * representing it in hours for most timezones. * * If value is -1 then all over value will be ignored. For example * if @month == -1, then #GstDateTime will created only for @year. If @@ -717,7 +726,7 @@ done: * 2012-06-23T23:30+0100, 2012-06-23T23:30:59Z, 2012-06-23T23:30:59+0100 * * Returns: a newly allocated string formatted according to ISO 8601 and - * only including the datetime fields that are valid, or NULL in case + * only including the datetime fields that are valid, or %NULL in case * there was an error. The string should be freed with g_free(). */ gchar * @@ -740,7 +749,7 @@ gst_date_time_to_iso8601_string (GstDateTime * datetime) * * Free-function: gst_date_time_unref * - * Returns: (transfer full): a newly created #GstDateTime, or NULL on error + * Returns: (transfer full): a newly created #GstDateTime, or %NULL on error */ GstDateTime * gst_date_time_new_from_iso8601_string (const gchar * string) @@ -868,7 +877,6 @@ ymd: return gst_date_time_new_ymd (year, month, day); } - static void gst_date_time_free (GstDateTime * datetime) { @@ -887,10 +895,7 @@ gst_date_time_free (GstDateTime * datetime) GstDateTime * gst_date_time_ref (GstDateTime * datetime) { - g_return_val_if_fail (datetime != NULL, NULL); - g_return_val_if_fail (datetime->ref_count > 0, NULL); - g_atomic_int_inc (&datetime->ref_count); - return datetime; + return (GstDateTime *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (datetime)); } /** @@ -903,9 +908,11 @@ gst_date_time_ref (GstDateTime * datetime) void gst_date_time_unref (GstDateTime * datetime) { - g_return_if_fail (datetime != NULL); - g_return_if_fail (datetime->ref_count > 0); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (datetime)); +} - if (g_atomic_int_dec_and_test (&datetime->ref_count)) - gst_date_time_free (datetime); +void +_priv_gst_date_time_initialize (void) +{ + _gst_date_time_type = gst_date_time_get_type (); } diff --git a/gst/gstdatetime.h b/gst/gstdatetime.h index 08139d7..251dce1 100644 --- a/gst/gstdatetime.h +++ b/gst/gstdatetime.h @@ -32,10 +32,24 @@ G_BEGIN_DECLS * information. It currently supports ranges from 0001-01-01 to * 9999-12-31 in the Gregorian proleptic calendar. * - * Use the acessor functions to get the stored values. + * Use the accessor functions to get the stored values. */ typedef struct _GstDateTime GstDateTime; +GST_EXPORT GType _gst_date_time_type; + +/** + * GST_TYPE_DATE_TIME: + * + * a boxed #GValue type for #GstDateTime that represents a date and time. + * + * Returns: the #GType of GstDateTime + */ + +#define GST_TYPE_DATE_TIME (_gst_date_time_type) + +GType gst_date_time_get_type (void); + /* query which fields are set */ gboolean gst_date_time_has_year (const GstDateTime * datetime); diff --git a/gst/gstdebugutils.c b/gst/gstdebugutils.c index 23c8f9b..7b3ebf9 100644 --- a/gst/gstdebugutils.c +++ b/gst/gstdebugutils.c @@ -163,6 +163,25 @@ debug_dump_pad (GstPad * pad, const gchar * color_name, if (details & GST_DEBUG_GRAPH_SHOW_STATES) { gchar pad_flags[4]; const gchar *activation_mode = "-><"; + const gchar *task_mode = ""; + GstTask *task; + + GST_OBJECT_LOCK (pad); + task = GST_PAD_TASK (pad); + if (task) { + switch (gst_task_get_state (task)) { + case GST_TASK_STARTED: + task_mode = "[T]"; + break; + case GST_TASK_PAUSED: + task_mode = "[t]"; + break; + default: + /* Invalid task state, ignoring */ + break; + } + } + GST_OBJECT_UNLOCK (pad); /* check if pad flags */ pad_flags[0] = @@ -174,9 +193,9 @@ debug_dump_pad (GstPad * pad, const gchar * color_name, pad_flags[3] = '\0'; fprintf (out, - "%s %s_%s [color=black, fillcolor=\"%s\", label=\"%s\\n[%c][%s]\", height=\"0.2\", style=\"%s\"];\n", + "%s %s_%s [color=black, fillcolor=\"%s\", label=\"%s\\n[%c][%s]%s\", height=\"0.2\", style=\"%s\"];\n", spc, element_name, pad_name, color_name, GST_OBJECT_NAME (pad), - activation_mode[pad->mode], pad_flags, style_name); + activation_mode[pad->mode], pad_flags, task_mode, style_name); } else { fprintf (out, "%s %s_%s [color=black, fillcolor=\"%s\", label=\"%s\", height=\"0.2\", style=\"%s\"];\n", @@ -254,6 +273,11 @@ string_append_field (GQuark field, const GValue * value, gpointer ptr) gchar *value_str = gst_value_serialize (value); gchar *esc_value_str; + if (value_str == NULL) { + g_string_append_printf (str, " %18s: NULL\\l", g_quark_to_string (field)); + return TRUE; + } + /* some enums can become really long */ if (strlen (value_str) > 25) { gint pos = 24; @@ -645,6 +669,12 @@ gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details, " label=\"<%s>\\n%s%s%s\";\n" " node [style=filled, shape=box, fontsize=\"9\", fontname=\"sans\", margin=\"0.0,0.0\"];\n" " edge [labelfontsize=\"6\", fontsize=\"9\", fontname=\"monospace\"];\n" + " \n" + " legend [\n" + " pos=\"0,0!\",\n" + " margin=\"0.05,0.05\",\n" + " label=\"Legend\\lElement-States: [~] void-pending, [0] null, [-] ready, [=] paused, [>] playing\\lPad-Activation: [-] none, [>] push, [<] pull\\lPad-Flags: [b]locked, [f]lushing, [b]locking; upper-case is set\\lPad-Task: [T] has started task, [t] has paused task\\l\"\n," + " ];" "\n", G_OBJECT_TYPE_NAME (bin), GST_OBJECT_NAME (bin), (state_name ? state_name : ""), (param_name ? param_name : "") ); diff --git a/gst/gstdevice.c b/gst/gstdevice.c new file mode 100644 index 0000000..9119ba9 --- /dev/null +++ b/gst/gstdevice.c @@ -0,0 +1,350 @@ +/* GStreamer + * Copyright (C) 2012 Olivier Crete <olivier.crete@collabora.com> + * + * gstdevice.c: Device discovery + * + * 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. + */ + +/** + * SECTION:gstdevice + * @short_description: Object representing a device + * @see_also: #GstDeviceMonitor + * + * #GstDevice are objects representing a device, they contain + * relevant metadata about the device, such as its class and the #GstCaps + * representing the media types it can produce or handle. + * + * #GstDevice are created by #GstDeviceMonitor objects which can be + * aggregated by #GstGlobalDeviceMonitor objects. + * + * Since: 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" + +#include "gstdevice.h" + +enum +{ + PROP_DISPLAY_NAME = 1, + PROP_CAPS, + PROP_DEVICE_CLASS +}; + +enum +{ + REMOVED, + LAST_SIGNAL +}; + +struct _GstDevicePrivate +{ + GstCaps *caps; + gchar *device_class; + gchar *display_name; +}; + + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_ABSTRACT_TYPE (GstDevice, gst_device, GST_TYPE_OBJECT); + +static void gst_device_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec); +static void gst_device_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec); +static void gst_device_finalize (GObject * object); + + +static void +gst_device_class_init (GstDeviceClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstDevicePrivate)); + + object_class->get_property = gst_device_get_property; + object_class->set_property = gst_device_set_property; + object_class->finalize = gst_device_finalize; + + g_object_class_install_property (object_class, PROP_DISPLAY_NAME, + g_param_spec_string ("display-name", "Display Name", + "The user-friendly name of the device", "", + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_CAPS, + g_param_spec_boxed ("caps", "Device Caps", + "The possible caps of a device", GST_TYPE_CAPS, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_DEVICE_CLASS, + g_param_spec_string ("device-class", "Device Class", + "The Class of the device", "", + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + signals[REMOVED] = g_signal_new ("removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); +} + +static void +gst_device_init (GstDevice * device) +{ + device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device, GST_TYPE_DEVICE, + GstDevicePrivate); +} + +static void +gst_device_finalize (GObject * object) +{ + GstDevice *device = GST_DEVICE (object); + + gst_caps_replace (&device->priv->caps, NULL); + + g_free (device->priv->display_name); + g_free (device->priv->device_class); + + G_OBJECT_CLASS (gst_device_parent_class)->finalize (object); +} + +static void +gst_device_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDevice *gstdevice; + + gstdevice = GST_DEVICE_CAST (object); + + switch (prop_id) { + case PROP_DISPLAY_NAME: + g_value_take_string (value, gst_device_get_display_name (gstdevice)); + break; + case PROP_CAPS: + if (gstdevice->priv->caps) + g_value_take_boxed (value, gst_device_get_caps (gstdevice)); + break; + case PROP_DEVICE_CLASS: + g_value_take_string (value, gst_device_get_device_class (gstdevice)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +gst_device_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDevice *gstdevice; + + gstdevice = GST_DEVICE_CAST (object); + + switch (prop_id) { + case PROP_DISPLAY_NAME: + gstdevice->priv->display_name = g_value_dup_string (value); + break; + case PROP_CAPS: + gst_caps_replace (&gstdevice->priv->caps, g_value_get_boxed (value)); + break; + case PROP_DEVICE_CLASS: + gstdevice->priv->device_class = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * gst_device_create_element: + * @device: a #GstDevice + * @name: (allow-none): name of new element, or %NULL to automatically + * create a unique name. + * + * Creates the element with all of the required paramaters set to use + * this device. + * + * Returns: (transfer full): a new #GstElement configured to use this device + * + * Since: 1.4 + */ +GstElement * +gst_device_create_element (GstDevice * device, const gchar * name) +{ + GstDeviceClass *klass = GST_DEVICE_GET_CLASS (device); + + if (klass->create_element) + return klass->create_element (device, name); + else + return NULL; +} + +/** + * gst_device_get_caps: + * @device: a #GstDevice + * + * Getter for the #GstCaps that this device supports. + * + * Returns: The #GstCaps supported by this device. Unref with + * gst_caps_unref() when done. + * + * Since: 1.4 + */ +GstCaps * +gst_device_get_caps (GstDevice * device) +{ + if (device->priv->caps) + return gst_caps_ref (device->priv->caps); + else + return NULL; +} + +/** + * gst_device_get_display_name: + * @device: a #GstDevice + * + * Gets the user-friendly name of the device. + * + * Returns: The device name. Free with g_free() after use. + * + * Since: 1.4 + */ +gchar * +gst_device_get_display_name (GstDevice * device) +{ + return + g_strdup (device->priv->display_name ? device->priv->display_name : ""); +} + +/** + * gst_device_get_device_class: + * @device: a #GstDevice + * + * Gets the "class" of a device. This is a "/" separated list of + * classes that represent this device. They are a subset of the + * classes of the #GstDeviceMonitor that produced this device. + * + * Returns: The device class. Free with g_free() after use. + * + * Since: 1.4 + */ +gchar * +gst_device_get_device_class (GstDevice * device) +{ + if (device->priv->device_class != NULL) + return g_strdup (device->priv->device_class); + else + return g_strdup (""); +} + +/** + * gst_device_reconfigure_element: + * @device: a #GstDevice + * @element: a #GstElement + * + * Tries to reconfigure an existing element to use the device. If this + * function fails, then one must destroy the element and create a new one + * using gst_device_create_element(). + * + * Note: This should only be implemented for elements can change their + * device in the PLAYING state. + * + * Returns: %TRUE if the element could be reconfigured to use this device, + * %FALSE otherwise. + * + * Since: 1.4 + */ +gboolean +gst_device_reconfigure_element (GstDevice * device, GstElement * element) +{ + GstDeviceClass *klass = GST_DEVICE_GET_CLASS (device); + + if (klass->reconfigure_element) + return klass->reconfigure_element (device, element); + else + return FALSE; +} + +/** + * gst_device_has_classesv: + * @device: a #GstDevice + * @classes: (array zero-terminated=1): a %NULL terminated array of klasses to match, only match if all + * classes are matched + * + * Check if @factory matches all of the given classes + * + * Returns: %TRUE if @device matches. + * + * Since: 1.4 + */ +gboolean +gst_device_has_classesv (GstDevice * device, gchar ** classes) +{ + g_return_val_if_fail (GST_IS_DEVICE (device), FALSE); + + + for (; classes[0]; classes++) { + const gchar *found; + guint len; + + if (classes[0] == '\0') + continue; + + found = strstr (device->priv->device_class, classes[0]); + + if (!found) + return FALSE; + if (found != device->priv->device_class && *(found - 1) != '/') + return FALSE; + + len = strlen (classes[0]); + if (found[len] != 0 && found[len] != '/') + return FALSE; + } + + return TRUE; +} + +/** + * gst_device_has_classes: + * @device: a #GstDevice + * @classes: a "/" separate list of device classes to match, only match if + * all classes are matched + * + * Check if @device matches all of the given classes + * + * Returns: %TRUE if @device matches. + * + * Since: 1.4 + */ +gboolean +gst_device_has_classes (GstDevice * device, const gchar * classes) +{ + gchar **classesv; + gboolean res; + + classesv = g_strsplit (classes, "/", 0); + + res = gst_device_has_classesv (device, classesv); + + g_strfreev (classesv); + + return res; +} diff --git a/gst/gstdevice.h b/gst/gstdevice.h new file mode 100644 index 0000000..b055aa0 --- /dev/null +++ b/gst/gstdevice.h @@ -0,0 +1,106 @@ +/* GStreamer + * Copyright (C) 2012 Olivier Crete <olivier.crete@collabora.com> + * + * gstdevice.c: Device discovery + * + * 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_DEVICE_H__ +#define __GST_DEVICE_H__ + +typedef struct _GstDevice GstDevice; +typedef struct _GstDeviceClass GstDeviceClass; + +#include <gst/gstelement.h> +#include <gst/gstcaps.h> + + +G_BEGIN_DECLS + +typedef struct _GstDevicePrivate GstDevicePrivate; + +#define GST_TYPE_DEVICE (gst_device_get_type()) +#define GST_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEVICE)) +#define GST_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEVICE)) +#define GST_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEVICE, GstDeviceClass)) +#define GST_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEVICE, GstDevice)) +#define GST_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE, GstDeviceClass)) +#define GST_DEVICE_CAST(obj) ((GstDevice *)(obj)) + +/** + * GstDevice: + * @parent: The parent #GstObject strucuture. + * + * A device object. + * + * Since: 1.4 + */ + +struct _GstDevice { + GstObject parent; + + /*< private >*/ + GstDevicePrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstDeviceClass: + * @parent_class: The parent #GstObjectClass strucuture. + * @create_element: Creates the fully configured element to access this device. + * Subclasses need to override this and return a new element. + * @reconfigure_element: This only needs to be implemented by subclasses if the + * element can be reconfigured to use a different device. See the documentation + * for gst_device_reconfigure_element(). + * + * The class structure for a #GstDevice object. + * + * Since: 1.4 + */ + +struct _GstDeviceClass { + GstObjectClass parent_class; + + GstElement * (*create_element) (GstDevice * device, const gchar * name); + gboolean (*reconfigure_element) (GstDevice * device, GstElement * element); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_device_get_type (void); + +GstElement * gst_device_create_element (GstDevice * device, const gchar * name); + +GstCaps * gst_device_get_caps (GstDevice * device); +gchar * gst_device_get_display_name (GstDevice * device); +gchar * gst_device_get_device_class (GstDevice * device); +gboolean gst_device_reconfigure_element (GstDevice * device, + GstElement * element); + +gboolean gst_device_has_classesv (GstDevice * device, + gchar ** classes); + +gboolean gst_device_has_classes (GstDevice * device, + const gchar * classes); + + +G_END_DECLS + +#endif /* __GST_DEVICE_H__ */ diff --git a/gst/gstdevicemonitor.c b/gst/gstdevicemonitor.c new file mode 100644 index 0000000..6fabe11 --- /dev/null +++ b/gst/gstdevicemonitor.c @@ -0,0 +1,587 @@ +/* GStreamer + * Copyright (C) 2012 Olivier Crete <olivier.crete@collabora.com> + * + * gstdevicemonitor.c: Device probing and monitoring + * + * 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. + */ + +/** + * SECTION:gstdevicemonitor + * @short_description: A device monitor and prober + * @see_also: #GstDevice, #GstGlobalDeviceMonitor + * + * A #GstDeviceMonitor subclass is provided by a plugin that handles devices + * if there is a way to programatically list connected devices. It can also + * optionally provide updates to the list of connected devices. + * + * Each #GstDeviceMonitor subclass is a singleton, a plugin should + * normally provide a single subclass for all devices. + * + * Applications would normally use a #GstGlobalDeviceMonitor to monitor devices + * from all revelant monitors. + * + * Since: 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" + +#include "gstdevicemonitor.h" + +#include "gstelementmetadata.h" +#include "gstquark.h" + +struct _GstDeviceMonitorPrivate +{ + GstBus *bus; + + GMutex start_lock; + + gboolean started_count; +}; + +/* this is used in gstelementfactory.c:gst_element_register() */ +GQuark __gst_devicemonitorclass_factory = 0; + +static void gst_device_monitor_class_init (GstDeviceMonitorClass * klass); +static void gst_device_monitor_init (GstDeviceMonitor * element); +static void gst_device_monitor_base_class_init (gpointer g_class); +static void gst_device_monitor_base_class_finalize (gpointer g_class); +static void gst_device_monitor_dispose (GObject * object); +static void gst_device_monitor_finalize (GObject * object); + +static gpointer gst_device_monitor_parent_class = NULL; + +GType +gst_device_monitor_get_type (void) +{ + static volatile gsize gst_device_monitor_type = 0; + + if (g_once_init_enter (&gst_device_monitor_type)) { + GType _type; + static const GTypeInfo element_info = { + sizeof (GstDeviceMonitorClass), + gst_device_monitor_base_class_init, + gst_device_monitor_base_class_finalize, + (GClassInitFunc) gst_device_monitor_class_init, + NULL, + NULL, + sizeof (GstDeviceMonitor), + 0, + (GInstanceInitFunc) gst_device_monitor_init, + NULL + }; + + _type = g_type_register_static (GST_TYPE_OBJECT, "GstDeviceMonitor", + &element_info, G_TYPE_FLAG_ABSTRACT); + + __gst_devicemonitorclass_factory = + g_quark_from_static_string ("GST_DEVICEMONITORCLASS_FACTORY"); + g_once_init_leave (&gst_device_monitor_type, _type); + } + return gst_device_monitor_type; +} + +static void +gst_device_monitor_base_class_init (gpointer g_class) +{ + GstDeviceMonitorClass *klass = GST_DEVICE_MONITOR_CLASS (g_class); + + /* Copy the element details here so elements can inherit the + * details from their base class and classes only need to set + * the details in class_init instead of base_init */ + klass->metadata = + klass->metadata ? gst_structure_copy (klass->metadata) : + gst_structure_new_empty ("metadata"); + + klass->factory = g_type_get_qdata (G_TYPE_FROM_CLASS (klass), + __gst_devicemonitorclass_factory); +} + +static void +gst_device_monitor_base_class_finalize (gpointer g_class) +{ + GstDeviceMonitorClass *klass = GST_DEVICE_MONITOR_CLASS (g_class); + + gst_structure_free (klass->metadata); +} + +static void +gst_device_monitor_class_init (GstDeviceMonitorClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gst_device_monitor_parent_class = g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (GstDeviceMonitorPrivate)); + + gobject_class->dispose = gst_device_monitor_dispose; + gobject_class->finalize = gst_device_monitor_finalize; +} + +static void +gst_device_monitor_init (GstDeviceMonitor * monitor) +{ + monitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (monitor, + GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorPrivate); + + g_mutex_init (&monitor->priv->start_lock); + + monitor->priv->bus = gst_bus_new (); + gst_bus_set_flushing (monitor->priv->bus, TRUE); +} + + +static void +gst_device_monitor_dispose (GObject * object) +{ + GstDeviceMonitor *monitor = GST_DEVICE_MONITOR (object); + + gst_object_replace ((GstObject **) & monitor->priv->bus, NULL); + + GST_OBJECT_LOCK (monitor); + g_list_free_full (monitor->devices, (GDestroyNotify) gst_object_unparent); + monitor->devices = NULL; + GST_OBJECT_UNLOCK (monitor); + + G_OBJECT_CLASS (gst_device_monitor_parent_class)->dispose (object); +} + +static void +gst_device_monitor_finalize (GObject * object) +{ + GstDeviceMonitor *monitor = GST_DEVICE_MONITOR (object); + + g_mutex_clear (&monitor->priv->start_lock); + + G_OBJECT_CLASS (gst_device_monitor_parent_class)->finalize (object); +} + +/** + * gst_device_monitor_class_add_metadata: + * @klass: class to set metadata for + * @key: the key to set + * @value: the value to set + * + * Set @key with @value as metadata in @klass. + */ +void +gst_device_monitor_class_add_metadata (GstDeviceMonitorClass * klass, + const gchar * key, const gchar * value) +{ + g_return_if_fail (GST_IS_DEVICE_MONITOR_CLASS (klass)); + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + gst_structure_set ((GstStructure *) klass->metadata, + key, G_TYPE_STRING, value, NULL); +} + +/** + * gst_device_monitor_class_add_static_metadata: + * @klass: class to set metadata for + * @key: the key to set + * @value: the value to set + * + * Set @key with @value as metadata in @klass. + * + * Same as gst_device_monitor_class_add_metadata(), but @value must be a static string + * or an inlined string, as it will not be copied. (GStreamer plugins will + * be made resident once loaded, so this function can be used even from + * dynamically loaded plugins.) + * + * Since: 1.4 + */ +void +gst_device_monitor_class_add_static_metadata (GstDeviceMonitorClass * klass, + const gchar * key, const gchar * value) +{ + GValue val = G_VALUE_INIT; + + g_return_if_fail (GST_IS_DEVICE_MONITOR_CLASS (klass)); + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + g_value_init (&val, G_TYPE_STRING); + g_value_set_static_string (&val, value); + gst_structure_take_value ((GstStructure *) klass->metadata, key, &val); +} + +/** + * gst_device_monitor_class_set_metadata: + * @klass: class to set metadata for + * @longname: The long English name of the device monitor. E.g. "File Sink" + * @classification: String describing the type of device monitor, as an unordered list + * separated with slashes ('/'). See draft-klass.txt of the design docs + * for more details and common types. E.g: "Sink/File" + * @description: Sentence describing the purpose of the device monitor. + * E.g: "Write stream to a file" + * @author: Name and contact details of the author(s). Use \n to separate + * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>" + * + * Sets the detailed information for a #GstDeviceMonitorClass. + * <note>This function is for use in _class_init functions only.</note> + * + * Since: 1.4 + */ +void +gst_device_monitor_class_set_metadata (GstDeviceMonitorClass * klass, + const gchar * longname, const gchar * classification, + const gchar * description, const gchar * author) +{ + g_return_if_fail (GST_IS_DEVICE_MONITOR_CLASS (klass)); + g_return_if_fail (longname != NULL && *longname != '\0'); + g_return_if_fail (classification != NULL && *classification != '\0'); + g_return_if_fail (description != NULL && *description != '\0'); + g_return_if_fail (author != NULL && *author != '\0'); + + gst_structure_id_set ((GstStructure *) klass->metadata, + GST_QUARK (ELEMENT_METADATA_LONGNAME), G_TYPE_STRING, longname, + GST_QUARK (ELEMENT_METADATA_KLASS), G_TYPE_STRING, classification, + GST_QUARK (ELEMENT_METADATA_DESCRIPTION), G_TYPE_STRING, description, + GST_QUARK (ELEMENT_METADATA_AUTHOR), G_TYPE_STRING, author, NULL); +} + +/** + * gst_device_monitor_class_set_static_metadata: + * @klass: class to set metadata for + * @longname: The long English name of the element. E.g. "File Sink" + * @classification: String describing the type of element, as an unordered list + * separated with slashes ('/'). See draft-klass.txt of the design docs + * for more details and common types. E.g: "Sink/File" + * @description: Sentence describing the purpose of the element. + * E.g: "Write stream to a file" + * @author: Name and contact details of the author(s). Use \n to separate + * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>" + * + * Sets the detailed information for a #GstDeviceMonitorClass. + * <note>This function is for use in _class_init functions only.</note> + * + * Same as gst_device_monitor_class_set_metadata(), but @longname, @classification, + * @description, and @author must be static strings or inlined strings, as + * they will not be copied. (GStreamer plugins will be made resident once + * loaded, so this function can be used even from dynamically loaded plugins.) + * + * Since: 1.4 + */ +void +gst_device_monitor_class_set_static_metadata (GstDeviceMonitorClass * klass, + const gchar * longname, const gchar * classification, + const gchar * description, const gchar * author) +{ + GstStructure *s = (GstStructure *) klass->metadata; + GValue val = G_VALUE_INIT; + + g_return_if_fail (GST_IS_DEVICE_MONITOR_CLASS (klass)); + g_return_if_fail (longname != NULL && *longname != '\0'); + g_return_if_fail (classification != NULL && *classification != '\0'); + g_return_if_fail (description != NULL && *description != '\0'); + g_return_if_fail (author != NULL && *author != '\0'); + + g_value_init (&val, G_TYPE_STRING); + + g_value_set_static_string (&val, longname); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_LONGNAME), &val); + + g_value_set_static_string (&val, classification); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_KLASS), &val); + + g_value_set_static_string (&val, description); + gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_DESCRIPTION), + &val); + + g_value_set_static_string (&val, author); + gst_structure_id_take_value (s, GST_QUARK (ELEMENT_METADATA_AUTHOR), &val); +} + +/** + * gst_device_monitor_class_get_metadata: + * @klass: class to get metadata for + * @key: the key to get + * + * Get metadata with @key in @klass. + * + * Returns: the metadata for @key. + * + * Since: 1.4 + */ +const gchar * +gst_device_monitor_class_get_metadata (GstDeviceMonitorClass * klass, + const gchar * key) +{ + g_return_val_if_fail (GST_IS_DEVICE_MONITOR_CLASS (klass), NULL); + g_return_val_if_fail (key != NULL, NULL); + + return gst_structure_get_string ((GstStructure *) klass->metadata, key); +} + +/** + * gst_device_monitor_get_devices: + * @monitor: A #GstDeviceMonitor + * + * Gets a list of devices that this monitor understands. This may actually + * probe the hardware if the monitor is not currently started. + * + * Returns: (transfer full) (element-type GstDevice): a #GList of + * #GstDevice + * + * Since: 1.4 + */ + +GList * +gst_device_monitor_get_devices (GstDeviceMonitor * monitor) +{ + GstDeviceMonitorClass *klass; + GList *devices = NULL; + gboolean started; + GList *item; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL); + klass = GST_DEVICE_MONITOR_GET_CLASS (monitor); + + g_mutex_lock (&monitor->priv->start_lock); + started = (monitor->priv->started_count > 0); + + if (started) { + GST_OBJECT_LOCK (monitor); + for (item = monitor->devices; item; item = item->next) + devices = g_list_prepend (devices, gst_object_ref (item->data)); + GST_OBJECT_UNLOCK (monitor); + } else if (klass->probe) + devices = klass->probe (monitor); + + g_mutex_unlock (&monitor->priv->start_lock); + + return devices; +} + +/** + * gst_device_monitor_start: + * @monitor: A #GstDeviceMonitor + * + * Starts monitoring the devices. This will cause #GST_MESSAGE_DEVICE messages + * to be posted on the monitor's bus when devices are added or removed from + * the system. + * + * Since the #GstDeviceMonitor is a singleton, + * gst_device_monitor_start() may already have been called by another + * user of the object, gst_device_monitor_stop() needs to be called the same + * number of times. + * + * Returns: %TRUE if the device monitoring could be started + * + * Since: 1.4 + */ + +gboolean +gst_device_monitor_start (GstDeviceMonitor * monitor) +{ + GstDeviceMonitorClass *klass; + gboolean ret = FALSE; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE); + klass = GST_DEVICE_MONITOR_GET_CLASS (monitor); + + g_mutex_lock (&monitor->priv->start_lock); + + if (monitor->priv->started_count > 0) { + ret = TRUE; + goto started; + } + + if (klass->start) + ret = klass->start (monitor); + + if (ret) { + monitor->priv->started_count++; + gst_bus_set_flushing (monitor->priv->bus, FALSE); + } + +started: + + g_mutex_unlock (&monitor->priv->start_lock); + + return ret; +} + +/** + * gst_device_monitor_stop: + * @monitor: A #GstDeviceMonitor + * + * Decreases the use-count by one. If the use count reaches zero, this + * #GstDeviceMonitor will stop monitoring the devices. This needs to be + * called the same number of times that gst_device_monitor_start() was called. + * + * Since: 1.4 + */ + +void +gst_device_monitor_stop (GstDeviceMonitor * monitor) +{ + GstDeviceMonitorClass *klass; + + g_return_if_fail (GST_IS_DEVICE_MONITOR (monitor)); + klass = GST_DEVICE_MONITOR_GET_CLASS (monitor); + + g_mutex_lock (&monitor->priv->start_lock); + + if (monitor->priv->started_count == 1) { + gst_bus_set_flushing (monitor->priv->bus, TRUE); + if (klass->stop) + klass->stop (monitor); + GST_OBJECT_LOCK (monitor); + g_list_free_full (monitor->devices, (GDestroyNotify) gst_object_unparent); + monitor->devices = NULL; + GST_OBJECT_UNLOCK (monitor); + } else if (monitor->priv->started_count < 1) { + g_critical ("Trying to stop a GstDeviceMonitor %s which is already stopped", + GST_OBJECT_NAME (monitor)); + } + + monitor->priv->started_count--; + g_mutex_unlock (&monitor->priv->start_lock); +} + + +/** + * gst_device_monitor_get_factory: + * @monitor: a #GstDeviceMonitor to request the device monitor factory of. + * + * Retrieves the factory that was used to create this device monitor. + * + * Returns: (transfer none): the #GstDeviceMonitorFactory used for creating this + * device monitor. no refcounting is needed. + * + * Since: 1.4 + */ +GstDeviceMonitorFactory * +gst_device_monitor_get_factory (GstDeviceMonitor * monitor) +{ + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL); + + return GST_DEVICE_MONITOR_GET_CLASS (monitor)->factory; +} + +/** + * gst_device_monitor_can_monitor: + * @monitor: a #GstDeviceMonitor + * + * If this function returns %TRUE, then the device monitor can monitor if + * devices are added or removed. Otherwise, it can only do static probing. + * + * Returns: %TRUE if the #GstDeviceMonitor support monitoring, %FALSE otherwise + */ +gboolean +gst_device_monitor_can_monitor (GstDeviceMonitor * monitor) +{ + GstDeviceMonitorClass *klass; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), FALSE); + klass = GST_DEVICE_MONITOR_GET_CLASS (monitor); + + if (klass->start) + return TRUE; + else + return FALSE; +} + +/** + * gst_device_monitor_get_bus: + * @monitor: a #GstDeviceMonitor + * + * Gets the #GstBus of this #GstDeviceMonitor + * + * Returns: (transfer full): a #GstBus + * + * Since: 1.4 + */ +GstBus * +gst_device_monitor_get_bus (GstDeviceMonitor * monitor) +{ + g_return_val_if_fail (GST_IS_DEVICE_MONITOR (monitor), NULL); + + return gst_object_ref (monitor->priv->bus); +} + +/** + * gst_device_monitor_device_add: + * @monitor: a #GstDeviceMonitor + * @device: (transfer full): a #GstDevice that has been added + * + * Posts a message on the monitor's #GstBus to inform applications that + * a new device has been added. + * + * This is for use by subclasses. + * + * Since: 1.4 + */ +void +gst_device_monitor_device_add (GstDeviceMonitor * monitor, GstDevice * device) +{ + GstMessage *message; + + if (!gst_object_set_parent (GST_OBJECT (device), GST_OBJECT (monitor))) { + GST_WARNING_OBJECT (monitor, "Could not parent device %p to monitor," + " it already has a parent", device); + return; + } + + GST_OBJECT_LOCK (monitor); + monitor->devices = g_list_prepend (monitor->devices, gst_object_ref (device)); + GST_OBJECT_UNLOCK (monitor); + + message = gst_message_new_device_added (GST_OBJECT (monitor), device); + gst_bus_post (monitor->priv->bus, message); + gst_object_unref (device); +} + + +/** + * gst_device_monitor_device_remove: + * @monitor: a #GstDeviceMonitor + * @device: a #GstDevice that has been removed + * + * Posts a message on the monitor's #GstBus to inform applications that + * a device has been removed. + * + * This is for use by subclasses. + * + * Since: 1.4 + */ +void +gst_device_monitor_device_remove (GstDeviceMonitor * monitor, + GstDevice * device) +{ + GstMessage *message; + GList *item; + + GST_OBJECT_LOCK (monitor); + item = g_list_find (monitor->devices, device); + if (item) { + monitor->devices = g_list_delete_link (monitor->devices, item); + } + GST_OBJECT_UNLOCK (monitor); + + message = gst_message_new_device_removed (GST_OBJECT (monitor), device); + g_signal_emit_by_name (device, "removed"); + gst_bus_post (monitor->priv->bus, message); + if (item) + gst_object_unparent (GST_OBJECT (device)); +} diff --git a/gst/gstdevicemonitor.h b/gst/gstdevicemonitor.h new file mode 100644 index 0000000..f5c3307 --- /dev/null +++ b/gst/gstdevicemonitor.h @@ -0,0 +1,142 @@ +/* GStreamer + * Copyright (C) 2012 Olivier Crete <olivier.crete@collabora.com> + * + * gstdevicemonitor.h: Device probing and monitoring + * + * 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. + */ + +#include <gst/gstdevicemonitorfactory.h> + + +#ifndef __GST_DEVICE_MONITOR_H__ +#define __GST_DEVICE_MONITOR_H__ + +#include <gst/gstelement.h> + +G_BEGIN_DECLS + +typedef struct _GstDeviceMonitor GstDeviceMonitor; +typedef struct _GstDeviceMonitorClass GstDeviceMonitorClass; +typedef struct _GstDeviceMonitorPrivate GstDeviceMonitorPrivate; + +#define GST_TYPE_DEVICE_MONITOR (gst_device_monitor_get_type()) +#define GST_IS_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEVICE_MONITOR)) +#define GST_IS_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEVICE_MONITOR)) +#define GST_DEVICE_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorClass)) +#define GST_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEVICE_MONITOR, GstDeviceMonitor)) +#define GST_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE_MONITOR, GstDeviceMonitorClass)) +#define GST_DEVICE_MONITOR_CAST(obj) ((GstDeviceMonitor *)(obj)) + + +/** + * GstDeviceMonitor: + * @parent: The parent #GstObject + * @devices: a #GList of the #GstDevice objects + * + * The structure of the base #GstDeviceMonitor + * + * Since: 1.4 + */ +struct _GstDeviceMonitor { + GstObject parent; + + /* Protected by the Object lock */ + GList *devices; + + /*< private >*/ + + GstDeviceMonitorPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstDeviceMonitorClass: + * @parent_class: the parent #GstObjectClass structure + * @factory: a pointer to the #GstDeviceMonitorFactory that creates this + * monitor + * @probe: Returns a list of devices that are currently available. + * This should never block. + * @start: Starts monitoring for new devices. Only subclasses that can know + * that devices have been added or remove need to implement this method. + * @stop: Stops monitoring for new devices. Only subclasses that implement + * the start() method need to implement this method. + * + * The structure of the base #GstDeviceMonitorClass + * + * Since: 1.4 + */ + +struct _GstDeviceMonitorClass { + GstObjectClass parent_class; + + GstDeviceMonitorFactory *factory; + + GList* (*probe) (GstDeviceMonitor * monitor); + + gboolean (*start) (GstDeviceMonitor * monitor); + void (*stop) (GstDeviceMonitor * monitor); + + /*< private >*/ + gpointer metadata; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_device_monitor_get_type (void); + + +GList * gst_device_monitor_get_devices (GstDeviceMonitor * monitor); + +gboolean gst_device_monitor_start (GstDeviceMonitor * monitor); +void gst_device_monitor_stop (GstDeviceMonitor * monitor); + +gboolean gst_device_monitor_can_monitor (GstDeviceMonitor * monitor); + +GstBus * gst_device_monitor_get_bus (GstDeviceMonitor * monitor); + +void gst_device_monitor_device_add (GstDeviceMonitor * monitor, + GstDevice * device); +void gst_device_monitor_device_remove (GstDeviceMonitor * monitor, + GstDevice * device); + + +/* device monitor class meta data */ +void gst_device_monitor_class_set_metadata (GstDeviceMonitorClass *klass, + const gchar *longname, + const gchar *classification, + const gchar *description, + const gchar *author); +void gst_device_monitor_class_set_static_metadata (GstDeviceMonitorClass *klass, + const gchar *longname, + const gchar *classification, + const gchar *description, + const gchar *author); +void gst_device_monitor_class_add_metadata (GstDeviceMonitorClass * klass, + const gchar * key, const gchar * value); +void gst_device_monitor_class_add_static_metadata (GstDeviceMonitorClass * klass, + const gchar * key, const gchar * value); +const gchar * gst_device_monitor_class_get_metadata (GstDeviceMonitorClass * klass, + const gchar * key); + +/* factory management */ +GstDeviceMonitorFactory * gst_device_monitor_get_factory (GstDeviceMonitor * monitor); + +G_END_DECLS + +#endif /* __GST_DEVICE_MONITOR_H__ */ diff --git a/gst/gstdevicemonitorfactory.c b/gst/gstdevicemonitorfactory.c new file mode 100644 index 0000000..f8c9826 --- /dev/null +++ b/gst/gstdevicemonitorfactory.c @@ -0,0 +1,594 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> + * 2000 Wim Taymans <wtay@chello.be> + * 2003 Benjamin Otte <in7y118@public.uni-hamburg.de> + * + * gstdevicemonitorfactory.c: GstDeviceMonitorFactory object, support routines + * + * 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. + */ + +/** + * SECTION:gstdevicemonitorfactory + * @short_description: Create GstDeviceMonitors from a factory + * @see_also: #GstDeviceMonitor, #GstPlugin, #GstPluginFeature, #GstPadTemplate. + * + * #GstDeviceMonitorFactory is used to create instances of device monitors. A + * GstDeviceMonitorfactory can be added to a #GstPlugin as it is also a + * #GstPluginFeature. + * + * Use the gst_device_monitor_factory_find() and gst_device_monitor_factory_create() + * functions to create device monitor instances or use gst_device_monitor_factory_make() as a + * convenient shortcut. + * + * Since: 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" + +#include "gstdevicemonitorfactory.h" +#include "gst.h" + +#include "glib-compat-private.h" + +GST_DEBUG_CATEGORY_STATIC (device_monitor_factory_debug); +#define GST_CAT_DEFAULT device_monitor_factory_debug + +static void gst_device_monitor_factory_finalize (GObject * object); +static void gst_device_monitor_factory_cleanup (GstDeviceMonitorFactory * + factory); + +/* static guint gst_device_monitor_factory_signals[LAST_SIGNAL] = { 0 }; */ + +/* this is defined in gstelement.c */ +extern GQuark __gst_devicemonitorclass_factory; + +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (device_monitor_factory_debug, "GST_DEVICE_MONITOR_FACTORY", \ + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, \ + "device monitor factories keep information about installed device monitors"); \ +} + +G_DEFINE_TYPE_WITH_CODE (GstDeviceMonitorFactory, gst_device_monitor_factory, + GST_TYPE_PLUGIN_FEATURE, _do_init); + +static void +gst_device_monitor_factory_class_init (GstDeviceMonitorFactoryClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->finalize = gst_device_monitor_factory_finalize; +} + +static void +gst_device_monitor_factory_init (GstDeviceMonitorFactory * factory) +{ +} + +static void +gst_device_monitor_factory_finalize (GObject * object) +{ + GstDeviceMonitorFactory *factory = GST_DEVICE_MONITOR_FACTORY (object); + GstDeviceMonitor *monitor; + + gst_device_monitor_factory_cleanup (factory); + + monitor = g_atomic_pointer_get (&factory->monitor); + if (monitor) + gst_object_unref (monitor); + + G_OBJECT_CLASS (gst_device_monitor_factory_parent_class)->finalize (object); +} + +/** + * gst_device_monitor_factory_find: + * @name: name of factory to find + * + * Search for an device monitor factory of the given name. Refs the returned + * device monitor factory; caller is responsible for unreffing. + * + * Returns: (transfer full): #GstDeviceMonitorFactory if found, %NULL otherwise + * + * Since: 1.4 + */ +GstDeviceMonitorFactory * +gst_device_monitor_factory_find (const gchar * name) +{ + GstPluginFeature *feature; + + g_return_val_if_fail (name != NULL, NULL); + + feature = gst_registry_find_feature (gst_registry_get (), name, + GST_TYPE_DEVICE_MONITOR_FACTORY); + if (feature) + return GST_DEVICE_MONITOR_FACTORY (feature); + + /* this isn't an error, for instance when you query if an device monitor factory is + * present */ + GST_LOG ("no such device monitor factory \"%s\"", name); + + return NULL; +} + +static void +gst_device_monitor_factory_cleanup (GstDeviceMonitorFactory * factory) +{ + if (factory->metadata) { + gst_structure_free ((GstStructure *) factory->metadata); + factory->metadata = NULL; + } + if (factory->type) { + factory->type = G_TYPE_INVALID; + } +} + +#define CHECK_METADATA_FIELD(klass, name, key) \ + G_STMT_START { \ + const gchar *metafield = gst_device_monitor_class_get_metadata (klass, key); \ + if (G_UNLIKELY (metafield == NULL || *metafield == '\0')) { \ + g_warning ("Device monitor factory metadata for '%s' has no valid %s field", name, key); \ + goto detailserror; \ + } \ + } G_STMT_END; + +/** + * gst_device_monitor_register: + * @plugin: (allow-none): #GstPlugin to register the device monitor with, or %NULL for + * a static device monitor. + * @name: name of device monitors of this type + * @rank: rank of device monitor (higher rank means more importance when autoplugging) + * @type: GType of device monitor to register + * + * Create a new device monitorfactory capable of instantiating objects of the + * @type and add the factory to @plugin. + * + * Returns: %TRUE, if the registering succeeded, %FALSE on error + * + * Since: 1.4 + */ +gboolean +gst_device_monitor_register (GstPlugin * plugin, const gchar * name, guint rank, + GType type) +{ + GstPluginFeature *existing_feature; + GstRegistry *registry; + GstDeviceMonitorFactory *factory; + GstDeviceMonitorClass *klass; + + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (g_type_is_a (type, GST_TYPE_DEVICE_MONITOR), FALSE); + + registry = gst_registry_get (); + + /* check if feature already exists, if it exists there is no need to update it + * when the registry is getting updated, outdated plugins and all their + * features are removed and readded. + */ + existing_feature = gst_registry_lookup_feature (registry, name); + if (existing_feature) { + GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)", + existing_feature, name); + factory = GST_DEVICE_MONITOR_FACTORY_CAST (existing_feature); + factory->type = type; + existing_feature->loaded = TRUE; + g_type_set_qdata (type, __gst_devicemonitorclass_factory, factory); + gst_object_unref (existing_feature); + return TRUE; + } + + factory = + GST_DEVICE_MONITOR_FACTORY_CAST (g_object_newv + (GST_TYPE_DEVICE_MONITOR_FACTORY, 0, NULL)); + gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name); + GST_LOG_OBJECT (factory, "Created new device monitorfactory for type %s", + g_type_name (type)); + + /* provide info needed during class structure setup */ + g_type_set_qdata (type, __gst_devicemonitorclass_factory, factory); + klass = GST_DEVICE_MONITOR_CLASS (g_type_class_ref (type)); + + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_LONGNAME); + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_KLASS); + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_DESCRIPTION); + CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_AUTHOR); + + factory->type = type; + factory->metadata = gst_structure_copy ((GstStructure *) klass->metadata); + + if (plugin && plugin->desc.name) { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin; + g_object_add_weak_pointer ((GObject *) plugin, + (gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin); + } else { + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL"; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL; + } + gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory), rank); + GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE; + + gst_registry_add_feature (registry, GST_PLUGIN_FEATURE_CAST (factory)); + + return TRUE; + + /* ERRORS */ +detailserror: + { + gst_device_monitor_factory_cleanup (factory); + return FALSE; + } +} + +/** + * gst_device_monitor_factory_get: + * @factory: factory to instantiate + * + * Returns the device monitor of the type defined by the given device + * monitorfactory. + * + * Returns: (transfer full): the #GstDeviceMonitor or %NULL if the + * device monitor couldn't be created + * + * Since: 1.4 + */ +GstDeviceMonitor * +gst_device_monitor_factory_get (GstDeviceMonitorFactory * factory) +{ + GstDeviceMonitor *device_monitor; + GstDeviceMonitorClass *oclass; + GstDeviceMonitorFactory *newfactory; + + g_return_val_if_fail (factory != NULL, NULL); + + newfactory = + GST_DEVICE_MONITOR_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE + (factory))); + + if (newfactory == NULL) + goto load_failed; + + factory = newfactory; + + GST_INFO ("getting device monitor \"%s\"", GST_OBJECT_NAME (factory)); + + if (factory->type == 0) + goto no_type; + + device_monitor = g_atomic_pointer_get (&newfactory->monitor); + if (device_monitor) + return gst_object_ref (device_monitor); + + /* create an instance of the device monitor, cast so we don't assert on NULL + * also set name as early as we can + */ + device_monitor = GST_DEVICE_MONITOR_CAST (g_object_newv (factory->type, 0, + NULL)); + if (G_UNLIKELY (device_monitor == NULL)) + goto no_device_monitor; + + /* fill in the pointer to the factory in the device monitor class. The + * class will not be unreffed currently. + * Be thread safe as there might be 2 threads creating the first instance of + * an device monitor at the same moment + */ + oclass = GST_DEVICE_MONITOR_GET_CLASS (device_monitor); + if (!g_atomic_pointer_compare_and_exchange (&oclass->factory, NULL, factory)) + gst_object_unref (factory); + + gst_object_ref_sink (device_monitor); + + /* We use an atomic to make sure we don't create two in parallel */ + if (!g_atomic_pointer_compare_and_exchange (&newfactory->monitor, NULL, + device_monitor)) { + gst_object_unref (device_monitor); + + device_monitor = g_atomic_pointer_get (&newfactory->monitor); + } + + GST_DEBUG ("created device monitor \"%s\"", GST_OBJECT_NAME (factory)); + + return gst_object_ref (device_monitor); + + /* ERRORS */ +load_failed: + { + GST_WARNING_OBJECT (factory, + "loading plugin containing feature %s returned NULL!", + GST_OBJECT_NAME (factory)); + return NULL; + } +no_type: + { + GST_WARNING_OBJECT (factory, "factory has no type"); + gst_object_unref (factory); + return NULL; + } +no_device_monitor: + { + GST_WARNING_OBJECT (factory, "could not create device monitor"); + gst_object_unref (factory); + return NULL; + } +} + +/** + * gst_device_monitor_factory_get_by_name: + * @factoryname: a named factory to instantiate + * + * Returns the device monitor of the type defined by the given device + * monitor factory. + * + * Returns: (transfer full): a #GstDeviceMonitor or %NULL if unable to + * create device monitor + * + * Since: 1.4 + */ +GstDeviceMonitor * +gst_device_monitor_factory_get_by_name (const gchar * factoryname) +{ + GstDeviceMonitorFactory *factory; + GstDeviceMonitor *device_monitor; + + g_return_val_if_fail (factoryname != NULL, NULL); + g_return_val_if_fail (gst_is_initialized (), NULL); + + GST_LOG ("gstdevicemonitorfactory: get_by_name \"%s\"", factoryname); + + factory = gst_device_monitor_factory_find (factoryname); + if (factory == NULL) + goto no_factory; + + GST_LOG_OBJECT (factory, "found factory %p", factory); + device_monitor = gst_device_monitor_factory_get (factory); + if (device_monitor == NULL) + goto create_failed; + + gst_object_unref (factory); + return device_monitor; + + /* ERRORS */ +no_factory: + { + GST_INFO ("no such device monitor factory \"%s\"!", factoryname); + return NULL; + } +create_failed: + { + GST_INFO_OBJECT (factory, "couldn't create instance!"); + gst_object_unref (factory); + return NULL; + } +} + +/** + * gst_device_monitor_factory_get_device_monitor_type: + * @factory: factory to get managed #GType from + * + * Get the #GType for device monitors managed by this factory. The type can + * only be retrieved if the device monitor factory is loaded, which can be + * assured with gst_plugin_feature_load(). + * + * Returns: the #GType for device monitors managed by this factory or 0 if + * the factory is not loaded. + * + * Since: 1.4 + */ +GType +gst_device_monitor_factory_get_device_monitor_type (GstDeviceMonitorFactory * + factory) +{ + g_return_val_if_fail (GST_IS_DEVICE_MONITOR_FACTORY (factory), 0); + + return factory->type; +} + +/** + * gst_device_monitor_factory_get_metadata: + * @factory: a #GstDeviceMonitorFactory + * @key: a key + * + * Get the metadata on @factory with @key. + * + * Returns: the metadata with @key on @factory or %NULL when there was no + * metadata with the given @key. + * + * Since: 1.4 + */ +const gchar * +gst_device_monitor_factory_get_metadata (GstDeviceMonitorFactory * factory, + const gchar * key) +{ + return gst_structure_get_string ((GstStructure *) factory->metadata, key); +} + +/** + * gst_device_monitor_factory_get_metadata_keys: + * @factory: a #GstDeviceMonitorFactory + * + * Get the available keys for the metadata on @factory. + * + * Returns: (transfer full) (element-type utf8) (array zero-terminated=1): + * a %NULL-terminated array of key strings, or %NULL when there is no + * metadata. Free with g_strfreev() when no longer needed. + * + * Since: 1.4 + */ +gchar ** +gst_device_monitor_factory_get_metadata_keys (GstDeviceMonitorFactory * factory) +{ + GstStructure *metadata; + gchar **arr; + gint i, num; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR_FACTORY (factory), NULL); + + metadata = (GstStructure *) factory->metadata; + if (metadata == NULL) + return NULL; + + num = gst_structure_n_fields (metadata); + if (num == 0) + return NULL; + + arr = g_new (gchar *, num + 1); + for (i = 0; i < num; ++i) { + arr[i] = g_strdup (gst_structure_nth_field_name (metadata, i)); + } + arr[i] = NULL; + return arr; +} + +/** + * gst_device_monitor_factory_has_classesv: + * @factory: a #GstDeviceMonitorFactory + * @classes: (array zero-terminated=1): a %NULL terminated array of + * klasses to match, only match if all classes are matched + * + * Check if @factory matches all of the given classes + * + * Returns: %TRUE if @factory matches. + * + * Since: 1.4 + */ +gboolean +gst_device_monitor_factory_has_classesv (GstDeviceMonitorFactory * factory, + gchar ** classes) +{ + const gchar *klass; + + g_return_val_if_fail (GST_IS_DEVICE_MONITOR_FACTORY (factory), FALSE); + + klass = gst_device_monitor_factory_get_metadata (factory, + GST_ELEMENT_METADATA_KLASS); + + if (klass == NULL) { + GST_ERROR_OBJECT (factory, + "device monitor factory is missing klass identifiers"); + return FALSE; + } + + for (; classes[0]; classes++) { + const gchar *found; + guint len; + + if (classes[0] == '\0') + continue; + + found = strstr (klass, classes[0]); + + if (!found) + return FALSE; + if (found != klass && *(found - 1) != '/') + return FALSE; + + len = strlen (classes[0]); + if (found[len] != 0 && found[len] != '/') + return FALSE; + } + + return TRUE; +} + +/** + * gst_device_monitor_factory_has_classes: + * @factory: a #GstDeviceMonitorFactory + * @classes: a "/" separate list of klasses to match, only match if all classes + * are matched + * + * Check if @factory matches all of the given @classes + * + * Returns: %TRUE if @factory matches. + * + * Since: 1.4 + */ +gboolean +gst_device_monitor_factory_has_classes (GstDeviceMonitorFactory * factory, + const gchar * classes) +{ + gchar **classesv; + gboolean res; + + classesv = g_strsplit (classes, "/", 0); + + res = gst_device_monitor_factory_has_classesv (factory, classesv); + + g_strfreev (classesv); + + return res; +} + +typedef struct +{ + const char *classes; + GstRank minrank; +} FilterData; + +static gboolean +device_monitor_filter (GstPluginFeature * feature, FilterData * data) +{ + gboolean res; + + /* we only care about device monitor factories */ + if (G_UNLIKELY (!GST_IS_DEVICE_MONITOR_FACTORY (feature))) + return FALSE; + + res = (gst_plugin_feature_get_rank (feature) >= data->minrank) && + gst_device_monitor_factory_has_classes (GST_DEVICE_MONITOR_FACTORY_CAST + (feature), data->classes); + + return res; +} + +/** + * gst_device_monitor_factory_list_get_device_monitors: + * @classes: a "/" separate list of klasses to match, only match if all classes + * are matched + * @minrank: Minimum rank + * + * Get a list of factories that match all of the given @classes. Only + * device monitors with a rank greater or equal to @minrank will be + * returned. The list of factories is returned by decreasing rank. + * + * Returns: (transfer full) (element-type Gst.DeviceMonitorFactory): a #GList of + * #GstDeviceMonitorFactory device monitors. Use gst_plugin_feature_list_free() after + * usage. + * + * Since: 1.4 + */ +GList *gst_device_monitor_factory_list_get_device_monitors + (const gchar * classes, GstRank minrank) +{ + GList *result; + FilterData data; + + /* prepare type */ + data.classes = classes; + data.minrank = minrank; + + /* get the feature list using the filter */ + result = gst_registry_feature_filter (gst_registry_get (), + (GstPluginFeatureFilter) device_monitor_filter, FALSE, &data); + + /* sort on rank and name */ + result = g_list_sort (result, gst_plugin_feature_rank_compare_func); + + return result; +} diff --git a/gst/gstdevicemonitorfactory.h b/gst/gstdevicemonitorfactory.h new file mode 100644 index 0000000..02bf04a --- /dev/null +++ b/gst/gstdevicemonitorfactory.h @@ -0,0 +1,90 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> + * 2000,2004 Wim Taymans <wim@fluendo.com> + * 2012 Olivier Crete <olivier.crete@collabora.com> + * + * gstdevicemonitorfactory.h: Header for GstDeviceMonitorFactory + * + * 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_DEVICE_MONITOR_FACTORY_H__ +#define __GST_DEVICE_MONITOR_FACTORY_H__ + +/** + * GstDeviceMonitorFactory: + * + * The opaque #GstDeviceMonitorFactory data structure. + * + * Since: 1.4 + */ + +/** + * GstDeviceMonitorFactoryClass: + * + * The opaque #GstDeviceMonitorFactoryClass data structure. + * + * Since: 1.4 + */ +typedef struct _GstDeviceMonitorFactory GstDeviceMonitorFactory; +typedef struct _GstDeviceMonitorFactoryClass GstDeviceMonitorFactoryClass; + +#include <gst/gstconfig.h> +#include <gst/gstplugin.h> +#include <gst/gstpluginfeature.h> +#include <gst/gstdevicemonitor.h> + +G_BEGIN_DECLS + +#define GST_TYPE_DEVICE_MONITOR_FACTORY (gst_device_monitor_factory_get_type()) +#define GST_DEVICE_MONITOR_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DEVICE_MONITOR_FACTORY,\ + GstDeviceMonitorFactory)) +#define GST_DEVICE_MONITOR_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DEVICE_MONITOR_FACTORY,\ + GstDeviceMonitorFactoryClass)) +#define GST_IS_DEVICE_MONITOR_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DEVICE_MONITOR_FACTORY)) +#define GST_IS_DEVICE_MONITOR_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DEVICE_MONITOR_FACTORY)) +#define GST_DEVICE_MONITOR_FACTORY_CAST(obj) ((GstDeviceMonitorFactory *)(obj)) + +GType gst_device_monitor_factory_get_type (void); + +GstDeviceMonitorFactory * gst_device_monitor_factory_find (const gchar *name); + +GType gst_device_monitor_factory_get_device_monitor_type (GstDeviceMonitorFactory *factory); + +const gchar * gst_device_monitor_factory_get_metadata (GstDeviceMonitorFactory *factory, const gchar *key); +gchar ** gst_device_monitor_factory_get_metadata_keys (GstDeviceMonitorFactory *factory); + +GstDeviceMonitor* gst_device_monitor_factory_get (GstDeviceMonitorFactory *factory) G_GNUC_MALLOC; +GstDeviceMonitor* gst_device_monitor_factory_get_by_name (const gchar *factoryname) G_GNUC_MALLOC; + +gboolean gst_device_monitor_register (GstPlugin *plugin, const gchar *name, + guint rank, + GType type); + +gboolean gst_device_monitor_factory_has_classesv (GstDeviceMonitorFactory * factory, + gchar ** classes); + +gboolean gst_device_monitor_factory_has_classes (GstDeviceMonitorFactory *factory, + const gchar * classes); + +GList * gst_device_monitor_factory_list_get_device_monitors (const gchar *classes, + GstRank minrank) G_GNUC_MALLOC; + +G_END_DECLS + +#endif /* __GST_DEVICE_MONITOR_FACTORY_H__ */ diff --git a/gst/gstelement.c b/gst/gstelement.c index 6af2ca1..25870f5 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -43,8 +43,7 @@ * * An existing pad of an element can be retrieved by name with * gst_element_get_static_pad(). A new dynamic pad can be created using - * gst_element_request_pad() with a #GstPadTemplate or - * gst_element_get_request_pad() with the template name such as "src_\%u". + * gst_element_request_pad() with a #GstPadTemplate. * An iterator of all pads can be retrieved with gst_element_iterate_pads(). * * Elements can be linked through their pads. @@ -72,11 +71,9 @@ * #GST_ELEMENT_FLAG_REQUIRE_CLOCK() flag is set, a clock should be set on the * element with gst_element_set_clock(). * - * Note that clock slection and distribution is normally handled by the + * Note that clock selection and distribution is normally handled by the * toplevel #GstPipeline so the clock functions are only to be used in very * specific situations. - * - * Last reviewed on 2012-03-28 (0.11.3) */ #include "gst_private.h" @@ -308,10 +305,10 @@ gst_element_init (GstElement * element) * @pad: the #GstPad to release. * * Makes the element free the previously requested pad as obtained - * with gst_element_get_request_pad(). + * with gst_element_request_pad(). * * This does not unref the pad. If the pad was created by using - * gst_element_get_request_pad(), gst_element_release_request_pad() needs to be + * gst_element_request_pad(), gst_element_release_request_pad() needs to be * followed by gst_object_unref() to free the @pad. * * MT safe. @@ -735,7 +732,7 @@ no_direction: * * This function is used by plugin developers and should not be used * by applications. Pads that were dynamically requested from elements - * with gst_element_get_request_pad() should be released with the + * with gst_element_request_pad() should be released with the * gst_element_release_request_pad() function instead. * * Pads are not automatically deactivated so elements should perform the needed @@ -798,6 +795,7 @@ gst_element_remove_pad (GstElement * element, GstPad * pad) break; } element->pads = g_list_remove (element->pads, pad); + GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_NEED_PARENT); element->numpads--; element->pads_cookie++; GST_OBJECT_UNLOCK (element); @@ -1535,7 +1533,7 @@ gst_element_default_send_event (GstElement * element, GstEvent * event) * event handler, the event will be pushed on a random linked sink pad for * upstream events or a random linked source pad for downstream events. * - * This function takes owership of the provided event so you should + * This function takes ownership of the provided event so you should * gst_event_ref() it if you want to reuse the event after this call. * * MT safe. @@ -1643,7 +1641,7 @@ gst_element_default_query (GstElement * element, GstQuery * query) * * Please note that some queries might need a running pipeline to work. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. * * MT safe. */ @@ -1875,7 +1873,7 @@ void gst_element_message_full * * MT safe. * - * Returns: TRUE, if the element's state is locked. + * Returns: %TRUE, if the element's state is locked. */ gboolean gst_element_is_locked_state (GstElement * element) @@ -1894,14 +1892,14 @@ gst_element_is_locked_state (GstElement * element) /** * gst_element_set_locked_state: * @element: a #GstElement - * @locked_state: TRUE to lock the element's state + * @locked_state: %TRUE to lock the element's state * * Locks the state of an element, so state changes of the parent don't affect * this element anymore. * * MT safe. * - * Returns: TRUE if the state was changed, FALSE if bad parameters were given + * Returns: %TRUE if the state was changed, %FALSE if bad parameters were given * or the elements state-locking needed no change. */ gboolean @@ -1946,9 +1944,9 @@ was_ok: * @element: a #GstElement. * * Tries to change the state of the element to the same as its parent. - * If this function returns FALSE, the state of element is undefined. + * If this function returns %FALSE, the state of element is undefined. * - * Returns: TRUE, if the element's state could be synced to the parent's state. + * Returns: %TRUE, if the element's state could be synced to the parent's state. * * MT safe. */ diff --git a/gst/gstelement.h b/gst/gstelement.h index 73ca545..408d10c 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -212,7 +212,7 @@ typedef enum { * </para></listitem> * <listitem><para> * The pipeline selects a #GstClock and distributes this to all the children - * before setting them to PLAYING. This means that it is only alowed to + * before setting them to PLAYING. This means that it is only allowed to * synchronize on the #GstClock in the PLAYING state. * </para></listitem> * <listitem><para> @@ -691,7 +691,7 @@ GType gst_element_get_type (void); * * Returns a copy of the name of @elem. * Caller should g_free() the return value after usage. - * For a nameless element, this returns NULL, which you can safely g_free() + * For a nameless element, this returns %NULL, which you can safely g_free() * as well. * * Returns: (transfer full): the name of @elem. g_free() after usage. MT safe. diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index 49bfec1..aa0c5af 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -27,7 +27,7 @@ * @see_also: #GstElement, #GstPlugin, #GstPluginFeature, #GstPadTemplate. * * #GstElementFactory is used to create instances of elements. A - * GstElementfactory can be added to a #GstPlugin as it is also a + * GstElementFactory can be added to a #GstPlugin as it is also a * #GstPluginFeature. * * Use the gst_element_factory_find() and gst_element_factory_create() @@ -53,8 +53,6 @@ * ... * </programlisting> * </example> - * - * Last reviewed on 2005-11-23 (0.9.5) */ #include "gst_private.h" @@ -125,7 +123,7 @@ gst_element_factory_finalize (GObject * object) * Search for an element factory of the given name. Refs the returned * element factory; caller is responsible for unreffing. * - * Returns: (transfer full): #GstElementFactory if found, NULL otherwise + * Returns: (transfer full): #GstElementFactory if found, %NULL otherwise */ GstElementFactory * gst_element_factory_find (const gchar * name) @@ -188,7 +186,7 @@ gst_element_factory_cleanup (GstElementFactory * factory) /** * gst_element_register: - * @plugin: (allow-none): #GstPlugin to register the element with, or NULL for + * @plugin: (allow-none): #GstPlugin to register the element with, or %NULL for * a static element. * @name: name of elements of this type * @rank: rank of element (higher rank means more importance when autoplugging) @@ -197,7 +195,7 @@ gst_element_factory_cleanup (GstElementFactory * factory) * Create a new elementfactory capable of instantiating objects of the * @type and add the factory to @plugin. * - * Returns: TRUE, if the registering succeeded, FALSE on error + * Returns: %TRUE, if the registering succeeded, %FALSE on error */ gboolean gst_element_register (GstPlugin * plugin, const gchar * name, guint rank, @@ -330,14 +328,14 @@ detailserror: /** * gst_element_factory_create: * @factory: factory to instantiate - * @name: (allow-none): name of new element, or NULL to automatically create + * @name: (allow-none): name of new element, or %NULL to automatically create * a unique name * * Create a new element of the type defined by the given elementfactory. * It will be given the name supplied, since all elements require a name as * their first argument. * - * Returns: (transfer floating): new #GstElement or NULL if the element couldn't + * Returns: (transfer floating): new #GstElement or %NULL if the element couldn't * be created */ GstElement * @@ -416,15 +414,15 @@ no_element: /** * gst_element_factory_make: * @factoryname: a named factory to instantiate - * @name: (allow-none): name of new element, or NULL to automatically create + * @name: (allow-none): name of new element, or %NULL to automatically create * a unique name * * Create a new element of the type defined by the given element factory. - * If name is NULL, then the element will receive a guaranteed unique name, + * If name is %NULL, then the element will receive a guaranteed unique name, * consisting of the element factory name and a number. * If name is given, it will be given the name supplied. * - * Returns: (transfer floating): new #GstElement or NULL if unable to create element + * Returns: (transfer floating): new #GstElement or %NULL if unable to create element */ GstElement * gst_element_factory_make (const gchar * factoryname, const gchar * name) @@ -621,13 +619,13 @@ gst_element_factory_get_uri_type (GstElementFactory * factory) * gst_element_factory_get_uri_protocols: * @factory: a #GstElementFactory * - * Gets a NULL-terminated array of protocols this element supports or NULL if + * Gets a %NULL-terminated array of protocols this element supports or %NULL if * no protocols are supported. You may not change the contents of the returned * array, as it is still owned by the element factory. Use g_strdupv() to * make a copy of the protocol string array if you need to. * * Returns: (transfer none) (array zero-terminated=1): the supported protocols - * or NULL + * or %NULL */ const gchar *const * gst_element_factory_get_uri_protocols (GstElementFactory * factory) @@ -644,7 +642,7 @@ gst_element_factory_get_uri_protocols (GstElementFactory * factory) * * Check if @factory implements the interface with name @interfacename. * - * Returns: #TRUE when @factory implement the interface. + * Returns: %TRUE when @factory implement the interface. */ gboolean gst_element_factory_has_interface (GstElementFactory * factory, @@ -818,7 +816,7 @@ gst_element_factory_list_get_elements (GstElementFactoryListType type, * whose pad templates caps can intersect with @caps will be returned. * * Returns: (transfer full) (element-type Gst.ElementFactory): a #GList of - * #GstElementFactory elements that match the given requisits. + * #GstElementFactory elements that match the given requisites. * Use #gst_plugin_feature_list_free after usage. */ GList * diff --git a/gst/gsterror.c b/gst/gsterror.c index e925689..0cf5285 100644 --- a/gst/gsterror.c +++ b/gst/gsterror.c @@ -23,7 +23,7 @@ * @see_also: #GstMessage * * GStreamer elements can throw non-fatal warnings and fatal errors. - * Higher-level elements and applications can programatically filter + * Higher-level elements and applications can programmatically filter * the ones they are interested in or can recover from, * and have a default handler handle the rest of them. * @@ -80,7 +80,7 @@ * currently provided should be enough. If you find your type of error * does not fit the current codes, you should use FAILED.</para></listitem> * <listitem><para>Don't provide a message if the default one suffices. - * this keeps messages more uniform. Use (NULL) - not forgetting the + * this keeps messages more uniform. Use (%NULL) - not forgetting the * parentheses.</para></listitem> * <listitem><para>If you do supply a custom message, it should be * marked for translation. The message should start with a capital @@ -89,13 +89,11 @@ * A user interface will present this message as the first thing a user * sees. Details, technical info, ... should go in the debug string. * </para></listitem> - * <listitem><para>The debug string can be as you like. Again, use (NULL) + * <listitem><para>The debug string can be as you like. Again, use (%NULL) * if there's nothing to add - file and line number will still be * passed. #GST_ERROR_SYSTEM can be used as a shortcut to give * debug information on a system call error.</para></listitem> * </itemizedlist> - * - * Last reviewed on 2006-09-15 (0.10.10) */ /* FIXME 0.11: the entire error system needs an overhaul - it's not very diff --git a/gst/gstevent.c b/gst/gstevent.c index a26cd9e..2217968 100644 --- a/gst/gstevent.c +++ b/gst/gstevent.c @@ -51,9 +51,7 @@ * construct and use seek events. * To do that gst_event_new_seek() is used to create a seek event. It takes * the needed parameters to specify seeking time and mode. - * <example> - * <title>performing a seek on a pipeline</title> - * <programlisting> + * |[ * GstEvent *event; * gboolean result; * ... @@ -69,10 +67,7 @@ * if (!result) * g_warning ("seek failed"); * ... - * </programlisting> - * </example> - * - * Last reviewed on 2012-03-28 (0.11.3) + * ]| */ @@ -93,6 +88,7 @@ typedef struct GstEvent event; GstStructure *structure; + gint64 running_time_offset; } GstEventImpl; #define GST_EVENT_STRUCTURE(e) (((GstEventImpl *)(e))->structure) @@ -254,6 +250,10 @@ _gst_event_copy (GstEvent * event) } else { GST_EVENT_STRUCTURE (copy) = NULL; } + + ((GstEventImpl *) copy)->running_time_offset = + ((GstEventImpl *) event)->running_time_offset; + return GST_EVENT_CAST (copy); } @@ -267,6 +267,7 @@ gst_event_init (GstEventImpl * event, GstEventType type) GST_EVENT_TYPE (event) = type; GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE; GST_EVENT_SEQNUM (event) = gst_util_seqnum_next (); + event->running_time_offset = 0; } @@ -347,10 +348,11 @@ gst_event_get_structure (GstEvent * event) * * Get a writable version of the structure. * - * Returns: The structure of the event. The structure is still - * owned by the event, which means that you should not free it and - * that the pointer becomes invalid when you free the event. - * This function checks if @event is writable and will never return NULL. + * Returns: (transfer none): The structure of the event. The structure + * is still owned by the event, which means that you should not free + * it and that the pointer becomes invalid when you free the event. + * This function checks if @event is writable and will never return + * %NULL. * * MT safe. */ @@ -446,6 +448,54 @@ gst_event_set_seqnum (GstEvent * event, guint32 seqnum) } /** + * gst_event_get_running_time_offset: + * @event: A #GstEvent. + * + * Retrieve the accumulated running time offset of the event. + * + * Events passing through #GstPads that have a running time + * offset set via gst_pad_set_offset() will get their offset + * adjusted according to the pad's offset. + * + * If the event contains any information that related to the + * running time, this information will need to be updated + * before usage with this offset. + * + * Returns: The event's running time offset + * + * MT safe. + * + * Since: 1.4 + */ +gint64 +gst_event_get_running_time_offset (GstEvent * event) +{ + g_return_val_if_fail (GST_IS_EVENT (event), 0); + + return ((GstEventImpl *) event)->running_time_offset; +} + +/** + * gst_event_set_running_time_offset: + * @event: A #GstEvent. + * @offset: A the new running time offset + * + * Set the running time offset of a event. See + * gst_event_get_running_time_offset() for more information. + * + * MT safe. + * + * Since: 1.4 + */ +void +gst_event_set_running_time_offset (GstEvent * event, gint64 offset) +{ + g_return_if_fail (GST_IS_EVENT (event)); + + ((GstEventImpl *) event)->running_time_offset = offset; +} + +/** * gst_event_new_flush_start: * * Allocate a new flush start event. The flush start event can be sent @@ -481,7 +531,7 @@ gst_event_new_flush_start (void) * pads accept data again. * * Elements can process this event synchronized with the dataflow since - * the preceeding FLUSH_START event stopped the dataflow. + * the preceding FLUSH_START event stopped the dataflow. * * This event is typically generated to complete a seek and to resume * dataflow. @@ -934,7 +984,7 @@ gst_event_parse_buffer_size (GstEvent * event, GstFormat * format, * increasing value. * * The upstream element can use the @diff and @timestamp values to decide - * whether to process more buffers. For possitive @diff, all buffers with + * whether to process more buffers. For positive @diff, all buffers with * timestamp <= @timestamp + @diff will certainly arrive late in the sink * as well. A (negative) @diff value so that @timestamp + @diff would yield a * result smaller than 0 is not allowed. @@ -979,6 +1029,8 @@ gst_event_new_qos (GstQOSType type, gdouble proportion, * * Get the type, proportion, diff and timestamp in the qos event. See * gst_event_new_qos() for more information about the different QoS values. + * + * @timestamp will be adjusted for any pad offsets of pads it was passing through. */ void gst_event_parse_qos (GstEvent * event, GstQOSType * type, @@ -1002,10 +1054,18 @@ gst_event_parse_qos (GstEvent * event, GstQOSType * type, *diff = g_value_get_int64 (gst_structure_id_get_value (structure, GST_QUARK (DIFF))); - if (timestamp) + if (timestamp) { + gint64 offset = gst_event_get_running_time_offset (event); + *timestamp = g_value_get_uint64 (gst_structure_id_get_value (structure, GST_QUARK (TIMESTAMP))); + /* Catch underflows */ + if (*timestamp > -offset) + *timestamp += offset; + else + *timestamp = 0; + } } /** @@ -1097,9 +1157,9 @@ gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags, * @format: (out): result location for the stream format * @flags: (out): result location for the #GstSeekFlags * @start_type: (out): result location for the #GstSeekType of the start position - * @start: (out): result location for the start postion expressed in @format + * @start: (out): result location for the start position expressed in @format * @stop_type: (out): result location for the #GstSeekType of the stop position - * @stop: (out): result location for the stop postion expressed in @format + * @stop: (out): result location for the stop position expressed in @format * * Parses a seek @event and stores the results in the given result locations. */ @@ -1298,7 +1358,7 @@ gst_event_parse_step (GstEvent * event, GstFormat * format, guint64 * amount, /** * gst_event_new_reconfigure: - * Create a new reconfigure event. The purpose of the reconfingure event is + * Create a new reconfigure event. The purpose of the reconfigure event is * to travel upstream and make elements renegotiate their caps or reconfigure * their buffer pools. This is useful when changing properties on elements * or changing the topology of the pipeline. @@ -1660,8 +1720,8 @@ gst_event_new_segment_done (GstFormat format, gint64 position) /** * gst_event_parse_segment_done: * @event: A valid #GstEvent of type GST_EVENT_SEGMENT_DONE. - * @format: (out) (allow-none): Result location for the format, or NULL - * @position: (out) (allow-none): Result location for the position, or NULL + * @format: (out) (allow-none): Result location for the format, or %NULL + * @position: (out) (allow-none): Result location for the position, or %NULL * * Extracts the position and format from the segment done message. * diff --git a/gst/gstevent.h b/gst/gstevent.h index 0d1f58d..2ee38eb 100644 --- a/gst/gstevent.h +++ b/gst/gstevent.h @@ -285,9 +285,9 @@ GST_EXPORT GType _gst_event_type; * in some cases), and the reference counts are updated appropriately (the old * event is unreffed, the new one is reffed). * - * Either @new_event or the #GstEvent pointed to by @old_event may be NULL. + * Either @new_event or the #GstEvent pointed to by @old_event may be %NULL. * - * Returns: TRUE if @new_event was different from @old_event + * Returns: %TRUE if @new_event was different from @old_event */ #ifdef _FOOL_GTK_DOC_ G_INLINE_FUNC gboolean gst_event_replace (GstEvent **old_event, GstEvent *new_event); @@ -304,7 +304,7 @@ gst_event_replace (GstEvent **old_event, GstEvent *new_event) * @old_event: (inout) (transfer full): pointer to a pointer to a #GstEvent * to be stolen. * - * Atomically replace the #GstEvent pointed to by @old_event with NULL and + * Atomically replace the #GstEvent pointed to by @old_event with %NULL and * return the original event. * * Returns: the #GstEvent that was in @old_event @@ -330,9 +330,9 @@ gst_event_steal (GstEvent **old_event) * function is similar to gst_event_replace() except that it takes ownership of * @new_event. * - * Either @new_event or the #GstEvent pointed to by @old_event may be NULL. + * Either @new_event or the #GstEvent pointed to by @old_event may be %NULL. * - * Returns: TRUE if @new_event was different from @old_event + * Returns: %TRUE if @new_event was different from @old_event */ #ifdef _FOOL_GTK_DOC_ G_INLINE_FUNC gboolean gst_event_take (GstEvent **old_event, GstEvent *new_event); @@ -482,6 +482,10 @@ gboolean gst_event_has_name (GstEvent *event, const gchar *n guint32 gst_event_get_seqnum (GstEvent *event); void gst_event_set_seqnum (GstEvent *event, guint32 seqnum); +/* accumulated pad offsets for the event */ +gint64 gst_event_get_running_time_offset (GstEvent *event); +void gst_event_set_running_time_offset (GstEvent *event, gint64 offset); + /* Stream start event */ GstEvent * gst_event_new_stream_start (const gchar *stream_id) G_GNUC_MALLOC; void gst_event_parse_stream_start (GstEvent *event, const gchar **stream_id); diff --git a/gst/gstformat.c b/gst/gstformat.c index 311b4bd..69600cd 100644 --- a/gst/gstformat.c +++ b/gst/gstformat.c @@ -85,7 +85,7 @@ _priv_gst_format_initialize (void) * * Get a printable name for the given format. Do not modify or free. * - * Returns: a reference to the static name of the format or NULL if + * Returns: a reference to the static name of the format or %NULL if * the format is unknown. */ const gchar * @@ -201,7 +201,7 @@ gst_format_get_by_nick (const gchar * nick) * * See if the given format is inside the format array. * - * Returns: TRUE if the format is found inside the array + * Returns: %TRUE if the format is found inside the array */ gboolean gst_formats_contains (const GstFormat * formats, GstFormat format) @@ -225,7 +225,7 @@ gst_formats_contains (const GstFormat * formats, GstFormat format) * * Get details about the given format. * - * Returns: The #GstFormatDefinition for @format or NULL on failure. + * Returns: The #GstFormatDefinition for @format or %NULL on failure. * * MT safe. */ diff --git a/gst/gstghostpad.c b/gst/gstghostpad.c index f6952cb..cac0d51 100644 --- a/gst/gstghostpad.c +++ b/gst/gstghostpad.c @@ -40,8 +40,6 @@ * association later on. * * Note that GhostPads add overhead to the data processing of a pipeline. - * - * Last reviewed on 2005-11-18 (0.9.5) */ #include "gst_private.h" @@ -77,11 +75,11 @@ static GstPad *gst_proxy_pad_get_target (GstPad * pad); /** * gst_proxy_pad_iterate_internal_links_default: * @pad: the #GstPad to get the internal links of. - * @parent: (allow-none): the parent of @pad or NULL + * @parent: (allow-none): the parent of @pad or %NULL * * Invoke the default iterate internal links function of the proxy pad. * - * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each + * Returns: a #GstIterator of #GstPad, or %NULL if @pad has no parent. Unref each * returned pad with gst_object_unref(). */ GstIterator * @@ -106,7 +104,7 @@ gst_proxy_pad_iterate_internal_links_default (GstPad * pad, GstObject * parent) /** * gst_proxy_pad_chain_default: * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. - * @parent: (allow-none): the parent of @pad or NULL + * @parent: (allow-none): the parent of @pad or %NULL * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR * if not. * @@ -134,7 +132,7 @@ gst_proxy_pad_chain_default (GstPad * pad, GstObject * parent, /** * gst_proxy_pad_chain_list_default: * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. - * @parent: (allow-none): the parent of @pad or NULL + * @parent: (allow-none): the parent of @pad or %NULL * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR * if not. * @@ -210,7 +208,7 @@ gst_proxy_pad_get_target (GstPad * pad) * The internal pad of a #GstGhostPad is the internally used * pad of opposite direction, which is used to link to the target. * - * Returns: (transfer full): the target #GstProxyPad, can be NULL. + * Returns: (transfer full): the target #GstProxyPad, can be %NULL. * Unref target pad after usage. */ GstProxyPad * @@ -332,7 +330,7 @@ gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent, /** * gst_ghost_pad_internal_activate_mode_default: * @pad: the #GstPad to activate or deactivate. - * @parent: (allow-none): the parent of @pad or NULL + * @parent: (allow-none): the parent of @pad or %NULL * @mode: the requested activation mode * @active: whether the pad should be active or not. * @@ -420,7 +418,7 @@ gst_ghost_pad_activate_pull_default (GstPad * pad, GstObject * parent, /** * gst_ghost_pad_activate_mode_default: * @pad: the #GstPad to activate or deactivate. - * @parent: (allow-none): the parent of @pad or NULL + * @parent: (allow-none): the parent of @pad or %NULL * @mode: the requested activation mode * @active: whether the pad should be active or not. * @@ -646,7 +644,7 @@ construct_failed: /** * gst_ghost_pad_new_no_target: - * @name: (allow-none): the name of the new pad, or NULL to assign a default name. + * @name: (allow-none): the name of the new pad, or %NULL to assign a default name. * @dir: the direction of the ghostpad * * Create a new ghostpad without a target with the given direction. @@ -655,7 +653,7 @@ construct_failed: * * The created ghostpad will not have a padtemplate. * - * Returns: (transfer full): a new #GstPad, or NULL in case of an error. + * Returns: (transfer full): a new #GstPad, or %NULL in case of an error. */ GstPad * gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir) @@ -673,7 +671,7 @@ gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir) /** * gst_ghost_pad_new: - * @name: (allow-none): the name of the new pad, or NULL to assign a default name + * @name: (allow-none): the name of the new pad, or %NULL to assign a default name * @target: (transfer none): the pad to ghost. * * Create a new ghostpad with @target as the target. The direction will be taken @@ -681,7 +679,7 @@ gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir) * * Will ref the target. * - * Returns: (transfer floating): a new #GstPad, or NULL in case of an error. + * Returns: (transfer floating): a new #GstPad, or %NULL in case of an error. */ GstPad * gst_ghost_pad_new (const gchar * name, GstPad * target) @@ -712,7 +710,7 @@ set_target_failed: /** * gst_ghost_pad_new_from_template: - * @name: (allow-none): the name of the new pad, or NULL to assign a default name. + * @name: (allow-none): the name of the new pad, or %NULL to assign a default name. * @target: (transfer none): the pad to ghost. * @templ: (transfer none): the #GstPadTemplate to use on the ghostpad. * @@ -721,7 +719,7 @@ set_target_failed: * * Will ref the target. * - * Returns: (transfer full): a new #GstPad, or NULL in case of an error. + * Returns: (transfer full): a new #GstPad, or %NULL in case of an error. */ GstPad * @@ -757,13 +755,13 @@ set_target_failed: /** * gst_ghost_pad_new_no_target_from_template: - * @name: (allow-none): the name of the new pad, or NULL to assign a default name + * @name: (allow-none): the name of the new pad, or %NULL to assign a default name * @templ: (transfer none): the #GstPadTemplate to create the ghostpad from. * * Create a new ghostpad based on @templ, without setting a target. The * direction will be taken from the @templ. * - * Returns: (transfer full): a new #GstPad, or NULL in case of an error. + * Returns: (transfer full): a new #GstPad, or %NULL in case of an error. */ GstPad * gst_ghost_pad_new_no_target_from_template (const gchar * name, @@ -785,7 +783,7 @@ gst_ghost_pad_new_no_target_from_template (const gchar * name, * * Get the target pad of @gpad. Unref target pad after usage. * - * Returns: (transfer full): the target #GstPad, can be NULL if the ghostpad + * Returns: (transfer full): the target #GstPad, can be %NULL if the ghostpad * has no target set. Unref target pad after usage. */ GstPad * @@ -809,10 +807,10 @@ gst_ghost_pad_get_target (GstGhostPad * gpad) * * Set the new target of the ghostpad @gpad. Any existing target * is unlinked and links to the new target are established. if @newtarget is - * NULL the target will be cleared. + * %NULL the target will be cleared. * - * Returns: (transfer full): TRUE if the new target could be set. This function - * can return FALSE when the internal pads could not be linked. + * Returns: (transfer full): %TRUE if the new target could be set. This function + * can return %FALSE when the internal pads could not be linked. */ gboolean gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget) @@ -869,8 +867,8 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget) /* ERRORS */ link_failed: { - GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%d", - lret); + GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%s", + gst_pad_link_get_name (lret)); return FALSE; } } diff --git a/gst/gstglobaldevicemonitor.c b/gst/gstglobaldevicemonitor.c new file mode 100644 index 0000000..68900ef --- /dev/null +++ b/gst/gstglobaldevicemonitor.c @@ -0,0 +1,501 @@ +/* GStreamer + * Copyright (C) 2013 Olivier Crete <olivier.crete@collabora.com> + * + * gstglobaldevicemonitor.c: Global device monitor + * + * 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. + */ + +/** + * SECTION:gstglobaldevicemonitor + * @short_description: A global device monitor and prober + * @see_also: #GstDevice, #GstDeviceMonitor + * + * Applications should create a #GstGlobalDeviceMonitor when they want + * to probe, list and monitor devices of a specific type. The + * #GstGlobalDeviceMonitor will create the appropriate + * #GstDeviceMonitor objects and manage them. It will then post + * messages on its #GstBus for devices that have been added and + * removed. + * + * Since: 1.4 + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst_private.h" +#include "gstglobaldevicemonitor.h" + +struct _GstGlobalDeviceMonitorPrivate +{ + gboolean started; + + GstBus *bus; + + GPtrArray *monitors; + guint cookie; + + GstCaps *caps; + gchar *classes; +}; + + +G_DEFINE_TYPE (GstGlobalDeviceMonitor, gst_global_device_monitor, + GST_TYPE_OBJECT); + +static void gst_global_device_monitor_dispose (GObject * object); + +static void +gst_global_device_monitor_class_init (GstGlobalDeviceMonitorClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GstGlobalDeviceMonitorPrivate)); + + object_class->dispose = gst_global_device_monitor_dispose; +} + +static void +bus_sync_message (GstBus * bus, GstMessage * message, + GstGlobalDeviceMonitor * monitor) +{ + GstMessageType type = GST_MESSAGE_TYPE (message); + + if (type == GST_MESSAGE_DEVICE_ADDED || type == GST_MESSAGE_DEVICE_REMOVED) { + gboolean matches; + GstCaps *caps; + GstDevice *device; + + if (type == GST_MESSAGE_DEVICE_ADDED) + gst_message_parse_device_added (message, &device); + else + gst_message_parse_device_removed (message, &device); + + GST_OBJECT_LOCK (monitor); + caps = gst_device_get_caps (device); + matches = gst_caps_can_intersect (monitor->priv->caps, caps) && + gst_device_has_classes (device, monitor->priv->classes); + gst_caps_unref (caps); + GST_OBJECT_UNLOCK (monitor); + + if (matches) + gst_bus_post (monitor->priv->bus, gst_message_ref (message)); + } +} + + +static void +gst_global_device_monitor_init (GstGlobalDeviceMonitor * self) +{ + GList *factories; + + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + GST_TYPE_GLOBAL_DEVICE_MONITOR, GstGlobalDeviceMonitorPrivate); + + self->priv->bus = gst_bus_new (); + gst_bus_set_flushing (self->priv->bus, TRUE); + + self->priv->monitors = g_ptr_array_new (); + self->priv->caps = gst_caps_new_any (); + self->priv->classes = g_strdup (""); + + factories = + gst_device_monitor_factory_list_get_device_monitors (self->priv->classes, + 1); + + while (factories) { + GstDeviceMonitorFactory *factory = factories->data; + GstDeviceMonitor *monitor; + + factories = g_list_remove (factories, factory); + + monitor = gst_device_monitor_factory_get (factory); + if (monitor) { + GstBus *bus = gst_device_monitor_get_bus (monitor); + + gst_bus_enable_sync_message_emission (bus); + g_signal_connect (bus, "sync-message", + G_CALLBACK (bus_sync_message), self); + g_ptr_array_add (self->priv->monitors, monitor); + } + + gst_object_unref (factory); + } +} + + +static void +gst_global_device_monitor_remove (GstGlobalDeviceMonitor * self, guint i) +{ + GstDeviceMonitor *monitor = g_ptr_array_index (self->priv->monitors, i); + GstBus *bus; + + g_ptr_array_remove_index_fast (self->priv->monitors, i); + + bus = gst_device_monitor_get_bus (monitor); + g_signal_handlers_disconnect_by_func (bus, bus_sync_message, self); + gst_object_unref (bus); + + gst_object_unref (monitor); +} + +static void +gst_global_device_monitor_dispose (GObject * object) +{ + GstGlobalDeviceMonitor *self = GST_GLOBAL_DEVICE_MONITOR (object); + + g_return_if_fail (self->priv->started == FALSE); + + if (self->priv->monitors) { + while (self->priv->monitors->len) + gst_global_device_monitor_remove (self, self->priv->monitors->len - 1); + g_ptr_array_unref (self->priv->monitors); + self->priv->monitors = NULL; + } + + gst_caps_replace (&self->priv->caps, NULL); + g_free (self->priv->classes); + gst_object_replace ((GstObject **) & self->priv->bus, NULL); + + G_OBJECT_CLASS (gst_global_device_monitor_parent_class)->dispose (object); +} + +/** + * gst_global_device_monitor_get_devices: + * @monitor: A #GstDeviceMonitor + * + * Gets a list of devices from all of the relevant monitors. This may actually + * probe the hardware if the global monitor is not currently started. + * + * Returns: (transfer full) (element-type GstDevice): a #GList of + * #GstDevice + * + * Since: 1.4 + */ + +GList * +gst_global_device_monitor_get_devices (GstGlobalDeviceMonitor * monitor) +{ + GList *devices = NULL; + guint i; + guint cookie; + + g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), NULL); + + GST_OBJECT_LOCK (monitor); + +again: + + g_list_free_full (devices, gst_object_unref); + devices = NULL; + + cookie = monitor->priv->cookie; + + for (i = 0; i < monitor->priv->monitors->len; i++) { + GList *tmpdev; + GstDeviceMonitor *device_monitor = + gst_object_ref (g_ptr_array_index (monitor->priv->monitors, i)); + GList *item; + + GST_OBJECT_UNLOCK (monitor); + + tmpdev = gst_device_monitor_get_devices (device_monitor); + + for (item = tmpdev; item; item = item->next) { + GstDevice *dev = GST_DEVICE (item->data); + GstCaps *caps = gst_device_get_caps (dev); + + if (gst_caps_can_intersect (monitor->priv->caps, caps) && + gst_device_has_classes (dev, monitor->priv->classes)) + devices = g_list_prepend (devices, gst_object_ref (dev)); + gst_caps_unref (caps); + } + + g_list_free_full (tmpdev, gst_object_unref); + gst_object_unref (device_monitor); + + GST_OBJECT_LOCK (monitor); + + if (monitor->priv->cookie != cookie) + goto again; + } + + GST_OBJECT_UNLOCK (monitor); + + return devices; +} + +/** + * gst_global_device_monitor_start: + * @monitor: A #GstGlobalDeviceMonitor + * + * Starts monitoring the devices, one this has succeeded, the + * %GST_MESSAGE_DEVICE_ADDED and %GST_MESSAGE_DEVICE_REMOVED messages + * will be emitted on the bus when the list of devices changes. + * + * Returns: %TRUE if the device monitoring could be started + * + * Since: 1.4 + */ + +gboolean +gst_global_device_monitor_start (GstGlobalDeviceMonitor * monitor) +{ + guint i; + + g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), FALSE); + + GST_OBJECT_LOCK (monitor); + + if (monitor->priv->monitors->len == 0) { + GST_OBJECT_UNLOCK (monitor); + return FALSE; + } + + gst_bus_set_flushing (monitor->priv->bus, FALSE); + + for (i = 0; i < monitor->priv->monitors->len; i++) { + if (!gst_device_monitor_start (g_ptr_array_index (monitor->priv->monitors, + i))) { + gst_bus_set_flushing (monitor->priv->bus, TRUE); + + for (; i != 0; i--) + gst_device_monitor_stop (g_ptr_array_index (monitor->priv->monitors, + i - 1)); + + GST_OBJECT_UNLOCK (monitor); + return FALSE; + } + } + + monitor->priv->started = TRUE; + GST_OBJECT_UNLOCK (monitor); + + return TRUE; +} + +/** + * gst_global_device_monitor_stop: + * @monitor: A #GstDeviceMonitor + * + * Stops monitoring the devices. + * + * Since: 1.4 + */ +void +gst_global_device_monitor_stop (GstGlobalDeviceMonitor * monitor) +{ + guint i; + + g_return_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor)); + + gst_bus_set_flushing (monitor->priv->bus, TRUE); + + GST_OBJECT_LOCK (monitor); + for (i = 0; i < monitor->priv->monitors->len; i++) + gst_device_monitor_stop (g_ptr_array_index (monitor->priv->monitors, i)); + monitor->priv->started = FALSE; + GST_OBJECT_UNLOCK (monitor); + +} + +/** + * gst_global_device_monitor_set_classes_filter: + * @monitor: the global device monitor + * @classes: device classes to use as filter + * + * Filter devices monitored by device class, e.g. in case you are only + * interested in a certain type of device like audio devices or + * video sources. + * + * Since: 1.4 + */ +void +gst_global_device_monitor_set_classes_filter (GstGlobalDeviceMonitor * monitor, + const gchar * classes) +{ + GList *factories = NULL; + guint i; + + g_return_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor)); + g_return_if_fail (!monitor->priv->started); + + GST_OBJECT_LOCK (monitor); + if (!strcmp (monitor->priv->classes, classes)) { + GST_OBJECT_UNLOCK (monitor); + return; + } + + g_free (monitor->priv->classes); + monitor->priv->classes = g_strdup (classes); + + factories = gst_device_monitor_factory_list_get_device_monitors (classes, 1); + + for (i = 0; i < monitor->priv->monitors->len; i++) { + GstDeviceMonitor *dev_monitor; + GstDeviceMonitorFactory *f; + GList *item; + + dev_monitor = g_ptr_array_index (monitor->priv->monitors, i); + f = gst_device_monitor_get_factory (dev_monitor); + + item = g_list_find (factories, f); + + if (item) { + /* If the item is in our list, then remove it from the list of factories, + * we don't have it to re-create it later + */ + factories = g_list_remove_link (factories, item); + gst_object_unref (f); + } else { + /* If it's not in our list, them remove it from the list of monitors. + */ + + monitor->priv->cookie++; + gst_global_device_monitor_remove (monitor, i); + i--; + } + } + + while (factories) { + GstDeviceMonitorFactory *factory = factories->data; + GstDeviceMonitor *device_monitor; + + factories = g_list_remove (factories, factory); + + device_monitor = gst_device_monitor_factory_get (factory); + if (device_monitor) { + GstBus *bus = gst_device_monitor_get_bus (device_monitor); + + gst_bus_enable_sync_message_emission (bus); + g_signal_connect (bus, "sync-message", + G_CALLBACK (bus_sync_message), monitor); + gst_object_unref (bus); + g_ptr_array_add (monitor->priv->monitors, device_monitor); + monitor->priv->cookie++; + } + + gst_object_unref (factory); + } + + GST_OBJECT_UNLOCK (monitor); +} + +/** + * gst_global_device_monitor_get_classes_filter: + * @monitor: the global device monitor + * + * Return the type (device classes) filter active for device filtering. + * + * Returns: string of device classes that are being filtered. + * + * Since: 1.4 + */ +gchar * +gst_global_device_monitor_get_classes_filter (GstGlobalDeviceMonitor * monitor) +{ + gchar *res; + + g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), 0); + + GST_OBJECT_LOCK (monitor); + res = g_strdup (monitor->priv->classes); + GST_OBJECT_UNLOCK (monitor); + + return res; +} + +/** + * gst_global_device_monitor_set_caps_filter: + * @monitor: the global device monitor + * @caps: caps to filter + * + * Set caps to use as filter for devices. By default ANY caps are used, + * meaning no caps filter is active. + * + * Since: 1.4 + */ +void +gst_global_device_monitor_set_caps_filter (GstGlobalDeviceMonitor * monitor, + GstCaps * caps) +{ + g_return_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor)); + g_return_if_fail (GST_IS_CAPS (caps)); + + GST_OBJECT_LOCK (monitor); + gst_caps_replace (&monitor->priv->caps, caps); + GST_OBJECT_UNLOCK (monitor); +} + +/** + * gst_global_device_monitor_get_caps_filter: + * @monitor: a global device monitor + * + * Get the #GstCaps filter set by gst_global_device_monitor_set_caps_filter(). + * + * Returns: (transfer full): the filter caps that are active (or ANY caps) + * + * Since: 1.4 + */ +GstCaps * +gst_global_device_monitor_get_caps_filter (GstGlobalDeviceMonitor * monitor) +{ + GstCaps *res; + + g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), NULL); + + GST_OBJECT_LOCK (monitor); + res = gst_caps_ref (monitor->priv->caps); + GST_OBJECT_UNLOCK (monitor); + + return res; +} + +/** + * gst_global_device_monitor_new: + * + * Create a new #GstGlobalDeviceMonitor + * + * Returns: (transfer full): a new global device monitor. + * + * Since: 1.4 + */ +GstGlobalDeviceMonitor * +gst_global_device_monitor_new (void) +{ + return g_object_new (GST_TYPE_GLOBAL_DEVICE_MONITOR, NULL); +} + +/** + * gst_global_device_monitor_get_bus: + * @monitor: a #GstDeviceMonitor + * + * Gets the #GstBus of this #GstGlobalDeviceMonitor + * + * Returns: (transfer full): a #GstBus + * + * Since: 1.4 + */ +GstBus * +gst_global_device_monitor_get_bus (GstGlobalDeviceMonitor * monitor) +{ + g_return_val_if_fail (GST_IS_GLOBAL_DEVICE_MONITOR (monitor), NULL); + + return gst_object_ref (monitor->priv->bus); +} diff --git a/gst/gstglobaldevicemonitor.h b/gst/gstglobaldevicemonitor.h new file mode 100644 index 0000000..b92fd40 --- /dev/null +++ b/gst/gstglobaldevicemonitor.h @@ -0,0 +1,105 @@ +/* GStreamer + * Copyright (C) 2013 Olivier Crete <olivier.crete@collabora.com> + * + * gstglobaldevicemonitor.c: Global device monitor + * + * 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_GLOBAL_DEVICE_MONITOR_H__ +#define __GST_GLOBAL_DEVICE_MONITOR_H__ + +#include <gst/gstobject.h> +#include <gst/gstdevice.h> +#include <gst/gstdevicemonitor.h> +#include <gst/gstdevicemonitorfactory.h> + +G_BEGIN_DECLS + +typedef struct _GstGlobalDeviceMonitor GstGlobalDeviceMonitor; +typedef struct _GstGlobalDeviceMonitorPrivate GstGlobalDeviceMonitorPrivate; +typedef struct _GstGlobalDeviceMonitorClass GstGlobalDeviceMonitorClass; + +#define GST_TYPE_GLOBAL_DEVICE_MONITOR (gst_global_device_monitor_get_type()) +#define GST_IS_GLOBAL_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GLOBAL_DEVICE_MONITOR)) +#define GST_IS_GLOBAL_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GLOBAL_DEVICE_MONITOR)) +#define GST_GLOBAL_DEVICE_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GLOBAL_DEVICE_MONITOR, GstGlobalDeviceMonitorClass)) +#define GST_GLOBAL_DEVICE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GLOBAL_DEVICE_MONITOR, GstGlobalDeviceMonitor)) +#define GST_GLOBAL_DEVICE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GLOBAL_DEVICE_MONITOR, GstGlobalDeviceMonitorClass)) +#define GST_GLOBAL_DEVICE_MONITOR_CAST(obj) ((GstGlobalDeviceMonitor *)(obj)) + +/** + * GstGlobalDeviceMonitor: + * @parent: the parent #GstObject structure + * + * Opaque global device monitor object structure. + * + * Since: 1.4 + */ +struct _GstGlobalDeviceMonitor { + GstObject parent; + + /*< private >*/ + + GstGlobalDeviceMonitorPrivate *priv; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstGlobalDeviceMonitorClass: + * @parent_class: the parent #GstObjectClass structure + * + * Opaque global device monitor class structure. + * + * Since: 1.4 + */ +struct _GstGlobalDeviceMonitorClass { + GstObjectClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_global_device_monitor_get_type (void); + +GstGlobalDeviceMonitor * gst_global_device_monitor_new (void); + +GstBus * gst_global_device_monitor_get_bus (GstGlobalDeviceMonitor * monitor); + +GList * gst_global_device_monitor_get_devices (GstGlobalDeviceMonitor * monitor); + + +gboolean gst_global_device_monitor_start (GstGlobalDeviceMonitor * monitor); + +void gst_global_device_monitor_stop (GstGlobalDeviceMonitor * monitor); + + +void gst_global_device_monitor_set_classes_filter (GstGlobalDeviceMonitor * monitor, + const gchar * classes); + +gchar * gst_global_device_monitor_get_classes_filter (GstGlobalDeviceMonitor * monitor); + + +void gst_global_device_monitor_set_caps_filter (GstGlobalDeviceMonitor * monitor, + GstCaps * caps); + +GstCaps * gst_global_device_monitor_get_caps_filter (GstGlobalDeviceMonitor * monitor); + +G_END_DECLS + +#endif /* __GST_GLOBAL_DEVICE_MONITOR_H__ */ diff --git a/gst/gstinfo.c b/gst/gstinfo.c index 5501217..3f56686 100644 --- a/gst/gstinfo.c +++ b/gst/gstinfo.c @@ -50,19 +50,15 @@ * categories. This is easily done with 3 lines. At the top of your code, * declare * the variables and set the default category. - * <informalexample> - * <programlisting> - * GST_DEBUG_CATEGORY_STATIC (my_category); // define category (statically) - * &hash;define GST_CAT_DEFAULT my_category // set as default - * </programlisting> - * </informalexample> + * |[ + * GST_DEBUG_CATEGORY_STATIC (my_category); // define category (statically) + * #define GST_CAT_DEFAULT my_category // set as default + * ]| * After that you only need to initialize the category. - * <informalexample> - * <programlisting> - * GST_DEBUG_CATEGORY_INIT (my_category, "my category", - * 0, "This is my very own"); - * </programlisting> - * </informalexample> + * |[ + * GST_DEBUG_CATEGORY_INIT (my_category, "my category", + * 0, "This is my very own"); + * ]| * Initialization must be done before the category is used first. * Plugins do this * in their plugin_init function, libraries and applications should do that @@ -248,6 +244,9 @@ LevelNameEntry; static GMutex __cat_mutex; static GSList *__categories = NULL; +static GstDebugCategory *_gst_debug_get_category_locked (const gchar * name); + + /* all registered debug handlers */ typedef struct { @@ -406,6 +405,17 @@ _priv_gst_debug_init (void) else if (strstr (env, "pretty_tags") || strstr (env, "pretty-tags")) pretty_tags = TRUE; } + + if (g_getenv ("GST_DEBUG_NO_COLOR") != NULL) + gst_debug_set_color_mode (GST_DEBUG_COLOR_MODE_OFF); + env = g_getenv ("GST_DEBUG_COLOR_MODE"); + if (env) + gst_debug_set_color_mode_from_string (env); + + env = g_getenv ("GST_DEBUG"); + if (env) { + gst_debug_set_threshold_from_string (env, FALSE); + } } /* we can't do this further above, because we initialize the GST_CAT_DEFAULT struct */ @@ -419,7 +429,7 @@ _priv_gst_debug_init (void) * @function: the function that emitted the message * @line: the line from that the message was emitted, usually __LINE__ * @object: (transfer none) (allow-none): the object this message relates to, - * or NULL if none + * or %NULL if none * @format: a printf style format string * @...: optional arguments for the format * @@ -471,7 +481,7 @@ gst_path_basename (const gchar * file_name) * @function: the function that emitted the message * @line: the line from that the message was emitted, usually __LINE__ * @object: (transfer none) (allow-none): the object this message relates to, - * or NULL if none + * or %NULL if none * @format: a printf style format string * @args: optional arguments for the format * @@ -562,7 +572,7 @@ prettify_structure_string (gchar * str) if (count > MAX_BUFFER_DUMP_STRING_LEN) { memcpy (pos + MAX_BUFFER_DUMP_STRING_LEN - 6, "..", 2); memcpy (pos + MAX_BUFFER_DUMP_STRING_LEN - 4, pos + count - 4, 4); - g_memmove (pos + MAX_BUFFER_DUMP_STRING_LEN, pos + count, + memmove (pos + MAX_BUFFER_DUMP_STRING_LEN, pos + count, strlen (pos + count) + 1); pos += MAX_BUFFER_DUMP_STRING_LEN; } @@ -661,16 +671,16 @@ gst_debug_print_object (gpointer ptr) if (object == NULL) { return g_strdup ("(NULL)"); } - if (*(GType *) ptr == GST_TYPE_CAPS) { + if (GST_IS_CAPS (ptr)) { return gst_caps_to_string ((const GstCaps *) ptr); } - if (*(GType *) ptr == GST_TYPE_STRUCTURE) { + if (GST_IS_STRUCTURE (ptr)) { return gst_info_structure_to_string ((const GstStructure *) ptr); } if (*(GType *) ptr == GST_TYPE_CAPS_FEATURES) { return gst_caps_features_to_string ((const GstCapsFeatures *) ptr); } - if (*(GType *) ptr == GST_TYPE_TAG_LIST) { + if (GST_IS_TAG_LIST (ptr)) { gchar *str = gst_tag_list_to_string ((GstTagList *) ptr); if (G_UNLIKELY (pretty_tags)) return prettify_structure_string (str); @@ -688,15 +698,6 @@ gst_debug_print_object (gpointer ptr) return g_strdup_printf ("<poisoned@%p>", ptr); } #endif - if (GST_IS_PAD (object) && GST_OBJECT_NAME (object)) { - return g_strdup_printf ("<%s:%s>", GST_DEBUG_PAD_NAME (object)); - } - if (GST_IS_OBJECT (object) && GST_OBJECT_NAME (object)) { - return g_strdup_printf ("<%s>", GST_OBJECT_NAME (object)); - } - if (G_IS_OBJECT (object)) { - return g_strdup_printf ("<%s@%p>", G_OBJECT_TYPE_NAME (object), object); - } if (GST_IS_MESSAGE (object)) { return gst_info_describe_message (GST_MESSAGE_CAST (object)); } @@ -721,6 +722,15 @@ gst_debug_print_object (gpointer ptr) g_free (s); return ret; } + if (GST_IS_PAD (object) && GST_OBJECT_NAME (object)) { + return g_strdup_printf ("<%s:%s>", GST_DEBUG_PAD_NAME (object)); + } + if (GST_IS_OBJECT (object) && GST_OBJECT_NAME (object)) { + return g_strdup_printf ("<%s>", GST_OBJECT_NAME (object)); + } + if (G_IS_OBJECT (object)) { + return g_strdup_printf ("<%s@%p>", G_OBJECT_TYPE_NAME (object), object); + } return g_strdup_printf ("%p", ptr); } @@ -741,10 +751,11 @@ gst_debug_print_segment (gpointer ptr) } case GST_FORMAT_TIME:{ return g_strdup_printf ("time segment start=%" GST_TIME_FORMAT - ", stop=%" GST_TIME_FORMAT ", rate=%f, applied_rate=%f" - ", flags=0x%02x, time=%" GST_TIME_FORMAT ", base=%" GST_TIME_FORMAT - ", position %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, - GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop), + ", offset=%" GST_TIME_FORMAT ", stop=%" GST_TIME_FORMAT + ", rate=%f, applied_rate=%f" ", flags=0x%02x, time=%" GST_TIME_FORMAT + ", base=%" GST_TIME_FORMAT ", position %" GST_TIME_FORMAT + ", duration %" GST_TIME_FORMAT, GST_TIME_ARGS (segment->start), + GST_TIME_ARGS (segment->offset), GST_TIME_ARGS (segment->stop), segment->rate, segment->applied_rate, (guint) segment->flags, GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->base), GST_TIME_ARGS (segment->position), GST_TIME_ARGS (segment->duration)); @@ -756,12 +767,13 @@ gst_debug_print_segment (gpointer ptr) if (G_UNLIKELY (format_name == NULL)) format_name = "(UNKNOWN FORMAT)"; return g_strdup_printf ("%s segment start=%" G_GINT64_FORMAT - ", stop=%" G_GINT64_FORMAT ", rate=%f, applied_rate=%f" - ", flags=0x%02x, time=%" G_GINT64_FORMAT ", base=%" G_GINT64_FORMAT - ", position %" G_GINT64_FORMAT ", duration %" G_GINT64_FORMAT, - format_name, segment->start, segment->stop, segment->rate, - segment->applied_rate, (guint) segment->flags, - segment->time, segment->base, segment->position, segment->duration); + ", offset=%" G_GINT64_FORMAT ", stop=%" G_GINT64_FORMAT + ", rate=%f, applied_rate=%f" ", flags=0x%02x, time=%" G_GINT64_FORMAT + ", base=%" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT + ", duration %" G_GINT64_FORMAT, format_name, segment->start, + segment->offset, segment->stop, segment->rate, segment->applied_rate, + (guint) segment->flags, segment->time, segment->base, + segment->position, segment->duration); } } } @@ -949,7 +961,7 @@ static const gchar *levelcolormap[GST_LEVEL_COUNT] = { * @line: the line from that the message was emitted, usually __LINE__ * @message: the actual message * @object: (transfer none) (allow-none): the object this message relates to, - * or NULL if none + * or %NULL if none * @unused: an unused variable, reserved for some user_data. * * The default logging handler used by GStreamer. Logging functions get called @@ -1306,7 +1318,7 @@ gst_debug_set_color_mode_from_string (const gchar * mode) * * Checks if the debugging output should be colored. * - * Returns: TRUE, if the debug output should be colored. + * Returns: %TRUE, if the debug output should be colored. */ gboolean gst_debug_is_colored (void) @@ -1355,7 +1367,7 @@ gst_debug_set_active (gboolean active) * * Checks if debugging output is activated. * - * Returns: TRUE, if debugging is activated + * Returns: %TRUE, if debugging is activated */ gboolean gst_debug_is_active (void) @@ -1506,7 +1518,7 @@ GstDebugCategory * _gst_debug_category_new (const gchar * name, guint color, const gchar * description) { - GstDebugCategory *cat; + GstDebugCategory *cat, *catfound; g_return_val_if_fail (name != NULL, NULL); @@ -1523,7 +1535,15 @@ _gst_debug_category_new (const gchar * name, guint color, /* add to category list */ g_mutex_lock (&__cat_mutex); - __categories = g_slist_prepend (__categories, cat); + catfound = _gst_debug_get_category_locked (name); + if (catfound) { + g_free ((gpointer) cat->name); + g_free ((gpointer) cat->description); + g_slice_free (GstDebugCategory, cat); + cat = catfound; + } else { + __categories = g_slist_prepend (__categories, cat); + } g_mutex_unlock (&__cat_mutex); return cat; @@ -1674,8 +1694,8 @@ gst_debug_get_all_categories (void) return ret; } -GstDebugCategory * -_gst_debug_get_category (const gchar * name) +static GstDebugCategory * +_gst_debug_get_category_locked (const gchar * name) { GstDebugCategory *ret = NULL; GSList *node; @@ -1689,6 +1709,18 @@ _gst_debug_get_category (const gchar * name) return NULL; } +GstDebugCategory * +_gst_debug_get_category (const gchar * name) +{ + GstDebugCategory *ret; + + g_mutex_lock (&__cat_mutex); + ret = _gst_debug_get_category_locked (name); + g_mutex_unlock (&__cat_mutex); + + return ret; +} + static gboolean parse_debug_category (gchar * str, const gchar ** category) { @@ -1759,7 +1791,7 @@ parse_debug_level (gchar * str, GstDebugLevel * level) * the order matters when you use wild cards, e.g. "foosrc:6,*src:3,*:2" sets * everything to log level 2. * - * Since: 1.2.0 + * Since: 1.2 */ void gst_debug_set_threshold_from_string (const gchar * list, gboolean reset) @@ -2153,7 +2185,7 @@ __gst_info_fallback_vasprintf (char **result, char const *format, va_list args) continue; } len = strlen (c + 4); - g_memmove (c + 2, c + 4, len + 1); + memmove (c + 2, c + 4, len + 1); c += 2; } while ((c = strstr (clean_format, "%P"))) /* old GST_PTR_FORMAT */ diff --git a/gst/gstinfo.h b/gst/gstinfo.h index 4f9baa6..319e841 100644 --- a/gst/gstinfo.h +++ b/gst/gstinfo.h @@ -34,10 +34,10 @@ G_BEGIN_DECLS * GstDebugLevel: * @GST_LEVEL_NONE: No debugging level specified or desired. Used to deactivate * debugging output. - * @GST_LEVEL_ERROR: Error messages are to be used only when an error occured + * @GST_LEVEL_ERROR: Error messages are to be used only when an error occurred * that stops the application from keeping working correctly. * An examples is gst_element_error, which outputs a message with this priority. - * It does not mean that the application is terminating as with g_errror. + * It does not mean that the application is terminating as with g_error. * @GST_LEVEL_WARNING: Warning messages are to inform about abnormal behaviour * that could lead to problems or weird behaviour later on. An example of this * would be clocking issues ("your computer is pretty slow") or broken input @@ -199,9 +199,9 @@ struct _GstDebugCategory { * GST_STR_NULL: * @str: The string to check. * - * Macro to use when a string must not be NULL, but may be NULL. If the string - * is NULL, "(NULL)" is printed instead. - * In GStreamer printf string arguments may not be NULL, because on some + * Macro to use when a string must not be %NULL, but may be %NULL. If the string + * is %NULL, "(NULL)" is printed instead. + * In GStreamer printf string arguments may not be %NULL, because on some * platforms (ie Solaris) the libc crashes in that case. This includes debugging * strings. */ @@ -470,7 +470,7 @@ G_STMT_START{ \ * * Looks up an existing #GstDebugCategory by its @name and sets @cat. If the * category is not found, but GST_CAT_DEFAULT is defined, that is assigned to - * @cat. Otherwise @cat will be NULL. + * @cat. Otherwise @cat will be %NULL. * * |[ * GST_DEBUG_CATEGORY_STATIC (gst_myplugin_debug); @@ -511,7 +511,7 @@ GST_EXPORT GstDebugLevel _gst_debug_min; * GST_CAT_LEVEL_LOG: * @cat: category to use * @level: the severity of the message - * @object: (allow-none): the #GObject the message belongs to or NULL if none + * @object: (allow-none): the #GObject the message belongs to or %NULL if none * @...: A printf-style message to output * * Outputs a debugging message. This is the most general macro for outputting diff --git a/gst/gstiterator.c b/gst/gstiterator.c index 0a63a90..4e5b1f5 100644 --- a/gst/gstiterator.c +++ b/gst/gstiterator.c @@ -34,40 +34,34 @@ * * In general, whenever calling a GstIterator function results in your code * receiving a refcounted object, the refcount for that object will have been - * increased. Your code is responsible for unrefing that object after use. + * increased. Your code is responsible for unreffing that object after use. * * The basic use pattern of an iterator is as follows: - * - * <example> - * <title>Using an iterator</title> - * <programlisting> - * it = _get_iterator(object); - * done = FALSE; - * while (!done) { - * switch (gst_iterator_next (it, &item)) { - * case GST_ITERATOR_OK: - * ... use/change item here... - * g_value_reset (&item); - * break; - * case GST_ITERATOR_RESYNC: - * ...rollback changes to items... - * gst_iterator_resync (it); - * break; - * case GST_ITERATOR_ERROR: - * ...wrong parameters were given... - * done = TRUE; - * break; - * case GST_ITERATOR_DONE: - * done = TRUE; - * break; - * } - * } - * g_value_unset (&item); - * gst_iterator_free (it); - * </programlisting> - * </example> - * - * Last reviewed on 2009-06-16 (0.10.24) + * |[ + * GstIterator *it = _get_iterator(object); + * done = FALSE; + * while (!done) { + * switch (gst_iterator_next (it, &item)) { + * case GST_ITERATOR_OK: + * ... use/change item here... + * g_value_reset (&item); + * break; + * case GST_ITERATOR_RESYNC: + * ...rollback changes to items... + * gst_iterator_resync (it); + * break; + * case GST_ITERATOR_ERROR: + * ...wrong parameters were given... + * done = TRUE; + * break; + * case GST_ITERATOR_DONE: + * done = TRUE; + * break; + * } + * } + * g_value_unset (&item); + * gst_iterator_free (it); + * ]| */ #include "gst_private.h" @@ -459,6 +453,7 @@ typedef struct _GstIteratorFilter GstIterator iterator; GstIterator *slave; + GMutex *master_lock; GCompareFunc func; GValue user_data; gboolean have_user_data; @@ -475,15 +470,15 @@ filter_next (GstIteratorFilter * it, GValue * elem) result = gst_iterator_next (it->slave, &item); switch (result) { case GST_ITERATOR_OK: - if (G_LIKELY (GST_ITERATOR (it)->lock)) - g_mutex_unlock (GST_ITERATOR (it)->lock); + if (G_LIKELY (it->master_lock)) + g_mutex_unlock (it->master_lock); if (it->func (&item, &it->user_data) == 0) { g_value_copy (&item, elem); done = TRUE; } g_value_reset (&item); - if (G_LIKELY (GST_ITERATOR (it)->lock)) - g_mutex_lock (GST_ITERATOR (it)->lock); + if (G_LIKELY (it->master_lock)) + g_mutex_lock (it->master_lock); break; case GST_ITERATOR_RESYNC: case GST_ITERATOR_DONE: @@ -502,6 +497,8 @@ static void filter_copy (const GstIteratorFilter * it, GstIteratorFilter * copy) { copy->slave = gst_iterator_copy (it->slave); + copy->master_lock = copy->slave->lock ? copy->slave->lock : it->master_lock; + copy->slave->lock = NULL; if (it->have_user_data) { memset (©->user_data, 0, sizeof (copy->user_data)); @@ -559,6 +556,7 @@ gst_iterator_filter (GstIterator * it, GCompareFunc func, (GstIteratorResyncFunction) filter_resync, (GstIteratorFreeFunction) filter_free); + result->master_lock = it->lock; it->lock = NULL; result->func = func; if (user_data) { @@ -588,8 +586,8 @@ gst_iterator_filter (GstIterator * it, GCompareFunc func, * This procedure can be used (and is used internally) to implement the * gst_iterator_foreach() and gst_iterator_find_custom() operations. * - * The fold will proceed as long as @func returns TRUE. When the iterator has no - * more arguments, %GST_ITERATOR_DONE will be returned. If @func returns FALSE, + * The fold will proceed as long as @func returns %TRUE. When the iterator has no + * more arguments, %GST_ITERATOR_DONE will be returned. If @func returns %FALSE, * the fold will stop, and %GST_ITERATOR_OK will be returned. Errors or resyncs * will cause fold to return %GST_ITERATOR_ERROR or %GST_ITERATOR_RESYNC as * appropriate. @@ -705,10 +703,10 @@ find_custom_fold_func (const GValue * item, GValue * ret, * * The iterator will not be freed. * - * This function will return FALSE if an error happened to the iterator + * This function will return %FALSE if an error happened to the iterator * or if the element wasn't found. * - * Returns: Returns TRUE if the element was found, else FALSE. + * Returns: Returns %TRUE if the element was found, else %FALSE. * * MT safe. */ diff --git a/gst/gstiterator.h b/gst/gstiterator.h index 7ad54ee..264f197 100644 --- a/gst/gstiterator.h +++ b/gst/gstiterator.h @@ -146,7 +146,7 @@ typedef void (*GstIteratorForeachFunction) (const GValue * item, gpo * * A function to be passed to gst_iterator_fold(). * - * Returns: TRUE if the fold should continue, FALSE if it should stop. + * Returns: %TRUE if the fold should continue, %FALSE if it should stop. */ typedef gboolean (*GstIteratorFoldFunction) (const GValue * item, GValue * ret, gpointer user_data); diff --git a/gst/gstmemory.c b/gst/gstmemory.c index 1f44e7b..c29fccd 100644 --- a/gst/gstmemory.c +++ b/gst/gstmemory.c @@ -33,7 +33,7 @@ * in the allocated region. * * Memory is usually created by allocators with a gst_allocator_alloc() - * method call. When NULL is used as the allocator, the default allocator will + * method call. When %NULL is used as the allocator, the default allocator will * be used. * * New allocators can be registered with gst_allocator_register(). @@ -59,9 +59,7 @@ * memory with an existing memory block at a custom offset and with a custom * size. * - * Memory can be efficiently merged when gst_memory_is_span() returns TRUE. - * - * Last reviewed on 2012-03-28 (0.11.3) + * Memory can be efficiently merged when gst_memory_is_span() returns %TRUE. */ #ifdef HAVE_CONFIG_H @@ -71,6 +69,7 @@ #include "gst_private.h" #include "gstmemory.h" +GType _gst_memory_type = 0; GST_DEFINE_MINI_OBJECT_TYPE (GstMemory, gst_memory); static GstMemory * @@ -226,7 +225,7 @@ gst_memory_resize (GstMemory * mem, gssize offset, gsize size) * This function takes ownership of old @mem and returns a reference to a new * #GstMemory. * - * Returns: (transfer full): a #GstMemory object mapped with @flags or NULL when + * Returns: (transfer full): a #GstMemory object mapped with @flags or %NULL when * a mapping is not possible. */ GstMemory * @@ -290,7 +289,7 @@ gst_memory_map (GstMemory * mem, GstMapInfo * info, GstMapFlags flags) g_return_val_if_fail (mem != NULL, FALSE); g_return_val_if_fail (info != NULL, FALSE); - if (!gst_memory_lock (mem, flags)) + if (!gst_memory_lock (mem, (GstLockFlags) flags)) goto lock_failed; info->data = mem->allocator->mem_map (mem, mem->maxsize, flags); @@ -310,13 +309,15 @@ gst_memory_map (GstMemory * mem, GstMapInfo * info, GstMapFlags flags) lock_failed: { GST_CAT_DEBUG (GST_CAT_MEMORY, "mem %p: lock %d failed", mem, flags); + memset (info, 0, sizeof (GstMapInfo)); return FALSE; } error: { /* something went wrong, restore the orginal state again */ GST_CAT_ERROR (GST_CAT_MEMORY, "mem %p: subclass map failed", mem); - gst_memory_unlock (mem, flags); + gst_memory_unlock (mem, (GstLockFlags) flags); + memset (info, 0, sizeof (GstMapInfo)); return FALSE; } } @@ -336,7 +337,7 @@ gst_memory_unmap (GstMemory * mem, GstMapInfo * info) g_return_if_fail (info->memory == mem); mem->allocator->mem_unmap (mem); - gst_memory_unlock (mem, info->flags); + gst_memory_unlock (mem, (GstLockFlags) info->flags); } /** @@ -425,3 +426,9 @@ gst_memory_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset) return TRUE; } + +void +_priv_gst_memory_initialize (void) +{ + _gst_memory_type = gst_memory_get_type (); +} diff --git a/gst/gstmemory.h b/gst/gstmemory.h index b5180ca..4819e2a 100644 --- a/gst/gstmemory.h +++ b/gst/gstmemory.h @@ -29,7 +29,8 @@ G_BEGIN_DECLS -#define GST_TYPE_MEMORY (gst_memory_get_type()) +GST_EXPORT GType _gst_memory_type; +#define GST_TYPE_MEMORY (_gst_memory_type) GType gst_memory_get_type(void); typedef struct _GstMemory GstMemory; diff --git a/gst/gstmessage.c b/gst/gstmessage.c index 1e6deff..5014016 100644 --- a/gst/gstmessage.c +++ b/gst/gstmessage.c @@ -34,18 +34,12 @@ * application using the #GstBus. * * The basic use pattern of posting a message on a #GstBus is as follows: - * - * <example> - * <title>Posting a #GstMessage</title> - * <programlisting> - * gst_bus_post (bus, gst_message_new_eos()); - * </programlisting> - * </example> + * |[ + * gst_bus_post (bus, gst_message_new_eos()); + * ]| * * A #GstElement usually posts messages on the bus provided by the parent * container using gst_element_post_message(). - * - * Last reviewed on 2005-11-09 (0.9.4) */ @@ -109,10 +103,12 @@ static GstMessageQuarks message_quarks[] = { {GST_MESSAGE_STREAM_START, "stream-start", 0}, {GST_MESSAGE_NEED_CONTEXT, "need-context", 0}, {GST_MESSAGE_HAVE_CONTEXT, "have-context", 0}, + {GST_MESSAGE_DEVICE_ADDED, "device-added", 0}, + {GST_MESSAGE_DEVICE_REMOVED, "device-removed", 0}, {0, NULL, 0} }; -static GType _gst_message_type = 0; +GType _gst_message_type = 0; GST_DEFINE_MINI_OBJECT_TYPE (GstMessage, gst_message); void @@ -265,7 +261,7 @@ gst_message_init (GstMessageImpl * message, GstMessageType type, * * Create a new custom-typed message. This can be used for anything not * handled by other message-specific functions to pass a message to the - * app. The structure field can be NULL. + * app. The structure field can be %NULL. * * Returns: (transfer full): The new message. * @@ -384,7 +380,7 @@ gst_message_new_eos (GstObject * src) * * Create a new error message. The message will copy @error and * @debug. This message is posted by element when a fatal event - * occured. The pipeline will probably (partially) stop. The application + * occurred. The pipeline will probably (partially) stop. The application * receiving this message should stop the pipeline. * * Returns: (transfer full): the new error message. @@ -586,7 +582,7 @@ gst_message_new_state_dirty (GstObject * src) * gst_message_new_clock_provide: * @src: (transfer none): the object originating the message. * @clock: (transfer none): the clock it provides - * @ready: TRUE if the sender can provide a clock + * @ready: %TRUE if the sender can provide a clock * * Create a clock provide message. This message is posted whenever an * element is ready to provide a clock or lost its ability to provide @@ -649,7 +645,7 @@ gst_message_new_clock_lost (GstObject * src, GstClock * clock) * @clock: (transfer none): the new selected clock * * Create a new clock message. This message is posted whenever the - * pipeline selectes a new clock for the pipeline. + * pipeline selects a new clock for the pipeline. * * Returns: (transfer full): The new new clock message. * @@ -795,7 +791,7 @@ gst_message_new_application (GstObject * src, GstStructure * structure) * Create a new element-specific message. This is meant as a generic way of * allowing one-way communication from an element to an application, for example * "the firewire cable was unplugged". The format of the message should be - * documented in the element's documentation. The structure field can be NULL. + * documented in the element's documentation. The structure field can be %NULL. * * Returns: (transfer full): The new element message. * @@ -912,7 +908,7 @@ gst_message_new_latency (GstObject * src) * changed. A typical use case would be an audio server that wants to pause the * pipeline because a higher priority stream is being played. * - * Returns: (transfer full): the new requst state message. + * Returns: (transfer full): the new request state message. * * MT safe. */ @@ -1060,11 +1056,11 @@ gst_message_set_buffering_stats (GstMessage * message, GstBufferingMode mode, /** * gst_message_parse_buffering_stats: * @message: A valid #GstMessage of type GST_MESSAGE_BUFFERING. - * @mode: (out) (allow-none): a buffering mode, or NULL - * @avg_in: (out) (allow-none): the average input rate, or NULL - * @avg_out: (out) (allow-none): the average output rate, or NULL + * @mode: (out) (allow-none): a buffering mode, or %NULL + * @avg_in: (out) (allow-none): the average input rate, or %NULL + * @avg_out: (out) (allow-none): the average output rate, or %NULL * @buffering_left: (out) (allow-none): amount of buffering time left in - * milliseconds, or NULL + * milliseconds, or %NULL * * Extracts the buffering stats values from @message. */ @@ -1097,9 +1093,9 @@ gst_message_parse_buffering_stats (GstMessage * message, /** * gst_message_parse_state_changed: * @message: a valid #GstMessage of type GST_MESSAGE_STATE_CHANGED - * @oldstate: (out) (allow-none): the previous state, or NULL - * @newstate: (out) (allow-none): the new (current) state, or NULL - * @pending: (out) (allow-none): the pending (target) state, or NULL + * @oldstate: (out) (allow-none): the previous state, or %NULL + * @newstate: (out) (allow-none): the new (current) state, or %NULL + * @pending: (out) (allow-none): the pending (target) state, or %NULL * * Extracts the old and new states from the GstMessage. * @@ -1152,8 +1148,8 @@ gst_message_parse_state_changed (GstMessage * message, * gst_message_parse_clock_provide: * @message: A valid #GstMessage of type GST_MESSAGE_CLOCK_PROVIDE. * @clock: (out) (allow-none) (transfer none): a pointer to hold a clock - * object, or NULL - * @ready: (out) (allow-none): a pointer to hold the ready flag, or NULL + * object, or %NULL + * @ready: (out) (allow-none): a pointer to hold the ready flag, or %NULL * * Extracts the clock and ready flag from the GstMessage. * The clock object returned remains valid until the message is freed. @@ -1285,7 +1281,7 @@ gst_message_parse_structure_change (GstMessage * message, * @message: A valid #GstMessage of type GST_MESSAGE_ERROR. * @gerror: (out) (allow-none) (transfer full): location for the GError * @debug: (out) (allow-none) (transfer full): location for the debug message, - * or NULL + * or %NULL * * Extracts the GError and debug string from the GstMessage. The values returned * in the output arguments are copies; the caller must free them when done. @@ -1329,7 +1325,7 @@ gst_message_parse_error (GstMessage * message, GError ** gerror, gchar ** debug) * @message: A valid #GstMessage of type GST_MESSAGE_WARNING. * @gerror: (out) (allow-none) (transfer full): location for the GError * @debug: (out) (allow-none) (transfer full): location for the debug message, - * or NULL + * or %NULL * * Extracts the GError and debug string from the GstMessage. The values returned * in the output arguments are copies; the caller must free them when done. @@ -1353,7 +1349,7 @@ gst_message_parse_warning (GstMessage * message, GError ** gerror, * @message: A valid #GstMessage of type GST_MESSAGE_INFO. * @gerror: (out) (allow-none) (transfer full): location for the GError * @debug: (out) (allow-none) (transfer full): location for the debug message, - * or NULL + * or %NULL * * Extracts the GError and debug string from the GstMessage. The values returned * in the output arguments are copies; the caller must free them when done. @@ -1374,8 +1370,8 @@ gst_message_parse_info (GstMessage * message, GError ** gerror, gchar ** debug) /** * gst_message_parse_segment_start: * @message: A valid #GstMessage of type GST_MESSAGE_SEGMENT_START. - * @format: (out) (allow-none): Result location for the format, or NULL - * @position: (out) (allow-none): Result location for the position, or NULL + * @format: (out) (allow-none): Result location for the format, or %NULL + * @position: (out) (allow-none): Result location for the position, or %NULL * * Extracts the position and format from the segment start message. * @@ -1404,8 +1400,8 @@ gst_message_parse_segment_start (GstMessage * message, GstFormat * format, /** * gst_message_parse_segment_done: * @message: A valid #GstMessage of type GST_MESSAGE_SEGMENT_DONE. - * @format: (out) (allow-none): Result location for the format, or NULL - * @position: (out) (allow-none): Result location for the position, or NULL + * @format: (out) (allow-none): Result location for the format, or %NULL + * @position: (out) (allow-none): Result location for the position, or %NULL * * Extracts the position and format from the segment done message. * @@ -1434,7 +1430,7 @@ gst_message_parse_segment_done (GstMessage * message, GstFormat * format, /** * gst_message_parse_async_done: * @message: A valid #GstMessage of type GST_MESSAGE_ASYNC_DONE. - * @running_time: (out) (allow-none): Result location for the running_time or NULL + * @running_time: (out) (allow-none): Result location for the running_time or %NULL * * Extract the running_time from the async_done message. * @@ -1458,7 +1454,7 @@ gst_message_parse_async_done (GstMessage * message, GstClockTime * running_time) /** * gst_message_parse_request_state: * @message: A valid #GstMessage of type GST_MESSAGE_REQUEST_STATE. - * @state: (out) (allow-none): Result location for the requested state or NULL + * @state: (out) (allow-none): Result location for the requested state or %NULL * * Extract the requested state from the request_state message. * @@ -1600,7 +1596,7 @@ gst_message_get_stream_status_object (GstMessage * message) * @eos: the step caused EOS * * This message is posted by elements when they complete a part, when @intermediate set - * to TRUE, or a complete step operation. + * to %TRUE, or a complete step operation. * * @duration will contain the amount of time (in GST_FORMAT_TIME) of the stepped * @amount of media in format @format. @@ -1679,12 +1675,12 @@ gst_message_parse_step_done (GstMessage * message, GstFormat * format, * This message is posted by elements when they accept or activate a new step * event for @amount in @format. * - * @active is set to FALSE when the element accepted the new step event and has + * @active is set to %FALSE when the element accepted the new step event and has * queued it for execution in the streaming threads. * - * @active is set to TRUE when the element has activated the step operation and + * @active is set to %TRUE when the element has activated the step operation and * is now ready to start executing the step in the streaming thread. After this - * message is emited, the application can queue a new step operation in the + * message is emitted, the application can queue a new step operation in the * element. * * Returns: (transfer full): The new step_start message. @@ -2064,7 +2060,7 @@ gst_message_new_toc (GstObject * src, GstToc * toc, gboolean updated) * @toc: (out) (transfer full): return location for the TOC. * @updated: (out): return location for the updated flag. * - * Extract thef TOC from the #GstMessage. The TOC returned in the + * Extract the TOC from the #GstMessage. The TOC returned in the * output argument is a copy; the caller must free it with * gst_toc_unref() when done. * @@ -2111,7 +2107,7 @@ gst_message_new_reset_time (GstObject * src, GstClockTime running_time) * gst_message_parse_reset_time: * @message: A valid #GstMessage of type GST_MESSAGE_RESET_TIME. * @running_time: (out) (allow-none): Result location for the running_time or - * NULL + * %NULL * * Extract the running-time from the RESET_TIME message. * @@ -2192,7 +2188,7 @@ gst_message_set_group_id (GstMessage * message, guint group_id) * gst_message_parse_group_id: * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_START. * @group_id: (out) (allow-none): Result location for the group id or - * NULL + * %NULL * * Extract the group from the STREAM_START message. * @@ -2256,7 +2252,7 @@ gst_message_new_need_context (GstObject * src, const gchar * context_type) /** * gst_message_parse_context_type: * @message: a GST_MESSAGE_NEED_CONTEXT type message - * @context_type: (out) (allow-none): the context type, or NULL + * @context_type: (out) (allow-none): the context type, or %NULL * * Parse a context type from an existing GST_MESSAGE_NEED_CONTEXT message. * @@ -2315,7 +2311,7 @@ gst_message_new_have_context (GstObject * src, GstContext * context) * gst_message_parse_have_context: * @message: A valid #GstMessage of type GST_MESSAGE_HAVE_CONTEXT. * @context: (out) (transfer full) (allow-none): Result location for the - * context or NULL + * context or %NULL * * Extract the context from the HAVE_CONTEXT message. * @@ -2333,3 +2329,107 @@ gst_message_parse_have_context (GstMessage * message, GstContext ** context) gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL); } + +/** + * gst_message_new_device_added: + * @src: The #GstObject that created the message + * @device: (transfer none): The new #GstDevice + * + * Creates a new device-added message. The device-added message is produced by + * #GstDeviceMonitor or a #GstGlobalDeviceMonitor. They announce the appearance + * of monitored devices. + * + * Returns: a newly allocated #GstMessage + * + * Since: 1.4 + */ +GstMessage * +gst_message_new_device_added (GstObject * src, GstDevice * device) +{ + GstMessage *message; + GstStructure *structure; + + g_return_val_if_fail (device != NULL, NULL); + g_return_val_if_fail (GST_IS_DEVICE (device), NULL); + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_DEVICE_ADDED), + GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL); + message = gst_message_new_custom (GST_MESSAGE_DEVICE_ADDED, src, structure); + + return message; +} + +/** + * gst_message_parse_device_added: + * @message: a #GstMessage of type %GST_MESSAGE_DEVICE_ADDED + * @device: (out) (allow-none) (transfer none): A location where to store a + * pointer to the new #GstDevice, or %NULL + * + * Parses a device-added message. The device-added message is produced by + * #GstDeviceMonitor or a #GstGlobalDeviceMonitor. It announces the appearance + * of monitored devices. + * + * Since: 1.4 + */ +void +gst_message_parse_device_added (GstMessage * message, GstDevice ** device) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DEVICE_ADDED); + + if (device) + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL); +} + +/** + * gst_message_new_device_removed: + * @src: The #GstObject that created the message + * @device: (transfer none): The removed #GstDevice + * + * Creates a new device-removed message. The device-removed message is produced + * by #GstDeviceMonitor or a #GstGlobalDeviceMonitor. They announce the + * disappearance of monitored devices. + * + * Returns: a newly allocated #GstMessage + * + * Since: 1.4 + */ +GstMessage * +gst_message_new_device_removed (GstObject * src, GstDevice * device) +{ + GstMessage *message; + GstStructure *structure; + + g_return_val_if_fail (device != NULL, NULL); + g_return_val_if_fail (GST_IS_DEVICE (device), NULL); + + structure = gst_structure_new_id (GST_QUARK (MESSAGE_DEVICE_REMOVED), + GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL); + message = gst_message_new_custom (GST_MESSAGE_DEVICE_REMOVED, src, structure); + + return message; +} + +/** + * gst_message_parse_device_removed: + * @message: a #GstMessage of type %GST_MESSAGE_DEVICE_REMOVED + * @device: (out) (allow-none) (transfer none): A location where to store a + * pointer to the removed #GstDevice, or %NULL + * + * Parses a device-removed message. The device-removed message is produced by + * #GstDeviceMonitor or a #GstGlobalDeviceMonitor. It announces the + * disappearance of monitored devices. + * + * Since: 1.4 + */ +void +gst_message_parse_device_removed (GstMessage * message, GstDevice ** device) +{ + g_return_if_fail (GST_IS_MESSAGE (message)); + g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DEVICE_REMOVED); + + if (device) + gst_structure_id_get (GST_MESSAGE_STRUCTURE (message), + GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL); +} diff --git a/gst/gstmessage.h b/gst/gstmessage.h index 38e6d7e..7433edc 100644 --- a/gst/gstmessage.h +++ b/gst/gstmessage.h @@ -33,11 +33,11 @@ typedef struct _GstMessage GstMessage; * only receive this message in the PLAYING state and every time it sets a * pipeline to PLAYING that is in the EOS state. The application can perform a * flushing seek in the pipeline, which will undo the EOS state again. - * @GST_MESSAGE_ERROR: an error occured. When the application receives an error + * @GST_MESSAGE_ERROR: an error occurred. When the application receives an error * message it should stop playback of the pipeline and not assume that more * data will be played. - * @GST_MESSAGE_WARNING: a warning occured. - * @GST_MESSAGE_INFO: an info message occured + * @GST_MESSAGE_WARNING: a warning occurred. + * @GST_MESSAGE_INFO: an info message occurred * @GST_MESSAGE_TAG: a tag was found. * @GST_MESSAGE_BUFFERING: the pipeline is buffering. When the application * receives a buffering message in the PLAYING state for a non-live pipeline it @@ -99,6 +99,15 @@ typedef struct _GstMessage GstMessage; * the URI for the next title has been set). * @GST_MESSAGE_NEED_CONTEXT: Message indicating that an element wants a specific context (Since 1.2) * @GST_MESSAGE_HAVE_CONTEXT: Message indicating that an element created a context (Since 1.2) + * @GST_MESSAGE_EXTENDED: Message is an extended message type (see below). + * These extended message IDs can't be used directly with mask-based API + * like gst_bus_poll() or gst_bus_timed_pop_filtered(), but you can still + * filter for GST_MESSAGE_EXTENDED and then check the result for the + * specific type. (Since 1.4) + * @GST_MESSAGE_DEVICE_ADDED: Message indicating a #GstDevice was added to + * a #GstDeviceMonitor (Since 1.4) + * @GST_MESSAGE_DEVICE_REMOVED: Message indicating a #GstDevice was removed + * from a #GstDeviceMonitor (Since 1.4) * @GST_MESSAGE_ANY: mask for all of the above messages. * * The different message types that are available. @@ -106,6 +115,7 @@ typedef struct _GstMessage GstMessage; /* NOTE: keep in sync with quark registration in gstmessage.c * NOTE: keep GST_MESSAGE_ANY a valid gint to avoid compiler warnings. */ +/* FIXME: 2.0: Make it NOT flags, just a regular 1,2,3,4.. enumeration */ typedef enum { GST_MESSAGE_UNKNOWN = 0, @@ -140,6 +150,9 @@ typedef enum GST_MESSAGE_STREAM_START = (1 << 28), GST_MESSAGE_NEED_CONTEXT = (1 << 29), GST_MESSAGE_HAVE_CONTEXT = (1 << 30), + GST_MESSAGE_EXTENDED = (1 << 31), + GST_MESSAGE_DEVICE_ADDED = GST_MESSAGE_EXTENDED + 1, + GST_MESSAGE_DEVICE_REMOVED = GST_MESSAGE_EXTENDED + 2, GST_MESSAGE_ANY = ~0 } GstMessageType; @@ -150,8 +163,11 @@ typedef enum #include <gst/gststructure.h> #include <gst/gstquery.h> #include <gst/gsttoc.h> +#include <gst/gstdevice.h> -#define GST_TYPE_MESSAGE (gst_message_get_type()) +GST_EXPORT GType _gst_message_type; + +#define GST_TYPE_MESSAGE (_gst_message_type) #define GST_IS_MESSAGE(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_MESSAGE)) #define GST_MESSAGE_CAST(obj) ((GstMessage*)(obj)) #define GST_MESSAGE(obj) (GST_MESSAGE_CAST(obj)) @@ -174,6 +190,15 @@ typedef enum */ #define GST_MESSAGE_TYPE(message) (GST_MESSAGE_CAST(message)->type) /** + * GST_MESSAGE_TYPE_IS_EXTENDED: + * @message: a #GstMessage + * + * Check if the message is in the extended message group + * (Since 1.4) + */ +#define GST_MESSAGE_TYPE_IS_EXTENDED(message) (!!(GST_MESSAGE_CAST(message)->type & GST_MESSAGE_EXTENDED)) + +/** * GST_MESSAGE_TYPE_NAME: * @message: a #GstMessage * @@ -260,7 +285,7 @@ typedef enum { * posted on the bus. * * The type of a %GST_MESSAGE_PROGRESS. The progress messages inform the - * application of the status of assynchronous tasks. + * application of the status of asynchronous tasks. */ typedef enum { GST_PROGRESS_TYPE_START = 0, @@ -389,9 +414,9 @@ gst_message_copy (const GstMessage * msg) * in some cases), and the reference counts are updated appropriately (the old * message is unreffed, the new one is reffed). * - * Either @new_message or the #GstMessage pointed to by @old_message may be NULL. + * Either @new_message or the #GstMessage pointed to by @old_message may be %NULL. * - * Returns: TRUE if @new_message was different from @old_message + * Returns: %TRUE if @new_message was different from @old_message */ #ifdef _FOOL_GTK_DOC_ G_INLINE_FUNC gboolean gst_message_replace (GstMessage **old_message, GstMessage *new_message); @@ -572,6 +597,15 @@ gboolean gst_message_parse_context_type (GstMessage * message, const gch GstMessage * gst_message_new_have_context (GstObject * src, GstContext *context) G_GNUC_MALLOC; void gst_message_parse_have_context (GstMessage *message, GstContext **context); +/* DEVICE_ADDED */ +GstMessage * gst_message_new_device_added (GstObject * src, GstDevice * device) G_GNUC_MALLOC; +void gst_message_parse_device_added (GstMessage * message, GstDevice ** device); + +/* DEVICE_REMOVED */ +GstMessage * gst_message_new_device_removed (GstObject * src, GstDevice * device) G_GNUC_MALLOC; +void gst_message_parse_device_removed (GstMessage * message, GstDevice ** device); + + G_END_DECLS #endif /* __GST_MESSAGE_H__ */ diff --git a/gst/gstmeta.c b/gst/gstmeta.c index 31f3ff1..0e0aca1 100644 --- a/gst/gstmeta.c +++ b/gst/gstmeta.c @@ -42,8 +42,6 @@ * * See #GstBuffer for how the metadata can be added, retrieved and removed from * buffers. - * - * Last reviewed on 2012-03-28 (0.11.3) */ #include "gst_private.h" @@ -207,7 +205,7 @@ gst_meta_register (GType api, const gchar * impl, gsize size, * Lookup a previously registered meta info structure by its implementation name * @impl. * - * Returns: (transfer none): a #GstMetaInfo with @impl, or #NULL when no such + * Returns: (transfer none): a #GstMetaInfo with @impl, or %NULL when no such * metainfo exists. */ const GstMetaInfo * diff --git a/gst/gstmeta.h b/gst/gstmeta.h index d294126..4283f8e 100644 --- a/gst/gstmeta.h +++ b/gst/gstmeta.h @@ -83,6 +83,7 @@ typedef enum { /** * GST_META_TAG_MEMORY_STR: + * * This metadata stays relevant as long as memory layout is unchanged. * * Since: 1.2 @@ -174,8 +175,8 @@ typedef gboolean (*GstMetaTransformFunction) (GstBuffer *transbuf, /** * GstMetaInfo: - * @api: tag indentifying the metadata structure and api - * @type: type indentifying the implementor of the api + * @api: tag identifying the metadata structure and api + * @type: type identifying the implementor of the api * @size: size of the metadata * @init_func: function for initializing the metadata * @free_func: function for freeing the metadata @@ -221,7 +222,9 @@ GST_EXPORT GQuark _gst_meta_tag_memory; * Deprecated: The GQuarks are not exported by any public API, use * GST_META_TAG_MEMORY_STR instead. */ +#ifndef GST_DISABLE_DEPRECATED #define GST_META_TAG_MEMORY (_gst_meta_tag_memory) +#endif G_END_DECLS diff --git a/gst/gstminiobject.c b/gst/gstminiobject.c index 25efc08..bece06a 100644 --- a/gst/gstminiobject.c +++ b/gst/gstminiobject.c @@ -47,8 +47,6 @@ * * A weak reference can be added and remove with gst_mini_object_weak_ref() * and gst_mini_object_weak_unref() respectively. - * - * Last reviewed on 2012-06-15 (0.11.93) */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -106,9 +104,9 @@ _priv_gst_mini_object_initialize (void) * @mini_object: a #GstMiniObject * @flags: initial #GstMiniObjectFlags * @type: the #GType of the mini-object to create - * @copy_func: (allow-none): the copy function, or NULL - * @dispose_func: (allow-none): the dispose function, or NULL - * @free_func: (allow-none): the free function or NULL + * @copy_func: (allow-none): the copy function, or %NULL + * @dispose_func: (allow-none): the dispose function, or %NULL + * @free_func: (allow-none): the free function or %NULL * * Initializes a mini-object with the desired type and copy/dispose/free * functions. @@ -281,7 +279,7 @@ gst_mini_object_unlock (GstMiniObject * object, GstLockFlags flags) * Modification of a mini-object should only be done after verifying that it * is writable. * - * Returns: TRUE if the object is writable. + * Returns: %TRUE if the object is writable. */ gboolean gst_mini_object_is_writable (const GstMiniObject * mini_object) @@ -336,7 +334,7 @@ gst_mini_object_make_writable (GstMiniObject * mini_object) * * Increase the reference count of the mini-object. * - * Note that the refcount affects the writeability + * Note that the refcount affects the writability * of @mini-object, see gst_mini_object_is_writable(). It is * important to note that keeping additional references to * GstMiniObject instances can potentially increase the number @@ -479,9 +477,9 @@ gst_mini_object_unref (GstMiniObject * mini_object) * The reference count of @olddata is decreased and the reference count of * @newdata is increased. * - * Either @newdata and the value pointed to by @olddata may be NULL. + * Either @newdata and the value pointed to by @olddata may be %NULL. * - * Returns: TRUE if @newdata was different from @olddata + * Returns: %TRUE if @newdata was different from @olddata */ gboolean gst_mini_object_replace (GstMiniObject ** olddata, GstMiniObject * newdata) @@ -520,7 +518,7 @@ gst_mini_object_replace (GstMiniObject ** olddata, GstMiniObject * newdata) * @olddata: (inout) (transfer full): pointer to a pointer to a mini-object to * be stolen * - * Replace the current #GstMiniObject pointer to by @olddata with NULL and + * Replace the current #GstMiniObject pointer to by @olddata with %NULL and * return the old value. * * Returns: the #GstMiniObject at @oldata @@ -556,9 +554,9 @@ gst_mini_object_steal (GstMiniObject ** olddata) * except that it does not increase the refcount of @newdata and thus * takes ownership of @newdata. * - * Either @newdata and the value pointed to by @olddata may be NULL. + * Either @newdata and the value pointed to by @olddata may be %NULL. * - * Returns: TRUE if @newdata was different from @olddata + * Returns: %TRUE if @newdata was different from @olddata */ gboolean gst_mini_object_take (GstMiniObject ** olddata, GstMiniObject * newdata) @@ -645,12 +643,12 @@ gst_mini_object_weak_unref (GstMiniObject * object, * needs to be freed * * This sets an opaque, named pointer on a miniobject. - * The name is specified through a #GQuark (retrived e.g. via + * The name is specified through a #GQuark (retrieved e.g. via * g_quark_from_static_string()), and the pointer * can be gotten back from the @object with gst_mini_object_get_qdata() * until the @object is disposed. * Setting a previously set user data pointer, overrides (frees) - * the old pointer set, using #NULL as pointer essentially + * the old pointer set, using %NULL as pointer essentially * removes the data stored. * * @destroy may be specified which is called with @data as argument diff --git a/gst/gstminiobject.h b/gst/gstminiobject.h index 7ae012d..bd56553 100644 --- a/gst/gstminiobject.h +++ b/gst/gstminiobject.h @@ -62,7 +62,7 @@ typedef gboolean (*GstMiniObjectDisposeFunction) (GstMiniObject *obj); * GstMiniObjectFreeFunction: * @obj: MiniObject to free * - * Virtual function prototype for methods to free ressources used by + * Virtual function prototype for methods to free resources used by * mini-objects. */ typedef void (*GstMiniObjectFreeFunction) (GstMiniObject *obj); @@ -114,7 +114,7 @@ typedef void (*GstMiniObjectNotify) (gpointer user_data, GstMiniObject * obj); * @obj: MiniObject to unset flag in. * @flag: Flag to set, must be a single bit in guint32. * - * This macro usets the given bits. + * This macro unsets the given bits. */ #define GST_MINI_OBJECT_FLAG_UNSET(obj,flag) (GST_MINI_OBJECT_FLAGS (obj) &= ~(flag)) diff --git a/gst/gstobject.c b/gst/gstobject.c index 3300464..b997db6 100644 --- a/gst/gstobject.c +++ b/gst/gstobject.c @@ -30,11 +30,11 @@ * #GInitiallyUnowned. It is an abstract class that is not very usable on its own. * * #GstObject gives us basic refcounting, parenting functionality and locking. - * Most of the function are just extended for special GStreamer needs and can be + * Most of the functions are just extended for special GStreamer needs and can be * found under the same name in the base class of #GstObject which is #GObject * (e.g. g_object_ref() becomes gst_object_ref()). * - * Since #GstObject dereives from #GInitiallyUnowned, it also inherits the + * Since #GstObject derives from #GInitiallyUnowned, it also inherits the * floating reference. Be aware that functions such as gst_bin_add() and * gst_element_add_pad() take ownership of the floating reference. * @@ -45,10 +45,10 @@ * <refsect2> * <title>controlled properties</title> * <para> - * Controlled properties offers a lightweight way to adjust gobject - * properties over stream-time. It works by using time-stamped value pairs that - * are queued for element-properties. At run-time the elements continuously pull - * values changes for the current stream-time. + * Controlled properties offers a lightweight way to adjust gobject properties + * over stream-time. It works by using time-stamped value pairs that are queued + * for element-properties. At run-time the elements continuously pull value + * changes for the current stream-time. * * What needs to be changed in a #GstElement? * Very little - it is just two steps to make a plugin controllable! @@ -60,8 +60,8 @@ * <listitem><para> * when processing data (get, chain, loop function) at the beginning call * gst_object_sync_values(element,timestamp). - * This will made the controller to update all gobject properties that are under - * control with the current values based on timestamp. + * This will make the controller update all GObject properties that are + * under its control with the current values based on the timestamp. * </para></listitem> * </orderedlist> * @@ -88,8 +88,6 @@ * </orderedlist> * </para> * </refsect2> - * - * Last reviewed on 2012-03-29 (0.11.3) */ #include "gst_private.h" @@ -172,6 +170,15 @@ gst_object_class_init (GstObjectClass * klass) g_param_spec_string ("name", "Name", "The name of the object", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + /** + * GstObject:parent: + * + * The parent of the object. Please note, that when changing the 'parent' + * property, we don't emit #GObject::notify and #GstObject::deep-notify + * signals due to locking issues. In some cases one can use + * #GstBin::element-added or #GstBin::element-removed signals on the parent to + * achieve a similar effect. + */ properties[PROP_PARENT] = g_param_spec_object ("parent", "Parent", "The parent of the object", GST_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); @@ -311,9 +318,9 @@ gst_object_ref_sink (gpointer object) * The reference count of @oldobj is decreased and the reference count of * @newobj is increased. * - * Either @newobj and the value pointed to by @oldobj may be NULL. + * Either @newobj and the value pointed to by @oldobj may be %NULL. * - * Returns: TRUE if @newobj was different from @oldobj + * Returns: %TRUE if @newobj was different from @oldobj */ gboolean gst_object_replace (GstObject ** oldobj, GstObject * newobj) @@ -474,7 +481,7 @@ gst_object_dispatch_properties_changed (GObject * object, * @orig: a #GstObject that initiated the notify. * @pspec: a #GParamSpec of the property. * @excluded_props: (array zero-terminated=1) (element-type gchar*) (allow-none): - * a set of user-specified properties to exclude or NULL to show + * a set of user-specified properties to exclude or %NULL to show * all changes. * * A default deep_notify signal callback for an object. The user data @@ -584,12 +591,12 @@ had_parent: * @name: new name of object * * Sets the name of @object, or gives @object a guaranteed unique - * name (if @name is NULL). + * name (if @name is %NULL). * This function makes a copy of the provided name, so the caller * retains ownership of the name it sent. * - * Returns: TRUE if the name could be set. Since Objects that have - * a parent cannot be renamed, this function returns FALSE in those + * Returns: %TRUE if the name could be set. Since Objects that have + * a parent cannot be renamed, this function returns %FALSE in those * cases. * * MT safe. This function grabs and releases @object's LOCK. @@ -637,7 +644,7 @@ had_parent: * * Returns a copy of the name of @object. * Caller should g_free() the return value after usage. - * For a nameless object, this returns NULL, which you can safely g_free() + * For a nameless object, this returns %NULL, which you can safely g_free() * as well. * * Free-function: g_free @@ -668,7 +675,7 @@ gst_object_get_name (GstObject * object) * Sets the parent of @object to @parent. The object's reference count will * be incremented, and any floating reference will be removed (see gst_object_ref_sink()). * - * Returns: TRUE if @parent could be set or FALSE when @object + * Returns: %TRUE if @parent could be set or %FALSE when @object * already had a parent or @object and @parent are the same. * * MT safe. Grabs and releases @object's LOCK. @@ -691,9 +698,11 @@ gst_object_set_parent (GstObject * object, GstObject * parent) gst_object_ref_sink (object); GST_OBJECT_UNLOCK (object); - /* FIXME, this does not work, the deep notify takes the lock from the parent - * object and deadlocks when the parent holds its lock when calling this - * function (like _element_add_pad()) */ + /* FIXME-2.0: this does not work, the deep notify takes the lock from the + * parent object and deadlocks when the parent holds its lock when calling + * this function (like _element_add_pad()), we need to use a GRecMutex + * for locking the parent instead. + */ /* g_object_notify_by_pspec ((GObject *)object, properties[PROP_PARENT]); */ return TRUE; @@ -715,7 +724,7 @@ had_parent: * Returns the parent of @object. This function increases the refcount * of the parent object so you should gst_object_unref() it after usage. * - * Returns: (transfer full): parent of @object, this can be NULL if @object + * Returns: (transfer full): parent of @object, this can be %NULL if @object * has no parent. unref after usage. * * MT safe. Grabs and releases @object's LOCK. @@ -776,7 +785,7 @@ gst_object_unparent (GstObject * object) * Check if @object has an ancestor @ancestor somewhere up in * the hierarchy. One can e.g. check if a #GstElement is inside a #GstPipeline. * - * Returns: TRUE if @ancestor is an ancestor of @object. + * Returns: %TRUE if @ancestor is an ancestor of @object. * * MT safe. Grabs and releases @object's locks. */ @@ -813,10 +822,10 @@ gst_object_has_ancestor (GstObject * object, GstObject * ancestor) * does not do any locking of any kind. You might want to protect the * provided list with the lock of the owner of the list. This function * will lock each #GstObject in the list to compare the name, so be - * carefull when passing a list with a locked object. + * careful when passing a list with a locked object. * - * Returns: TRUE if a #GstObject named @name does not appear in @list, - * FALSE if it does. + * Returns: %TRUE if a #GstObject named @name does not appear in @list, + * %FALSE if it does. * * MT safe. Grabs and releases the LOCK of each object in the list. */ @@ -921,7 +930,7 @@ gst_object_get_path_string (GstObject * object) path = g_strdup (""); /* first walk the object hierarchy to build a list of the parents, - * be carefull here with refcounting. */ + * be careful here with refcounting. */ do { if (GST_IS_OBJECT (object)) { parent = gst_object_get_parent (object); @@ -1136,8 +1145,8 @@ gst_object_set_control_bindings_disabled (GstObject * object, gboolean disabled) * @disabled: boolean that specifies whether to disable the controller * or not. * - * This function is used to disable the #GstController on a property for - * some time, i.e. gst_controller_sync_values() will do nothing for the + * This function is used to disable the control bindings on a property for + * some time, i.e. gst_object_sync_values() will do nothing for the * property. */ void diff --git a/gst/gstobject.h b/gst/gstobject.h index 209fe6c..86c5715 100644 --- a/gst/gstobject.h +++ b/gst/gstobject.h @@ -89,7 +89,7 @@ typedef enum * @obj: a #GstObject. * * This macro will try to obtain a lock on the object, but will return with - * FALSE if it can't get it immediately. + * %FALSE if it can't get it immediately. */ #define GST_OBJECT_TRYLOCK(obj) g_mutex_trylock(GST_OBJECT_GET_LOCK(obj)) /** @@ -145,7 +145,7 @@ typedef enum * @obj: a #GstObject * @flag: Flag to set * - * This macro usets the given bits. + * This macro unsets the given bits. */ #define GST_OBJECT_FLAG_UNSET(obj,flag) (GST_OBJECT_FLAGS (obj) &= ~(flag)) diff --git a/gst/gstpad.c b/gst/gstpad.c index 1261a47..09ce750 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -38,7 +38,7 @@ * application requests. * * Pads without pad templates can be created with gst_pad_new(), - * which takes a direction and a name as an argument. If the name is NULL, + * which takes a direction and a name as an argument. If the name is %NULL, * then a guaranteed unique name will be assigned to it. * * A #GstElement creating a pad will typically use the various @@ -47,7 +47,7 @@ * * gst_pad_get_parent() will retrieve the #GstElement that owns the pad. * - * After two pads are retrieved from an element with gst_element_get_pad(), + * After two pads are retrieved from an element by gst_element_get_static_pad(), * the pads can be linked with gst_pad_link(). (For quick links, * you can also use gst_element_link(), which will make the obvious * link for you if it's straightforward.). Pads can be unlinked again with @@ -84,8 +84,6 @@ * Convenience functions exist to start, pause and stop the task on a pad with * gst_pad_start_task(), gst_pad_pause_task() and gst_pad_stop_task() * respectively. - * - * Last reviewed on 2012-03-29 (0.11.3) */ #include "gst_private.h" @@ -125,7 +123,7 @@ enum /* we have a pending and an active event on the pad. On source pads only the * active event is used. On sinkpads, events are copied to the pending entry and - * moved to the active event when the eventfunc returned TRUE. */ + * moved to the active event when the eventfunc returned %TRUE. */ typedef struct { gboolean received; @@ -136,6 +134,7 @@ struct _GstPadPrivate { guint events_cookie; GArray *events; + guint last_cookie; gint using; guint probe_list_cookie; @@ -250,6 +249,38 @@ gst_flow_to_quark (GstFlowReturn ret) return 0; } +/** + * gst_pad_link_get_name: + * @ret: a #GstPadLinkReturn to get the name of. + * + * Gets a string representing the given pad-link return. + * + * Returns: a static string with the name of the pad-link return. + * + * Since: 1.4 + */ +const gchar * +gst_pad_link_get_name (GstPadLinkReturn ret) +{ + switch (ret) { + case GST_PAD_LINK_OK: + return "ok"; + case GST_PAD_LINK_WRONG_HIERARCHY: + return "wrong hierarchy"; + case GST_PAD_LINK_WAS_LINKED: + return "was linked"; + case GST_PAD_LINK_WRONG_DIRECTION: + return "wrong direction"; + case GST_PAD_LINK_NOFORMAT: + return "no common format"; + case GST_PAD_LINK_NOSCHED: + return "incompatible scheduling"; + case GST_PAD_LINK_REFUSED: + return "refused"; + } + g_return_val_if_reached ("unknown"); +} + #define _do_init \ { \ gint i; \ @@ -356,6 +387,9 @@ gst_pad_init (GstPad * pad) g_hook_list_init (&pad->probes, sizeof (GstProbe)); pad->priv->events = g_array_sized_new (FALSE, TRUE, sizeof (PadEvent), 16); + pad->priv->events_cookie = 0; + pad->priv->last_cookie = -1; + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; } /* called when setting the pad inactive. It removes all sticky events from @@ -470,7 +504,7 @@ remove_event_by_type (GstPad * pad, GstEventType type) } /* check all events on srcpad against those on sinkpad. All events that are not - * on sinkpad are marked as received=FALSE and the PENDING_EVENTS is set on the + * on sinkpad are marked as received=%FALSE and the PENDING_EVENTS is set on the * srcpad so that the events will be sent next time */ /* should be called with srcpad and sinkpad LOCKS */ static void @@ -566,20 +600,35 @@ restart: /* should be called with LOCK */ static GstEvent * -apply_pad_offset (GstPad * pad, GstEvent * event) +apply_pad_offset (GstPad * pad, GstEvent * event, gboolean upstream) { /* check if we need to adjust the segment */ if (pad->offset != 0) { - GstSegment segment; - - /* copy segment values */ - gst_event_copy_segment (event, &segment); - gst_event_unref (event); + gint64 offset; GST_DEBUG_OBJECT (pad, "apply pad offset %" GST_TIME_FORMAT, GST_TIME_ARGS (pad->offset)); - gst_segment_offset_running_time (&segment, segment.format, pad->offset); - event = gst_event_new_segment (&segment); + + if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) { + GstSegment segment; + + g_assert (!upstream); + + /* copy segment values */ + gst_event_copy_segment (event, &segment); + gst_event_unref (event); + + gst_segment_offset_running_time (&segment, segment.format, pad->offset); + event = gst_event_new_segment (&segment); + } + + event = gst_event_make_writable (event); + offset = gst_event_get_running_time_offset (event); + if (upstream) + offset -= pad->offset; + else + offset += pad->offset; + gst_event_set_running_time_offset (event, offset); } return event; } @@ -721,11 +770,11 @@ gst_pad_get_property (GObject * object, guint prop_id, * @direction: the #GstPadDirection of the pad. * * Creates a new pad with the given name in the given direction. - * If name is NULL, a guaranteed unique name (across all pads) + * If name is %NULL, a guaranteed unique name (across all pads) * will be assigned. * This function makes a copy of the name so you can safely free the name. * - * Returns: (transfer floating): a new #GstPad, or NULL in case of an error. + * Returns: (transfer floating): a new #GstPad, or %NULL in case of an error. * * MT safe. */ @@ -742,11 +791,11 @@ gst_pad_new (const gchar * name, GstPadDirection direction) * @name: the name of the element * * Creates a new pad with the given name from the given template. - * If name is NULL, a guaranteed unique name (across all pads) + * If name is %NULL, a guaranteed unique name (across all pads) * will be assigned. * This function makes a copy of the name so you can safely free the name. * - * Returns: (transfer full): a new #GstPad, or NULL in case of an error. + * Returns: (transfer floating): a new #GstPad, or %NULL in case of an error. */ GstPad * gst_pad_new_from_template (GstPadTemplate * templ, const gchar * name) @@ -763,11 +812,11 @@ gst_pad_new_from_template (GstPadTemplate * templ, const gchar * name) * @name: the name of the element * * Creates a new pad with the given name from the given static template. - * If name is NULL, a guaranteed unique name (across all pads) + * If name is %NULL, a guaranteed unique name (across all pads) * will be assigned. * This function makes a copy of the name so you can safely free the name. * - * Returns: (transfer full): a new #GstPad, or NULL in case of an error. + * Returns: (transfer floating): a new #GstPad, or %NULL in case of an error. */ GstPad * gst_pad_new_from_static_template (GstStaticPadTemplate * templ, @@ -860,6 +909,7 @@ pre_activate (GstPad * pad, GstPadMode new_mode) GST_OBJECT_LOCK (pad); GST_DEBUG_OBJECT (pad, "setting PAD_MODE NONE, set flushing"); GST_PAD_SET_FLUSHING (pad); + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; GST_PAD_MODE (pad) = new_mode; /* unlock blocked pads so element can resume and stop */ GST_PAD_BLOCK_BROADCAST (pad); @@ -871,6 +921,7 @@ pre_activate (GstPad * pad, GstPadMode new_mode) GST_DEBUG_OBJECT (pad, "setting pad into %s mode, unset flushing", gst_pad_mode_get_name (new_mode)); GST_PAD_UNSET_FLUSHING (pad); + pad->ABI.abi.last_flowret = GST_FLOW_OK; GST_PAD_MODE (pad) = new_mode; if (GST_PAD_IS_SINK (pad)) { GstPad *peer; @@ -930,9 +981,9 @@ post_activate (GstPad * pad, GstPadMode new_mode) * function to perform the actual activation. * * If not @active, calls gst_pad_activate_mode() with the pad's current mode - * and a FALSE argument. + * and a %FALSE argument. * - * Returns: #TRUE if the operation was successful. + * Returns: %TRUE if the operation was successful. * * MT safe. */ @@ -954,6 +1005,8 @@ gst_pad_set_active (GstPad * pad, gboolean active) if (old == GST_PAD_MODE_NONE) { GST_DEBUG_OBJECT (pad, "activating pad from none"); ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad, parent); + if (ret) + pad->ABI.abi.last_flowret = GST_FLOW_OK; } else { GST_DEBUG_OBJECT (pad, "pad was active in %s mode", gst_pad_mode_get_name (old)); @@ -967,6 +1020,8 @@ gst_pad_set_active (GstPad * pad, gboolean active) GST_DEBUG_OBJECT (pad, "deactivating pad from %s mode", gst_pad_mode_get_name (old)); ret = gst_pad_activate_mode (pad, old, FALSE); + if (ret) + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; } } @@ -1009,7 +1064,7 @@ failed: * * If you don't know what this is, you probably don't want to call it. * - * Returns: TRUE if the operation was successful. + * Returns: %TRUE if the operation was successful. * * MT safe. */ @@ -1161,7 +1216,7 @@ failure: * * Query if a pad is active * - * Returns: TRUE if the pad is active. + * Returns: %TRUE if the pad is active. * * MT safe. */ @@ -1219,8 +1274,10 @@ cleanup_hook (GstPad * pad, GHook * hook) * Be notified of different states of pads. The provided callback is called for * every state that matches @mask. * - * Returns: an id or 0 on error. The id can be used to remove the probe with - * gst_pad_remove_probe(). + * Returns: an id or 0 if no probe is pending. The id can be used to remove the + * probe with gst_pad_remove_probe(). When using GST_PAD_PROBE_TYPE_IDLE it can + * happend that the probe can be run immediately and if the probe returns + * GST_PAD_PROBE_REMOVE this functions returns 0. * * MT safe. */ @@ -1379,7 +1436,7 @@ not_found: * last requested state of the pad. It is not certain that the pad * is actually blocking at this point (see gst_pad_is_blocking()). * - * Returns: TRUE if the pad is blocked. + * Returns: %TRUE if the pad is blocked. * * MT safe. */ @@ -1404,7 +1461,7 @@ gst_pad_is_blocked (GstPad * pad) * Checks if the pad is blocking or not. This is a guaranteed state * of whether the pad is actually blocking on a #GstBuffer or a #GstEvent. * - * Returns: TRUE if the pad is blocking. + * Returns: %TRUE if the pad is blocking. * * MT safe. */ @@ -1496,7 +1553,7 @@ gst_pad_mark_reconfigure (GstPad * pad) * @p: a #GstPad. * @f: the #GstPadActivateFunction to set. * - * Calls gst_pad_set_activate_function_full() with NULL for the user_data and + * Calls gst_pad_set_activate_function_full() with %NULL for the user_data and * notify. */ /** @@ -1533,7 +1590,7 @@ gst_pad_set_activate_function_full (GstPad * pad, * @p: a #GstPad. * @f: the #GstPadActivateModeFunction to set. * - * Calls gst_pad_set_activatemode_function_full() with NULL for the user_data and + * Calls gst_pad_set_activatemode_function_full() with %NULL for the user_data and * notify. */ /** @@ -1568,7 +1625,7 @@ gst_pad_set_activatemode_function_full (GstPad * pad, * @p: a sink #GstPad. * @f: the #GstPadChainFunction to set. * - * Calls gst_pad_set_chain_function_full() with NULL for the user_data and + * Calls gst_pad_set_chain_function_full() with %NULL for the user_data and * notify. */ /** @@ -1603,7 +1660,7 @@ gst_pad_set_chain_function_full (GstPad * pad, GstPadChainFunction chain, * @p: a sink #GstPad. * @f: the #GstPadChainListFunction to set. * - * Calls gst_pad_set_chain_list_function_full() with NULL for the user_data and + * Calls gst_pad_set_chain_list_function_full() with %NULL for the user_data and * notify. */ /** @@ -1640,7 +1697,7 @@ gst_pad_set_chain_list_function_full (GstPad * pad, * @p: a source #GstPad. * @f: the #GstPadGetRangeFunction to set. * - * Calls gst_pad_set_getrange_function_full() with NULL for the user_data and + * Calls gst_pad_set_getrange_function_full() with %NULL for the user_data and * notify. */ /** @@ -1676,7 +1733,7 @@ gst_pad_set_getrange_function_full (GstPad * pad, GstPadGetRangeFunction get, * @p: a #GstPad of either direction. * @f: the #GstPadEventFunction to set. * - * Calls gst_pad_set_event_function_full() with NULL for the user_data and + * Calls gst_pad_set_event_function_full() with %NULL for the user_data and * notify. */ /** @@ -1709,7 +1766,7 @@ gst_pad_set_event_function_full (GstPad * pad, GstPadEventFunction event, * @p: a #GstPad of either direction. * @f: the #GstPadQueryFunction to set. * - * Calls gst_pad_set_query_function_full() with NULL for the user_data and + * Calls gst_pad_set_query_function_full() with %NULL for the user_data and * notify. */ /** @@ -1742,7 +1799,7 @@ gst_pad_set_query_function_full (GstPad * pad, GstPadQueryFunction query, * @p: a #GstPad of either direction. * @f: the #GstPadIterIntLinkFunction to set. * - * Calls gst_pad_set_iterate_internal_links_function_full() with NULL + * Calls gst_pad_set_iterate_internal_links_function_full() with %NULL * for the user_data and notify. */ /** @@ -1776,7 +1833,7 @@ gst_pad_set_iterate_internal_links_function_full (GstPad * pad, * @p: a #GstPad. * @f: the #GstPadLinkFunction to set. * - * Calls gst_pad_set_link_function_full() with NULL + * Calls gst_pad_set_link_function_full() with %NULL * for the user_data and notify. */ /** @@ -1819,7 +1876,7 @@ gst_pad_set_link_function_full (GstPad * pad, GstPadLinkFunction link, * @p: a #GstPad. * @f: the #GstPadUnlinkFunction to set. * - * Calls gst_pad_set_unlink_function_full() with NULL + * Calls gst_pad_set_unlink_function_full() with %NULL * for the user_data and notify. */ /** @@ -1856,7 +1913,7 @@ gst_pad_set_unlink_function_full (GstPad * pad, GstPadUnlinkFunction unlink, * Unlinks the source pad from the sink pad. Will emit the #GstPad::unlinked * signal on both pads. * - * Returns: TRUE if the pads were unlinked. This function returns FALSE if + * Returns: %TRUE if the pads were unlinked. This function returns %FALSE if * the pads were not linked together. * * MT safe. @@ -1958,7 +2015,7 @@ not_linked_together: * * Checks if a @pad is linked to another pad or not. * - * Returns: TRUE if the pad is linked, FALSE otherwise. + * Returns: %TRUE if the pad is linked, %FALSE otherwise. * * MT safe. */ @@ -2022,7 +2079,7 @@ gst_pad_link_check_compatible_unlocked (GstPad * src, GstPad * sink, sinkcaps); /* if we have caps on both pads we can check the intersection. If one - * of the caps is NULL, we return TRUE. */ + * of the caps is %NULL, we return %TRUE. */ if (G_UNLIKELY (srccaps == NULL || sinkcaps == NULL)) { if (srccaps) gst_caps_unref (srccaps); @@ -2037,7 +2094,7 @@ gst_pad_link_check_compatible_unlocked (GstPad * src, GstPad * sink, done: GST_CAT_DEBUG (GST_CAT_CAPS, "caps are %scompatible", - (compatible ? "" : "not")); + (compatible ? "" : "not ")); return compatible; } @@ -2188,7 +2245,7 @@ no_format: * Checks if the source pad and the sink pad are compatible so they can be * linked. * - * Returns: TRUE if the pads can be linked. + * Returns: %TRUE if the pads can be linked. */ gboolean gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad) @@ -2347,8 +2404,9 @@ concurrent_link: } link_failed: { - GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed", - GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); + GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed: %s", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad), + gst_pad_link_get_name (result)); GST_PAD_PEER (srcpad) = NULL; GST_PAD_PEER (sinkpad) = NULL; @@ -2422,7 +2480,7 @@ gst_pad_get_pad_template (GstPad * pad) * * Check if @pad has caps set on it with a #GST_EVENT_CAPS event. * - * Returns: TRUE when @pad has caps associated with it. + * Returns: %TRUE when @pad has caps associated with it. */ gboolean gst_pad_has_current_caps (GstPad * pad) @@ -2527,7 +2585,7 @@ gst_pad_get_peer (GstPad * pad) * on the resulting caps. * * Returns: (transfer full): the allowed #GstCaps of the pad link. Unref the - * caps when you no longer need it. This function returns NULL when @pad + * caps when you no longer need it. This function returns %NULL when @pad * has no peer. * * MT safe. @@ -2574,7 +2632,7 @@ no_peer: /** * gst_pad_iterate_internal_links_default: * @pad: the #GstPad to get the internal links of. - * @parent: (allow-none): the parent of @pad or NULL + * @parent: (allow-none): the parent of @pad or %NULL * * Iterate the list of pads to which the given pad is linked to inside of * the parent element. @@ -2583,7 +2641,7 @@ no_peer: * * The caller must free this iterator after use with gst_iterator_free(). * - * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each + * Returns: a #GstIterator of #GstPad, or %NULL if @pad has no parent. Unref each * returned pad with gst_object_unref(). */ GstIterator * @@ -2691,9 +2749,9 @@ no_parent: * dynamically changing internal pads and will make sure that the @forward * function is only called once for each pad. * - * When @forward returns TRUE, no further pads will be processed. + * When @forward returns %TRUE, no further pads will be processed. * - * Returns: TRUE if one of the dispatcher functions returned TRUE. + * Returns: %TRUE if one of the dispatcher functions returned %TRUE. */ gboolean gst_pad_forward (GstPad * pad, GstPadForwardFunction forward, @@ -2783,7 +2841,7 @@ event_forward_func (GstPad * pad, EventData * data) /** * gst_pad_event_default: * @pad: a #GstPad to call the default event handler on. - * @parent: (allow-none): the parent of @pad or NULL + * @parent: (allow-none): the parent of @pad or %NULL * @event: (transfer full): the #GstEvent to handle. * * Invokes the default event handler for the given pad. @@ -2794,7 +2852,7 @@ event_forward_func (GstPad * pad, EventData * data) * The the event is sent to all pads internally linked to @pad. This function * takes ownership of @event. * - * Returns: TRUE if the event was sent successfully. + * Returns: %TRUE if the event was sent successfully. */ gboolean gst_pad_event_default (GstPad * pad, GstObject * parent, GstEvent * event) @@ -2864,8 +2922,16 @@ gst_pad_query_accept_caps_default (GstPad * pad, GstQuery * query) allowed = gst_pad_query_caps (pad, caps); if (allowed) { - GST_DEBUG_OBJECT (pad, "allowed caps %" GST_PTR_FORMAT, allowed); - result = gst_caps_is_subset (caps, allowed); + if (GST_PAD_IS_ACCEPT_INTERSECT (pad)) { + GST_DEBUG_OBJECT (pad, + "allowed caps intersect %" GST_PTR_FORMAT ", caps %" GST_PTR_FORMAT, + allowed, caps); + result = gst_caps_can_intersect (caps, allowed); + } else { + GST_DEBUG_OBJECT (pad, "allowed caps subset %" GST_PTR_FORMAT ", caps %" + GST_PTR_FORMAT, allowed, caps); + result = gst_caps_is_subset (caps, allowed); + } gst_caps_unref (allowed); } else { GST_DEBUG_OBJECT (pad, "no compatible caps allowed on the pad"); @@ -2973,7 +3039,7 @@ query_forward_func (GstPad * pad, QueryData * data) /** * gst_pad_query_default: * @pad: a #GstPad to call the default query handler on. - * @parent: (allow-none): the parent of @pad or NULL + * @parent: (allow-none): the parent of @pad or %NULL * @query: (transfer none): the #GstQuery to handle. * * Invokes the default query handler for the given pad. @@ -2982,7 +3048,7 @@ query_forward_func (GstPad * pad, QueryData * data) * @pad, only one will be sent the query. * Multi-sinkpad elements should implement custom query handlers. * - * Returns: TRUE if the query was performed successfully. + * Returns: %TRUE if the query was performed successfully. */ gboolean gst_pad_query_default (GstPad * pad, GstObject * parent, GstQuery * query) @@ -3293,6 +3359,13 @@ gst_pad_get_offset (GstPad * pad) return result; } +static gboolean +mark_event_not_received (GstPad * pad, PadEvent * ev, gpointer user_data) +{ + ev->received = FALSE; + return TRUE; +} + /** * gst_pad_set_offset: * @pad: a #GstPad @@ -3303,8 +3376,6 @@ gst_pad_get_offset (GstPad * pad) void gst_pad_set_offset (GstPad * pad, gint64 offset) { - PadEvent *ev; - g_return_if_fail (GST_IS_PAD (pad)); GST_OBJECT_LOCK (pad); @@ -3315,16 +3386,9 @@ gst_pad_set_offset (GstPad * pad, gint64 offset) pad->offset = offset; GST_DEBUG_OBJECT (pad, "changed offset to %" G_GINT64_FORMAT, offset); - /* sinkpads will apply their offset the next time a segment - * event is received. */ - if (GST_PAD_IS_SINK (pad)) - goto done; - - /* resend the last segment event on next buffer push */ - if ((ev = find_event_by_type (pad, GST_EVENT_SEGMENT, 0))) { - ev->received = FALSE; - GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); - } + /* resend all sticky events with updated offset on next buffer push */ + events_foreach (pad, mark_event_not_received, NULL); + GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS); done: GST_OBJECT_UNLOCK (pad); @@ -3465,7 +3529,7 @@ check_sticky (GstPad * pad, GstEvent * event) * * Please also note that some queries might need a running pipeline to work. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ gboolean gst_pad_query (GstPad * pad, GstQuery * query) @@ -3590,7 +3654,7 @@ probe_stopped: * The caller is responsible for both the allocation and deallocation of * the query structure. * - * Returns: TRUE if the query could be performed. This function returns %FALSE + * Returns: %TRUE if the query could be performed. This function returns %FALSE * if @pad has no peer. */ gboolean @@ -3624,7 +3688,7 @@ gst_pad_peer_query (GstPad * pad, GstQuery * query) if (GST_PAD_IS_SRC (pad) && serialized) { /* all serialized queries on the srcpad trigger push of * sticky events */ - if (!check_sticky (pad, NULL) == GST_FLOW_OK) + if (check_sticky (pad, NULL) != GST_FLOW_OK) goto sticky_failed; } @@ -3723,15 +3787,18 @@ gst_pad_chain_data_unchecked (GstPad * pad, GstPadProbeType type, void *data) goto wrong_mode; #ifndef G_DISABLE_ASSERT - if (!find_event_by_type (pad, GST_EVENT_STREAM_START, 0)) { - g_warning (G_STRLOC - ":%s:<%s:%s> Got data flow before stream-start event", - G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); - } - if (!find_event_by_type (pad, GST_EVENT_SEGMENT, 0)) { - g_warning (G_STRLOC - ":%s:<%s:%s> Got data flow before segment event", - G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); + if (G_UNLIKELY (pad->priv->last_cookie != pad->priv->events_cookie)) { + if (!find_event_by_type (pad, GST_EVENT_STREAM_START, 0)) { + g_warning (G_STRLOC + ":%s:<%s:%s> Got data flow before stream-start event", + G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); + } + if (!find_event_by_type (pad, GST_EVENT_SEGMENT, 0)) { + g_warning (G_STRLOC + ":%s:<%s:%s> Got data flow before segment event", + G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); + } + pad->priv->last_cookie = pad->priv->events_cookie; } #endif @@ -3822,7 +3889,7 @@ probe_stopped: ret = GST_FLOW_OK; break; default: - GST_DEBUG_OBJECT (pad, "an error occured %s", gst_flow_get_name (ret)); + GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret)); break; } return ret; @@ -3848,7 +3915,7 @@ no_function: * The function returns #GST_FLOW_FLUSHING if the pad was flushing. * * If the buffer type is not acceptable for @pad (as negotiated with a - * preceeding GST_EVENT_CAPS event), this function returns + * preceding GST_EVENT_CAPS event), this function returns * #GST_FLOW_NOT_NEGOTIATED. * * The function proceeds calling the chain function installed on @pad (see @@ -3954,15 +4021,18 @@ gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data) goto wrong_mode; #ifndef G_DISABLE_ASSERT - if (!find_event_by_type (pad, GST_EVENT_STREAM_START, 0)) { - g_warning (G_STRLOC - ":%s:<%s:%s> Got data flow before stream-start event", - G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); - } - if (!find_event_by_type (pad, GST_EVENT_SEGMENT, 0)) { - g_warning (G_STRLOC - ":%s:<%s:%s> Got data flow before segment event", - G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); + if (G_UNLIKELY (pad->priv->last_cookie != pad->priv->events_cookie)) { + if (!find_event_by_type (pad, GST_EVENT_STREAM_START, 0)) { + g_warning (G_STRLOC + ":%s:<%s:%s> Got data flow before stream-start event", + G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); + } + if (!find_event_by_type (pad, GST_EVENT_SEGMENT, 0)) { + g_warning (G_STRLOC + ":%s:<%s:%s> Got data flow before segment event", + G_STRFUNC, GST_DEBUG_PAD_NAME (pad)); + } + pad->priv->last_cookie = pad->priv->events_cookie; } #endif @@ -3992,6 +4062,7 @@ gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data) gst_object_unref (peer); GST_OBJECT_LOCK (pad); + pad->ABI.abi.last_flowret = ret; pad->priv->using--; if (pad->priv->using == 0) { /* pad is not active anymore, trigger idle callbacks */ @@ -4008,6 +4079,7 @@ flushing: { GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing, but pad was flushing"); + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; GST_OBJECT_UNLOCK (pad); gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); return GST_FLOW_FLUSHING; @@ -4015,6 +4087,7 @@ flushing: eos: { GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing, but pad was EOS"); + pad->ABI.abi.last_flowret = GST_FLOW_EOS; GST_OBJECT_UNLOCK (pad); gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); return GST_FLOW_EOS; @@ -4023,6 +4096,7 @@ wrong_mode: { g_critical ("pushing on pad %s:%s but it was not activated in push mode", GST_DEBUG_PAD_NAME (pad)); + pad->ABI.abi.last_flowret = GST_FLOW_ERROR; GST_OBJECT_UNLOCK (pad); gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); return GST_FLOW_ERROR; @@ -4031,6 +4105,7 @@ events_error: { GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "error pushing events, return %s", gst_flow_get_name (ret)); + pad->ABI.abi.last_flowret = ret; GST_OBJECT_UNLOCK (pad); gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); return ret; @@ -4038,6 +4113,8 @@ events_error: probe_stopped: { GST_OBJECT_UNLOCK (pad); + pad->ABI.abi.last_flowret = + ret == GST_FLOW_CUSTOM_SUCCESS ? GST_FLOW_OK : ret; gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); switch (ret) { @@ -4046,7 +4123,7 @@ probe_stopped: ret = GST_FLOW_OK; break; default: - GST_DEBUG_OBJECT (pad, "an error occured %s", gst_flow_get_name (ret)); + GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret)); break; } return ret; @@ -4055,6 +4132,7 @@ not_linked: { GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing, but it was not linked"); + pad->ABI.abi.last_flowret = GST_FLOW_NOT_LINKED; GST_OBJECT_UNLOCK (pad); gst_mini_object_unref (GST_MINI_OBJECT_CAST (data)); return GST_FLOW_NOT_LINKED; @@ -4177,14 +4255,15 @@ gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size, RELEASE_PARENT (parent); + GST_OBJECT_LOCK (pad); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto get_range_failed; /* can only fire the signal if we have a valid buffer */ - GST_OBJECT_LOCK (pad); probed_data: PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER, res_buf, offset, size, probe_stopped_unref); + pad->ABI.abi.last_flowret = ret; GST_OBJECT_UNLOCK (pad); GST_PAD_STREAM_UNLOCK (pad); @@ -4198,6 +4277,7 @@ flushing: { GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "getrange, but pad was flushing"); + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; GST_OBJECT_UNLOCK (pad); GST_PAD_STREAM_UNLOCK (pad); return GST_FLOW_FLUSHING; @@ -4206,6 +4286,7 @@ wrong_mode: { g_critical ("getrange on pad %s:%s but it was not activated in pull mode", GST_DEBUG_PAD_NAME (pad)); + pad->ABI.abi.last_flowret = GST_FLOW_ERROR; GST_OBJECT_UNLOCK (pad); GST_PAD_STREAM_UNLOCK (pad); return GST_FLOW_ERROR; @@ -4213,6 +4294,7 @@ wrong_mode: events_error: { GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "error pushing events"); + pad->ABI.abi.last_flowret = ret; GST_OBJECT_UNLOCK (pad); GST_PAD_STREAM_UNLOCK (pad); return ret; @@ -4220,6 +4302,7 @@ events_error: no_parent: { GST_DEBUG_OBJECT (pad, "no parent"); + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; GST_OBJECT_UNLOCK (pad); GST_PAD_STREAM_UNLOCK (pad); return GST_FLOW_FLUSHING; @@ -4249,6 +4332,7 @@ probe_stopped: ret = GST_FLOW_EOS; } } + pad->ABI.abi.last_flowret = ret; GST_OBJECT_UNLOCK (pad); GST_PAD_STREAM_UNLOCK (pad); @@ -4261,6 +4345,7 @@ probe_stopped_unref: /* if we drop here, it signals EOS */ if (ret == GST_FLOW_CUSTOM_SUCCESS) ret = GST_FLOW_EOS; + pad->ABI.abi.last_flowret = ret; GST_OBJECT_UNLOCK (pad); GST_PAD_STREAM_UNLOCK (pad); if (*buffer == NULL) @@ -4269,6 +4354,8 @@ probe_stopped_unref: } get_range_failed: { + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); GST_PAD_STREAM_UNLOCK (pad); GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING, (ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING, @@ -4293,7 +4380,7 @@ get_range_failed: * installed (see gst_pad_set_getrange_function()) this function returns * #GST_FLOW_NOT_SUPPORTED. * - * If @buffer points to a variable holding NULL, a valid new #GstBuffer will be + * If @buffer points to a variable holding %NULL, a valid new #GstBuffer will be * placed in @buffer when this function returns #GST_FLOW_OK. The new buffer * must be freed with gst_buffer_unref() after usage. * @@ -4310,7 +4397,7 @@ get_range_failed: * When this function returns any other result value than #GST_FLOW_OK, @buffer * will be unchanged. * - * This is a lowlevel function. Usualy gst_pad_pull_range() is used. + * This is a lowlevel function. Usually gst_pad_pull_range() is used. * * Returns: a #GstFlowReturn from the pad. * @@ -4347,10 +4434,10 @@ gst_pad_get_range (GstPad * pad, guint64 offset, guint size, * See gst_pad_get_range() for a list of return values and for the * semantics of the arguments of this function. * - * If @buffer points to a variable holding NULL, a valid new #GstBuffer will be + * If @buffer points to a variable holding %NULL, a valid new #GstBuffer will be * placed in @buffer when this function returns #GST_FLOW_OK. The new buffer * must be freed with gst_buffer_unref() after usage. When this function - * returns any other result value, @buffer will still point to NULL. + * returns any other result value, @buffer will still point to %NULL. * * When @buffer points to a variable that points to a valid #GstBuffer, the * buffer will be filled with the result data when this function returns @@ -4409,6 +4496,7 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, GST_OBJECT_LOCK (pad); pad->priv->using--; + pad->ABI.abi.last_flowret = ret; if (pad->priv->using == 0) { /* pad is not active anymore, trigger idle callbacks */ PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_IDLE, @@ -4433,6 +4521,7 @@ flushing: { GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pullrange, but pad was flushing"); + pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; GST_OBJECT_UNLOCK (pad); return GST_FLOW_FLUSHING; } @@ -4440,6 +4529,7 @@ wrong_mode: { g_critical ("pullrange on pad %s:%s but it was not activated in pull mode", GST_DEBUG_PAD_NAME (pad)); + pad->ABI.abi.last_flowret = GST_FLOW_ERROR; GST_OBJECT_UNLOCK (pad); return GST_FLOW_ERROR; } @@ -4460,6 +4550,7 @@ probe_stopped: ret = GST_FLOW_EOS; } } + pad->ABI.abi.last_flowret = ret; GST_OBJECT_UNLOCK (pad); return ret; } @@ -4467,11 +4558,13 @@ not_linked: { GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pulling range, but it was not linked"); + pad->ABI.abi.last_flowret = GST_FLOW_NOT_LINKED; GST_OBJECT_UNLOCK (pad); return GST_FLOW_NOT_LINKED; } pull_range_failed: { + pad->ABI.abi.last_flowret = ret; GST_OBJECT_UNLOCK (pad); GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING, (ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING, @@ -4482,10 +4575,14 @@ probe_stopped_unref: { GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "post probe returned %s", gst_flow_get_name (ret)); - GST_OBJECT_UNLOCK (pad); + /* if we drop here, it signals EOS */ if (ret == GST_FLOW_CUSTOM_SUCCESS) ret = GST_FLOW_EOS; + + pad->ABI.abi.last_flowret = ret; + GST_OBJECT_UNLOCK (pad); + if (*buffer == NULL) gst_buffer_unref (res_buf); return ret; @@ -4505,7 +4602,7 @@ store_sticky_event (GstPad * pad, GstEvent * event) type = GST_EVENT_TYPE (event); - /* Store all sticky events except SEGMENT/SEGMENT when we're flushing, + /* Store all sticky events except SEGMENT/EOS when we're flushing, * otherwise they can be dropped and nothing would ever resend them. * Only do that for activated pads though, everything else is a bug! */ @@ -4583,8 +4680,10 @@ store_sticky_event (GstPad * pad, GstEvent * event) break; } } - if (type == GST_EVENT_EOS) + if (type == GST_EVENT_EOS) { GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_EOS); + pad->ABI.abi.last_flowret = GST_FLOW_EOS; + } return GST_PAD_IS_FLUSHING (pad) ? GST_FLOW_FLUSHING : GST_FLOW_OK; @@ -4650,6 +4749,10 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event, GstPad *peerpad; GstEventType event_type; + /* pass the adjusted event on. We need to do this even if + * there is no peer pad because of the probes. */ + event = apply_pad_offset (pad, event, GST_PAD_IS_SINK (pad)); + /* Two checks to be made: * . (un)set the FLUSHING flag for flushing events, * . handle pad blocking */ @@ -4669,6 +4772,7 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event, remove_event_by_type (pad, GST_EVENT_EOS); remove_event_by_type (pad, GST_EVENT_SEGMENT); GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); + pad->ABI.abi.last_flowret = GST_FLOW_OK; type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH; break; @@ -4683,11 +4787,6 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event, */ switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEGMENT: - /* pass the adjusted segment event on. We need to do this even if - * there is no peer pad because of the probes. */ - event = apply_pad_offset (pad, event); - break; case GST_EVENT_RECONFIGURE: if (GST_PAD_IS_SINK (pad)) GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE); @@ -4726,14 +4825,15 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event, GST_OBJECT_UNLOCK (pad); GST_LOG_OBJECT (pad, "sending event %p (%s) to peerpad %" GST_PTR_FORMAT, - event, GST_EVENT_TYPE_NAME (event), peerpad); + event, gst_event_type_get_name (event_type), peerpad); ret = gst_pad_send_event_unchecked (peerpad, event, type); /* Note: we gave away ownership of the event at this point but we can still * print the old pointer */ - GST_LOG_OBJECT (pad, "sent event %p to peerpad %" GST_PTR_FORMAT ", ret %s", - event, peerpad, gst_flow_get_name (ret)); + GST_LOG_OBJECT (pad, + "sent event %p to (%s) peerpad %" GST_PTR_FORMAT ", ret %s", event, + gst_event_type_get_name (event_type), peerpad, gst_flow_get_name (ret)); gst_object_unref (peerpad); @@ -4763,7 +4863,7 @@ probe_stopped: GST_DEBUG_OBJECT (pad, "dropped event"); break; default: - GST_DEBUG_OBJECT (pad, "an error occured %s", gst_flow_get_name (ret)); + GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret)); break; } return ret; @@ -4797,10 +4897,10 @@ idle_probe_stopped: * mainly used by elements to send events to their peer * elements. * - * This function takes owership of the provided event so you should + * This function takes ownership of the provided event so you should * gst_event_ref() it if you want to reuse the event after this call. * - * Returns: TRUE if the event was handled. + * Returns: %TRUE if the event was handled. * * MT safe. */ @@ -4940,6 +5040,9 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, GstObject *parent; GST_OBJECT_LOCK (pad); + + event = apply_pad_offset (pad, event, GST_PAD_IS_SRC (pad)); + if (GST_PAD_IS_SINK (pad)) serialized = GST_EVENT_IS_SERIALIZED (event); else @@ -4968,6 +5071,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, remove_event_by_type (pad, GST_EVENT_EOS); remove_event_by_type (pad, GST_EVENT_SEGMENT); GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS); + pad->ABI.abi.last_flowret = GST_FLOW_OK; GST_OBJECT_UNLOCK (pad); /* grab stream lock */ @@ -5002,14 +5106,6 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event, if (G_UNLIKELY (GST_PAD_IS_EOS (pad))) goto eos; } - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEGMENT: - event = apply_pad_offset (pad, event); - break; - default: - break; - } break; } @@ -5107,7 +5203,7 @@ probe_stopped: ret = GST_FLOW_OK; break; default: - GST_DEBUG_OBJECT (pad, "an error occured %s", gst_flow_get_name (ret)); + GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret)); break; } return ret; @@ -5165,10 +5261,10 @@ precheck_failed: * plugin doesn't need to bother itself with this information; the core handles * all necessary locks and checks. * - * This function takes owership of the provided event so you should + * This function takes ownership of the provided event so you should * gst_event_ref() it if you want to reuse the event after this call. * - * Returns: TRUE if the event was handled. + * Returns: %TRUE if the event was handled. */ gboolean gst_pad_send_event (GstPad * pad, GstEvent * event) @@ -5252,7 +5348,7 @@ gst_pad_get_element_private (GstPad * pad) * Returns a new reference of the sticky event of type @event_type * from the event. * - * Returns: (transfer full): a #GstEvent of type @event_type or NULL when no + * Returns: (transfer full): a #GstEvent of type @event_type or %NULL when no * event of @event_type was on @pad. Unref after usage. */ GstEvent * @@ -5448,7 +5544,7 @@ concurrent_stop: * function executed by the task is finished if this function is not * called from the task function. * - * Returns: a TRUE if the task could be paused or FALSE when the pad + * Returns: a %TRUE if the task could be paused or %FALSE when the pad * has no task. */ gboolean @@ -5497,7 +5593,7 @@ no_task: * Regardless of whether the pad has a task, the stream lock is acquired and * released so as to ensure that streaming through this pad has finished. * - * Returns: a TRUE if the task could be stopped or FALSE on error. + * Returns: a %TRUE if the task could be stopped or %FALSE on error. */ gboolean gst_pad_stop_task (GstPad * pad) @@ -5616,3 +5712,23 @@ gst_pad_probe_info_get_buffer_list (GstPadProbeInfo * info) return GST_PAD_PROBE_INFO_BUFFER_LIST (info); } + +/** + * gst_pad_get_last_flow_return: + * @pad: the #GstPad + * + * Gets the #GstFlowReturn return from the last data passed by this pad. + * + * Since: 1.4 + */ +GstFlowReturn +gst_pad_get_last_flow_return (GstPad * pad) +{ + GstFlowReturn ret; + + GST_OBJECT_LOCK (pad); + ret = GST_PAD_LAST_FLOW_RETURN (pad); + GST_OBJECT_UNLOCK (pad); + + return ret; +} diff --git a/gst/gstpad.h b/gst/gstpad.h index 13d4571..bfb8b1a 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -61,6 +61,8 @@ typedef enum { GST_PAD_MODE_PULL } GstPadMode; +const gchar * gst_pad_mode_get_name (GstPadMode mode); + #include <gst/gstobject.h> #include <gst/gstbuffer.h> #include <gst/gstbufferlist.h> @@ -131,7 +133,7 @@ typedef enum { * @GST_FLOW_FLUSHING: Pad is flushing. * @GST_FLOW_EOS: Pad is EOS. * @GST_FLOW_NOT_NEGOTIATED: Pad is not negotiated. - * @GST_FLOW_ERROR: Some (fatal) error occured. Element generating + * @GST_FLOW_ERROR: Some (fatal) error occurred. Element generating * this error should post an error message with more * details. * @GST_FLOW_NOT_SUPPORTED: This operation is not supported. @@ -177,8 +179,9 @@ typedef enum { GST_FLOW_CUSTOM_ERROR_2 = -102 } GstFlowReturn; -const gchar* gst_flow_get_name (GstFlowReturn ret); -GQuark gst_flow_to_quark (GstFlowReturn ret); +const gchar* gst_flow_get_name (GstFlowReturn ret); +GQuark gst_flow_to_quark (GstFlowReturn ret); +const gchar* gst_pad_link_get_name (GstPadLinkReturn ret); /** * GstPadLinkCheck: @@ -226,7 +229,7 @@ typedef enum { * activate function that puts the pad in push mode but elements can * override this function to activate the pad in pull mode if they wish. * - * Returns: TRUE if the pad could be activated. + * Returns: %TRUE if the pad could be activated. */ typedef gboolean (*GstPadActivateFunction) (GstPad *pad, GstObject *parent); /** @@ -238,7 +241,7 @@ typedef gboolean (*GstPadActivateFunction) (GstPad *pad, GstObject *parent); * * The prototype of the push and pull activate functions. * - * Returns: TRUE if the pad could be activated or deactivated. + * Returns: %TRUE if the pad could be activated or deactivated. */ typedef gboolean (*GstPadActivateModeFunction) (GstPad *pad, GstObject *parent, GstPadMode mode, gboolean active); @@ -249,7 +252,7 @@ typedef gboolean (*GstPadActivateModeFunction) (GstPad *pad, GstObject *parent, * GstPadChainFunction: * @pad: the sink #GstPad that performed the chain. * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set, - * @parent is guaranteed to be not-NULL and remain valid during the + * @parent is guaranteed to be not-%NULL and remain valid during the * execution of this function. * @buffer: the #GstBuffer that is chained, not %NULL. * @@ -272,7 +275,7 @@ typedef GstFlowReturn (*GstPadChainFunction) (GstPad *pad, GstObject *parent, * GstPadChainListFunction: * @pad: the sink #GstPad that performed the chain. * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set, - * @parent is guaranteed to be not-NULL and remain valid during the + * @parent is guaranteed to be not-%NULL and remain valid during the * execution of this function. * @list: the #GstBufferList that is chained, not %NULL. * @@ -295,11 +298,11 @@ typedef GstFlowReturn (*GstPadChainListFunction) (GstPad *pad, GstObject *paren * GstPadGetRangeFunction: * @pad: the src #GstPad to perform the getrange on. * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set, - * @parent is guaranteed to be not-NULL and remain valid during the + * @parent is guaranteed to be not-%NULL and remain valid during the * execution of this function. * @offset: the offset of the range * @length: the length of the range - * @buffer: a memory location to hold the result buffer, cannot be NULL. + * @buffer: a memory location to hold the result buffer, cannot be %NULL. * * This function will be called on source pads when a peer element * request a buffer at the specified @offset and @length. If this function @@ -346,13 +349,13 @@ typedef GstFlowReturn (*GstPadGetRangeFunction) (GstPad *pad, GstObject *parent * GstPadEventFunction: * @pad: the #GstPad to handle the event. * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set, - * @parent is guaranteed to be not-NULL and remain valid during the + * @parent is guaranteed to be not-%NULL and remain valid during the * execution of this function. * @event: the #GstEvent to handle. * * Function signature to handle an event for the pad. * - * Returns: TRUE if the pad could handle the event. + * Returns: %TRUE if the pad could handle the event. */ typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstObject *parent, GstEvent *event); @@ -363,7 +366,7 @@ typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstObject *parent, * GstPadIterIntLinkFunction: * @pad: The #GstPad to query. * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set, - * @parent is guaranteed to be not-NULL and remain valid during the + * @parent is guaranteed to be not-%NULL and remain valid during the * execution of this function. * * The signature of the internal pad link iterator function. @@ -380,13 +383,13 @@ typedef GstIterator* (*GstPadIterIntLinkFunction) (GstPad *pad, Gst * GstPadQueryFunction: * @pad: the #GstPad to query. * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set, - * @parent is guaranteed to be not-NULL and remain valid during the + * @parent is guaranteed to be not-%NULL and remain valid during the * execution of this function. * @query: the #GstQuery object to execute * * The signature of the query function. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ typedef gboolean (*GstPadQueryFunction) (GstPad *pad, GstObject *parent, GstQuery *query); @@ -397,7 +400,7 @@ typedef gboolean (*GstPadQueryFunction) (GstPad *pad, GstObject *parent, * GstPadLinkFunction: * @pad: the #GstPad that is linked. * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set, - * @parent is guaranteed to be not-NULL and remain valid during the + * @parent is guaranteed to be not-%NULL and remain valid during the * execution of this function. * @peer: the peer #GstPad of the link * @@ -410,7 +413,7 @@ typedef GstPadLinkReturn (*GstPadLinkFunction) (GstPad *pad, GstObject *parent, * GstPadUnlinkFunction: * @pad: the #GstPad that is linked. * @parent: the parent of @pad. If the #GST_PAD_FLAG_NEED_PARENT flag is set, - * @parent is guaranteed to be not-NULL and remain valid during the + * @parent is guaranteed to be not-%NULL and remain valid during the * execution of this function. * * Function signature to handle a unlinking the pad prom its peer. @@ -427,7 +430,7 @@ typedef void (*GstPadUnlinkFunction) (GstPad *pad, GstObject *parent); * A forward function is called for all internally linked pads, see * gst_pad_forward(). * - * Returns: TRUE if the dispatching procedure has to be stopped. + * Returns: %TRUE if the dispatching procedure has to be stopped. */ typedef gboolean (*GstPadForwardFunction) (GstPad *pad, gpointer user_data); @@ -501,7 +504,7 @@ typedef enum * @GST_PAD_PROBE_DROP: drop data in data probes. For push mode this means that * the data item is not sent downstream. For pull mode, it means that the * data item is not passed upstream. In both cases, this result code - * returns #GST_FLOW_OK or %TRUE to the caller. + * means that #GST_FLOW_OK or %TRUE is returned to the caller. * @GST_PAD_PROBE_REMOVE: remove probe * @GST_PAD_PROBE_PASS: pass the data item in the block probe and block on * the next item @@ -522,7 +525,7 @@ typedef enum * @type: the current probe type * @id: the id of the probe * @data: type specific data, check the @type field to know the datatype. - * This field can be NULL. + * This field can be %NULL. * @offset: offset of pull probe, this field is valid when @type contains * #GST_PAD_PROBE_TYPE_PULL * @size: size of pull probe, this field is valid when @type contains @@ -586,7 +589,7 @@ typedef GstPadProbeReturn (*GstPadProbeCallback) (GstPad *pad, GstPadProbeIn * When this function returns %TRUE, the next event will be * returned. When %FALSE is returned, gst_pad_sticky_events_foreach() will return. * - * When @event is set to NULL, the item will be removed from the list of sticky events. + * When @event is set to %NULL, the item will be removed from the list of sticky events. * @event can be replaced by assigning a new reference to it. * This function is responsible for unreffing the old event when * removing or modifying. @@ -608,9 +611,9 @@ typedef gboolean (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEvent ** * The flag has to be unset manually after * reconfiguration happened. * @GST_PAD_FLAG_PENDING_EVENTS: the pad has pending events - * @GST_PAD_FLAG_FIXED_CAPS: the pad is using fixed caps this means that once the - * caps are set on the pad, the caps query function only - * returns those caps. + * @GST_PAD_FLAG_FIXED_CAPS: the pad is using fixed caps. This means that + * once the caps are set on the pad, the default caps query function + * will only return those caps. * @GST_PAD_FLAG_PROXY_CAPS: the default event and query handler will forward * all events and queries to the internally linked pads * instead of discarding them. @@ -620,6 +623,10 @@ typedef gboolean (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEvent ** * @GST_PAD_FLAG_PROXY_SCHEDULING: the default query handler will forward * scheduling queries to the internally linked pads * instead of discarding them. + * @GST_PAD_FLAG_ACCEPT_INTERSECT: the default accept-caps handler will check + * it the caps intersect the query-caps result instead + * of checking for a subset. This is interesting for + * parsers that can accept incompletely specified caps. * @GST_PAD_FLAG_LAST: offset to define more flags * * Pad state flags @@ -636,6 +643,7 @@ typedef enum { GST_PAD_FLAG_PROXY_CAPS = (GST_OBJECT_FLAG_LAST << 8), GST_PAD_FLAG_PROXY_ALLOCATION = (GST_OBJECT_FLAG_LAST << 9), GST_PAD_FLAG_PROXY_SCHEDULING = (GST_OBJECT_FLAG_LAST << 10), + GST_PAD_FLAG_ACCEPT_INTERSECT = (GST_OBJECT_FLAG_LAST << 11), /* padding */ GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16) } GstPadFlags; @@ -718,7 +726,12 @@ struct _GstPad { GstPadPrivate *priv; - gpointer _gst_reserved[GST_PADDING]; + union { + gpointer _gst_reserved[GST_PADDING]; + struct { + GstFlowReturn last_flowret; + } abi; + } ABI; }; struct _GstPadClass { @@ -735,90 +748,412 @@ struct _GstPadClass { /***** helper macros *****/ /* GstPad */ + +/** + * GST_PAD_NAME: + * @pad: a #GstPad + * + * Get name of the given pad. + * No locking is performed in this function, use gst_pad_get_name() instead. + */ #define GST_PAD_NAME(pad) (GST_OBJECT_NAME(pad)) +/** + * GST_PAD_PARENT: + * @pad: a #GstPad + * + * Get the @pad parent. + * No locking is performed in this function, use gst_pad_get_parent() instead. + */ #define GST_PAD_PARENT(pad) (GST_ELEMENT_CAST(GST_OBJECT_PARENT(pad))) +/** + * GST_PAD_ELEMENT_PRIVATE: + * @pad: a #GstPad + * + * Get the private data of @pad, which is usually some pad- or stream-specific + * structure created by the element and set on the pad when creating it. + * No locking is performed in this function. + */ #define GST_PAD_ELEMENT_PRIVATE(pad) (GST_PAD_CAST(pad)->element_private) +/** + * GST_PAD_PAD_TEMPLATE: + * @pad: a #GstPad + * + * Get the @pad #GstPadTemplate. It describes the possible media types + * a @pad or an element factory can handle. + */ #define GST_PAD_PAD_TEMPLATE(pad) (GST_PAD_CAST(pad)->padtemplate) +/** + * GST_PAD_DIRECTION: + * @pad: a #GstPad + * + * Get the #GstPadDirection of the given @pad. Accessor macro, use + * gst_pad_get_direction() instead. + */ #define GST_PAD_DIRECTION(pad) (GST_PAD_CAST(pad)->direction) +/** + * GST_PAD_TASK: + * @pad: a #GstPad + * + * Get the #GstTask of @pad. Accessor macro used by GStreamer. Use the + * gst_pad_start_task(), gst_pad_stop_task() and gst_pad_pause_task() + * functions instead. + */ #define GST_PAD_TASK(pad) (GST_PAD_CAST(pad)->task) +/** + * GST_PAD_MODE: + * @pad: a #GstPad + * + * Get the #GstPadMode of pad, which will be GST_PAD_MODE_NONE if the pad + * has not been activated yet, and otherwise either GST_PAD_MODE_PUSH or + * GST_PAD_MODE_PULL depending on which mode the pad was activated in. + */ #define GST_PAD_MODE(pad) (GST_PAD_CAST(pad)->mode) - +/** + * GST_PAD_ACTIVATEFUNC: + * @pad: a #GstPad + * + * Get the #GstPadActivateFunction from @pad. + */ #define GST_PAD_ACTIVATEFUNC(pad) (GST_PAD_CAST(pad)->activatefunc) +/** + * GST_PAD_ACTIVATEMODEFUNC: + * @pad: a #GstPad + * + * Get the #GstPadActivateModeFunction from the given @pad. + */ #define GST_PAD_ACTIVATEMODEFUNC(pad) (GST_PAD_CAST(pad)->activatemodefunc) +/** + * GST_PAD_CHAINFUNC: + * @pad: a #GstPad + * + * Get the #GstPadChainFunction from the given @pad. + */ #define GST_PAD_CHAINFUNC(pad) (GST_PAD_CAST(pad)->chainfunc) +/** + * GST_PAD_CHAINLISTFUNC: + * @pad: a #GstPad + * + * Get the #GstPadChainListFunction from the given @pad. + */ #define GST_PAD_CHAINLISTFUNC(pad) (GST_PAD_CAST(pad)->chainlistfunc) +/** + * GST_PAD_GETRANGEFUNC: + * @pad: a #GstPad + * + * Get the #GstPadGetRangeFunction from the given @pad. + */ #define GST_PAD_GETRANGEFUNC(pad) (GST_PAD_CAST(pad)->getrangefunc) +/** + * GST_PAD_EVENTFUNC: + * @pad: a #GstPad + * + * Get the #GstPadEventFunction from the given @pad, which + * is the function that handles events on the pad. You can + * use this to set your own event handling function on a pad + * after you create it. If your element derives from a base + * class, use the base class's virtual functions instead. + */ #define GST_PAD_EVENTFUNC(pad) (GST_PAD_CAST(pad)->eventfunc) +/** + * GST_PAD_QUERYFUNC: + * @pad: a #GstPad + * + * Get the #GstPadQueryFunction from @pad, which is the function + * that handles queries on the pad. You can use this to set your + * own query handling function on a pad after you create it. If your + * element derives from a base class, use the base class's virtual + * functions instead. + */ #define GST_PAD_QUERYFUNC(pad) (GST_PAD_CAST(pad)->queryfunc) +/** + * GST_PAD_ITERINTLINKFUNC: + * @pad: a #GstPad + * + * Get the #GstPadIterIntLinkFunction from the given @pad. + */ #define GST_PAD_ITERINTLINKFUNC(pad) (GST_PAD_CAST(pad)->iterintlinkfunc) - +/** + * GST_PAD_PEER: + * @pad: a #GstPad + * + * Return the pad's peer member. This member is a pointer to the linked @pad. + * No locking is performed in this function, use gst_pad_get_peer() instead. + */ #define GST_PAD_PEER(pad) (GST_PAD_CAST(pad)->peer) +/** + * GST_PAD_LINKFUNC: + * @pad: a #GstPad + * + * Get the #GstPadLinkFunction for the given @pad. + */ #define GST_PAD_LINKFUNC(pad) (GST_PAD_CAST(pad)->linkfunc) +/** + * GST_PAD_UNLINKFUNC: + * @pad: a #GstPad + * + * Get the #GstPadUnlinkFunction from the given @pad. + */ #define GST_PAD_UNLINKFUNC(pad) (GST_PAD_CAST(pad)->unlinkfunc) - +/** + * GST_PAD_IS_SRC: + * @pad: a #GstPad + * + * Returns: %TRUE if the pad is a source pad (i.e. produces data). + */ #define GST_PAD_IS_SRC(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SRC) +/** + * GST_PAD_IS_SINK: + * @pad: a #GstPad + * + * Returns: %TRUE if the pad is a sink pad (i.e. consumes data). + */ #define GST_PAD_IS_SINK(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SINK) - +/** + * GST_PAD_IS_LINKED: + * @pad: a #GstPad + * + * Returns: %TRUE if the pad is linked to another pad. Use gst_pad_is_linked() + * instead. + */ #define GST_PAD_IS_LINKED(pad) (GST_PAD_PEER(pad) != NULL) - +/** + * GST_PAD_IS_ACTIVE: + * @pad: a #GstPad + * + * Returns: %TRUE if the pad has been activated. + */ #define GST_PAD_IS_ACTIVE(pad) (GST_PAD_MODE(pad) != GST_PAD_MODE_NONE) - +/** + * GST_PAD_IS_BLOCKED: + * @pad: a #GstPad + * + * Check if the dataflow on a @pad is blocked. Use gst_pad_is_blocked() instead. + */ #define GST_PAD_IS_BLOCKED(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKED)) +/** + * GST_PAD_IS_BLOCKING: + * @pad: a #GstPad + * + * Check if the @pad is currently blocking on a buffer or event. Use + * gst_pad_is_blocking() instead. + */ #define GST_PAD_IS_BLOCKING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKING)) - +/** + * GST_PAD_IS_FLUSHING: + * @pad: a #GstPad + * + * Check if the given @pad is flushing. + */ #define GST_PAD_IS_FLUSHING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FLUSHING)) +/** + * GST_PAD_SET_FLUSHING: + * @pad: a #GstPad + * + * Set the given @pad to flushing state, which means it will not accept any + * more events, queries or buffers, and return GST_FLOW_FLUSHING if any buffers + * are pushed on it. This usually happens when the pad is shut down or when + * a flushing seek happens. This is used inside GStreamer when flush start/stop + * events pass through pads, or when an element state is changed and pads are + * activated or deactivated. + */ #define GST_PAD_SET_FLUSHING(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_FLUSHING)) +/** + * GST_PAD_UNSET_FLUSHING: + * @pad: a #GstPad + * + * Unset the flushing flag. + */ #define GST_PAD_UNSET_FLUSHING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_FLUSHING)) - +/** + * GST_PAD_IS_EOS: + * @pad: a #GstPad + * + * Check if the @pad is in EOS state. + */ #define GST_PAD_IS_EOS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_EOS)) - +/** + * GST_PAD_NEEDS_RECONFIGURE: + * @pad: a #GstPad + * + * Check if the @pad should be reconfigured/renegotiated. + * The flag has to be unset manually after reconfiguration happened. + * Use gst_pad_needs_reconfigure() or gst_pad_check_reconfigure() instead. + */ #define GST_PAD_NEEDS_RECONFIGURE(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE)) +/** + * GST_PAD_HAS_PENDING_EVENTS: + * @pad: a #GstPad + * + * Check if the given @pad has pending events. This is used internally by + * GStreamer. + */ #define GST_PAD_HAS_PENDING_EVENTS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PENDING_EVENTS)) +/** + * GST_PAD_IS_FIXED_CAPS: + * @pad: a #GstPad + * + * Check if the given @pad is using fixed caps, which means that + * once the caps are set on the @pad, the caps query function will + * only return those caps. See gst_pad_use_fixed_caps(). + */ #define GST_PAD_IS_FIXED_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FIXED_CAPS)) +/** + * GST_PAD_NEEDS_PARENT: + * @pad: a #GstPad + * + * Check if there is a parent object before calling into the @pad callbacks. + * This is used internally by GStreamer. + */ #define GST_PAD_NEEDS_PARENT(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_NEED_PARENT)) - +/** + * GST_PAD_IS_PROXY_CAPS: + * @pad: a #GstPad + * + * Check if the given @pad is set to proxy caps. This means that the default + * event and query handler will forward all events and queries to the + * internally linked @pads instead of discarding them. + */ #define GST_PAD_IS_PROXY_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PROXY_CAPS)) +/** + * GST_PAD_SET_PROXY_CAPS: + * @pad: a #GstPad + * + * Set @pad to proxy caps, so that all caps-related events and queries are + * proxied down- or upstream to the other side of the element automatically. + * Set this if the element always outputs data in the exact same format as it + * receives as input. This is just for convenience to avoid implementing some + * standard event and query handling code in an element. + */ #define GST_PAD_SET_PROXY_CAPS(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PROXY_CAPS)) +/** + * GST_PAD_UNSET_PROXY_CAPS: + * @pad: a #GstPad + * + * Unset proxy caps flag. + */ #define GST_PAD_UNSET_PROXY_CAPS(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PROXY_CAPS)) - +/** + * GST_PAD_IS_PROXY_ALLOCATION: + * @pad: a #GstPad + * + * Check if the given @pad is set as proxy allocation which means + * that the default query handler will forward allocation queries to the + * internally linked @pads instead of discarding them. + */ #define GST_PAD_IS_PROXY_ALLOCATION(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PROXY_ALLOCATION)) +/** + * GST_PAD_SET_PROXY_ALLOCATION: + * @pad: a #GstPad + * + * Set @pad to proxy allocation queries, which means that the default query + * handler will forward allocation queries to the internally linked @pads + * instead of discarding them. + * Set this if the element always outputs data in the exact same format as it + * receives as input. This is just for convenience to avoid implementing some + * standard query handling code in an element. + */ #define GST_PAD_SET_PROXY_ALLOCATION(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PROXY_ALLOCATION)) +/** + * GST_PAD_UNSET_PROXY_ALLOCATION: + * @pad: a #GstPad + * + * Unset proxy allocation flag. + */ #define GST_PAD_UNSET_PROXY_ALLOCATION(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PROXY_ALLOCATION)) - +/** + * GST_PAD_IS_PROXY_SCHEDULING: + * @pad: a #GstPad + * + * Check if the given @pad is set to proxy scheduling queries, which means that + * the default query handler will forward scheduling queries to the internally + * linked @pads instead of discarding them. + */ #define GST_PAD_IS_PROXY_SCHEDULING(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_PROXY_SCHEDULING)) +/** + * GST_PAD_SET_PROXY_SCHEDULING: + * @pad: a #GstPad + * + * Set @pad to proxy scheduling queries, which means that the default query + * handler will forward scheduling queries to the internally linked @pads + * instead of discarding them. You will usually want to handle scheduling + * queries explicitly if your element supports multiple scheduling modes. + */ #define GST_PAD_SET_PROXY_SCHEDULING(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PROXY_SCHEDULING)) +/** + * GST_PAD_UNSET_PROXY_SCHEDULING: + * @pad: a #GstPad + * + * Unset proxy scheduling flag. + */ #define GST_PAD_UNSET_PROXY_SCHEDULING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PROXY_SCHEDULING)) - +/** + * GST_PAD_IS_ACCEPT_INTERSECT: + * @pad: a #GstPad + * + * Check if the pad's accept intersect flag is set. The default accept-caps + * handler will check it the caps intersect the query-caps result instead of + * checking for a subset. This is interesting for parser elements that can + * accept incompletely specified caps. + */ +#define GST_PAD_IS_ACCEPT_INTERSECT(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_ACCEPT_INTERSECT)) +/** + * GST_PAD_SET_ACCEPT_INTERSECT: + * @pad: a #GstPad + * + * Set @pad to by default accept caps by intersecting the result instead of + * checking for a subset. This is interesting for parser elements that can + * accept incompletely specified caps. + */ +#define GST_PAD_SET_ACCEPT_INTERSECT(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_ACCEPT_INTERSECT)) +/** + * GST_PAD_UNSET_ACCEPT_INTERSECT: + * @pad: a #GstPad + * + * Unset accept intersect flag. + */ +#define GST_PAD_UNSET_ACCEPT_INTERSECT(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_ACCEPT_INTERSECT)) /** * GST_PAD_GET_STREAM_LOCK: * @pad: a #GstPad * * Get the stream lock of @pad. The stream lock is protecting the - * resources used in the data processing functions of @pad. + * resources used in the data processing functions of @pad. Accessor + * macro, use GST_PAD_STREAM_LOCK() and GST_PAD_STREAM_UNLOCK() instead + * to take/release the pad's stream lock. */ #define GST_PAD_GET_STREAM_LOCK(pad) (&(GST_PAD_CAST(pad)->stream_rec_lock)) /** * GST_PAD_STREAM_LOCK: * @pad: a #GstPad * - * Lock the stream lock of @pad. + * Take the pad's stream lock. The stream lock is recursive and will be taken + * when buffers or serialized downstream events are pushed on a pad. */ #define GST_PAD_STREAM_LOCK(pad) g_rec_mutex_lock(GST_PAD_GET_STREAM_LOCK(pad)) /** * GST_PAD_STREAM_TRYLOCK: * @pad: a #GstPad * - * Try to Lock the stream lock of the pad, return TRUE if the lock could be - * taken. + * Try to take the pad's stream lock, and return %TRUE if the lock could be + * taken, and otherwise %FALSE. */ #define GST_PAD_STREAM_TRYLOCK(pad) g_rec_mutex_trylock(GST_PAD_GET_STREAM_LOCK(pad)) /** * GST_PAD_STREAM_UNLOCK: * @pad: a #GstPad * - * Unlock the stream lock of @pad. + * Release the pad's stream lock. */ #define GST_PAD_STREAM_UNLOCK(pad) g_rec_mutex_unlock(GST_PAD_GET_STREAM_LOCK(pad)) +/** + * GST_PAD_LAST_FLOW_RETURN: + * @pad: a #GstPad + * + * Gets the last flow return on this pad + * + * Since: 1.4 + */ +#define GST_PAD_LAST_FLOW_RETURN(pad) (GST_PAD_CAST(pad)->ABI.abi.last_flowret) #define GST_PAD_BLOCK_GET_COND(pad) (&GST_PAD_CAST(pad)->block_cond) #define GST_PAD_BLOCK_WAIT(pad) (g_cond_wait(GST_PAD_BLOCK_GET_COND (pad), GST_OBJECT_GET_LOCK (pad))) @@ -848,7 +1183,7 @@ GstPad* gst_pad_new_from_static_template (GstStaticPadTemplate *templ, const g * * Get the parent of @pad. This function increases the refcount * of the parent object so you should gst_object_unref() it after usage. - * Can return NULL if the pad did not have a parent. + * Can return %NULL if the pad did not have a parent. * * MT safe. */ @@ -961,6 +1296,7 @@ GstFlowReturn gst_pad_pull_range (GstPad *pad, guint64 offset, guint size, gboolean gst_pad_push_event (GstPad *pad, GstEvent *event); gboolean gst_pad_event_default (GstPad *pad, GstObject *parent, GstEvent *event); +GstFlowReturn gst_pad_get_last_flow_return (GstPad *pad); /* data passing functions on pad */ GstFlowReturn gst_pad_chain (GstPad *pad, GstBuffer *buffer); @@ -1000,8 +1336,6 @@ gboolean gst_pad_query_default (GstPad *pad, GstObject *parent, gboolean gst_pad_forward (GstPad *pad, GstPadForwardFunction forward, gpointer user_data); -const gchar * gst_pad_mode_get_name (GstPadMode mode); - G_END_DECLS #endif /* __GST_PAD_H__ */ diff --git a/gst/gstpadtemplate.c b/gst/gstpadtemplate.c index c7c4914..8eac996 100644 --- a/gst/gstpadtemplate.c +++ b/gst/gstpadtemplate.c @@ -54,9 +54,7 @@ * (see gst_element_class_add_pad_template ()). * * The following code example shows the code to create a pad from a padtemplate. - * <example> - * <title>Create a pad from a padtemplate</title> - * <programlisting> + * |[ * GstStaticPadTemplate my_template = * GST_STATIC_PAD_TEMPLATE ( * "sink", // the name of the pad @@ -74,13 +72,11 @@ * pad = gst_pad_new_from_static_template (&my_template, "sink"); * ... * } - * </programlisting> - * </example> + * ]| * * The following example shows you how to add the padtemplate to an * element class, this is usually done in the class_init of the class: - * <informalexample> - * <programlisting> + * |[ * static void * my_element_class_init (GstMyElementClass *klass) * { @@ -89,10 +85,7 @@ * gst_element_class_add_pad_template (gstelement_class, * gst_static_pad_template_get (&my_template)); * } - * </programlisting> - * </informalexample> - * - * Last reviewed on 2006-02-14 (0.10.3) + * ]| */ #include "gst_private.h" diff --git a/gst/gstpadtemplate.h b/gst/gstpadtemplate.h index 2700e9b..636b143 100644 --- a/gst/gstpadtemplate.h +++ b/gst/gstpadtemplate.h @@ -52,7 +52,7 @@ G_BEGIN_DECLS * @GST_PAD_ALWAYS: the pad is always available * @GST_PAD_SOMETIMES: the pad will become available depending on the media stream * @GST_PAD_REQUEST: the pad is only available on request with - * gst_element_get_request_pad(). + * gst_element_request_pad(). * * Indicates when this pad will become available. */ diff --git a/gst/gstparamspecs.c b/gst/gstparamspecs.c index 0777c6a..6425e18 100644 --- a/gst/gstparamspecs.c +++ b/gst/gstparamspecs.c @@ -22,8 +22,6 @@ * to GStreamer * * GParamSpec implementations specific to GStreamer. - * - * Last reviewed on 2008-03-11 (0.10.18) */ #ifdef HAVE_CONFIG_H diff --git a/gst/gstparse.c b/gst/gstparse.c index a23cafa..dd22113 100644 --- a/gst/gstparse.c +++ b/gst/gstparse.c @@ -139,7 +139,7 @@ gst_parse_context_free (GstParseContext * context) * of %GST_PARSE_ERROR_NO_SUCH_ELEMENT was returned. * * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*): a - * NULL-terminated array of element factory name strings of missing + * %NULL-terminated array of element factory name strings of missing * elements. Free with g_strfreev() when no longer needed. */ gchar ** @@ -204,7 +204,7 @@ _gst_parse_escape (const gchar * str) * @error: pointer to a #GError * * Create a new element based on command line syntax. - * @error will contain an error message if an erroneuos pipeline is specified. + * @error will contain an error message if an erroneous pipeline is specified. * An error does not mean that the pipeline could not be constructed. * * Returns: (transfer floating): a new element on success and %NULL on failure. @@ -314,6 +314,7 @@ gst_parse_launch_full (const gchar * pipeline_description, { #ifndef GST_DISABLE_PARSE GstElement *element; + GError *myerror = NULL; g_return_val_if_fail (pipeline_description != NULL, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); @@ -321,16 +322,20 @@ gst_parse_launch_full (const gchar * pipeline_description, GST_CAT_INFO (GST_CAT_PIPELINE, "parsing pipeline description '%s'", pipeline_description); - element = priv_gst_parse_launch (pipeline_description, error, context, flags); + element = priv_gst_parse_launch (pipeline_description, &myerror, context, + flags); /* don't return partially constructed pipeline if FATAL_ERRORS was given */ - if (G_UNLIKELY (error != NULL && *error != NULL && element != NULL)) { + if (G_UNLIKELY (myerror != NULL && element != NULL)) { if ((flags & GST_PARSE_FLAG_FATAL_ERRORS)) { gst_object_unref (element); element = NULL; } } + if (myerror) + g_propagate_error (error, myerror); + return element; #else gchar *msg; diff --git a/gst/gstparse.h b/gst/gstparse.h index de437b1..b1ec83d 100644 --- a/gst/gstparse.h +++ b/gst/gstparse.h @@ -37,7 +37,7 @@ GQuark gst_parse_error_quark (void); /** * GstParseError: - * @GST_PARSE_ERROR_SYNTAX: A syntax error occured. + * @GST_PARSE_ERROR_SYNTAX: A syntax error occurred. * @GST_PARSE_ERROR_NO_SUCH_ELEMENT: The description contained an unknown element * @GST_PARSE_ERROR_NO_SUCH_PROPERTY: An element did not have a specified property * @GST_PARSE_ERROR_LINK: There was an error linking two pads. @@ -61,7 +61,7 @@ typedef enum /** * GstParseFlags: * @GST_PARSE_FLAG_NONE: Do not use any special parsing options. - * @GST_PARSE_FLAG_FATAL_ERRORS: Always return NULL when an error occurs + * @GST_PARSE_FLAG_FATAL_ERRORS: Always return %NULL when an error occurs * (default behaviour is to return partially constructed bins or elements * in some cases) * @GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS: If a bin only has a single element, diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index 5d1d4ae..21e0620 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -71,8 +71,6 @@ * between the clock time and the base time) will count how much time was spent * in the PLAYING state. This default behaviour can be changed with the * gst_element_set_start_time() method. - * - * Last reviewed on 2012-03-29 (0.11.3) */ #include "gst_private.h" @@ -654,7 +652,7 @@ gst_pipeline_get_clock (GstPipeline * pipeline) * always use the given clock even if new clock providers are added * to this pipeline. * - * If @clock is NULL all clocking will be disabled which will make + * If @clock is %NULL all clocking will be disabled which will make * the pipeline run as fast as possible. * * MT safe. @@ -685,7 +683,7 @@ gst_pipeline_use_clock (GstPipeline * pipeline, GstClock * clock) * Set the clock for @pipeline. The clock will be distributed * to all the elements managed by the pipeline. * - * Returns: TRUE if the clock could be set on the pipeline. FALSE if + * Returns: %TRUE if the clock could be set on the pipeline. %FALSE if * some element did not accept the clock. * * MT safe. diff --git a/gst/gstplugin.c b/gst/gstplugin.c index d6a9b76..9bfacc1 100644 --- a/gst/gstplugin.c +++ b/gst/gstplugin.c @@ -39,7 +39,7 @@ * Once you have a handle to a #GstPlugin (e.g. from the #GstRegistry), you * can add any object that subclasses #GstPluginFeature. * - * Usually plugins are always automaticlly loaded so you don't need to call + * Usually plugins are always automatically loaded so you don't need to call * gst_plugin_load() explicitly to bring it into memory. There are options to * statically link plugins to an app or even use GStreamer without a plugin * repository in which case gst_plugin_load() can be needed to bring the plugin @@ -193,7 +193,7 @@ gst_plugin_error_quark (void) * You must make sure that GStreamer has been initialised (with gst_init() or * via gst_init_get_option_group()) before calling this function. * - * Returns: TRUE if the plugin was registered correctly, otherwise FALSE. + * Returns: %TRUE if the plugin was registered correctly, otherwise %FALSE. */ gboolean gst_plugin_register_static (gint major_version, gint minor_version, @@ -258,7 +258,7 @@ gst_plugin_register_static (gint major_version, gint minor_version, * You must make sure that GStreamer has been initialised (with gst_init() or * via gst_init_get_option_group()) before calling this function. * - * Returns: TRUE if the plugin was registered correctly, otherwise FALSE. + * Returns: %TRUE if the plugin was registered correctly, otherwise %FALSE. */ gboolean gst_plugin_register_static_full (gint major_version, gint minor_version, @@ -657,18 +657,21 @@ static GMutex gst_plugin_loading_mutex; #define CHECK_PLUGIN_DESC_FIELD(desc,field,fn) \ if (G_UNLIKELY ((desc)->field == NULL || *(desc)->field == '\0')) { \ g_warning ("Plugin description for '%s' has no valid %s field", fn, G_STRINGIFY (field)); \ + g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, \ + "Plugin %s has invalid plugin description field '%s'", \ + filename, G_STRINGIFY (field)); \ goto return_error; \ } /** * gst_plugin_load_file: * @filename: the plugin filename to load - * @error: pointer to a NULL-valued GError + * @error: pointer to a %NULL-valued GError * * Loads the given plugin and refs it. Caller needs to unref after use. * * Returns: (transfer full): a reference to the existing loaded GstPlugin, a - * reference to the newly-loaded GstPlugin, or NULL if an error occurred. + * reference to the newly-loaded GstPlugin, or %NULL if an error occurred. */ GstPlugin * gst_plugin_load_file (const gchar * filename, GError ** error) @@ -1019,7 +1022,7 @@ gst_plugin_get_release_date_string (GstPlugin * plugin) * * queries if the plugin is loaded into memory * - * Returns: TRUE is loaded, FALSE otherwise + * Returns: %TRUE is loaded, %FALSE otherwise */ gboolean gst_plugin_is_loaded (GstPlugin * plugin) @@ -1162,7 +1165,7 @@ gst_plugin_list_feature_filter (GList * list, * * Find a feature of the given name and type in the given plugin. * - * Returns: a GstPluginFeature or NULL if the feature was not found. + * Returns: a GstPluginFeature or %NULL if the feature was not found. */ GstPluginFeature * gst_plugin_find_feature (GstPlugin * plugin, const gchar * name, GType type) @@ -1206,7 +1209,7 @@ gst_plugin_feature_name_filter (GstPluginFeature * feature, const gchar * name) * * Find a feature of the given name in the given plugin. * - * Returns: a GstPluginFeature or NULL if the feature was not found. + * Returns: a GstPluginFeature or %NULL if the feature was not found. */ GstPluginFeature * gst_plugin_find_feature_by_name (GstPlugin * plugin, const gchar * name) @@ -1236,7 +1239,7 @@ gst_plugin_find_feature_by_name (GstPlugin * plugin, const gchar * name) * * Load the named plugin. Refs the plugin. * - * Returns: (transfer full): a reference to a loaded plugin, or NULL on error. + * Returns: (transfer full): a reference to a loaded plugin, or %NULL on error. */ GstPlugin * gst_plugin_load_by_name (const gchar * name) @@ -1279,7 +1282,7 @@ gst_plugin_load_by_name (const gchar * name) * plugin = loaded_plugin; * </programlisting> * - * Returns: (transfer full): a reference to a loaded plugin, or NULL on error. + * Returns: (transfer full): a reference to a loaded plugin, or %NULL on error. */ GstPlugin * gst_plugin_load (GstPlugin * plugin) @@ -1708,18 +1711,18 @@ gst_plugin_ext_dep_equals (GstPluginDep * dep, const gchar ** env_vars, /** * gst_plugin_add_dependency: * @plugin: a #GstPlugin - * @env_vars: (allow-none): NULL-terminated array of environment variables affecting the + * @env_vars: (allow-none): %NULL-terminated array of environment variables affecting the * feature set of the plugin (e.g. an environment variable containing * paths where to look for additional modules/plugins of a library), - * or NULL. Environment variable names may be followed by a path component + * or %NULL. Environment variable names may be followed by a path component * which will be added to the content of the environment variable, e.g. * "HOME/.mystuff/plugins". - * @paths: (allow-none): NULL-terminated array of directories/paths where dependent files - * may be, or NULL. - * @names: (allow-none): NULL-terminated array of file names (or file name suffixes, + * @paths: (allow-none): %NULL-terminated array of directories/paths where dependent files + * may be, or %NULL. + * @names: (allow-none): %NULL-terminated array of file names (or file name suffixes, * depending on @flags) to be used in combination with the paths from * @paths and/or the paths extracted from the environment variables in - * @env_vars, or NULL. + * @env_vars, or %NULL. * @flags: optional flags, or #GST_PLUGIN_DEPENDENCY_FLAG_NONE * * Make GStreamer aware of external dependencies which affect the feature @@ -1780,13 +1783,13 @@ gst_plugin_add_dependency (GstPlugin * plugin, const gchar ** env_vars, * gst_plugin_add_dependency_simple: * @plugin: the #GstPlugin * @env_vars: (allow-none): one or more environment variables (separated by ':', ';' or ','), - * or NULL. Environment variable names may be followed by a path component + * or %NULL. Environment variable names may be followed by a path component * which will be added to the content of the environment variable, e.g. * "HOME/.mystuff/plugins:MYSTUFF_PLUGINS_PATH" * @paths: (allow-none): one ore more directory paths (separated by ':' or ';' or ','), - * or NULL. Example: "/usr/lib/mystuff/plugins" + * or %NULL. Example: "/usr/lib/mystuff/plugins" * @names: (allow-none): one or more file names or file name suffixes (separated by commas), - * or NULL + * or %NULL * @flags: optional flags, or #GST_PLUGIN_DEPENDENCY_FLAG_NONE * * Make GStreamer aware of external dependencies which affect the feature diff --git a/gst/gstplugin.h b/gst/gstplugin.h index 66ede12..500be30 100644 --- a/gst/gstplugin.h +++ b/gst/gstplugin.h @@ -146,7 +146,7 @@ typedef gboolean (*GstPluginInitFullFunc) (GstPlugin *plugin, gpointer user_data * @package: shipped package plugin belongs to * @origin: URL to provider of plugin * @release_datetime: date time string in ISO 8601 format (or rather, a - * subset thereof), or NULL. Allowed are the following formats: + * subset thereof), or %NULL. Allowed are the following formats: * "YYYY-MM-DD" and "YYY-MM-DDTHH:MMZ" (with 'T' a separator and 'Z' * indicating UTC/Zulu time). This field should be set via the * GST_PACKAGE_RELEASE_DATETIME preprocessor macro. @@ -198,7 +198,7 @@ struct _GstPluginDesc { * and must be placed outside any block to declare the plugin initialization * function. * - * Since: 1.2.0 + * Since: 1.2 */ #define GST_PLUGIN_STATIC_DECLARE(name) \ extern void G_PASTE(gst_plugin_, G_PASTE(name, _register)) (void) @@ -212,7 +212,7 @@ struct _GstPluginDesc { * It has to be used in combination with GST_PLUGIN_STATIC_DECLARE and * calls the plugin initialization function. * - * Since: 1.2.0 + * Since: 1.2 */ #define GST_PLUGIN_STATIC_REGISTER(name) G_PASTE(gst_plugin_, G_PASTE(name, _register)) () @@ -277,7 +277,7 @@ G_END_DECLS /** * GST_LICENSE_UNKNOWN: * - * To be used in GST_PLUGIN_DEFINE if usure about the licence. + * To be used in GST_PLUGIN_DEFINE if unsure about the licence. */ #define GST_LICENSE_UNKNOWN "unknown" @@ -291,7 +291,7 @@ G_END_DECLS * A function that can be used with e.g. gst_registry_plugin_filter() * to get a list of plugins that match certain criteria. * - * Returns: TRUE for a positive match, FALSE otherwise + * Returns: %TRUE for a positive match, %FALSE otherwise */ typedef gboolean (*GstPluginFilter) (GstPlugin *plugin, gpointer user_data); diff --git a/gst/gstpluginfeature.c b/gst/gstpluginfeature.c index 6dd5e56..6672f7b 100644 --- a/gst/gstpluginfeature.c +++ b/gst/gstpluginfeature.c @@ -90,7 +90,7 @@ gst_plugin_feature_finalize (GObject * object) * feature = loaded_feature; * ]| * - * Returns: (transfer full): a reference to the loaded feature, or NULL on error + * Returns: (transfer full): a reference to the loaded feature, or %NULL on error */ GstPluginFeature * gst_plugin_feature_load (GstPluginFeature * feature) @@ -208,7 +208,7 @@ gst_plugin_feature_get_plugin (GstPluginFeature * feature) * Returns: the name of the plugin that provides this feature, or %NULL if * the feature is not associated with a plugin. * - * Since: 1.2.0 + * Since: 1.2 */ const gchar * gst_plugin_feature_get_plugin_name (GstPluginFeature * feature) @@ -307,8 +307,8 @@ gst_plugin_feature_list_debug (GList * list) * Checks whether the given plugin feature is at least * the required version * - * Returns: #TRUE if the plugin feature has at least - * the required version, otherwise #FALSE. + * Returns: %TRUE if the plugin feature has at least + * the required version, otherwise %FALSE. */ gboolean gst_plugin_feature_check_version (GstPluginFeature * feature, diff --git a/gst/gstpluginfeature.h b/gst/gstpluginfeature.h index ca9f0d3..bc01969 100644 --- a/gst/gstpluginfeature.h +++ b/gst/gstpluginfeature.h @@ -73,7 +73,7 @@ typedef enum { * @feature: a #GstPluginFeature to get the name of @feature. * * Returns the name of @feature. - * For a nameless plugin feature, this returns NULL. + * For a nameless plugin feature, this returns %NULL. * * Returns: (transfer none): the name of @feature. MT safe. * diff --git a/gst/gstpluginloader.c b/gst/gstpluginloader.c index 13a8fd5..96d4994 100644 --- a/gst/gstpluginloader.c +++ b/gst/gstpluginloader.c @@ -33,8 +33,13 @@ #include <fcntl.h> #include <unistd.h> #else +#define WIN32_LEAN_AND_MEAN + #define fsync(fd) _commit(fd) #include <io.h> + +#include <windows.h> +extern HMODULE _priv_gst_dll_handle; #endif #ifdef HAVE_SYS_UTSNAME_H @@ -470,7 +475,22 @@ gst_plugin_loader_spawn (GstPluginLoader * loader) if (!res) { GST_LOG ("Trying installed plugin scanner"); + +#ifdef G_OS_WIN32 + { + gchar *basedir; + + basedir = g_win32_get_package_installation_directory_of_module (_priv_gst_dll_handle); + helper_bin = g_build_filename (basedir, + "lib", + "gstreamer-" GST_API_VERSION, + "gst-plugin-scanner.exe", + NULL); + g_free (basedir); + } +#else helper_bin = g_strdup (GST_PLUGIN_SCANNER_INSTALLED); +#endif res = gst_plugin_loader_try_helper (loader, helper_bin); g_free (helper_bin); @@ -508,6 +528,7 @@ plugin_loader_cleanup_child (GstPluginLoader * l) gboolean _gst_plugin_loader_client_run (void) { + gboolean res = TRUE; GstPluginLoader *l; l = plugin_loader_new (NULL); @@ -524,7 +545,8 @@ _gst_plugin_loader_client_run (void) dup_fd = dup (0); /* STDIN */ if (dup_fd == -1) { GST_ERROR ("Failed to start. Could no dup STDIN, errno %d", errno); - return FALSE; + res = FALSE; + goto beach; } l->fd_r.fd = dup_fd; close (0); @@ -532,7 +554,8 @@ _gst_plugin_loader_client_run (void) dup_fd = dup (1); /* STDOUT */ if (dup_fd == -1) { GST_ERROR ("Failed to start. Could no dup STDOUT, errno %d", errno); - return FALSE; + res = FALSE; + goto beach; } l->fd_w.fd = dup_fd; close (1); @@ -558,9 +581,13 @@ _gst_plugin_loader_client_run (void) /* Loop, listening for incoming packets on the fd and writing responses */ while (!l->rx_done && exchange_packets (l)); +#ifndef G_OS_WIN32 +beach: +#endif + plugin_loader_free (l); - return TRUE; + return res; } static void diff --git a/gst/gstpoll.c b/gst/gstpoll.c index 03c2a14..6694a87 100644 --- a/gst/gstpoll.c +++ b/gst/gstpoll.c @@ -24,7 +24,7 @@ /** * SECTION:gstpoll * @short_description: Keep track of file descriptors and make it possible - * to wait on them in a cancelable way + * to wait on them in a cancellable way * * A #GstPoll keeps track of file descriptors much like fd_set (used with * select()) or a struct pollfd array (used with poll()). Once created with @@ -553,9 +553,8 @@ gst_poll_new (gboolean controllable) { GstPoll *nset; - GST_DEBUG ("controllable : %d", controllable); - nset = g_slice_new0 (GstPoll); + GST_DEBUG ("%p: new controllable : %d", nset, controllable); g_mutex_init (&nset->lock); #ifndef G_OS_WIN32 nset->mode = GST_POLL_MODE_AUTO; @@ -870,7 +869,7 @@ gst_poll_fd_ctl_write (GstPoll * set, GstPollFD * fd, gboolean active) else pfd->events &= ~POLLOUT; - GST_LOG ("pfd->events now %d (POLLOUT:%d)", pfd->events, POLLOUT); + GST_LOG ("%p: pfd->events now %d (POLLOUT:%d)", set, pfd->events, POLLOUT); #else gst_poll_update_winsock_event_mask (set, idx, FD_WRITE | FD_CONNECT, active); @@ -1193,7 +1192,7 @@ gst_poll_wait (GstPoll * set, GstClockTime timeout) g_return_val_if_fail (set != NULL, -1); - GST_DEBUG ("timeout :%" GST_TIME_FORMAT, GST_TIME_ARGS (timeout)); + GST_DEBUG ("%p: timeout :%" GST_TIME_FORMAT, set, GST_TIME_ARGS (timeout)); is_timer = set->timer; @@ -1304,9 +1303,9 @@ gst_poll_wait (GstPoll * set, GstClockTime timeout) tvptr = NULL; } - GST_DEBUG ("Calling select"); + GST_DEBUG ("%p: Calling select", set); res = select (max_fd + 1, &readfds, &writefds, &errorfds, tvptr); - GST_DEBUG ("After select, res:%d", res); + GST_DEBUG ("%p: After select, res:%d", set, res); } else { #ifdef HAVE_PSELECT struct timespec ts; @@ -1319,10 +1318,10 @@ gst_poll_wait (GstPoll * set, GstClockTime timeout) tsptr = NULL; } - GST_DEBUG ("Calling pselect"); + GST_DEBUG ("%p: Calling pselect", set); res = pselect (max_fd + 1, &readfds, &writefds, &errorfds, tsptr, NULL); - GST_DEBUG ("After pselect, res:%d", res); + GST_DEBUG ("%p: After pselect, res:%d", set, res); #endif } diff --git a/gst/gstpreset.c b/gst/gstpreset.c index 6a0b181..19f0fbb 100644 --- a/gst/gstpreset.c +++ b/gst/gstpreset.c @@ -78,6 +78,13 @@ #endif #include <glib/gstdio.h> +#ifdef G_OS_WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +extern HMODULE _priv_gst_dll_handle; +#endif + #define GST_CAT_DEFAULT preset_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); @@ -175,8 +182,18 @@ preset_get_paths (GstPreset * preset, const gchar ** preset_user_path, gchar *preset_dir; /* system presets in '$GST_DATADIR/gstreamer-1.0/presets/GstAudioPanorama.prs' */ +#ifdef G_OS_WIN32 + gchar *basedir = + g_win32_get_package_installation_directory_of_module + (_priv_gst_dll_handle); + preset_dir = + g_build_filename (basedir, "share", "gstreamer-" GST_API_VERSION, + "presets", NULL); + g_free (basedir); +#else preset_dir = g_build_filename (GST_DATADIR, "gstreamer-" GST_API_VERSION, "presets", NULL); +#endif GST_INFO_OBJECT (preset, "system_preset_dir: '%s'", preset_dir); preset_path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.prs", preset_dir, element_name); @@ -514,6 +531,8 @@ gst_preset_default_get_property_names (GstPreset * preset) } g_free (props); } + + g_object_unref (child); } } if (!result) { @@ -937,10 +956,10 @@ no_presets: * gst_preset_get_preset_names: * @preset: a #GObject that implements #GstPreset * - * Get a copy of preset names as a NULL terminated string array. + * Get a copy of preset names as a %NULL terminated string array. * * Returns: (transfer full) (array zero-terminated=1) (element-type gchar*): - * list with names, ue g_strfreev() after usage. + * list with names, use g_strfreev() after usage. */ gchar ** gst_preset_get_preset_names (GstPreset * preset) diff --git a/gst/gstquark.c b/gst/gstquark.c index 5598b99..cf5c766 100644 --- a/gst/gstquark.c +++ b/gst/gstquark.c @@ -68,7 +68,9 @@ static const gchar *_quark_strings[] = { "GstEventSegmentDone", "GstEventStreamStart", "stream-id", "GstQueryContext", "GstMessageNeedContext", "GstMessageHaveContext", "context", "context-type", - "GstMessageStreamStart", "group-id", "uri-redirection" + "GstMessageStreamStart", "group-id", "uri-redirection", + "GstMessageDeviceAdded", "GstMessageDeviceRemoved", "device", + "uri-redirection-permanent" }; GQuark _priv_gst_quark_table[GST_QUARK_MAX]; diff --git a/gst/gstquark.h b/gst/gstquark.h index 025f508..98bfdd0 100644 --- a/gst/gstquark.h +++ b/gst/gstquark.h @@ -196,7 +196,11 @@ typedef enum _GstQuarkId GST_QUARK_MESSAGE_STREAM_START = 167, GST_QUARK_GROUP_ID = 168, GST_QUARK_URI_REDIRECTION = 169, - GST_QUARK_MAX = 170 + GST_QUARK_MESSAGE_DEVICE_ADDED = 170, + GST_QUARK_MESSAGE_DEVICE_REMOVED = 171, + GST_QUARK_DEVICE = 172, + GST_QUARK_URI_REDIRECTION_PERMANENT = 173, + GST_QUARK_MAX = 174 } GstQuarkId; extern GQuark _priv_gst_quark_table[GST_QUARK_MAX]; diff --git a/gst/gstquery.c b/gst/gstquery.c index 48a9022..78a04fa 100644 --- a/gst/gstquery.c +++ b/gst/gstquery.c @@ -36,27 +36,20 @@ * gst_query_parse_*() helpers. * * The following example shows how to query the duration of a pipeline: - * - * <example> - * <title>Query duration on a pipeline</title> - * <programlisting> - * GstQuery *query; - * gboolean res; - * query = gst_query_new_duration (GST_FORMAT_TIME); - * res = gst_element_query (pipeline, query); - * if (res) { - * gint64 duration; - * gst_query_parse_duration (query, NULL, &duration); - * g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration)); - * } - * else { - * g_print ("duration query failed..."); - * } - * gst_query_unref (query); - * </programlisting> - * </example> - * - * Last reviewed on 2012-03-29 (0.11.3) + * |[ + * GstQuery *query; + * gboolean res; + * query = gst_query_new_duration (GST_FORMAT_TIME); + * res = gst_element_query (pipeline, query); + * if (res) { + * gint64 duration; + * gst_query_parse_duration (query, NULL, &duration); + * g_print ("duration = %"GST_TIME_FORMAT, GST_TIME_ARGS (duration)); + * } else { + * g_print ("duration query failed..."); + * } + * gst_query_unref (query); + * ]| */ @@ -72,7 +65,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_query_debug); #define GST_CAT_DEFAULT gst_query_debug -static GType _gst_query_type = 0; +GType _gst_query_type = 0; typedef struct { @@ -275,11 +268,11 @@ gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur) * gst_query_parse_position: * @query: a #GstQuery * @format: (out) (allow-none): the storage for the #GstFormat of the - * position values (may be NULL) - * @cur: (out) (allow-none): the storage for the current position (may be NULL) + * position values (may be %NULL) + * @cur: (out) (allow-none): the storage for the current position (may be %NULL) * * Parse a position query, writing the format into @format, and the position - * into @cur, if the respective parameters are non-NULL. + * into @cur, if the respective parameters are non-%NULL. */ void gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur) @@ -352,11 +345,11 @@ gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration) * gst_query_parse_duration: * @query: a #GstQuery * @format: (out) (allow-none): the storage for the #GstFormat of the duration - * value, or NULL. - * @duration: (out) (allow-none): the storage for the total duration, or NULL. + * value, or %NULL. + * @duration: (out) (allow-none): the storage for the total duration, or %NULL. * * Parse a duration query answer. Write the format of the duration into @format, - * and the value into @duration, if the respective variables are non-NULL. + * and the value into @duration, if the respective variables are non-%NULL. */ void gst_query_parse_duration (GstQuery * query, GstFormat * format, @@ -431,9 +424,9 @@ gst_query_set_latency (GstQuery * query, gboolean live, /** * gst_query_parse_latency: * @query: a #GstQuery - * @live: (out) (allow-none): storage for live or NULL - * @min_latency: (out) (allow-none): the storage for the min latency or NULL - * @max_latency: (out) (allow-none): the storage for the max latency or NULL + * @live: (out) (allow-none): storage for live or %NULL + * @min_latency: (out) (allow-none): the storage for the min latency or %NULL + * @max_latency: (out) (allow-none): the storage for the max latency or %NULL * * Parse a latency query answer. */ @@ -520,15 +513,15 @@ gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value, * gst_query_parse_convert: * @query: a #GstQuery * @src_format: (out) (allow-none): the storage for the #GstFormat of the - * source value, or NULL - * @src_value: (out) (allow-none): the storage for the source value, or NULL + * source value, or %NULL + * @src_value: (out) (allow-none): the storage for the source value, or %NULL * @dest_format: (out) (allow-none): the storage for the #GstFormat of the - * destination value, or NULL + * destination value, or %NULL * @dest_value: (out) (allow-none): the storage for the destination value, - * or NULL + * or %NULL * * Parse a convert query answer. Any of @src_format, @src_value, @dest_format, - * and @dest_value may be NULL, in which case that value is omitted. + * and @dest_value may be %NULL, in which case that value is omitted. */ void gst_query_parse_convert (GstQuery * query, GstFormat * src_format, @@ -623,14 +616,14 @@ gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format, /** * gst_query_parse_segment: * @query: a #GstQuery - * @rate: (out) (allow-none): the storage for the rate of the segment, or NULL + * @rate: (out) (allow-none): the storage for the rate of the segment, or %NULL * @format: (out) (allow-none): the storage for the #GstFormat of the values, - * or NULL - * @start_value: (out) (allow-none): the storage for the start value, or NULL - * @stop_value: (out) (allow-none): the storage for the stop value, or NULL + * or %NULL + * @start_value: (out) (allow-none): the storage for the start value, or %NULL + * @stop_value: (out) (allow-none): the storage for the stop value, or %NULL * * Parse a segment query answer. Any of @rate, @format, @start_value, and - * @stop_value may be NULL, which will cause this value to be omitted. + * @stop_value may be %NULL, which will cause this value to be omitted. * * See gst_query_set_segment() for an explanation of the function arguments. */ @@ -727,7 +720,7 @@ gst_query_get_structure (GstQuery * query) * @query: a #GstQuery * * Get the structure of a query. This method should be called with a writable - * @query so that the returned structure is guranteed to be writable. + * @query so that the returned structure is guaranteed to be writable. * * Returns: (transfer none): the #GstStructure of the query. The structure is * still owned by the query and will therefore be freed when the query @@ -801,14 +794,14 @@ gst_query_set_seeking (GstQuery * query, GstFormat format, * gst_query_parse_seeking: * @query: a GST_QUERY_SEEKING type query #GstQuery * @format: (out) (allow-none): the format to set for the @segment_start - * and @segment_end values, or NULL - * @seekable: (out) (allow-none): the seekable flag to set, or NULL - * @segment_start: (out) (allow-none): the segment_start to set, or NULL - * @segment_end: (out) (allow-none): the segment_end to set, or NULL + * and @segment_end values, or %NULL + * @seekable: (out) (allow-none): the seekable flag to set, or %NULL + * @segment_start: (out) (allow-none): the segment_start to set, or %NULL + * @segment_end: (out) (allow-none): the segment_end to set, or %NULL * * Parse a seeking query, writing the format into @format, and * other results into the passed parameters, if the respective parameters - * are non-NULL + * are non-%NULL */ void gst_query_parse_seeking (GstQuery * query, GstFormat * format, @@ -1081,8 +1074,8 @@ gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent) /** * gst_query_parse_buffering_percent: * @query: A valid #GstQuery of type GST_QUERY_BUFFERING. - * @busy: (out) (allow-none): if buffering is busy, or NULL - * @percent: (out) (allow-none): a buffering percent, or NULL + * @busy: (out) (allow-none): if buffering is busy, or %NULL + * @percent: (out) (allow-none): a buffering percent, or %NULL * * Get the percentage of buffered data. This is a value between 0 and 100. * The @busy indicator is %TRUE when the buffering is in progress. @@ -1134,11 +1127,11 @@ gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode, /** * gst_query_parse_buffering_stats: * @query: A valid #GstQuery of type GST_QUERY_BUFFERING. - * @mode: (out) (allow-none): a buffering mode, or NULL - * @avg_in: (out) (allow-none): the average input rate, or NULL - * @avg_out: (out) (allow-none): the average output rat, or NULLe + * @mode: (out) (allow-none): a buffering mode, or %NULL + * @avg_in: (out) (allow-none): the average input rate, or %NULL + * @avg_out: (out) (allow-none): the average output rat, or %NULL * @buffering_left: (out) (allow-none): amount of buffering time left in - * milliseconds, or NULL + * milliseconds, or %NULL * * Extracts the buffering stats values from @query. */ @@ -1175,7 +1168,7 @@ gst_query_parse_buffering_stats (GstQuery * query, * @start: the start to set * @stop: the stop to set * @estimated_total: estimated total amount of download time remaining in - * miliseconds + * milliseconds * * Set the available query result fields in @query. */ @@ -1200,15 +1193,15 @@ gst_query_set_buffering_range (GstQuery * query, GstFormat format, * gst_query_parse_buffering_range: * @query: a GST_QUERY_BUFFERING type query #GstQuery * @format: (out) (allow-none): the format to set for the @segment_start - * and @segment_end values, or NULL - * @start: (out) (allow-none): the start to set, or NULL - * @stop: (out) (allow-none): the stop to set, or NULL + * and @segment_end values, or %NULL + * @start: (out) (allow-none): the start to set, or %NULL + * @stop: (out) (allow-none): the stop to set, or %NULL * @estimated_total: (out) (allow-none): estimated total amount of download - * time remaining in miliseconds, or NULL + * time remaining in milliseconds, or %NULL * * Parse an available query, writing the format into @format, and * other results into the passed parameters, if the respective parameters - * are non-NULL + * are non-%NULL */ void gst_query_parse_buffering_range (GstQuery * query, GstFormat * format, @@ -1315,8 +1308,8 @@ gst_query_get_n_buffering_ranges (GstQuery * query) * gst_query_parse_nth_buffering_range: * @query: a GST_QUERY_BUFFERING type query #GstQuery * @index: position in the buffered-ranges array to read - * @start: (out) (allow-none): the start position to set, or NULL - * @stop: (out) (allow-none): the stop position to set, or NULL + * @start: (out) (allow-none): the start position to set, or %NULL + * @stop: (out) (allow-none): the stop position to set, or %NULL * * Parse an available query and get the start and stop values stored * at the @index of the buffered ranges array. @@ -1399,10 +1392,10 @@ gst_query_set_uri (GstQuery * query, const gchar * uri) * gst_query_parse_uri: * @query: a #GstQuery * @uri: (out) (transfer full) (allow-none): the storage for the current URI - * (may be NULL) + * (may be %NULL) * * Parse an URI query, writing the URI into @uri as a newly - * allocated string, if the respective parameters are non-NULL. + * allocated string, if the respective parameters are non-%NULL. * Free the string with g_free() after usage. */ void @@ -1445,10 +1438,10 @@ gst_query_set_uri_redirection (GstQuery * query, const gchar * uri) * gst_query_parse_uri_redirection: * @query: a #GstQuery * @uri: (out) (transfer full) (allow-none): the storage for the redirect URI - * (may be NULL) + * (may be %NULL) * * Parse an URI query, writing the URI into @uri as a newly - * allocated string, if the respective parameters are non-NULL. + * allocated string, if the respective parameters are non-%NULL. * Free the string with g_free() after usage. * * Since: 1.2 @@ -1469,6 +1462,58 @@ gst_query_parse_uri_redirection (GstQuery * query, gchar ** uri) } /** + * gst_query_set_uri_redirection_permanent: + * @query: a #GstQuery with query type GST_QUERY_URI + * @permanent: whether the redirect is permanent or not + * + * Answer a URI query by setting the requested URI redirection + * to permanent or not. + * + * Since: 1.4 + */ +void +gst_query_set_uri_redirection_permanent (GstQuery * query, gboolean permanent) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + g_return_if_fail (gst_query_is_writable (query)); + + structure = GST_QUERY_STRUCTURE (query); + gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION_PERMANENT), + G_TYPE_BOOLEAN, permanent, NULL); +} + +/** + * gst_query_parse_uri_redirection_permanent: + * @query: a #GstQuery + * @permanent: (out) (allow-none): if the URI redirection is permanent + * (may be %NULL) + * + * Parse an URI query, and set @permanent to %TRUE if there is a redirection + * and it should be considered permanent. If a redirection is permanent, + * applications should update their internal storage of the URI, otherwise + * they should make all future requests to the original URI. + * + * Since: 1.4 + */ +void +gst_query_parse_uri_redirection_permanent (GstQuery * query, + gboolean * permanent) +{ + GstStructure *structure; + + g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_URI); + + structure = GST_QUERY_STRUCTURE (query); + if (permanent) { + if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION_PERMANENT), + G_TYPE_BOOLEAN, permanent, NULL)) + *permanent = FALSE; + } +} + +/** * gst_query_new_allocation: * @caps: the negotiated caps * @need_pool: return a pool @@ -1502,7 +1547,7 @@ gst_query_new_allocation (GstCaps * caps, gboolean need_pool) * * Parse an allocation query, writing the requested caps in @caps and * whether a pool is needed in @need_pool, if the respective parameters - * are non-NULL. + * are non-%NULL. */ void gst_query_parse_allocation (GstQuery * query, GstCaps ** caps, @@ -1838,11 +1883,11 @@ gst_query_remove_nth_allocation_meta (GstQuery * query, guint index) * @api: the metadata API * @index: (out) (transfer none) (allow-none): the index * - * Check if @query has metadata @api set. When this function returns TRUE, + * Check if @query has metadata @api set. When this function returns %TRUE, * @index will contain the index where the requested API and the flags can be * found. * - * Returns: TRUE when @api is in the list of metadata. + * Returns: %TRUE when @api is in the list of metadata. */ gboolean gst_query_find_allocation_meta (GstQuery * query, GType api, guint * index) @@ -1954,7 +1999,7 @@ gst_query_get_n_allocation_params (GstQuery * query) * @allocator: (out) (transfer full) (allow-none): variable to hold the result * @params: (out) (allow-none): parameters for the allocator * - * Parse an available query and get the alloctor and its params + * Parse an available query and get the allocator and its params * at @index of the allocator array. */ void @@ -1988,7 +2033,7 @@ gst_query_parse_nth_allocation_param (GstQuery * query, guint index, * @allocator: (transfer none) (allow-none): new allocator to set * @params: (transfer none) (allow-none): parameters for the allocator * - * Parse an available query and get the alloctor and its params + * Parse an available query and get the allocator and its params * at @index of the allocator array. */ void @@ -2129,7 +2174,7 @@ gst_query_parse_scheduling (GstQuery * query, GstSchedulingFlags * flags, * @query: a GST_QUERY_SCHEDULING type query #GstQuery * @mode: a #GstPadMode * - * Add @mode as aone of the supported scheduling modes to @query. + * Add @mode as one of the supported scheduling modes to @query. */ void gst_query_add_scheduling_mode (GstQuery * query, GstPadMode mode) @@ -2215,7 +2260,7 @@ gst_query_parse_nth_scheduling_mode (GstQuery * query, guint index) * </para> * </note> * - * Returns: TRUE when @mode is in the list of scheduling modes. + * Returns: %TRUE when @mode is in the list of scheduling modes. */ gboolean gst_query_has_scheduling_mode (GstQuery * query, GstPadMode mode) @@ -2247,7 +2292,7 @@ gst_query_has_scheduling_mode (GstQuery * query, GstPadMode mode) * Check if @query has scheduling mode set and @flags is set in * query scheduling flags. * - * Returns: TRUE when @mode is in the list of scheduling modes + * Returns: %TRUE when @mode is in the list of scheduling modes * and @flags are compatible with query flags. */ gboolean @@ -2571,7 +2616,7 @@ gst_query_parse_context (GstQuery * query, GstContext ** context) /** * gst_query_parse_context_type: * @query: a GST_QUERY_CONTEXT type query - * @context_type: (out) (transfer none) (allow-none): the context type, or NULL + * @context_type: (out) (transfer none) (allow-none): the context type, or %NULL * * Parse a context type from an existing GST_QUERY_CONTEXT query. * diff --git a/gst/gstquery.h b/gst/gstquery.h index 8943b86..3750a19 100644 --- a/gst/gstquery.h +++ b/gst/gstquery.h @@ -132,7 +132,9 @@ typedef enum { } GstQueryType; #undef FLAG -#define GST_TYPE_QUERY (gst_query_get_type()) +GST_EXPORT GType _gst_query_type; + +#define GST_TYPE_QUERY (_gst_query_type) #define GST_IS_QUERY(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_QUERY)) #define GST_QUERY_CAST(obj) ((GstQuery*)(obj)) #define GST_QUERY(obj) (GST_QUERY_CAST(obj)) @@ -284,9 +286,9 @@ gst_query_copy (const GstQuery * q) * in some cases), and the reference counts are updated appropriately (the old * query is unreffed, the new one is reffed). * - * Either @new_query or the #GstQuery pointed to by @old_query may be NULL. + * Either @new_query or the #GstQuery pointed to by @old_query may be %NULL. * - * Returns: TRUE if @new_query was different from @old_query + * Returns: %TRUE if @new_query was different from @old_query */ #ifdef _FOOL_GTK_DOC_ G_INLINE_FUNC gboolean gst_query_replace (GstQuery **old_query, GstQuery *new_query); @@ -399,6 +401,8 @@ void gst_query_parse_uri (GstQuery *query, gchar **u void gst_query_set_uri (GstQuery *query, const gchar *uri); void gst_query_parse_uri_redirection (GstQuery *query, gchar **uri); void gst_query_set_uri_redirection (GstQuery *query, const gchar *uri); +void gst_query_parse_uri_redirection_permanent (GstQuery *query, gboolean * permanent); +void gst_query_set_uri_redirection_permanent (GstQuery *query, gboolean permanent); /* allocation query */ GstQuery * gst_query_new_allocation (GstCaps *caps, gboolean need_pool) G_GNUC_MALLOC; diff --git a/gst/gstregistry.c b/gst/gstregistry.c index c03a1ef..2838737 100644 --- a/gst/gstregistry.c +++ b/gst/gstregistry.c @@ -57,15 +57,21 @@ * <listitem> * <para>default locations (if GST_PLUGIN_SYSTEM_PATH is not set). Those * default locations are: - * <filename>~/.gstreamer-$GST_API_VERSION/plugins/</filename> + * <filename>$XDG_DATA_HOME/gstreamer-$GST_API_VERSION/plugins/</filename> * and <filename>$prefix/libs/gstreamer-$GST_API_VERSION/</filename>. + * <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html"> + * <filename>$XDG_DATA_HOME</filename></ulink> defaults to + * <filename>$HOME/.local/share</filename>. * </para> * </listitem> * </itemizedlist> * The registry cache file is loaded from - * <filename>~/.gstreamer-$GST_API_VERSION/registry-$ARCH.bin</filename> or the - * file listed in the GST_REGISTRY env var. One reason to change the registry - * location is for testing. + * <filename>$XDG_CACHE_HOME/gstreamer-$GST_API_VERSION/registry-$ARCH.bin</filename> + * (where + * <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html"> + * <filename>$XDG_CACHE_HOME</filename></ulink> defaults to + * <filename>$HOME/.cache</filename>) or the file listed in the GST_REGISTRY + * env var. One reason to change the registry location is for testing. * * For each plugin that is found in the plugin search path, there could be 3 * possibilities for cached information: @@ -98,8 +104,6 @@ * stored in the default registry, and plugins not relevant to the current * process are marked with the %GST_PLUGIN_FLAG_CACHED bit. These plugins are * removed at the end of initialization. - * - * Last reviewed on 2012-03-29 (0.11.3) */ #ifdef HAVE_CONFIG_H @@ -123,6 +127,7 @@ #include "gstinfo.h" #include "gsterror.h" #include "gstregistry.h" +#include "gstdevicemonitorfactory.h" #include "gstpluginloader.h" @@ -161,6 +166,8 @@ struct _GstRegistryPrivate guint32 efl_cookie; GList *typefind_factory_list; guint32 tfl_cookie; + GList *device_monitor_factory_list; + guint32 dmfl_cookie; }; /* the one instance of the default registry and the mutex protecting the @@ -310,6 +317,12 @@ gst_registry_finalize (GObject * object) gst_plugin_feature_list_free (registry->priv->typefind_factory_list); } + if (registry->priv->device_monitor_factory_list) { + GST_DEBUG_OBJECT (registry, + "Cleaning up cached device monitor factory list"); + gst_plugin_feature_list_free (registry->priv->device_monitor_factory_list); + } + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -417,7 +430,7 @@ gst_registry_get_path_list (GstRegistry * registry) * Add the plugin to the registry. The plugin-added signal will be emitted. * This function will sink @plugin. * - * Returns: TRUE on success. + * Returns: %TRUE on success. * * MT safe. */ @@ -543,7 +556,7 @@ gst_registry_remove_plugin (GstRegistry * registry, GstPlugin * plugin) * Add the feature to the registry. The feature-added signal will be emitted. * This function sinks @feature. * - * Returns: TRUE on success. + * Returns: %TRUE on success. * * MT safe. */ @@ -774,6 +787,28 @@ gst_registry_get_typefind_factory_list (GstRegistry * registry) return list; } + +static GList * +gst_registry_get_device_monitor_factory_list (GstRegistry * registry) +{ + GList *list; + + GST_OBJECT_LOCK (registry); + + gst_registry_get_feature_list_or_create (registry, + ®istry->priv->device_monitor_factory_list, + ®istry->priv->dmfl_cookie, GST_TYPE_DEVICE_MONITOR_FACTORY); + + /* Return reffed copy */ + list = + gst_plugin_feature_list_copy (registry-> + priv->device_monitor_factory_list); + + GST_OBJECT_UNLOCK (registry); + + return list; +} + /** * gst_registry_feature_filter: * @registry: registry to query @@ -833,7 +868,7 @@ gst_registry_plugin_name_filter (GstPlugin * plugin, const gchar * name) * Find the plugin with the given name in the registry. * The plugin will be reffed; caller is responsible for unreffing. * - * Returns: (transfer full): the plugin with the given name or NULL if the + * Returns: (transfer full): the plugin with the given name or %NULL if the * plugin was not found. gst_object_unref() after usage. * * MT safe. @@ -868,7 +903,7 @@ gst_registry_find_plugin (GstRegistry * registry, const gchar * name) * Find the pluginfeature with the given name and type in the registry. * * Returns: (transfer full): the pluginfeature with the given name and type - * or NULL if the plugin was not found. gst_object_unref() after usage. + * or %NULL if the plugin was not found. gst_object_unref() after usage. * * MT safe. */ @@ -916,6 +951,8 @@ gst_registry_get_feature_list (GstRegistry * registry, GType type) return gst_registry_get_element_factory_list (registry); else if (type == GST_TYPE_TYPE_FIND_FACTORY) return gst_registry_get_typefind_factory_list (registry); + else if (type == GST_TYPE_DEVICE_MONITOR_FACTORY) + return gst_registry_get_device_monitor_factory_list (registry); data.type = type; data.name = NULL; @@ -1018,7 +1055,7 @@ gst_registry_lookup_bn (GstRegistry * registry, const char *basename) * Look up a plugin in the given registry with the given filename. * If found, plugin is reffed. * - * Returns: (transfer full): the #GstPlugin if found, or NULL if not. + * Returns: (transfer full): the #GstPlugin if found, or %NULL if not. * gst_object_unref() after usage. */ GstPlugin * @@ -1415,8 +1452,8 @@ _priv_gst_registry_cleanup (void) * @registry and whether its version is at least the * version required. * - * Returns: #TRUE if the feature could be found and the version is - * the same as the required version or newer, and #FALSE otherwise. + * Returns: %TRUE if the feature could be found and the version is + * the same as the required version or newer, and %FALSE otherwise. */ gboolean gst_registry_check_feature_version (GstRegistry * registry, @@ -1471,7 +1508,7 @@ load_plugin_func (gpointer data, gpointer user_data) #ifndef GST_DISABLE_REGISTRY /* Unref all plugins marked 'cached', to clear old plugins that no - * longer exist. Returns TRUE if any plugins were removed */ + * longer exist. Returns %TRUE if any plugins were removed */ static gboolean gst_registry_remove_cache_plugins (GstRegistry * registry) { @@ -1593,8 +1630,6 @@ scan_and_update_registry (GstRegistry * default_registry, g_free (home_plugins); /* add the main (installed) library path */ - GST_DEBUG ("scanning main plugins %s", PLUGINDIR); - changed |= gst_registry_scan_path_internal (&context, PLUGINDIR); #ifdef G_OS_WIN32 { @@ -1605,9 +1640,11 @@ scan_and_update_registry (GstRegistry * default_registry, g_win32_get_package_installation_directory_of_module (_priv_gst_dll_handle); - dir = - g_build_filename (base_dir, "lib", "gstreamer-" GST_API_VERSION, - NULL); + dir = g_build_filename (base_dir, +#ifdef _DEBUG + "debug" +#endif + "lib", "gstreamer-" GST_API_VERSION, NULL); GST_DEBUG ("scanning DLL dir %s", dir); changed |= gst_registry_scan_path_internal (&context, dir); @@ -1615,6 +1652,9 @@ scan_and_update_registry (GstRegistry * default_registry, g_free (dir); g_free (base_dir); } +#else + GST_DEBUG ("scanning main plugins %s", PLUGINDIR); + changed |= gst_registry_scan_path_internal (&context, PLUGINDIR); #endif } else { gchar **list; @@ -1807,7 +1847,7 @@ gst_update_registry (void) * gst_registry_get_feature_list_cookie: * @registry: the registry * - * Returns the registrys feature list cookie. This changes + * Returns the registry's feature list cookie. This changes * every time a feature is added or removed from the registry. * * Returns: the feature list cookie. diff --git a/gst/gstregistrybinary.c b/gst/gstregistrybinary.c index 837e3b4..ee4a7a0 100644 --- a/gst/gstregistrybinary.c +++ b/gst/gstregistrybinary.c @@ -56,6 +56,7 @@ #include <gst/gstelement.h> #include <gst/gsttypefind.h> #include <gst/gsttypefindfactory.h> +#include <gst/gstdevicemonitorfactory.h> #include <gst/gsturi.h> #include <gst/gstinfo.h> #include <gst/gstenumtypes.h> @@ -525,6 +526,7 @@ priv_gst_registry_binary_read_cache (GstRegistry * registry, /* make sure these types exist */ GST_TYPE_ELEMENT_FACTORY; GST_TYPE_TYPE_FIND_FACTORY; + GST_TYPE_DEVICE_MONITOR_FACTORY; #ifndef GST_DISABLE_GST_DEBUG timer = g_timer_new (); diff --git a/gst/gstregistrychunks.c b/gst/gstregistrychunks.c index 571f6be..fcacd6b 100644 --- a/gst/gstregistrychunks.c +++ b/gst/gstregistrychunks.c @@ -33,6 +33,7 @@ #include <gst/gstelement.h> #include <gst/gsttypefind.h> #include <gst/gsttypefindfactory.h> +#include <gst/gstdevicemonitorfactory.h> #include <gst/gsturi.h> #include <gst/gstinfo.h> #include <gst/gstenumtypes.h> @@ -227,10 +228,11 @@ G_STMT_START { \ static gboolean gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature) { - const gchar *type_name = g_type_name (G_OBJECT_TYPE (feature)); + const gchar *type_name = G_OBJECT_TYPE_NAME (feature); GstRegistryChunkPluginFeature *pf = NULL; GstRegistryChunk *chk = NULL; GList *walk; + gsize pf_size = 0; if (!type_name) { GST_ERROR ("NULL feature type_name, aborting."); @@ -245,9 +247,8 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature) * valgrind complaining about copying unitialized memory */ ef = g_slice_new0 (GstRegistryChunkElementFactory); - chk = - gst_registry_chunks_make_data (ef, - sizeof (GstRegistryChunkElementFactory)); + pf_size = sizeof (GstRegistryChunkElementFactory); + chk = gst_registry_chunks_make_data (ef, pf_size); ef->npadtemplates = ef->ninterfaces = ef->nuriprotocols = 0; pf = (GstRegistryChunkPluginFeature *) ef; @@ -256,8 +257,8 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature) walk = g_list_next (walk), ef->ninterfaces++) { gst_registry_chunks_save_const_string (list, (gchar *) walk->data); } - GST_DEBUG ("Feature %s: saved %d interfaces %d pad templates", - GST_OBJECT_NAME (feature), ef->ninterfaces, ef->npadtemplates); + GST_DEBUG_OBJECT (feature, "saved %d interfaces %d pad templates", + ef->ninterfaces, ef->npadtemplates); /* save uritypes */ if (GST_URI_TYPE_IS_VALID (factory->uri_type)) { @@ -276,7 +277,7 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature) ef->nuriprotocols++; } *list = g_list_prepend (*list, subchk); - GST_DEBUG ("Saved %d UriTypes", ef->nuriprotocols); + GST_DEBUG_OBJECT (feature, "Saved %d UriTypes", ef->nuriprotocols); } else { g_warning ("GStreamer feature '%s' is URI handler but does not provide" " any protocols it can handle", GST_OBJECT_NAME (feature)); @@ -289,7 +290,7 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature) GstStaticPadTemplate *template = walk->data; if (!gst_registry_chunks_save_pad_template (list, template)) { - GST_ERROR ("Can't fill pad template, aborting."); + GST_ERROR_OBJECT (feature, "Can't fill pad template, aborting."); goto fail; } } @@ -306,9 +307,8 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature) * valgrind complaining about copying unitialized memory */ tff = g_slice_new0 (GstRegistryChunkTypeFindFactory); - chk = - gst_registry_chunks_make_data (tff, - sizeof (GstRegistryChunkTypeFindFactory)); + pf_size = sizeof (GstRegistryChunkTypeFindFactory); + chk = gst_registry_chunks_make_data (tff, pf_size); tff->nextensions = 0; pf = (GstRegistryChunkPluginFeature *) tff; @@ -319,6 +319,7 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature) factory->extensions[tff->nextensions++]); } } + GST_DEBUG_OBJECT (feature, "saved %d extensions", tff->nextensions); /* save caps */ if (factory->caps) { GstCaps *fcaps = gst_caps_ref (factory->caps); @@ -332,8 +333,25 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature) } else { gst_registry_chunks_save_const_string (list, ""); } + } else if (GST_IS_DEVICE_MONITOR_FACTORY (feature)) { + GstRegistryChunkDeviceMonitorFactory *tff; + GstDeviceMonitorFactory *factory = GST_DEVICE_MONITOR_FACTORY (feature); + + /* Initialize with zeroes because of struct padding and + * valgrind complaining about copying unitialized memory + */ + tff = g_slice_new0 (GstRegistryChunkDeviceMonitorFactory); + chk = + gst_registry_chunks_make_data (tff, + sizeof (GstRegistryChunkDeviceMonitorFactory)); + pf = (GstRegistryChunkPluginFeature *) tff; + + + /* pack element metadata strings */ + gst_registry_chunks_save_string (list, + gst_structure_to_string (factory->metadata)); } else { - GST_WARNING ("unhandled feature type '%s'", type_name); + GST_WARNING_OBJECT (feature, "unhandled feature type '%s'", type_name); } if (pf) { @@ -349,8 +367,8 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature) /* Errors */ fail: - g_free (chk); - g_free (pf); + g_slice_free (GstRegistryChunk, chk); + g_slice_free1 (pf_size, pf); return FALSE; } @@ -465,8 +483,8 @@ _priv_gst_registry_chunks_save_plugin (GList ** list, GstRegistry * registry, /* Errors */ fail: gst_plugin_feature_list_free (plugin_features); - g_free (chk); - g_free (pe); + g_slice_free (GstRegistryChunk, chk); + g_slice_free (GstRegistryChunkPluginElement, pe); return FALSE; } @@ -650,6 +668,30 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in, factory->extensions[i - 1] = str; } } + } else if (GST_IS_DEVICE_MONITOR_FACTORY (feature)) { + GstRegistryChunkDeviceMonitorFactory *dmf; + GstDeviceMonitorFactory *factory = GST_DEVICE_MONITOR_FACTORY (feature); + const gchar *meta_data_str; + + align (*in); + GST_DEBUG + ("Reading/casting for GstRegistryChunkPluginFeature at address %p", + *in); + unpack_element (*in, dmf, GstRegistryChunkDeviceMonitorFactory, end, fail); + + pf = (GstRegistryChunkPluginFeature *) dmf; + + /* unpack element factory strings */ + unpack_string_nocopy (*in, meta_data_str, end, fail); + if (meta_data_str && *meta_data_str) { + factory->metadata = gst_structure_from_string (meta_data_str, NULL); + if (!factory->metadata) { + GST_ERROR + ("Error when trying to deserialize structure for metadata '%s'", + meta_data_str); + goto fail; + } + } } else { GST_WARNING ("unhandled factory type : %s", G_OBJECT_TYPE_NAME (feature)); goto fail; diff --git a/gst/gstregistrychunks.h b/gst/gstregistrychunks.h index 3e6e923..e2c86ba 100644 --- a/gst/gstregistrychunks.h +++ b/gst/gstregistrychunks.h @@ -122,7 +122,7 @@ typedef struct _GstRegistryChunkElementFactory * GstRegistryChunkTypeFindFactory: * @nextensions: stores the number of typefind extensions * - * A structure containing the element factory fields + * A structure containing the type find factory fields */ typedef struct _GstRegistryChunkTypeFindFactory { @@ -132,6 +132,17 @@ typedef struct _GstRegistryChunkTypeFindFactory } GstRegistryChunkTypeFindFactory; /* + * GstRegistryChunkDeviceMonitorFactory: + * + * A structure containing the device monitor factory fields + */ +typedef struct _GstRegistryChunkDeviceMonitorFactory +{ + GstRegistryChunkPluginFeature plugin_feature; + +} GstRegistryChunkDeviceMonitorFactory; + +/* * GstRegistryChunkPadTemplate: * * A structure containing the static pad templates of a plugin feature diff --git a/gst/gstsample.c b/gst/gstsample.c index 9517af0..76b76bd 100644 --- a/gst/gstsample.c +++ b/gst/gstsample.c @@ -26,8 +26,6 @@ * * A #GstSample is a small object containing data, a type, timing and * extra arbitrary information. - * - * Last reviewed on 2012-03-29 (0.11.3) */ #include "gst_private.h" @@ -87,10 +85,10 @@ _gst_sample_free (GstSample * sample) /** * gst_sample_new: - * @buffer: (transfer none) (allow-none): a #GstBuffer, or NULL - * @caps: (transfer none) (allow-none): a #GstCaps, or NULL - * @segment: (transfer none) (allow-none): a #GstSegment, or NULL - * @info: (transfer full) (allow-none): a #GstStructure, or NULL + * @buffer: (transfer none) (allow-none): a #GstBuffer, or %NULL + * @caps: (transfer none) (allow-none): a #GstCaps, or %NULL + * @segment: (transfer none) (allow-none): a #GstSegment, or %NULL + * @info: (transfer full) (allow-none): a #GstStructure, or %NULL * * Create a new #GstSample with the provided details. * @@ -145,7 +143,7 @@ had_parent: * * Get the buffer associated with @sample * - * Returns: (transfer none): the buffer of @sample or NULL when there + * Returns: (transfer none): the buffer of @sample or %NULL when there * is no buffer. The buffer remains valid as long as @sample is valid. * If you need to hold on to it for longer than that, take a ref to * the buffer with gst_buffer_ref(). @@ -164,7 +162,7 @@ gst_sample_get_buffer (GstSample * sample) * * Get the caps associated with @sample * - * Returns: (transfer none): the caps of @sample or NULL when there + * Returns: (transfer none): the caps of @sample or %NULL when there * is no caps. The caps remain valid as long as @sample is valid. * If you need to hold on to the caps for longer than that, take a ref to * the caps with gst_caps_ref(). diff --git a/gst/gstsegment.c b/gst/gstsegment.c index cb6d19c..3c4081b 100644 --- a/gst/gstsegment.c +++ b/gst/gstsegment.c @@ -79,8 +79,6 @@ * For elements that need to perform operations on media data in stream_time, * gst_segment_to_stream_time() can be used to convert a timestamp and the segment * info to stream time (which is always between 0 and the duration of the stream). - * - * Last reviewed on 2012-03-29 (0.11.3) */ /** @@ -218,8 +216,8 @@ gst_segment_init (GstSegment * segment, GstFormat format) * If the caller can apply a rate change, it should update @segment * rate and applied_rate after calling this function. * - * @update will be set to TRUE if a seek should be performed to the segment - * position field. This field can be FALSE if, for example, only the @rate + * @update will be set to %TRUE if a seek should be performed to the segment + * position field. This field can be %FALSE if, for example, only the @rate * has been changed but not the playback position. * * Returns: %TRUE if the seek could be performed. @@ -460,7 +458,7 @@ gst_segment_to_stream_time (const GstSegment * segment, GstFormat format, * segment. Position is a value between @segment start and stop time. * * This function is typically used by elements that need to synchronize to the - * global clock in a pipeline. The runnning time is a constantly increasing value + * global clock in a pipeline. The running time is a constantly increasing value * starting from 0. When gst_segment_init() is called, this value will reset to * 0. * @@ -553,18 +551,18 @@ gst_segment_to_running_time (const GstSegment * segment, GstFormat format, * in @segment. @start and @stop are compared and clipped to @segment * start and stop values. * - * If the function returns FALSE, @start and @stop are known to fall + * If the function returns %FALSE, @start and @stop are known to fall * outside of @segment and @clip_start and @clip_stop are not updated. * - * When the function returns TRUE, @clip_start and @clip_stop will be + * When the function returns %TRUE, @clip_start and @clip_stop will be * updated. If @clip_start or @clip_stop are different from @start or @stop * respectively, the region fell partially in the segment. * * Note that when @stop is -1, @clip_stop will be set to the end of the * segment. Depending on the use case, this may or may not be what you want. * - * Returns: TRUE if the given @start and @stop times fall partially or - * completely in @segment, FALSE if the values are completely outside + * Returns: %TRUE if the given @start and @stop times fall partially or + * completely in @segment, %FALSE if the values are completely outside * of the segment. */ gboolean diff --git a/gst/gstsegment.h b/gst/gstsegment.h index 0f08eb5..c9ec1e4 100644 --- a/gst/gstsegment.h +++ b/gst/gstsegment.h @@ -56,7 +56,7 @@ typedef enum { * @GST_SEEK_FLAG_KEY_UNIT: seek to the nearest keyframe. This might be * faster but less accurate. * @GST_SEEK_FLAG_SEGMENT: perform a segment seek. - * @GST_SEEK_FLAG_SKIP: when doing fast foward or fast reverse playback, allow + * @GST_SEEK_FLAG_SKIP: when doing fast forward or fast reverse playback, allow * elements to skip frames instead of generating all * frames. * @GST_SEEK_FLAG_SNAP_BEFORE: go to a location before the requested position, @@ -81,7 +81,7 @@ typedef enum { * complete scan of the file in those cases. * * When performing a segment seek: after the playback of the segment completes, - * no EOS will be emmited by the element that performed the seek, but a + * no EOS will be emitted by the element that performed the seek, but a * #GST_MESSAGE_SEGMENT_DONE message will be posted on the bus by the element. * When this message is posted, it is possible to send a new seek event to * continue playback. With this seek method it is possible to perform seamless diff --git a/gst/gststructure.c b/gst/gststructure.c index 48b7031..5013860 100644 --- a/gst/gststructure.c +++ b/gst/gststructure.c @@ -51,9 +51,13 @@ * gst_structure_remove_fields(). * * Strings in structures must be ASCII or UTF-8 encoded. Other encodings are - * not allowed. Strings must not be empty either, but may be NULL. + * not allowed. Strings may be %NULL however. * - * Last reviewed on 2012-03-29 (0.11.3) + * Be aware that the current #GstCaps / #GstStructure serialization into string + * has limited support for nested #GstCaps / #GstStructure fields. It can only + * support one level of nesting. Using more levels will lead to unexpected + * behavior when using serialization features, such as gst_caps_to_string() or + * gst_value_serialize() and their counterparts. */ #ifdef HAVE_CONFIG_H @@ -233,7 +237,7 @@ gst_structure_new_empty (const gchar * name) * Creates a new #GstStructure with the given name. Parses the * list of variable arguments and sets fields to the values listed. * Variable arguments should be passed as field name, field type, - * and value. Last variable argument should be NULL. + * and value. Last variable argument should be %NULL. * * Free-function: gst_structure_free * @@ -411,7 +415,7 @@ gst_structure_get_name (const GstStructure * structure) * * Checks if the structure has the given name * - * Returns: TRUE if @name matches the name of the structure. + * Returns: %TRUE if @name matches the name of the structure. */ gboolean gst_structure_has_name (const GstStructure * structure, const gchar * name) @@ -617,7 +621,7 @@ gst_structure_set_valist_internal (GstStructure * structure, * * Parses the variable arguments and sets fields accordingly. * Variable arguments should be in the form field name, field type - * (as a GType), value(s). The last variable argument should be NULL. + * (as a GType), value(s). The last variable argument should be %NULL. */ void gst_structure_set (GstStructure * structure, const gchar * field, ...) @@ -690,7 +694,7 @@ gst_structure_id_set_valist_internal (GstStructure * structure, * passed using the GQuark for the field name. This allows more efficient * setting of the structure if the caller already knows the associated * quark values. - * The last variable argument must be NULL. + * The last variable argument must be %NULL. */ void gst_structure_id_set (GstStructure * structure, GQuark field, ...) @@ -733,7 +737,7 @@ gst_structure_id_set_valist (GstStructure * structure, * gst_structure_id_set(). Basically a convenience wrapper around * gst_structure_new_id_empty() and gst_structure_id_set(). * - * The last variable argument must be NULL (or 0). + * The last variable argument must be %NULL (or 0). * * Free-function: gst_structure_free * @@ -771,9 +775,13 @@ static void gst_structure_set_field (GstStructure * structure, GstStructureField * field) { GstStructureField *f; - guint i, len = GST_STRUCTURE_FIELDS (structure)->len; + GType field_value_type; + guint i, len; + + len = GST_STRUCTURE_FIELDS (structure)->len; - if (G_UNLIKELY (G_VALUE_HOLDS_STRING (&field->value))) { + field_value_type = G_VALUE_TYPE (&field->value); + if (field_value_type == G_TYPE_STRING) { const gchar *s; s = g_value_get_string (&field->value); @@ -800,7 +808,7 @@ gst_structure_set_field (GstStructure * structure, GstStructureField * field) g_value_unset (&field->value); return; } - } else if (G_UNLIKELY (G_VALUE_HOLDS (&field->value, G_TYPE_DATE))) { + } else if (G_UNLIKELY (field_value_type == G_TYPE_DATE)) { const GDate *d; d = g_value_get_boxed (&field->value); @@ -956,7 +964,7 @@ gst_structure_remove_field (GstStructure * structure, const gchar * fieldname) * gst_structure_remove_fields: * @structure: a #GstStructure * @fieldname: the name of the field to remove - * @...: NULL-terminated list of more fieldnames to remove + * @...: %NULL-terminated list of more fieldnames to remove * * Removes the fields with the given names. If a field does not exist, the * argument is ignored. @@ -980,7 +988,7 @@ gst_structure_remove_fields (GstStructure * structure, * gst_structure_remove_fields_valist: * @structure: a #GstStructure * @fieldname: the name of the field to remove - * @varargs: NULL-terminated list of more fieldnames to remove + * @varargs: %NULL-terminated list of more fieldnames to remove * * va_list form of gst_structure_remove_fields(). */ @@ -1100,8 +1108,8 @@ gst_structure_nth_field_name (const GstStructure * structure, guint index) * Calls the provided function once for each field in the #GstStructure. The * function must not modify the fields. Also see gst_structure_map_in_place(). * - * Returns: TRUE if the supplied function returns TRUE For each of the fields, - * FALSE otherwise. + * Returns: %TRUE if the supplied function returns %TRUE For each of the fields, + * %FALSE otherwise. */ gboolean gst_structure_foreach (const GstStructure * structure, @@ -1137,8 +1145,8 @@ gst_structure_foreach (const GstStructure * structure, * contrast to gst_structure_foreach(), the function may modify but not delete the * fields. The structure must be mutable. * - * Returns: TRUE if the supplied function returns TRUE For each of the fields, - * FALSE otherwise. + * Returns: %TRUE if the supplied function returns %TRUE For each of the fields, + * %FALSE otherwise. */ gboolean gst_structure_map_in_place (GstStructure * structure, @@ -1171,7 +1179,7 @@ gst_structure_map_in_place (GstStructure * structure, * * Check if @structure contains a field named @field. * - * Returns: TRUE if the structure contains a field with the given name + * Returns: %TRUE if the structure contains a field with the given name */ gboolean gst_structure_id_has_field (const GstStructure * structure, GQuark field) @@ -1193,7 +1201,7 @@ gst_structure_id_has_field (const GstStructure * structure, GQuark field) * * Check if @structure contains a field named @fieldname. * - * Returns: TRUE if the structure contains a field with the given name + * Returns: %TRUE if the structure contains a field with the given name */ gboolean gst_structure_has_field (const GstStructure * structure, @@ -1214,7 +1222,7 @@ gst_structure_has_field (const GstStructure * structure, * * Check if @structure contains a field named @field and with GType @type. * - * Returns: TRUE if the structure contains a field with the given name and type + * Returns: %TRUE if the structure contains a field with the given name and type */ gboolean gst_structure_id_has_field_typed (const GstStructure * structure, @@ -1240,7 +1248,7 @@ gst_structure_id_has_field_typed (const GstStructure * structure, * * Check if @structure contains a field named @fieldname and with GType @type. * - * Returns: TRUE if the structure contains a field with the given name and type + * Returns: %TRUE if the structure contains a field with the given name and type */ gboolean gst_structure_has_field_typed (const GstStructure * structure, @@ -1265,9 +1273,9 @@ gst_structure_has_field_typed (const GstStructure * structure, * given field. Caller is responsible for making sure the field exists * and has the correct type. * - * Returns: TRUE if the value could be set correctly. If there was no field + * Returns: %TRUE if the value could be set correctly. If there was no field * with @fieldname or the existing field did not contain a boolean, this - * function returns FALSE. + * function returns %FALSE. */ gboolean gst_structure_get_boolean (const GstStructure * structure, @@ -1280,9 +1288,7 @@ gst_structure_get_boolean (const GstStructure * structure, field = gst_structure_get_field (structure, fieldname); - if (field == NULL) - return FALSE; - if (!G_VALUE_HOLDS_BOOLEAN (&field->value)) + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_BOOLEAN) return FALSE; *value = gst_g_value_get_boolean_unchecked (&field->value); @@ -1316,9 +1322,7 @@ gst_structure_get_int (const GstStructure * structure, field = gst_structure_get_field (structure, fieldname); - if (field == NULL) - return FALSE; - if (!G_VALUE_HOLDS_INT (&field->value)) + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_INT) return FALSE; *value = gst_g_value_get_int_unchecked (&field->value); @@ -1352,9 +1356,7 @@ gst_structure_get_uint (const GstStructure * structure, field = gst_structure_get_field (structure, fieldname); - if (field == NULL) - return FALSE; - if (!G_VALUE_HOLDS_UINT (&field->value)) + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_UINT) return FALSE; *value = gst_g_value_get_uint_unchecked (&field->value); @@ -1363,6 +1365,78 @@ gst_structure_get_uint (const GstStructure * structure, } /** + * gst_structure_get_int64: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out): a pointer to an int64 to set + * + * Sets the int64 pointed to by @value corresponding to the value of the + * given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain an int64, this function + * returns %FALSE. + * + * Since: 1.4 + */ +gboolean +gst_structure_get_int64 (const GstStructure * structure, + const gchar * fieldname, gint64 * value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_INT64) + return FALSE; + + *value = gst_g_value_get_int64_unchecked (&field->value); + + return TRUE; +} + +/** + * gst_structure_get_uint64: + * @structure: a #GstStructure + * @fieldname: the name of a field + * @value: (out): a pointer to a uint64 to set + * + * Sets the uint64 pointed to by @value corresponding to the value of the + * given field. Caller is responsible for making sure the field exists + * and has the correct type. + * + * Returns: %TRUE if the value could be set correctly. If there was no field + * with @fieldname or the existing field did not contain a uint64, this function + * returns %FALSE. + * + * Since: 1.4 + */ +gboolean +gst_structure_get_uint64 (const GstStructure * structure, + const gchar * fieldname, guint64 * value) +{ + GstStructureField *field; + + g_return_val_if_fail (structure != NULL, FALSE); + g_return_val_if_fail (fieldname != NULL, FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + field = gst_structure_get_field (structure, fieldname); + + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_UINT64) + return FALSE; + + *value = gst_g_value_get_uint64_unchecked (&field->value); + + return TRUE; +} + +/** * gst_structure_get_date: * @structure: a #GstStructure * @fieldname: the name of a field @@ -1377,9 +1451,9 @@ gst_structure_get_uint (const GstStructure * structure, * inconsistent with e.g. gst_structure_get_string() which doesn't return a * copy of the string). * - * Returns: TRUE if the value could be set correctly. If there was no field + * Returns: %TRUE if the value could be set correctly. If there was no field * with @fieldname or the existing field did not contain a data, this function - * returns FALSE. + * returns %FALSE. */ gboolean gst_structure_get_date (const GstStructure * structure, const gchar * fieldname, @@ -1393,12 +1467,10 @@ gst_structure_get_date (const GstStructure * structure, const gchar * fieldname, field = gst_structure_get_field (structure, fieldname); - if (field == NULL) - return FALSE; - if (!G_VALUE_HOLDS (&field->value, G_TYPE_DATE)) + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_DATE) return FALSE; - /* FIXME: 0.11 g_value_dup_boxed() -> g_value_get_boxed() */ + /* FIXME: 2.0 g_value_dup_boxed() -> g_value_get_boxed() */ *value = g_value_dup_boxed (&field->value); return TRUE; @@ -1419,9 +1491,9 @@ gst_structure_get_date (const GstStructure * structure, const gchar * fieldname, * (note: this is inconsistent with e.g. gst_structure_get_string() * which doesn't return a copy of the string). * - * Returns: TRUE if the value could be set correctly. If there was no field + * Returns: %TRUE if the value could be set correctly. If there was no field * with @fieldname or the existing field did not contain a data, this function - * returns FALSE. + * returns %FALSE. */ gboolean gst_structure_get_date_time (const GstStructure * structure, @@ -1456,30 +1528,15 @@ gst_structure_get_date_time (const GstStructure * structure, * of the given field. Caller is responsible for making sure the field exists * and has the correct type. * - * Returns: TRUE if the value could be set correctly. If there was no field + * Returns: %TRUE if the value could be set correctly. If there was no field * with @fieldname or the existing field did not contain a #GstClockTime, this - * function returns FALSE. + * function returns %FALSE. */ gboolean gst_structure_get_clock_time (const GstStructure * structure, const gchar * fieldname, GstClockTime * value) { - GstStructureField *field; - - g_return_val_if_fail (structure != NULL, FALSE); - g_return_val_if_fail (fieldname != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); - - field = gst_structure_get_field (structure, fieldname); - - if (field == NULL) - return FALSE; - if (!G_VALUE_HOLDS_UINT64 (&field->value)) - return FALSE; - - *value = gst_g_value_get_uint64_unchecked (&field->value); - - return TRUE; + return gst_structure_get_uint64 (structure, fieldname, value); } /** @@ -1492,9 +1549,9 @@ gst_structure_get_clock_time (const GstStructure * structure, * given field. Caller is responsible for making sure the field exists * and has the correct type. * - * Returns: TRUE if the value could be set correctly. If there was no field + * Returns: %TRUE if the value could be set correctly. If there was no field * with @fieldname or the existing field did not contain a double, this - * function returns FALSE. + * function returns %FALSE. */ gboolean gst_structure_get_double (const GstStructure * structure, @@ -1508,9 +1565,7 @@ gst_structure_get_double (const GstStructure * structure, field = gst_structure_get_field (structure, fieldname); - if (field == NULL) - return FALSE; - if (!G_VALUE_HOLDS_DOUBLE (&field->value)) + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_DOUBLE) return FALSE; *value = gst_g_value_get_double_unchecked (&field->value); @@ -1530,7 +1585,7 @@ gst_structure_get_double (const GstStructure * structure, * The string should not be modified, and remains valid until the next * call to a gst_structure_*() function with the given structure. * - * Returns: a pointer to the string or NULL when the field did not exist + * Returns: a pointer to the string or %NULL when the field did not exist * or did not contain a string. */ const gchar * @@ -1544,9 +1599,7 @@ gst_structure_get_string (const GstStructure * structure, field = gst_structure_get_field (structure, fieldname); - if (field == NULL) - return NULL; - if (!G_VALUE_HOLDS_STRING (&field->value)) + if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_STRING) return NULL; return gst_g_value_get_string_unchecked (&field->value); @@ -1563,9 +1616,9 @@ gst_structure_get_string (const GstStructure * structure, * given field. Caller is responsible for making sure the field exists, * has the correct type and that the enumtype is correct. * - * Returns: TRUE if the value could be set correctly. If there was no field + * Returns: %TRUE if the value could be set correctly. If there was no field * with @fieldname or the existing field did not contain an enum of the given - * type, this function returns FALSE. + * type, this function returns %FALSE. */ gboolean gst_structure_get_enum (const GstStructure * structure, @@ -1601,9 +1654,9 @@ gst_structure_get_enum (const GstStructure * structure, * corresponding to the value of the given field. Caller is responsible * for making sure the field exists and has the correct type. * - * Returns: TRUE if the values could be set correctly. If there was no field + * Returns: %TRUE if the values could be set correctly. If there was no field * with @fieldname or the existing field did not contain a GstFraction, this - * function returns FALSE. + * function returns %FALSE. */ gboolean gst_structure_get_fraction (const GstStructure * structure, @@ -1618,9 +1671,7 @@ gst_structure_get_fraction (const GstStructure * structure, field = gst_structure_get_field (structure, fieldname); - if (field == NULL) - return FALSE; - if (!GST_VALUE_HOLDS_FRACTION (&field->value)) + if (field == NULL || G_VALUE_TYPE (&field->value) != GST_TYPE_FRACTION) return FALSE; *value_numerator = gst_value_get_fraction_numerator (&field->value); @@ -1815,7 +1866,10 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure, * |[ * GST_LOG ("structure is %" GST_PTR_FORMAT, structure); * ]| - * This prints the structure in human readble form. + * This prints the structure in human readable form. + * + * The current implementation of serialization will lead to unexpected results + * when there are nested #GstCaps / #GstStructure deeper than one level. * * Free-function: g_free * @@ -2312,12 +2366,15 @@ priv_gst_structure_parse_fields (gchar * str, gchar ** end, * @string: a string representation of a #GstStructure * * Creates a #GstStructure from a string representation. - * If end is not NULL, a pointer to the place inside the given string + * If end is not %NULL, a pointer to the place inside the given string * where parsing ended will be returned. * + * The current implementation of serialization will lead to unexpected results + * when there are nested #GstCaps / #GstStructure deeper than one level. + * * Free-function: gst_structure_free * - * Returns: (transfer full): a new #GstStructure or NULL when the string could + * Returns: (transfer full): a new #GstStructure or %NULL when the string could * not be parsed. Free with gst_structure_free() after use. * * Since: 1.2 @@ -2334,12 +2391,12 @@ gst_structure_new_from_string (const gchar * string) * @end: (out) (allow-none) (transfer none) (skip): pointer to store the end of the string in. * * Creates a #GstStructure from a string representation. - * If end is not NULL, a pointer to the place inside the given string + * If end is not %NULL, a pointer to the place inside the given string * where parsing ended will be returned. * * Free-function: gst_structure_free * - * Returns: (transfer full): a new #GstStructure or NULL when the string could + * Returns: (transfer full): a new #GstStructure or %NULL when the string could * not be parsed. Free with gst_structure_free() after use. */ GstStructure * @@ -2417,7 +2474,7 @@ gst_structure_copy_conditional (const GstStructure * structure) * Fixates a #GstStructure by changing the given field to the nearest * integer to @target that is a subset of the existing field. * - * Returns: TRUE if the structure could be fixated + * Returns: %TRUE if the structure could be fixated */ gboolean gst_structure_fixate_field_nearest_int (GstStructure * structure, @@ -2481,7 +2538,7 @@ gst_structure_fixate_field_nearest_int (GstStructure * structure, * Fixates a #GstStructure by changing the given field to the nearest * double to @target that is a subset of the existing field. * - * Returns: TRUE if the structure could be fixated + * Returns: %TRUE if the structure could be fixated */ gboolean gst_structure_fixate_field_nearest_double (GstStructure * structure, @@ -2546,7 +2603,7 @@ gst_structure_fixate_field_nearest_double (GstStructure * structure, * Fixates a #GstStructure by changing the given @field_name field to the given * @target boolean if that field is not fixed yet. * - * Returns: TRUE if the structure could be fixated + * Returns: %TRUE if the structure could be fixated */ gboolean gst_structure_fixate_field_boolean (GstStructure * structure, @@ -2599,7 +2656,7 @@ gst_structure_fixate_field_boolean (GstStructure * structure, * Fixates a #GstStructure by changing the given @field_name field to the given * @target string if that field is not fixed yet. * - * Returns: TRUE if the structure could be fixated + * Returns: %TRUE if the structure could be fixated */ gboolean gst_structure_fixate_field_string (GstStructure * structure, @@ -2654,7 +2711,7 @@ gst_structure_fixate_field_string (GstStructure * structure, * fraction to @target_numerator/@target_denominator that is a subset * of the existing field. * - * Returns: TRUE if the structure could be fixated + * Returns: %TRUE if the structure could be fixated */ gboolean gst_structure_fixate_field_nearest_fraction (GstStructure * structure, @@ -2756,7 +2813,7 @@ default_fixate (GQuark field_id, const GValue * value, gpointer data) * * Fixates a #GstStructure by changing the given field with its fixated value. * - * Returns: TRUE if the structure field could be fixated + * Returns: %TRUE if the structure field could be fixated */ gboolean gst_structure_fixate_field (GstStructure * structure, const char *field_name) @@ -2774,7 +2831,7 @@ gst_structure_fixate_field (GstStructure * structure, const char *field_name) /* our very own version of G_VALUE_LCOPY that allows NULL return locations * (useful for message parsing functions where the return location is user - * supplied and the user may pass NULL if the value isn't of interest) */ + * supplied and the user may pass %NULL if the value isn't of interest) */ #define GST_VALUE_LCOPY(value, var_args, flags, __error, fieldname) \ G_STMT_START { \ const GValue *_value = (value); \ @@ -2808,7 +2865,7 @@ G_STMT_START { \ * valist-variant of gst_structure_get(). Look at the documentation of * gst_structure_get() for more details. * - * Returns: TRUE, or FALSE if there was a problem reading any of the fields + * Returns: %TRUE, or %FALSE if there was a problem reading any of the fields */ gboolean gst_structure_get_valist (const GstStructure * structure, @@ -2875,7 +2932,7 @@ wrong_type: * valist-variant of gst_structure_id_get(). Look at the documentation of * gst_structure_id_get() for more details. * - * Returns: TRUE, or FALSE if there was a problem reading any of the fields + * Returns: %TRUE, or %FALSE if there was a problem reading any of the fields */ gboolean gst_structure_id_get_valist (const GstStructure * structure, @@ -2942,16 +2999,16 @@ wrong_type: * Parses the variable arguments and reads fields from @structure accordingly. * Variable arguments should be in the form field name, field type * (as a GType), pointer(s) to a variable(s) to hold the return value(s). - * The last variable argument should be NULL. + * The last variable argument should be %NULL. * * For refcounted (mini)objects you will receive a new reference which * you must release with a suitable _unref() when no longer needed. For * strings and boxed types you will receive a copy which you will need to * release with either g_free() or the suitable function for the boxed type. * - * Returns: FALSE if there was a problem reading any of the fields (e.g. + * Returns: %FALSE if there was a problem reading any of the fields (e.g. * because the field requested did not exist, or was of a type other - * than the type specified), otherwise TRUE. + * than the type specified), otherwise %TRUE. */ gboolean gst_structure_get (const GstStructure * structure, const char *first_fieldname, @@ -2979,9 +3036,9 @@ gst_structure_get (const GstStructure * structure, const char *first_fieldname, * Parses the variable arguments and reads fields from @structure accordingly. * Variable arguments should be in the form field id quark, field type * (as a GType), pointer(s) to a variable(s) to hold the return value(s). - * The last variable argument should be NULL (technically it should be a - * 0 quark, but we require NULL so compilers that support it can check for - * the NULL terminator and warn if it's not there). + * The last variable argument should be %NULL (technically it should be a + * 0 quark, but we require %NULL so compilers that support it can check for + * the %NULL terminator and warn if it's not there). * * This function is just like gst_structure_get() only that it is slightly * more efficient since it saves the string-to-quark lookup in the global @@ -2992,9 +3049,9 @@ gst_structure_get (const GstStructure * structure, const char *first_fieldname, * strings and boxed types you will receive a copy which you will need to * release with either g_free() or the suitable function for the boxed type. * - * Returns: FALSE if there was a problem reading any of the fields (e.g. + * Returns: %FALSE if there was a problem reading any of the fields (e.g. * because the field requested did not exist, or was of a type other - * than the type specified), otherwise TRUE. + * than the type specified), otherwise %TRUE. */ gboolean gst_structure_id_get (const GstStructure * structure, GQuark first_field_id, @@ -3036,7 +3093,7 @@ gst_structure_is_equal_foreach (GQuark field_id, const GValue * val2, * * Tests if the two #GstStructure are equal. * - * Returns: TRUE if the two structures have the same name and field. + * Returns: %TRUE if the two structures have the same name and field. **/ gboolean gst_structure_is_equal (const GstStructure * structure1, @@ -3104,7 +3161,7 @@ gst_structure_intersect_field2 (GQuark id, const GValue * val1, gpointer data) * @struct1: a #GstStructure * @struct2: a #GstStructure * - * Interesects @struct1 and @struct2 and returns the intersection. + * Intersects @struct1 and @struct2 and returns the intersection. * * Returns: Intersection of @struct1 and @struct2 */ diff --git a/gst/gststructure.h b/gst/gststructure.h index f7cc61b..6687970 100644 --- a/gst/gststructure.h +++ b/gst/gststructure.h @@ -47,8 +47,8 @@ typedef struct _GstStructure GstStructure; * A function that will be called in gst_structure_foreach(). The function may * not modify @value. * - * Returns: TRUE if the foreach operation should continue, FALSE if - * the foreach operation should stop with FALSE. + * Returns: %TRUE if the foreach operation should continue, %FALSE if + * the foreach operation should stop with %FALSE. */ typedef gboolean (*GstStructureForeachFunc) (GQuark field_id, const GValue * value, @@ -63,8 +63,8 @@ typedef gboolean (*GstStructureForeachFunc) (GQuark field_id, * A function that will be called in gst_structure_map_in_place(). The function * may modify @value. * - * Returns: TRUE if the map operation should continue, FALSE if - * the map operation should stop with FALSE. + * Returns: %TRUE if the map operation should continue, %FALSE if + * the map operation should stop with %FALSE. */ typedef gboolean (*GstStructureMapFunc) (GQuark field_id, GValue * value, @@ -230,6 +230,14 @@ gboolean gst_structure_get_uint (const GstStructure * const gchar * fieldname, guint * value); +gboolean gst_structure_get_int64 (const GstStructure * structure, + const gchar * fieldname, + gint64 * value); + +gboolean gst_structure_get_uint64 (const GstStructure * structure, + const gchar * fieldname, + guint64 * value); + gboolean gst_structure_get_double (const GstStructure * structure, const gchar * fieldname, gdouble * value); diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c index 5e7f6b1..01beee7 100644 --- a/gst/gstsystemclock.c +++ b/gst/gstsystemclock.c @@ -34,8 +34,6 @@ * Subclasses can however override all of the important methods for sync and * async notifications to implement their own callback methods or blocking * wait operations. - * - * Last reviewed on 2006-03-08 (0.10.4) */ #include "gst_private.h" @@ -112,6 +110,7 @@ enum /* the one instance of the systemclock */ static GstClock *_the_system_clock = NULL; +static gboolean _external_default_clock = FALSE; static void gst_system_clock_dispose (GObject * object); static void gst_system_clock_set_property (GObject * object, guint prop_id, @@ -281,6 +280,45 @@ gst_system_clock_get_property (GObject * object, guint prop_id, GValue * value, } /** + * gst_system_clock_set_default: + * @new_clock: a #GstClock + * + * Sets the default system clock that can be obtained with + * gst_system_clock_obtain. + * + * This is mostly used for testing and debugging purposes when you + * want to have control over the time reported by the default system + * clock. + * + * MT safe. + * + * Since: 1.4 + */ +void +gst_system_clock_set_default (GstClock * new_clock) +{ + GstClock *clock; + + g_mutex_lock (&_gst_sysclock_mutex); + clock = _the_system_clock; + + if (clock != NULL) + g_object_unref (clock); + + if (new_clock == NULL) { + GST_CAT_DEBUG (GST_CAT_CLOCK, "resetting default system clock"); + _external_default_clock = FALSE; + } else { + GST_CAT_DEBUG (GST_CAT_CLOCK, "setting new default system clock to %p", + new_clock); + _external_default_clock = TRUE; + g_object_ref (new_clock); + } + _the_system_clock = new_clock; + g_mutex_unlock (&_gst_sysclock_mutex); +} + +/** * gst_system_clock_obtain: * * Get a handle to the default system clock. The refcount of the @@ -301,6 +339,7 @@ gst_system_clock_obtain (void) if (clock == NULL) { GST_CAT_DEBUG (GST_CAT_CLOCK, "creating new static system clock"); + g_assert (_external_default_clock == FALSE); clock = g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", "GstSystemClock", NULL); diff --git a/gst/gstsystemclock.h b/gst/gstsystemclock.h index aa9dc14..fe5d009 100644 --- a/gst/gstsystemclock.h +++ b/gst/gstsystemclock.h @@ -81,6 +81,7 @@ struct _GstSystemClockClass { GType gst_system_clock_get_type (void); GstClock* gst_system_clock_obtain (void); +void gst_system_clock_set_default (GstClock *new_clock); G_END_DECLS diff --git a/gst/gsttaglist.c b/gst/gsttaglist.c index 5cff28d..c96cb56 100644 --- a/gst/gsttaglist.c +++ b/gst/gsttaglist.c @@ -25,9 +25,8 @@ * * List of tags and values used to describe media metadata. * - * Strings must be in ASCII or UTF-8 encoding. No other encodings are allowed. - * - * Last reviewed on 2009-06-09 (0.10.23) + * Strings in structures must be ASCII or UTF-8 encoded. Other encodings are + * not allowed. Strings must not be empty or %NULL. */ #ifdef HAVE_CONFIG_H @@ -85,6 +84,7 @@ static GMutex __tag_mutex; /* tags hash table: maps tag name string => GstTagInfo */ static GHashTable *__tags; +GType _gst_tag_list_type = 0; GST_DEFINE_MINI_OBJECT_TYPE (GstTagList, gst_tag_list); static void __gst_tag_list_free (GstTagList * list); @@ -99,6 +99,8 @@ _priv_gst_tag_initialize (void) { g_mutex_init (&__tag_mutex); + _gst_tag_list_type = gst_tag_list_get_type (); + __tags = g_hash_table_new (g_str_hash, g_str_equal); gst_tag_register_static (GST_TAG_TITLE, GST_TAG_FLAG_META, G_TYPE_STRING, @@ -396,6 +398,9 @@ _priv_gst_tag_initialize (void) _("interpreted-by"), _("Information about the people behind a remix and similar " "interpretations"), gst_tag_merge_strings_with_comma); + gst_tag_register_static (GST_TAG_MIDI_BASE_NOTE, GST_TAG_FLAG_META, + G_TYPE_UINT, + _("midi-base-note"), _("Midi note number of the audio track."), NULL); } /** @@ -463,7 +468,7 @@ gst_tag_lookup (const gchar * tag_name) * @type: the type this data is in * @nick: human-readable name * @blurb: a human-readable description about this tag - * @func: (allow-none): function for merging multiple values of this tag, or NULL + * @func: (allow-none): function for merging multiple values of this tag, or %NULL * * 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. @@ -472,7 +477,7 @@ gst_tag_lookup (const gchar * tag_name) * * Important: if you do not supply a merge function the implication will be * that there can only be one single value for this tag in a tag list and - * any additional values will silenty be discarded when being added (unless + * any additional values will silently be discarded when being added (unless * #GST_TAG_MERGE_REPLACE, #GST_TAG_MERGE_REPLACE_ALL, or * #GST_TAG_MERGE_PREPEND is used as merge mode, in which case the new * value will replace the old one in the list). @@ -507,7 +512,7 @@ gst_tag_register (const gchar * name, GstTagFlag flag, GType type, * @type: the type this data is in * @nick: human-readable name or short description (string constant) * @blurb: a human-readable description for this tag (string constant) - * @func: (allow-none): function for merging multiple values of this tag, or NULL + * @func: (allow-none): function for merging multiple values of this tag, or %NULL * * Registers a new tag type for the use with GStreamer's type system. * @@ -553,7 +558,7 @@ gst_tag_register_static (const gchar * name, GstTagFlag flag, GType type, * * Checks if the given type is already registered. * - * Returns: TRUE if the type is already registered + * Returns: %TRUE if the type is already registered */ gboolean gst_tag_exists (const gchar * tag) @@ -652,7 +657,7 @@ gst_tag_get_flag (const gchar * tag) * 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. + * Returns: %TRUE, if the given tag is fixed. */ gboolean gst_tag_is_fixed (const gchar * tag) @@ -738,10 +743,10 @@ gst_tag_list_new_empty (void) /** * gst_tag_list_new: * @tag: tag - * @...: NULL-terminated list of values to set + * @...: %NULL-terminated list of values to set * * Creates a new taglist and appends the values for the given tags. It expects - * tag-value pairs like gst_tag_list_add(), and a NULL terminator after the + * tag-value pairs like gst_tag_list_add(), and a %NULL terminator after the * last pair. The type of the values is implicit and is documented in the API * reference, but can also be queried at runtime with gst_tag_get_type(). It * is an error to pass a value of a type not matching the tag type into this @@ -839,7 +844,7 @@ gst_tag_list_get_scope (const GstTagList * list) * * Serializes a tag list to a string. * - * Returns: a newly-allocated string, or NULL in case of an error. The + * Returns: a newly-allocated string, or %NULL in case of an error. The * string must be freed with g_free() when no longer needed. */ gchar * @@ -856,7 +861,7 @@ gst_tag_list_to_string (const GstTagList * list) * * Deserializes a tag list. * - * Returns: a new #GstTagList, or NULL in case of an error. + * Returns: a new #GstTagList, or %NULL in case of an error. */ GstTagList * gst_tag_list_new_from_string (const gchar * str) @@ -917,7 +922,7 @@ gst_tag_list_nth_tag_name (const GstTagList * list, guint index) * * Checks if the given taglist is empty. * - * Returns: TRUE if the taglist is empty, otherwise FALSE. + * Returns: %TRUE if the taglist is empty, otherwise %FALSE. */ gboolean gst_tag_list_is_empty (const GstTagList * list) @@ -956,7 +961,7 @@ gst_tag_list_fields_equal (const GValue * value1, const GValue * value2) * * Checks if the two given taglists are equal. * - * Returns: TRUE if the taglists are equal, otherwise FALSE + * Returns: %TRUE if the taglists are equal, otherwise %FALSE */ gboolean gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2) @@ -1130,8 +1135,8 @@ gst_tag_list_insert (GstTagList * into, const GstTagList * from, * @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. + * 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. * * Free-function: gst_tag_list_unref * @@ -1195,7 +1200,7 @@ gst_tag_list_get_tag_size (const GstTagList * list, const gchar * tag) * @list: list to set tags in * @mode: the mode to use * @tag: tag - * @...: NULL-terminated list of values to set + * @...: %NULL-terminated list of values to set * * Sets the values for the given tags using the specified mode. */ @@ -1419,7 +1424,7 @@ gst_tag_list_foreach (const GstTagList * list, GstTagForeachFunc func, * Gets the value that is at the given index for the given tag in the given * list. * - * Returns: (transfer none): The GValue for the specified entry or NULL if the + * Returns: (transfer none): The GValue for the specified entry or %NULL if the * tag wasn't available or the tag doesn't have as many entries */ const GValue * @@ -1457,7 +1462,7 @@ gst_tag_list_get_value_index (const GstTagList * list, const gchar * tag, * 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 + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ gboolean @@ -1547,7 +1552,7 @@ gst_tag_list_get_ ## name ## _index (const GstTagList *list, \ * Copies the contents for the given tag into the value, merging multiple values * into one if multiple values are associated with the tag. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ /** @@ -1560,7 +1565,7 @@ gst_tag_list_get_ ## name ## _index (const GstTagList *list, \ * Gets the value that is at the given index for the given tag in the given * list. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ TAG_MERGE_FUNCS (boolean, gboolean, TRUE); @@ -1573,7 +1578,7 @@ TAG_MERGE_FUNCS (boolean, gboolean, TRUE); * Copies the contents for the given tag into the value, merging multiple values * into one if multiple values are associated with the tag. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ /** @@ -1586,7 +1591,7 @@ TAG_MERGE_FUNCS (boolean, gboolean, TRUE); * Gets the value that is at the given index for the given tag in the given * list. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ TAG_MERGE_FUNCS (int, gint, TRUE); @@ -1599,7 +1604,7 @@ TAG_MERGE_FUNCS (int, gint, TRUE); * Copies the contents for the given tag into the value, merging multiple values * into one if multiple values are associated with the tag. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ /** @@ -1612,7 +1617,7 @@ TAG_MERGE_FUNCS (int, gint, TRUE); * Gets the value that is at the given index for the given tag in the given * list. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ TAG_MERGE_FUNCS (uint, guint, TRUE); @@ -1626,7 +1631,7 @@ TAG_MERGE_FUNCS (uint, guint, TRUE); * Gets the value that is at the given index for the given tag in the given * list. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ TAG_MERGE_FUNCS (int64, gint64, TRUE); @@ -1639,7 +1644,7 @@ TAG_MERGE_FUNCS (int64, gint64, TRUE); * Copies the contents for the given tag into the value, merging multiple values * into one if multiple values are associated with the tag. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ /** @@ -1652,7 +1657,7 @@ TAG_MERGE_FUNCS (int64, gint64, TRUE); * Gets the value that is at the given index for the given tag in the given * list. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ TAG_MERGE_FUNCS (uint64, guint64, TRUE); @@ -1665,7 +1670,7 @@ TAG_MERGE_FUNCS (uint64, guint64, TRUE); * Copies the contents for the given tag into the value, merging multiple values * into one if multiple values are associated with the tag. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ /** @@ -1678,7 +1683,7 @@ TAG_MERGE_FUNCS (uint64, guint64, TRUE); * Gets the value that is at the given index for the given tag in the given * list. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ TAG_MERGE_FUNCS (float, gfloat, TRUE); @@ -1691,7 +1696,7 @@ TAG_MERGE_FUNCS (float, gfloat, TRUE); * Copies the contents for the given tag into the value, merging multiple values * into one if multiple values are associated with the tag. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ /** @@ -1704,7 +1709,7 @@ TAG_MERGE_FUNCS (float, gfloat, TRUE); * Gets the value that is at the given index for the given tag in the given * list. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ TAG_MERGE_FUNCS (double, gdouble, TRUE); @@ -1717,7 +1722,7 @@ TAG_MERGE_FUNCS (double, gdouble, TRUE); * Copies the contents for the given tag into the value, merging multiple values * into one if multiple values are associated with the tag. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ /** @@ -1730,7 +1735,7 @@ TAG_MERGE_FUNCS (double, gdouble, TRUE); * Gets the value that is at the given index for the given tag in the given * list. * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ TAG_MERGE_FUNCS (pointer, gpointer, (*value != NULL)); @@ -1761,11 +1766,11 @@ _gst_strdup0 (const gchar * s) * * The resulting string in @value will be in UTF-8 encoding and should be * freed by the caller using g_free when no longer needed. The - * returned string is also guaranteed to be non-NULL and non-empty. + * returned string is also guaranteed to be non-%NULL and non-empty. * * Free-function: g_free * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ /** @@ -1780,11 +1785,11 @@ _gst_strdup0 (const gchar * s) * * The resulting string in @value will be in UTF-8 encoding and should be * freed by the caller using g_free when no longer needed. The - * returned string is also guaranteed to be non-NULL and non-empty. + * returned string is also guaranteed to be non-%NULL and non-empty. * * Free-function: g_free * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the * given list. */ TAG_MERGE_FUNCS (string, gchar *, (*value != NULL)); @@ -1806,9 +1811,9 @@ TAG_MERGE_FUNCS (string, gchar *, (*value != NULL)); * * The resulting string in @value will be in UTF-8 encoding and doesn't need * to be freed by the caller. The returned string is also guaranteed to - * be non-NULL and non-empty. + * be non-%NULL and non-empty. * - * Returns: TRUE, if a value was set, FALSE if the tag didn't exist in the + * Returns: %TRUE, if a value was set, %FALSE if the tag didn't exist in the * given list. */ gboolean @@ -1840,8 +1845,8 @@ gst_tag_list_peek_string_index (const GstTagList * list, * * Free-function: g_date_free * - * Returns: TRUE, if a date was copied, FALSE if the tag didn't exist in the - * given list or if it was #NULL. + * Returns: %TRUE, if a date was copied, %FALSE if the tag didn't exist in the + * given list or if it was %NULL. */ gboolean gst_tag_list_get_date (const GstTagList * list, const gchar * tag, @@ -1873,8 +1878,8 @@ gst_tag_list_get_date (const GstTagList * list, const gchar * tag, * * Free-function: g_date_free * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the - * given list or if it was #NULL. + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list or if it was %NULL. */ gboolean gst_tag_list_get_date_index (const GstTagList * list, @@ -1905,8 +1910,8 @@ gst_tag_list_get_date_index (const GstTagList * list, * * Free-function: gst_date_time_unref * - * Returns: TRUE, if a datetime was copied, FALSE if the tag didn't exist in - * thegiven list or if it was #NULL. + * Returns: %TRUE, if a datetime was copied, %FALSE if the tag didn't exist in + * the given list or if it was %NULL. */ gboolean gst_tag_list_get_date_time (const GstTagList * list, const gchar * tag, @@ -1921,8 +1926,6 @@ gst_tag_list_get_date_time (const GstTagList * list, const gchar * tag, if (!gst_tag_list_copy_value (&v, list, tag)) return FALSE; - g_return_val_if_fail (GST_VALUE_HOLDS_DATE_TIME (&v), FALSE); - *value = (GstDateTime *) g_value_dup_boxed (&v); g_value_unset (&v); return (*value != NULL); @@ -1941,8 +1944,8 @@ gst_tag_list_get_date_time (const GstTagList * list, const gchar * tag, * * Free-function: gst_date_time_unref * - * Returns: TRUE, if a value was copied, FALSE if the tag didn't exist in the - * given list or if it was #NULL. + * Returns: %TRUE, if a value was copied, %FALSE if the tag didn't exist in the + * given list or if it was %NULL. */ gboolean gst_tag_list_get_date_time_index (const GstTagList * list, @@ -1975,8 +1978,8 @@ gst_tag_list_get_date_time_index (const GstTagList * list, * * Free-function: gst_sample_unref * - * Returns: TRUE, if a sample was returned, FALSE if the tag didn't exist in - * the given list or if it was #NULL. + * Returns: %TRUE, if a sample was returned, %FALSE if the tag didn't exist in + * the given list or if it was %NULL. */ gboolean gst_tag_list_get_sample (const GstTagList * list, const gchar * tag, @@ -2004,15 +2007,15 @@ gst_tag_list_get_sample (const GstTagList * list, const gchar * tag, * pointer variable to store the result into * * Gets the sample that is at the given index for the given tag in the given - * list and copies it into the variable pointed to by @smple. Free the sample + * list and copies it into the variable pointed to by @sample. Free the sample * with gst_sample_unref() when it is no longer needed. You can retrieve the * buffer from the sample using gst_sample_get_buffer() and the associated * caps (if any) with gst_sample_get_caps(). * * Free-function: gst_sample_unref * - * Returns: TRUE, if a sample was copied, FALSE if the tag didn't exist in the - * given list or if it was #NULL. + * Returns: %TRUE, if a sample was copied, %FALSE if the tag didn't exist in the + * given list or if it was %NULL. */ gboolean gst_tag_list_get_sample_index (const GstTagList * list, diff --git a/gst/gsttaglist.h b/gst/gsttaglist.h index b5e683e..42f944b 100644 --- a/gst/gsttaglist.h +++ b/gst/gsttaglist.h @@ -154,8 +154,10 @@ struct _GstTagList { GstMiniObject mini_object; }; +GST_EXPORT GType _gst_tag_list_type; + #define GST_TAG_LIST(x) ((GstTagList *) (x)) -#define GST_TYPE_TAG_LIST (gst_tag_list_get_type ()) +#define GST_TYPE_TAG_LIST (_gst_tag_list_type) #define GST_IS_TAG_LIST(obj) (GST_IS_MINI_OBJECT_TYPE((obj), GST_TYPE_TAG_LIST)) /** @@ -1060,6 +1062,16 @@ gst_tag_list_copy (const GstTagList * taglist) * Since: 1.2 */ #define GST_TAG_INTERPRETED_BY "interpreted-by" +/** + * GST_TAG_MIDI_BASE_NOTE: + * + * <ulink url="http://en.wikipedia.org/wiki/Note#Note_designation_in_accordance_with_octave_name">Midi note number</ulink> + * of the audio track. This is useful for sample instruments and in particular + * for multi-samples. + * + * Since: 1.4 + */ +#define GST_TAG_MIDI_BASE_NOTE "midi-base-note" G_END_DECLS diff --git a/gst/gsttagsetter.c b/gst/gsttagsetter.c index cd402cb..b2955d6 100644 --- a/gst/gsttagsetter.c +++ b/gst/gsttagsetter.c @@ -64,8 +64,6 @@ * * GST_LOG_OBJECT (tagsetter, "final tags: %" GST_PTR_FORMAT, result); * ]| - * - * Last reviewed on 2006-05-18 (0.10.6) */ #ifdef HAVE_CONFIG_H @@ -202,7 +200,7 @@ gst_tag_setter_merge_tags (GstTagSetter * setter, const GstTagList * list, * @...: 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 NULL. + * The list must be terminated with %NULL. */ void gst_tag_setter_add_tags (GstTagSetter * setter, GstTagMergeMode mode, @@ -226,7 +224,7 @@ gst_tag_setter_add_tags (GstTagSetter * setter, GstTagMergeMode mode, * @...: more tag / GValue pairs to set * * Adds the given tag / GValue pairs on the setter using the given merge mode. - * The list must be terminated with NULL. + * The list must be terminated with %NULL. */ void gst_tag_setter_add_tag_values (GstTagSetter * setter, GstTagMergeMode mode, @@ -250,7 +248,7 @@ gst_tag_setter_add_tag_values (GstTagSetter * setter, GstTagMergeMode mode, * @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 NULL. + * The list must be terminated with %NULL. */ void gst_tag_setter_add_tag_valist (GstTagSetter * setter, GstTagMergeMode mode, @@ -280,7 +278,7 @@ gst_tag_setter_add_tag_valist (GstTagSetter * setter, GstTagMergeMode mode, * @var_args: tag / GValue pairs to set * * Adds the given tag / GValue pairs on the setter using the given merge mode. - * The list must be terminated with NULL. + * The list must be terminated with %NULL. */ void gst_tag_setter_add_tag_valist_values (GstTagSetter * setter, @@ -343,7 +341,7 @@ gst_tag_setter_add_tag_value (GstTagSetter * setter, * This function is not thread-safe. * * Returns: (transfer none): a current snapshot of the taglist used in the - * setter or NULL if none is used. + * setter or %NULL if none is used. */ const GstTagList * gst_tag_setter_get_tag_list (GstTagSetter * setter) diff --git a/gst/gsttask.c b/gst/gsttask.c index 993eb70..b562f6c 100644 --- a/gst/gsttask.c +++ b/gst/gsttask.c @@ -64,8 +64,6 @@ * name on Linux. Please note that the object name should be configured before the * task is started; changing the object name after the task has been started, has * no effect on the thread name. - * - * Last reviewed on 2012-03-29 (0.11.3) */ #include "gst_private.h" @@ -197,6 +195,9 @@ gst_task_init (GstTask * task) g_mutex_lock (&pool_lock); task->priv->pool = gst_object_ref (klass->pool); g_mutex_unlock (&pool_lock); + + /* clear floating flag */ + gst_object_ref_sink (task); } static void @@ -330,7 +331,7 @@ exit: GST_OBJECT_LOCK (task); } /* now we allow messing with the lock again by setting the running flag to - * FALSE. Together with the SIGNAL this is the sign for the _join() to + * %FALSE. Together with the SIGNAL this is the sign for the _join() to * complete. * Note that we still have not dropped the final ref on the task. We could * check here if there is a pending join() going on and drop the last ref diff --git a/gst/gsttaskpool.c b/gst/gsttaskpool.c index e08f2a3..d7ff344 100644 --- a/gst/gsttaskpool.c +++ b/gst/gsttaskpool.c @@ -28,8 +28,6 @@ * implementation uses a regular GThreadPool to start tasks. * * Subclasses can be made to create custom threads. - * - * Last reviewed on 2009-04-23 (0.10.24) */ #include "gst_private.h" @@ -141,6 +139,8 @@ gst_task_pool_class_init (GstTaskPoolClass * klass) static void gst_task_pool_init (GstTaskPool * pool) { + /* clear floating flag */ + gst_object_ref_sink (pool); } #ifndef GST_DISABLE_GST_DEBUG @@ -224,7 +224,7 @@ gst_task_pool_cleanup (GstTaskPool * pool) * Start the execution of a new thread from @pool. * * Returns: (transfer none): a pointer that should be used for the - * gst_task_pool_join function. This pointer can be NULL, you must + * gst_task_pool_join function. This pointer can be %NULL, you must * check @error to detect errors. */ gpointer diff --git a/gst/gsttoc.c b/gst/gsttoc.c index 6da7ad8..bee13cb 100644 --- a/gst/gsttoc.c +++ b/gst/gsttoc.c @@ -96,6 +96,8 @@ struct _GstTocEntry GstClockTime start, stop; GList *subentries; GstTagList *tags; + GstTocLoopType loop_type; + gint repeat_count; }; struct _GstToc @@ -114,6 +116,9 @@ static void gst_toc_free (GstToc * toc); static GstTocEntry *gst_toc_entry_copy (const GstTocEntry * toc); static void gst_toc_entry_free (GstTocEntry * toc); +GType _gst_toc_type = 0; +GType _gst_toc_entry_type = 0; + GST_DEFINE_MINI_OBJECT_TYPE (GstToc, gst_toc); GST_DEFINE_MINI_OBJECT_TYPE (GstTocEntry, gst_toc_entry); @@ -355,7 +360,7 @@ gst_toc_entry_find_sub_entry (const GstTocEntry * entry, const gchar * uid) * * Find #GstTocEntry with given @uid in the @toc. * - * Returns: (transfer none): #GstTocEntry with specified @uid from the @toc, or NULL if not found. + * Returns: (transfer none): #GstTocEntry with specified @uid from the @toc, or %NULL if not found. */ GstTocEntry * gst_toc_find_entry (const GstToc * toc, const gchar * uid) @@ -388,7 +393,7 @@ gst_toc_find_entry (const GstToc * toc, const gchar * uid) * * Copy #GstTocEntry with all subentries (deep copy). * - * Returns: newly allocated #GstTocEntry in case of success, NULL otherwise; + * Returns: newly allocated #GstTocEntry in case of success, %NULL otherwise; * free it when done with gst_toc_entry_unref(). */ static GstTocEntry * @@ -432,7 +437,7 @@ gst_toc_entry_copy (const GstTocEntry * entry) * * Copy #GstToc with all subentries (deep copy). * - * Returns: newly allocated #GstToc in case of success, NULL otherwise; + * Returns: newly allocated #GstToc in case of success, %NULL otherwise; * free it when done with gst_toc_unref(). */ static GstToc * @@ -487,20 +492,19 @@ gst_toc_entry_set_start_stop_times (GstTocEntry * entry, gint64 start, /** * gst_toc_entry_get_start_stop_times: * @entry: #GstTocEntry to get values from. - * @start: (out): the storage for the start value, leave #NULL if not need. - * @stop: (out): the storage for the stop value, leave #NULL if not need. + * @start: (out): the storage for the start value, leave %NULL if not need. + * @stop: (out): the storage for the stop value, leave %NULL if not need. * - * Get start and stop values from the @entry and write them into appropriate storages. + * Get @start and @stop values from the @entry and write them into appropriate + * storages. * - * Returns: TRUE if all non-NULL storage pointers were filled with appropriate values, - * FALSE otherwise. + * Returns: %TRUE if all non-%NULL storage pointers were filled with appropriate + * values, %FALSE otherwise. */ gboolean gst_toc_entry_get_start_stop_times (const GstTocEntry * entry, gint64 * start, gint64 * stop) { - gboolean ret = TRUE; - g_return_val_if_fail (entry != NULL, FALSE); if (start != NULL) @@ -508,9 +512,62 @@ gst_toc_entry_get_start_stop_times (const GstTocEntry * entry, gint64 * start, if (stop != NULL) *stop = entry->stop; - return ret; + return TRUE; +} + +/** + * gst_toc_entry_set_loop: + * @entry: #GstTocEntry to set values. + * @loop_type: loop_type value to set. + * @repeat_count: repeat_count value to set. + * + * Set @loop_type and @repeat_count values for the @entry. + * + * Since: 1.4 + */ +void +gst_toc_entry_set_loop (GstTocEntry * entry, GstTocLoopType loop_type, + gint repeat_count) +{ + g_return_if_fail (entry != NULL); + + entry->loop_type = loop_type; + entry->repeat_count = repeat_count; +} + +/** + * gst_toc_entry_get_loop: + * @entry: #GstTocEntry to get values from. + * @loop_type: (out): the storage for the loop_type value, leave %NULL if not + * need. + * @repeat_count: (out): the storage for the repeat_count value, leave %NULL if + * not need. + * + * Get @loop_type and @repeat_count values from the @entry and write them into + * appropriate storages. Loops are e.g. used by sampled instruments. GStreamer + * is not automatically applying the loop. The application can process this + * meta data and use it e.g. to send a seek-event to loop a section. + * + * Returns: %TRUE if all non-%NULL storage pointers were filled with appropriate + * values, %FALSE otherwise. + * + * Since: 1.4 + */ +gboolean +gst_toc_entry_get_loop (const GstTocEntry * entry, GstTocLoopType * loop_type, + gint * repeat_count) +{ + g_return_val_if_fail (entry != NULL, FALSE); + + if (loop_type != NULL) + *loop_type = entry->loop_type; + if (repeat_count != NULL) + *repeat_count = entry->repeat_count; + + return TRUE; } + /** * gst_toc_entry_type_get_nick: * @type: a #GstTocEntryType. @@ -766,3 +823,10 @@ gst_toc_dump (GstToc * toc) gst_toc_dump_entries (toc->entries, 2); #endif } + +void +_priv_gst_toc_initialize (void) +{ + _gst_toc_type = gst_toc_get_type (); + _gst_toc_entry_type = gst_toc_entry_get_type (); +} diff --git a/gst/gsttoc.h b/gst/gsttoc.h index 632435a..39469c1 100644 --- a/gst/gsttoc.h +++ b/gst/gsttoc.h @@ -30,8 +30,11 @@ G_BEGIN_DECLS -#define GST_TYPE_TOC (gst_toc_get_type ()) -#define GST_TYPE_TOC_ENTRY (gst_toc_entry_get_type ()) +GST_EXPORT GType _gst_toc_type; +GST_EXPORT GType _gst_toc_entry_type; + +#define GST_TYPE_TOC (_gst_toc_type) +#define GST_TYPE_TOC_ENTRY (_gst_toc_entry_type) typedef struct _GstTocEntry GstTocEntry; typedef struct _GstToc GstToc; @@ -81,6 +84,35 @@ typedef enum { #define GST_TOC_ENTRY_TYPE_IS_ALTERNATIVE(entry_type) (entry_type < 0) #define GST_TOC_ENTRY_TYPE_IS_SEQUENCE(entry_type) (entry_type > 0) +/** + * GstTocLoopType: + * @GST_TOC_LOOP_NONE: single forward playback + * @GST_TOC_LOOP_FORWARD: repeat forward + * @GST_TOC_LOOP_REVERSE: repeat backward + * @GST_TOC_LOOP_PING_PONG: repeat forward and backward + * + * How a #GstTocEntry should be repeated. By default, entries are played a + * single time. + * + * Since: 1.4 + */ +typedef enum { + GST_TOC_LOOP_NONE = 0, + GST_TOC_LOOP_FORWARD, + GST_TOC_LOOP_REVERSE, + GST_TOC_LOOP_PING_PONG +} GstTocLoopType; + +/** + * GST_TOC_REPEAT_COUNT_INFINITE: + * + * Special value for the repeat_count set in gst_toc_entry_set_loop() or + * returned by gst_toc_entry_set_loop() to indicate infinite looping. + * + * Since: 1.4 + */ +#define GST_TOC_REPEAT_COUNT_INFINITE (-1) + /* functions to return type structures */ GType gst_toc_get_type (void); GType gst_toc_entry_get_type (void); @@ -130,6 +162,9 @@ gboolean gst_toc_entry_is_sequence (const GstTocEntry *ent void gst_toc_entry_set_start_stop_times (GstTocEntry *entry, gint64 start, gint64 stop); gboolean gst_toc_entry_get_start_stop_times (const GstTocEntry *entry, gint64 *start, gint64 *stop); +void gst_toc_entry_set_loop (GstTocEntry *entry, GstTocLoopType loop_type, gint repeat_count); +gboolean gst_toc_entry_get_loop (const GstTocEntry *entry, GstTocLoopType *loop_type, gint *repeat_count); + GstToc * gst_toc_entry_get_toc (GstTocEntry *entry); GstTocEntry * gst_toc_entry_get_parent (GstTocEntry *entry); diff --git a/gst/gsttocsetter.c b/gst/gsttocsetter.c index 182a98c..42839d2 100644 --- a/gst/gsttocsetter.c +++ b/gst/gsttocsetter.c @@ -128,7 +128,7 @@ gst_toc_setter_reset (GstTocSetter * setter) * modified without making it writable first. * * - * Returns: (transfer full): TOC set, or NULL. Unref with gst_toc_unref() + * Returns: (transfer full): TOC set, or %NULL. Unref with gst_toc_unref() * when no longer needed */ GstToc * @@ -155,8 +155,8 @@ gst_toc_setter_get_toc (GstTocSetter * setter) * @setter: a #GstTocSetter. * @toc: (allow-none): a #GstToc to set. * - * Set the given TOC on the setter. Previously setted TOC will be - * unrefed before setting a new one. + * Set the given TOC on the setter. Previously set TOC will be + * unreffed before setting a new one. */ void gst_toc_setter_set_toc (GstTocSetter * setter, GstToc * toc) diff --git a/gst/gsttypefind.c b/gst/gsttypefind.c index c414810..1fcbea1 100644 --- a/gst/gsttypefind.c +++ b/gst/gsttypefind.c @@ -25,8 +25,6 @@ * * The following functions allow you to detect the media type of an unknown * stream. - * - * Last reviewed on 2005-11-09 (0.9.4) */ #include "gst_private.h" @@ -42,7 +40,7 @@ G_DEFINE_POINTER_TYPE (GstTypeFind, gst_type_find); /** * gst_type_find_register: - * @plugin: (allow-none): A #GstPlugin, or NULL for a static typefind function + * @plugin: (allow-none): A #GstPlugin, or %NULL for a static typefind function * @name: The name for registering * @rank: The rank (or importance) of this typefind function * @func: The #GstTypeFindFunction to use @@ -59,7 +57,7 @@ G_DEFINE_POINTER_TYPE (GstTypeFind, gst_type_find); * registering this function will be available for typefinding. * This function is typically called during an element's plugin initialization. * - * Returns: TRUE on success, FALSE otherwise + * Returns: %TRUE on success, %FALSE otherwise */ gboolean gst_type_find_register (GstPlugin * plugin, const gchar * name, guint rank, @@ -121,7 +119,7 @@ gst_type_find_register (GstPlugin * plugin, const gchar * name, guint rank, * the stream. The returned memory is valid until the typefinding function * returns and must not be freed. * - * Returns: (transfer none) (array length=size): the requested data, or NULL + * Returns: (transfer none) (array length=size): the requested data, or %NULL * if that data is not available. */ const guint8 * @@ -159,7 +157,7 @@ gst_type_find_suggest (GstTypeFind * find, guint probability, GstCaps * caps) * @find: The #GstTypeFind object the function was called with * @probability: The probability in percent that the suggestion is right * @media_type: the media type of the suggested caps - * @fieldname: (allow-none): first field of the suggested caps, or NULL + * @fieldname: (allow-none): first field of the suggested caps, or %NULL * @...: additional arguments to the suggested caps in the same format as the * arguments passed to gst_structure_new() (ie. triplets of field name, * field GType and field value) @@ -173,7 +171,7 @@ gst_type_find_suggest (GstTypeFind * find, guint probability, GstCaps * caps) * passing a #GstCaps argument you can create the caps on the fly in the same * way as you can with gst_caps_new_simple(). * - * Make sure you terminate the list of arguments with a NULL argument and that + * Make sure you terminate the list of arguments with a %NULL argument and that * the values passed have the correct type (in terms of width in bytes when * passed to the vararg function - this applies particularly to gdouble and * guint64 arguments). diff --git a/gst/gsttypefind.h b/gst/gsttypefind.h index f596f30..4431b1c 100644 --- a/gst/gsttypefind.h +++ b/gst/gsttypefind.h @@ -36,7 +36,7 @@ typedef struct _GstTypeFind GstTypeFind; /** * GstTypeFindFunction: * @find: A #GstTypeFind structure - * @user_data: optionnal data to pass to the function + * @user_data: optional data to pass to the function * * A function that will be called by typefinding. */ diff --git a/gst/gsttypefindfactory.c b/gst/gsttypefindfactory.c index 92eb52b..c216eb3 100644 --- a/gst/gsttypefindfactory.c +++ b/gst/gsttypefindfactory.c @@ -28,9 +28,10 @@ * the section <link linkend="gstreamer-Writing-typefind-functions"> * "Writing typefind functions"</link>. * - * <example> - * <title>how to write a simple typefinder</title> - * <programlisting> + * The following example shows how to write a very simple typefinder that + * identifies the given data. You can get quite a bit more complicated than + * that though. + * |[ * typedef struct { * guint8 *data; * guint size; @@ -70,14 +71,7 @@ * g_list_free (type_list); * return find.caps; * }; - * </programlisting> - * </example> - * - * The above example shows how to write a very simple typefinder that - * identifies the given data. You can get quite a bit more complicated than - * that though. - * - * Last reviewed on 2005-11-09 (0.9.4) + * ]| */ #include "gst_private.h" @@ -180,11 +174,11 @@ gst_type_find_factory_get_caps (GstTypeFindFactory * factory) * * Gets the extensions associated with a #GstTypeFindFactory. The returned * array should not be changed. If you need to change stuff in it, you should - * copy it using g_strdupv(). This function may return NULL to indicate + * copy it using g_strdupv(). This function may return %NULL to indicate * a 0-length list. * * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): a - * NULL-terminated array of extensions associated with this factory + * %NULL-terminated array of extensions associated with this factory */ const gchar *const * gst_type_find_factory_get_extensions (GstTypeFindFactory * factory) @@ -231,7 +225,7 @@ gst_type_find_factory_call_function (GstTypeFindFactory * factory, * without typefind functions are a last-effort fallback mechanism to * e.g. assume a certain media type based on the file extension. * - * Returns: TRUE if the factory has a typefind functions set, otherwise FALSE + * Returns: %TRUE if the factory has a typefind functions set, otherwise %FALSE */ gboolean gst_type_find_factory_has_function (GstTypeFindFactory * factory) diff --git a/gst/gsturi.c b/gst/gsturi.c index 234a27d..00a496f 100644 --- a/gst/gsturi.c +++ b/gst/gsturi.c @@ -33,8 +33,6 @@ * (gst_element_make_from_uri()). * * Source and Sink plugins should implement this interface when possible. - * - * Last reviewed on 2005-11-09 (0.9.4) */ #ifdef HAVE_CONFIG_H @@ -303,7 +301,7 @@ gst_uri_protocol_check_internal (const gchar * uri, gchar ** endptr) * must consist of alphanumeric characters, '+', '-' and '.' and must * start with a alphabetic character. See RFC 3986 Section 3.1. * - * Returns: TRUE if the string is a valid protocol identifier, FALSE otherwise. + * Returns: %TRUE if the string is a valid protocol identifier, %FALSE otherwise. */ gboolean gst_uri_protocol_is_valid (const gchar * protocol) @@ -324,7 +322,7 @@ gst_uri_protocol_is_valid (const gchar * protocol) * Tests if the given string is a valid URI identifier. URIs start with a valid * scheme followed by ":" and maybe a string identifying the location. * - * Returns: TRUE if the string is a valid URI + * Returns: %TRUE if the string is a valid URI */ gboolean gst_uri_is_valid (const gchar * uri) @@ -397,7 +395,7 @@ gst_uri_has_protocol (const gchar * uri, const gchar * protocol) * * Free-function: g_free * - * Returns: (transfer full): the location for this URI. Returns NULL if the + * Returns: (transfer full): the location for this URI. Returns %NULL if the * URI isn't valid. If the URI does not contain a location, an empty * string is returned. */ @@ -426,7 +424,7 @@ gst_uri_get_location (const gchar * uri) g_ascii_isalpha (unescaped[1]) && (unescaped[2] == ':' || unescaped[2] == '|')) { unescaped[2] = ':'; - g_memmove (unescaped, unescaped + 1, strlen (unescaped + 1) + 1); + memmove (unescaped, unescaped + 1, strlen (unescaped + 1) + 1); } #endif @@ -444,8 +442,8 @@ gst_uri_get_location (const gchar * uri) * * Free-function: g_free * - * Returns: (transfer full): a new string for this URI. Returns NULL if the - * given URI protocol is not valid, or the given location is NULL. + * Returns: (transfer full): a new string for this URI. Returns %NULL if the + * given URI protocol is not valid, or the given location is %NULL. */ gchar * gst_uri_construct (const gchar * protocol, const gchar * location) @@ -535,7 +533,7 @@ get_element_factories_from_uri_protocol (const GstURIType type, * that a positive return value does not imply that a subsequent call to * gst_element_make_from_uri() is guaranteed to work. * - * Returns: TRUE + * Returns: %TRUE */ gboolean gst_uri_protocol_is_supported (const GstURIType type, const gchar * protocol) @@ -557,12 +555,12 @@ gst_uri_protocol_is_supported (const GstURIType type, const gchar * protocol) * gst_element_make_from_uri: * @type: Whether to create a source or a sink * @uri: URI to create an element for - * @elementname: (allow-none): Name of created element, can be NULL. - * @error: (allow-none): address where to store error information, or NULL. + * @elementname: (allow-none): Name of created element, can be %NULL. + * @error: (allow-none): address where to store error information, or %NULL. * * Creates an element for handling the given URI. * - * Returns: (transfer floating): a new element or NULL if none could be created + * Returns: (transfer floating): a new element or %NULL if none could be created */ GstElement * gst_element_make_from_uri (const GstURIType type, const gchar * uri, @@ -667,7 +665,7 @@ gst_uri_handler_get_uri_type (GstURIHandler * handler) * modified. * * Returns: (transfer none) (element-type utf8): the supported protocols. - * Returns NULL if the @handler isn't implemented properly, or the @handler + * Returns %NULL if the @handler isn't implemented properly, or the @handler * doesn't support any protocols. */ const gchar *const * @@ -695,7 +693,7 @@ gst_uri_handler_get_protocols (GstURIHandler * handler) * Gets the currently handled URI. * * Returns: (transfer full): the URI currently handled by the @handler. - * Returns NULL if there are no URI currently handled. The + * Returns %NULL if there are no URI currently handled. The * returned string must be freed with g_free() when no longer needed. */ gchar * @@ -721,11 +719,11 @@ gst_uri_handler_get_uri (GstURIHandler * handler) * @handler: A #GstURIHandler * @uri: URI to set * @error: (allow-none): address where to store a #GError in case of - * an error, or NULL + * an error, or %NULL * * Tries to set the URI of the given handler. * - * Returns: TRUE if the URI was set successfully, else FALSE. + * Returns: %TRUE if the URI was set successfully, else %FALSE. */ gboolean gst_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri, @@ -801,7 +799,7 @@ gst_file_utils_canonicalise_path (const gchar * path) if (strcmp (*p, ".") == 0) { /* just move all following parts on top of this, incl. NUL terminator */ g_free (*p); - g_memmove (p, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *)); + memmove (p, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *)); /* re-check the new current part again in the next iteration */ continue; } else if (strcmp (*p, "..") == 0 && p > parts) { @@ -809,7 +807,7 @@ gst_file_utils_canonicalise_path (const gchar * path) * NUL terminator */ g_free (*(p - 1)); g_free (*p); - g_memmove (p - 1, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *)); + memmove (p - 1, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *)); /* re-check the new current part again in the next iteration */ --p; continue; @@ -821,7 +819,7 @@ gst_file_utils_canonicalise_path (const gchar * path) num_parts = g_strv_length (parts) + 1; /* incl. terminator */ parts = g_renew (gchar *, parts, num_parts + 1); - g_memmove (parts + 1, parts, num_parts * sizeof (gchar *)); + memmove (parts + 1, parts, num_parts * sizeof (gchar *)); parts[0] = g_strdup ("/"); } @@ -841,7 +839,7 @@ file_path_contains_relatives (const gchar * path) /** * gst_filename_to_uri: * @filename: absolute or relative file name path - * @error: pointer to error, or NULL + * @error: pointer to error, or %NULL * * Similar to g_filename_to_uri(), but attempts to handle relative file paths * as well. Before converting @filename into an URI, it will be prefixed by diff --git a/gst/gstutils.c b/gst/gstutils.c index 24aa66a..c411631 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -117,7 +117,7 @@ gst_util_set_value_from_string (GValue * value, const gchar * value_str) * @name: the name of the argument to set * @value: the string value to set * - * Convertes the string value to the type of the objects argument and + * Converts the string value to the type of the objects argument and * sets the argument with it. * * Note that this function silently returns if @object has no property named @@ -150,7 +150,7 @@ gst_util_set_object_arg (GObject * object, const gchar * name, g_value_init (&v, value_type); /* special case for element <-> xml (de)serialisation */ - if (GST_VALUE_HOLDS_STRUCTURE (&v) && strcmp (value, "NULL") == 0) { + if (value_type == GST_TYPE_STRUCTURE && strcmp (value, "NULL") == 0) { g_value_set_boxed (&v, NULL); goto done; } @@ -773,7 +773,7 @@ gst_element_create_all_pads (GstElement * element) * Retrieves a pad template from @element that is compatible with @compattempl. * Pads from compatible templates can be linked together. * - * Returns: (transfer none): a compatible #GstPadTemplate, or NULL if none + * Returns: (transfer none): a compatible #GstPadTemplate, or %NULL if none * was found. No unreferencing is necessary. */ GstPadTemplate * @@ -1505,10 +1505,10 @@ pad_link_maybe_ghosting (GstPad * src, GstPad * sink, GstPadLinkCheck flags) * gst_element_link_pads_full: * @src: a #GstElement containing the source pad. * @srcpadname: (allow-none): the name of the #GstPad in source element - * or NULL for any pad. + * or %NULL for any pad. * @dest: (transfer none): the #GstElement containing the destination pad. * @destpadname: (allow-none): the name of the #GstPad in destination element, - * or NULL for any pad. + * or %NULL for any pad. * @flags: the #GstPadLinkCheck to be performed when linking pads. * * Links the two named pads of the source and destination elements. @@ -1522,7 +1522,7 @@ pad_link_maybe_ghosting (GstPad * src, GstPad * sink, GstPadLinkCheck flags) * * This is a convenience function for gst_pad_link_full(). * - * Returns: TRUE if the pads could be linked, FALSE otherwise. + * Returns: %TRUE if the pads could be linked, %FALSE otherwise. */ gboolean gst_element_link_pads_full (GstElement * src, const gchar * srcpadname, @@ -1784,17 +1784,17 @@ gst_element_link_pads_full (GstElement * src, const gchar * srcpadname, * gst_element_link_pads: * @src: a #GstElement containing the source pad. * @srcpadname: (allow-none): the name of the #GstPad in source element - * or NULL for any pad. + * or %NULL for any pad. * @dest: (transfer none): the #GstElement containing the destination pad. * @destpadname: (allow-none): the name of the #GstPad in destination element, - * or NULL for any pad. + * or %NULL for any pad. * * Links the two named pads of the source and destination elements. * Side effect is that if one of the pads has no parent, it becomes a * child of the parent of the other element. If they have different * parents, the link fails. * - * Returns: TRUE if the pads could be linked, FALSE otherwise. + * Returns: %TRUE if the pads could be linked, %FALSE otherwise. */ gboolean gst_element_link_pads (GstElement * src, const gchar * srcpadname, @@ -1808,19 +1808,19 @@ gst_element_link_pads (GstElement * src, const gchar * srcpadname, * gst_element_link_pads_filtered: * @src: a #GstElement containing the source pad. * @srcpadname: (allow-none): the name of the #GstPad in source element - * or NULL for any pad. + * or %NULL for any pad. * @dest: (transfer none): the #GstElement containing the destination pad. * @destpadname: (allow-none): the name of the #GstPad in destination element - * or NULL for any pad. + * or %NULL for any pad. * @filter: (transfer none) (allow-none): the #GstCaps to filter the link, - * or #NULL for no filter. + * or %NULL for no filter. * * Links the two named pads of the source and destination elements. Side effect * is that if one of the pads has no parent, it becomes a child of the parent of * the other element. If they have different parents, the link fails. If @caps - * is not #NULL, makes sure that the caps of the link is a subset of @caps. + * is not %NULL, makes sure that the caps of the link is a subset of @caps. * - * Returns: TRUE if the pads could be linked, FALSE otherwise. + * Returns: %TRUE if the pads could be linked, %FALSE otherwise. */ gboolean gst_element_link_pads_filtered (GstElement * src, const gchar * srcpadname, @@ -1906,7 +1906,7 @@ gst_element_link_pads_filtered (GstElement * src, const gchar * srcpadname, * Make sure you have added your elements to a bin or pipeline with * gst_bin_add() before trying to link them. * - * Returns: TRUE if the elements could be linked, FALSE otherwise. + * Returns: %TRUE if the elements could be linked, %FALSE otherwise. */ gboolean gst_element_link (GstElement * src, GstElement * dest) @@ -1918,13 +1918,13 @@ gst_element_link (GstElement * src, GstElement * dest) * gst_element_link_many: * @element_1: (transfer none): the first #GstElement in the link chain. * @element_2: (transfer none): the second #GstElement in the link chain. - * @...: the NULL-terminated list of elements to link in order. + * @...: the %NULL-terminated list of elements to link in order. * * Chain together a series of elements. Uses gst_element_link(). * Make sure you have added your elements to a bin or pipeline with * gst_bin_add() before trying to link them. * - * Returns: TRUE on success, FALSE otherwise. + * Returns: %TRUE on success, %FALSE otherwise. */ gboolean gst_element_link_many (GstElement * element_1, GstElement * element_2, ...) @@ -1957,7 +1957,7 @@ gst_element_link_many (GstElement * element_1, GstElement * element_2, ...) * @src: a #GstElement containing the source pad. * @dest: (transfer none): the #GstElement containing the destination pad. * @filter: (transfer none) (allow-none): the #GstCaps to filter the link, - * or #NULL for no filter. + * or %NULL for no filter. * * Links @src to @dest using the given caps as filtercaps. * The link must be from source to @@ -1968,7 +1968,7 @@ gst_element_link_many (GstElement * element_1, GstElement * element_2, ...) * Make sure you have added your elements to a bin or pipeline with * gst_bin_add() before trying to link them. * - * Returns: TRUE if the pads could be linked, FALSE otherwise. + * Returns: %TRUE if the pads could be linked, %FALSE otherwise. */ gboolean gst_element_link_filtered (GstElement * src, GstElement * dest, @@ -2038,7 +2038,7 @@ free_src: * gst_element_unlink_many: * @element_1: (transfer none): the first #GstElement in the link chain. * @element_2: (transfer none): the second #GstElement in the link chain. - * @...: the NULL-terminated list of elements to unlink in order. + * @...: the %NULL-terminated list of elements to unlink in order. * * Unlinks a series of elements. Uses gst_element_unlink(). */ @@ -2134,7 +2134,7 @@ gst_element_unlink (GstElement * src, GstElement * dest) * @element: a #GstElement to invoke the position query on. * @format: the #GstFormat requested * @cur: (out) (allow-none): a location in which to store the current - * position, or NULL. + * position, or %NULL. * * Queries an element (usually top-level pipeline or playbin element) for the * stream position in nanoseconds. This will be a value between 0 and the @@ -2146,7 +2146,7 @@ gst_element_unlink (GstElement * src, GstElement * dest) * If one repeatedly calls this function one can also create a query and reuse * it in gst_element_query(). * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ gboolean gst_element_query_position (GstElement * element, GstFormat format, @@ -2173,7 +2173,7 @@ gst_element_query_position (GstElement * element, GstFormat format, * gst_element_query_duration: * @element: a #GstElement to invoke the duration query on. * @format: the #GstFormat requested - * @duration: (out) (allow-none): A location in which to store the total duration, or NULL. + * @duration: (out) (allow-none): A location in which to store the total duration, or %NULL. * * Queries an element (usually top-level pipeline or playbin element) for the * total stream duration in nanoseconds. This query will only work once the @@ -2184,7 +2184,7 @@ gst_element_query_position (GstElement * element, GstFormat format, * message on the pipeline bus, in which case you should re-query the duration * using this function. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ gboolean gst_element_query_duration (GstElement * element, GstFormat format, @@ -2217,7 +2217,7 @@ gst_element_query_duration (GstElement * element, GstFormat format, * * Queries an element to convert @src_val in @src_format to @dest_format. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ gboolean gst_element_query_convert (GstElement * element, GstFormat src_format, @@ -2309,7 +2309,7 @@ gst_pad_use_fixed_caps (GstPad * pad) * @pad: a pad * * Gets the parent of @pad, cast to a #GstElement. If a @pad has no parent or - * its parent is not an element, return NULL. + * its parent is not an element, return %NULL. * * Returns: (transfer full): the parent of the pad. The caller has a * reference on the parent, so unref when you're finished with it. @@ -2336,7 +2336,7 @@ gst_pad_get_parent_element (GstPad * pad) * gst_object_default_error: * @source: the #GstObject that initiated the error. * @error: (in): the GError. - * @debug: (in) (allow-none): an additional debug information string, or NULL + * @debug: (in) (allow-none): an additional debug information string, or %NULL * * A default error function that uses g_printerr() to display the error message * and the optional debug sting.. @@ -2362,7 +2362,7 @@ gst_object_default_error (GstObject * source, const GError * error, * @element_1: (transfer full): the #GstElement element to add to the bin * @...: (transfer full): additional elements to add to the bin * - * Adds a NULL-terminated list of elements to a bin. This function is + * Adds a %NULL-terminated list of elements to a bin. This function is * equivalent to calling gst_bin_add() for each member of the list. The return * value of each gst_bin_add() is ignored. */ @@ -2389,7 +2389,7 @@ gst_bin_add_many (GstBin * bin, GstElement * element_1, ...) * gst_bin_remove_many: * @bin: a #GstBin * @element_1: (transfer none): the first #GstElement to remove from the bin - * @...: (transfer none): NULL-terminated list of elements to remove from the bin + * @...: (transfer none): %NULL-terminated list of elements to remove from the bin * * Remove a list of elements from a bin. This function is equivalent * to calling gst_bin_remove() with each member of the list. @@ -2436,14 +2436,14 @@ query_accept_caps_func (GstPad * pad, QueryAcceptCapsData * data) * @pad: a #GstPad to proxy. * @query: an ACCEPT_CAPS #GstQuery. * - * Calls gst_pad_accept_caps() for all internally linked pads of @pad and + * Checks if all internally linked pads of @pad accepts the caps in @query and * returns the intersection of the results. * * This function is useful as a default accept caps query function for an element * that can handle any stream format, but requires caps that are acceptable for - * all oposite pads. + * all opposite pads. * - * Returns: TRUE if @query could be executed + * Returns: %TRUE if @query could be executed */ gboolean gst_pad_proxy_query_accept_caps (GstPad * pad, GstQuery * query) @@ -2459,12 +2459,16 @@ gst_pad_proxy_query_accept_caps (GstPad * pad, GstQuery * query) data.query = query; /* value to hold the return, by default it holds TRUE */ + /* FIXME: TRUE is wrong when there are no pads */ data.ret = TRUE; gst_pad_forward (pad, (GstPadForwardFunction) query_accept_caps_func, &data); gst_query_set_accept_caps_result (query, data.ret); - return TRUE; + GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "proxying accept caps query: %d", + data.ret); + + return data.ret; } typedef struct @@ -2500,14 +2504,14 @@ query_caps_func (GstPad * pad, QueryCapsData * data) * @pad: a #GstPad to proxy. * @query: a CAPS #GstQuery. * - * Calls gst_pad_query_caps() for all internally linked pads fof @pad and returns + * Calls gst_pad_query_caps() for all internally linked pads of @pad and returns * the intersection of the results. * * This function is useful as a default caps query function for an element * that can handle any stream format, but requires all its pads to have * the same caps. Two such elements are tee and adder. * - * Returns: TRUE if @query could be executed + * Returns: %TRUE if @query could be executed */ gboolean gst_pad_proxy_query_caps (GstPad * pad, GstQuery * query) @@ -2538,6 +2542,7 @@ gst_pad_proxy_query_caps (GstPad * pad, GstQuery * query) gst_query_set_caps_result (query, result); gst_caps_unref (result); + /* FIXME: return something depending on the processing */ return TRUE; } @@ -2545,11 +2550,11 @@ gst_pad_proxy_query_caps (GstPad * pad, GstQuery * query) * gst_pad_query_position: * @pad: a #GstPad to invoke the position query on. * @format: the #GstFormat requested - * @cur: (out) (allow-none): A location in which to store the current position, or NULL. + * @cur: (out) (allow-none): A location in which to store the current position, or %NULL. * * Queries a pad for the stream position. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ gboolean gst_pad_query_position (GstPad * pad, GstFormat format, gint64 * cur) @@ -2574,11 +2579,11 @@ gst_pad_query_position (GstPad * pad, GstFormat format, gint64 * cur) * Must be a sink pad. * @format: the #GstFormat requested * @cur: (out) (allow-none): a location in which to store the current - * position, or NULL. + * position, or %NULL. * * Queries the peer of a given sink pad for the stream position. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ gboolean gst_pad_peer_query_position (GstPad * pad, GstFormat format, gint64 * cur) @@ -2602,11 +2607,11 @@ gst_pad_peer_query_position (GstPad * pad, GstFormat format, gint64 * cur) * @pad: a #GstPad to invoke the duration query on. * @format: the #GstFormat requested * @duration: (out) (allow-none): a location in which to store the total - * duration, or NULL. + * duration, or %NULL. * * Queries a pad for the total stream duration. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ gboolean gst_pad_query_duration (GstPad * pad, GstFormat format, gint64 * duration) @@ -2631,11 +2636,11 @@ gst_pad_query_duration (GstPad * pad, GstFormat format, gint64 * duration) * Must be a sink pad. * @format: the #GstFormat requested * @duration: (out) (allow-none): a location in which to store the total - * duration, or NULL. + * duration, or %NULL. * * Queries the peer pad of a given sink pad for the total stream duration. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ gboolean gst_pad_peer_query_duration (GstPad * pad, GstFormat format, gint64 * duration) @@ -2665,7 +2670,7 @@ gst_pad_peer_query_duration (GstPad * pad, GstFormat format, gint64 * duration) * * Queries a pad to convert @src_val in @src_format to @dest_format. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ gboolean gst_pad_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val, @@ -2703,7 +2708,7 @@ gst_pad_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val, * Queries the peer pad of a given sink pad to convert @src_val in @src_format * to @dest_format. * - * Returns: TRUE if the query could be performed. + * Returns: %TRUE if the query could be performed. */ gboolean gst_pad_peer_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val, @@ -2728,19 +2733,19 @@ gst_pad_peer_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val, /** * gst_pad_query_caps: * @pad: a #GstPad to get the capabilities of. - * @filter: (allow-none): suggested #GstCaps, or NULL + * @filter: (allow-none): suggested #GstCaps, or %NULL * * Gets the capabilities this pad can produce or consume. * Note that this method doesn't necessarily return the caps set by sending a * gst_event_new_caps() - use gst_pad_get_current_caps() for that instead. * gst_pad_query_caps returns all possible caps a pad can operate with, using * the pad's CAPS query function, If the query fails, this function will return - * @filter, if not #NULL, otherwise ANY. + * @filter, if not %NULL, otherwise ANY. * * When called on sinkpads @filter contains the caps that * upstream could produce in the order preferred by upstream. When * called on srcpads @filter contains the caps accepted by - * downstream in the preffered order. @filter might be %NULL but + * downstream in the preferred order. @filter might be %NULL but * if it is not %NULL the returned caps will be a subset of @filter. * * Note that this function does not return writable #GstCaps, use @@ -2779,7 +2784,7 @@ gst_pad_query_caps (GstPad * pad, GstCaps * filter) /** * gst_pad_peer_query_caps: * @pad: a #GstPad to get the capabilities of. - * @filter: (allow-none): a #GstCaps filter, or NULL. + * @filter: (allow-none): a #GstCaps filter, or %NULL. * * Gets the capabilities of the peer connected to this pad. Similar to * gst_pad_query_caps(). @@ -2787,7 +2792,7 @@ gst_pad_query_caps (GstPad * pad, GstCaps * filter) * When called on srcpads @filter contains the caps that * upstream could produce in the order preferred by upstream. When * called on sinkpads @filter contains the caps accepted by - * downstream in the preffered order. @filter might be %NULL but + * downstream in the preferred order. @filter might be %NULL but * if it is not %NULL the returned caps will be a subset of @filter. * * Returns: the caps of the peer pad with incremented ref-count. When there is @@ -2829,7 +2834,7 @@ gst_pad_peer_query_caps (GstPad * pad, GstCaps * filter) * * Check if the given pad accepts the caps. * - * Returns: TRUE if the pad can accept the caps. + * Returns: %TRUE if the pad can accept the caps. */ gboolean gst_pad_query_accept_caps (GstPad * pad, GstCaps * caps) @@ -2859,9 +2864,9 @@ gst_pad_query_accept_caps (GstPad * pad, GstCaps * caps) * @caps: a #GstCaps to check on the pad * * Check if the peer of @pad accepts @caps. If @pad has no peer, this function - * returns TRUE. + * returns %TRUE. * - * Returns: TRUE if the peer of @pad can accept the caps or @pad has no peer. + * Returns: %TRUE if the peer of @pad can accept the caps or @pad has no peer. */ gboolean gst_pad_peer_query_accept_caps (GstPad * pad, GstCaps * caps) @@ -2948,11 +2953,11 @@ element_find_unlinked_pad (GstElement * element, GstPadDirection direction) * * Recursively looks for elements with an unlinked pad of the given * direction within the specified bin and returns an unlinked pad - * if one is found, or NULL otherwise. If a pad is found, the caller + * if one is found, or %NULL otherwise. If a pad is found, the caller * owns a reference to it and should use gst_object_unref() on the * pad when it is not needed any longer. * - * Returns: (transfer full): unlinked pad of the given direction, or NULL. + * Returns: (transfer full): unlinked pad of the given direction, %NULL. */ GstPad * gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction) @@ -3000,7 +3005,7 @@ gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction) * @bin_description: command line describing the bin * @ghost_unlinked_pads: whether to automatically create ghost pads * for unlinked source or sink pads within the bin - * @err: where to store the error message in case of an error, or NULL + * @err: where to store the error message in case of an error, or %NULL * * This is a convenience wrapper around gst_parse_launch() to create a * #GstBin from a gst-launch-style pipeline description. See @@ -3031,7 +3036,7 @@ gst_parse_bin_from_description (const gchar * bin_description, * @context: (transfer none) (allow-none): a parse context allocated with * gst_parse_context_new(), or %NULL * @flags: parsing options, or #GST_PARSE_FLAG_NONE - * @err: where to store the error message in case of an error, or NULL + * @err: where to store the error message in case of an error, or %NULL * * This is a convenience wrapper around gst_parse_launch() to create a * #GstBin from a gst-launch-style pipeline description. See @@ -3043,9 +3048,10 @@ gst_parse_bin_from_description (const gchar * bin_description, * and want them all ghosted, you will have to create the ghost pads * yourself). * - * Returns: (transfer full) (type Gst.Element): a newly-created element, which - * is guaranteed to be a bin unless GST_FLAG_NO_SINGLE_ELEMENT_BINS was - * passed, or %NULL if an error occurred. + * Returns: (transfer floating) (type Gst.Element): a newly-created + * element, which is guaranteed to be a bin unless + * GST_FLAG_NO_SINGLE_ELEMENT_BINS was passed, or %NULL if an error + * occurred. */ GstElement * gst_parse_bin_from_description_full (const gchar * bin_description, @@ -3417,6 +3423,13 @@ gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d, g_return_val_if_fail (a_d != 0, FALSE); g_return_val_if_fail (b_d != 0, FALSE); + /* early out if either is 0, as its gcd would be 0 */ + if (a_n == 0 || b_n == 0) { + *res_n = 0; + *res_d = 1; + return TRUE; + } + gcd = gst_util_greatest_common_divisor (a_n, a_d); a_n /= gcd; a_d /= gcd; @@ -3562,32 +3575,9 @@ gst_util_fraction_compare (gint a_n, gint a_d, gint b_n, gint b_d) g_return_val_if_reached (0); } -/** - * gst_pad_create_stream_id_printf_valist: - * @pad: A source #GstPad - * @parent: Parent #GstElement of @pad - * @stream_id: (allow-none): The stream-id - * @var_args: parameters for the @stream_id format string - * - * Creates a stream-id for the source #GstPad @pad by combining the - * upstream information with the optional @stream_id of the stream - * of @pad. @pad must have a parent #GstElement and which must have zero - * or one sinkpad. @stream_id can only be %NULL if the parent element - * of @pad has only a single source pad. - * - * This function generates an unique stream-id by getting the upstream - * stream-start event stream ID and appending @stream_id to it. If the - * element has no sinkpad it will generate an upstream stream-id by - * doing an URI query on the element and in the worst case just uses - * a random number. Source elements that don't implement the URI - * handler interface should ideally generate a unique, deterministic - * stream-id manually instead. - * - * Returns: A stream-id for @pad. g_free() after usage. - */ -gchar * -gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent, - const gchar * stream_id, va_list var_args) +static gchar * +gst_pad_create_stream_id_internal (GstPad * pad, GstElement * parent, + const gchar * stream_id) { GstEvent *upstream_event; gchar *upstream_stream_id = NULL, *new_stream_id; @@ -3655,9 +3645,7 @@ gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent, } if (stream_id) { - gchar *expanded = g_strdup_vprintf (stream_id, var_args); - new_stream_id = g_strconcat (upstream_stream_id, "/", expanded, NULL); - g_free (expanded); + new_stream_id = g_strconcat (upstream_stream_id, "/", stream_id, NULL); } else { new_stream_id = g_strdup (upstream_stream_id); } @@ -3668,6 +3656,45 @@ gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent, } /** + * gst_pad_create_stream_id_printf_valist: + * @pad: A source #GstPad + * @parent: Parent #GstElement of @pad + * @stream_id: (allow-none): The stream-id + * @var_args: parameters for the @stream_id format string + * + * Creates a stream-id for the source #GstPad @pad by combining the + * upstream information with the optional @stream_id of the stream + * of @pad. @pad must have a parent #GstElement and which must have zero + * or one sinkpad. @stream_id can only be %NULL if the parent element + * of @pad has only a single source pad. + * + * This function generates an unique stream-id by getting the upstream + * stream-start event stream ID and appending @stream_id to it. If the + * element has no sinkpad it will generate an upstream stream-id by + * doing an URI query on the element and in the worst case just uses + * a random number. Source elements that don't implement the URI + * handler interface should ideally generate a unique, deterministic + * stream-id manually instead. + * + * Returns: A stream-id for @pad. g_free() after usage. + */ +gchar * +gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent, + const gchar * stream_id, va_list var_args) +{ + gchar *expanded = NULL, *new_stream_id; + + if (stream_id) + expanded = g_strdup_vprintf (stream_id, var_args); + + new_stream_id = gst_pad_create_stream_id_internal (pad, parent, expanded); + + g_free (expanded); + + return new_stream_id; +} + +/** * gst_pad_create_stream_id_printf: * @pad: A source #GstPad * @parent: Parent #GstElement of @pad @@ -3735,7 +3762,7 @@ gchar * gst_pad_create_stream_id (GstPad * pad, GstElement * parent, const gchar * stream_id) { - return gst_pad_create_stream_id_printf (pad, parent, stream_id, NULL); + return gst_pad_create_stream_id_internal (pad, parent, stream_id); } /** @@ -3751,7 +3778,7 @@ gst_pad_create_stream_id (GstPad * pad, GstElement * parent, * The returned stream-id string should be treated as an opaque string, its * contents should not be interpreted. * - * Returns: a newly-allocated copy of the stream-idfor @pad, or %NULL. + * Returns: a newly-allocated copy of the stream-id for @pad, or %NULL. * g_free() the returned string when no longer needed. * * Since: 1.2 diff --git a/gst/gstutils.h b/gst/gstutils.h index 1530807..a935883 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -113,6 +113,7 @@ guint gst_util_group_id_next (void); #define _GST_PUT(__data, __idx, __size, __shift, __num) \ (((guint8 *) (__data))[__idx] = (((guint##__size) (__num)) >> (__shift)) & 0xff) +#ifndef __GTK_DOC_IGNORE__ #if GST_HAVE_UNALIGNED_ACCESS static inline guint16 __gst_fast_read16(const guint8 *v) { return *(const guint16*)(v); @@ -135,6 +136,7 @@ static inline guint64 __gst_fast_read_swap64(const guint8 *v) { # define _GST_FAST_READ(s, d) __gst_fast_read##s((const guint8 *)(d)) # define _GST_FAST_READ_SWAP(s, d) __gst_fast_read_swap##s((const guint8 *)(d)) #endif +#endif /** @@ -814,6 +816,24 @@ GST_WRITE_DOUBLE_BE(guint8 *data, gdouble num) * Rounds an integer value up to the next multiple of 64. */ #define GST_ROUND_UP_64(num) (((num)+63)&~63) +/** + * GST_ROUND_UP_128: + * @num: integer value to round up + * + * Rounds an integer value up to the next multiple of 128. + * Since: 1.4 + */ +#define GST_ROUND_UP_128(num) (((num)+127)&~127) +/** + * GST_ROUND_UP_N: + * @num: integrer value to round up + * @align: a power of two to round up to + * + * Rounds an integer value up to the next multiple of @align. @align MUST be a + * power of two. + */ +#define GST_ROUND_UP_N(num,align) ((((num) + ((align) - 1)) & ~((align) - 1))) + /** * GST_ROUND_DOWN_2: @@ -857,6 +877,24 @@ GST_WRITE_DOUBLE_BE(guint8 *data, gdouble num) * Rounds an integer value down to the next multiple of 64. */ #define GST_ROUND_DOWN_64(num) ((num)&(~63)) +/** + * GST_ROUND_DOWN_128: + * @num: integer value to round down + * + * Rounds an integer value down to the next multiple of 128. + * Since: 1.4 + */ +#define GST_ROUND_DOWN_128(num) ((num)&(~127)) +/** + * GST_ROUND_DOWN_N: + * @num: integrer value to round down + * @align: a power of two to round down to + * + * Rounds an integer value down to the next multiple of @align. @align MUST be a + * power of two. + */ +#define GST_ROUND_DOWN_N(num,align) (((num) & ~((align) - 1))) + void gst_object_default_error (GstObject * source, const GError * error, @@ -934,9 +972,9 @@ gboolean gst_pad_peer_query_convert (GstPad *pad, GstFormat GstCaps * gst_pad_peer_query_caps (GstPad * pad, GstCaps *filter); gboolean gst_pad_peer_query_accept_caps (GstPad * pad, GstCaps *caps); -gchar * gst_pad_create_stream_id (GstPad * pad, GstElement * parent, const gchar *stream_id); -gchar * gst_pad_create_stream_id_printf (GstPad * pad, GstElement * parent, const gchar *stream_id, ...); -gchar * gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent, const gchar *stream_id, va_list var_args); +gchar * gst_pad_create_stream_id (GstPad * pad, GstElement * parent, const gchar *stream_id) G_GNUC_MALLOC; +gchar * gst_pad_create_stream_id_printf (GstPad * pad, GstElement * parent, const gchar *stream_id, ...) G_GNUC_PRINTF (3, 4) G_GNUC_MALLOC; +gchar * gst_pad_create_stream_id_printf_valist (GstPad * pad, GstElement * parent, const gchar *stream_id, va_list var_args) G_GNUC_PRINTF (3, 0) G_GNUC_MALLOC; gchar * gst_pad_get_stream_id (GstPad * pad); diff --git a/gst/gstvalue.c b/gst/gstvalue.c index c2885cd..f088cca 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -26,8 +26,6 @@ * * Note that operations on the same #GValue from multiple threads may lead to * undefined behaviour. - * - * Last reviewed on 2008-03-11 (0.10.18) */ #ifdef HAVE_CONFIG_H @@ -65,8 +63,8 @@ typedef gboolean (*GstValueUnionFunc) (GValue * dest, * * Used by gst_value_intersect() to perform intersection for a specific #GValue * type. If the intersection is non-empty, the result is - * placed in @dest and TRUE is returned. If the intersection is - * empty, @dest is unmodified and FALSE is returned. + * placed in @dest and %TRUE is returned. If the intersection is + * empty, @dest is unmodified and %FALSE is returned. * Register a new implementation with gst_value_register_intersect_func(). * * Returns: %TRUE if the values can intersect @@ -123,8 +121,9 @@ struct _GstValueSubtractInfo #define FUNDAMENTAL_TYPE_ID(type) \ ((type) >> G_TYPE_FUNDAMENTAL_SHIFT) -#define VALUE_LIST_SIZE(v) (((GArray *) (v)->data[0].v_pointer)->len) -#define VALUE_LIST_GET_VALUE(v, index) ((const GValue *) &g_array_index ((GArray *) (v)->data[0].v_pointer, GValue, (index))) +#define VALUE_LIST_ARRAY(v) ((GArray *) (v)->data[0].v_pointer) +#define VALUE_LIST_SIZE(v) (VALUE_LIST_ARRAY(v)->len) +#define VALUE_LIST_GET_VALUE(v, index) ((const GValue *) &g_array_index (VALUE_LIST_ARRAY(v), GValue, (index))) static GArray *gst_value_table; static GHashTable *gst_value_hash; @@ -533,6 +532,56 @@ gst_value_list_concat (GValue * dest, const GValue * value1, } } +/* same as gst_value_list_concat() but takes ownership of GValues */ +static void +gst_value_list_concat_and_take_values (GValue * dest, GValue * val1, + GValue * val2) +{ + guint i, val1_length, val2_length; + gboolean val1_is_list; + gboolean val2_is_list; + GArray *array; + + g_assert (dest != NULL); + g_assert (G_VALUE_TYPE (dest) == 0); + g_assert (G_IS_VALUE (val1)); + g_assert (G_IS_VALUE (val2)); + g_assert (gst_value_list_or_array_are_compatible (val1, val2)); + + val1_is_list = GST_VALUE_HOLDS_LIST (val1); + val1_length = (val1_is_list ? VALUE_LIST_SIZE (val1) : 1); + + val2_is_list = GST_VALUE_HOLDS_LIST (val2); + val2_length = (val2_is_list ? VALUE_LIST_SIZE (val2) : 1); + + g_value_init (dest, GST_TYPE_LIST); + array = (GArray *) dest->data[0].v_pointer; + g_array_set_size (array, val1_length + val2_length); + + if (val1_is_list) { + for (i = 0; i < val1_length; i++) { + g_array_index (array, GValue, i) = *VALUE_LIST_GET_VALUE (val1, i); + } + g_array_set_size (VALUE_LIST_ARRAY (val1), 0); + g_value_unset (val1); + } else { + g_array_index (array, GValue, 0) = *val1; + G_VALUE_TYPE (val1) = G_TYPE_INVALID; + } + + if (val2_is_list) { + for (i = 0; i < val2_length; i++) { + const GValue *v2 = VALUE_LIST_GET_VALUE (val2, i); + g_array_index (array, GValue, i + val1_length) = *v2; + } + g_array_set_size (VALUE_LIST_ARRAY (val2), 0); + g_value_unset (val2); + } else { + g_array_index (array, GValue, val1_length) = *val2; + G_VALUE_TYPE (val2) = G_TYPE_INVALID; + } +} + /** * gst_value_list_merge: * @dest: (out caller-allocates): an uninitialized #GValue to take the result @@ -899,52 +948,36 @@ gst_value_deserialize_array (GValue * dest, const gchar * s) * Values in the range are defined as any value greater or equal * to min*step, AND lesser or equal to max*step. * For step == 1, this falls back to the traditional range semantics. + * + * data[0] = (min << 32) | (max) + * data[1] = step + * *************/ -#define INT_RANGE_MIN(v) (((gint *)((v)->data[0].v_pointer))[0]) -#define INT_RANGE_MAX(v) (((gint *)((v)->data[0].v_pointer))[1]) -#define INT_RANGE_STEP(v) (((gint *)((v)->data[0].v_pointer))[2]) +#define INT_RANGE_MIN(v) ((gint) (((v)->data[0].v_uint64) >> 32)) +#define INT_RANGE_MAX(v) ((gint) (((v)->data[0].v_uint64) & 0xffffffff)) +#define INT_RANGE_STEP(v) ((v)->data[1].v_int) static void gst_value_init_int_range (GValue * value) { - gint *vals = g_slice_alloc0 (3 * sizeof (gint)); - value->data[0].v_pointer = vals; - INT_RANGE_MIN (value) = 0; - INT_RANGE_MAX (value) = 0; - INT_RANGE_STEP (value) = 1; -} + G_STATIC_ASSERT (sizeof (gint) <= 2 * sizeof (guint64)); -static void -gst_value_free_int_range (GValue * value) -{ - g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value)); - g_slice_free1 (3 * sizeof (gint), value->data[0].v_pointer); - value->data[0].v_pointer = NULL; + value->data[0].v_uint64 = 0; + value->data[1].v_int = 1; } static void gst_value_copy_int_range (const GValue * src_value, GValue * dest_value) { - gint *vals = (gint *) dest_value->data[0].v_pointer; - gint *src_vals = (gint *) src_value->data[0].v_pointer; - - if (vals == NULL) { - gst_value_init_int_range (dest_value); - } - if (src_vals != NULL) { - INT_RANGE_MIN (dest_value) = INT_RANGE_MIN (src_value); - INT_RANGE_MAX (dest_value) = INT_RANGE_MAX (src_value); - INT_RANGE_STEP (dest_value) = INT_RANGE_STEP (src_value); - } + dest_value->data[0].v_uint64 = src_value->data[0].v_uint64; + dest_value->data[1].v_int = src_value->data[1].v_int; } static gchar * gst_value_collect_int_range (GValue * value, guint n_collect_values, GTypeCValue * collect_values, guint collect_flags) { - gint *vals = value->data[0].v_pointer; - if (n_collect_values != 2) return g_strdup_printf ("not enough value locations for `%s' passed", G_VALUE_TYPE_NAME (value)); @@ -952,10 +985,6 @@ gst_value_collect_int_range (GValue * value, guint n_collect_values, return g_strdup_printf ("range start is not smaller than end for `%s'", G_VALUE_TYPE_NAME (value)); - if (vals == NULL) { - gst_value_init_int_range (value); - } - gst_value_set_int_range_step (value, collect_values[0].v_int, collect_values[1].v_int, 1); @@ -968,8 +997,6 @@ gst_value_lcopy_int_range (const GValue * value, guint n_collect_values, { guint32 *int_range_start = collect_values[0].v_pointer; guint32 *int_range_end = collect_values[1].v_pointer; - guint32 *int_range_step = collect_values[2].v_pointer; - gint *vals = (gint *) value->data[0].v_pointer; if (!int_range_start) return g_strdup_printf ("start value location for `%s' passed as NULL", @@ -977,18 +1004,9 @@ gst_value_lcopy_int_range (const GValue * value, guint n_collect_values, if (!int_range_end) return g_strdup_printf ("end value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); - if (!int_range_step) - return g_strdup_printf ("step value location for `%s' passed as NULL", - G_VALUE_TYPE_NAME (value)); - - if (G_UNLIKELY (vals == NULL)) { - return g_strdup_printf ("Uninitialised `%s' passed", - G_VALUE_TYPE_NAME (value)); - } *int_range_start = INT_RANGE_MIN (value); *int_range_end = INT_RANGE_MAX (value); - *int_range_step = INT_RANGE_STEP (value); return NULL; } @@ -1005,15 +1023,18 @@ gst_value_lcopy_int_range (const GValue * value, guint n_collect_values, void gst_value_set_int_range_step (GValue * value, gint start, gint end, gint step) { + guint64 sstart, sstop; + g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value)); g_return_if_fail (start < end); g_return_if_fail (step > 0); g_return_if_fail (start % step == 0); g_return_if_fail (end % step == 0); - INT_RANGE_MIN (value) = start / step; - INT_RANGE_MAX (value) = end / step; - INT_RANGE_STEP (value) = step; + sstart = (guint) (start / step); + sstop = (guint) (end / step); + value->data[0].v_uint64 = (sstart << 32) | sstop; + value->data[1].v_int = step; } /** @@ -1052,7 +1073,7 @@ gst_value_get_int_range_min (const GValue * value) * * Gets the maximum of the range specified by @value. * - * Returns: the maxumum of the range + * Returns: the maximum of the range */ gint gst_value_get_int_range_max (const GValue * value) @@ -1111,8 +1132,8 @@ gst_value_compare_int_range (const GValue * value1, const GValue * value2) and bounds lie on the same value */ if (n1 > 1) { if (INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) && - INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) && - INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2)) { + INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2) && + INT_RANGE_MAX (value1) == INT_RANGE_MAX (value2)) { return GST_VALUE_EQUAL; } return GST_VALUE_UNORDERED; @@ -1304,7 +1325,7 @@ gst_value_get_int64_range_min (const GValue * value) * * Gets the maximum of the range specified by @value. * - * Returns: the maxumum of the range + * Returns: the maximum of the range */ gint64 gst_value_get_int64_range_max (const GValue * value) @@ -1366,8 +1387,8 @@ gst_value_compare_int64_range (const GValue * value1, const GValue * value2) and bounds lie on the same value */ if (n1 > 1) { if (INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) && - INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) && - INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2)) { + INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2) && + INT64_RANGE_MAX (value1) == INT64_RANGE_MAX (value2)) { return GST_VALUE_EQUAL; } return GST_VALUE_UNORDERED; @@ -1495,7 +1516,7 @@ gst_value_get_double_range_min (const GValue * value) * * Gets the maximum of the range specified by @value. * - * Returns: the maxumum of the range + * Returns: the maximum of the range */ gdouble gst_value_get_double_range_max (const GValue * value) @@ -1522,7 +1543,7 @@ static gint gst_value_compare_double_range (const GValue * value1, const GValue * value2) { if (value2->data[0].v_double == value1->data[0].v_double && - value2->data[0].v_double == value1->data[0].v_double) + value2->data[1].v_double == value1->data[1].v_double) return GST_VALUE_EQUAL; return GST_VALUE_UNORDERED; } @@ -1724,6 +1745,15 @@ gst_value_set_fraction_range_full (GValue * value, /* g_value_unset (&end); */ } +/* FIXME 2.0: Don't leak the internal representation of fraction + * ranges but instead return the numerator and denominator + * separately. + * This would allow to store fraction ranges as + * data[0] = (min_n << 32) | (min_d) + * data[1] = (max_n << 32) | (max_d) + * without requiring an additional allocation for each value. + */ + /** * gst_value_get_fraction_range_min: * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE @@ -1887,8 +1917,7 @@ static gchar * gst_value_serialize_caps (const GValue * value) { GstCaps *caps = g_value_get_boxed (value); - - return gst_caps_to_string (caps); + return gst_string_take_and_wrap (gst_caps_to_string (caps)); } static gboolean @@ -1896,7 +1925,17 @@ gst_value_deserialize_caps (GValue * dest, const gchar * s) { GstCaps *caps; - caps = gst_caps_from_string (s); + if (*s != '"') { + caps = gst_caps_from_string (s); + } else { + gchar *str = gst_string_unwrap (s); + + if (G_UNLIKELY (!str)) + return FALSE; + + caps = gst_caps_from_string (str); + g_free (str); + } if (caps) { g_value_take_boxed (dest, caps); @@ -2523,7 +2562,7 @@ gst_value_deserialize_int_helper (gint64 * to, const gchar * s, { gboolean ret = FALSE; gchar *end; - gint64 mask = -1; + guint64 mask = ~0; errno = 0; *to = g_ascii_strtoull (s, &end, 0); @@ -2886,7 +2925,7 @@ gst_string_take_and_wrap (gchar * s) * 0->3, y is copied unescaped. * * If \xyy is found where x is an octal number but y is not, an - * error is encountered and NULL is returned. + * error is encountered and %NULL is returned. * * the input string must be \0 terminated. */ @@ -3352,15 +3391,23 @@ gst_value_union_int_int_range (GValue * dest, const GValue * src1, /* check if it extends the range */ if (v == (INT_RANGE_MIN (src2) - 1) * INT_RANGE_STEP (src2)) { if (dest) { + guint64 new_min = + (guint) ((INT_RANGE_MIN (src2) - 1) * INT_RANGE_STEP (src2)); + guint64 new_max = (guint) (INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2)); + gst_value_init_and_copy (dest, src2); - --INT_RANGE_MIN (src2); + dest->data[0].v_uint64 = (new_min << 32) | (new_max); } return TRUE; } if (v == (INT_RANGE_MAX (src2) + 1) * INT_RANGE_STEP (src2)) { if (dest) { + guint64 new_min = (guint) (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2)); + guint64 new_max = + (guint) ((INT_RANGE_MAX (src2) + 1) * INT_RANGE_STEP (src2)); + gst_value_init_and_copy (dest, src2); - ++INT_RANGE_MAX (src2); + dest->data[0].v_uint64 = (new_min << 32) | (new_max); } return TRUE; } @@ -3426,15 +3473,26 @@ gst_value_union_int_range_int_range (GValue * dest, const GValue * src1, if (scalar == (INT_RANGE_MIN (range_value) - 1) * INT_RANGE_STEP (range_value)) { if (dest) { + guint64 new_min = (guint) + ((INT_RANGE_MIN (range_value) - + 1) * INT_RANGE_STEP (range_value)); + guint64 new_max = (guint) + (INT_RANGE_MAX (range_value) * INT_RANGE_STEP (range_value)); + gst_value_init_and_copy (dest, range_value); - --INT_RANGE_MIN (range_value); + dest->data[0].v_uint64 = (new_min << 32) | (new_max); } return TRUE; } else if (scalar == (INT_RANGE_MAX (range_value) + 1) * INT_RANGE_STEP (range_value)) { if (dest) { + guint64 new_min = (guint) + (INT_RANGE_MIN (range_value) * INT_RANGE_STEP (range_value)); + guint64 new_max = (guint) + ((INT_RANGE_MAX (range_value) + + 1) * INT_RANGE_STEP (range_value)); gst_value_init_and_copy (dest, range_value); - ++INT_RANGE_MIN (range_value); + dest->data[0].v_uint64 = (new_min << 32) | (new_max); } return TRUE; } @@ -3784,6 +3842,9 @@ gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend, gint step = gst_value_get_int_range_step (subtrahend); gint val = g_value_get_int (minuend); + if (step == 0) + return FALSE; + /* subtracting a range from an int only works if the int is not in the * range */ if (val < min || val > max || val % step) { @@ -3843,9 +3904,7 @@ gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2, } if (min1 <= max1 && min2 <= max2) { - gst_value_list_concat (dest, pv1, pv2); - g_value_unset (pv1); - g_value_unset (pv2); + gst_value_list_concat_and_take_values (dest, pv1, pv2); } return TRUE; } @@ -3861,6 +3920,9 @@ gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend, g_return_val_if_fail (min < max, FALSE); + if (step == 0) + return FALSE; + /* value is outside of the range, return range unchanged */ if (val < min || val > max || val % step) { if (dest) @@ -3902,6 +3964,9 @@ gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend, } step = step1; + if (step == 0) + return FALSE; + if (max2 >= max1 && min2 <= min1) { return FALSE; } else if (max2 >= max1) { @@ -3925,6 +3990,8 @@ gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend, gint64 step = gst_value_get_int64_range_step (subtrahend); gint64 val = g_value_get_int64 (minuend); + if (step == 0) + return FALSE; /* subtracting a range from an int64 only works if the int64 is not in the * range */ if (val < min || val > max || val % step) { @@ -3984,9 +4051,7 @@ gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1, } if (min1 <= max1 && min2 <= max2) { - gst_value_list_concat (dest, pv1, pv2); - g_value_unset (pv1); - g_value_unset (pv2); + gst_value_list_concat_and_take_values (dest, pv1, pv2); } return TRUE; } @@ -4002,6 +4067,9 @@ gst_value_subtract_int64_range_int64 (GValue * dest, const GValue * minuend, g_return_val_if_fail (min < max, FALSE); + if (step == 0) + return FALSE; + /* value is outside of the range, return range unchanged */ if (val < min || val > max || val % step) { if (dest) @@ -4042,6 +4110,10 @@ gst_value_subtract_int64_range_int64_range (GValue * dest, g_assert (FALSE); return FALSE; } + + if (step1 == 0) + return FALSE; + step = step1; if (max2 >= max1 && min2 <= min1) { @@ -4125,9 +4197,7 @@ gst_value_subtract_double_range_double_range (GValue * dest, } if (min1 < max1 && min2 < max2) { - gst_value_list_concat (dest, pv1, pv2); - g_value_unset (pv1); - g_value_unset (pv2); + gst_value_list_concat_and_take_values (dest, pv1, pv2); } return TRUE; } @@ -4139,9 +4209,6 @@ gst_value_subtract_from_list (GValue * dest, const GValue * minuend, guint i, size; GValue subtraction = { 0, }; gboolean ret = FALSE; - GType ltype; - - ltype = gst_value_list_get_type (); size = VALUE_LIST_SIZE (minuend); for (i = 0; i < size; i++) { @@ -4160,16 +4227,14 @@ gst_value_subtract_from_list (GValue * dest, const GValue * minuend, if (!ret) { gst_value_move (dest, &subtraction); ret = TRUE; - } else if (G_VALUE_HOLDS (dest, ltype) - && !G_VALUE_HOLDS (&subtraction, ltype)) { + } else if (G_VALUE_TYPE (dest) == GST_TYPE_LIST + && G_VALUE_TYPE (&subtraction) != GST_TYPE_LIST) { _gst_value_list_append_and_take_value (dest, &subtraction); } else { GValue temp; gst_value_move (&temp, dest); - gst_value_list_concat (dest, &temp, &subtraction); - g_value_unset (&temp); - g_value_unset (&subtraction); + gst_value_list_concat_and_take_values (dest, &temp, &subtraction); } } } @@ -4303,9 +4368,7 @@ gst_value_subtract_fraction_range_fraction_range (GValue * dest, } if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) { - gst_value_list_concat (dest, pv1, pv2); - g_value_unset (pv1); - g_value_unset (pv2); + gst_value_list_concat_and_take_values (dest, pv1, pv2); } return TRUE; } @@ -4355,6 +4418,15 @@ gst_value_get_compare_func (const GValue * value1) return NULL; } +static inline gboolean +gst_value_can_compare_unchecked (const GValue * value1, const GValue * value2) +{ + if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) + return FALSE; + + return gst_value_get_compare_func (value1) != NULL; +} + /** * gst_value_can_compare: * @value1: a value to compare @@ -4362,7 +4434,7 @@ gst_value_get_compare_func (const GValue * value1) * * Determines if @value1 and @value2 can be compared. * - * Returns: TRUE if the values can be compared + * Returns: %TRUE if the values can be compared */ gboolean gst_value_can_compare (const GValue * value1, const GValue * value2) @@ -4370,10 +4442,7 @@ gst_value_can_compare (const GValue * value1, const GValue * value2) g_return_val_if_fail (G_IS_VALUE (value1), FALSE); g_return_val_if_fail (G_IS_VALUE (value2), FALSE); - if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) - return FALSE; - - return gst_value_get_compare_func (value1) != NULL; + return gst_value_can_compare_unchecked (value1, value2); } static gboolean @@ -4382,9 +4451,9 @@ gst_value_list_equals_range (const GValue * list, const GValue * value) const GValue *first; guint list_size, n; - g_return_val_if_fail (G_IS_VALUE (list), FALSE); - g_return_val_if_fail (G_IS_VALUE (value), FALSE); - g_return_val_if_fail (GST_VALUE_HOLDS_LIST (list), FALSE); + g_assert (G_IS_VALUE (list)); + g_assert (G_IS_VALUE (value)); + g_assert (GST_VALUE_HOLDS_LIST (list)); /* TODO: compare against an empty list ? No type though... */ list_size = VALUE_LIST_SIZE (list); @@ -4399,6 +4468,8 @@ gst_value_list_equals_range (const GValue * list, const GValue * value) const gint rmin = gst_value_get_int_range_min (value); const gint rmax = gst_value_get_int_range_max (value); const gint rstep = gst_value_get_int_range_step (value); + if (rstep == 0) + return FALSE; /* note: this will overflow for min 0 and max INT_MAX, but this would only be equal to a list of INT_MAX elements, which seems very unlikely */ @@ -4416,6 +4487,8 @@ gst_value_list_equals_range (const GValue * list, const GValue * value) const gint64 rmax = gst_value_get_int64_range_max (value); const gint64 rstep = gst_value_get_int64_range_step (value); GST_DEBUG ("List/range of int64s"); + if (rstep == 0) + return FALSE; if (list_size != rmax / rstep - rmin / rstep + 1) return FALSE; for (n = 0; n < list_size; ++n) { @@ -4431,6 +4504,27 @@ gst_value_list_equals_range (const GValue * list, const GValue * value) return FALSE; } +/* "Pure" variant of gst_value_compare which is guaranteed to + * not have list arguments and therefore does basic comparisions + */ +static inline gint +_gst_value_compare_nolist (const GValue * value1, const GValue * value2) +{ + GstValueCompareFunc compare; + + if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) + return GST_VALUE_UNORDERED; + + compare = gst_value_get_compare_func (value1); + if (compare) { + return compare (value1, value2); + } + + g_critical ("unable to compare values of type %s\n", + g_type_name (G_VALUE_TYPE (value1))); + return GST_VALUE_UNORDERED; +} + /** * gst_value_compare: * @value1: a value to compare @@ -4447,47 +4541,67 @@ gst_value_list_equals_range (const GValue * list, const GValue * value) gint gst_value_compare (const GValue * value1, const GValue * value2) { - GstValueCompareFunc compare; - GType ltype; + gboolean value1_is_list; + gboolean value2_is_list; g_return_val_if_fail (G_IS_VALUE (value1), GST_VALUE_LESS_THAN); g_return_val_if_fail (G_IS_VALUE (value2), GST_VALUE_GREATER_THAN); + value1_is_list = G_VALUE_TYPE (value1) == GST_TYPE_LIST; + value2_is_list = G_VALUE_TYPE (value2) == GST_TYPE_LIST; + /* Special cases: lists and scalar values ("{ 1 }" and "1" are equal), as well as lists and ranges ("{ 1, 2 }" and "[ 1, 2 ]" are equal) */ - ltype = gst_value_list_get_type (); - if (G_VALUE_HOLDS (value1, ltype) && !G_VALUE_HOLDS (value2, ltype)) { + if (value1_is_list && !value2_is_list) { + gint i, n, ret; if (gst_value_list_equals_range (value1, value2)) { return GST_VALUE_EQUAL; - } else if (gst_value_list_get_size (value1) == 1) { + } + + n = gst_value_list_get_size (value1); + if (n == 0) + return GST_VALUE_UNORDERED; + + for (i = 0; i < n; i++) { const GValue *elt; - elt = gst_value_list_get_value (value1, 0); - return gst_value_compare (elt, value2); + elt = gst_value_list_get_value (value1, i); + ret = gst_value_compare (elt, value2); + if (ret != GST_VALUE_EQUAL && n == 1) + return ret; + else if (ret != GST_VALUE_EQUAL) + return GST_VALUE_UNORDERED; } - } else if (G_VALUE_HOLDS (value2, ltype) && !G_VALUE_HOLDS (value1, ltype)) { + + return GST_VALUE_EQUAL; + } else if (value2_is_list && !value1_is_list) { + gint i, n, ret; + if (gst_value_list_equals_range (value2, value1)) { return GST_VALUE_EQUAL; - } else if (gst_value_list_get_size (value2) == 1) { + } + + n = gst_value_list_get_size (value2); + if (n == 0) + return GST_VALUE_UNORDERED; + + for (i = 0; i < n; i++) { const GValue *elt; - elt = gst_value_list_get_value (value2, 0); - return gst_value_compare (elt, value1); + elt = gst_value_list_get_value (value2, i); + ret = gst_value_compare (elt, value1); + if (ret != GST_VALUE_EQUAL && n == 1) + return ret; + else if (ret != GST_VALUE_EQUAL) + return GST_VALUE_UNORDERED; } - } - if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) - return GST_VALUE_UNORDERED; - - compare = gst_value_get_compare_func (value1); - if (compare) { - return compare (value1, value2); + return GST_VALUE_EQUAL; } - g_critical ("unable to compare values of type %s\n", - g_type_name (G_VALUE_TYPE (value1))); - return GST_VALUE_UNORDERED; + /* And now handle the generic case */ + return _gst_value_compare_nolist (value1, value2); } /* @@ -4523,13 +4637,13 @@ gst_value_compare_with_func (const GValue * value1, const GValue * value2, * * Determines if @value1 and @value2 can be non-trivially unioned. * Any two values can be trivially unioned by adding both of them - * to a GstValueList. However, certain types have the possibility + * to a #GstValueList. However, certain types have the possibility * to be unioned in a simpler way. For example, an integer range * and an integer can be unioned if the integer is a subset of the * integer range. If there is the possibility that two values can - * be unioned, this function returns TRUE. + * be unioned, this function returns %TRUE. * - * Returns: TRUE if there is a function allowing the two values to + * Returns: %TRUE if there is a function allowing the two values to * be unioned. */ gboolean @@ -4564,7 +4678,7 @@ gst_value_can_union (const GValue * value1, const GValue * value2) * * Creates a GValue corresponding to the union of @value1 and @value2. * - * Returns: TRUE if the union suceeded. + * Returns: %TRUE if the union succeeded. */ gboolean gst_value_union (GValue * dest, const GValue * value1, const GValue * value2) @@ -4630,35 +4744,32 @@ gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func) * * Determines if intersecting two values will produce a valid result. * Two values will produce a valid intersection if they have the same - * type, or if there is a method (registered by - * gst_value_register_intersect_func()) to calculate the intersection. + * type. * - * Returns: TRUE if the values can intersect + * Returns: %TRUE if the values can intersect */ gboolean gst_value_can_intersect (const GValue * value1, const GValue * value2) { GstValueIntersectInfo *intersect_info; guint i, len; - GType ltype, type1, type2; + GType type1, type2; g_return_val_if_fail (G_IS_VALUE (value1), FALSE); g_return_val_if_fail (G_IS_VALUE (value2), FALSE); - ltype = gst_value_list_get_type (); - - /* special cases */ - if (G_VALUE_HOLDS (value1, ltype) || G_VALUE_HOLDS (value2, ltype)) - return TRUE; - type1 = G_VALUE_TYPE (value1); type2 = G_VALUE_TYPE (value2); /* practically all GstValue types have a compare function (_can_compare=TRUE) - * GstStructure and GstCaps have npot, but are intersectable */ + * GstStructure and GstCaps have not, but are intersectable */ if (type1 == type2) return TRUE; + /* special cases */ + if (type1 == GST_TYPE_LIST || type2 == GST_TYPE_LIST) + return TRUE; + /* check registered intersect functions */ len = gst_value_intersect_funcs->len; for (i = 0; i < len; i++) { @@ -4669,22 +4780,22 @@ gst_value_can_intersect (const GValue * value1, const GValue * value2) return TRUE; } - return gst_value_can_compare (value1, value2); + return gst_value_can_compare_unchecked (value1, value2); } /** * gst_value_intersect: * @dest: (out caller-allocates) (transfer full): a uninitialized #GValue that will hold the calculated - * intersection value. May be NULL if the resulting set if not needed. + * intersection value. May be %NULL if the resulting set if not needed. * @value1: a value to intersect * @value2: another value to intersect * * Calculates the intersection of two values. If the values have * a non-empty intersection, the value representing the intersection - * is placed in @dest, unless NULL. If the intersection is non-empty, + * is placed in @dest, unless %NULL. If the intersection is non-empty, * @dest is not modified. * - * Returns: TRUE if the intersection is non-empty + * Returns: %TRUE if the intersection is non-empty */ gboolean gst_value_intersect (GValue * dest, const GValue * value1, @@ -4692,28 +4803,26 @@ gst_value_intersect (GValue * dest, const GValue * value1, { GstValueIntersectInfo *intersect_info; guint i, len; - GType ltype, type1, type2; + GType type1, type2; g_return_val_if_fail (G_IS_VALUE (value1), FALSE); g_return_val_if_fail (G_IS_VALUE (value2), FALSE); - ltype = gst_value_list_get_type (); + type1 = G_VALUE_TYPE (value1); + type2 = G_VALUE_TYPE (value2); /* special cases first */ - if (G_VALUE_HOLDS (value1, ltype)) + if (type1 == GST_TYPE_LIST) return gst_value_intersect_list (dest, value1, value2); - if (G_VALUE_HOLDS (value2, ltype)) + if (type2 == GST_TYPE_LIST) return gst_value_intersect_list (dest, value2, value1); - if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) { + if (_gst_value_compare_nolist (value1, value2) == GST_VALUE_EQUAL) { if (dest) gst_value_init_and_copy (dest, value1); return TRUE; } - type1 = G_VALUE_TYPE (value1); - type2 = G_VALUE_TYPE (value2); - len = gst_value_intersect_funcs->len; for (i = 0; i < len; i++) { intersect_info = &g_array_index (gst_value_intersect_funcs, @@ -4762,7 +4871,7 @@ gst_value_register_intersect_func (GType type1, GType type2, /** * gst_value_subtract: * @dest: (out caller-allocates): the destination value for the result if the - * subtraction is not empty. May be NULL, in which case the resulting set + * subtraction is not empty. May be %NULL, in which case the resulting set * will not be computed, which can give a fair speedup. * @minuend: the value to subtract from * @subtrahend: the value to subtract @@ -4778,22 +4887,20 @@ gst_value_subtract (GValue * dest, const GValue * minuend, { GstValueSubtractInfo *info; guint i, len; - GType ltype, mtype, stype; + GType mtype, stype; g_return_val_if_fail (G_IS_VALUE (minuend), FALSE); g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE); - ltype = gst_value_list_get_type (); + mtype = G_VALUE_TYPE (minuend); + stype = G_VALUE_TYPE (subtrahend); /* special cases first */ - if (G_VALUE_HOLDS (minuend, ltype)) + if (mtype == GST_TYPE_LIST) return gst_value_subtract_from_list (dest, minuend, subtrahend); - if (G_VALUE_HOLDS (subtrahend, ltype)) + if (stype == GST_TYPE_LIST) return gst_value_subtract_list (dest, minuend, subtrahend); - mtype = G_VALUE_TYPE (minuend); - stype = G_VALUE_TYPE (subtrahend); - len = gst_value_subtract_funcs->len; for (i = 0; i < len; i++) { info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i); @@ -4802,7 +4909,7 @@ gst_value_subtract (GValue * dest, const GValue * minuend, } } - if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) { + if (_gst_value_compare_nolist (minuend, subtrahend) != GST_VALUE_EQUAL) { if (dest) gst_value_init_and_copy (dest, minuend); return TRUE; @@ -4832,27 +4939,25 @@ gst_value_subtract (GValue * dest, const GValue * minuend, * * Checks if it's possible to subtract @subtrahend from @minuend. * - * Returns: TRUE if a subtraction is possible + * Returns: %TRUE if a subtraction is possible */ gboolean gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend) { GstValueSubtractInfo *info; guint i, len; - GType ltype, mtype, stype; + GType mtype, stype; g_return_val_if_fail (G_IS_VALUE (minuend), FALSE); g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE); - ltype = gst_value_list_get_type (); + mtype = G_VALUE_TYPE (minuend); + stype = G_VALUE_TYPE (subtrahend); /* special cases */ - if (G_VALUE_HOLDS (minuend, ltype) || G_VALUE_HOLDS (subtrahend, ltype)) + if (mtype == GST_TYPE_LIST || stype == GST_TYPE_LIST) return TRUE; - mtype = G_VALUE_TYPE (minuend); - stype = G_VALUE_TYPE (subtrahend); - len = gst_value_subtract_funcs->len; for (i = 0; i < len; i++) { info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i); @@ -4860,7 +4965,7 @@ gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend) return TRUE; } - return gst_value_can_compare (minuend, subtrahend); + return gst_value_can_compare_unchecked (minuend, subtrahend); } /* gst_value_register_subtract_func: (skip) @@ -4954,7 +5059,7 @@ gst_value_move (GValue * dest, GValue * src) * * Free-function: g_free * - * Returns: (transfer full): the serialization for @value or NULL if none exists + * Returns: (transfer full): the serialization for @value or %NULL if none exists */ gchar * gst_value_serialize (const GValue * value) @@ -5003,9 +5108,9 @@ gst_value_serialize (const GValue * value) * @src: string to deserialize * * Tries to deserialize a string into the type specified by the given GValue. - * If the operation succeeds, TRUE is returned, FALSE otherwise. + * If the operation succeeds, %TRUE is returned, %FALSE otherwise. * - * Returns: TRUE on success + * Returns: %TRUE on success */ gboolean gst_value_deserialize (GValue * dest, const gchar * src) @@ -5087,9 +5192,9 @@ gst_value_is_fixed (const GValue * value) * Fixate @src into a new value @dest. * For ranges, the first element is taken. For lists and arrays, the * first item is fixated and returned. - * If @src is already fixed, this function returns FALSE. + * If @src is already fixed, this function returns %FALSE. * - * Returns: true if @dest contains a fixated version of @src. + * Returns: %TRUE if @dest contains a fixated version of @src. */ gboolean gst_value_fixate (GValue * dest, const GValue * src) @@ -5293,7 +5398,7 @@ gst_value_get_fraction_denominator (const GValue * value) * Multiplies the two #GValue items containing a #GST_TYPE_FRACTION and sets * @product to the product of the two fractions. * - * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise. + * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise. */ gboolean gst_value_fraction_multiply (GValue * product, const GValue * factor1, @@ -5327,7 +5432,7 @@ gst_value_fraction_multiply (GValue * product, const GValue * factor1, * * Subtracts the @subtrahend from the @minuend and sets @dest to the result. * - * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise. + * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise. */ gboolean gst_value_fraction_subtract (GValue * dest, @@ -5785,6 +5890,51 @@ gst_value_compare_bitmask (const GValue * value1, const GValue * value2) return GST_VALUE_UNORDERED; } + +/*********************** + * GstAllocationParams * + ***********************/ +static gint +gst_value_compare_allocation_params (const GValue * value1, + const GValue * value2) +{ + GstAllocationParams *v1, *v2; + + v1 = value1->data[0].v_pointer; + v2 = value2->data[0].v_pointer; + + if (v1 == NULL && v1 == v2) + return GST_VALUE_EQUAL; + + if (v1 == NULL || v2 == NULL) + return GST_VALUE_UNORDERED; + + if (v1->flags == v2->flags && v1->align == v2->align && + v1->prefix == v2->prefix && v1->padding == v2->padding) + return GST_VALUE_EQUAL; + + return GST_VALUE_UNORDERED; +} + + +/************ + * GObject * + ************/ + +static gint +gst_value_compare_object (const GValue * value1, const GValue * value2) +{ + gpointer v1, v2; + + v1 = value1->data[0].v_pointer; + v2 = value2->data[0].v_pointer; + + if (v1 == v2) + return GST_VALUE_EQUAL; + + return GST_VALUE_UNORDERED; +} + static void gst_value_transform_object_string (const GValue * src_value, GValue * dest_value) @@ -5822,17 +5972,20 @@ static GTypeFundamentalInfo _finfo = { }; #define FUNC_VALUE_GET_TYPE(type, name) \ +GType _gst_ ## type ## _type = 0; \ + \ GType gst_ ## type ## _get_type (void) \ { \ - static volatile GType gst_ ## type ## _type = 0; \ + static volatile GType gst_ ## type ## _type = 0; \ \ - if (g_once_init_enter (&gst_ ## type ## _type)) { \ - GType _type; \ + if (g_once_init_enter (&gst_ ## type ## _type)) { \ + GType _type; \ _info.value_table = & _gst_ ## type ## _value_table; \ - _type = g_type_register_fundamental ( \ + _type = g_type_register_fundamental ( \ g_type_fundamental_next (), \ name, &_info, &_finfo, 0); \ - g_once_init_leave(&gst_ ## type ## _type, _type); \ + _gst_ ## type ## _type = _type; \ + g_once_init_leave(&gst_ ## type ## _type, _type); \ } \ \ return gst_ ## type ## _type; \ @@ -5840,7 +5993,7 @@ GType gst_ ## type ## _get_type (void) \ static const GTypeValueTable _gst_int_range_value_table = { gst_value_init_int_range, - gst_value_free_int_range, + NULL, gst_value_copy_int_range, NULL, (char *) "ii", @@ -5929,9 +6082,6 @@ static const GTypeValueTable _gst_fraction_value_table = { FUNC_VALUE_GET_TYPE (fraction, "GstFraction"); -G_DEFINE_BOXED_TYPE (GstDateTime, gst_date_time, - (GBoxedCopyFunc) gst_date_time_ref, (GBoxedFreeFunc) gst_date_time_unref); - static const GTypeValueTable _gst_bitmask_value_table = { gst_value_init_bitmask, NULL, @@ -6184,6 +6334,30 @@ _priv_gst_value_initialize (void) gst_value_register (&gst_value); } + { + static GstValueTable gst_value = { + 0, + gst_value_compare_allocation_params, + NULL, + NULL, + }; + + gst_value.type = gst_allocation_params_get_type (); + gst_value_register (&gst_value); + } + + { + static GstValueTable gst_value = { + 0, + gst_value_compare_object, + NULL, + NULL, + }; + + gst_value.type = G_TYPE_OBJECT; + gst_value_register (&gst_value); + } + REGISTER_SERIALIZATION (G_TYPE_DOUBLE, double); REGISTER_SERIALIZATION (G_TYPE_FLOAT, float); diff --git a/gst/gstvalue.h b/gst/gstvalue.h index d03d22e..de01abc 100644 --- a/gst/gstvalue.h +++ b/gst/gstvalue.h @@ -92,7 +92,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_INT_RANGE value. */ -#define GST_VALUE_HOLDS_INT_RANGE(x) (G_VALUE_HOLDS((x), gst_int_range_get_type ())) +#define GST_VALUE_HOLDS_INT_RANGE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_int_range_type) /** * GST_VALUE_HOLDS_INT64_RANGE: @@ -100,7 +100,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_INT64_RANGE value. */ -#define GST_VALUE_HOLDS_INT64_RANGE(x) (G_VALUE_HOLDS((x), gst_int64_range_get_type ())) +#define GST_VALUE_HOLDS_INT64_RANGE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_int64_range_type) /** * GST_VALUE_HOLDS_DOUBLE_RANGE: @@ -108,7 +108,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_DOUBLE_RANGE value. */ -#define GST_VALUE_HOLDS_DOUBLE_RANGE(x) (G_VALUE_HOLDS((x), gst_double_range_get_type ())) +#define GST_VALUE_HOLDS_DOUBLE_RANGE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_double_range_type) /** * GST_VALUE_HOLDS_FRACTION_RANGE: @@ -116,7 +116,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_FRACTION_RANGE value. */ -#define GST_VALUE_HOLDS_FRACTION_RANGE(x) (G_VALUE_HOLDS((x), gst_fraction_range_get_type ())) +#define GST_VALUE_HOLDS_FRACTION_RANGE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_fraction_range_type) /** * GST_VALUE_HOLDS_LIST: @@ -124,7 +124,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_LIST value. */ -#define GST_VALUE_HOLDS_LIST(x) (G_VALUE_HOLDS((x), gst_value_list_get_type ())) +#define GST_VALUE_HOLDS_LIST(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_value_list_type) /** * GST_VALUE_HOLDS_ARRAY: @@ -132,7 +132,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_ARRAY value. */ -#define GST_VALUE_HOLDS_ARRAY(x) (G_VALUE_HOLDS((x), gst_value_array_get_type ())) +#define GST_VALUE_HOLDS_ARRAY(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_value_array_type) /** * GST_VALUE_HOLDS_CAPS: @@ -140,7 +140,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_CAPS value. */ -#define GST_VALUE_HOLDS_CAPS(x) (G_VALUE_HOLDS((x), GST_TYPE_CAPS)) +#define GST_VALUE_HOLDS_CAPS(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_caps_type) /** * GST_VALUE_HOLDS_STRUCTURE: @@ -148,7 +148,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_STRUCTURE value. */ -#define GST_VALUE_HOLDS_STRUCTURE(x) (G_VALUE_HOLDS((x), GST_TYPE_STRUCTURE)) +#define GST_VALUE_HOLDS_STRUCTURE(x) (G_VALUE_HOLDS((x), _gst_structure_type)) /** * GST_VALUE_HOLDS_CAPS_FEATURES: @@ -156,7 +156,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_CAPS_FEATURES value. */ -#define GST_VALUE_HOLDS_CAPS_FEATURES(x) (G_VALUE_HOLDS((x), GST_TYPE_CAPS_FEATURES)) +#define GST_VALUE_HOLDS_CAPS_FEATURES(x) (G_VALUE_HOLDS((x), _gst_caps_features_type)) /** * GST_VALUE_HOLDS_BUFFER: @@ -164,7 +164,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_BUFFER value. */ -#define GST_VALUE_HOLDS_BUFFER(x) (G_VALUE_HOLDS((x), GST_TYPE_BUFFER)) +#define GST_VALUE_HOLDS_BUFFER(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_buffer_type) /** * GST_VALUE_HOLDS_SAMPLE: @@ -172,7 +172,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_SAMPLE value. */ -#define GST_VALUE_HOLDS_SAMPLE(x) (G_VALUE_HOLDS((x), GST_TYPE_SAMPLE)) +#define GST_VALUE_HOLDS_SAMPLE(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_sample_type) /** * GST_VALUE_HOLDS_FRACTION: @@ -180,7 +180,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_FRACTION value. */ -#define GST_VALUE_HOLDS_FRACTION(x) (G_VALUE_HOLDS((x), gst_fraction_get_type ())) +#define GST_VALUE_HOLDS_FRACTION(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_fraction_type) /** * GST_VALUE_HOLDS_DATE_TIME: @@ -188,7 +188,7 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_DATE_TIME value. */ -#define GST_VALUE_HOLDS_DATE_TIME(x) (G_VALUE_HOLDS((x), gst_date_time_get_type ())) +#define GST_VALUE_HOLDS_DATE_TIME(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_date_time_type) /** * GST_VALUE_HOLDS_BITMASK: @@ -196,7 +196,9 @@ G_BEGIN_DECLS * * Checks if the given #GValue contains a #GST_TYPE_BITMASK value. */ -#define GST_VALUE_HOLDS_BITMASK(x) (G_VALUE_HOLDS((x), gst_bitmask_get_type ())) +#define GST_VALUE_HOLDS_BITMASK(x) ((x) != NULL && G_VALUE_TYPE(x) == _gst_bitmask_type) + +GST_EXPORT GType _gst_int_range_type; /** * GST_TYPE_INT_RANGE: @@ -205,7 +207,9 @@ G_BEGIN_DECLS * * Returns: the #GType of GstIntRange */ -#define GST_TYPE_INT_RANGE gst_int_range_get_type () +#define GST_TYPE_INT_RANGE (_gst_int_range_type) + +GST_EXPORT GType _gst_int64_range_type; /** * GST_TYPE_INT64_RANGE: @@ -214,16 +218,20 @@ G_BEGIN_DECLS * * Returns: the #GType of GstInt64Range */ -#define GST_TYPE_INT64_RANGE gst_int64_range_get_type () +#define GST_TYPE_INT64_RANGE (_gst_int64_range_type) + +GST_EXPORT GType _gst_double_range_type; /** * GST_TYPE_DOUBLE_RANGE: * - * a #GValue type that represents a floating point range with double precission + * a #GValue type that represents a floating point range with double precision * * Returns: the #GType of GstIntRange */ -#define GST_TYPE_DOUBLE_RANGE gst_double_range_get_type () +#define GST_TYPE_DOUBLE_RANGE (_gst_double_range_type) + +GST_EXPORT GType _gst_fraction_range_type; /** * GST_TYPE_FRACTION_RANGE: @@ -232,7 +240,9 @@ G_BEGIN_DECLS * * Returns: the #GType of GstFractionRange */ -#define GST_TYPE_FRACTION_RANGE gst_fraction_range_get_type () +#define GST_TYPE_FRACTION_RANGE (_gst_fraction_range_type) + +GST_EXPORT GType _gst_value_list_type; /** * GST_TYPE_LIST: @@ -245,7 +255,9 @@ G_BEGIN_DECLS * * Returns: the #GType of GstValueList (which is not explicitly typed) */ -#define GST_TYPE_LIST gst_value_list_get_type () +#define GST_TYPE_LIST (_gst_value_list_type) + +GST_EXPORT GType _gst_value_array_type; /** * GST_TYPE_ARRAY: @@ -259,7 +271,9 @@ G_BEGIN_DECLS * * Returns: the #GType of GstArrayList (which is not explicitly typed) */ -#define GST_TYPE_ARRAY gst_value_array_get_type () +#define GST_TYPE_ARRAY (_gst_value_array_type) + +GST_EXPORT GType _gst_fraction_type; /** * GST_TYPE_FRACTION: @@ -270,17 +284,9 @@ G_BEGIN_DECLS * Returns: the #GType of GstFraction (which is not explicitly typed) */ -#define GST_TYPE_FRACTION gst_fraction_get_type () +#define GST_TYPE_FRACTION (_gst_fraction_type) -/** - * GST_TYPE_DATE_TIME: - * - * a boxed #GValue type for #GstDateTime that represents a date and time. - * - * Returns: the #GType of GstDateTime - */ - -#define GST_TYPE_DATE_TIME gst_date_time_get_type () +GST_EXPORT GType _gst_bitmask_type; /** * GST_TYPE_BITMASK: @@ -290,7 +296,7 @@ G_BEGIN_DECLS * Returns: the #GType of GstBitmask (which is not explicitly typed) */ -#define GST_TYPE_BITMASK gst_bitmask_get_type () +#define GST_TYPE_BITMASK (_gst_bitmask_type) /** * GST_TYPE_G_THREAD: @@ -405,8 +411,6 @@ GType gst_bitmask_get_type (void); GType gst_g_thread_get_type (void); #endif -GType gst_date_time_get_type (void); - void gst_value_register (const GstValueTable *table); void gst_value_init_and_copy (GValue *dest, const GValue *src); diff --git a/gst/parse/Makefile.am b/gst/parse/Makefile.am index 7b5fd27..a26d471 100644 --- a/gst/parse/Makefile.am +++ b/gst/parse/Makefile.am @@ -1,22 +1,20 @@ # libgstparse.la is an optionally built helper library linked into core noinst_LTLIBRARIES = libgstparse.la -CLEANFILES = grammar.tab.h grammar.output +CLEANFILES = grammar.tab.h parse_lex.h grammar.output EXTRA_DIST = \ grammar.y \ parse.l # uncomment these lines to dist the generated sources -#BUILT_SOURCES = grammar.tab.h grammar.tab.c lex.priv_gst_parse_yy.c +#BUILT_SOURCES = grammar.tab.h grammar.tab.c parse_lex.h lex.priv_gst_parse_yy.c #libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c # uncomment these lines to _NOT_ dist the generated sources -nodist_libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c grammar.tab.h +nodist_libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c grammar.tag.h parse_lex.h CLEANFILES += grammar.tab.c lex.priv_gst_parse_yy.c -# can't use GST_ALL_CFLAGS here because that'd pull in -Werror -libgstparse_la_CFLAGS = -I$(top_srcdir) -I$(top_builddir) \ - $(GLIB_CFLAGS) $(GST_OPTION_CFLAGS) +libgstparse_la_CFLAGS = $(GST_ALL_CFLAGS) -DYYMALLOC=g_malloc -DYYFREE=g_free libgstparse_la_LIBADD = $(GST_ALL_LIBS) noinst_HEADERS = types.h @@ -39,14 +37,15 @@ grammar.tab.c grammar.tab.h: grammar.y rm grammar.tab_tmp.c && \ mv grammar.tab_tmp2.c grammar.tab.c -lex.priv_gst_parse_yy.c: parse.l grammar.tab.h - $(AM_V_GEN)$(FLEX_PATH) -Ppriv_gst_parse_yy $^ && \ +lex.priv_gst_parse_yy.c parse_lex.h: parse.l grammar.tab.h + $(AM_V_GEN)$(FLEX_PATH) --header-file=parse_lex.h -Ppriv_gst_parse_yy $^ && \ mv lex.priv_gst_parse_yy.c lex.priv_gst_parse_yy_tmp.c && \ echo '#ifdef HAVE_CONFIG_H' > lex.priv_gst_parse_yy_tmp2.c && \ echo '#include <config.h>' >> lex.priv_gst_parse_yy_tmp2.c && \ echo '#endif' >> lex.priv_gst_parse_yy_tmp2.c && \ - echo 'static inline int priv_gst_parse_yyget_column (void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c && \ - echo 'static inline void priv_gst_parse_yyset_column (int column_no , void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c && \ + { grep -q priv_gst_parse_yyget_column parse_lex.h || \ + { echo 'int priv_gst_parse_yyget_column (void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c && \ + echo 'void priv_gst_parse_yyset_column (int column_no , void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c; }; } && \ cat lex.priv_gst_parse_yy_tmp.c >> lex.priv_gst_parse_yy_tmp2.c && \ rm lex.priv_gst_parse_yy_tmp.c && \ mv lex.priv_gst_parse_yy_tmp2.c lex.priv_gst_parse_yy.c diff --git a/gst/parse/Makefile.in b/gst/parse/Makefile.in index 0dd9b73..517775a 100644 --- a/gst/parse/Makefile.in +++ b/gst/parse/Makefile.in @@ -89,7 +89,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ $(top_srcdir)/common/m4/as-compiler-flag.m4 \ $(top_srcdir)/common/m4/as-docbook.m4 \ $(top_srcdir)/common/m4/as-libtool.m4 \ - $(top_srcdir)/common/m4/as-scrub-include.m4 \ $(top_srcdir)/common/m4/as-version.m4 \ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ $(top_srcdir)/common/m4/gst-arch.m4 \ @@ -482,7 +481,7 @@ top_srcdir = @top_srcdir@ # libgstparse.la is an optionally built helper library linked into core noinst_LTLIBRARIES = libgstparse.la -CLEANFILES = grammar.tab.h grammar.output grammar.tab.c \ +CLEANFILES = grammar.tab.h parse_lex.h grammar.output grammar.tab.c \ lex.priv_gst_parse_yy.c EXTRA_DIST = \ grammar.y \ @@ -490,16 +489,12 @@ EXTRA_DIST = \ # uncomment these lines to dist the generated sources -#BUILT_SOURCES = grammar.tab.h grammar.tab.c lex.priv_gst_parse_yy.c +#BUILT_SOURCES = grammar.tab.h grammar.tab.c parse_lex.h lex.priv_gst_parse_yy.c #libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c # uncomment these lines to _NOT_ dist the generated sources -nodist_libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c grammar.tab.h - -# can't use GST_ALL_CFLAGS here because that'd pull in -Werror -libgstparse_la_CFLAGS = -I$(top_srcdir) -I$(top_builddir) \ - $(GLIB_CFLAGS) $(GST_OPTION_CFLAGS) - +nodist_libgstparse_la_SOURCES = lex.priv_gst_parse_yy.c grammar.tab.c grammar.tag.h parse_lex.h +libgstparse_la_CFLAGS = $(GST_ALL_CFLAGS) -DYYMALLOC=g_malloc -DYYFREE=g_free libgstparse_la_LIBADD = $(GST_ALL_LIBS) noinst_HEADERS = types.h all: all-am @@ -827,14 +822,15 @@ grammar.tab.c grammar.tab.h: grammar.y rm grammar.tab_tmp.c && \ mv grammar.tab_tmp2.c grammar.tab.c -lex.priv_gst_parse_yy.c: parse.l grammar.tab.h - $(AM_V_GEN)$(FLEX_PATH) -Ppriv_gst_parse_yy $^ && \ +lex.priv_gst_parse_yy.c parse_lex.h: parse.l grammar.tab.h + $(AM_V_GEN)$(FLEX_PATH) --header-file=parse_lex.h -Ppriv_gst_parse_yy $^ && \ mv lex.priv_gst_parse_yy.c lex.priv_gst_parse_yy_tmp.c && \ echo '#ifdef HAVE_CONFIG_H' > lex.priv_gst_parse_yy_tmp2.c && \ echo '#include <config.h>' >> lex.priv_gst_parse_yy_tmp2.c && \ echo '#endif' >> lex.priv_gst_parse_yy_tmp2.c && \ - echo 'static inline int priv_gst_parse_yyget_column (void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c && \ - echo 'static inline void priv_gst_parse_yyset_column (int column_no , void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c && \ + { grep -q priv_gst_parse_yyget_column parse_lex.h || \ + { echo 'int priv_gst_parse_yyget_column (void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c && \ + echo 'void priv_gst_parse_yyset_column (int column_no , void * yyscanner);' >> lex.priv_gst_parse_yy_tmp2.c; }; } && \ cat lex.priv_gst_parse_yy_tmp.c >> lex.priv_gst_parse_yy_tmp2.c && \ rm lex.priv_gst_parse_yy_tmp.c && \ mv lex.priv_gst_parse_yy_tmp2.c lex.priv_gst_parse_yy.c diff --git a/gst/parse/grammar.y b/gst/parse/grammar.y index f533389..3f0513e 100644 --- a/gst/parse/grammar.y +++ b/gst/parse/grammar.y @@ -33,14 +33,9 @@ #define YYLTYPE_IS_TRIVIAL 0 #endif -typedef void* yyscan_t; - -int priv_gst_parse_yylex (void * yylval_param , yyscan_t yyscanner); -int priv_gst_parse_yylex_init (yyscan_t scanner); -int priv_gst_parse_yylex_destroy (yyscan_t scanner); -struct yy_buffer_state * priv_gst_parse_yy_scan_string (char* , yyscan_t); -void _gst_parse_yypush_buffer_state (void * new_buffer ,yyscan_t yyscanner ); -void _gst_parse_yypop_buffer_state (yyscan_t yyscanner ); +/******************************************************************************************* +*** Tracing memory leaks +*******************************************************************************************/ #ifdef __GST_PARSE_TRACE static guint __strings; @@ -65,7 +60,7 @@ __gst_parse_strfree (gchar *str) __strings--; } } -link_t *__gst_parse_link_new () +link_t *__gst_parse_link_new (void) { link_t *ret; __links++; @@ -84,18 +79,18 @@ __gst_parse_link_free (link_t *data) } } chain_t * -__gst_parse_chain_new () +__gst_parse_chain_new (void) { chain_t *ret; __chains++; ret = g_slice_new0 (chain_t); - /* g_print ("ALLOCATED CHAIN (%3u): %p\n", __chains, ret); */ + /* g_print ("@%p: ALLOCATED CHAIN (%3u):\n", ret, __chains); */ return ret; } void __gst_parse_chain_free (chain_t *data) { - /* g_print ("FREEING CHAIN (%3u): %p\n", __chains - 1, data); */ + /* g_print ("@%p: FREEING CHAIN (%3u):\n", data, __chains - 1); */ g_slice_free (chain_t, data); g_return_if_fail (__chains > 0); __chains--; @@ -103,22 +98,9 @@ __gst_parse_chain_free (chain_t *data) #endif /* __GST_PARSE_TRACE */ -typedef struct { - gchar *src_pad; - gchar *sink_pad; - GstElement *sink; - GstCaps *caps; - gulong signal_id; -} DelayedLink; - -typedef struct { - gchar *name; - gchar *value_str; - gulong signal_id; -} DelayedSet; - -/*** define SET_ERROR macro/function */ - +/******************************************************************************************* +*** define SET_ERROR macro/function +*******************************************************************************************/ #ifdef G_HAVE_ISO_VARARGS # define SET_ERROR(error, type, ...) \ @@ -206,79 +188,77 @@ YYPRINTF(const char *format, ...) #endif /* GST_DISABLE_GST_DEBUG */ -#define ADD_MISSING_ELEMENT(graph,name) G_STMT_START { \ - if ((graph)->ctx) { \ - (graph)->ctx->missing_elements = \ - g_list_append ((graph)->ctx->missing_elements, g_strdup (name)); \ - } } G_STMT_END -static void -no_free (gconstpointer foo) -{ - /* do nothing */ +/* + * include headers generated by bison & flex, after defining (or not defining) YYDEBUG + */ +#include "grammar.tab.h" +#include "parse_lex.h" + +/******************************************************************************************* +*** report missing elements/bins/.. +*******************************************************************************************/ + + +static void add_missing_element(graph_t *graph,gchar *name){ + if ((graph)->ctx){ + (graph)->ctx->missing_elements = g_list_append ((graph)->ctx->missing_elements, g_strdup (name)); + } } -#define GST_BIN_MAKE(res, type, chainval, assign, type_string_free_func) \ -G_STMT_START { \ - chain_t *chain = chainval; \ - GSList *walk; \ - GstBin *bin = (GstBin *) gst_element_factory_make (type, NULL); \ - if (!chain) { \ - SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY_BIN, \ - _("specified empty bin \"%s\", not allowed"), type); \ - g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \ - g_slist_free (assign); \ - gst_object_unref (bin); \ - type_string_free_func (type); /* Need to clean up the string */ \ - YYERROR; \ - } else if (!bin) { \ - ADD_MISSING_ELEMENT(graph, type); \ - SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, \ - _("no bin \"%s\", skipping"), type); \ - g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \ - g_slist_free (assign); \ - res = chain; \ - } else { \ - for (walk = chain->elements; walk; walk = walk->next ) \ - gst_bin_add (bin, GST_ELEMENT (walk->data)); \ - g_slist_free (chain->elements); \ - chain->elements = g_slist_prepend (NULL, bin); \ - res = chain; \ - /* set the properties now */ \ - for (walk = assign; walk; walk = walk->next) \ - gst_parse_element_set ((gchar *) walk->data, GST_ELEMENT (bin), graph); \ - g_slist_free (assign); \ - } \ -} G_STMT_END -#define MAKE_LINK(link, _src, _src_name, _src_pads, _sink, _sink_name, _sink_pads) \ -G_STMT_START { \ - link = gst_parse_link_new (); \ - link->src = _src; \ - link->sink = _sink; \ - link->src_name = _src_name; \ - link->sink_name = _sink_name; \ - link->src_pads = _src_pads; \ - link->sink_pads = _sink_pads; \ - link->caps = NULL; \ +/******************************************************************************************* +*** helpers for pipeline-setup +*******************************************************************************************/ + +#define TRY_SETUP_LINK(l) G_STMT_START { \ + if( (!(l)->src.element) && (!(l)->src.name) ){ \ + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link has no source [sink=%s@%p]"), \ + (l)->sink.name ? (l)->sink.name : _(""), \ + (l)->sink.element); \ + gst_parse_free_link (l); \ + }else if( (!(l)->sink.element) && (!(l)->sink.name) ){ \ + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link has no sink [source=%s@%p]"), \ + (l)->src.name ? (l)->src.name :_(""), \ + (l)->src.element); \ + gst_parse_free_link (l); \ + }else{ \ + graph->links = g_slist_append (graph->links, l ); \ + } \ } G_STMT_END -#define MAKE_REF(link, _src, _pads) \ -G_STMT_START { \ - gchar *padname = _src; \ - GSList *pads = _pads; \ - if (padname) { \ - while (*padname != '.') padname++; \ - *padname = '\0'; \ - padname++; \ - if (*padname != '\0') \ - pads = g_slist_prepend (pads, gst_parse_strdup (padname)); \ - } \ - MAKE_LINK (link, NULL, _src, pads, NULL, NULL, NULL); \ -} G_STMT_END +typedef struct { + gchar *src_pad; + gchar *sink_pad; + GstElement *sink; + GstCaps *caps; + gulong signal_id; +} DelayedLink; -static void -gst_parse_free_delayed_set (DelayedSet *set) +typedef struct { + gchar *name; + gchar *value_str; + gulong signal_id; +} DelayedSet; + +static int gst_resolve_reference(reference_t *rr, GstElement *pipeline){ + GstBin *bin; + + if(rr->element) return 0; /* already resolved! */ + if(!rr->name) return -2; /* no chance! */ + + if (GST_IS_BIN (pipeline)){ + bin = GST_BIN (pipeline); + rr->element = gst_bin_get_by_name_recurse_up (bin, rr->name); + } else { + rr->element = strcmp (GST_ELEMENT_NAME (pipeline), rr->name) == 0 ? + gst_object_ref(pipeline) : NULL; + } + if(rr->element) return 0; /* resolved */ + else return -1; /* not found */ +} + +static void gst_parse_free_delayed_set (DelayedSet *set) { g_free(set->name); g_free(set->value_str); @@ -288,8 +268,7 @@ gst_parse_free_delayed_set (DelayedSet *set) static void gst_parse_new_child(GstChildProxy *child_proxy, GObject *object, const gchar * name, gpointer data); -static void -gst_parse_add_delayed_set (GstElement *element, gchar *name, gchar *value_str) +static void gst_parse_add_delayed_set (GstElement *element, gchar *name, gchar *value_str) { DelayedSet *data = g_slice_new0 (DelayedSet); @@ -325,8 +304,7 @@ gst_parse_add_delayed_set (GstElement *element, gchar *name, gchar *value_str) } } -static void -gst_parse_new_child(GstChildProxy *child_proxy, GObject *object, +static void gst_parse_new_child(GstChildProxy *child_proxy, GObject *object, const gchar * name, gpointer data) { DelayedSet *set = (DelayedSet *) data; @@ -385,8 +363,7 @@ error: goto out; } -static void -gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph) +static void gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph) { GParamSpec *pspec = NULL; gchar *pos = value; @@ -474,21 +451,34 @@ error: goto out; } -static inline void -gst_parse_free_link (link_t *link) +static void gst_parse_free_reference (reference_t *rr) { - gst_parse_strfree (link->src_name); - gst_parse_strfree (link->sink_name); - g_slist_foreach (link->src_pads, (GFunc) gst_parse_strfree, NULL); - g_slist_foreach (link->sink_pads, (GFunc) gst_parse_strfree, NULL); - g_slist_free (link->src_pads); - g_slist_free (link->sink_pads); + if(rr->element) gst_object_unref(rr->element); + gst_parse_strfree (rr->name); + g_slist_foreach (rr->pads, (GFunc) gst_parse_strfree, NULL); + g_slist_free (rr->pads); +} + +static void gst_parse_free_link (link_t *link) +{ + gst_parse_free_reference (&(link->src)); + gst_parse_free_reference (&(link->sink)); if (link->caps) gst_caps_unref (link->caps); gst_parse_link_free (link); } -static void -gst_parse_free_delayed_link (DelayedLink *link) +static void gst_parse_free_chain (chain_t *ch) +{ + GSList *walk; + gst_parse_free_reference (&(ch->first)); + gst_parse_free_reference (&(ch->last)); + for(walk=ch->elements;walk;walk=walk->next) + gst_object_unref (walk->data); + g_slist_free (ch->elements); + gst_parse_chain_free (ch); +} + +static void gst_parse_free_delayed_link (DelayedLink *link) { g_free (link->src_pad); g_free (link->sink_pad); @@ -496,8 +486,7 @@ gst_parse_free_delayed_link (DelayedLink *link) g_slice_free (DelayedLink, link); } -static void -gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data) +static void gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data) { DelayedLink *link = data; @@ -564,17 +553,17 @@ gst_parse_perform_delayed_link (GstElement *src, const gchar *src_pad, static gint gst_parse_perform_link (link_t *link, graph_t *graph) { - GstElement *src = link->src; - GstElement *sink = link->sink; - GSList *srcs = link->src_pads; - GSList *sinks = link->sink_pads; + GstElement *src = link->src.element; + GstElement *sink = link->sink.element; + GSList *srcs = link->src.pads; + GSList *sinks = link->sink.pads; g_assert (GST_IS_ELEMENT (src)); g_assert (GST_IS_ELEMENT (sink)); GST_CAT_INFO (GST_CAT_PIPELINE, "linking %s:%s to %s:%s (%u/%u) with caps \"%" GST_PTR_FORMAT "\"", - GST_ELEMENT_NAME (src), link->src_name ? link->src_name : "(any)", - GST_ELEMENT_NAME (sink), link->sink_name ? link->sink_name : "(any)", + GST_ELEMENT_NAME (src), link->src.name ? link->src.name : "(any)", + GST_ELEMENT_NAME (sink), link->sink.name ? link->sink.name : "(any)", g_slist_length (srcs), g_slist_length (sinks), link->caps); if (!srcs || !sinks) { @@ -592,7 +581,7 @@ gst_parse_perform_link (link_t *link, graph_t *graph) } } } - if (g_slist_length (link->src_pads) != g_slist_length (link->sink_pads)) { + if (g_slist_length (link->src.pads) != g_slist_length (link->sink.pads)) { goto error; } while (srcs && sinks) { @@ -631,27 +620,44 @@ static int yyerror (void *scanner, graph_t *graph, const char *s); %} %union { - gchar *s; - chain_t *c; - link_t *l; - GstElement *e; - GSList *p; - graph_t *g; + gchar *ss; + chain_t *cc; + link_t *ll; + reference_t rr; + GstElement *ee; + GSList *pp; + graph_t *gg; } -%token <s> PARSE_URL -%token <s> IDENTIFIER -%left <s> REF PADREF BINREF -%token <s> ASSIGNMENT -%token <s> LINK +/* No grammar ambiguities expected, FAIL otherwise */ +%expect 0 + +%token <ss> PARSE_URL +%token <ss> IDENTIFIER +%left <ss> REF PADREF BINREF +%token <ss> ASSIGNMENT +%token <ss> LINK + +%type <ss> binopener +%type <gg> graph +%type <cc> chain bin chainlist openchain elementary +%type <rr> reference +%type <ll> link +%type <ee> element +%type <pp> morepads pads assignments + +%destructor { gst_parse_strfree ($$); } <ss> +%destructor { if($$) + gst_parse_free_chain($$); } <cc> +%destructor { gst_parse_free_link ($$); } <ll> +%destructor { gst_parse_free_reference(&($$));} <rr> +%destructor { gst_object_unref ($$); } <ee> +%destructor { GSList *walk; + for(walk=$$;walk;walk=walk->next) + gst_parse_strfree (walk->data); + g_slist_free ($$); } <pp> + -%type <g> graph -%type <c> chain bin -%type <l> reference -%type <l> linkpart link -%type <p> linklist -%type <e> element -%type <p> padlist pads assignments %left '(' ')' %left ',' @@ -666,17 +672,19 @@ static int yyerror (void *scanner, graph_t *graph, const char *s); %start graph %% +/************************************************************* +* Grammar explanation: +* _element_s are specified by an identifier of their type. +* a name can be give in the optional property-assignments +* coffeeelement +* fakesrc name=john +* identity silence=false name=frodo +* (cont'd) +**************************************************************/ element: IDENTIFIER { $$ = gst_element_factory_make ($1, NULL); if ($$ == NULL) { - ADD_MISSING_ELEMENT (graph, $1); + add_missing_element(graph, $1); SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), $1); - /* if FATAL_ERRORS flag is set, we don't have to worry about backwards - * compatibility and can continue parsing and check for other missing - * elements */ - if ((graph->flags & GST_PARSE_FLAG_FATAL_ERRORS) == 0) { - gst_parse_strfree ($1); - YYERROR; - } } gst_parse_strfree ($1); } @@ -684,211 +692,307 @@ element: IDENTIFIER { $$ = gst_element_factory_make ($1, NULL); $$ = $1; } ; -assignments: /* NOP */ { $$ = NULL; } - | assignments ASSIGNMENT { $$ = g_slist_prepend ($1, $2); } + +/************************************************************* +* Grammar explanation: (cont'd) +* a graph has (pure) _element_s, _bin_s and _link_s. +* since bins are special elements, bins and elements can +* be generalized as _elementary_. +* The construction of _bin_s will be discussed later. +* (cont'd) +* +**************************************************************/ +elementary: + element { $$ = gst_parse_chain_new (); + /* g_print ("@%p: CHAINing elementary\n", $$); */ + $$->first.element = $1? gst_object_ref($1) : NULL; + $$->last.element = $1? gst_object_ref($1) : NULL; + $$->first.name = $$->last.name = NULL; + $$->first.pads = $$->last.pads = NULL; + $$->elements = $1 ? g_slist_prepend (NULL, $1) : NULL; + } + | bin { $$=$1; } ; -bin: '(' assignments chain ')' { GST_BIN_MAKE ($$, "bin", $3, $2, no_free); } - | BINREF assignments chain ')' { GST_BIN_MAKE ($$, $1, $3, $2, gst_parse_strfree); - gst_parse_strfree ($1); + +/************************************************************* +* Grammar explanation: (cont'd) +* a _chain_ is a list of _elementary_s that have _link_s inbetween +* which are represented through infix-notation. +* +* fakesrc ! sometransformation ! fakesink +* +* every _link_ can be augmented with _pads_. +* +* coffeesrc .sound ! speakersink +* multisrc .movie,ads ! .projector,smallscreen multisink +* +* and every _link_ can be setup to filter media-types +* mediasrc ! audio/x-raw, signed=TRUE ! stereosink +* +* User HINT: +* if the lexer does not recognize your media-type it +* will make it an element name. that results in errors +* like +* NO SUCH ELEMENT: no element audio7x-raw +* '7' vs. '/' in https://en.wikipedia.org/wiki/QWERTZ +* +* Parsing HINT: +* in the parser we need to differ between chains that can +* be extended by more elementaries (_openchain_) and others +* that are syntactically closed (handled later in this file). +* (e.g. fakesrc ! sinkreferencename.padname) +**************************************************************/ +chain: openchain { $$=$1; + if($$->last.name){ + SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX, + _("unexpected reference \"%s\" - ignoring"), $$->last.name); + gst_parse_strfree($$->last.name); + $$->last.name=NULL; + } + if($$->last.pads){ + SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX, + _("unexpected pad-reference \"%s\" - ignoring"), (gchar*)$$->last.pads->data); + g_slist_foreach ($$->last.pads, (GFunc) gst_parse_strfree, NULL); + g_slist_free ($$->last.pads); + $$->last.pads=NULL; + } } - | BINREF assignments ')' { GST_BIN_MAKE ($$, $1, NULL, $2, gst_parse_strfree); - gst_parse_strfree ($1); + ; + +openchain: + elementary pads { $$=$1; + $$->last.pads = g_slist_concat ($$->last.pads, $2); + /* g_print ("@%p@%p: FKI elementary pads\n", $1, $$->last.pads); */ } - | BINREF assignments error ')' { GST_BIN_MAKE ($$, $1, NULL, $2, gst_parse_strfree); - gst_parse_strfree ($1); + | openchain link pads elementary pads + { + $2->src = $1->last; + $2->sink = $4->first; + $2->sink.pads = g_slist_concat ($3, $2->sink.pads); + TRY_SETUP_LINK($2); + $4->first = $1->first; + $4->elements = g_slist_concat ($1->elements, $4->elements); + gst_parse_chain_free($1); + $$ = $4; + $$->last.pads = g_slist_concat ($$->last.pads, $5); } + ; -pads: PADREF { $$ = g_slist_prepend (NULL, $1); } - | PADREF padlist { $$ = $2; - $$ = g_slist_prepend ($$, $1); +link: LINK { $$ = gst_parse_link_new (); + $$->src.element = NULL; + $$->sink.element = NULL; + $$->src.name = NULL; + $$->sink.name = NULL; + $$->src.pads = NULL; + $$->sink.pads = NULL; + $$->caps = NULL; + if ($1) { + $$->caps = gst_caps_from_string ($1); + if ($$->caps == NULL) + SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $1); + gst_parse_strfree ($1); + } } ; -padlist: ',' IDENTIFIER { $$ = g_slist_prepend (NULL, $2); } - | ',' IDENTIFIER padlist { $$ = g_slist_prepend ($3, $2); } +pads: /* NOP */ { $$ = NULL; } + | PADREF morepads { $$ = $2; + $$ = g_slist_prepend ($$, $1); + } ; - -reference: REF { MAKE_REF ($$, $1, NULL); } - | REF padlist { MAKE_REF ($$, $1, $2); } +morepads: /* NOP */ { $$ = NULL; } + | ',' IDENTIFIER morepads { $$ = g_slist_prepend ($3, $2); } ; -linkpart: reference { $$ = $1; } - | pads { MAKE_REF ($$, NULL, $1); } - | /* NOP */ { MAKE_REF ($$, NULL, NULL); } +/************************************************************* +* Grammar explanation: (cont'd) +* the first and last elements of a _chain_ can be give +* as URL. This creates special elements that fit the URL. +* +* fakesrc ! http://fake-sink.org +* http://somesource.org ! fakesink +**************************************************************/ + +chain: openchain link PARSE_URL { GstElement *element = + gst_element_make_from_uri (GST_URI_SINK, $3, NULL, NULL); + /* FIXME: get and parse error properly */ + if (!element) { + SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + _("no sink element for URI \"%s\""), $3); + } + $$ = $1; + $2->sink.element = element?gst_object_ref(element):NULL; + $2->src = $1->last; + TRY_SETUP_LINK($2); + $$->last.element = NULL; + $$->last.name = NULL; + $$->last.pads = NULL; + if(element) $$->elements = g_slist_append ($$->elements, element); + g_free ($3); + } ; - -link: linkpart LINK linkpart { $$ = $1; - if ($2) { - $$->caps = gst_caps_from_string ($2); - if ($$->caps == NULL) - SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $2); - gst_parse_strfree ($2); +openchain: + PARSE_URL { GstElement *element = + gst_element_make_from_uri (GST_URI_SRC, $1, NULL, NULL); + /* FIXME: get and parse error properly */ + if (!element) { + SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + _("no source element for URI \"%s\""), $1); } - $$->sink_name = $3->src_name; - $$->sink_pads = $3->src_pads; - gst_parse_link_free ($3); + $$ = gst_parse_chain_new (); + /* g_print ("@%p: CHAINing srcURL\n", $$); */ + $$->first.element = NULL; + $$->first.name = NULL; + $$->first.pads = NULL; + $$->last.element = element ? gst_object_ref(element):NULL; + $$->last.name = NULL; + $$->last.pads = NULL; + $$->elements = element ? g_slist_prepend (NULL, element) : NULL; + g_free($1); } ; -linklist: link { $$ = g_slist_prepend (NULL, $1); } - | link linklist { $$ = g_slist_prepend ($2, $1); } - | linklist error { $$ = $1; } - ; -chain: element { $$ = gst_parse_chain_new (); - $$->first = $$->last = $1; - $$->front = $$->back = NULL; - $$->elements = g_slist_prepend (NULL, $1); +/************************************************************* +* Grammar explanation: (cont'd) +* the first and last elements of a _chain_ can be linked +* to a named _reference_ (with optional pads). +* +* fakesrc ! nameOfSinkElement. +* fakesrc ! nameOfSinkElement.Padname +* fakesrc ! nameOfSinkElement.Padname, anotherPad +* nameOfSource.Padname ! fakesink +**************************************************************/ + +chain: openchain link reference { $$ = $1; + $2->sink= $3; + $2->src = $1->last; + TRY_SETUP_LINK($2); + $$->last.element = NULL; + $$->last.name = NULL; + $$->last.pads = NULL; } - | bin { $$ = $1; } - | chain chain { if ($1->back && $2->front) { - if (!$1->back->sink_name) { - SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element")); - gst_parse_free_link ($1->back); - } else { - graph->links = g_slist_prepend (graph->links, $1->back); - } - if (!$2->front->src_name) { - SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without sink element")); - gst_parse_free_link ($2->front); - } else { - graph->links = g_slist_prepend (graph->links, $2->front); - } - $1->back = NULL; - } else if ($1->back) { - if (!$1->back->sink_name) { - $1->back->sink = $2->first; - } - } else if ($2->front) { - if (!$2->front->src_name) { - $2->front->src = $1->last; - } - $1->back = $2->front; - } + ; - if ($1->back) { - graph->links = g_slist_prepend (graph->links, $1->back); - } - $1->last = $2->last; - $1->back = $2->back; - $1->elements = g_slist_concat ($1->elements, $2->elements); - if ($2) - gst_parse_chain_free ($2); - $$ = $1; + +openchain: + reference { $$ = gst_parse_chain_new (); + $$->last=$1; + $$->first.element = NULL; + $$->first.name = NULL; + $$->first.pads = NULL; + $$->elements = NULL; } - | chain linklist { GSList *walk; - if ($1->back) { - $2 = g_slist_prepend ($2, $1->back); - $1->back = NULL; - } else { - if (!((link_t *) $2->data)->src_name) { - ((link_t *) $2->data)->src = $1->last; - } - } - for (walk = $2; walk; walk = walk->next) { - link_t *link = (link_t *) walk->data; - if (!link->sink_name && walk->next) { - SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without sink element")); - gst_parse_free_link (link); - } else if (!link->src_name && !link->src) { - SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element")); - gst_parse_free_link (link); - } else { - if (walk->next) { - graph->links = g_slist_prepend (graph->links, link); - } else { - $1->back = link; - } - } + ; +reference: REF morepads { + gchar *padname = $1; + GSList *pads = $2; + if (padname) { + while (*padname != '.') padname++; + *padname = '\0'; + padname++; + if (*padname != '\0') + pads = g_slist_prepend (pads, gst_parse_strdup (padname)); } - g_slist_free ($2); - $$ = $1; + $$.element=NULL; + $$.name=$1; + $$.pads=pads; } - | chain error { $$ = $1; } - | link chain { if ($2->front) { - if (!$2->front->src_name) { - SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element")); - gst_parse_free_link ($2->front); - } else { - graph->links = g_slist_prepend (graph->links, $2->front); - } - } - if (!$1->sink_name) { - $1->sink = $2->first; + ; + + +/************************************************************* +* Grammar explanation: (cont'd) +* a _chainlist_ is just a list of _chain_s. +* +* You can specify _link_s with named +* _reference_ on each side. That +* works already after the explanations above. +* someSourceName.Pad ! someSinkName. +* someSourceName.Pad,anotherPad ! someSinkName.Apad,Bpad +* +* If a syntax error occurs, the already finished _chain_s +* and _links_ are kept intact. +*************************************************************/ + +chainlist: /* NOP */ { $$ = NULL; } + | chainlist chain { if ($1){ + gst_parse_free_reference(&($1->last)); + gst_parse_free_reference(&($2->first)); + $2->first = $1->first; + $2->elements = g_slist_concat ($1->elements, $2->elements); + gst_parse_chain_free ($1); } - $2->front = $1; $$ = $2; } - | PARSE_URL chain { $$ = $2; - if ($$->front) { - GstElement *element = - gst_element_make_from_uri (GST_URI_SRC, $1, NULL, NULL); - /* FIXME: get and parse error properly */ - if (!element) { - SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, - _("no source element for URI \"%s\""), $1); - } else { - $$->front->src = element; - graph->links = g_slist_prepend ( - graph->links, $$->front); - $$->front = NULL; - $$->elements = g_slist_prepend ($$->elements, element); - } - } else { - SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, - _("no element to link URI \"%s\" to"), $1); - } - g_free ($1); + | chainlist error { $$=$1; + GST_CAT_DEBUG (GST_CAT_PIPELINE,"trying to recover from syntax error"); + SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX, _("syntax error")); } - | link PARSE_URL { GstElement *element = - gst_element_make_from_uri (GST_URI_SINK, $2, NULL, NULL); - /* FIXME: get and parse error properly */ - if (!element) { + ; + +/************************************************************* +* Grammar explanation: (cont'd) +* _bins_ +*************************************************************/ + + +assignments: /* NOP */ { $$ = NULL; } + | ASSIGNMENT assignments { $$ = g_slist_prepend ($2, $1); } + ; + +binopener: '(' { $$ = gst_parse_strdup(_("bin")); } + | BINREF { $$ = $1; } + ; +bin: binopener assignments chainlist ')' { + chain_t *chain = $3; + GSList *walk; + GstBin *bin = (GstBin *) gst_element_factory_make ($1, NULL); + if (!chain) { + SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY_BIN, + _("specified empty bin \"%s\", not allowed"), $1); + chain = gst_parse_chain_new (); + chain->first.element = chain->last.element = NULL; + chain->first.name = chain->last.name = NULL; + chain->first.pads = chain->last.pads = NULL; + chain->elements = NULL; + } + if (!bin) { + add_missing_element(graph, $1); SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, - _("no sink element for URI \"%s\""), $2); - gst_parse_link_free ($1); - g_free ($2); - YYERROR; - } else if ($1->sink_name || $1->sink_pads) { - gst_object_unref (element); - SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, - _("could not link sink element for URI \"%s\""), $2); - gst_parse_link_free ($1); - g_free ($2); - YYERROR; + _("no bin \"%s\", unpacking elements"), $1); + /* clear property-list */ + g_slist_foreach ($2, (GFunc) gst_parse_strfree, NULL); + g_slist_free ($2); + $2 = NULL; } else { - $$ = gst_parse_chain_new (); - $$->first = $$->last = element; - $$->front = $1; - $$->front->sink = element; - $$->elements = g_slist_prepend (NULL, element); + for (walk = chain->elements; walk; walk = walk->next ) + gst_bin_add (bin, GST_ELEMENT (walk->data)); + g_slist_free (chain->elements); + chain->elements = g_slist_prepend (NULL, bin); } - g_free ($2); + $$ = chain; + /* set the properties now + * HINT: property-list cleared above, if bin==NULL + */ + for (walk = $2; walk; walk = walk->next) + gst_parse_element_set ((gchar *) walk->data, + GST_ELEMENT (bin), graph); + g_slist_free ($2); + gst_parse_strfree ($1); } ; -graph: /* NOP */ { SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed")); - $$ = graph; - } - | chain { $$ = graph; - if ($1->front) { - if (!$1->front->src_name) { - SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element")); - gst_parse_free_link ($1->front); - } else { - $$->links = g_slist_prepend ($$->links, $1->front); - } - $1->front = NULL; - } - if ($1->back) { - if (!$1->back->sink_name) { - SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without sink element")); - gst_parse_free_link ($1->back); - } else { - $$->links = g_slist_prepend ($$->links, $1->back); - } - $1->back = NULL; - } + +/************************************************************* +* Grammar explanation: (cont'd) +* _graph_ +*************************************************************/ + +graph: chainlist { $$ = graph; $$->chain = $1; + if(!$1) { + SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed")); + } } ; @@ -929,11 +1033,13 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx, __strings = __chains = __links = 0; #endif /* __GST_PARSE_TRACE */ + /* g_print("Now scanning: %s\n", str); */ + dstr = g_strdup (str); priv_gst_parse_yylex_init (&scanner); priv_gst_parse_yy_scan_string (dstr, scanner); -#ifndef YYDEBUG +#if YYDEBUG yydebug = 1; #endif @@ -953,17 +1059,25 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx, g.chain ? g_slist_length (g.chain->elements) : 0, g_slist_length (g.links)); - if (!g.chain) { - ret = NULL; - } else if (!g.chain->elements->next) { - /* only one toplevel element */ - ret = (GstElement *) g.chain->elements->data; - g_slist_free (g.chain->elements); - if (GST_IS_BIN (ret)) - bin = GST_BIN (ret); - gst_parse_chain_free (g.chain); - } else { - /* put all elements in our bin */ + /* ensure chain is not NULL */ + if (!g.chain){ + g.chain=gst_parse_chain_new (); + g.chain->elements=NULL; + g.chain->first.element=NULL; + g.chain->first.name=NULL; + g.chain->first.pads=NULL; + g.chain->last.element=NULL; + g.chain->last.name=NULL; + g.chain->last.pads=NULL; + }; + + /* ensure elements is not empty */ + if(!g.chain->elements){ + g.chain->elements= g_slist_prepend (NULL, NULL); + }; + + /* put all elements in our bin if necessary */ + if(g.chain->elements->next){ bin = GST_BIN (gst_element_factory_make ("pipeline", NULL)); g_assert (bin); @@ -971,56 +1085,49 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx, if (walk->data != NULL) gst_bin_add (bin, GST_ELEMENT (walk->data)); } - g_slist_free (g.chain->elements); - ret = GST_ELEMENT (bin); - gst_parse_chain_free (g.chain); - } + g.chain->elements = g_slist_prepend (NULL, bin); + } + + ret = (GstElement *) g.chain->elements->data; + g_slist_free (g.chain->elements); + g.chain->elements=NULL; + if (GST_IS_BIN (ret)) + bin = GST_BIN (ret); + gst_parse_free_chain (g.chain); + g.chain = NULL; - /* remove links */ + + /* resolve and perform links */ for (walk = g.links; walk; walk = walk->next) { link_t *l = (link_t *) walk->data; - if (!l->src) { - if (l->src_name) { - if (bin) { - l->src = gst_bin_get_by_name_recurse_up (bin, l->src_name); - if (l->src) - gst_object_unref (l->src); - } else { - l->src = strcmp (GST_ELEMENT_NAME (ret), l->src_name) == 0 ? ret : NULL; - } - } - if (!l->src) { - if (l->src_name) { + int err; + err=gst_resolve_reference( &(l->src), ret); + if (err) { + if(-1==err){ SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, - "No element named \"%s\" - omitting link", l->src_name); - } else { + "No src-element named \"%s\" - omitting link", l->src.name); + }else{ /* probably a missing element which we've handled already */ - } - gst_parse_free_link (l); - continue; - } + SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + "No src-element found - omitting link"); + } + gst_parse_free_link (l); + continue; } - if (!l->sink) { - if (l->sink_name) { - if (bin) { - l->sink = gst_bin_get_by_name_recurse_up (bin, l->sink_name); - if (l->sink) - gst_object_unref (l->sink); - } else { - l->sink = strcmp (GST_ELEMENT_NAME (ret), l->sink_name) == 0 ? ret : NULL; - } - } - if (!l->sink) { - if (l->sink_name) { + + err=gst_resolve_reference( &(l->sink), ret); + if (err) { + if(-1==err){ SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, - "No element named \"%s\" - omitting link", l->sink_name); - } else { + "No sink-element named \"%s\" - omitting link", l->src.name); + }else{ /* probably a missing element which we've handled already */ - } - gst_parse_free_link (l); - continue; - } + SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, + "No sink-element found - omitting link"); + } + gst_parse_free_link (l); + continue; } gst_parse_perform_link (l, &g); } @@ -1041,9 +1148,8 @@ out: error1: if (g.chain) { - g_slist_foreach (g.chain->elements, (GFunc)gst_object_unref, NULL); - g_slist_free (g.chain->elements); - gst_parse_chain_free (g.chain); + gst_parse_free_chain (g.chain); + g.chain=NULL; } g_slist_foreach (g.links, (GFunc)gst_parse_free_link, NULL); diff --git a/gst/parse/parse.l b/gst/parse/parse.l index bcd6527..53afba8 100644 --- a/gst/parse/parse.l +++ b/gst/parse/parse.l @@ -11,6 +11,22 @@ #include "../gsturi.h" #include "grammar.tab.h" +#ifdef malloc +#undef malloc +#endif + +#ifdef free +#undef free +#endif + +#ifdef realloc +#undef realloc +#endif + +#define malloc g_malloc +#define free g_free +#define realloc g_realloc + /* Override the default ECHO so as to avoid fortify warnings. Ignore the embedded-NUL case for now. We know yytext is NUL-terminated. */ #define ECHO g_fprintf(yyout, "%s", yytext) @@ -73,7 +89,7 @@ _link ("!"[[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*) {_assignment} { /* "=" */ PRINT ("ASSIGNMENT: %s", yytext); - yylval->s = gst_parse_strdup (yytext); + yylval->ss = gst_parse_strdup (yytext); BEGIN (INITIAL); return ASSIGNMENT; } @@ -81,14 +97,14 @@ _link ("!"[[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*) {_padref} { yytext++; PRINT ("PADREF: %s", yytext); - yylval->s = gst_parse_strdup (yytext); + yylval->ss = gst_parse_strdup (yytext); BEGIN (INITIAL); return PADREF; } {_ref} { PRINT ("REF: %s", yytext); - yylval->s = gst_parse_strdup (yytext); + yylval->ss = gst_parse_strdup (yytext); BEGIN (INITIAL); return REF; } @@ -98,14 +114,14 @@ _link ("!"[[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*) while (!g_ascii_isspace (*pos) && (*pos != '.')) pos++; *pos = '\0'; PRINT ("BINREF: %s", yytext); - yylval->s = gst_parse_strdup (yytext); + yylval->ss = gst_parse_strdup (yytext); BEGIN (INITIAL); return BINREF; } {_identifier} { PRINT ("IDENTIFIER: %s", yytext); - yylval->s = gst_parse_strdup (yytext); + yylval->ss = gst_parse_strdup (yytext); BEGIN (INITIAL); return IDENTIFIER; } @@ -116,22 +132,22 @@ _link ("!"[[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*) c++; if (*c) { while (g_ascii_isspace (*c)) c++; - c = yylval->s = gst_parse_strdup (c); + c = yylval->ss = gst_parse_strdup (c); while (*c) c++; if (*--c != '!') g_assert_not_reached (); while (g_ascii_isspace (*--c)); *++c = '\0'; } else { - yylval->s = NULL; + yylval->ss = NULL; } BEGIN (INITIAL); return LINK; } {_url} { PRINT ("URL: %s", yytext); - yylval->s = g_strdup (yytext); - gst_parse_unescape (yylval->s); + yylval->ss = g_strdup (yytext); + gst_parse_unescape (yylval->ss); BEGIN (INITIAL); return PARSE_URL; } diff --git a/gst/parse/types.h b/gst/parse/types.h index 79a14c6..fbeaf20 100644 --- a/gst/parse/types.h +++ b/gst/parse/types.h @@ -6,21 +6,21 @@ #include "../gstparse.h" typedef struct { - GstElement *src; - GstElement *sink; - gchar *src_name; - gchar *sink_name; - GSList *src_pads; - GSList *sink_pads; + GstElement *element; + gchar *name; + GSList *pads; +} reference_t; + +typedef struct { + reference_t src; + reference_t sink; GstCaps *caps; } link_t; typedef struct { GSList *elements; - GstElement *first; - GstElement *last; - link_t *front; - link_t *back; + reference_t first; + reference_t last; } chain_t; typedef struct _graph_t graph_t; @@ -38,17 +38,21 @@ struct _graph_t { * doesn't really work. * This is not safe from reentrance issues, but that doesn't matter as long as * we lock a mutex before parsing anyway. + * + * FIXME: Disable this for now for the above reasons */ +#if 0 #ifdef GST_DEBUG_ENABLED # define __GST_PARSE_TRACE #endif +#endif #ifdef __GST_PARSE_TRACE G_GNUC_INTERNAL gchar *__gst_parse_strdup (gchar *org); G_GNUC_INTERNAL void __gst_parse_strfree (gchar *str); -G_GNUC_INTERNAL link_t *__gst_parse_link_new (); +G_GNUC_INTERNAL link_t *__gst_parse_link_new (void); G_GNUC_INTERNAL void __gst_parse_link_free (link_t *data); -G_GNUC_INTERNAL chain_t *__gst_parse_chain_new (); +G_GNUC_INTERNAL chain_t *__gst_parse_chain_new (void); G_GNUC_INTERNAL void __gst_parse_chain_free (chain_t *data); # define gst_parse_strdup __gst_parse_strdup # define gst_parse_strfree __gst_parse_strfree @@ -59,10 +63,10 @@ G_GNUC_INTERNAL void __gst_parse_chain_free (chain_t *data); #else /* __GST_PARSE_TRACE */ # define gst_parse_strdup g_strdup # define gst_parse_strfree g_free -# define gst_parse_link_new() g_new0 (link_t, 1) -# define gst_parse_link_free g_free -# define gst_parse_chain_new() g_new0 (chain_t, 1) -# define gst_parse_chain_free g_free +# define gst_parse_link_new() g_slice_new0 (link_t) +# define gst_parse_link_free(l) g_slice_free (link_t, l) +# define gst_parse_chain_new() g_slice_new0 (chain_t) +# define gst_parse_chain_free(c) g_slice_free (chain_t, c) #endif /* __GST_PARSE_TRACE */ static inline void diff --git a/gst/printf/Makefile.in b/gst/printf/Makefile.in index 895cb68..092dcea 100644 --- a/gst/printf/Makefile.in +++ b/gst/printf/Makefile.in @@ -88,7 +88,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \ $(top_srcdir)/common/m4/as-compiler-flag.m4 \ $(top_srcdir)/common/m4/as-docbook.m4 \ $(top_srcdir)/common/m4/as-libtool.m4 \ - $(top_srcdir)/common/m4/as-scrub-include.m4 \ $(top_srcdir)/common/m4/as-version.m4 \ $(top_srcdir)/common/m4/ax_create_stdint_h.m4 \ $(top_srcdir)/common/m4/gst-arch.m4 \ |