Merge remote branch 'coling/history'
[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     dbus_bool_t mute;
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, DBusMessageIter *iter, void *userdata);
74 static void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
75 static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, 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_MUTE,
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_MUTE]            = { .property_name = "Mute",           .type = "b",      .get_cb = handle_get_mute,            .set_cb = handle_set_mute },
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, DBusMessageIter *iter, void *userdata) {
347     pa_dbusiface_stream *s = userdata;
348     DBusMessageIter array_iter;
349     int stream_channels = 0;
350     dbus_uint32_t *volume = NULL;
351     int n_volume_entries = 0;
352     pa_cvolume new_vol;
353     int i = 0;
354
355     pa_assert(conn);
356     pa_assert(msg);
357     pa_assert(iter);
358     pa_assert(s);
359
360     if (s->type == STREAM_TYPE_RECORD) {
361         pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have volume.");
362         return;
363     }
364
365     pa_cvolume_init(&new_vol);
366
367     stream_channels = s->sink_input->channel_map.channels;
368
369     new_vol.channels = stream_channels;
370
371     dbus_message_iter_recurse(iter, &array_iter);
372     dbus_message_iter_get_fixed_array(&array_iter, &volume, &n_volume_entries);
373
374     if (n_volume_entries != stream_channels) {
375         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS,
376                            "Expected %u volume entries, got %u.", stream_channels, n_volume_entries);
377         return;
378     }
379
380     for (i = 0; i < n_volume_entries; ++i) {
381         if (volume[i] > PA_VOLUME_MAX) {
382             pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too large volume value: %u", volume[i]);
383             return;
384         }
385         new_vol.values[i] = volume[i];
386     }
387
388     pa_sink_input_set_volume(s->sink_input, &new_vol, TRUE, TRUE);
389
390     pa_dbus_send_empty_reply(conn, msg);
391 }
392
393 static void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
394     pa_dbusiface_stream *s = userdata;
395
396     pa_assert(conn);
397     pa_assert(msg);
398     pa_assert(s);
399
400     if (s->type == STREAM_TYPE_RECORD) {
401         pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have mute.");
402         return;
403     }
404
405     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &s->mute);
406 }
407
408 static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
409     pa_dbusiface_stream *s = userdata;
410     dbus_bool_t mute = FALSE;
411
412     pa_assert(conn);
413     pa_assert(msg);
414     pa_assert(iter);
415     pa_assert(s);
416
417     dbus_message_iter_get_basic(iter, &mute);
418
419     if (s->type == STREAM_TYPE_RECORD) {
420         pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have mute.");
421         return;
422     }
423
424     pa_sink_input_set_mute(s->sink_input, mute, TRUE);
425
426     pa_dbus_send_empty_reply(conn, msg);
427 };
428
429 static void handle_get_buffer_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) {
430     pa_dbusiface_stream *s = userdata;
431     dbus_uint64_t buffer_latency = 0;
432
433     pa_assert(conn);
434     pa_assert(msg);
435     pa_assert(s);
436
437     if (s->type == STREAM_TYPE_PLAYBACK)
438         buffer_latency = pa_sink_input_get_latency(s->sink_input, NULL);
439     else
440         buffer_latency = pa_source_output_get_latency(s->source_output, NULL);
441
442     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &buffer_latency);
443 }
444
445 static void handle_get_device_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) {
446     pa_dbusiface_stream *s = userdata;
447     dbus_uint64_t device_latency = 0;
448
449     pa_assert(conn);
450     pa_assert(msg);
451     pa_assert(s);
452
453     if (s->type == STREAM_TYPE_PLAYBACK)
454         pa_sink_input_get_latency(s->sink_input, &device_latency);
455     else
456         pa_source_output_get_latency(s->source_output, &device_latency);
457
458     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &device_latency);
459 }
460
461 static void handle_get_resample_method(DBusConnection *conn, DBusMessage *msg, void *userdata) {
462     pa_dbusiface_stream *s = userdata;
463     const char *resample_method = NULL;
464
465     pa_assert(conn);
466     pa_assert(msg);
467     pa_assert(s);
468
469     if (s->type == STREAM_TYPE_PLAYBACK)
470         resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method);
471     else
472         resample_method = pa_resample_method_to_string(s->source_output->actual_resample_method);
473
474     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &resample_method);
475 }
476
477 static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
478     pa_dbusiface_stream *s = userdata;
479
480     pa_assert(conn);
481     pa_assert(msg);
482     pa_assert(s);
483
484     pa_dbus_send_proplist_variant_reply(conn, msg, s->proplist);
485 }
486
487 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
488     pa_dbusiface_stream *s = userdata;
489     DBusMessage *reply = NULL;
490     DBusMessageIter msg_iter;
491     DBusMessageIter dict_iter;
492     dbus_uint32_t idx = 0;
493     const char *driver = NULL;
494     pa_module *owner_module = NULL;
495     const char *owner_module_path = NULL;
496     pa_client *client = NULL;
497     const char *client_path = NULL;
498     const char *device = NULL;
499     dbus_uint32_t sample_format = 0;
500     pa_channel_map *channel_map = NULL;
501     dbus_uint32_t channels[PA_CHANNELS_MAX];
502     dbus_uint32_t volume[PA_CHANNELS_MAX];
503     dbus_uint64_t buffer_latency = 0;
504     dbus_uint64_t device_latency = 0;
505     const char *resample_method = NULL;
506     unsigned i = 0;
507
508     pa_assert(conn);
509     pa_assert(msg);
510     pa_assert(s);
511
512     if (s->type == STREAM_TYPE_PLAYBACK) {
513         idx = s->sink_input->index;
514         driver = s->sink_input->driver;
515         owner_module = s->sink_input->module;
516         client = s->sink_input->client;
517         device = pa_dbusiface_core_get_sink_path(s->core, s->sink);
518         sample_format = s->sink_input->sample_spec.format;
519         channel_map = &s->sink_input->channel_map;
520         for (i = 0; i < s->volume.channels; ++i)
521             volume[i] = s->volume.values[i];
522         buffer_latency = pa_sink_input_get_latency(s->sink_input, &device_latency);
523         resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method);
524     } else {
525         idx = s->source_output->index;
526         driver = s->source_output->driver;
527         owner_module = s->source_output->module;
528         client = s->source_output->client;
529         device = pa_dbusiface_core_get_source_path(s->core, s->source);
530         sample_format = s->source_output->sample_spec.format;
531         channel_map = &s->source_output->channel_map;
532         buffer_latency = pa_source_output_get_latency(s->source_output, &device_latency);
533         resample_method = pa_resample_method_to_string(s->source_output->actual_resample_method);
534     }
535     if (owner_module)
536         owner_module_path = pa_dbusiface_core_get_module_path(s->core, owner_module);
537     if (client)
538         client_path = pa_dbusiface_core_get_client_path(s->core, client);
539     for (i = 0; i < channel_map->channels; ++i)
540         channels[i] = channel_map->map[i];
541
542     pa_assert_se((reply = dbus_message_new_method_return(msg)));
543
544     dbus_message_iter_init_append(reply, &msg_iter);
545     pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
546
547     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx);
548
549     if (driver)
550         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &driver);
551
552     if (owner_module)
553         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module_path);
554
555     if (client)
556         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CLIENT].property_name, DBUS_TYPE_OBJECT_PATH, &client_path);
557
558     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format);
559     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &s->sample_rate);
560     pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, channel_map->channels);
561
562     if (s->type == STREAM_TYPE_PLAYBACK) {
563         pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME].property_name, DBUS_TYPE_UINT32, volume, s->volume.channels);
564         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &s->mute);
565     }
566
567     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BUFFER_LATENCY].property_name, DBUS_TYPE_UINT64, &buffer_latency);
568     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEVICE_LATENCY].property_name, DBUS_TYPE_UINT64, &device_latency);
569     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_RESAMPLE_METHOD].property_name, DBUS_TYPE_STRING, &resample_method);
570     pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, s->proplist);
571
572     pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
573     pa_assert_se(dbus_connection_send(conn, reply, NULL));
574     dbus_message_unref(reply);
575 }
576
577 static void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata) {
578     pa_dbusiface_stream *s = userdata;
579     const char *device = NULL;
580
581     pa_assert(conn);
582     pa_assert(msg);
583     pa_assert(s);
584
585     pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID));
586
587     if (s->type == STREAM_TYPE_PLAYBACK) {
588         pa_sink *sink = pa_dbusiface_core_get_sink(s->core, device);
589
590         if (!sink) {
591             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", device);
592             return;
593         }
594
595         if (pa_sink_input_move_to(s->sink_input, sink, TRUE) < 0) {
596             pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED,
597                                "Moving playback stream %u to sink %s failed.", s->sink_input->index, sink->name);
598             return;
599         }
600     } else {
601         pa_source *source = pa_dbusiface_core_get_source(s->core, device);
602
603         if (!source) {
604             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such source.", device);
605             return;
606         }
607
608         if (pa_source_output_move_to(s->source_output, source, TRUE) < 0) {
609             pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED,
610                                "Moving record stream %u to source %s failed.", s->source_output->index, source->name);
611             return;
612         }
613     }
614
615     pa_dbus_send_empty_reply(conn, msg);
616 }
617
618 static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata) {
619     pa_dbusiface_stream *s = userdata;
620
621     pa_assert(conn);
622     pa_assert(msg);
623     pa_assert(s);
624
625     if (s->type == STREAM_TYPE_PLAYBACK)
626         pa_sink_input_kill(s->sink_input);
627     else
628         pa_source_output_kill(s->source_output);
629
630     pa_dbus_send_empty_reply(conn, msg);
631 }
632
633 static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
634     pa_dbusiface_stream *s = userdata;
635     DBusMessage *signal = NULL;
636     const char *new_device_path = NULL;
637     uint32_t new_sample_rate = 0;
638     pa_proplist *new_proplist = NULL;
639     unsigned i = 0;
640
641     pa_assert(c);
642     pa_assert(s);
643
644     if ((s->type == STREAM_TYPE_PLAYBACK && idx != s->sink_input->index)
645         || (s->type == STREAM_TYPE_RECORD && idx != s->source_output->index))
646         return;
647
648     if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
649         return;
650
651     pa_assert(((s->type == STREAM_TYPE_PLAYBACK)
652                 && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT))
653               || ((s->type == STREAM_TYPE_RECORD)
654                    && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT)));
655
656     if (s->type == STREAM_TYPE_PLAYBACK) {
657         pa_sink *new_sink = s->sink_input->sink;
658
659         if (s->sink != new_sink) {
660             pa_sink_unref(s->sink);
661             s->sink = pa_sink_ref(new_sink);
662
663             new_device_path = pa_dbusiface_core_get_sink_path(s->core, new_sink);
664
665             pa_assert_se(signal = dbus_message_new_signal(s->path,
666                                                           PA_DBUSIFACE_STREAM_INTERFACE,
667                                                           signals[SIGNAL_DEVICE_UPDATED].name));
668             pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
669
670             pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
671             dbus_message_unref(signal);
672             signal = NULL;
673         }
674     } else {
675         pa_source *new_source = s->source_output->source;
676
677         if (s->source != new_source) {
678             pa_source_unref(s->source);
679             s->source = pa_source_ref(new_source);
680
681             new_device_path = pa_dbusiface_core_get_source_path(s->core, new_source);
682
683             pa_assert_se(signal = dbus_message_new_signal(s->path,
684                                                           PA_DBUSIFACE_STREAM_INTERFACE,
685                                                           signals[SIGNAL_DEVICE_UPDATED].name));
686             pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
687
688             pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
689             dbus_message_unref(signal);
690             signal = NULL;
691         }
692     }
693
694     new_sample_rate = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->sample_spec.rate : s->source_output->sample_spec.rate;
695
696     if (s->sample_rate != new_sample_rate) {
697         s->sample_rate = new_sample_rate;
698
699         pa_assert_se(signal = dbus_message_new_signal(s->path,
700                                                       PA_DBUSIFACE_STREAM_INTERFACE,
701                                                       signals[SIGNAL_SAMPLE_RATE_UPDATED].name));
702         pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID));
703
704         pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
705         dbus_message_unref(signal);
706         signal = NULL;
707     }
708
709     if (s->type == STREAM_TYPE_PLAYBACK) {
710         pa_cvolume new_volume;
711         pa_bool_t new_mute = FALSE;
712
713         pa_sink_input_get_volume(s->sink_input, &new_volume, TRUE);
714
715         if (!pa_cvolume_equal(&s->volume, &new_volume)) {
716             dbus_uint32_t volume[PA_CHANNELS_MAX];
717             dbus_uint32_t *volume_ptr = volume;
718
719             s->volume = new_volume;
720
721             for (i = 0; i < s->volume.channels; ++i)
722                 volume[i] = s->volume.values[i];
723
724             pa_assert_se(signal = dbus_message_new_signal(s->path,
725                                                           PA_DBUSIFACE_STREAM_INTERFACE,
726                                                           signals[SIGNAL_VOLUME_UPDATED].name));
727             pa_assert_se(dbus_message_append_args(signal,
728                                                   DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels,
729                                                   DBUS_TYPE_INVALID));
730
731             pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
732             dbus_message_unref(signal);
733             signal = NULL;
734         }
735
736         new_mute = pa_sink_input_get_mute(s->sink_input);
737
738         if (s->mute != new_mute) {
739             s->mute = new_mute;
740
741             pa_assert_se(signal = dbus_message_new_signal(s->path,
742                                                           PA_DBUSIFACE_STREAM_INTERFACE,
743                                                           signals[SIGNAL_MUTE_UPDATED].name));
744             pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &s->mute, DBUS_TYPE_INVALID));
745
746             pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
747             dbus_message_unref(signal);
748             signal = NULL;
749         }
750     }
751
752     new_proplist = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->proplist : s->source_output->proplist;
753
754     if (!pa_proplist_equal(s->proplist, new_proplist)) {
755         DBusMessageIter msg_iter;
756
757         pa_proplist_update(s->proplist, PA_UPDATE_SET, new_proplist);
758
759         pa_assert_se(signal = dbus_message_new_signal(s->path,
760                                                       PA_DBUSIFACE_STREAM_INTERFACE,
761                                                       signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
762         dbus_message_iter_init_append(signal, &msg_iter);
763         pa_dbus_append_proplist(&msg_iter, s->proplist);
764
765         pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
766         dbus_message_unref(signal);
767         signal = NULL;
768     }
769 }
770
771 static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *slot_data) {
772     pa_dbusiface_stream *s = slot_data;
773     DBusMessage *signal = NULL;
774     DBusMessageIter msg_iter;
775     const char *name = NULL;
776     pa_proplist *property_list = NULL;
777
778     pa_assert(call_data);
779     pa_assert(s);
780
781     if (s->type == STREAM_TYPE_PLAYBACK) {
782         pa_sink_input_send_event_hook_data *data = call_data;
783
784         if (data->sink_input != s->sink_input)
785             return PA_HOOK_OK;
786
787         name = data->event;
788         property_list = data->data;
789     } else {
790         pa_source_output_send_event_hook_data *data = call_data;
791
792         if (data->source_output != s->source_output)
793             return PA_HOOK_OK;
794
795         name = data->event;
796         property_list = data->data;
797     }
798
799     pa_assert_se(signal = dbus_message_new_signal(s->path,
800                                                   PA_DBUSIFACE_STREAM_INTERFACE,
801                                                   signals[SIGNAL_STREAM_EVENT].name));
802     dbus_message_iter_init_append(signal, &msg_iter);
803     pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name));
804     pa_dbus_append_proplist(&msg_iter, property_list);
805
806     pa_dbus_protocol_send_signal(s->dbus_protocol, signal);
807     dbus_message_unref(signal);
808
809     return PA_HOOK_OK;
810 }
811
812 pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, pa_sink_input *sink_input) {
813     pa_dbusiface_stream *s;
814
815     pa_assert(core);
816     pa_assert(sink_input);
817
818     s = pa_xnew(pa_dbusiface_stream, 1);
819     s->core = core;
820     s->sink_input = pa_sink_input_ref(sink_input);
821     s->type = STREAM_TYPE_PLAYBACK;
822     s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, PLAYBACK_OBJECT_NAME, sink_input->index);
823     s->sink = pa_sink_ref(sink_input->sink);
824     s->sample_rate = sink_input->sample_spec.rate;
825     pa_sink_input_get_volume(sink_input, &s->volume, TRUE);
826     s->mute = pa_sink_input_get_mute(sink_input);
827     s->proplist = pa_proplist_copy(sink_input->proplist);
828     s->dbus_protocol = pa_dbus_protocol_get(sink_input->core);
829     s->subscription = pa_subscription_new(sink_input->core, PA_SUBSCRIPTION_MASK_SINK_INPUT, subscription_cb, s);
830     s->send_event_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT],
831                                          PA_HOOK_NORMAL,
832                                          send_event_cb,
833                                          s);
834
835     pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0);
836
837     return s;
838 }
839
840 pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_source_output *source_output) {
841     pa_dbusiface_stream *s;
842
843     pa_assert(core);
844     pa_assert(source_output);
845
846     s = pa_xnew(pa_dbusiface_stream, 1);
847     s->core = core;
848     s->source_output = pa_source_output_ref(source_output);
849     s->type = STREAM_TYPE_RECORD;
850     s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, RECORD_OBJECT_NAME, source_output->index);
851     s->source = pa_source_ref(source_output->source);
852     s->sample_rate = source_output->sample_spec.rate;
853     pa_cvolume_init(&s->volume);
854     s->mute = FALSE;
855     s->proplist = pa_proplist_copy(source_output->proplist);
856     s->dbus_protocol = pa_dbus_protocol_get(source_output->core);
857     s->subscription = pa_subscription_new(source_output->core, PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscription_cb, s);
858     s->send_event_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT],
859                                          PA_HOOK_NORMAL,
860                                          send_event_cb,
861                                          s);
862
863     pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0);
864
865     return s;
866 }
867
868 void pa_dbusiface_stream_free(pa_dbusiface_stream *s) {
869     pa_assert(s);
870
871     pa_assert_se(pa_dbus_protocol_remove_interface(s->dbus_protocol, s->path, stream_interface_info.name) >= 0);
872
873     if (s->type == STREAM_TYPE_PLAYBACK) {
874         pa_sink_input_unref(s->sink_input);
875         pa_sink_unref(s->sink);
876     } else {
877         pa_source_output_unref(s->source_output);
878         pa_source_unref(s->source);
879     }
880
881     pa_proplist_free(s->proplist);
882     pa_dbus_protocol_unref(s->dbus_protocol);
883     pa_subscription_free(s->subscription);
884     pa_hook_slot_free(s->send_event_slot);
885
886     pa_xfree(s->path);
887     pa_xfree(s);
888 }
889
890 const char *pa_dbusiface_stream_get_path(pa_dbusiface_stream *s) {
891     pa_assert(s);
892
893     return s->path;
894 }