diff --git a/ChangeLog b/ChangeLog index 7190f9024b..23b6ef33b5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2006-01-31 Stefan Kost + + * docs/manual/advanced-dparams.xml: + * docs/pwg/advanced-dparams.xml: + more dparam docs + * gst/gstindex.c: + fix docs + * libs/gst/controller/lib.c: (gst_controller_init): + init just once + 2006-01-31 Thomas Vander Stichele * gst/gstelement.c: (gst_element_message_full): diff --git a/docs/manual/advanced-dparams.xml b/docs/manual/advanced-dparams.xml index fc88098144..e0ad3a10b5 100644 --- a/docs/manual/advanced-dparams.xml +++ b/docs/manual/advanced-dparams.xml @@ -13,7 +13,7 @@ This subsystem is contained within the - gstcontrol library. + gstcontroller library. You need to include the header in your application's source file: @@ -32,17 +32,18 @@ ... - gst_init(&argc,&argv); - gst_controller_init(&argc,&argv); + gst_init (&argc, &argv); + gst_controller_init (&argc, &argv); ... - Setting up parameters + Setting up parameter control - It makes not sense for all GObject parameter to be real-time controlled. - Therefore the first step is to mark controllable parameters. + The first step is to select the parameters that should be controlled. + This returns a controller object that is needed to further adjust the + behaviour. controller = g_object_control_properties(object, "prop1", "prop2",...); diff --git a/docs/pwg/advanced-dparams.xml b/docs/pwg/advanced-dparams.xml index 5e7abcc1a1..800ae30221 100644 --- a/docs/pwg/advanced-dparams.xml +++ b/docs/pwg/advanced-dparams.xml @@ -5,343 +5,60 @@ Supporting Dynamic Parameters Sometimes object properties are not powerful enough to control the - parameters that affect the behaviour of your element. When this is the case - you can expose these parameters as Dynamic Parameters which can be - manipulated by any Dynamic Parameters aware application. + parameters that affect the behaviour of your element. + When this is the case you can mark these parameters as beeing Controllable. + Aware appliations can use the controller subsystem to dynamically adjust + the property values over time. - - Throughout this section, the term dparams will be used - as an abbreviation for "Dynamic Parameters". - - - - Comparing Dynamic Parameters with GObject Properties - - Your first exposure to dparams may be to convert an existing element from - using object properties to using dparams. The following table gives an - overview of the difference between these approaches. The significance of - these differences should become apparent later on. - - - - - - - Object Properties - Dynamic Parameters - - - - - Parameter definition - Class level at compile time - Any level at run time - - - Getting and setting - Implemented by element subclass as functions - Handled entirely by dparams subsystem - - - Extra objects required - None - all functionality is derived from base GObject - Element needs to create and store a GstDParamManager at object creation - - - Frequency and resolution of updates - Object properties will only be updated between calls to _get, _chain or _loop - dparams can be updated at any rate independent of calls to _get, _chain or _loop up to sample-level accuracy - - - - - Getting Started - The dparams subsystem is contained within the - gstcontrol library. You need to include the header in + The controller subsystem is contained within the + gstcontroller library. You need to include the header in your element's source file: - #include <gst/control/control.h> +... +#include <gst/gst.h> +#include <gst/controller/gstcontroller.h> +... - Even though the gstcontrol library may be linked into - the host application, you should make sure it is loaded in your + Even though the gstcontroller library may be linked into + the host application, you should make sure it is initialized in your plugin_init function: static gboolean - plugin_init (GModule *module, GstPlugin *plugin) + plugin_init (GstPlugin *plugin) { ... - - /* load dparam support library */ - if (!gst_library_load ("gstcontrol")) - { - gst_info ("example: could not load support library: 'gstcontrol'\n"); - return FALSE; - } - + /* initialize library */ + gst_controller_init (NULL, NULL); ... } - - You need to store an instance of GstDParamManager in - your element's struct: + It makes not sense for all GObject parameter to be real-time controlled. + Therefore the next step is to mark controllable parameters. + This is done by using the special flag GST_PARAM_CONTROLLABLE. + when setting up GObject params in the _class_init method. - struct _GstExample { - GstElement element; - ... - - GstDParamManager *dpman; - - ... - }; + g_object_class_install_property (gobject_class, PROP_FREQ, + g_param_spec_double ("freq", "Frequency", "Frequency of test signal", + 0.0, 20000.0, 440.0, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); - - The GstDParamManager can be initialised in your - element's init function: - - - static void - gst_example_init (GstExample *example) - { - ... - - example->dpman = gst_dpman_new ("example_dpman", GST_ELEMENT(example)); - - ... - } - - - - - Defining Parameter Specifications - - You can define the dparams you need anywhere within your element but will - usually need to do so in only a couple of places: - - - - In the element init function, just after the call - to gst_dpman_new - - - - - Whenever a new pad is created so that parameters can affect data going - into or out of a specific pad. An example of this would be a mixer - element where a separate volume parameter is needed on every pad. - - - - - - There are three different ways the dparams subsystem can pass parameters - into your element. Which one you use will depend on how that parameter is - used within your element. Each of these methods has its own function to - define a required dparam: - - - gst_dpman_add_required_dparam_direct - gst_dpman_add_required_dparam_callback - gst_dpman_add_required_dparam_array - - These functions will return TRUE if the required dparam was added - successfully. - - - The following function will be used as an example. - - gboolean - gst_dpman_add_required_dparam_direct (GstDParamManager *dpman, - GParamSpec *param_spec, - gboolean is_log, - gboolean is_rate, - gpointer update_data) - - The common parameters to these functions are: - - - - GstDParamManager *dpman the element's dparam - manager - - - - - GParamSpec *param_spec the param spec which defines - the required dparam - - - - - gboolean is_log whether this dparam value should be - interpreted on a log scale (such as a frequency or a decibel value) - - - - - gboolean is_rate whether this dparam value is a - proportion of the sample rate. For example with a sample rate of 44100, - 0.5 would be 22050 Hz and 0.25 would be 11025 Hz. - - - - - - Direct Method - - This method is the simplest and has the lowest overhead for parameters - which change less frequently than the sample rate. First you need - somewhere to store the parameter - this will usually be in your element's - struct. - - - struct _GstExample { - GstElement element; - ... - - GstDParamManager *dpman; - gfloat volume; - ... - }; - - - Then to define the required dparam just call - gst_dpman_add_required_dparam_direct and pass in the - location of the parameter to change. In this case the location is - &(example->volume). - - - gst_dpman_add_required_dparam_direct ( - example->dpman, - g_param_spec_float("volume","Volume","Volume of the audio", - 0.0, 1.0, 0.8, G_PARAM_READWRITE), - FALSE, - FALSE, - &(example->volume) - ); - - - You can now use example->volume anywhere in your - element knowing that it will always contain the correct value to use. - - - - Callback Method - - This should be used if the you have other values to calculate whenever a - parameter changes. If you used the direct method you wouldn't know if a - parameter had changed so you would have to recalculate the other values - every time you needed them. By using the callback method, other values - only have to be recalculated when the dparam value actually changes. - - - The following code illustrates an instance where you might want to use the - callback method. If you had a volume dparam which was represented by a - gfloat number, your element may only deal with integer arithmetic. The - callback could be used to calculate the integer scaler when the volume - changes. First you will need somewhere to store these values. - - - struct _GstExample { - GstElement element; - ... - - GstDParamManager *dpman; - gfloat volume_f; - gint volume_i; - ... - }; - - - When the required dparam is defined, the callback function - gst_example_update_volume and some user data (which - in this case is our element instance) is passed in to the call to - gst_dpman_add_required_dparam_callback. - - - gst_dpman_add_required_dparam_callback ( - example->dpman, - g_param_spec_float("volume","Volume","Volume of the audio", - 0.0, 1.0, 0.8, G_PARAM_READWRITE), - FALSE, - FALSE, - gst_example_update_volume, - example - ); - - - The callback function needs to conform to this signature - - -typedef void (*GstDPMUpdateFunction) (GValue *value, gpointer data); - - - In our example the callback function looks like this - - -static void -gst_example_update_volume(GValue *value, gpointer data) -{ - GstExample *example = (GstExample*)data; - g_return_if_fail(GST_IS_EXAMPLE(example)); - - example->volume_f = g_value_get_float(value); - example->volume_i = example->volume_f * 8192; -} - - - Now example->volume_i can be used elsewhere and it - will always contain the correct value. - - - - Array Method - - This method is quite different from the other two. It could be thought of - as a specialised method which should only be used if you need the - advantages that it provides. Instead of giving the element a single value - it provides an array of values where each item in the array corresponds to - a sample of audio in your buffer. There are a couple of reasons why this - might be useful. - - - - - - Certain optimisations may be possible since you can iterate over your - dparams array and your buffer data together. - - - - - Some dparams may be able to interpolate changing values at the sample - rate. This would allow the array to contain very smoothly changing - values which may be required for the stability and quality of some DSP - algorithms. - - - - - The array method is currently the least mature of the three methods and is - not yet ready to be used in elements, but plugin writers should be aware - of its existence for the future. - - The Data Processing Loop + This is the most critical aspect of the dparams subsystem as it relates to elements. In a traditional audio processing loop, a for diff --git a/gst/gstindex.c b/gst/gstindex.c index c9b13098a9..ef93149a44 100644 --- a/gst/gstindex.c +++ b/gst/gstindex.c @@ -667,7 +667,6 @@ gst_index_add_entry (GstIndex * index, GstIndexEntry * entry) * @flags: optinal flags for this entry * @n: number of associations * @list: list of associations - * @...: other format/value pairs or 0 to end the list * * Associate given format/value pairs with each other. * diff --git a/libs/gst/controller/lib.c b/libs/gst/controller/lib.c index 5c3d3cc5da..e6454ba905 100644 --- a/libs/gst/controller/lib.c +++ b/libs/gst/controller/lib.c @@ -43,6 +43,13 @@ GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); gboolean gst_controller_init (int *argc, char ***argv) { + static gboolean _gst_controller_initialized = FALSE; + + if (_gst_controller_initialized) + return TRUE; + + _gst_controller_initialized = TRUE; + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontroller", 0, "dynamic parameter control for gstreamer elements");