2 * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * mixer.c: mixer design virtual class function wrappers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
27 #include "audio-marshal.h"
29 #define GST_MIXER_MESSAGE_NAME "gst-mixer-message"
33 * @short_description: Interface for elements that provide mixer operations
34 * @see_also: alsamixer, oss4mixer, sunaudiomixer
36 * Basic interface for hardware mixer controls.
38 * Applications rarely need to use this interface, it is provided mainly
39 * for system-level mixer applets and the like. Volume control in playback
40 * applications should be done using a <classname>volume</classname>
41 * element or, if available, using the <quote>volume</quote> property of
42 * the audio sink element used (as provided by <classname>pulsesink</classname>
43 * for example), or even better: just use the <classname>playbin2</classname>
44 * element's <quote>volume</quote> property.
46 * Usage: In order to use the <classname>GstMixer</classname> interface, the
47 * element needs to be at least in READY state (so that the element has opened
48 * the mixer device). Once the element has been set to READY state or higher,
49 * it can be cast to a <classname>GstMixer</classname> using the GST_MIXER
50 * macro (in C) and the mixer API can be used.
53 /* FIXME 0.11: check if we need to add API for sometimes-supportedness
54 * (aka making up for GstImplementsInterface removal) */
56 static void gst_mixer_class_init (GstMixerInterface * iface);
59 gst_mixer_get_type (void)
61 static GType gst_mixer_type = 0;
63 if (!gst_mixer_type) {
64 static const GTypeInfo gst_mixer_info = {
65 sizeof (GstMixerInterface),
66 (GBaseInitFunc) gst_mixer_class_init,
76 gst_mixer_type = g_type_register_static (G_TYPE_INTERFACE,
77 "GstMixer", &gst_mixer_info, 0);
80 return gst_mixer_type;
84 gst_mixer_class_init (GstMixerInterface * iface)
86 /* default virtual functions */
87 iface->get_mixer_type = NULL;
88 iface->list_tracks = NULL;
89 iface->set_volume = NULL;
90 iface->get_volume = NULL;
91 iface->set_mute = NULL;
92 iface->set_record = NULL;
93 iface->set_option = NULL;
94 iface->get_option = NULL;
98 * gst_mixer_list_tracks:
99 * @mixer: the #GstMixer (a #GstElement) to get the tracks from.
101 * Returns a list of available tracks for this mixer/element. Note
102 * that it is allowed for sink (output) elements to only provide
103 * the output tracks in this list. Likewise, for sources (inputs),
104 * it is allowed to only provide input elements in this list.
106 * Returns: A #GList consisting of zero or more #GstMixerTracks.
107 * The list is owned by the #GstMixer instance and must not be freed
112 gst_mixer_list_tracks (GstMixer * mixer)
114 GstMixerInterface *iface;
116 g_return_val_if_fail (mixer != NULL, NULL);
118 iface = GST_MIXER_GET_INTERFACE (mixer);
120 if (iface->list_tracks) {
121 return iface->list_tracks (mixer);
128 * gst_mixer_set_volume:
129 * @mixer: The #GstMixer (a #GstElement) that owns the track.
130 * @track: The #GstMixerTrack to set the volume on.
131 * @volumes: an array of integers (of size track->num_channels)
132 * that gives the wanted volume for each channel in
135 * Sets the volume on each channel in a track. Short note about
136 * naming: a track is defined as one separate stream owned by
137 * the mixer/element, such as 'Line-in' or 'Microphone'. A
138 * channel is said to be a mono-stream inside this track. A
139 * stereo track thus contains two channels.
143 gst_mixer_set_volume (GstMixer * mixer, GstMixerTrack * track, gint * volumes)
145 GstMixerInterface *iface;
147 g_return_if_fail (mixer != NULL);
148 g_return_if_fail (track != NULL);
149 g_return_if_fail (volumes != NULL);
151 iface = GST_MIXER_GET_INTERFACE (mixer);
153 if (iface->set_volume) {
154 iface->set_volume (mixer, track, volumes);
159 * gst_mixer_get_volume:
160 * @mixer: the #GstMixer (a #GstElement) that owns the track
161 * @track: the GstMixerTrack to get the volume from.
162 * @volumes: a pre-allocated array of integers (of size
163 * track->num_channels) to store the current volume
164 * of each channel in the given track in.
166 * Get the current volume(s) on the given track.
170 gst_mixer_get_volume (GstMixer * mixer, GstMixerTrack * track, gint * volumes)
172 GstMixerInterface *iface;
174 g_return_if_fail (mixer != NULL);
175 g_return_if_fail (track != NULL);
176 g_return_if_fail (volumes != NULL);
178 iface = GST_MIXER_GET_INTERFACE (mixer);
180 if (iface->get_volume) {
181 iface->get_volume (mixer, track, volumes);
185 for (i = 0; i < track->num_channels; i++) {
192 * gst_mixer_set_mute:
193 * @mixer: the #GstMixer (a #GstElement) that owns the track.
194 * @track: the #GstMixerTrack to operate on.
195 * @mute: a boolean value indicating whether to turn on or off
198 * Mutes or unmutes the given channel. To find out whether a
199 * track is currently muted, use GST_MIXER_TRACK_HAS_FLAG ().
203 gst_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
205 GstMixerInterface *iface;
207 g_return_if_fail (mixer != NULL);
208 g_return_if_fail (track != NULL);
210 iface = GST_MIXER_GET_INTERFACE (mixer);
212 if (iface->set_mute) {
213 iface->set_mute (mixer, track, mute);
218 * gst_mixer_set_record:
219 * @mixer: The #GstMixer (a #GstElement) that owns the track.
220 * @track: the #GstMixerTrack to operate on.
221 * @record: a boolean value that indicates whether to turn on
224 * Enables or disables recording on the given track. Note that
225 * this is only possible on input tracks, not on output tracks
226 * (see GST_MIXER_TRACK_HAS_FLAG () and the GST_MIXER_TRACK_INPUT
231 gst_mixer_set_record (GstMixer * mixer, GstMixerTrack * track, gboolean record)
233 GstMixerInterface *iface = GST_MIXER_GET_INTERFACE (mixer);
235 if (iface->set_record) {
236 iface->set_record (mixer, track, record);
241 * gst_mixer_set_option:
242 * @mixer: The #GstMixer (a #GstElement) that owns the optionlist.
243 * @opts: The #GstMixerOptions that we operate on.
244 * @value: The requested new option value.
246 * Sets a name/value option in the mixer to the requested value.
250 gst_mixer_set_option (GstMixer * mixer, GstMixerOptions * opts, gchar * value)
252 GstMixerInterface *iface;
254 g_return_if_fail (mixer != NULL);
255 g_return_if_fail (opts != NULL);
257 iface = GST_MIXER_GET_INTERFACE (mixer);
259 if (iface->set_option) {
260 iface->set_option (mixer, opts, value);
265 * gst_mixer_get_option:
266 * @mixer: The #GstMixer (a #GstElement) that owns the optionlist.
267 * @opts: The #GstMixerOptions that we operate on.
269 * Get the current value of a name/value option in the mixer.
271 * Returns: current value of the name/value option.
275 gst_mixer_get_option (GstMixer * mixer, GstMixerOptions * opts)
277 GstMixerInterface *iface;
279 g_return_val_if_fail (mixer != NULL, NULL);
280 g_return_val_if_fail (opts != NULL, NULL);
282 iface = GST_MIXER_GET_INTERFACE (mixer);
284 if (iface->get_option) {
285 return iface->get_option (mixer, opts);
292 * gst_mixer_get_mixer_type:
293 * @mixer: The #GstMixer implementation
295 * Get the #GstMixerType of this mixer implementation.
297 * Returns: A the #GstMixerType.
302 gst_mixer_get_mixer_type (GstMixer * mixer)
304 GstMixerInterface *iface = GST_MIXER_GET_INTERFACE (mixer);
306 g_return_val_if_fail (iface->get_mixer_type != NULL, GST_MIXER_SOFTWARE);
307 return iface->get_mixer_type (mixer);
311 * gst_mixer_get_mixer_flags:
312 * @mixer: The #GstMixer implementation
314 * Get the set of supported flags for this mixer implementation.
316 * Returns: A set of or-ed GstMixerFlags for supported features.
319 gst_mixer_get_mixer_flags (GstMixer * mixer)
321 GstMixerInterface *iface;
323 g_return_val_if_fail (mixer != NULL, FALSE);
324 iface = GST_MIXER_GET_INTERFACE (mixer);
326 if (iface->get_mixer_flags) {
327 return iface->get_mixer_flags (mixer);
329 return GST_MIXER_FLAG_NONE;
333 * gst_mixer_mute_toggled:
334 * @mixer: the #GstMixer (a #GstElement) that owns the track
335 * @track: the GstMixerTrack that has change mute state.
336 * @mute: the new state of the mute flag on the track
338 * This function is called by the mixer implementation to produce
339 * a notification message on the bus indicating that the given track
340 * has changed mute state.
342 * This function only works for GstElements that are implementing the
343 * GstMixer interface, and the element needs to have been provided a bus.
346 gst_mixer_mute_toggled (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
351 g_return_if_fail (mixer != NULL);
352 g_return_if_fail (GST_IS_ELEMENT (mixer));
353 g_return_if_fail (track != NULL);
355 s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
356 "type", G_TYPE_STRING, "mute-toggled",
357 "track", GST_TYPE_MIXER_TRACK, track, "mute", G_TYPE_BOOLEAN, mute, NULL);
359 m = gst_message_new_element (GST_OBJECT (mixer), s);
360 if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
361 GST_WARNING ("This element has no bus, therefore no message sent!");
366 * gst_mixer_record_toggled:
367 * @mixer: the #GstMixer (a #GstElement) that owns the track
368 * @track: the GstMixerTrack that has changed recording state.
369 * @record: the new state of the record flag on the track
371 * This function is called by the mixer implementation to produce
372 * a notification message on the bus indicating that the given track
373 * has changed recording state.
375 * This function only works for GstElements that are implementing the
376 * GstMixer interface, and the element needs to have been provided a bus.
379 gst_mixer_record_toggled (GstMixer * mixer,
380 GstMixerTrack * track, gboolean record)
385 g_return_if_fail (mixer != NULL);
386 g_return_if_fail (GST_IS_ELEMENT (mixer));
387 g_return_if_fail (track != NULL);
389 s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
390 "type", G_TYPE_STRING, "record-toggled",
391 "track", GST_TYPE_MIXER_TRACK, track,
392 "record", G_TYPE_BOOLEAN, record, NULL);
394 m = gst_message_new_element (GST_OBJECT (mixer), s);
395 if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
396 GST_WARNING ("This element has no bus, therefore no message sent!");
401 * gst_mixer_volume_changed:
402 * @mixer: the #GstMixer (a #GstElement) that owns the track
403 * @track: the GstMixerTrack that has changed.
404 * @volumes: Array of volume values, one per channel on the mixer track.
406 * This function is called by the mixer implementation to produce
407 * a notification message on the bus indicating that the volume(s) for the
408 * given track have changed.
410 * This function only works for GstElements that are implementing the
411 * GstMixer interface, and the element needs to have been provided a bus.
414 gst_mixer_volume_changed (GstMixer * mixer,
415 GstMixerTrack * track, gint * volumes)
423 g_return_if_fail (mixer != NULL);
424 g_return_if_fail (GST_IS_ELEMENT (mixer));
425 g_return_if_fail (track != NULL);
427 s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
428 "type", G_TYPE_STRING, "volume-changed",
429 "track", GST_TYPE_MIXER_TRACK, track, NULL);
431 g_value_init (&l, GST_TYPE_ARRAY);
433 g_value_init (&v, G_TYPE_INT);
435 /* FIXME 0.11: pass track->num_channels to the function */
436 for (i = 0; i < track->num_channels; ++i) {
437 g_value_set_int (&v, volumes[i]);
438 gst_value_array_append_value (&l, &v);
442 gst_structure_set_value (s, "volumes", &l);
445 m = gst_message_new_element (GST_OBJECT (mixer), s);
446 if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
447 GST_WARNING ("This element has no bus, therefore no message sent!");
452 * gst_mixer_option_changed:
453 * @mixer: the #GstMixer (a #GstElement) that owns the options
454 * @opts: the GstMixerOptions that has changed value.
455 * @value: the new value of the GstMixerOptions.
457 * This function is called by the mixer implementation to produce
458 * a notification message on the bus indicating that the given options
459 * object has changed state.
461 * This function only works for GstElements that are implementing the
462 * GstMixer interface, and the element needs to have been provided a bus.
465 gst_mixer_option_changed (GstMixer * mixer,
466 GstMixerOptions * opts, const gchar * value)
471 g_return_if_fail (mixer != NULL);
472 g_return_if_fail (GST_IS_ELEMENT (mixer));
473 g_return_if_fail (opts != NULL);
475 s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
476 "type", G_TYPE_STRING, "option-changed",
477 "options", GST_TYPE_MIXER_OPTIONS, opts,
478 "value", G_TYPE_STRING, value, NULL);
480 m = gst_message_new_element (GST_OBJECT (mixer), s);
481 if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
482 GST_WARNING ("This element has no bus, therefore no message sent!");
487 * gst_mixer_options_list_changed:
488 * @mixer: the #GstMixer (a #GstElement) that owns the options
489 * @opts: the GstMixerOptions whose list of values has changed
491 * This function is called by the mixer implementation to produce
492 * a notification message on the bus indicating that the list of possible
493 * options of a given options object has changed.
495 * The new options are not contained in the message on purpose. Applications
496 * should call gst_mixer_options_get_values() on @opts to make @opts update
497 * its internal state and obtain the new list of values.
499 * This function only works for GstElements that are implementing the
500 * GstMixer interface, and the element needs to have been provided a bus
506 gst_mixer_options_list_changed (GstMixer * mixer, GstMixerOptions * opts)
511 g_return_if_fail (mixer != NULL);
512 g_return_if_fail (GST_IS_ELEMENT (mixer));
513 g_return_if_fail (opts != NULL);
514 g_return_if_fail (GST_IS_MIXER_OPTIONS (opts));
516 /* we do not include the new list here on purpose, so that the application
517 * has to use gst_mixer_options_get_values() to get the new list, which then
518 * allows the mixer options object to update the internal GList in a somewhat
519 * thread-safe way at least */
520 s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
521 "type", G_TYPE_STRING, "options-list-changed",
522 "options", GST_TYPE_MIXER_OPTIONS, opts, NULL);
524 m = gst_message_new_element (GST_OBJECT (mixer), s);
525 if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
526 GST_WARNING ("This element has no bus, therefore no message sent!");
531 * gst_mixer_mixer_changed:
532 * @mixer: the #GstMixer (a #GstElement) which has changed
534 * This function is called by the mixer implementation to produce
535 * a notification message on the bus indicating that the list of available
536 * mixer tracks for a given mixer object has changed. Applications should
537 * rebuild their interface when they receive this message.
539 * This function only works for GstElements that are implementing the
540 * GstMixer interface, and the element needs to have been provided a bus.
545 gst_mixer_mixer_changed (GstMixer * mixer)
550 g_return_if_fail (mixer != NULL);
551 g_return_if_fail (GST_IS_ELEMENT (mixer));
553 s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
554 "type", G_TYPE_STRING, "mixer-changed", NULL);
556 m = gst_message_new_element (GST_OBJECT (mixer), s);
557 if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
558 GST_WARNING ("This element has no bus, therefore no message sent!");
563 gst_mixer_message_is_mixer_message (GstMessage * message)
565 const GstStructure *s;
569 if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
572 s = gst_message_get_structure (message);
573 return gst_structure_has_name (s, GST_MIXER_MESSAGE_NAME);
577 * gst_mixer_message_get_type:
578 * @message: A GstMessage to inspect.
580 * Check a bus message to see if it is a GstMixer notification
581 * message and return the GstMixerMessageType identifying which
582 * type of notification it is.
584 * Returns: The type of the GstMixerMessage, or GST_MIXER_MESSAGE_INVALID
585 * if the message is not a GstMixer notification.
590 gst_mixer_message_get_type (GstMessage * message)
592 const GstStructure *s;
595 if (!gst_mixer_message_is_mixer_message (message))
596 return GST_MIXER_MESSAGE_INVALID;
598 s = gst_message_get_structure (message);
599 m_type = gst_structure_get_string (s, "type");
600 g_return_val_if_fail (m_type != NULL, GST_MIXER_MESSAGE_INVALID);
602 if (g_str_equal (m_type, "mute-toggled"))
603 return GST_MIXER_MESSAGE_MUTE_TOGGLED;
604 else if (g_str_equal (m_type, "record-toggled"))
605 return GST_MIXER_MESSAGE_RECORD_TOGGLED;
606 else if (g_str_equal (m_type, "volume-changed"))
607 return GST_MIXER_MESSAGE_VOLUME_CHANGED;
608 else if (g_str_equal (m_type, "option-changed"))
609 return GST_MIXER_MESSAGE_OPTION_CHANGED;
610 else if (g_str_equal (m_type, "options-list-changed"))
611 return GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED;
612 else if (g_str_equal (m_type, "mixer-changed"))
613 return GST_MIXER_MESSAGE_MIXER_CHANGED;
615 return GST_MIXER_MESSAGE_INVALID;
618 #define GST_MIXER_MESSAGE_HAS_TYPE(msg,msg_type) \
619 (gst_mixer_message_get_type (msg) == GST_MIXER_MESSAGE_ ## msg_type)
622 * gst_mixer_message_parse_mute_toggled:
623 * @message: A mute-toggled change notification message.
624 * @track: Pointer to hold a GstMixerTrack object, or NULL.
625 * @mute: A pointer to a gboolean variable, or NULL.
627 * Extracts the contents of a mute-toggled bus message. Reads
628 * the GstMixerTrack that has changed, and the new value of the mute
631 * The GstMixerTrack remains valid until the message is freed.
636 gst_mixer_message_parse_mute_toggled (GstMessage * message,
637 GstMixerTrack ** track, gboolean * mute)
639 const GstStructure *s;
641 g_return_if_fail (gst_mixer_message_is_mixer_message (message));
642 g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, MUTE_TOGGLED));
644 s = gst_message_get_structure (message);
647 const GValue *v = gst_structure_get_value (s, "track");
649 g_return_if_fail (v != NULL);
650 *track = (GstMixerTrack *) g_value_get_object (v);
651 g_return_if_fail (GST_IS_MIXER_TRACK (*track));
655 g_return_if_fail (gst_structure_get_boolean (s, "mute", mute));
659 * gst_mixer_message_parse_record_toggled:
660 * @message: A record-toggled change notification message.
661 * @track: Pointer to hold a GstMixerTrack object, or NULL.
662 * @record: A pointer to a gboolean variable, or NULL.
664 * Extracts the contents of a record-toggled bus message. Reads
665 * the GstMixerTrack that has changed, and the new value of the
668 * The GstMixerTrack remains valid until the message is freed.
673 gst_mixer_message_parse_record_toggled (GstMessage * message,
674 GstMixerTrack ** track, gboolean * record)
676 const GstStructure *s;
678 g_return_if_fail (gst_mixer_message_is_mixer_message (message));
679 g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, RECORD_TOGGLED));
681 s = gst_message_get_structure (message);
684 const GValue *v = gst_structure_get_value (s, "track");
686 g_return_if_fail (v != NULL);
687 *track = (GstMixerTrack *) g_value_get_object (v);
688 g_return_if_fail (GST_IS_MIXER_TRACK (*track));
692 g_return_if_fail (gst_structure_get_boolean (s, "record", record));
696 * gst_mixer_message_parse_volume_changed:
697 * @message: A volume-changed change notification message.
698 * @track: Pointer to hold a GstMixerTrack object, or NULL.
699 * @volumes: A pointer to receive an array of gint values, or NULL.
700 * @num_channels: Result location to receive the number of channels, or NULL.
702 * Parses a volume-changed notification message and extracts the track object
703 * it refers to, as well as an array of volumes and the size of the volumes array.
705 * The track object remains valid until the message is freed.
707 * The caller must free the array returned in the volumes parameter using g_free
708 * when they are done with it.
713 gst_mixer_message_parse_volume_changed (GstMessage * message,
714 GstMixerTrack ** track, gint ** volumes, gint * num_channels)
716 const GstStructure *s;
718 g_return_if_fail (gst_mixer_message_is_mixer_message (message));
719 g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, VOLUME_CHANGED));
721 s = gst_message_get_structure (message);
724 const GValue *v = gst_structure_get_value (s, "track");
726 g_return_if_fail (v != NULL);
727 *track = (GstMixerTrack *) g_value_get_object (v);
728 g_return_if_fail (GST_IS_MIXER_TRACK (*track));
731 if (volumes || num_channels) {
733 const GValue *v = gst_structure_get_value (s, "volumes");
735 g_return_if_fail (v != NULL);
736 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (v));
738 n_chans = gst_value_array_get_size (v);
740 *num_channels = n_chans;
743 *volumes = g_new (gint, n_chans);
744 for (i = 0; i < n_chans; i++) {
745 const GValue *e = gst_value_array_get_value (v, i);
747 g_return_if_fail (e != NULL && G_VALUE_HOLDS_INT (e));
748 (*volumes)[i] = g_value_get_int (e);
755 * gst_mixer_message_parse_option_changed:
756 * @message: A volume-changed change notification message.
757 * @options: Pointer to hold a GstMixerOptions object, or NULL.
758 * @value: Result location to receive the new options value, or NULL.
760 * Extracts the GstMixerOptions and new value from a option-changed bus notification
763 * The options and value returned remain valid until the message is freed.
768 gst_mixer_message_parse_option_changed (GstMessage * message,
769 GstMixerOptions ** options, const gchar ** value)
771 const GstStructure *s;
773 g_return_if_fail (gst_mixer_message_is_mixer_message (message));
774 g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, OPTION_CHANGED));
776 s = gst_message_get_structure (message);
779 const GValue *v = gst_structure_get_value (s, "options");
781 g_return_if_fail (v != NULL);
782 *options = (GstMixerOptions *) g_value_get_object (v);
783 g_return_if_fail (GST_IS_MIXER_OPTIONS (*options));
787 *value = gst_structure_get_string (s, "value");
791 * gst_mixer_message_parse_options_list_changed:
792 * @message: A volume-changed change notification message.
793 * @options: Pointer to hold a GstMixerOptions object, or NULL.
795 * Extracts the GstMixerOptions whose value list has changed from an
796 * options-list-changed bus notification message.
798 * The options object returned remains valid until the message is freed. You
799 * do not need to unref it.
804 gst_mixer_message_parse_options_list_changed (GstMessage * message,
805 GstMixerOptions ** options)
807 const GstStructure *s;
809 g_return_if_fail (gst_mixer_message_is_mixer_message (message));
810 g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, OPTIONS_LIST_CHANGED));
812 s = gst_message_get_structure (message);
815 const GValue *v = gst_structure_get_value (s, "options");
817 g_return_if_fail (v != NULL);
818 *options = (GstMixerOptions *) g_value_get_object (v);
819 g_return_if_fail (GST_IS_MIXER_OPTIONS (*options));