]> code.delx.au - pulseaudio/blob - src/modules/dbus/iface-device.c
Rename all the signal parameters and variables to something more explicit.
[pulseaudio] / src / modules / dbus / iface-device.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2009 Tanu Kaskinen
5
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <pulsecore/core-util.h>
27 #include <pulsecore/dbus-util.h>
28 #include <pulsecore/protocol-dbus.h>
29
30 #include "iface-device-port.h"
31
32 #include "iface-device.h"
33
34 #define SINK_OBJECT_NAME "sink"
35 #define SOURCE_OBJECT_NAME "source"
36
37 static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata);
38 static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
39 static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata);
40 static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata);
41 static void handle_get_card(DBusConnection *conn, DBusMessage *msg, void *userdata);
42 static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata);
43 static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata);
44 static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata);
45 static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
46 static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
47 static void handle_get_has_flat_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
48 static void handle_get_has_convertible_to_decibel_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
49 static void handle_get_base_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
50 static void handle_get_volume_steps(DBusConnection *conn, DBusMessage *msg, void *userdata);
51 static void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
52 static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
53 static void handle_get_has_hardware_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
54 static void handle_get_has_hardware_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
55 static void handle_get_configured_latency(DBusConnection *conn, DBusMessage *msg, void *userdata);
56 static void handle_get_has_dynamic_latency(DBusConnection *conn, DBusMessage *msg, void *userdata);
57 static void handle_get_latency(DBusConnection *conn, DBusMessage *msg, void *userdata);
58 static void handle_get_is_hardware_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
59 static void handle_get_is_network_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
60 static void handle_get_state(DBusConnection *conn, DBusMessage *msg, void *userdata);
61 static void handle_get_ports(DBusConnection *conn, DBusMessage *msg, void *userdata);
62 static void handle_get_active_port(DBusConnection *conn, DBusMessage *msg, void *userdata);
63 static void handle_set_active_port(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
64 static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
65
66 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
67
68 static void handle_suspend(DBusConnection *conn, DBusMessage *msg, void *userdata);
69 static void handle_get_port_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
70
71 static void handle_sink_get_monitor_source(DBusConnection *conn, DBusMessage *msg, void *userdata);
72
73 static void handle_sink_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
74
75 static void handle_source_get_monitor_of_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
76
77 static void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
78
79 enum device_type {
80 DEVICE_TYPE_SINK,
81 DEVICE_TYPE_SOURCE
82 };
83
84 struct pa_dbusiface_device {
85 pa_dbusiface_core *core;
86
87 union {
88 pa_sink *sink;
89 pa_source *source;
90 };
91 enum device_type type;
92 char *path;
93 pa_cvolume volume;
94 dbus_bool_t mute;
95 union {
96 pa_sink_state_t sink_state;
97 pa_source_state_t source_state;
98 };
99 pa_hashmap *ports;
100 uint32_t next_port_index;
101 pa_device_port *active_port;
102 pa_proplist *proplist;
103
104 pa_dbus_protocol *dbus_protocol;
105 pa_subscription *subscription;
106 };
107
108 enum property_handler_index {
109 PROPERTY_HANDLER_INDEX,
110 PROPERTY_HANDLER_NAME,
111 PROPERTY_HANDLER_DRIVER,
112 PROPERTY_HANDLER_OWNER_MODULE,
113 PROPERTY_HANDLER_CARD,
114 PROPERTY_HANDLER_SAMPLE_FORMAT,
115 PROPERTY_HANDLER_SAMPLE_RATE,
116 PROPERTY_HANDLER_CHANNELS,
117 PROPERTY_HANDLER_VOLUME,
118 PROPERTY_HANDLER_HAS_FLAT_VOLUME,
119 PROPERTY_HANDLER_HAS_CONVERTIBLE_TO_DECIBEL_VOLUME,
120 PROPERTY_HANDLER_BASE_VOLUME,
121 PROPERTY_HANDLER_VOLUME_STEPS,
122 PROPERTY_HANDLER_MUTE,
123 PROPERTY_HANDLER_HAS_HARDWARE_VOLUME,
124 PROPERTY_HANDLER_HAS_HARDWARE_MUTE,
125 PROPERTY_HANDLER_CONFIGURED_LATENCY,
126 PROPERTY_HANDLER_HAS_DYNAMIC_LATENCY,
127 PROPERTY_HANDLER_LATENCY,
128 PROPERTY_HANDLER_IS_HARDWARE_DEVICE,
129 PROPERTY_HANDLER_IS_NETWORK_DEVICE,
130 PROPERTY_HANDLER_STATE,
131 PROPERTY_HANDLER_PORTS,
132 PROPERTY_HANDLER_ACTIVE_PORT,
133 PROPERTY_HANDLER_PROPERTY_LIST,
134 PROPERTY_HANDLER_MAX
135 };
136
137 enum sink_property_handler_index {
138 SINK_PROPERTY_HANDLER_MONITOR_SOURCE,
139 SINK_PROPERTY_HANDLER_MAX
140 };
141
142 enum source_property_handler_index {
143 SOURCE_PROPERTY_HANDLER_MONITOR_OF_SINK,
144 SOURCE_PROPERTY_HANDLER_MAX
145 };
146
147 static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = {
148 [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL },
149 [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL },
150 [PROPERTY_HANDLER_DRIVER] = { .property_name = "Driver", .type = "s", .get_cb = handle_get_driver, .set_cb = NULL },
151 [PROPERTY_HANDLER_OWNER_MODULE] = { .property_name = "OwnerModule", .type = "o", .get_cb = handle_get_owner_module, .set_cb = NULL },
152 [PROPERTY_HANDLER_CARD] = { .property_name = "Card", .type = "o", .get_cb = handle_get_card, .set_cb = NULL },
153 [PROPERTY_HANDLER_SAMPLE_FORMAT] = { .property_name = "SampleFormat", .type = "u", .get_cb = handle_get_sample_format, .set_cb = NULL },
154 [PROPERTY_HANDLER_SAMPLE_RATE] = { .property_name = "SampleRate", .type = "u", .get_cb = handle_get_sample_rate, .set_cb = NULL },
155 [PROPERTY_HANDLER_CHANNELS] = { .property_name = "Channels", .type = "au", .get_cb = handle_get_channels, .set_cb = NULL },
156 [PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "au", .get_cb = handle_get_volume, .set_cb = handle_set_volume },
157 [PROPERTY_HANDLER_HAS_FLAT_VOLUME] = { .property_name = "HasFlatVolume", .type = "b", .get_cb = handle_get_has_flat_volume, .set_cb = NULL },
158 [PROPERTY_HANDLER_HAS_CONVERTIBLE_TO_DECIBEL_VOLUME] = { .property_name = "HasConvertibleToDecibelVolume", .type = "b", .get_cb = handle_get_has_convertible_to_decibel_volume, .set_cb = NULL },
159 [PROPERTY_HANDLER_BASE_VOLUME] = { .property_name = "BaseVolume", .type = "u", .get_cb = handle_get_base_volume, .set_cb = NULL },
160 [PROPERTY_HANDLER_VOLUME_STEPS] = { .property_name = "VolumeSteps", .type = "u", .get_cb = handle_get_volume_steps, .set_cb = NULL },
161 [PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_get_mute, .set_cb = handle_set_mute },
162 [PROPERTY_HANDLER_HAS_HARDWARE_VOLUME] = { .property_name = "HasHardwareVolume", .type = "b", .get_cb = handle_get_has_hardware_volume, .set_cb = NULL },
163 [PROPERTY_HANDLER_HAS_HARDWARE_MUTE] = { .property_name = "HasHardwareMute", .type = "b", .get_cb = handle_get_has_hardware_mute, .set_cb = NULL },
164 [PROPERTY_HANDLER_CONFIGURED_LATENCY] = { .property_name = "ConfiguredLatency", .type = "t", .get_cb = handle_get_configured_latency, .set_cb = NULL },
165 [PROPERTY_HANDLER_HAS_DYNAMIC_LATENCY] = { .property_name = "HasDynamicLatency", .type = "b", .get_cb = handle_get_has_dynamic_latency, .set_cb = NULL },
166 [PROPERTY_HANDLER_LATENCY] = { .property_name = "Latency", .type = "t", .get_cb = handle_get_latency, .set_cb = NULL },
167 [PROPERTY_HANDLER_IS_HARDWARE_DEVICE] = { .property_name = "IsHardwareDevice", .type = "b", .get_cb = handle_get_is_hardware_device, .set_cb = NULL },
168 [PROPERTY_HANDLER_IS_NETWORK_DEVICE] = { .property_name = "IsNetworkDevice", .type = "b", .get_cb = handle_get_is_network_device, .set_cb = NULL },
169 [PROPERTY_HANDLER_STATE] = { .property_name = "State", .type = "u", .get_cb = handle_get_state, .set_cb = NULL },
170 [PROPERTY_HANDLER_PORTS] = { .property_name = "Ports", .type = "ao", .get_cb = handle_get_ports, .set_cb = NULL },
171 [PROPERTY_HANDLER_ACTIVE_PORT] = { .property_name = "ActivePort", .type = "o", .get_cb = handle_get_active_port, .set_cb = handle_set_active_port },
172 [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL }
173 };
174
175 static pa_dbus_property_handler sink_property_handlers[SINK_PROPERTY_HANDLER_MAX] = {
176 [SINK_PROPERTY_HANDLER_MONITOR_SOURCE] = { .property_name = "MonitorSource", .type = "o", .get_cb = handle_sink_get_monitor_source, .set_cb = NULL }
177 };
178
179 static pa_dbus_property_handler source_property_handlers[SOURCE_PROPERTY_HANDLER_MAX] = {
180 [SOURCE_PROPERTY_HANDLER_MONITOR_OF_SINK] = { .property_name = "MonitorOfSink", .type = "o", .get_cb = handle_source_get_monitor_of_sink, .set_cb = NULL }
181 };
182
183 enum method_handler_index {
184 METHOD_HANDLER_SUSPEND,
185 METHOD_HANDLER_GET_PORT_BY_NAME,
186 METHOD_HANDLER_MAX
187 };
188
189 static pa_dbus_arg_info suspend_args[] = { { "suspend", "b", "in" } };
190 static pa_dbus_arg_info get_port_by_name_args[] = { { "name", "s", "in" }, { "port", "o", "out" } };
191
192 static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
193 [METHOD_HANDLER_SUSPEND] = {
194 .method_name = "Suspend",
195 .arguments = suspend_args,
196 .n_arguments = sizeof(suspend_args) / sizeof(pa_dbus_arg_info),
197 .receive_cb = handle_suspend },
198 [METHOD_HANDLER_GET_PORT_BY_NAME] = {
199 .method_name = "GetPortByName",
200 .arguments = get_port_by_name_args,
201 .n_arguments = sizeof(get_port_by_name_args) / sizeof(pa_dbus_arg_info),
202 .receive_cb = handle_get_port_by_name }
203 };
204
205 enum signal_index {
206 SIGNAL_VOLUME_UPDATED,
207 SIGNAL_MUTE_UPDATED,
208 SIGNAL_STATE_UPDATED,
209 SIGNAL_ACTIVE_PORT_UPDATED,
210 SIGNAL_PROPERTY_LIST_UPDATED,
211 SIGNAL_MAX
212 };
213
214 static pa_dbus_arg_info volume_updated_args[] = { { "volume", "au", NULL } };
215 static pa_dbus_arg_info mute_updated_args[] = { { "muted", "b", NULL } };
216 static pa_dbus_arg_info state_updated_args[] = { { "state", "u", NULL } };
217 static pa_dbus_arg_info active_port_updated_args[] = { { "port", "o", NULL } };
218 static pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } };
219
220 static pa_dbus_signal_info signals[SIGNAL_MAX] = {
221 [SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = volume_updated_args, .n_arguments = 1 },
222 [SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = mute_updated_args, .n_arguments = 1 },
223 [SIGNAL_STATE_UPDATED] = { .name = "StateUpdated", .arguments = state_updated_args, .n_arguments = 1 },
224 [SIGNAL_ACTIVE_PORT_UPDATED] = { .name = "ActivePortUpdated", .arguments = active_port_updated_args, .n_arguments = 1 },
225 [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 }
226 };
227
228 static pa_dbus_interface_info device_interface_info = {
229 .name = PA_DBUSIFACE_DEVICE_INTERFACE,
230 .method_handlers = method_handlers,
231 .n_method_handlers = METHOD_HANDLER_MAX,
232 .property_handlers = property_handlers,
233 .n_property_handlers = PROPERTY_HANDLER_MAX,
234 .get_all_properties_cb = handle_get_all,
235 .signals = signals,
236 .n_signals = SIGNAL_MAX
237 };
238
239 static pa_dbus_interface_info sink_interface_info = {
240 .name = PA_DBUSIFACE_SINK_INTERFACE,
241 .method_handlers = NULL,
242 .n_method_handlers = 0,
243 .property_handlers = sink_property_handlers,
244 .n_property_handlers = SINK_PROPERTY_HANDLER_MAX,
245 .get_all_properties_cb = handle_sink_get_all,
246 .signals = NULL,
247 .n_signals = 0
248 };
249
250 static pa_dbus_interface_info source_interface_info = {
251 .name = PA_DBUSIFACE_SOURCE_INTERFACE,
252 .method_handlers = NULL,
253 .n_method_handlers = 0,
254 .property_handlers = source_property_handlers,
255 .n_property_handlers = SOURCE_PROPERTY_HANDLER_MAX,
256 .get_all_properties_cb = handle_source_get_all,
257 .signals = NULL,
258 .n_signals = 0
259 };
260
261 static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) {
262 pa_dbusiface_device *d = userdata;
263 dbus_uint32_t idx = 0;
264
265 pa_assert(conn);
266 pa_assert(msg);
267 pa_assert(d);
268
269 idx = (d->type == DEVICE_TYPE_SINK) ? d->sink->index : d->source->index;
270
271 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx);
272 }
273
274 static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
275 pa_dbusiface_device *d = userdata;
276 const char *name = NULL;
277
278 pa_assert(conn);
279 pa_assert(msg);
280 pa_assert(d);
281
282 name = (d->type == DEVICE_TYPE_SINK) ? d->sink->name : d->source->name;
283
284 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &name);
285 }
286
287 static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) {
288 pa_dbusiface_device *d = userdata;
289 const char *driver = NULL;
290
291 pa_assert(conn);
292 pa_assert(msg);
293 pa_assert(d);
294
295 driver = (d->type == DEVICE_TYPE_SINK) ? d->sink->driver : d->source->driver;
296
297 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &driver);
298 }
299
300 static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata) {
301 pa_dbusiface_device *d = userdata;
302 pa_module *owner_module = NULL;
303 const char *object_path = NULL;
304
305 pa_assert(conn);
306 pa_assert(msg);
307 pa_assert(d);
308
309 owner_module = (d->type == DEVICE_TYPE_SINK) ? d->sink->module : d->source->module;
310
311 if (!owner_module) {
312 if (d->type == DEVICE_TYPE_SINK)
313 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
314 "Sink %s doesn't have an owner module.", d->sink->name);
315 else
316 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
317 "Source %s doesn't have an owner module.", d->source->name);
318 return;
319 }
320
321 object_path = pa_dbusiface_core_get_module_path(d->core, owner_module);
322
323 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
324 }
325
326 static void handle_get_card(DBusConnection *conn, DBusMessage *msg, void *userdata) {
327 pa_dbusiface_device *d = userdata;
328 pa_card *card = NULL;
329 const char *object_path = NULL;
330
331 pa_assert(conn);
332 pa_assert(msg);
333 pa_assert(d);
334
335 card = (d->type == DEVICE_TYPE_SINK) ? d->sink->card : d->source->card;
336
337 if (!card) {
338 if (d->type == DEVICE_TYPE_SINK)
339 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
340 "Sink %s doesn't belong to any card.", d->sink->name);
341 else
342 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
343 "Source %s doesn't belong to any card.", d->source->name);
344 return;
345 }
346
347 object_path = pa_dbusiface_core_get_card_path(d->core, card);
348
349 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
350 }
351
352 static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) {
353 pa_dbusiface_device *d = userdata;
354 dbus_uint32_t sample_format = 0;
355
356 pa_assert(conn);
357 pa_assert(msg);
358 pa_assert(d);
359
360 sample_format = (d->type == DEVICE_TYPE_SINK) ? d->sink->sample_spec.format : d->source->sample_spec.format;
361
362 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_format);
363 }
364
365 static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) {
366 pa_dbusiface_device *d = userdata;
367 dbus_uint32_t sample_rate = 0;
368
369 pa_assert(conn);
370 pa_assert(msg);
371 pa_assert(d);
372
373 sample_rate = (d->type == DEVICE_TYPE_SINK) ? d->sink->sample_spec.rate : d->source->sample_spec.rate;
374
375 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_rate);
376 }
377
378 static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata) {
379 pa_dbusiface_device *d = userdata;
380 pa_channel_map *channel_map = NULL;
381 dbus_uint32_t channels[PA_CHANNELS_MAX];
382 unsigned i = 0;
383
384 pa_assert(conn);
385 pa_assert(msg);
386 pa_assert(d);
387
388 channel_map = (d->type == DEVICE_TYPE_SINK) ? &d->sink->channel_map : &d->source->channel_map;
389
390 for (i = 0; i < channel_map->channels; ++i)
391 channels[i] = channel_map->map[i];
392
393 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, channels, channel_map->channels);
394 }
395
396 static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
397 pa_dbusiface_device *d = userdata;
398 dbus_uint32_t volume[PA_CHANNELS_MAX];
399 unsigned i = 0;
400
401 pa_assert(conn);
402 pa_assert(msg);
403 pa_assert(d);
404
405 for (i = 0; i < d->volume.channels; ++i)
406 volume[i] = d->volume.values[i];
407
408 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, volume, d->volume.channels);
409 }
410
411 static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
412 pa_dbusiface_device *d = userdata;
413 DBusMessageIter array_iter;
414 int device_channels = 0;
415 dbus_uint32_t *volume = NULL;
416 int n_volume_entries = 0;
417 pa_cvolume new_vol;
418 int i = 0;
419
420 pa_assert(conn);
421 pa_assert(msg);
422 pa_assert(iter);
423 pa_assert(d);
424
425 pa_cvolume_init(&new_vol);
426
427 device_channels = (d->type == DEVICE_TYPE_SINK) ? d->sink->channel_map.channels : d->source->channel_map.channels;
428
429 new_vol.channels = device_channels;
430
431 dbus_message_iter_recurse(iter, &array_iter);
432 dbus_message_iter_get_fixed_array(&array_iter, &volume, &n_volume_entries);
433
434 if (n_volume_entries != device_channels) {
435 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS,
436 "Expected %u volume entries, got %i.", device_channels, n_volume_entries);
437 return;
438 }
439
440 for (i = 0; i < n_volume_entries; ++i) {
441 if (volume[i] > PA_VOLUME_MAX) {
442 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too large volume value: %u", volume[i]);
443 return;
444 }
445 new_vol.values[i] = volume[i];
446 }
447
448 if (d->type == DEVICE_TYPE_SINK)
449 pa_sink_set_volume(d->sink, &new_vol, TRUE, TRUE);
450 else
451 pa_source_set_volume(d->source, &new_vol, TRUE);
452
453 pa_dbus_send_empty_reply(conn, msg);
454 }
455
456 static void handle_get_has_flat_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
457 pa_dbusiface_device *d = userdata;
458 dbus_bool_t has_flat_volume = FALSE;
459
460 pa_assert(conn);
461 pa_assert(msg);
462 pa_assert(d);
463
464 has_flat_volume = (d->type == DEVICE_TYPE_SINK) ? (d->sink->flags & PA_SINK_FLAT_VOLUME) : FALSE;
465
466 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_flat_volume);
467 }
468
469 static void handle_get_has_convertible_to_decibel_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
470 pa_dbusiface_device *d = userdata;
471 dbus_bool_t has_convertible_to_decibel_volume = FALSE;
472
473 pa_assert(conn);
474 pa_assert(msg);
475 pa_assert(d);
476
477 has_convertible_to_decibel_volume = (d->type == DEVICE_TYPE_SINK)
478 ? (d->sink->flags & PA_SINK_DECIBEL_VOLUME)
479 : (d->source->flags & PA_SOURCE_DECIBEL_VOLUME);
480
481 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_convertible_to_decibel_volume);
482 }
483
484 static void handle_get_base_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
485 pa_dbusiface_device *d = userdata;
486 dbus_uint32_t base_volume;
487
488 pa_assert(conn);
489 pa_assert(msg);
490 pa_assert(d);
491
492 base_volume = (d->type == DEVICE_TYPE_SINK) ? d->sink->base_volume : d->source->base_volume;
493
494 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &base_volume);
495 }
496
497 static void handle_get_volume_steps(DBusConnection *conn, DBusMessage *msg, void *userdata) {
498 pa_dbusiface_device *d = userdata;
499 dbus_uint32_t volume_steps;
500
501 pa_assert(conn);
502 pa_assert(msg);
503 pa_assert(d);
504
505 volume_steps = (d->type == DEVICE_TYPE_SINK) ? d->sink->n_volume_steps : d->source->n_volume_steps;
506
507 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &volume_steps);
508 }
509
510 static void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
511 pa_dbusiface_device *d = userdata;
512
513 pa_assert(conn);
514 pa_assert(msg);
515 pa_assert(d);
516
517 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &d->mute);
518 }
519
520 static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
521 pa_dbusiface_device *d = userdata;
522 dbus_bool_t mute = FALSE;
523
524 pa_assert(conn);
525 pa_assert(msg);
526 pa_assert(iter);
527 pa_assert(d);
528
529 dbus_message_iter_get_basic(iter, &mute);
530
531 if (d->type == DEVICE_TYPE_SINK)
532 pa_sink_set_mute(d->sink, mute, TRUE);
533 else
534 pa_source_set_mute(d->source, mute, TRUE);
535
536 pa_dbus_send_empty_reply(conn, msg);
537 }
538
539 static void handle_get_has_hardware_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
540 pa_dbusiface_device *d = userdata;
541 dbus_bool_t has_hardware_volume = FALSE;
542
543 pa_assert(conn);
544 pa_assert(msg);
545 pa_assert(d);
546
547 has_hardware_volume = (d->type == DEVICE_TYPE_SINK)
548 ? (d->sink->flags & PA_SINK_HW_VOLUME_CTRL)
549 : (d->source->flags & PA_SOURCE_HW_VOLUME_CTRL);
550
551 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_hardware_volume);
552 }
553
554 static void handle_get_has_hardware_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
555 pa_dbusiface_device *d = userdata;
556 dbus_bool_t has_hardware_mute = FALSE;
557
558 pa_assert(conn);
559 pa_assert(msg);
560 pa_assert(d);
561
562 has_hardware_mute = (d->type == DEVICE_TYPE_SINK)
563 ? (d->sink->flags & PA_SINK_HW_MUTE_CTRL)
564 : (d->source->flags & PA_SOURCE_HW_MUTE_CTRL);
565
566 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_hardware_mute);
567 }
568
569 static void handle_get_configured_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) {
570 pa_dbusiface_device *d = userdata;
571 dbus_uint64_t configured_latency = 0;
572
573 pa_assert(conn);
574 pa_assert(msg);
575 pa_assert(d);
576
577 configured_latency = (d->type == DEVICE_TYPE_SINK)
578 ? pa_sink_get_requested_latency(d->sink)
579 : pa_source_get_requested_latency(d->source);
580
581 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &configured_latency);
582 }
583
584 static void handle_get_has_dynamic_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) {
585 pa_dbusiface_device *d = userdata;
586 dbus_bool_t has_dynamic_latency = FALSE;
587
588 pa_assert(conn);
589 pa_assert(msg);
590 pa_assert(d);
591
592 has_dynamic_latency = (d->type == DEVICE_TYPE_SINK)
593 ? (d->sink->flags & PA_SINK_DYNAMIC_LATENCY)
594 : (d->source->flags & PA_SOURCE_DYNAMIC_LATENCY);
595
596 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_dynamic_latency);
597 }
598
599 static void handle_get_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) {
600 pa_dbusiface_device *d = userdata;
601 dbus_uint64_t latency = 0;
602
603 pa_assert(conn);
604 pa_assert(msg);
605 pa_assert(d);
606
607 if (d->type == DEVICE_TYPE_SINK && !(d->sink->flags & PA_SINK_LATENCY))
608 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
609 "Sink %s doesn't support latency querying.", d->sink->name);
610 else if (d->type == DEVICE_TYPE_SOURCE && !(d->source->flags & PA_SOURCE_LATENCY))
611 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
612 "Source %s doesn't support latency querying.", d->source->name);
613 return;
614
615 latency = (d->type == DEVICE_TYPE_SINK) ? pa_sink_get_latency(d->sink) : pa_source_get_latency(d->source);
616
617 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &latency);
618 }
619
620 static void handle_get_is_hardware_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
621 pa_dbusiface_device *d = userdata;
622 dbus_bool_t is_hardware_device = FALSE;
623
624 pa_assert(conn);
625 pa_assert(msg);
626 pa_assert(d);
627
628 is_hardware_device = (d->type == DEVICE_TYPE_SINK)
629 ? (d->sink->flags & PA_SINK_HARDWARE)
630 : (d->source->flags & PA_SOURCE_HARDWARE);
631
632 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &is_hardware_device);
633 }
634
635 static void handle_get_is_network_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
636 pa_dbusiface_device *d = userdata;
637 dbus_bool_t is_network_device = FALSE;
638
639 pa_assert(conn);
640 pa_assert(msg);
641 pa_assert(d);
642
643 is_network_device = (d->type == DEVICE_TYPE_SINK)
644 ? (d->sink->flags & PA_SINK_NETWORK)
645 : (d->source->flags & PA_SOURCE_NETWORK);
646
647 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &is_network_device);
648 }
649
650 static void handle_get_state(DBusConnection *conn, DBusMessage *msg, void *userdata) {
651 pa_dbusiface_device *d = userdata;
652 dbus_uint32_t state;
653
654 pa_assert(conn);
655 pa_assert(msg);
656 pa_assert(d);
657
658 state = (d->type == DEVICE_TYPE_SINK) ? d->sink_state : d->source_state;
659
660 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &state);
661 }
662
663 /* The caller frees the array, but not the strings. */
664 static const char **get_ports(pa_dbusiface_device *d, unsigned *n) {
665 const char **ports;
666 unsigned i = 0;
667 void *state = NULL;
668 pa_dbusiface_device_port *port = NULL;
669
670 pa_assert(d);
671 pa_assert(n);
672
673 *n = pa_hashmap_size(d->ports);
674
675 if (*n == 0)
676 return NULL;
677
678 ports = pa_xnew(const char *, *n);
679
680 PA_HASHMAP_FOREACH(port, d->ports, state)
681 ports[i++] = pa_dbusiface_device_port_get_path(port);
682
683 return ports;
684 }
685
686 static void handle_get_ports(DBusConnection *conn, DBusMessage *msg, void *userdata) {
687 pa_dbusiface_device *d = userdata;
688 const char **ports = NULL;
689 unsigned n_ports = 0;
690
691 pa_assert(conn);
692 pa_assert(msg);
693 pa_assert(d);
694
695 ports = get_ports(d, &n_ports);
696
697 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, ports, n_ports);
698
699 pa_xfree(ports);
700 }
701
702 static void handle_get_active_port(DBusConnection *conn, DBusMessage *msg, void *userdata) {
703 pa_dbusiface_device *d = userdata;
704 const char *active_port;
705
706 pa_assert(conn);
707 pa_assert(msg);
708 pa_assert(d);
709
710 if (!d->active_port) {
711 pa_assert(pa_hashmap_isempty(d->ports));
712
713 if (d->type == DEVICE_TYPE_SINK)
714 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
715 "The sink %s has no ports, and therefore there's no active port either.", d->sink->name);
716 else
717 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
718 "The source %s has no ports, and therefore there's no active port either.", d->source->name);
719 return;
720 }
721
722 active_port = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name));
723
724 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &active_port);
725 }
726
727 static void handle_set_active_port(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
728 pa_dbusiface_device *d = userdata;
729 const char *new_active_path;
730 pa_dbusiface_device_port *new_active;
731 int r;
732
733 pa_assert(conn);
734 pa_assert(msg);
735 pa_assert(iter);
736 pa_assert(d);
737
738 if (!d->active_port) {
739 pa_assert(pa_hashmap_isempty(d->ports));
740
741 if (d->type == DEVICE_TYPE_SINK)
742 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
743 "The sink %s has no ports, and therefore there's no active port either.", d->sink->name);
744 else
745 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
746 "The source %s has no ports, and therefore there's no active port either.", d->source->name);
747 return;
748 }
749
750 dbus_message_iter_get_basic(iter, &new_active_path);
751
752 if (!(new_active = pa_hashmap_get(d->ports, new_active_path))) {
753 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such port: %s", new_active_path);
754 return;
755 }
756
757 if (d->type == DEVICE_TYPE_SINK) {
758 if ((r = pa_sink_set_port(d->sink, pa_dbusiface_device_port_get_name(new_active), TRUE)) < 0) {
759 pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED,
760 "Internal error in PulseAudio: pa_sink_set_port() failed with error code %i.", r);
761 return;
762 }
763 } else {
764 if ((r = pa_source_set_port(d->source, pa_dbusiface_device_port_get_name(new_active), TRUE)) < 0) {
765 pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED,
766 "Internal error in PulseAudio: pa_source_set_port() failed with error code %i.", r);
767 return;
768 }
769 }
770
771 pa_dbus_send_empty_reply(conn, msg);
772 }
773
774 static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
775 pa_dbusiface_device *d = userdata;
776
777 pa_assert(conn);
778 pa_assert(msg);
779 pa_assert(d);
780
781 pa_dbus_send_proplist_variant_reply(conn, msg, d->proplist);
782 }
783
784 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
785 pa_dbusiface_device *d = userdata;
786 DBusMessage *reply = NULL;
787 DBusMessageIter msg_iter;
788 DBusMessageIter dict_iter;
789 dbus_uint32_t idx = 0;
790 const char *name = NULL;
791 const char *driver = NULL;
792 pa_module *owner_module = NULL;
793 const char *owner_module_path = NULL;
794 pa_card *card = NULL;
795 const char *card_path = NULL;
796 dbus_uint32_t sample_format = 0;
797 dbus_uint32_t sample_rate = 0;
798 pa_channel_map *channel_map = NULL;
799 dbus_uint32_t channels[PA_CHANNELS_MAX];
800 dbus_uint32_t volume[PA_CHANNELS_MAX];
801 dbus_bool_t has_flat_volume = FALSE;
802 dbus_bool_t has_convertible_to_decibel_volume = FALSE;
803 dbus_uint32_t base_volume = 0;
804 dbus_uint32_t volume_steps = 0;
805 dbus_bool_t has_hardware_volume = FALSE;
806 dbus_bool_t has_hardware_mute = FALSE;
807 dbus_uint64_t configured_latency = 0;
808 dbus_bool_t has_dynamic_latency = FALSE;
809 dbus_uint64_t latency = 0;
810 dbus_bool_t is_hardware_device = FALSE;
811 dbus_bool_t is_network_device = FALSE;
812 dbus_uint32_t state = 0;
813 const char **ports = NULL;
814 unsigned n_ports = 0;
815 const char *active_port = NULL;
816 unsigned i = 0;
817
818 pa_assert(conn);
819 pa_assert(msg);
820 pa_assert(d);
821
822 if (d->type == DEVICE_TYPE_SINK) {
823 idx = d->sink->index;
824 name = d->sink->name;
825 driver = d->sink->driver;
826 owner_module = d->sink->module;
827 card = d->sink->card;
828 sample_format = d->sink->sample_spec.format;
829 sample_rate = d->sink->sample_spec.rate;
830 channel_map = &d->sink->channel_map;
831 has_flat_volume = d->sink->flags & PA_SINK_FLAT_VOLUME;
832 has_convertible_to_decibel_volume = d->sink->flags & PA_SINK_DECIBEL_VOLUME;
833 base_volume = d->sink->base_volume;
834 volume_steps = d->sink->n_volume_steps;
835 has_hardware_volume = d->sink->flags & PA_SINK_HW_VOLUME_CTRL;
836 has_hardware_mute = d->sink->flags & PA_SINK_HW_MUTE_CTRL;
837 configured_latency = pa_sink_get_requested_latency(d->sink);
838 has_dynamic_latency = d->sink->flags & PA_SINK_DYNAMIC_LATENCY;
839 latency = pa_sink_get_latency(d->sink);
840 is_hardware_device = d->sink->flags & PA_SINK_HARDWARE;
841 is_network_device = d->sink->flags & PA_SINK_NETWORK;
842 state = pa_sink_get_state(d->sink);
843 } else {
844 idx = d->source->index;
845 name = d->source->name;
846 driver = d->source->driver;
847 owner_module = d->source->module;
848 card = d->source->card;
849 sample_format = d->source->sample_spec.format;
850 sample_rate = d->source->sample_spec.rate;
851 channel_map = &d->source->channel_map;
852 has_flat_volume = FALSE;
853 has_convertible_to_decibel_volume = d->source->flags & PA_SOURCE_DECIBEL_VOLUME;
854 base_volume = d->source->base_volume;
855 volume_steps = d->source->n_volume_steps;
856 has_hardware_volume = d->source->flags & PA_SOURCE_HW_VOLUME_CTRL;
857 has_hardware_mute = d->source->flags & PA_SOURCE_HW_MUTE_CTRL;
858 configured_latency = pa_source_get_requested_latency(d->source);
859 has_dynamic_latency = d->source->flags & PA_SOURCE_DYNAMIC_LATENCY;
860 latency = pa_source_get_latency(d->source);
861 is_hardware_device = d->source->flags & PA_SOURCE_HARDWARE;
862 is_network_device = d->source->flags & PA_SOURCE_NETWORK;
863 state = pa_source_get_state(d->source);
864 }
865 if (owner_module)
866 owner_module_path = pa_dbusiface_core_get_module_path(d->core, owner_module);
867 if (card)
868 card_path = pa_dbusiface_core_get_card_path(d->core, card);
869 for (i = 0; i < channel_map->channels; ++i)
870 channels[i] = channel_map->map[i];
871 for (i = 0; i < d->volume.channels; ++i)
872 volume[i] = d->volume.values[i];
873 ports = get_ports(d, &n_ports);
874 if (d->active_port)
875 active_port = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name));
876
877 pa_assert_se((reply = dbus_message_new_method_return(msg)));
878
879 dbus_message_iter_init_append(reply, &msg_iter);
880 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
881
882 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx);
883 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &name);
884 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &driver);
885
886 if (owner_module)
887 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module_path);
888
889 if (card)
890 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CARD].property_name, DBUS_TYPE_OBJECT_PATH, &card_path);
891
892 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format);
893 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &sample_rate);
894 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, channel_map->channels);
895 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME].property_name, DBUS_TYPE_UINT32, volume, d->volume.channels);
896 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_FLAT_VOLUME].property_name, DBUS_TYPE_BOOLEAN, &has_flat_volume);
897 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_CONVERTIBLE_TO_DECIBEL_VOLUME].property_name, DBUS_TYPE_BOOLEAN, &has_convertible_to_decibel_volume);
898 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BASE_VOLUME].property_name, DBUS_TYPE_UINT32, &base_volume);
899 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME_STEPS].property_name, DBUS_TYPE_UINT32, &volume_steps);
900 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &d->mute);
901 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_HARDWARE_VOLUME].property_name, DBUS_TYPE_BOOLEAN, &has_hardware_volume);
902 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_HARDWARE_MUTE].property_name, DBUS_TYPE_BOOLEAN, &has_hardware_mute);
903 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CONFIGURED_LATENCY].property_name, DBUS_TYPE_UINT64, &configured_latency);
904 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_DYNAMIC_LATENCY].property_name, DBUS_TYPE_BOOLEAN, &has_dynamic_latency);
905 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_LATENCY].property_name, DBUS_TYPE_UINT64, &latency);
906 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_IS_HARDWARE_DEVICE].property_name, DBUS_TYPE_BOOLEAN, &is_hardware_device);
907 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_IS_NETWORK_DEVICE].property_name, DBUS_TYPE_BOOLEAN, &is_network_device);
908 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_STATE].property_name, DBUS_TYPE_UINT32, &state);
909 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PORTS].property_name, DBUS_TYPE_OBJECT_PATH, ports, n_ports);
910
911 if (active_port)
912 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ACTIVE_PORT].property_name, DBUS_TYPE_OBJECT_PATH, &active_port);
913
914 pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, d->proplist);
915
916 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
917
918 pa_assert_se(dbus_connection_send(conn, reply, NULL));
919
920 dbus_message_unref(reply);
921
922 pa_xfree(ports);
923 }
924
925 static void handle_suspend(DBusConnection *conn, DBusMessage *msg, void *userdata) {
926 pa_dbusiface_device *d = userdata;
927 dbus_bool_t suspend = FALSE;
928
929 pa_assert(conn);
930 pa_assert(msg);
931 pa_assert(d);
932
933 pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &suspend, DBUS_TYPE_INVALID));
934
935 if ((d->type == DEVICE_TYPE_SINK) && (pa_sink_suspend(d->sink, suspend, PA_SUSPEND_USER) < 0)) {
936 pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Internal error in PulseAudio: pa_sink_suspend() failed.");
937 return;
938 } else if ((d->type == DEVICE_TYPE_SOURCE) && (pa_source_suspend(d->source, suspend, PA_SUSPEND_USER) < 0)) {
939 pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Internal error in PulseAudio: pa_source_suspend() failed.");
940 return;
941 }
942
943 pa_dbus_send_empty_reply(conn, msg);
944 }
945
946 static void handle_get_port_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
947 pa_dbusiface_device *d = userdata;
948 const char *port_name = NULL;
949 pa_dbusiface_device_port *port = NULL;
950 const char *port_path = NULL;
951
952 pa_assert(conn);
953 pa_assert(msg);
954 pa_assert(d);
955
956 pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &port_name, DBUS_TYPE_INVALID));
957
958 if (!(port = pa_hashmap_get(d->ports, port_name))) {
959 if (d->type == DEVICE_TYPE_SINK)
960 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND,
961 "%s: No such port on sink %s.", port_name, d->sink->name);
962 else
963 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND,
964 "%s: No such port on source %s.", port_name, d->source->name);
965 return;
966 }
967
968 port_path = pa_dbusiface_device_port_get_path(port);
969
970 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &port_path);
971 }
972
973 static void handle_sink_get_monitor_source(DBusConnection *conn, DBusMessage *msg, void *userdata) {
974 pa_dbusiface_device *d = userdata;
975 const char *monitor_source = NULL;
976
977 pa_assert(conn);
978 pa_assert(msg);
979 pa_assert(d);
980 pa_assert(d->type == DEVICE_TYPE_SINK);
981
982 monitor_source = pa_dbusiface_core_get_source_path(d->core, d->sink->monitor_source);
983
984 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &monitor_source);
985 }
986
987 static void handle_sink_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
988 pa_dbusiface_device *d = userdata;
989 DBusMessage *reply = NULL;
990 DBusMessageIter msg_iter;
991 DBusMessageIter dict_iter;
992 const char *monitor_source = NULL;
993
994 pa_assert(conn);
995 pa_assert(msg);
996 pa_assert(d);
997 pa_assert(d->type == DEVICE_TYPE_SINK);
998
999 monitor_source = pa_dbusiface_core_get_source_path(d->core, d->sink->monitor_source);
1000
1001 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1002
1003 dbus_message_iter_init_append(reply, &msg_iter);
1004 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
1005
1006 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[SINK_PROPERTY_HANDLER_MONITOR_SOURCE].property_name, DBUS_TYPE_OBJECT_PATH, &monitor_source);
1007
1008 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
1009
1010 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1011
1012 dbus_message_unref(reply);
1013 }
1014
1015 static void handle_source_get_monitor_of_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) {
1016 pa_dbusiface_device *d = userdata;
1017 const char *monitor_of_sink = NULL;
1018
1019 pa_assert(conn);
1020 pa_assert(msg);
1021 pa_assert(d);
1022 pa_assert(d->type == DEVICE_TYPE_SOURCE);
1023
1024 if (!d->source->monitor_of) {
1025 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Source %s is not a monitor source.", d->source->name);
1026 return;
1027 }
1028
1029 monitor_of_sink = pa_dbusiface_core_get_sink_path(d->core, d->source->monitor_of);
1030
1031 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &monitor_of_sink);
1032 }
1033
1034 static void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
1035 pa_dbusiface_device *d = userdata;
1036 DBusMessage *reply = NULL;
1037 DBusMessageIter msg_iter;
1038 DBusMessageIter dict_iter;
1039 const char *monitor_of_sink = NULL;
1040
1041 pa_assert(conn);
1042 pa_assert(msg);
1043 pa_assert(d);
1044 pa_assert(d->type == DEVICE_TYPE_SOURCE);
1045
1046 if (d->source->monitor_of)
1047 monitor_of_sink = pa_dbusiface_core_get_sink_path(d->core, d->source->monitor_of);
1048
1049 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1050
1051 dbus_message_iter_init_append(reply, &msg_iter);
1052 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
1053
1054 if (monitor_of_sink)
1055 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[SOURCE_PROPERTY_HANDLER_MONITOR_OF_SINK].property_name, DBUS_TYPE_OBJECT_PATH, &monitor_of_sink);
1056
1057 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
1058
1059 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1060
1061 dbus_message_unref(reply);
1062 }
1063
1064 static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
1065 pa_dbusiface_device *d = userdata;
1066 DBusMessage *signal_msg = NULL;
1067 const pa_cvolume *new_volume = NULL;
1068 pa_bool_t new_mute = FALSE;
1069 pa_sink_state_t new_sink_state = 0;
1070 pa_source_state_t new_source_state = 0;
1071 pa_device_port *new_active_port = NULL;
1072 pa_proplist *new_proplist = NULL;
1073 unsigned i = 0;
1074
1075 pa_assert(c);
1076 pa_assert(d);
1077
1078 if ((d->type == DEVICE_TYPE_SINK && idx != d->sink->index) || (d->type == DEVICE_TYPE_SOURCE && idx != d->source->index))
1079 return;
1080
1081 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
1082 return;
1083
1084 pa_assert(((d->type == DEVICE_TYPE_SINK)
1085 && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK))
1086 || ((d->type == DEVICE_TYPE_SOURCE)
1087 && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE)));
1088
1089 new_volume = (d->type == DEVICE_TYPE_SINK)
1090 ? pa_sink_get_volume(d->sink, FALSE)
1091 : pa_source_get_volume(d->source, FALSE);
1092
1093 if (!pa_cvolume_equal(&d->volume, new_volume)) {
1094 dbus_uint32_t volume[PA_CHANNELS_MAX];
1095 dbus_uint32_t *volume_ptr = volume;
1096
1097 d->volume = *new_volume;
1098
1099 for (i = 0; i < d->volume.channels; ++i)
1100 volume[i] = d->volume.values[i];
1101
1102 pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
1103 PA_DBUSIFACE_DEVICE_INTERFACE,
1104 signals[SIGNAL_VOLUME_UPDATED].name));
1105 pa_assert_se(dbus_message_append_args(signal_msg,
1106 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, d->volume.channels,
1107 DBUS_TYPE_INVALID));
1108
1109 pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
1110 dbus_message_unref(signal_msg);
1111 signal_msg = NULL;
1112 }
1113
1114 new_mute = (d->type == DEVICE_TYPE_SINK) ? pa_sink_get_mute(d->sink, FALSE) : pa_source_get_mute(d->source, FALSE);
1115
1116 if (d->mute != new_mute) {
1117 d->mute = new_mute;
1118
1119 pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
1120 PA_DBUSIFACE_DEVICE_INTERFACE,
1121 signals[SIGNAL_MUTE_UPDATED].name));
1122 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &d->mute, DBUS_TYPE_INVALID));
1123
1124 pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
1125 dbus_message_unref(signal_msg);
1126 signal_msg = NULL;
1127 }
1128
1129 if (d->type == DEVICE_TYPE_SINK)
1130 new_sink_state = pa_sink_get_state(d->sink);
1131 else
1132 new_source_state = pa_source_get_state(d->source);
1133
1134 if ((d->type == DEVICE_TYPE_SINK && d->sink_state != new_sink_state)
1135 || (d->type == DEVICE_TYPE_SOURCE && d->source_state != new_source_state)) {
1136 dbus_uint32_t state = 0;
1137
1138 if (d->type == DEVICE_TYPE_SINK)
1139 d->sink_state = new_sink_state;
1140 else
1141 d->source_state = new_source_state;
1142
1143 state = (d->type == DEVICE_TYPE_SINK) ? d->sink_state : d->source_state;
1144
1145 pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
1146 PA_DBUSIFACE_DEVICE_INTERFACE,
1147 signals[SIGNAL_STATE_UPDATED].name));
1148 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID));
1149
1150 pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
1151 dbus_message_unref(signal_msg);
1152 signal_msg = NULL;
1153 }
1154
1155 new_active_port = (d->type == DEVICE_TYPE_SINK) ? d->sink->active_port : d->source->active_port;
1156
1157 if (d->active_port != new_active_port) {
1158 const char *object_path = NULL;
1159
1160 d->active_port = new_active_port;
1161 object_path = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name));
1162
1163 pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
1164 PA_DBUSIFACE_DEVICE_INTERFACE,
1165 signals[SIGNAL_ACTIVE_PORT_UPDATED].name));
1166 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
1167
1168 pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
1169 dbus_message_unref(signal_msg);
1170 signal_msg = NULL;
1171 }
1172
1173 new_proplist = (d->type == DEVICE_TYPE_SINK) ? d->sink->proplist : d->source->proplist;
1174
1175 if (!pa_proplist_equal(d->proplist, new_proplist)) {
1176 DBusMessageIter msg_iter;
1177
1178 pa_proplist_update(d->proplist, PA_UPDATE_SET, new_proplist);
1179
1180 pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
1181 PA_DBUSIFACE_DEVICE_INTERFACE,
1182 signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
1183 dbus_message_iter_init_append(signal_msg, &msg_iter);
1184 pa_dbus_append_proplist(&msg_iter, d->proplist);
1185
1186 pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
1187 dbus_message_unref(signal_msg);
1188 signal_msg = NULL;
1189 }
1190 }
1191
1192 pa_dbusiface_device *pa_dbusiface_device_new_sink(pa_dbusiface_core *core, pa_sink *sink) {
1193 pa_dbusiface_device *d = NULL;
1194
1195 pa_assert(core);
1196 pa_assert(sink);
1197
1198 d = pa_xnew0(pa_dbusiface_device, 1);
1199 d->core = core;
1200 d->sink = pa_sink_ref(sink);
1201 d->type = DEVICE_TYPE_SINK;
1202 d->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, SINK_OBJECT_NAME, sink->index);
1203 d->volume = *pa_sink_get_volume(sink, FALSE);
1204 d->mute = pa_sink_get_mute(sink, FALSE);
1205 d->sink_state = pa_sink_get_state(sink);
1206 d->ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
1207 d->next_port_index = 0;
1208 d->active_port = NULL;
1209 d->proplist = pa_proplist_copy(sink->proplist);
1210 d->dbus_protocol = pa_dbus_protocol_get(sink->core);
1211 d->subscription = pa_subscription_new(sink->core, PA_SUBSCRIPTION_MASK_SINK, subscription_cb, d);
1212
1213 if (sink->ports) {
1214 pa_device_port *port;
1215 void *state = NULL;
1216
1217 PA_HASHMAP_FOREACH(port, sink->ports, state) {
1218 pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, sink->core, port, d->next_port_index++);
1219 pa_hashmap_put(d->ports, pa_dbusiface_device_port_get_name(p), p);
1220 }
1221 pa_assert_se(d->active_port = sink->active_port);
1222 }
1223
1224 pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &device_interface_info, d) >= 0);
1225 pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &sink_interface_info, d) >= 0);
1226
1227 return d;
1228 }
1229
1230 pa_dbusiface_device *pa_dbusiface_device_new_source(pa_dbusiface_core *core, pa_source *source) {
1231 pa_dbusiface_device *d = NULL;
1232
1233 pa_assert(core);
1234 pa_assert(source);
1235
1236 d = pa_xnew0(pa_dbusiface_device, 1);
1237 d->core = core;
1238 d->source = pa_source_ref(source);
1239 d->type = DEVICE_TYPE_SOURCE;
1240 d->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, SOURCE_OBJECT_NAME, source->index);
1241 d->volume = *pa_source_get_volume(source, FALSE);
1242 d->mute = pa_source_get_mute(source, FALSE);
1243 d->source_state = pa_source_get_state(source);
1244 d->ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
1245 d->next_port_index = 0;
1246 d->active_port = NULL;
1247 d->proplist = pa_proplist_copy(source->proplist);
1248 d->dbus_protocol = pa_dbus_protocol_get(source->core);
1249 d->subscription = pa_subscription_new(source->core, PA_SUBSCRIPTION_MASK_SOURCE, subscription_cb, d);
1250
1251 if (source->ports) {
1252 pa_device_port *port;
1253 void *state = NULL;
1254
1255 PA_HASHMAP_FOREACH(port, source->ports, state) {
1256 pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, source->core, port, d->next_port_index++);
1257 pa_hashmap_put(d->ports, pa_dbusiface_device_port_get_name(p), p);
1258 }
1259 pa_assert_se(d->active_port = source->active_port);
1260 }
1261
1262 pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &device_interface_info, d) >= 0);
1263 pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &source_interface_info, d) >= 0);
1264
1265 return d;
1266 }
1267
1268 static void port_free_cb(void *p, void *userdata) {
1269 pa_dbusiface_device_port *port = p;
1270
1271 pa_assert(port);
1272
1273 pa_dbusiface_device_port_free(port);
1274 }
1275
1276 void pa_dbusiface_device_free(pa_dbusiface_device *d) {
1277 pa_assert(d);
1278
1279 pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, device_interface_info.name) >= 0);
1280
1281 if (d->type == DEVICE_TYPE_SINK) {
1282 pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, sink_interface_info.name) >= 0);
1283 pa_sink_unref(d->sink);
1284
1285 } else {
1286 pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, source_interface_info.name) >= 0);
1287 pa_source_unref(d->source);
1288 }
1289 pa_hashmap_free(d->ports, port_free_cb, NULL);
1290 pa_proplist_free(d->proplist);
1291 pa_dbus_protocol_unref(d->dbus_protocol);
1292 pa_subscription_free(d->subscription);
1293
1294 pa_xfree(d->path);
1295 pa_xfree(d);
1296 }
1297
1298 const char *pa_dbusiface_device_get_path(pa_dbusiface_device *d) {
1299 pa_assert(d);
1300
1301 return d->path;
1302 }
1303
1304 pa_sink *pa_dbusiface_device_get_sink(pa_dbusiface_device *d) {
1305 pa_assert(d);
1306 pa_assert(d->type == DEVICE_TYPE_SINK);
1307
1308 return d->sink;
1309 }
1310
1311 pa_source *pa_dbusiface_device_get_source(pa_dbusiface_device *d) {
1312 pa_assert(d);
1313 pa_assert(d->type == DEVICE_TYPE_SOURCE);
1314
1315 return d->source;
1316 }