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