Allow read-only or non-existing sink input volume.
[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     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &resample_method);
494 }
495
496 static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
497     pa_dbusiface_stream *s = userdata;
498
499     pa_assert(conn);
500     pa_assert(msg);
501     pa_assert(s);
502
503     pa_dbus_send_proplist_variant_reply(conn, msg, s->proplist);
504 }
505
506 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
507     pa_dbusiface_stream *s = userdata;
508     DBusMessage *reply = NULL;
509     DBusMessageIter msg_iter;
510     DBusMessageIter dict_iter;
511     dbus_uint32_t idx = 0;
512     const char *driver = NULL;
513     pa_module *owner_module = NULL;
514     const char *owner_module_path = NULL;
515     pa_client *client = NULL;
516     const char *client_path = NULL;
517     const char *device = NULL;
518     dbus_uint32_t sample_format = 0;
519     pa_channel_map *channel_map = NULL;
520     dbus_uint32_t channels[PA_CHANNELS_MAX];
521     dbus_uint32_t volume[PA_CHANNELS_MAX];
522     dbus_uint64_t buffer_latency = 0;
523     dbus_uint64_t device_latency = 0;
524     const char *resample_method = NULL;
525     unsigned i = 0;
526
527     pa_assert(conn);
528     pa_assert(msg);
529     pa_assert(s);
530
531     if (s->has_volume) {
532         for (i = 0; i < s->volume.channels; ++i)
533             volume[i] = s->volume.values[i];
534     }
535
536     if (s->type == STREAM_TYPE_PLAYBACK) {
537         idx = s->sink_input->index;
538         driver = s->sink_input->driver;
539         owner_module = s->sink_input->module;
540         client = s->sink_input->client;
541         device = pa_dbusiface_core_get_sink_path(s->core, s->sink);
542         sample_format = s->sink_input->sample_spec.format;
543         channel_map = &s->sink_input->channel_map;
544         buffer_latency = pa_sink_input_get_latency(s->sink_input, &device_latency);
545         resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method);
546     } else {
547         idx = s->source_output->index;
548         driver = s->source_output->driver;
549         owner_module = s->source_output->module;
550         client = s->source_output->client;
551         device = pa_dbusiface_core_get_source_path(s->core, s->source);
552         sample_format = s->source_output->sample_spec.format;
553         channel_map = &s->source_output->channel_map;
554         buffer_latency = pa_source_output_get_latency(s->source_output, &device_latency);
555         resample_method = pa_resample_method_to_string(s->source_output->actual_resample_method);
556     }
557     if (owner_module)
558         owner_module_path = pa_dbusiface_core_get_module_path(s->core, owner_module);
559     if (client)
560         client_path = pa_dbusiface_core_get_client_path(s->core, client);
561     for (i = 0; i < channel_map->channels; ++i)
562         channels[i] = channel_map->map[i];
563
564     pa_assert_se((reply = dbus_message_new_method_return(msg)));
565
566     dbus_message_iter_init_append(reply, &msg_iter);
567     pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
568
569     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx);
570
571     if (driver)
572         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &driver);
573
574     if (owner_module)
575         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module_path);
576
577     if (client)
578         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CLIENT].property_name, DBUS_TYPE_OBJECT_PATH, &client_path);
579
580     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_OBJECT_PATH, &device);
581     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format);
582     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &s->sample_rate);
583     pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, channel_map->channels);
584
585     if (s->has_volume) {
586         pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME].property_name, DBUS_TYPE_UINT32, volume, s->volume.channels);
587         pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &s->mute);
588     }
589
590     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BUFFER_LATENCY].property_name, DBUS_TYPE_UINT64, &buffer_latency);
591     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEVICE_LATENCY].property_name, DBUS_TYPE_UINT64, &device_latency);
592     pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_RESAMPLE_METHOD].property_name, DBUS_TYPE_STRING, &resample_method);
593     pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, s->proplist);
594
595     pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
596     pa_assert_se(dbus_connection_send(conn, reply, NULL));
597     dbus_message_unref(reply);
598 }
599
600 static void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata) {
601     pa_dbusiface_stream *s = userdata;
602     const char *device = NULL;
603
604     pa_assert(conn);
605     pa_assert(msg);
606     pa_assert(s);
607
608     pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID));
609
610     if (s->type == STREAM_TYPE_PLAYBACK) {
611         pa_sink *sink = pa_dbusiface_core_get_sink(s->core, device);
612
613         if (!sink) {
614             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", device);
615             return;
616         }
617
618         if (pa_sink_input_move_to(s->sink_input, sink, TRUE) < 0) {
619             pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED,
620                                "Moving playback stream %u to sink %s failed.", s->sink_input->index, sink->name);
621             return;
622         }
623     } else {
624         pa_source *source = pa_dbusiface_core_get_source(s->core, device);
625
626         if (!source) {
627             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such source.", device);
628             return;
629         }
630
631         if (pa_source_output_move_to(s->source_output, source, TRUE) < 0) {
632             pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED,
633                                "Moving record stream %u to source %s failed.", s->source_output->index, source->name);
634             return;
635         }
636     }
637
638     pa_dbus_send_empty_reply(conn, msg);
639 }
640
641 static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata) {
642     pa_dbusiface_stream *s = userdata;
643
644     pa_assert(conn);
645     pa_assert(msg);
646     pa_assert(s);
647
648     if (s->type == STREAM_TYPE_PLAYBACK)
649         pa_sink_input_kill(s->sink_input);
650     else
651         pa_source_output_kill(s->source_output);
652
653     pa_dbus_send_empty_reply(conn, msg);
654 }
655
656 static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
657     pa_dbusiface_stream *s = userdata;
658     DBusMessage *signal_msg = NULL;
659     const char *new_device_path = NULL;
660     uint32_t new_sample_rate = 0;
661     pa_proplist *new_proplist = NULL;
662     unsigned i = 0;
663
664     pa_assert(c);
665     pa_assert(s);
666
667     if ((s->type == STREAM_TYPE_PLAYBACK && idx != s->sink_input->index)
668         || (s->type == STREAM_TYPE_RECORD && idx != s->source_output->index))
669         return;
670
671     if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
672         return;
673
674     pa_assert(((s->type == STREAM_TYPE_PLAYBACK)
675                 && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT))
676               || ((s->type == STREAM_TYPE_RECORD)
677                    && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT)));
678
679     if (s->type == STREAM_TYPE_PLAYBACK) {
680         pa_sink *new_sink = s->sink_input->sink;
681
682         if (s->sink != new_sink) {
683             pa_sink_unref(s->sink);
684             s->sink = pa_sink_ref(new_sink);
685
686             new_device_path = pa_dbusiface_core_get_sink_path(s->core, new_sink);
687
688             pa_assert_se(signal_msg = 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_msg, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
692
693             pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
694             dbus_message_unref(signal_msg);
695             signal_msg = NULL;
696         }
697     } else {
698         pa_source *new_source = s->source_output->source;
699
700         if (s->source != new_source) {
701             pa_source_unref(s->source);
702             s->source = pa_source_ref(new_source);
703
704             new_device_path = pa_dbusiface_core_get_source_path(s->core, new_source);
705
706             pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
707                                                               PA_DBUSIFACE_STREAM_INTERFACE,
708                                                               signals[SIGNAL_DEVICE_UPDATED].name));
709             pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
710
711             pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
712             dbus_message_unref(signal_msg);
713             signal_msg = NULL;
714         }
715     }
716
717     new_sample_rate = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->sample_spec.rate : s->source_output->sample_spec.rate;
718
719     if (s->sample_rate != new_sample_rate) {
720         s->sample_rate = new_sample_rate;
721
722         pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
723                                                           PA_DBUSIFACE_STREAM_INTERFACE,
724                                                           signals[SIGNAL_SAMPLE_RATE_UPDATED].name));
725         pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID));
726
727         pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
728         dbus_message_unref(signal_msg);
729         signal_msg = NULL;
730     }
731
732     if (s->type == STREAM_TYPE_PLAYBACK) {
733         pa_bool_t new_mute = FALSE;
734
735         if (s->has_volume) {
736             pa_cvolume new_volume;
737
738             pa_sink_input_get_volume(s->sink_input, &new_volume, TRUE);
739
740             if (!pa_cvolume_equal(&s->volume, &new_volume)) {
741                 dbus_uint32_t volume[PA_CHANNELS_MAX];
742                 dbus_uint32_t *volume_ptr = volume;
743
744                 s->volume = new_volume;
745
746                 for (i = 0; i < s->volume.channels; ++i)
747                     volume[i] = s->volume.values[i];
748
749                 pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
750                                                                   PA_DBUSIFACE_STREAM_INTERFACE,
751                                                                   signals[SIGNAL_VOLUME_UPDATED].name));
752                 pa_assert_se(dbus_message_append_args(signal_msg,
753                                                       DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels,
754                                                       DBUS_TYPE_INVALID));
755
756                 pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
757                 dbus_message_unref(signal_msg);
758                 signal_msg = NULL;
759             }
760         }
761
762         new_mute = pa_sink_input_get_mute(s->sink_input);
763
764         if (s->mute != new_mute) {
765             s->mute = new_mute;
766
767             pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
768                                                               PA_DBUSIFACE_STREAM_INTERFACE,
769                                                               signals[SIGNAL_MUTE_UPDATED].name));
770             pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &s->mute, DBUS_TYPE_INVALID));
771
772             pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
773             dbus_message_unref(signal_msg);
774             signal_msg = NULL;
775         }
776     }
777
778     new_proplist = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->proplist : s->source_output->proplist;
779
780     if (!pa_proplist_equal(s->proplist, new_proplist)) {
781         DBusMessageIter msg_iter;
782
783         pa_proplist_update(s->proplist, PA_UPDATE_SET, new_proplist);
784
785         pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
786                                                           PA_DBUSIFACE_STREAM_INTERFACE,
787                                                           signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
788         dbus_message_iter_init_append(signal_msg, &msg_iter);
789         pa_dbus_append_proplist(&msg_iter, s->proplist);
790
791         pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
792         dbus_message_unref(signal_msg);
793         signal_msg = NULL;
794     }
795 }
796
797 static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *slot_data) {
798     pa_dbusiface_stream *s = slot_data;
799     DBusMessage *signal_msg = NULL;
800     DBusMessageIter msg_iter;
801     const char *name = NULL;
802     pa_proplist *property_list = NULL;
803
804     pa_assert(call_data);
805     pa_assert(s);
806
807     if (s->type == STREAM_TYPE_PLAYBACK) {
808         pa_sink_input_send_event_hook_data *data = call_data;
809
810         if (data->sink_input != s->sink_input)
811             return PA_HOOK_OK;
812
813         name = data->event;
814         property_list = data->data;
815     } else {
816         pa_source_output_send_event_hook_data *data = call_data;
817
818         if (data->source_output != s->source_output)
819             return PA_HOOK_OK;
820
821         name = data->event;
822         property_list = data->data;
823     }
824
825     pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
826                                                       PA_DBUSIFACE_STREAM_INTERFACE,
827                                                       signals[SIGNAL_STREAM_EVENT].name));
828     dbus_message_iter_init_append(signal_msg, &msg_iter);
829     pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name));
830     pa_dbus_append_proplist(&msg_iter, property_list);
831
832     pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
833     dbus_message_unref(signal_msg);
834
835     return PA_HOOK_OK;
836 }
837
838 pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, pa_sink_input *sink_input) {
839     pa_dbusiface_stream *s;
840
841     pa_assert(core);
842     pa_assert(sink_input);
843
844     s = pa_xnew(pa_dbusiface_stream, 1);
845     s->core = core;
846     s->sink_input = pa_sink_input_ref(sink_input);
847     s->type = STREAM_TYPE_PLAYBACK;
848     s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, PLAYBACK_OBJECT_NAME, sink_input->index);
849     s->sink = pa_sink_ref(sink_input->sink);
850     s->sample_rate = sink_input->sample_spec.rate;
851     s->has_volume = pa_sink_input_is_volume_readable(sink_input);
852     s->read_only_volume = s->has_volume ? !pa_sink_input_is_volume_writable(sink_input) : FALSE;
853
854     if (s->has_volume)
855         pa_sink_input_get_volume(sink_input, &s->volume, TRUE);
856     else
857         pa_cvolume_init(&s->volume);
858
859     s->mute = pa_sink_input_get_mute(sink_input);
860     s->proplist = pa_proplist_copy(sink_input->proplist);
861     s->dbus_protocol = pa_dbus_protocol_get(sink_input->core);
862     s->subscription = pa_subscription_new(sink_input->core, PA_SUBSCRIPTION_MASK_SINK_INPUT, subscription_cb, s);
863     s->send_event_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_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 pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_source_output *source_output) {
874     pa_dbusiface_stream *s;
875
876     pa_assert(core);
877     pa_assert(source_output);
878
879     s = pa_xnew(pa_dbusiface_stream, 1);
880     s->core = core;
881     s->source_output = pa_source_output_ref(source_output);
882     s->type = STREAM_TYPE_RECORD;
883     s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, RECORD_OBJECT_NAME, source_output->index);
884     s->source = pa_source_ref(source_output->source);
885     s->sample_rate = source_output->sample_spec.rate;
886     pa_cvolume_init(&s->volume);
887     s->mute = FALSE;
888     s->proplist = pa_proplist_copy(source_output->proplist);
889     s->has_volume = FALSE;
890     s->read_only_volume = FALSE;
891     s->dbus_protocol = pa_dbus_protocol_get(source_output->core);
892     s->subscription = pa_subscription_new(source_output->core, PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscription_cb, s);
893     s->send_event_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT],
894                                          PA_HOOK_NORMAL,
895                                          send_event_cb,
896                                          s);
897
898     pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0);
899
900     return s;
901 }
902
903 void pa_dbusiface_stream_free(pa_dbusiface_stream *s) {
904     pa_assert(s);
905
906     pa_assert_se(pa_dbus_protocol_remove_interface(s->dbus_protocol, s->path, stream_interface_info.name) >= 0);
907
908     if (s->type == STREAM_TYPE_PLAYBACK) {
909         pa_sink_input_unref(s->sink_input);
910         pa_sink_unref(s->sink);
911     } else {
912         pa_source_output_unref(s->source_output);
913         pa_source_unref(s->source);
914     }
915
916     pa_proplist_free(s->proplist);
917     pa_dbus_protocol_unref(s->dbus_protocol);
918     pa_subscription_free(s->subscription);
919     pa_hook_slot_free(s->send_event_slot);
920
921     pa_xfree(s->path);
922     pa_xfree(s);
923 }
924
925 const char *pa_dbusiface_stream_get_path(pa_dbusiface_stream *s) {
926     pa_assert(s);
927
928     return s->path;
929 }