Branch data Line data Source code
1 : : /* GStreamer Mixer
2 : : * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3 : : *
4 : : * mixer.c: mixer design virtual class function wrappers
5 : : *
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.
10 : : *
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.
15 : : *
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.
20 : : */
21 : :
22 : : #ifdef HAVE_CONFIG_H
23 : : #include "config.h"
24 : : #endif
25 : :
26 : : #include "mixer.h"
27 : : #include "interfaces-marshal.h"
28 : :
29 : : #define GST_MIXER_MESSAGE_NAME "gst-mixer-message"
30 : :
31 : : /**
32 : : * SECTION:gstmixer
33 : : * @short_description: Interface for elements that provide mixer operations
34 : : * @see_also: alsamixer, oss4mixer, sunaudiomixer
35 : : *
36 : : * Basic interface for hardware mixer controls.
37 : : *
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.
45 : : *
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.
51 : : */
52 : :
53 : : #ifndef GST_DISABLE_DEPRECATED
54 : : enum
55 : : {
56 : : SIGNAL_MUTE_TOGGLED,
57 : : SIGNAL_RECORD_TOGGLED,
58 : : SIGNAL_VOLUME_CHANGED,
59 : : SIGNAL_OPTION_CHANGED,
60 : : LAST_SIGNAL
61 : : };
62 : :
63 : : static guint gst_mixer_signals[LAST_SIGNAL] = { 0 };
64 : :
65 : : #endif
66 : :
67 : : static void gst_mixer_class_init (GstMixerClass * klass);
68 : :
69 : : GType
70 : 248 : gst_mixer_get_type (void)
71 : : {
72 : : static GType gst_mixer_type = 0;
73 : :
74 [ + + ]: 248 : if (!gst_mixer_type) {
75 : : static const GTypeInfo gst_mixer_info = {
76 : : sizeof (GstMixerClass),
77 : : (GBaseInitFunc) gst_mixer_class_init,
78 : : NULL,
79 : : NULL,
80 : : NULL,
81 : : NULL,
82 : : 0,
83 : : 0,
84 : : NULL,
85 : : };
86 : :
87 : 119 : gst_mixer_type = g_type_register_static (G_TYPE_INTERFACE,
88 : : "GstMixer", &gst_mixer_info, 0);
89 : 119 : g_type_interface_add_prerequisite (gst_mixer_type,
90 : : GST_TYPE_IMPLEMENTS_INTERFACE);
91 : : }
92 : :
93 : 248 : return gst_mixer_type;
94 : : }
95 : :
96 : : static void
97 : 255 : gst_mixer_class_init (GstMixerClass * klass)
98 : : {
99 : : #ifndef GST_DISABLE_DEPRECATED
100 : : static gboolean initialized = FALSE;
101 : :
102 : : /* signals (deprecated) */
103 : : if (!initialized) {
104 : : gst_mixer_signals[SIGNAL_RECORD_TOGGLED] =
105 : : g_signal_new ("record-toggled",
106 : : GST_TYPE_MIXER, G_SIGNAL_RUN_LAST,
107 : : G_STRUCT_OFFSET (GstMixerClass, record_toggled),
108 : : NULL, NULL,
109 : : gst_interfaces_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2,
110 : : GST_TYPE_MIXER_TRACK, G_TYPE_BOOLEAN);
111 : : gst_mixer_signals[SIGNAL_MUTE_TOGGLED] =
112 : : g_signal_new ("mute-toggled",
113 : : GST_TYPE_MIXER, G_SIGNAL_RUN_LAST,
114 : : G_STRUCT_OFFSET (GstMixerClass, mute_toggled),
115 : : NULL, NULL,
116 : : gst_interfaces_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2,
117 : : GST_TYPE_MIXER_TRACK, G_TYPE_BOOLEAN);
118 : : gst_mixer_signals[SIGNAL_VOLUME_CHANGED] =
119 : : g_signal_new ("volume-changed",
120 : : GST_TYPE_MIXER, G_SIGNAL_RUN_LAST,
121 : : G_STRUCT_OFFSET (GstMixerClass, volume_changed),
122 : : NULL, NULL,
123 : : gst_interfaces_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2,
124 : : GST_TYPE_MIXER_TRACK, G_TYPE_POINTER);
125 : : gst_mixer_signals[SIGNAL_OPTION_CHANGED] =
126 : : g_signal_new ("option-changed",
127 : : GST_TYPE_MIXER, G_SIGNAL_RUN_LAST,
128 : : G_STRUCT_OFFSET (GstMixerClass, option_changed),
129 : : NULL, NULL,
130 : : gst_interfaces_marshal_VOID__OBJECT_STRING, G_TYPE_NONE, 2,
131 : : GST_TYPE_MIXER_OPTIONS, G_TYPE_STRING);
132 : :
133 : : initialized = TRUE;
134 : : }
135 : : #endif
136 : :
137 : 255 : klass->mixer_type = GST_MIXER_SOFTWARE;
138 : :
139 : : /* default virtual functions */
140 : 255 : klass->list_tracks = NULL;
141 : 255 : klass->set_volume = NULL;
142 : 255 : klass->get_volume = NULL;
143 : 255 : klass->set_mute = NULL;
144 : 255 : klass->set_record = NULL;
145 : 255 : klass->set_option = NULL;
146 : 255 : klass->get_option = NULL;
147 : 255 : }
148 : :
149 : : /**
150 : : * gst_mixer_list_tracks:
151 : : * @mixer: the #GstMixer (a #GstElement) to get the tracks from.
152 : : *
153 : : * Returns a list of available tracks for this mixer/element. Note
154 : : * that it is allowed for sink (output) elements to only provide
155 : : * the output tracks in this list. Likewise, for sources (inputs),
156 : : * it is allowed to only provide input elements in this list.
157 : : *
158 : : * Returns: A #GList consisting of zero or more #GstMixerTracks.
159 : : * The list is owned by the #GstMixer instance and must not be freed
160 : : * or modified.
161 : : */
162 : :
163 : : const GList *
164 : 1 : gst_mixer_list_tracks (GstMixer * mixer)
165 : : {
166 : : GstMixerClass *klass;
167 : :
168 [ - + ]: 1 : g_return_val_if_fail (mixer != NULL, NULL);
169 : :
170 : 1 : klass = GST_MIXER_GET_CLASS (mixer);
171 : :
172 [ + - ]: 1 : if (klass->list_tracks) {
173 : 1 : return klass->list_tracks (mixer);
174 : : }
175 : :
176 : 1 : return NULL;
177 : : }
178 : :
179 : : /**
180 : : * gst_mixer_set_volume:
181 : : * @mixer: The #GstMixer (a #GstElement) that owns the track.
182 : : * @track: The #GstMixerTrack to set the volume on.
183 : : * @volumes: an array of integers (of size track->num_channels)
184 : : * that gives the wanted volume for each channel in
185 : : * this track.
186 : : *
187 : : * Sets the volume on each channel in a track. Short note about
188 : : * naming: a track is defined as one separate stream owned by
189 : : * the mixer/element, such as 'Line-in' or 'Microphone'. A
190 : : * channel is said to be a mono-stream inside this track. A
191 : : * stereo track thus contains two channels.
192 : : */
193 : :
194 : : void
195 : 0 : gst_mixer_set_volume (GstMixer * mixer, GstMixerTrack * track, gint * volumes)
196 : : {
197 : : GstMixerClass *klass;
198 : :
199 [ # # ]: 0 : g_return_if_fail (mixer != NULL);
200 [ # # ]: 0 : g_return_if_fail (track != NULL);
201 [ # # ]: 0 : g_return_if_fail (volumes != NULL);
202 : :
203 : 0 : klass = GST_MIXER_GET_CLASS (mixer);
204 : :
205 [ # # ]: 0 : if (klass->set_volume) {
206 : 0 : klass->set_volume (mixer, track, volumes);
207 : : }
208 : : }
209 : :
210 : : /**
211 : : * gst_mixer_get_volume:
212 : : * @mixer: the #GstMixer (a #GstElement) that owns the track
213 : : * @track: the GstMixerTrack to get the volume from.
214 : : * @volumes: a pre-allocated array of integers (of size
215 : : * track->num_channels) to store the current volume
216 : : * of each channel in the given track in.
217 : : *
218 : : * Get the current volume(s) on the given track.
219 : : */
220 : :
221 : : void
222 : 0 : gst_mixer_get_volume (GstMixer * mixer, GstMixerTrack * track, gint * volumes)
223 : : {
224 : : GstMixerClass *klass;
225 : :
226 [ # # ]: 0 : g_return_if_fail (mixer != NULL);
227 [ # # ]: 0 : g_return_if_fail (track != NULL);
228 [ # # ]: 0 : g_return_if_fail (volumes != NULL);
229 : :
230 : 0 : klass = GST_MIXER_GET_CLASS (mixer);
231 : :
232 [ # # ]: 0 : if (klass->get_volume) {
233 : 0 : klass->get_volume (mixer, track, volumes);
234 : : } else {
235 : : gint i;
236 : :
237 [ # # ]: 0 : for (i = 0; i < track->num_channels; i++) {
238 : 0 : volumes[i] = 0;
239 : : }
240 : : }
241 : : }
242 : :
243 : : /**
244 : : * gst_mixer_set_mute:
245 : : * @mixer: the #GstMixer (a #GstElement) that owns the track.
246 : : * @track: the #GstMixerTrack to operate on.
247 : : * @mute: a boolean value indicating whether to turn on or off
248 : : * muting.
249 : : *
250 : : * Mutes or unmutes the given channel. To find out whether a
251 : : * track is currently muted, use GST_MIXER_TRACK_HAS_FLAG ().
252 : : */
253 : :
254 : : void
255 : 0 : gst_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
256 : : {
257 : : GstMixerClass *klass;
258 : :
259 [ # # ]: 0 : g_return_if_fail (mixer != NULL);
260 [ # # ]: 0 : g_return_if_fail (track != NULL);
261 : :
262 : 0 : klass = GST_MIXER_GET_CLASS (mixer);
263 : :
264 [ # # ]: 0 : if (klass->set_mute) {
265 : 0 : klass->set_mute (mixer, track, mute);
266 : : }
267 : : }
268 : :
269 : : /**
270 : : * gst_mixer_set_record:
271 : : * @mixer: The #GstMixer (a #GstElement) that owns the track.
272 : : * @track: the #GstMixerTrack to operate on.
273 : : * @record: a boolean value that indicates whether to turn on
274 : : * or off recording.
275 : : *
276 : : * Enables or disables recording on the given track. Note that
277 : : * this is only possible on input tracks, not on output tracks
278 : : * (see GST_MIXER_TRACK_HAS_FLAG () and the GST_MIXER_TRACK_INPUT
279 : : * flag).
280 : : */
281 : :
282 : : void
283 : 0 : gst_mixer_set_record (GstMixer * mixer, GstMixerTrack * track, gboolean record)
284 : : {
285 : 0 : GstMixerClass *klass = GST_MIXER_GET_CLASS (mixer);
286 : :
287 [ # # ]: 0 : if (klass->set_record) {
288 : 0 : klass->set_record (mixer, track, record);
289 : : }
290 : 0 : }
291 : :
292 : : /**
293 : : * gst_mixer_set_option:
294 : : * @mixer: The #GstMixer (a #GstElement) that owns the optionlist.
295 : : * @opts: The #GstMixerOptions that we operate on.
296 : : * @value: The requested new option value.
297 : : *
298 : : * Sets a name/value option in the mixer to the requested value.
299 : : */
300 : :
301 : : void
302 : 0 : gst_mixer_set_option (GstMixer * mixer, GstMixerOptions * opts, gchar * value)
303 : : {
304 : : GstMixerClass *klass;
305 : :
306 [ # # ]: 0 : g_return_if_fail (mixer != NULL);
307 [ # # ]: 0 : g_return_if_fail (opts != NULL);
308 : :
309 : 0 : klass = GST_MIXER_GET_CLASS (mixer);
310 : :
311 [ # # ]: 0 : if (klass->set_option) {
312 : 0 : klass->set_option (mixer, opts, value);
313 : : }
314 : : }
315 : :
316 : : /**
317 : : * gst_mixer_get_option:
318 : : * @mixer: The #GstMixer (a #GstElement) that owns the optionlist.
319 : : * @opts: The #GstMixerOptions that we operate on.
320 : : *
321 : : * Get the current value of a name/value option in the mixer.
322 : : *
323 : : * Returns: current value of the name/value option.
324 : : */
325 : :
326 : : const gchar *
327 : 0 : gst_mixer_get_option (GstMixer * mixer, GstMixerOptions * opts)
328 : : {
329 : : GstMixerClass *klass;
330 : :
331 [ # # ]: 0 : g_return_val_if_fail (mixer != NULL, NULL);
332 [ # # ]: 0 : g_return_val_if_fail (opts != NULL, NULL);
333 : :
334 : 0 : klass = GST_MIXER_GET_CLASS (mixer);
335 : :
336 [ # # ]: 0 : if (klass->get_option) {
337 : 0 : return klass->get_option (mixer, opts);
338 : : }
339 : :
340 : 0 : return NULL;
341 : : }
342 : :
343 : : /**
344 : : * gst_mixer_get_mixer_type:
345 : : * @mixer: The #GstMixer implementation
346 : : *
347 : : * Get the #GstMixerType of this mixer implementation.
348 : : *
349 : : * Returns: A the #GstMixerType.
350 : : *
351 : : * Since: 0.10.24
352 : : */
353 : : GstMixerType
354 : 0 : gst_mixer_get_mixer_type (GstMixer * mixer)
355 : : {
356 : 0 : GstMixerClass *klass = GST_MIXER_GET_CLASS (mixer);
357 : :
358 : 0 : return klass->mixer_type;
359 : : }
360 : :
361 : : /**
362 : : * gst_mixer_get_mixer_flags:
363 : : * @mixer: The #GstMixer implementation
364 : : *
365 : : * Get the set of supported flags for this mixer implementation.
366 : : *
367 : : * Returns: A set of or-ed GstMixerFlags for supported features.
368 : : */
369 : : GstMixerFlags
370 : 0 : gst_mixer_get_mixer_flags (GstMixer * mixer)
371 : : {
372 : : GstMixerClass *klass;
373 : :
374 [ # # ]: 0 : g_return_val_if_fail (mixer != NULL, FALSE);
375 : 0 : klass = GST_MIXER_GET_CLASS (mixer);
376 : :
377 [ # # ]: 0 : if (klass->get_mixer_flags) {
378 : 0 : return klass->get_mixer_flags (mixer);
379 : : }
380 : 0 : return GST_MIXER_FLAG_NONE;
381 : : }
382 : :
383 : : /**
384 : : * gst_mixer_mute_toggled:
385 : : * @mixer: the #GstMixer (a #GstElement) that owns the track
386 : : * @track: the GstMixerTrack that has change mute state.
387 : : * @mute: the new state of the mute flag on the track
388 : : *
389 : : * This function is called by the mixer implementation to produce
390 : : * a notification message on the bus indicating that the given track
391 : : * has changed mute state.
392 : : *
393 : : * This function only works for GstElements that are implementing the
394 : : * GstMixer interface, and the element needs to have been provided a bus.
395 : : */
396 : : void
397 : 1 : gst_mixer_mute_toggled (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
398 : : {
399 : : GstStructure *s;
400 : : GstMessage *m;
401 : :
402 [ - + ]: 1 : g_return_if_fail (mixer != NULL);
403 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_ELEMENT (mixer));
[ - + ][ - + ]
404 [ - + ]: 1 : g_return_if_fail (track != NULL);
405 : :
406 : 1 : s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
407 : : "type", G_TYPE_STRING, "mute-toggled",
408 : : "track", GST_TYPE_MIXER_TRACK, track, "mute", G_TYPE_BOOLEAN, mute, NULL);
409 : :
410 : 1 : m = gst_message_new_element (GST_OBJECT (mixer), s);
411 [ - + ]: 1 : if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
412 [ # # ]: 1 : GST_WARNING ("This element has no bus, therefore no message sent!");
413 : : }
414 : : }
415 : :
416 : : /**
417 : : * gst_mixer_record_toggled:
418 : : * @mixer: the #GstMixer (a #GstElement) that owns the track
419 : : * @track: the GstMixerTrack that has changed recording state.
420 : : * @record: the new state of the record flag on the track
421 : : *
422 : : * This function is called by the mixer implementation to produce
423 : : * a notification message on the bus indicating that the given track
424 : : * has changed recording state.
425 : : *
426 : : * This function only works for GstElements that are implementing the
427 : : * GstMixer interface, and the element needs to have been provided a bus.
428 : : */
429 : : void
430 : 1 : gst_mixer_record_toggled (GstMixer * mixer,
431 : : GstMixerTrack * track, gboolean record)
432 : : {
433 : : GstStructure *s;
434 : : GstMessage *m;
435 : :
436 [ - + ]: 1 : g_return_if_fail (mixer != NULL);
437 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_ELEMENT (mixer));
[ - + ][ - + ]
438 [ - + ]: 1 : g_return_if_fail (track != NULL);
439 : :
440 : 1 : s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
441 : : "type", G_TYPE_STRING, "record-toggled",
442 : : "track", GST_TYPE_MIXER_TRACK, track,
443 : : "record", G_TYPE_BOOLEAN, record, NULL);
444 : :
445 : 1 : m = gst_message_new_element (GST_OBJECT (mixer), s);
446 [ - + ]: 1 : if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
447 [ # # ]: 1 : GST_WARNING ("This element has no bus, therefore no message sent!");
448 : : }
449 : : }
450 : :
451 : : /**
452 : : * gst_mixer_volume_changed:
453 : : * @mixer: the #GstMixer (a #GstElement) that owns the track
454 : : * @track: the GstMixerTrack that has changed.
455 : : * @volumes: Array of volume values, one per channel on the mixer track.
456 : : *
457 : : * This function is called by the mixer implementation to produce
458 : : * a notification message on the bus indicating that the volume(s) for the
459 : : * given track have changed.
460 : : *
461 : : * This function only works for GstElements that are implementing the
462 : : * GstMixer interface, and the element needs to have been provided a bus.
463 : : */
464 : : void
465 : 1 : gst_mixer_volume_changed (GstMixer * mixer,
466 : : GstMixerTrack * track, gint * volumes)
467 : : {
468 : : GstStructure *s;
469 : : GstMessage *m;
470 : 1 : GValue l = { 0, };
471 : 1 : GValue v = { 0, };
472 : : gint i;
473 : :
474 [ - + ]: 1 : g_return_if_fail (mixer != NULL);
475 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_ELEMENT (mixer));
[ - + ][ - + ]
476 [ - + ]: 1 : g_return_if_fail (track != NULL);
477 : :
478 : 1 : s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
479 : : "type", G_TYPE_STRING, "volume-changed",
480 : : "track", GST_TYPE_MIXER_TRACK, track, NULL);
481 : :
482 : 1 : g_value_init (&l, GST_TYPE_ARRAY);
483 : :
484 : 1 : g_value_init (&v, G_TYPE_INT);
485 : :
486 : : /* FIXME 0.11: pass track->num_channels to the function */
487 [ + + ]: 3 : for (i = 0; i < track->num_channels; ++i) {
488 : 2 : g_value_set_int (&v, volumes[i]);
489 : 2 : gst_value_array_append_value (&l, &v);
490 : : }
491 : 1 : g_value_unset (&v);
492 : :
493 : 1 : gst_structure_set_value (s, "volumes", &l);
494 : 1 : g_value_unset (&l);
495 : :
496 : 1 : m = gst_message_new_element (GST_OBJECT (mixer), s);
497 [ - + ]: 1 : if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
498 [ # # ]: 1 : GST_WARNING ("This element has no bus, therefore no message sent!");
499 : : }
500 : : }
501 : :
502 : : /**
503 : : * gst_mixer_option_changed:
504 : : * @mixer: the #GstMixer (a #GstElement) that owns the options
505 : : * @opts: the GstMixerOptions that has changed value.
506 : : * @value: the new value of the GstMixerOptions.
507 : : *
508 : : * This function is called by the mixer implementation to produce
509 : : * a notification message on the bus indicating that the given options
510 : : * object has changed state.
511 : : *
512 : : * This function only works for GstElements that are implementing the
513 : : * GstMixer interface, and the element needs to have been provided a bus.
514 : : */
515 : : void
516 : 1 : gst_mixer_option_changed (GstMixer * mixer,
517 : : GstMixerOptions * opts, const gchar * value)
518 : : {
519 : : GstStructure *s;
520 : : GstMessage *m;
521 : :
522 [ - + ]: 1 : g_return_if_fail (mixer != NULL);
523 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_ELEMENT (mixer));
[ - + ][ - + ]
524 [ - + ]: 1 : g_return_if_fail (opts != NULL);
525 : :
526 : 1 : s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
527 : : "type", G_TYPE_STRING, "option-changed",
528 : : "options", GST_TYPE_MIXER_OPTIONS, opts,
529 : : "value", G_TYPE_STRING, value, NULL);
530 : :
531 : 1 : m = gst_message_new_element (GST_OBJECT (mixer), s);
532 [ - + ]: 1 : if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
533 [ # # ]: 1 : GST_WARNING ("This element has no bus, therefore no message sent!");
534 : : }
535 : : }
536 : :
537 : : /**
538 : : * gst_mixer_options_list_changed:
539 : : * @mixer: the #GstMixer (a #GstElement) that owns the options
540 : : * @opts: the GstMixerOptions whose list of values has changed
541 : : *
542 : : * This function is called by the mixer implementation to produce
543 : : * a notification message on the bus indicating that the list of possible
544 : : * options of a given options object has changed.
545 : : *
546 : : * The new options are not contained in the message on purpose. Applications
547 : : * should call gst_mixer_option_get_values() on @opts to make @opts update
548 : : * its internal state and obtain the new list of values.
549 : : *
550 : : * This function only works for GstElements that are implementing the
551 : : * GstMixer interface, and the element needs to have been provided a bus
552 : : * for this to work.
553 : : *
554 : : * Since: 0.10.18
555 : : */
556 : : void
557 : 1 : gst_mixer_options_list_changed (GstMixer * mixer, GstMixerOptions * opts)
558 : : {
559 : : GstStructure *s;
560 : : GstMessage *m;
561 : :
562 [ - + ]: 1 : g_return_if_fail (mixer != NULL);
563 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_ELEMENT (mixer));
[ - + ][ - + ]
564 [ - + ]: 1 : g_return_if_fail (opts != NULL);
565 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_MIXER_OPTIONS (opts));
[ + - ][ - + ]
566 : :
567 : : /* we do not include the new list here on purpose, so that the application
568 : : * has to use gst_mixer_options_get_values() to get the new list, which then
569 : : * allows the mixer options object to update the internal GList in a somewhat
570 : : * thread-safe way at least */
571 : 1 : s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
572 : : "type", G_TYPE_STRING, "options-list-changed",
573 : : "options", GST_TYPE_MIXER_OPTIONS, opts, NULL);
574 : :
575 : 1 : m = gst_message_new_element (GST_OBJECT (mixer), s);
576 [ - + ]: 1 : if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
577 [ # # ]: 1 : GST_WARNING ("This element has no bus, therefore no message sent!");
578 : : }
579 : : }
580 : :
581 : : /**
582 : : * gst_mixer_mixer_changed:
583 : : * @mixer: the #GstMixer (a #GstElement) which has changed
584 : : *
585 : : * This function is called by the mixer implementation to produce
586 : : * a notification message on the bus indicating that the list of available
587 : : * mixer tracks for a given mixer object has changed. Applications should
588 : : * rebuild their interface when they receive this message.
589 : : *
590 : : * This function only works for GstElements that are implementing the
591 : : * GstMixer interface, and the element needs to have been provided a bus.
592 : : *
593 : : * Since: 0.10.18
594 : : */
595 : : void
596 : 1 : gst_mixer_mixer_changed (GstMixer * mixer)
597 : : {
598 : : GstStructure *s;
599 : : GstMessage *m;
600 : :
601 [ - + ]: 1 : g_return_if_fail (mixer != NULL);
602 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_ELEMENT (mixer));
[ - + ][ - + ]
603 : :
604 : 1 : s = gst_structure_new (GST_MIXER_MESSAGE_NAME,
605 : : "type", G_TYPE_STRING, "mixer-changed", NULL);
606 : :
607 : 1 : m = gst_message_new_element (GST_OBJECT (mixer), s);
608 [ - + ]: 1 : if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) {
609 [ # # ]: 1 : GST_WARNING ("This element has no bus, therefore no message sent!");
610 : : }
611 : : }
612 : :
613 : : static gboolean
614 : 26 : gst_mixer_message_is_mixer_message (GstMessage * message)
615 : : {
616 : : const GstStructure *s;
617 : :
618 [ - + ]: 26 : if (message == NULL)
619 : 0 : return FALSE;
620 [ - + ]: 26 : if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
621 : 0 : return FALSE;
622 : :
623 : 26 : s = gst_message_get_structure (message);
624 : 26 : return gst_structure_has_name (s, GST_MIXER_MESSAGE_NAME);
625 : : }
626 : :
627 : : /**
628 : : * gst_mixer_message_get_type:
629 : : * @message: A GstMessage to inspect.
630 : : *
631 : : * Check a bus message to see if it is a GstMixer notification
632 : : * message and return the GstMixerMessageType identifying which
633 : : * type of notification it is.
634 : : *
635 : : * Returns: The type of the GstMixerMessage, or GST_MIXER_MESSAGE_INVALID
636 : : * if the message is not a GstMixer notification.
637 : : *
638 : : * Since: 0.10.14
639 : : */
640 : : GstMixerMessageType
641 : 16 : gst_mixer_message_get_type (GstMessage * message)
642 : : {
643 : : const GstStructure *s;
644 : : const gchar *m_type;
645 : :
646 [ - + ]: 16 : if (!gst_mixer_message_is_mixer_message (message))
647 : 0 : return GST_MIXER_MESSAGE_INVALID;
648 : :
649 : 16 : s = gst_message_get_structure (message);
650 : 16 : m_type = gst_structure_get_string (s, "type");
651 [ - + ]: 16 : g_return_val_if_fail (m_type != NULL, GST_MIXER_MESSAGE_INVALID);
652 : :
653 [ + + ]: 16 : if (g_str_equal (m_type, "mute-toggled"))
654 : 3 : return GST_MIXER_MESSAGE_MUTE_TOGGLED;
655 [ + + ]: 13 : else if (g_str_equal (m_type, "record-toggled"))
656 : 3 : return GST_MIXER_MESSAGE_RECORD_TOGGLED;
657 [ + + ]: 10 : else if (g_str_equal (m_type, "volume-changed"))
658 : 4 : return GST_MIXER_MESSAGE_VOLUME_CHANGED;
659 [ + + ]: 6 : else if (g_str_equal (m_type, "option-changed"))
660 : 3 : return GST_MIXER_MESSAGE_OPTION_CHANGED;
661 [ + + ]: 3 : else if (g_str_equal (m_type, "options-list-changed"))
662 : 2 : return GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED;
663 [ + - ]: 1 : else if (g_str_equal (m_type, "mixer-changed"))
664 : 1 : return GST_MIXER_MESSAGE_MIXER_CHANGED;
665 : :
666 : 16 : return GST_MIXER_MESSAGE_INVALID;
667 : : }
668 : :
669 : : #define GST_MIXER_MESSAGE_HAS_TYPE(msg,msg_type) \
670 : : (gst_mixer_message_get_type (msg) == GST_MIXER_MESSAGE_ ## msg_type)
671 : :
672 : : /**
673 : : * gst_mixer_message_parse_mute_toggled:
674 : : * @message: A mute-toggled change notification message.
675 : : * @track: Pointer to hold a GstMixerTrack object, or NULL.
676 : : * @mute: A pointer to a gboolean variable, or NULL.
677 : : *
678 : : * Extracts the contents of a mute-toggled bus message. Reads
679 : : * the GstMixerTrack that has changed, and the new value of the mute
680 : : * flag.
681 : : *
682 : : * The GstMixerTrack remains valid until the message is freed.
683 : : *
684 : : * Since: 0.10.14
685 : : */
686 : : void
687 : 2 : gst_mixer_message_parse_mute_toggled (GstMessage * message,
688 : : GstMixerTrack ** track, gboolean * mute)
689 : : {
690 : : const GstStructure *s;
691 : :
692 [ - + ]: 2 : g_return_if_fail (gst_mixer_message_is_mixer_message (message));
693 [ - + ]: 2 : g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, MUTE_TOGGLED));
694 : :
695 : 2 : s = gst_message_get_structure (message);
696 : :
697 [ + + ]: 2 : if (track) {
698 : 1 : const GValue *v = gst_structure_get_value (s, "track");
699 : :
700 [ - + ]: 1 : g_return_if_fail (v != NULL);
701 : 1 : *track = (GstMixerTrack *) g_value_get_object (v);
702 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_MIXER_TRACK (*track));
[ + - ][ - + ]
703 : : }
704 : :
705 [ + + ]: 2 : if (mute)
706 [ - + ]: 2 : g_return_if_fail (gst_structure_get_boolean (s, "mute", mute));
707 : : }
708 : :
709 : : /**
710 : : * gst_mixer_message_parse_record_toggled:
711 : : * @message: A record-toggled change notification message.
712 : : * @track: Pointer to hold a GstMixerTrack object, or NULL.
713 : : * @record: A pointer to a gboolean variable, or NULL.
714 : : *
715 : : * Extracts the contents of a record-toggled bus message. Reads
716 : : * the GstMixerTrack that has changed, and the new value of the
717 : : * recording flag.
718 : : *
719 : : * The GstMixerTrack remains valid until the message is freed.
720 : : *
721 : : * Since: 0.10.14
722 : : */
723 : : void
724 : 2 : gst_mixer_message_parse_record_toggled (GstMessage * message,
725 : : GstMixerTrack ** track, gboolean * record)
726 : : {
727 : : const GstStructure *s;
728 : :
729 [ - + ]: 2 : g_return_if_fail (gst_mixer_message_is_mixer_message (message));
730 [ - + ]: 2 : g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, RECORD_TOGGLED));
731 : :
732 : 2 : s = gst_message_get_structure (message);
733 : :
734 [ + + ]: 2 : if (track) {
735 : 1 : const GValue *v = gst_structure_get_value (s, "track");
736 : :
737 [ - + ]: 1 : g_return_if_fail (v != NULL);
738 : 1 : *track = (GstMixerTrack *) g_value_get_object (v);
739 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_MIXER_TRACK (*track));
[ + - ][ - + ]
740 : : }
741 : :
742 [ + + ]: 2 : if (record)
743 [ - + ]: 2 : g_return_if_fail (gst_structure_get_boolean (s, "record", record));
744 : : }
745 : :
746 : : /**
747 : : * gst_mixer_message_parse_volume_changed:
748 : : * @message: A volume-changed change notification message.
749 : : * @track: Pointer to hold a GstMixerTrack object, or NULL.
750 : : * @volumes: A pointer to receive an array of gint values, or NULL.
751 : : * @num_channels: Result location to receive the number of channels, or NULL.
752 : : *
753 : : * Parses a volume-changed notification message and extracts the track object
754 : : * it refers to, as well as an array of volumes and the size of the volumes array.
755 : : *
756 : : * The track object remains valid until the message is freed.
757 : : *
758 : : * The caller must free the array returned in the volumes parameter using g_free
759 : : * when they are done with it.
760 : : *
761 : : * Since: 0.10.14
762 : : */
763 : : void
764 : 3 : gst_mixer_message_parse_volume_changed (GstMessage * message,
765 : : GstMixerTrack ** track, gint ** volumes, gint * num_channels)
766 : : {
767 : : const GstStructure *s;
768 : :
769 [ - + ]: 3 : g_return_if_fail (gst_mixer_message_is_mixer_message (message));
770 [ - + ]: 3 : g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, VOLUME_CHANGED));
771 : :
772 : 3 : s = gst_message_get_structure (message);
773 : :
774 [ + + ]: 3 : if (track) {
775 : 1 : const GValue *v = gst_structure_get_value (s, "track");
776 : :
777 [ - + ]: 1 : g_return_if_fail (v != NULL);
778 : 1 : *track = (GstMixerTrack *) g_value_get_object (v);
779 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_MIXER_TRACK (*track));
[ + - ][ - + ]
780 : : }
781 : :
782 [ + + ][ + + ]: 3 : if (volumes || num_channels) {
783 : : gint n_chans, i;
784 : 2 : const GValue *v = gst_structure_get_value (s, "volumes");
785 : :
786 [ - + ]: 2 : g_return_if_fail (v != NULL);
787 [ - + ][ + - ]: 2 : g_return_if_fail (GST_VALUE_HOLDS_ARRAY (v));
[ - + ]
788 : :
789 : 2 : n_chans = gst_value_array_get_size (v);
790 [ + - ]: 2 : if (num_channels)
791 : 2 : *num_channels = n_chans;
792 : :
793 [ + + ]: 2 : if (volumes) {
794 : 1 : *volumes = g_new (gint, n_chans);
795 [ + + ]: 5 : for (i = 0; i < n_chans; i++) {
796 : 2 : const GValue *e = gst_value_array_get_value (v, i);
797 : :
798 [ + - ][ - + ]: 2 : g_return_if_fail (e != NULL && G_VALUE_HOLDS_INT (e));
[ + - ][ + - ]
799 : 2 : (*volumes)[i] = g_value_get_int (e);
800 : : }
801 : : }
802 : : }
803 : : }
804 : :
805 : : /**
806 : : * gst_mixer_message_parse_option_changed:
807 : : * @message: A volume-changed change notification message.
808 : : * @options: Pointer to hold a GstMixerOptions object, or NULL.
809 : : * @value: Result location to receive the new options value, or NULL.
810 : : *
811 : : * Extracts the GstMixerOptions and new value from a option-changed bus notification
812 : : * message.
813 : : *
814 : : * The options and value returned remain valid until the message is freed.
815 : : *
816 : : * Since: 0.10.14
817 : : */
818 : : void
819 : 2 : gst_mixer_message_parse_option_changed (GstMessage * message,
820 : : GstMixerOptions ** options, const gchar ** value)
821 : : {
822 : : const GstStructure *s;
823 : :
824 [ - + ]: 2 : g_return_if_fail (gst_mixer_message_is_mixer_message (message));
825 [ - + ]: 2 : g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, OPTION_CHANGED));
826 : :
827 : 2 : s = gst_message_get_structure (message);
828 : :
829 [ + + ]: 2 : if (options) {
830 : 1 : const GValue *v = gst_structure_get_value (s, "options");
831 : :
832 [ - + ]: 1 : g_return_if_fail (v != NULL);
833 : 1 : *options = (GstMixerOptions *) g_value_get_object (v);
834 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_MIXER_OPTIONS (*options));
[ + - ][ - + ]
835 : : }
836 : :
837 [ + + ]: 2 : if (value)
838 : 2 : *value = gst_structure_get_string (s, "value");
839 : : }
840 : :
841 : : /**
842 : : * gst_mixer_message_parse_options_list_changed:
843 : : * @message: A volume-changed change notification message.
844 : : * @options: Pointer to hold a GstMixerOptions object, or NULL.
845 : : *
846 : : * Extracts the GstMixerOptions whose value list has changed from an
847 : : * options-list-changed bus notification message.
848 : : *
849 : : * The options object returned remains valid until the message is freed. You
850 : : * do not need to unref it.
851 : : *
852 : : * Since: 0.10.18
853 : : */
854 : : void
855 : 1 : gst_mixer_message_parse_options_list_changed (GstMessage * message,
856 : : GstMixerOptions ** options)
857 : : {
858 : : const GstStructure *s;
859 : :
860 [ - + ]: 1 : g_return_if_fail (gst_mixer_message_is_mixer_message (message));
861 [ - + ]: 1 : g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, OPTIONS_LIST_CHANGED));
862 : :
863 : 1 : s = gst_message_get_structure (message);
864 : :
865 [ + - ]: 1 : if (options) {
866 : 1 : const GValue *v = gst_structure_get_value (s, "options");
867 : :
868 [ - + ]: 1 : g_return_if_fail (v != NULL);
869 : 1 : *options = (GstMixerOptions *) g_value_get_object (v);
870 [ - + ][ + - ]: 1 : g_return_if_fail (GST_IS_MIXER_OPTIONS (*options));
[ + - ][ - + ]
871 : : }
872 : : }
|