Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-mixer-adapter"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <gio/gio.h>
9 : : #include <libvalent-core.h>
10 : :
11 : : #include "valent-mixer.h"
12 : : #include "valent-mixer-adapter.h"
13 : :
14 : :
15 : : /**
16 : : * ValentMixerAdapter
17 : : *
18 : : * An abstract base class for audio mixers.
19 : : *
20 : : * `ValentMixerAdapter` is a base class for plugins that provide an interface to
21 : : * audio mixers and volume control. This usually means monitoring the available
22 : : * input and output streams, changing properties on those streams, and selecting
23 : : * which are the active input and output.
24 : : *
25 : : * ## `.plugin` File
26 : : *
27 : : * Implementations may define the following extra fields in the `.plugin` file:
28 : : *
29 : : * - `X-MixerAdapterPriority`
30 : : *
31 : : * An integer indicating the adapter priority. The implementation with the
32 : : * lowest value will be used as the primary adapter.
33 : : *
34 : : * Since: 1.0
35 : : */
36 : :
37 : : typedef struct
38 : : {
39 : : GPtrArray *streams;
40 : : } ValentMixerAdapterPrivate;
41 : :
42 : : static void g_list_model_iface_init (GListModelInterface *iface);
43 : :
44 [ + + + - ]: 681 : G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ValentMixerAdapter, valent_mixer_adapter, VALENT_TYPE_EXTENSION,
45 : : G_ADD_PRIVATE (ValentMixerAdapter)
46 : : G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, g_list_model_iface_init))
47 : :
48 : :
49 : : /**
50 : : * ValentMixerAdapterClass:
51 : : * @get_default_input: the virtual function pointer for valent_mixer_adapter_get_default_input()
52 : : * @set_default_input: the virtual function pointer for valent_mixer_adapter_set_default_input()
53 : : * @get_default_output: the virtual function pointer for valent_mixer_adapter_get_default_output()
54 : : * @set_default_output: the virtual function pointer for valent_mixer_adapter_set_default_output()
55 : : *
56 : : * The virtual function table for `ValentMixerAdapter`.
57 : : */
58 : :
59 : : enum {
60 : : PROP_0,
61 : : PROP_DEFAULT_INPUT,
62 : : PROP_DEFAULT_OUTPUT,
63 : : N_PROPERTIES
64 : : };
65 : :
66 : : static GParamSpec *properties[N_PROPERTIES] = { NULL, };
67 : :
68 : :
69 : : /*
70 : : * GListModel
71 : : */
72 : : static gpointer
73 : 50 : valent_mixer_adapter_get_item (GListModel *list,
74 : : unsigned int position)
75 : : {
76 : 50 : ValentMixerAdapter *self = VALENT_MIXER_ADAPTER (list);
77 : 50 : ValentMixerAdapterPrivate *priv = valent_mixer_adapter_get_instance_private (self);
78 : :
79 [ + - ]: 50 : g_assert (VALENT_IS_MIXER_ADAPTER (self));
80 : :
81 [ + - ]: 50 : if G_UNLIKELY (position >= priv->streams->len)
82 : : return NULL;
83 : :
84 : 50 : return g_object_ref (g_ptr_array_index (priv->streams, position));
85 : : }
86 : :
87 : : static GType
88 : 0 : valent_mixer_adapter_get_item_type (GListModel *list)
89 : : {
90 : 0 : return VALENT_TYPE_MIXER_STREAM;
91 : : }
92 : :
93 : : static unsigned int
94 : 10 : valent_mixer_adapter_get_n_items (GListModel *list)
95 : : {
96 : 10 : ValentMixerAdapter *self = VALENT_MIXER_ADAPTER (list);
97 : 10 : ValentMixerAdapterPrivate *priv = valent_mixer_adapter_get_instance_private (self);
98 : :
99 [ + - ]: 10 : g_assert (VALENT_IS_MIXER_ADAPTER (self));
100 : :
101 : 10 : return priv->streams->len;
102 : : }
103 : :
104 : : static void
105 : 66 : g_list_model_iface_init (GListModelInterface *iface)
106 : : {
107 : 66 : iface->get_item = valent_mixer_adapter_get_item;
108 : 66 : iface->get_item_type = valent_mixer_adapter_get_item_type;
109 : 66 : iface->get_n_items = valent_mixer_adapter_get_n_items;
110 : 66 : }
111 : :
112 : : /* LCOV_EXCL_START */
113 : : static ValentMixerStream *
114 : : valent_mixer_adapter_real_get_default_input (ValentMixerAdapter *adapter)
115 : : {
116 : : g_assert (VALENT_IS_MIXER_ADAPTER (adapter));
117 : :
118 : : return NULL;
119 : : }
120 : :
121 : : static void
122 : : valent_mixer_adapter_real_set_default_input (ValentMixerAdapter *adapter,
123 : : ValentMixerStream *stream)
124 : : {
125 : : g_assert (VALENT_IS_MIXER_ADAPTER (adapter));
126 : : g_assert (VALENT_IS_MIXER_STREAM (stream));
127 : : }
128 : :
129 : : static ValentMixerStream *
130 : : valent_mixer_adapter_real_get_default_output (ValentMixerAdapter *adapter)
131 : : {
132 : : g_assert (VALENT_IS_MIXER_ADAPTER (adapter));
133 : :
134 : : return NULL;
135 : : }
136 : :
137 : : static void
138 : : valent_mixer_adapter_real_set_default_output (ValentMixerAdapter *adapter,
139 : : ValentMixerStream *stream)
140 : : {
141 : : g_assert (VALENT_IS_MIXER_ADAPTER (adapter));
142 : : g_assert (VALENT_IS_MIXER_STREAM (stream));
143 : : }
144 : : /* LCOV_EXCL_STOP */
145 : :
146 : : /*
147 : : * ValentObject
148 : : */
149 : : static void
150 : 8 : valent_mixer_adapter_destroy (ValentObject *object)
151 : : {
152 : 8 : ValentMixerAdapter *self = VALENT_MIXER_ADAPTER (object);
153 : 8 : ValentMixerAdapterPrivate *priv = valent_mixer_adapter_get_instance_private (self);
154 : :
155 [ + - ]: 8 : g_clear_pointer (&priv->streams, g_ptr_array_unref);
156 : :
157 : 8 : VALENT_OBJECT_CLASS (valent_mixer_adapter_parent_class)->destroy (object);
158 : 8 : }
159 : :
160 : : /*
161 : : * GObject
162 : : */
163 : : static void
164 : 2 : valent_mixer_adapter_get_property (GObject *object,
165 : : guint prop_id,
166 : : GValue *value,
167 : : GParamSpec *pspec)
168 : : {
169 : 2 : ValentMixerAdapter *self = VALENT_MIXER_ADAPTER (object);
170 : :
171 [ + + - ]: 2 : switch (prop_id)
172 : : {
173 : 1 : case PROP_DEFAULT_INPUT:
174 : 1 : g_value_set_object (value, valent_mixer_adapter_get_default_input (self));
175 : 1 : break;
176 : :
177 : 1 : case PROP_DEFAULT_OUTPUT:
178 : 1 : g_value_set_object (value, valent_mixer_adapter_get_default_output (self));
179 : 1 : break;
180 : :
181 : 0 : default:
182 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
183 : : }
184 : 2 : }
185 : :
186 : : static void
187 : 2 : valent_mixer_adapter_set_property (GObject *object,
188 : : guint prop_id,
189 : : const GValue *value,
190 : : GParamSpec *pspec)
191 : : {
192 : 2 : ValentMixerAdapter *self = VALENT_MIXER_ADAPTER (object);
193 : :
194 [ + + - ]: 2 : switch (prop_id)
195 : : {
196 : 1 : case PROP_DEFAULT_INPUT:
197 : 1 : valent_mixer_adapter_set_default_input (self, g_value_get_object (value));
198 : 1 : break;
199 : :
200 : 1 : case PROP_DEFAULT_OUTPUT:
201 : 1 : valent_mixer_adapter_set_default_output (self, g_value_get_object (value));
202 : 1 : break;
203 : :
204 : 0 : default:
205 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
206 : : }
207 : 2 : }
208 : :
209 : : static void
210 : 66 : valent_mixer_adapter_class_init (ValentMixerAdapterClass *klass)
211 : : {
212 : 66 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
213 : 66 : ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
214 : :
215 : 66 : object_class->get_property = valent_mixer_adapter_get_property;
216 : 66 : object_class->set_property = valent_mixer_adapter_set_property;
217 : :
218 : 66 : vobject_class->destroy = valent_mixer_adapter_destroy;
219 : :
220 : 66 : klass->get_default_input = valent_mixer_adapter_real_get_default_input;
221 : 66 : klass->set_default_input = valent_mixer_adapter_real_set_default_input;
222 : 66 : klass->get_default_output = valent_mixer_adapter_real_get_default_output;
223 : 66 : klass->set_default_output = valent_mixer_adapter_real_set_default_output;
224 : :
225 : : /**
226 : : * ValentMixerAdapter:default-input: (getter get_default_input) (setter set_default_input)
227 : : *
228 : : * The active input stream.
229 : : *
230 : : * Implementations should emit [signal@GObject.Object::notify] for this
231 : : * property when the default stream changes.
232 : : *
233 : : * Since: 1.0
234 : : */
235 : 132 : properties [PROP_DEFAULT_INPUT] =
236 : 66 : g_param_spec_object ("default-input", NULL, NULL,
237 : : VALENT_TYPE_MIXER_STREAM,
238 : : (G_PARAM_READWRITE |
239 : : G_PARAM_EXPLICIT_NOTIFY |
240 : : G_PARAM_STATIC_STRINGS));
241 : :
242 : : /**
243 : : * ValentMixerAdapter:default-output: (getter get_default_output) (setter set_default_output)
244 : : *
245 : : * The active output stream.
246 : : *
247 : : * Implementations should emit [signal@GObject.Object::notify] for this
248 : : * property when the default stream changes.
249 : : *
250 : : * Since: 1.0
251 : : */
252 : 132 : properties [PROP_DEFAULT_OUTPUT] =
253 : 66 : g_param_spec_object ("default-output", NULL, NULL,
254 : : VALENT_TYPE_MIXER_STREAM,
255 : : (G_PARAM_READWRITE |
256 : : G_PARAM_EXPLICIT_NOTIFY |
257 : : G_PARAM_STATIC_STRINGS));
258 : :
259 : 66 : g_object_class_install_properties (object_class, N_PROPERTIES, properties);
260 : 66 : }
261 : :
262 : : static void
263 : 8 : valent_mixer_adapter_init (ValentMixerAdapter *self)
264 : : {
265 : 8 : ValentMixerAdapterPrivate *priv = valent_mixer_adapter_get_instance_private (self);
266 : :
267 : 8 : priv->streams = g_ptr_array_new_with_free_func (g_object_unref);
268 : 8 : }
269 : :
270 : : /**
271 : : * valent_mixer_adapter_stream_added:
272 : : * @adapter: a `ValentMixerAdapter`
273 : : * @stream: a `ValentMixerStream`
274 : : *
275 : : * Called when @stream has been added to the mixer.
276 : : *
277 : : * This method should only be called by implementations of
278 : : * [class@Valent.MixerAdapter]. @adapter will hold a reference on @stream and
279 : : * emit [signal@Gio.ListModel::items-changed].
280 : : *
281 : : * Since: 1.0
282 : : */
283 : : void
284 : 23 : valent_mixer_adapter_stream_added (ValentMixerAdapter *adapter,
285 : : ValentMixerStream *stream)
286 : : {
287 : 23 : ValentMixerAdapterPrivate *priv = valent_mixer_adapter_get_instance_private (adapter);
288 : 23 : unsigned int position = 0;
289 : :
290 [ + - ]: 23 : g_return_if_fail (VALENT_IS_MIXER_ADAPTER (adapter));
291 [ - + ]: 23 : g_return_if_fail (VALENT_IS_MIXER_STREAM (stream));
292 : :
293 : 23 : position = priv->streams->len;
294 : 23 : g_ptr_array_add (priv->streams, g_object_ref (stream));
295 : 23 : g_list_model_items_changed (G_LIST_MODEL (adapter), position, 0, 1);
296 : : }
297 : :
298 : : /**
299 : : * valent_mixer_adapter_stream_removed:
300 : : * @adapter: a `ValentMixerAdapter`
301 : : * @stream: a `ValentMixerStream`
302 : : *
303 : : * Called when @stream has been removed from the mixer.
304 : : *
305 : : * This method should only be called by implementations of
306 : : * [class@Valent.MixerAdapter]. @adapter will drop its reference on @stream and
307 : : * emit [signal@Gio.ListModel::items-changed].
308 : : *
309 : : * Since: 1.0
310 : : */
311 : : void
312 : 5 : valent_mixer_adapter_stream_removed (ValentMixerAdapter *adapter,
313 : : ValentMixerStream *stream)
314 : : {
315 : 5 : ValentMixerAdapterPrivate *priv = valent_mixer_adapter_get_instance_private (adapter);
316 : 5 : g_autoptr (ValentMixerStream) item = NULL;
317 : 5 : unsigned int position = 0;
318 : :
319 [ + - ]: 5 : g_return_if_fail (VALENT_IS_MIXER_ADAPTER (adapter));
320 [ - + ]: 5 : g_return_if_fail (VALENT_IS_MIXER_STREAM (stream));
321 : :
322 [ + - ]: 5 : if (!g_ptr_array_find (priv->streams, stream, &position))
323 : : return;
324 : :
325 : 5 : item = g_ptr_array_steal_index (priv->streams, position);
326 [ + - ]: 5 : g_list_model_items_changed (G_LIST_MODEL (adapter), position, 1, 0);
327 : : }
328 : :
329 : : /**
330 : : * valent_mixer_adapter_get_default_input: (get-property default-input) (virtual get_default_input)
331 : : * @adapter: a `ValentMixerAdapter`
332 : : *
333 : : * Get the default input stream for @adapter.
334 : : *
335 : : * Returns: (transfer none): a `ValentMixerStream`
336 : : *
337 : : * Since: 1.0
338 : : */
339 : : ValentMixerStream *
340 : 13 : valent_mixer_adapter_get_default_input (ValentMixerAdapter *adapter)
341 : : {
342 : 13 : ValentMixerStream *ret;
343 : :
344 : 13 : VALENT_ENTRY;
345 : :
346 [ + - ]: 13 : g_return_val_if_fail (VALENT_IS_MIXER_ADAPTER (adapter), NULL);
347 : :
348 : 13 : ret = VALENT_MIXER_ADAPTER_GET_CLASS (adapter)->get_default_input (adapter);
349 : :
350 : 13 : VALENT_RETURN (ret);
351 : : }
352 : :
353 : : /**
354 : : * valent_mixer_adapter_set_default_input: (set-property default-input) (virtual set_default_input)
355 : : * @adapter: a `ValentMixerAdapter`
356 : : * @stream: a `ValentMixerStream`
357 : : *
358 : : * Set the default input stream for @adapter to @stream.
359 : : *
360 : : * Since: 1.0
361 : : */
362 : : void
363 : 11 : valent_mixer_adapter_set_default_input (ValentMixerAdapter *adapter,
364 : : ValentMixerStream *stream)
365 : : {
366 : 11 : VALENT_ENTRY;
367 : :
368 [ + - ]: 11 : g_return_if_fail (VALENT_IS_MIXER_ADAPTER (adapter));
369 [ - + ]: 11 : g_return_if_fail (VALENT_IS_MIXER_STREAM (stream));
370 : :
371 : 11 : VALENT_MIXER_ADAPTER_GET_CLASS (adapter)->set_default_input (adapter, stream);
372 : :
373 : 11 : VALENT_EXIT;
374 : : }
375 : :
376 : : /**
377 : : * valent_mixer_adapter_get_default_output: (get-property default-output) (virtual get_default_output)
378 : : * @adapter: a `ValentMixerAdapter`
379 : : *
380 : : * Get the default output stream for @adapter.
381 : : *
382 : : * Returns: (transfer none): a `ValentMixerStream`
383 : : *
384 : : * Since: 1.0
385 : : */
386 : : ValentMixerStream *
387 : 25 : valent_mixer_adapter_get_default_output (ValentMixerAdapter *adapter)
388 : : {
389 : 25 : ValentMixerStream *ret;
390 : :
391 : 25 : VALENT_ENTRY;
392 : :
393 [ + - ]: 25 : g_return_val_if_fail (VALENT_IS_MIXER_ADAPTER (adapter), NULL);
394 : :
395 : 25 : ret = VALENT_MIXER_ADAPTER_GET_CLASS (adapter)->get_default_output (adapter);
396 : :
397 : 25 : VALENT_RETURN (ret);
398 : : }
399 : :
400 : : /**
401 : : * valent_mixer_adapter_set_default_output: (set-property default-output) (virtual set_default_output)
402 : : * @adapter: a `ValentMixerAdapter`
403 : : * @stream: a `ValentMixerStream`
404 : : *
405 : : * Set the default output stream for @adapter to @stream.
406 : : *
407 : : * Since: 1.0
408 : : */
409 : : void
410 : 14 : valent_mixer_adapter_set_default_output (ValentMixerAdapter *adapter,
411 : : ValentMixerStream *stream)
412 : : {
413 : 14 : VALENT_ENTRY;
414 : :
415 [ + - ]: 14 : g_return_if_fail (VALENT_IS_MIXER_ADAPTER (adapter));
416 [ - + ]: 14 : g_return_if_fail (VALENT_IS_MIXER_STREAM (stream));
417 : :
418 : 14 : VALENT_MIXER_ADAPTER_GET_CLASS (adapter)->set_default_output (adapter, stream);
419 : :
420 : 14 : VALENT_EXIT;
421 : : }
422 : :
|