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