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"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <gio/gio.h>
9 : : #include <libpeas.h>
10 : : #include <libvalent-core.h>
11 : :
12 : : #include "valent-mixer-adapter.h"
13 : : #include "valent-mixer-stream.h"
14 : :
15 : : #include "valent-mixer.h"
16 : :
17 : : /**
18 : : * ValentMixer:
19 : : *
20 : : * A class for monitoring and controlling the system volume.
21 : : *
22 : : * `ValentMixer` is an abstraction of volume mixers, intended for use by
23 : : * [class@Valent.DevicePlugin] implementations.
24 : : *
25 : : * Plugins can implement [class@Valent.MixerAdapter] to provide an interface to
26 : : * monitor and control audio streams.
27 : : *
28 : : * Since: 1.0
29 : : */
30 : : struct _ValentMixer
31 : : {
32 : : ValentComponent parent_instance;
33 : :
34 : : ValentMixerAdapter *default_adapter;
35 : : };
36 : :
37 [ + + + - ]: 195 : G_DEFINE_FINAL_TYPE (ValentMixer, valent_mixer, VALENT_TYPE_COMPONENT)
38 : :
39 : : typedef enum {
40 : : PROP_DEFAULT_INPUT = 1,
41 : : PROP_DEFAULT_OUTPUT,
42 : : } ValentMixerProperty;
43 : :
44 : : static GParamSpec *properties[PROP_DEFAULT_OUTPUT + 1] = { NULL, };
45 : :
46 : : /*
47 : : * ValentMixerAdapter Callbacks
48 : : */
49 : : static void
50 : 10 : on_default_input_changed (ValentMixerAdapter *adapter,
51 : : GParamSpec *pspec,
52 : : ValentMixer *self)
53 : : {
54 [ + - ]: 10 : if (self->default_adapter != adapter)
55 : : return;
56 : :
57 : 10 : g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DEFAULT_INPUT]);
58 : : }
59 : :
60 : : static void
61 : 14 : on_default_output_changed (ValentMixerAdapter *adapter,
62 : : GParamSpec *pspec,
63 : : ValentMixer *self)
64 : : {
65 [ + - ]: 14 : if (self->default_adapter != adapter)
66 : : return;
67 : :
68 : 14 : g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DEFAULT_OUTPUT]);
69 : : }
70 : :
71 : : /*
72 : : * ValentComponent
73 : : */
74 : : static void
75 : 22 : valent_mixer_bind_preferred (ValentComponent *component,
76 : : ValentExtension *extension)
77 : : {
78 : 22 : ValentMixer *self = VALENT_MIXER (component);
79 : 22 : ValentMixerAdapter *adapter = VALENT_MIXER_ADAPTER (extension);
80 : :
81 : 22 : VALENT_ENTRY;
82 : :
83 [ + - ]: 22 : g_assert (VALENT_IS_MIXER (self));
84 [ + + - + ]: 22 : g_assert (adapter == NULL || VALENT_IS_MIXER_ADAPTER (adapter));
85 : :
86 [ + + ]: 22 : if (self->default_adapter != NULL)
87 : : {
88 : 11 : g_signal_handlers_disconnect_by_func (self->default_adapter,
89 : : self,
90 : : on_default_input_changed);
91 : 11 : g_signal_handlers_disconnect_by_func (self->default_adapter,
92 : : self,
93 : : on_default_output_changed);
94 : 11 : self->default_adapter = NULL;
95 : : }
96 : :
97 [ + + ]: 22 : if (adapter != NULL)
98 : : {
99 : 11 : self->default_adapter = adapter;
100 : 11 : g_signal_connect_object (self->default_adapter,
101 : : "notify::default-input",
102 : : G_CALLBACK (on_default_input_changed),
103 : : self,
104 : : G_CONNECT_DEFAULT);
105 : 11 : g_object_notify (G_OBJECT (self), "default-input");
106 : 11 : g_signal_connect_object (self->default_adapter,
107 : : "notify::default-output",
108 : : G_CALLBACK (on_default_output_changed),
109 : : self,
110 : : G_CONNECT_DEFAULT);
111 : 11 : g_object_notify (G_OBJECT (self), "default-output");
112 : : }
113 : :
114 : 22 : VALENT_EXIT;
115 : : }
116 : :
117 : : /*
118 : : * GObject
119 : : */
120 : : static void
121 : 2 : valent_mixer_get_property (GObject *object,
122 : : guint prop_id,
123 : : GValue *value,
124 : : GParamSpec *pspec)
125 : : {
126 : 2 : ValentMixer *self = VALENT_MIXER (object);
127 : :
128 [ + + - ]: 2 : switch ((ValentMixerProperty)prop_id)
129 : : {
130 : 1 : case PROP_DEFAULT_INPUT:
131 : 1 : g_value_set_object (value, valent_mixer_get_default_input (self));
132 : 1 : break;
133 : :
134 : 1 : case PROP_DEFAULT_OUTPUT:
135 : 1 : g_value_set_object (value, valent_mixer_get_default_output (self));
136 : 1 : break;
137 : :
138 : 0 : default:
139 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
140 : : }
141 : 2 : }
142 : :
143 : : static void
144 : 2 : valent_mixer_set_property (GObject *object,
145 : : guint prop_id,
146 : : const GValue *value,
147 : : GParamSpec *pspec)
148 : : {
149 : 2 : ValentMixer *self = VALENT_MIXER (object);
150 : :
151 [ + + - ]: 2 : switch ((ValentMixerProperty)prop_id)
152 : : {
153 : 1 : case PROP_DEFAULT_INPUT:
154 : 1 : valent_mixer_set_default_input (self, g_value_get_object (value));
155 : 1 : break;
156 : :
157 : 1 : case PROP_DEFAULT_OUTPUT:
158 : 1 : valent_mixer_set_default_output (self, g_value_get_object (value));
159 : 1 : break;
160 : :
161 : 0 : default:
162 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
163 : : }
164 : 2 : }
165 : :
166 : : static void
167 : 4 : valent_mixer_class_init (ValentMixerClass *klass)
168 : : {
169 : 4 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
170 : 4 : ValentComponentClass *component_class = VALENT_COMPONENT_CLASS (klass);
171 : :
172 : 4 : object_class->get_property = valent_mixer_get_property;
173 : 4 : object_class->set_property = valent_mixer_set_property;
174 : :
175 : 4 : component_class->bind_preferred = valent_mixer_bind_preferred;
176 : :
177 : : /**
178 : : * ValentMixer:default-input: (getter get_default_input) (setter set_default_input)
179 : : *
180 : : * The active input stream.
181 : : *
182 : : * Since: 1.0
183 : : */
184 : 8 : properties [PROP_DEFAULT_INPUT] =
185 : 4 : g_param_spec_object ("default-input", NULL, NULL,
186 : : VALENT_TYPE_MIXER_STREAM,
187 : : (G_PARAM_READWRITE |
188 : : G_PARAM_EXPLICIT_NOTIFY |
189 : : G_PARAM_STATIC_STRINGS));
190 : :
191 : : /**
192 : : * ValentMixer:default-output: (getter get_default_output) (setter set_default_output)
193 : : *
194 : : * The active output stream.
195 : : *
196 : : * Since: 1.0
197 : : */
198 : 8 : properties [PROP_DEFAULT_OUTPUT] =
199 : 4 : g_param_spec_object ("default-output", NULL, NULL,
200 : : VALENT_TYPE_MIXER_STREAM,
201 : : (G_PARAM_READWRITE |
202 : : G_PARAM_EXPLICIT_NOTIFY |
203 : : G_PARAM_STATIC_STRINGS));
204 : :
205 : 4 : g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
206 : 4 : }
207 : :
208 : : static void
209 : 11 : valent_mixer_init (ValentMixer *self)
210 : : {
211 : 11 : }
212 : :
213 : : /**
214 : : * valent_mixer_get_default:
215 : : *
216 : : * Get the default [class@Valent.Mixer].
217 : : *
218 : : * Returns: (transfer none) (not nullable): a `ValentMixer`
219 : : *
220 : : * Since: 1.0
221 : : */
222 : : ValentMixer *
223 : 64 : valent_mixer_get_default (void)
224 : : {
225 : 64 : static ValentMixer *default_instance = NULL;
226 : :
227 [ + + ]: 64 : if (default_instance == NULL)
228 : : {
229 : 11 : default_instance = g_object_new (VALENT_TYPE_MIXER,
230 : : "plugin-domain", "mixer",
231 : : "plugin-type", VALENT_TYPE_MIXER_ADAPTER,
232 : : NULL);
233 : 11 : g_object_add_weak_pointer (G_OBJECT (default_instance),
234 : : (gpointer)&default_instance);
235 : : }
236 : :
237 : 64 : return default_instance;
238 : : }
239 : :
240 : : /**
241 : : * valent_mixer_get_default_input: (get-property default-input)
242 : : * @mixer: a `ValentMixer`
243 : : *
244 : : * Get the default input stream for the primary [class@Valent.MixerAdapter].
245 : : *
246 : : * Returns: (transfer none) (nullable): a `ValentMixerStream`
247 : : *
248 : : * Since: 1.0
249 : : */
250 : : ValentMixerStream *
251 : 10 : valent_mixer_get_default_input (ValentMixer *mixer)
252 : : {
253 : 10 : ValentMixerStream *ret = NULL;
254 : :
255 : 10 : VALENT_ENTRY;
256 : :
257 [ + - ]: 10 : g_return_val_if_fail (VALENT_IS_MIXER (mixer), NULL);
258 : :
259 [ - + ]: 10 : if G_LIKELY (mixer->default_adapter != NULL)
260 : 10 : ret = valent_mixer_adapter_get_default_input (mixer->default_adapter);
261 : :
262 : 10 : VALENT_RETURN (ret);
263 : : }
264 : :
265 : : /**
266 : : * valent_mixer_set_default_input: (set-property default-input)
267 : : * @mixer: a `ValentMixer`
268 : : * @stream: a `ValentMixerStream`
269 : : *
270 : : * Set the default input stream for the primary [class@Valent.MixerAdapter].
271 : : *
272 : : * Since: 1.0
273 : : */
274 : : void
275 : 1 : valent_mixer_set_default_input (ValentMixer *mixer,
276 : : ValentMixerStream *stream)
277 : : {
278 : 1 : VALENT_ENTRY;
279 : :
280 [ + - ]: 1 : g_return_if_fail (VALENT_IS_MIXER (mixer));
281 [ - + ]: 1 : g_return_if_fail (VALENT_IS_MIXER_STREAM (stream));
282 : :
283 [ + - ]: 1 : if G_LIKELY (mixer->default_adapter != NULL)
284 : 1 : valent_mixer_adapter_set_default_input (mixer->default_adapter, stream);
285 : :
286 : 1 : VALENT_EXIT;
287 : : }
288 : :
289 : : /**
290 : : * valent_mixer_get_default_output: (get-property default-output)
291 : : * @mixer: a `ValentMixer`
292 : : *
293 : : * Get the default output stream for the primary [class@Valent.MixerAdapter].
294 : : *
295 : : * Returns: (transfer none) (nullable): a `ValentMixerStream`
296 : : *
297 : : * Since: 1.0
298 : : */
299 : : ValentMixerStream *
300 : 10 : valent_mixer_get_default_output (ValentMixer *mixer)
301 : : {
302 : 10 : ValentMixerStream *ret = NULL;
303 : :
304 : 10 : VALENT_ENTRY;
305 : :
306 [ + - ]: 10 : g_return_val_if_fail (VALENT_IS_MIXER (mixer), NULL);
307 : :
308 [ - + ]: 10 : if G_LIKELY (mixer->default_adapter != NULL)
309 : 10 : ret = valent_mixer_adapter_get_default_output (mixer->default_adapter);
310 : :
311 : 10 : VALENT_RETURN (ret);
312 : : }
313 : :
314 : : /**
315 : : * valent_mixer_set_default_output: (set-property default-output)
316 : : * @mixer: a `ValentMixer`
317 : : * @stream: a `ValentMixerStream`
318 : : *
319 : : * Set the default output stream for the primary [class@Valent.MixerAdapter].
320 : : *
321 : : * Since: 1.0
322 : : */
323 : : void
324 : 1 : valent_mixer_set_default_output (ValentMixer *mixer,
325 : : ValentMixerStream *stream)
326 : : {
327 : 1 : VALENT_ENTRY;
328 : :
329 [ + - ]: 1 : g_return_if_fail (VALENT_IS_MIXER (mixer));
330 [ - + ]: 1 : g_return_if_fail (VALENT_IS_MIXER_STREAM (stream));
331 : :
332 [ + - ]: 1 : if G_LIKELY (mixer->default_adapter != NULL)
333 : 1 : valent_mixer_adapter_set_default_output (mixer->default_adapter, stream);
334 : :
335 : 1 : VALENT_EXIT;
336 : : }
337 : :
|