diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index a8b0dfe3c1..70f3c8555f 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -1537,6 +1537,11 @@ gst_static_caps_get_type GST_PARAM_CONTROLLABLE GST_PARAM_USER_SHIFT +GST_PARAM_MUTABLE_PAUSED +GST_PARAM_MUTABLE_PLAYING +GST_PARAM_MUTABLE_READY + +gst_param_spec_is_mutable GstParamSpecFraction diff --git a/gst/gstparamspecs.c b/gst/gstparamspecs.c index e75a944322..1e3439c3d0 100644 --- a/gst/gstparamspecs.c +++ b/gst/gstparamspecs.c @@ -205,3 +205,43 @@ gst_param_spec_fraction (const gchar * name, const gchar * nick, return pspec; } + +/** + * gst_param_spec_is_mutable + * @param_spec: a GParamSpec representing a property + * @element: the GstElement of the property to be modified + * + * Checks if an object property for the GstElement given in @element + * may be modified given the current state of @element. + * + * Returns: TRUE if the property may be modified + */ +gboolean +gst_param_spec_is_mutable (GParamSpec * param_spec, GstElement * element) +{ + gboolean ret = TRUE; + GstState state; + + if (param_spec->flags & GST_PARAM_MUTABLE_PLAYING) { + return TRUE; + } + + GST_OBJECT_LOCK (element); + state = GST_STATE (element); + if (param_spec->flags & GST_PARAM_MUTABLE_PAUSED) { + if (state > GST_STATE_PAUSED) { + ret = FALSE; + } + } else if (param_spec->flags & GST_PARAM_MUTABLE_READY) { + if (state > GST_STATE_READY) { + ret = FALSE; + } + } else { + if (state > GST_STATE_NULL) { + ret = FALSE; + } + } + GST_OBJECT_UNLOCK (element); + + return ret; +} diff --git a/gst/gstparamspecs.h b/gst/gstparamspecs.h index 079ff4d17a..86d066f262 100644 --- a/gst/gstparamspecs.h +++ b/gst/gstparamspecs.h @@ -20,6 +20,7 @@ #ifndef __GST_PARAMSPECS_H__ #define __GST_PARAMSPECS_H__ +#include #include G_BEGIN_DECLS @@ -34,6 +35,32 @@ G_BEGIN_DECLS */ #define GST_PARAM_CONTROLLABLE (1 << (G_PARAM_USER_SHIFT + 1)) +/** + * GST_PARAM_MUTABLE_READY: + * + * Use this flag on GObject properties of GstElements to indicate that + * they can be changed when the element is in the READY or lower state. + */ +#define GST_PARAM_MUTABLE_READY (1 << (G_PARAM_USER_SHIFT + 2)) + +/** + * GST_PARAM_MUTABLE_PAUSED: + * + * Use this flag on GObject properties of GstElements to indicate that + * they can be changed when the element is in the PAUSED or lower state. + * This flag implies GST_PARAM_MUTABLE_READY. + */ +#define GST_PARAM_MUTABLE_PAUSED (1 << (G_PARAM_USER_SHIFT + 3)) + +/** + * GST_PARAM_MUTABLE_PLAYING: + * + * Use this flag on GObject properties of GstElements to indicate that + * they can be changed when the element is in the PLAYING or lower state. + * This flag implies GST_PARAM_MUTABLE_PAUSED. + */ +#define GST_PARAM_MUTABLE_PLAYING (1 << (G_PARAM_USER_SHIFT + 4)) + /** * GST_PARAM_USER_SHIFT: * @@ -90,6 +117,9 @@ GParamSpec * gst_param_spec_fraction (const gchar * name, gint default_num, gint default_denom, GParamFlags flags); +gboolean gst_param_spec_is_mutable (GParamSpec *param_spec, + GstElement *element); + G_END_DECLS #endif /* __GST_PARAMSPECS_H__ */ diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c index 3a55a7e922..2c03167686 100644 --- a/plugins/elements/gstfilesrc.c +++ b/plugins/elements/gstfilesrc.c @@ -248,15 +248,19 @@ gst_file_src_class_init (GstFileSrcClass * klass) g_object_class_install_property (gobject_class, ARG_LOCATION, g_param_spec_string ("location", "File Location", "Location of the file to read", NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); g_object_class_install_property (gobject_class, ARG_MMAPSIZE, g_param_spec_ulong ("mmapsize", "mmap() Block Size", "Size in bytes of mmap()d regions", 0, G_MAXULONG, DEFAULT_MMAPSIZE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_PLAYING)); g_object_class_install_property (gobject_class, ARG_TOUCH, g_param_spec_boolean ("touch", "Touch mapped region read data", "Touch mmapped data regions to force them to be read from disk", - DEFAULT_TOUCH, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + DEFAULT_TOUCH, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_PLAYING)); /** * GstFileSrc:use-mmap * @@ -278,12 +282,14 @@ gst_file_src_class_init (GstFileSrcClass * klass) g_object_class_install_property (gobject_class, ARG_USEMMAP, g_param_spec_boolean ("use-mmap", "Use mmap to read data", "Whether to use mmap() instead of read()", - DEFAULT_USEMMAP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + DEFAULT_USEMMAP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); g_object_class_install_property (gobject_class, ARG_SEQUENTIAL, g_param_spec_boolean ("sequential", "Optimise for sequential mmap access", "Whether to use madvise to hint to the kernel that access to " "mmap pages will be sequential", - DEFAULT_SEQUENTIAL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + DEFAULT_SEQUENTIAL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_PLAYING)); gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_file_src_finalize); @@ -383,6 +389,11 @@ gst_file_src_set_property (GObject * object, guint prop_id, src = GST_FILE_SRC (object); + if (!gst_param_spec_is_mutable (pspec, GST_ELEMENT (src))) { + GST_WARNING_OBJECT (src, "attempting to change property in wrong state"); + return; + } + switch (prop_id) { case ARG_LOCATION: gst_file_src_set_location (src, g_value_get_string (value));