dbusiface-stream: Only send stream event signals from the right D-Bus objects.
[profile/ivi/pulseaudio-panda.git] / src / modules / dbus / iface-stream.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2009 Tanu Kaskinen
5   Copyright 2009 Vincent Filali-Ansary <filali.v@azurdigitalnetworks.net>
6
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20   USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <pulsecore/core-util.h>
28 #include <pulsecore/dbus-util.h>
29 #include <pulsecore/protocol-dbus.h>
30
31 #include "iface-stream.h"
32
33 #define PLAYBACK_OBJECT_NAME "playback_stream"
34 #define RECORD_OBJECT_NAME "record_stream"
35
36 enum stream_type {
37     STREAM_TYPE_PLAYBACK,
38     STREAM_TYPE_RECORD
39 };
40
41 struct pa_dbusiface_stream {
42     pa_dbusiface_core *core;
43
44     union {
45         pa_sink_input *sink_input;
46         pa_source_output *source_output;
47     };
48     enum stream_type type;
49     char *path;
50     union {
51         pa_sink *sink;
52         pa_source *source;
53     };
54     uint32_t sample_rate;
55     pa_cvolume volume;
56     pa_bool_t is_muted;
57     pa_proplist *proplist;
58
59     pa_dbus_protocol *dbus_protocol;
60     pa_subscription *subscription;
61     pa_hook_slot *send_event_slot;
62 };
63
64 static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata);
65 static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata);
66 static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata);
67 static void handle_get_client(DBusConnection *conn, DBusMessage *msg, void *userdata);
68 static void handle_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
69 static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata);
70 static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata);
71 static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata);
72 static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
73 static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
74 static void handle_get_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata);
75 static void handle_set_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata);
76 static void handle_get_buffer_latency(DBusConnection *conn, DBusMessage *msg, void *userdata);
77 static void handle_get_device_latency(DBusConnection *conn, DBusMessage *msg, void *userdata);
78 static void handle_get_resample_method(DBusConnection *conn, DBusMessage *msg, void *userdata);
79 static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
80
81 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
82
83 static void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata);
84 static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata);
85
86 enum property_handler_index {
87     PROPERTY_HANDLER_INDEX,
88     PROPERTY_HANDLER_DRIVER,
89     PROPERTY_HANDLER_OWNER_MODULE,
90     PROPERTY_HANDLER_CLIENT,
91     PROPERTY_HANDLER_DEVICE,
92     PROPERTY_HANDLER_SAMPLE_FORMAT,
93     PROPERTY_HANDLER_SAMPLE_RATE,
94     PROPERTY_HANDLER_CHANNELS,
95     PROPERTY_HANDLER_VOLUME,
96     PROPERTY_HANDLER_IS_MUTED,
97     PROPERTY_HANDLER_BUFFER_LATENCY,
98     PROPERTY_HANDLER_DEVICE_LATENCY,
99     PROPERTY_HANDLER_RESAMPLE_METHOD,
100     PROPERTY_HANDLER_PROPERTY_LIST,
101     PROPERTY_HANDLER_MAX
102 };
103
104 static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = {
105     [PROPERTY_HANDLER_INDEX]           = { .property_name = "Index",          .type = "u",      .get_cb = handle_get_index,           .set_cb = NULL },
106     [PROPERTY_HANDLER_DRIVER]          = { .property_name = "Driver",         .type = "s",      .get_cb = handle_get_driver,          .set_cb = NULL },
107     [PROPERTY_HANDLER_OWNER_MODULE]    = { .property_name = "OwnerModule",    .type = "o",      .get_cb = handle_get_owner_module,    .set_cb = NULL },
108     [PROPERTY_HANDLER_CLIENT]          = { .property_name = "Client",         .type = "o",      .get_cb = handle_get_client,          .set_cb = NULL },
109     [PROPERTY_HANDLER_DEVICE]          = { .property_name = "Device",         .type = "o",      .get_cb = handle_get_device,          .set_cb = NULL },
110     [PROPERTY_HANDLER_SAMPLE_FORMAT]   = { .property_name = "SampleFormat",   .type = "u",      .get_cb = handle_get_sample_format,   .set_cb = NULL },
111     [PROPERTY_HANDLER_SAMPLE_RATE]     = { .property_name = "SampleRate",     .type = "u",      .get_cb = handle_get_sample_rate,     .set_cb = NULL },
112     [PROPERTY_HANDLER_CHANNELS]        = { .property_name = "Channels",       .type = "au",     .get_cb = handle_get_channels,        .set_cb = NULL },
113     [PROPERTY_HANDLER_VOLUME]          = { .property_name = "Volume",         .type = "au",     .get_cb = handle_get_volume,          .set_cb = handle_set_volume },
114     [PROPERTY_HANDLER_IS_MUTED]        = { .property_name = "IsMuted",        .type = "b",      .get_cb = handle_get_is_muted,        .set_cb = handle_set_is_muted },
115     [PROPERTY_HANDLER_BUFFER_LATENCY]  = { .property_name = "BufferLatency",  .type = "t",      .get_cb = handle_get_buffer_latency,  .set_cb = NULL },
116     [PROPERTY_HANDLER_DEVICE_LATENCY]  = { .property_name = "DeviceLatency",  .type = "t",      .get_cb = handle_get_device_latency,  .set_cb = NULL },
117     [PROPERTY_HANDLER_RESAMPLE_METHOD] = { .property_name = "ResampleMethod", .type = "s",      .get_cb = handle_get_resample_method, .set_cb = NULL },
118     [PROPERTY_HANDLER_PROPERTY_LIST]   = { .property_name = "PropertyList",   .type = "a{say}", .get_cb = handle_get_property_list,   .set_cb = NULL }
119 };
120
121 enum method_handler_index {
122     METHOD_HANDLER_MOVE,
123     METHOD_HANDLER_KILL,
124     METHOD_HANDLER_MAX
125 };
126
127 static pa_dbus_arg_info move_args[] = { { "device", "o", "in" } };
128
129 static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
130     [METHOD_HANDLER_MOVE] = {
131         .method_name = "Move",
132         .arguments = move_args,
133         .n_arguments = sizeof(move_args) / sizeof(pa_dbus_arg_info),
134         .receive_cb = handle_move },
135     [METHOD_HANDLER_KILL] = {
136         .method_name = "Kill",
137         .arguments = NULL,
138         .n_arguments = 0,
139         .receive_cb = handle_kill }
140 };
141
142 enum signal_index {
143     SIGNAL_DEVICE_UPDATED,
144     SIGNAL_SAMPLE_RATE_UPDATED,
145     SIGNAL_VOLUME_UPDATED,
146     SIGNAL_MUTE_UPDATED,
147     SIGNAL_PROPERTY_LIST_UPDATED,
148     SIGNAL_STREAM_EVENT,
149     SIGNAL_MAX
150 };
151
152 static pa_dbus_arg_info device_updated_args[]        = { { "device",        "o",      NULL } };
153 static pa_dbus_arg_info sample_rate_updated_args[]   = { { "sample_rate",   "u",      NULL } };
154 static pa_dbus_arg_info volume_updated_args[]        = { { "volume",        "au",     NULL } };
155 static pa_dbus_arg_info mute_updated_args[]          = { { "muted",         "b",      NULL } };
156 static pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } };
157 static pa_dbus_arg_info stream_event_args[]          = { { "name",          "s",      NULL }, { "property_list", "a{say}", NULL } };
158
159 static pa_dbus_signal_info signals[SIGNAL_MAX] = {
160     [SIGNAL_DEVICE_UPDATED]        = { .name = "DeviceUpdated",       .arguments = device_updated_args,        .n_arguments = 1 },
161     [SIGNAL_SAMPLE_RATE_UPDATED]   = { .name = "SampleRateUpdated",   .arguments = sample_rate_updated_args,   .n_arguments = 1 },
162     [SIGNAL_VOLUME_UPDATED]        = { .name = "VolumeUpdated",       .arguments = volume_updated_args,        .n_arguments = 1 },
163     [SIGNAL_MUTE_UPDATED]          = { .name = "MuteUpdated",         .arguments = mute_updated_args,          .n_arguments = 1 },
164     [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 },
165     [SIGNAL_STREAM_EVENT]          = { .name = "StreamEvent",         .arguments = stream_event_args,          .n_arguments = sizeof(stream_event_args) / sizeof(pa_dbus_arg_info) }
166 };
167
168 static pa_dbus_interface_info stream_interface_info = {
169     .name = PA_DBUSIFACE_STREAM_INTERFACE,
170     .method_handlers = method_handlers,
171     .n_method_handlers = METHOD_HANDLER_MAX,
172     .property_handlers = property_handlers,
173     .n_property_handlers = PROPERTY_HANDLER_MAX,
174     .get_all_properties_cb = handle_get_all,
175     .signals = signals,
176     .n_signals = SIGNAL_MAX
177 };
178
179 static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) {
180     pa_dbusiface_stream *s = userdata;
181     dbus_uint32_t idx;
182
183     pa_assert(conn);
184     pa_assert(msg);
185     pa_assert(s);
186
187     idx = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->index : s->source_output->index;
188
189     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx);
190 }
191
192 static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) {
193     pa_dbusiface_stream *s = userdata;
194     const char *driver = NULL;
195
196     pa_assert(conn);
197     pa_assert(msg);
198     pa_assert(s);
199
200     driver = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->driver : s->source_output->driver;
201
202     if (!driver) {
203         if (s->type == STREAM_TYPE_PLAYBACK)
204             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
205                                "Playback stream %u doesn't have a driver.", s->sink_input->index);
206         else
207             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
208                                "Record stream %u doesn't have a driver.", s->source_output->index);
209         return;
210     }
211
212     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &driver);
213 }
214
215 static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata) {
216     pa_dbusiface_stream *s = userdata;
217     pa_module *owner_module = NULL;
218     const char *object_path = NULL;
219
220     pa_assert(conn);
221     pa_assert(msg);
222     pa_assert(s);
223
224     owner_module = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->module : s->source_output->module;
225
226     if (!owner_module) {
227         if (s->type == STREAM_TYPE_PLAYBACK)
228             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
229                                "Playback stream %u doesn't have an owner module.", s->sink_input->index);
230         else
231             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
232                                "Record stream %u doesn't have an owner module.", s->source_output->index);
233         return;
234     }
235
236     object_path = pa_dbusiface_core_get_module_path(s->core, owner_module);
237
238     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
239 }
240
241 static void handle_get_client(DBusConnection *conn, DBusMessage *msg, void *userdata) {
242     pa_dbusiface_stream *s = userdata;
243     pa_client *client = NULL;
244     const char *object_path = NULL;
245
246     pa_assert(conn);
247     pa_assert(msg);
248     pa_assert(s);
249
250     client = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->client : s->source_output->client;
251
252     if (!client) {
253         if (s->type == STREAM_TYPE_PLAYBACK)
254             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
255                                "Playback stream %u isn't associated to any client.", s->sink_input->index);
256         else
257             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
258                                "Record stream %u isn't associated to any client.", s->source_output->index);
259         return;
260     }
261
262     object_path = pa_dbusiface_core_get_client_path(s->core, client);
263
264     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path);
265 }
266
267 static void handle_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
268     pa_dbusiface_stream *s = userdata;
269     const char *device = NULL;
270
271     pa_assert(conn);
272     pa_assert(msg);
273     pa_assert(s);
274
275     if (s->type == STREAM_TYPE_PLAYBACK)
276         device = pa_dbusiface_core_get_sink_path(s->core, s->sink);
277     else
278         device = pa_dbusiface_core_get_source_path(s->core, s->source);
279
280     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &device);
281 }
282
283 static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) {
284     pa_dbusiface_stream *s = userdata;
285     dbus_uint32_t sample_format = 0;
286
287     pa_assert(conn);
288     pa_assert(msg);
289     pa_assert(s);
290
291     sample_format = (s->type == STREAM_TYPE_PLAYBACK)
292                     ? s->sink_input->sample_spec.format
293                     : s->source_output->sample_spec.format;
294
295     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_format);
296 }
297
298 static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) {
299     pa_dbusiface_stream *s = userdata;
300
301     pa_assert(conn);
302     pa_assert(msg);
303     pa_assert(s);
304
305     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &s->sample_rate);
306 }
307
308 static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata) {
309     pa_dbusiface_stream *s = userdata;
310     pa_channel_map *channel_map = NULL;
311     dbus_uint32_t channels[PA_CHANNELS_MAX];
312     unsigned i = 0;
313
314     pa_assert(conn);
315     pa_assert(msg);
316     pa_assert(s);
317
318     channel_map = (s->type == STREAM_TYPE_PLAYBACK) ? &s->sink_input->channel_map : &s->source_output->channel_map;
319
320     for (i = 0; i < channel_map->channels; ++i)
321         channels[i] = channel_map->map[i];
322
323     pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, channels, channel_map->channels);
324 }
325
326 static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
327     pa_dbusiface_stream *s = userdata;
328     dbus_uint32_t volume[PA_CHANNELS_MAX];
329     unsigned i = 0;
330
331     pa_assert(conn);
332     pa_assert(msg);
333     pa_assert(s);
334
335     if (s->type == STREAM_TYPE_RECORD) {
336         pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have volume.");
337         return;
338     }
339
340     for (i = 0; i < s->volume.channels; ++i)
341         volume[i] = s->volume.values[i];
342
343     pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, volume, s->volume.channels);
344 }
345
346 static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
347     pa_dbusiface_stream *s = userdata;
348     unsigned stream_channels = 0;
349     dbus_uint32_t *volume = NULL;
350     unsigned n_volume_entries = 0;
351     pa_cvolume new_vol;
352     unsigned i = 0;
353
354     pa_assert(conn);
355     pa_assert(msg);
356     pa_assert(s);
357
358     if (s->type == STREAM_TYPE_RECORD) {
359         pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have volume.");
360         return;
361     }
362
363     pa_cvolume_init(&new_vol);
364
365     stream_channels = s->sink_input->channel_map.channels;
366
367     new_vol.channels = stream_channels;
368
369     if (pa_dbus_get_fixed_array_set_property_arg(conn, msg, DBUS_TYPE_UINT32, &volume, &n_volume_entries) < 0)
370         return;
371
372     if (n_volume_entries != stream_channels) {
373         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS,
374                            "Expected %u volume entries, got %u.", stream_channels, n_volume_entries);
375         return;
376     }
377
378     for (i = 0; i < n_volume_entries; ++i) {
379         if (volume[i] > PA_VOLUME_MAX) {
380             pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too large volume value: %u", volume[i]);
381             return;
382         }
383         new_vol.values[i] = volume[i];
384     }
385
386     pa_sink_input_set_volume(s->sink_input, &new_vol, TRUE, TRUE);
387
388     pa_dbus_send_empty_reply(conn, msg);
389 }
390
391 static void handle_get_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata) {
392     pa_dbusiface_stream *s = userdata;
393
394     pa_assert(conn);
395     pa_assert(msg);
396     pa_assert(s);
397
398     if (s->type == STREAM_TYPE_RECORD) {
399         pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have mute.");
400         return;
401     }
402
403     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &s->is_muted);
404 }
405
406 static void handle_set_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata) {
407     pa_dbusiface_stream *s = userdata;
408     dbus_bool_t is_muted = FALSE;
409
410     pa_assert(conn);
411     pa_assert(msg);
412     pa_assert(s);
413
414     if (pa_dbus_get_basic_set_property_arg(conn, msg, DBUS_TYPE_BOOLEAN, &is_muted) < 0)
415         return;
416
417     if (s->type == STREAM_TYPE_RECORD) {
418         pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have mute.");
419         return;
420     }
421
422     pa_sink_input_set_mute(s->sink_input, is_muted, TRUE);
423
424     pa_dbus_send_empty_reply(conn, msg);
425 };
426
427 static void handle_get_buffer_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) {
428     pa_dbusiface_stream *s = userdata;
429     dbus_uint64_t buffer_latency = 0;
430
431     pa_assert(conn);
432     pa_assert(msg);
433     pa_assert(s);
434
435     if (s->type == STREAM_TYPE_PLAYBACK)
436         buffer_latency = pa_sink_input_get_latency(s->sink_input, NULL);
437     else
438         buffer_latency = pa_source_output_get_latency(s->source_output, NULL);
439
440     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &buffer_latency);
441 }
442
443 static void handle_get_device_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) {
444     pa_dbusiface_stream *s = userdata;
445     dbus_uint64_t device_latency = 0;
446
447     pa_assert(conn);
448     pa_assert(msg);
449     pa_assert(s);
450
451     if (s->type == STREAM_TYPE_PLAYBACK)
452         pa_sink_input_get_latency(s->sink_input, &device_latency);
453     else
454         pa_source_output_get_latency(s->source_output, &device_latency);
455
456     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &device_latency);
457 }
458
459 static void handle_get_resample_method(DBusConnection *conn, DBusMessage *msg, void *userdata) {
460     pa_dbusiface_stream *s = userdata;
461     const char *resample_method = NULL;
462
463     pa_assert(conn);
464     pa_assert(msg);
465     pa_assert(s);
466
467     if (s->type == STREAM_TYPE_PLAYBACK)
468         resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method);
469     else
470         resample_method = pa_resample_method_to_string(s->source_output->actual_resample_method);
471
472     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &resample_method);
473 }
474
475 static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
476     pa_dbusiface_stream *s = userdata;
477
478     pa_assert(conn);
479     pa_assert(msg);
480     pa_assert(s);
481
482     pa_dbus_send_proplist_variant_reply(conn, msg, s->proplist);
483 }
484
485 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
486     pa_dbusiface_stream *s = userdata;
487     DBusMessage *reply = NULL;
488     DBusMessageIter msg_iter;
489     DBusMessageIter dict_iter;
490     dbus_uint32_t idx = 0;
491     const char *driver = NULL;
492     pa_module *owner_module = NULL;
493     const char *owner_module_path = NULL;
494     pa_client *client = NULL;
495     const char *client_path = NULL;
496     const char *device = NULL;
497     dbus_uint32_t sample_format = 0;
498     pa_channel_map *channel_map = NULL;
499     dbus_uint32_t channels[PA_CHANNELS_MAX];
500     dbus_uint32_t volume[PA_CHANNELS_MAX];
501     dbus_uint64_t buffer_latency = 0;
502     dbus_uint64_t device_latency = 0;
503     const char *resample_method = NULL;
504     unsigned i = 0;
505
506     pa_assert(conn);
507     pa_assert(msg);
508     pa_assert(s);
509
510     if (s->type == STREAM_TYPE_PLAYBACK) {
511         idx = s->sink_input->index;
512         driver = s->sink_input->driver;
513         owner_module = s->sink_input->module;
514         client = s->sink_input->client;
515         device = pa_dbusiface_core_get_sink_path(s->core, s->sink);
516         sample_format = s->sink_input->sample_spec.format;
517         channel_map = &s->sink_input->channel_map;
518         for (i = 0; i < s->volume.channels; ++i)
519             volume[i] = s->volume.values[i];
520         buffer_latency = pa_sink_input_get_latency(s->sink_input, &device_latency);
521         resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method);
522     } else {
523         idx = s->source_output->index;
524         driver = s->source_output->driver;
525         owner_module = s->source_output->module;
526         client = s->source_output->client;
527         device = pa_dbusiface_core_get_source_path(s->core, s->source);
528         sample_format = s->source_output->sample_spec.format;
529         channel_map = &s->source_output->channel_map;
530         buffer_latency = pa_source_output_get_latency(s->source_output, &device_latency);
531         resample_method = pa_resample_method_to_string(s->source_output->actual_resample_method);
532     }
533     if (owner_module)
534         owner_module_path = pa_dbusiface_core_get_module_path(s->core, owner_module);
535     if (client)
536         client_path = pa_dbusiface_core_get_client_path(s->core, client);
537     for (i = 0; i < channel_map->channels; ++i)
538         channels[i] = channel_map->map[i];
539
540     pa_assert_se((reply = dbus_message_new_method_return(msg)));
541
542     dbus_message_iter_init_append(reply, &msg_iter);
543     pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
544
545     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx);
546
547     if (driver)
548         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &driver);
549
550     if (owner_module)
551         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module_path);
552
553     if (client)
554         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CLIENT].property_name, DBUS_TYPE_OBJECT_PATH, &client_path);
555
556     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format);
557     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &s->sample_rate);
558     pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, channel_map->channels);
559
560     if (s->type == STREAM_TYPE_PLAYBACK) {
561         pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME].property_name, DBUS_TYPE_UINT32, volume, s->volume.channels);
562         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_IS_MUTED].property_name, DBUS_TYPE_BOOLEAN, &s->is_muted);
563     }
564
565     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BUFFER_LATENCY].property_name, DBUS_TYPE_UINT64, &buffer_latency);
566     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEVICE_LATENCY].property_name, DBUS_TYPE_UINT64, &device_latency);
567     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_RESAMPLE_METHOD].property_name, DBUS_TYPE_STRING, &resample_method);
568     pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, s->proplist);
569
570     pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
571     pa_assert_se(dbus_connection_send(conn, reply, NULL));
572     dbus_message_unref(reply);
573 }
574
575 static void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata) {
576     pa_dbusiface_stream *s = userdata;
577     const char *device = NULL;
578     DBusError error;
579
580     pa_assert(conn);
581     pa_assert(msg);
582     pa_assert(s);
583
584     dbus_error_init(&error);
585
586     if (!dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID)) {
587         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
588         dbus_error_free(&error);
589         return;
590     }
591
592     if (s->type == STREAM_TYPE_PLAYBACK) {
593         pa_sink *sink = pa_dbusiface_core_get_sink(s->core, device);
594
595         if (!sink) {
596             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", device);
597             return;
598         }
599
600         if (pa_sink_input_move_to(s->sink_input, sink, TRUE) < 0) {
601             pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED,
602                                "Moving playback stream %u to sink %s failed.", s->sink_input->index, sink->name);
603             return;
604         }
605     } else {
606         pa_source *source = pa_dbusiface_core_get_source(s->core, device);
607
608         if (!source) {
609             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such source.", device);
610             return;
611         }
612
613         if (pa_source_output_move_to(s->source_output, source, TRUE) < 0) {
614             pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED,
615                                "Moving record stream %u to source %s failed.", s->source_output->index, source->name);
616             return;
617         }
618     }
619
620     pa_dbus_send_empty_reply(conn, msg);
621 }
622
623 static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata) {
624     pa_dbusiface_stream *s = userdata;
625
626     pa_assert(conn);
627     pa_assert(msg);
628     pa_assert(s);
629
630     if (s->type == STREAM_TYPE_PLAYBACK)
631         pa_sink_input_kill(s->sink_input);
632     else
633         pa_source_output_kill(s->source_output);
634
635     pa_dbus_send_empty_reply(conn, msg);
636 }
637
638 static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
639     pa_dbusiface_stream *s = userdata;
640     DBusMessage *signal = NULL;
641     const char *new_device_path = NULL;
642     uint32_t new_sample_rate = 0;
643     pa_proplist *new_proplist = NULL;
644     unsigned i = 0;
645
646     pa_assert(c);
647     pa_assert(s);
648
649     if ((s->type == STREAM_TYPE_PLAYBACK && idx != s->sink_input->index)
650         || (s->type == STREAM_TYPE_RECORD && idx != s->source_output->index))
651         return;
652
653     if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
654         return;
655
656     pa_assert(((s->type == STREAM_TYPE_PLAYBACK)
657                 && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT))
658               || ((s->type == STREAM_TYPE_RECORD)
659                    && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT)));
660
661     if (s->type == STREAM_TYPE_PLAYBACK) {
662         pa_sink *new_sink = s->sink_input->sink;
663
664         if (s->sink != new_sink) {
665             pa_sink_unref(s->sink);
666             s->sink = pa_sink_ref(new_sink);
667
668             new_device_path = pa_dbusiface_core_get_sink_path(s->core, new_sink);
669
670             pa_assert_se(signal = dbus_message_new_signal(s->path,
671                                                           PA_DBUSIFACE_STREAM_INTERFACE,
672                                                           signals[SIGNAL_DEVICE_UPDATED].name));
673             pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
674
675             pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
676             dbus_message_unref(signal);
677             signal = NULL;
678         }
679     } else {
680         pa_source *new_source = s->source_output->source;
681
682         if (s->source != new_source) {
683             pa_source_unref(s->source);
684             s->source = pa_source_ref(new_source);
685
686             new_device_path = pa_dbusiface_core_get_source_path(s->core, new_source);
687
688             pa_assert_se(signal = dbus_message_new_signal(s->path,
689                                                           PA_DBUSIFACE_STREAM_INTERFACE,
690                                                           signals[SIGNAL_DEVICE_UPDATED].name));
691             pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
692
693             pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
694             dbus_message_unref(signal);
695             signal = NULL;
696         }
697     }
698
699     new_sample_rate = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->sample_spec.rate : s->source_output->sample_spec.rate;
700
701     if (s->sample_rate != new_sample_rate) {
702         s->sample_rate = new_sample_rate;
703
704         pa_assert_se(signal = dbus_message_new_signal(s->path,
705                                                       PA_DBUSIFACE_STREAM_INTERFACE,
706                                                       signals[SIGNAL_SAMPLE_RATE_UPDATED].name));
707         pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID));
708
709         pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
710         dbus_message_unref(signal);
711         signal = NULL;
712     }
713
714     if (s->type == STREAM_TYPE_PLAYBACK) {
715         pa_cvolume new_volume;
716         pa_bool_t new_muted = FALSE;
717
718         pa_sink_input_get_volume(s->sink_input, &new_volume, TRUE);
719
720         if (!pa_cvolume_equal(&s->volume, &new_volume)) {
721             dbus_uint32_t volume[PA_CHANNELS_MAX];
722             dbus_uint32_t *volume_ptr = volume;
723
724             s->volume = new_volume;
725
726             for (i = 0; i < s->volume.channels; ++i)
727                 volume[i] = s->volume.values[i];
728
729             pa_assert_se(signal = dbus_message_new_signal(s->path,
730                                                           PA_DBUSIFACE_STREAM_INTERFACE,
731                                                           signals[SIGNAL_VOLUME_UPDATED].name));
732             pa_assert_se(dbus_message_append_args(signal,
733                                                   DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels,
734                                                   DBUS_TYPE_INVALID));
735
736             pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
737             dbus_message_unref(signal);
738             signal = NULL;
739         }
740
741         new_muted = pa_sink_input_get_mute(s->sink_input);
742
743         if (s->is_muted != new_muted) {
744             s->is_muted = new_muted;
745
746             pa_assert_se(signal = dbus_message_new_signal(s->path,
747                                                           PA_DBUSIFACE_STREAM_INTERFACE,
748                                                           signals[SIGNAL_MUTE_UPDATED].name));
749             pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &s->is_muted, DBUS_TYPE_INVALID));
750
751             pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
752             dbus_message_unref(signal);
753             signal = NULL;
754         }
755     }
756
757     new_proplist = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->proplist : s->source_output->proplist;
758
759     if (!pa_proplist_equal(s->proplist, new_proplist)) {
760         DBusMessageIter msg_iter;
761
762         pa_proplist_update(s->proplist, PA_UPDATE_SET, new_proplist);
763
764         pa_assert_se(signal = dbus_message_new_signal(s->path,
765                                                       PA_DBUSIFACE_STREAM_INTERFACE,
766                                                       signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
767         dbus_message_iter_init_append(signal, &msg_iter);
768         pa_dbus_append_proplist(&msg_iter, s->proplist);
769
770         pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
771         dbus_message_unref(signal);
772         signal = NULL;
773     }
774 }
775
776 static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *slot_data) {
777     pa_dbusiface_stream *s = slot_data;
778     DBusMessage *signal = NULL;
779     DBusMessageIter msg_iter;
780     const char *name = NULL;
781     pa_proplist *property_list = NULL;
782
783     pa_assert(call_data);
784     pa_assert(s);
785
786     if (s->type == STREAM_TYPE_PLAYBACK) {
787         pa_sink_input_send_event_hook_data *data = call_data;
788
789         if (data->sink_input != s->sink_input)
790             return PA_HOOK_OK;
791
792         name = data->event;
793         property_list = data->data;
794     } else {
795         pa_source_output_send_event_hook_data *data = call_data;
796
797         if (data->source_output != s->source_output)
798             return PA_HOOK_OK;
799
800         name = data->event;
801         property_list = data->data;
802     }
803
804     pa_assert_se(signal = dbus_message_new_signal(s->path,
805                                                   PA_DBUSIFACE_STREAM_INTERFACE,
806                                                   signals[SIGNAL_STREAM_EVENT].name));
807     dbus_message_iter_init_append(signal, &msg_iter);
808     pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name));
809     pa_dbus_append_proplist(&msg_iter, property_list);
810
811     pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
812     dbus_message_unref(signal);
813
814     return PA_HOOK_OK;
815 }
816
817 pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, pa_sink_input *sink_input) {
818     pa_dbusiface_stream *s;
819
820     pa_assert(core);
821     pa_assert(sink_input);
822
823     s = pa_xnew(pa_dbusiface_stream, 1);
824     s->core = core;
825     s->sink_input = pa_sink_input_ref(sink_input);
826     s->type = STREAM_TYPE_PLAYBACK;
827     s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, PLAYBACK_OBJECT_NAME, sink_input->index);
828     s->sink = pa_sink_ref(sink_input->sink);
829     s->sample_rate = sink_input->sample_spec.rate;
830     pa_sink_input_get_volume(sink_input, &s->volume, TRUE);
831     s->is_muted = pa_sink_input_get_mute(sink_input);
832     s->proplist = pa_proplist_copy(sink_input->proplist);
833     s->dbus_protocol = pa_dbus_protocol_get(sink_input->core);
834     s->subscription = pa_subscription_new(sink_input->core, PA_SUBSCRIPTION_MASK_SINK_INPUT, subscription_cb, s);
835     s->send_event_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT],
836                                          PA_HOOK_NORMAL,
837                                          send_event_cb,
838                                          s);
839
840     pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0);
841
842     return s;
843 }
844
845 pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_source_output *source_output) {
846     pa_dbusiface_stream *s;
847
848     pa_assert(core);
849     pa_assert(source_output);
850
851     s = pa_xnew(pa_dbusiface_stream, 1);
852     s->core = core;
853     s->source_output = pa_source_output_ref(source_output);
854     s->type = STREAM_TYPE_RECORD;
855     s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, RECORD_OBJECT_NAME, source_output->index);
856     s->source = pa_source_ref(source_output->source);
857     s->sample_rate = source_output->sample_spec.rate;
858     pa_cvolume_init(&s->volume);
859     s->is_muted = FALSE;
860     s->proplist = pa_proplist_copy(source_output->proplist);
861     s->dbus_protocol = pa_dbus_protocol_get(source_output->core);
862     s->subscription = pa_subscription_new(source_output->core, PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscription_cb, s);
863     s->send_event_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT],
864                                          PA_HOOK_NORMAL,
865                                          send_event_cb,
866                                          s);
867
868     pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0);
869
870     return s;
871 }
872
873 void pa_dbusiface_stream_free(pa_dbusiface_stream *s) {
874     pa_assert(s);
875
876     pa_assert_se(pa_dbus_protocol_remove_interface(s->dbus_protocol, s->path, stream_interface_info.name) >= 0);
877
878     if (s->type == STREAM_TYPE_PLAYBACK) {
879         pa_sink_input_unref(s->sink_input);
880         pa_sink_unref(s->sink);
881     } else {
882         pa_source_output_unref(s->source_output);
883         pa_source_unref(s->source);
884     }
885
886     pa_proplist_free(s->proplist);
887     pa_dbus_protocol_unref(s->dbus_protocol);
888     pa_subscription_free(s->subscription);
889     pa_hook_slot_free(s->send_event_slot);
890
891     pa_xfree(s->path);
892     pa_xfree(s);
893 }
894
895 const char *pa_dbusiface_stream_get_path(pa_dbusiface_stream *s) {
896     pa_assert(s);
897
898     return s->path;
899 }