]> code.delx.au - pulseaudio/blob - src/modules/module-stream-restore.c
stream-restore: Expose module to D-Bus.
[pulseaudio] / src / modules / module-stream-restore.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2008 Lennart Poettering
5 Copyright 2009 Tanu Kaskinen
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 <unistd.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34
35 #include <pulse/xmalloc.h>
36 #include <pulse/volume.h>
37 #include <pulse/timeval.h>
38 #include <pulse/util.h>
39 #include <pulse/rtclock.h>
40
41 #include <pulsecore/core-error.h>
42 #include <pulsecore/module.h>
43 #include <pulsecore/core-util.h>
44 #include <pulsecore/modargs.h>
45 #include <pulsecore/log.h>
46 #include <pulsecore/core-subscribe.h>
47 #include <pulsecore/sink-input.h>
48 #include <pulsecore/source-output.h>
49 #include <pulsecore/namereg.h>
50 #include <pulsecore/protocol-native.h>
51 #include <pulsecore/pstream.h>
52 #include <pulsecore/pstream-util.h>
53 #include <pulsecore/database.h>
54
55 #ifdef HAVE_DBUS
56 #include <pulsecore/dbus-util.h>
57 #include <pulsecore/protocol-dbus.h>
58 #endif
59
60 #include "module-stream-restore-symdef.h"
61
62 PA_MODULE_AUTHOR("Lennart Poettering");
63 PA_MODULE_DESCRIPTION("Automatically restore the volume/mute/device state of streams");
64 PA_MODULE_VERSION(PACKAGE_VERSION);
65 PA_MODULE_LOAD_ONCE(TRUE);
66 PA_MODULE_USAGE(
67 "restore_device=<Save/restore sinks/sources?> "
68 "restore_volume=<Save/restore volumes?> "
69 "restore_muted=<Save/restore muted states?> "
70 "on_hotplug=<When new device becomes available, recheck streams?> "
71 "on_rescue=<When device becomes unavailable, recheck streams?>");
72
73 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
74 #define IDENTIFICATION_PROPERTY "module-stream-restore.id"
75
76 static const char* const valid_modargs[] = {
77 "restore_device",
78 "restore_volume",
79 "restore_muted",
80 "on_hotplug",
81 "on_rescue",
82 NULL
83 };
84
85 struct userdata {
86 pa_core *core;
87 pa_module *module;
88 pa_subscription *subscription;
89 pa_hook_slot
90 *sink_input_new_hook_slot,
91 *sink_input_fixate_hook_slot,
92 *source_output_new_hook_slot,
93 *sink_put_hook_slot,
94 *source_put_hook_slot,
95 *sink_unlink_hook_slot,
96 *source_unlink_hook_slot,
97 *connection_unlink_hook_slot;
98 pa_time_event *save_time_event;
99 pa_database* database;
100
101 pa_bool_t restore_device:1;
102 pa_bool_t restore_volume:1;
103 pa_bool_t restore_muted:1;
104 pa_bool_t on_hotplug:1;
105 pa_bool_t on_rescue:1;
106
107 pa_native_protocol *protocol;
108 pa_idxset *subscribed;
109
110 #ifdef HAVE_DBUS
111 pa_dbus_protocol *dbus_protocol;
112 pa_hashmap *dbus_entries;
113 uint32_t next_index; /* For generating object paths for entries. */
114 #endif
115 };
116
117 #define ENTRY_VERSION 2
118
119 struct entry {
120 uint8_t version;
121 pa_bool_t muted_valid:1, volume_valid:1, device_valid:1;
122 pa_bool_t muted:1;
123 pa_channel_map channel_map;
124 pa_cvolume volume;
125 char device[PA_NAME_MAX];
126 } PA_GCC_PACKED;
127
128 enum {
129 SUBCOMMAND_TEST,
130 SUBCOMMAND_READ,
131 SUBCOMMAND_WRITE,
132 SUBCOMMAND_DELETE,
133 SUBCOMMAND_SUBSCRIBE,
134 SUBCOMMAND_EVENT
135 };
136
137 static struct entry *read_entry(struct userdata *u, const char *name);
138 static void apply_entry(struct userdata *u, const char *name, struct entry *e);
139 static void trigger_save(struct userdata *u);
140
141 #ifdef HAVE_DBUS
142
143 #define OBJECT_PATH "/org/pulseaudio/stream_restore1"
144 #define ENTRY_OBJECT_NAME "entry"
145 #define INTERFACE_STREAM_RESTORE "org.PulseAudio.Ext.StreamRestore1"
146 #define INTERFACE_ENTRY INTERFACE_STREAM_RESTORE ".RestoreEntry"
147
148 #define DBUS_INTERFACE_REVISION 0
149
150 struct dbus_entry {
151 struct userdata *userdata;
152
153 char *entry_name;
154 uint32_t index;
155 char *object_path;
156 };
157
158 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata);
159 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata);
160
161 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
162
163 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata);
164 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
165
166 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata);
167 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
168 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
169 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
170 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
171 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
172 static void handle_entry_get_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata);
173 static void handle_entry_set_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata);
174
175 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
176
177 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata);
178
179 enum property_handler_index {
180 PROPERTY_HANDLER_INTERFACE_REVISION,
181 PROPERTY_HANDLER_ENTRIES,
182 PROPERTY_HANDLER_MAX
183 };
184
185 enum entry_property_handler_index {
186 ENTRY_PROPERTY_HANDLER_INDEX,
187 ENTRY_PROPERTY_HANDLER_NAME,
188 ENTRY_PROPERTY_HANDLER_DEVICE,
189 ENTRY_PROPERTY_HANDLER_VOLUME,
190 ENTRY_PROPERTY_HANDLER_IS_MUTED,
191 ENTRY_PROPERTY_HANDLER_MAX
192 };
193
194 static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = {
195 [PROPERTY_HANDLER_INTERFACE_REVISION] = { .property_name = "InterfaceRevision", .type = "u", .get_cb = handle_get_interface_revision, .set_cb = NULL },
196 [PROPERTY_HANDLER_ENTRIES] = { .property_name = "Entries", .type = "ao", .get_cb = handle_get_entries, .set_cb = NULL }
197 };
198
199 static pa_dbus_property_handler entry_property_handlers[ENTRY_PROPERTY_HANDLER_MAX] = {
200 [ENTRY_PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_entry_get_index, .set_cb = NULL },
201 [ENTRY_PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_entry_get_name, .set_cb = NULL },
202 [ENTRY_PROPERTY_HANDLER_DEVICE] = { .property_name = "Device", .type = "s", .get_cb = handle_entry_get_device, .set_cb = handle_entry_set_device },
203 [ENTRY_PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "a(uu)", .get_cb = handle_entry_get_volume, .set_cb = handle_entry_set_volume },
204 [ENTRY_PROPERTY_HANDLER_IS_MUTED] = { .property_name = "IsMuted", .type = "b", .get_cb = handle_entry_get_is_muted, .set_cb = handle_entry_set_is_muted }
205 };
206
207 enum method_handler_index {
208 METHOD_HANDLER_ADD_ENTRY,
209 METHOD_HANDLER_GET_ENTRY_BY_NAME,
210 METHOD_HANDLER_MAX
211 };
212
213 enum entry_method_handler_index {
214 ENTRY_METHOD_HANDLER_REMOVE,
215 ENTRY_METHOD_HANDLER_MAX
216 };
217
218 static pa_dbus_arg_info add_entry_args[] = { { "name", "s", "in" },
219 { "device", "s", "in" },
220 { "volume", "a(uu)", "in" },
221 { "is_muted", "b", "in" },
222 { "entry", "o", "out" } };
223 static pa_dbus_arg_info get_entry_by_name_args[] = { { "name", "s", "in" }, { "entry", "o", "out" } };
224
225 static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
226 [METHOD_HANDLER_ADD_ENTRY] = {
227 .method_name = "AddEntry",
228 .arguments = add_entry_args,
229 .n_arguments = sizeof(add_entry_args) / sizeof(pa_dbus_arg_info),
230 .receive_cb = handle_add_entry },
231 [METHOD_HANDLER_GET_ENTRY_BY_NAME] = {
232 .method_name = "GetEntryByName",
233 .arguments = get_entry_by_name_args,
234 .n_arguments = sizeof(get_entry_by_name_args) / sizeof(pa_dbus_arg_info),
235 .receive_cb = handle_get_entry_by_name }
236 };
237
238 static pa_dbus_method_handler entry_method_handlers[ENTRY_METHOD_HANDLER_MAX] = {
239 [ENTRY_METHOD_HANDLER_REMOVE] = {
240 .method_name = "Remove",
241 .arguments = NULL,
242 .n_arguments = 0,
243 .receive_cb = handle_entry_remove }
244 };
245
246 enum signal_index {
247 SIGNAL_NEW_ENTRY,
248 SIGNAL_ENTRY_REMOVED,
249 SIGNAL_MAX
250 };
251
252 enum entry_signal_index {
253 ENTRY_SIGNAL_DEVICE_UPDATED,
254 ENTRY_SIGNAL_VOLUME_UPDATED,
255 ENTRY_SIGNAL_MUTE_UPDATED,
256 ENTRY_SIGNAL_MAX
257 };
258
259 static pa_dbus_arg_info new_entry_args[] = { { "entry", "o", NULL } };
260 static pa_dbus_arg_info entry_removed_args[] = { { "entry", "o", NULL } };
261
262 static pa_dbus_arg_info entry_device_updated_args[] = { { "device", "s", NULL } };
263 static pa_dbus_arg_info entry_volume_updated_args[] = { { "volume", "a(uu)", NULL } };
264 static pa_dbus_arg_info entry_mute_updated_args[] = { { "muted", "b", NULL } };
265
266 static pa_dbus_signal_info signals[SIGNAL_MAX] = {
267 [SIGNAL_NEW_ENTRY] = { .name = "NewEntry", .arguments = new_entry_args, .n_arguments = 1 },
268 [SIGNAL_ENTRY_REMOVED] = { .name = "EntryRemoved", .arguments = entry_removed_args, .n_arguments = 1 }
269 };
270
271 static pa_dbus_signal_info entry_signals[ENTRY_SIGNAL_MAX] = {
272 [ENTRY_SIGNAL_DEVICE_UPDATED] = { .name = "DeviceUpdated", .arguments = entry_device_updated_args, .n_arguments = 1 },
273 [ENTRY_SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = entry_volume_updated_args, .n_arguments = 1 },
274 [ENTRY_SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = entry_mute_updated_args, .n_arguments = 1 }
275 };
276
277 static pa_dbus_interface_info stream_restore_interface_info = {
278 .name = INTERFACE_STREAM_RESTORE,
279 .method_handlers = method_handlers,
280 .n_method_handlers = METHOD_HANDLER_MAX,
281 .property_handlers = property_handlers,
282 .n_property_handlers = PROPERTY_HANDLER_MAX,
283 .get_all_properties_cb = handle_get_all,
284 .signals = signals,
285 .n_signals = SIGNAL_MAX
286 };
287
288 static pa_dbus_interface_info entry_interface_info = {
289 .name = INTERFACE_ENTRY,
290 .method_handlers = entry_method_handlers,
291 .n_method_handlers = ENTRY_METHOD_HANDLER_MAX,
292 .property_handlers = entry_property_handlers,
293 .n_property_handlers = ENTRY_PROPERTY_HANDLER_MAX,
294 .get_all_properties_cb = handle_entry_get_all,
295 .signals = entry_signals,
296 .n_signals = ENTRY_SIGNAL_MAX
297 };
298
299 static struct dbus_entry *dbus_entry_new(struct userdata *u, const char *entry_name) {
300 struct dbus_entry *de;
301
302 pa_assert(u);
303 pa_assert(entry_name);
304 pa_assert(*entry_name);
305
306 de = pa_xnew(struct dbus_entry, 1);
307 de->userdata = u;
308 de->entry_name = pa_xstrdup(entry_name);
309 de->index = u->next_index++;
310 de->object_path = pa_sprintf_malloc("%s/%s%u", OBJECT_PATH, ENTRY_OBJECT_NAME, de->index);
311
312 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, de->object_path, &entry_interface_info, u) >= 0);
313
314 return de;
315 }
316
317 static void dbus_entry_free(struct dbus_entry *de) {
318 pa_assert(de);
319
320 pa_assert_se(pa_dbus_protocol_remove_interface(de->userdata->dbus_protocol, de->object_path, entry_interface_info.name) >= 0);
321
322 pa_xfree(de->entry_name);
323 pa_xfree(de->object_path);
324 }
325
326 /* Reads an array [(UInt32, UInt32)] from the iterator. The struct items are
327 * are a channel position and a volume value, respectively. The result is
328 * stored in the map and vol arguments. If the volume can't be read from the
329 * iterator, an error reply is sent and a negative number is returned. In case
330 * of a failure we make no guarantees about the state of map and vol. In case
331 * of an empty array the channels field of both map and vol are set to 0. */
332 static int get_volume_arg(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, pa_channel_map *map, pa_cvolume *vol) {
333 DBusMessageIter array_iter;
334 DBusMessageIter struct_iter;
335 int arg_type;
336
337 pa_assert(conn);
338 pa_assert(msg);
339 pa_assert(iter);
340 pa_assert(map);
341 pa_assert(vol);
342
343 pa_channel_map_init(map);
344 pa_cvolume_init(vol);
345
346 map->channels = 0;
347 vol->channels = 0;
348
349 arg_type = dbus_message_iter_get_arg_type(iter);
350 if (arg_type != DBUS_TYPE_ARRAY) {
351 if (arg_type == DBUS_TYPE_INVALID)
352 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments. An array was expected.");
353 else
354 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Wrong argument type: '%c'. An array was expected.", (char) arg_type);
355 return -1;
356 }
357
358 arg_type = dbus_message_iter_get_element_type(iter);
359 if (arg_type != DBUS_TYPE_STRUCT) {
360 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Wrong array element type: '%c'. A struct was expected.", (char) arg_type);
361 return -1;
362 }
363
364 dbus_message_iter_recurse(iter, &array_iter);
365
366 while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
367 dbus_uint32_t chan_pos;
368 dbus_uint32_t chan_vol;
369
370 dbus_message_iter_recurse(&array_iter, &struct_iter);
371
372 arg_type = dbus_message_iter_get_arg_type(&struct_iter);
373 if (arg_type != DBUS_TYPE_UINT32) {
374 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Wrong channel position type: '%c'. An unsigned 32-bit integer was expected.", (char) arg_type);
375 return -1;
376 }
377
378 dbus_message_iter_get_basic(&struct_iter, &chan_pos);
379 dbus_message_iter_next(&struct_iter);
380
381 if (chan_pos >= PA_CHANNEL_POSITION_MAX) {
382 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position: %u", chan_pos);
383 return -1;
384 }
385
386 arg_type = dbus_message_iter_get_arg_type(&struct_iter);
387 if (arg_type != DBUS_TYPE_UINT32) {
388 if (arg_type == DBUS_TYPE_INVALID)
389 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Channel volume missing.");
390 else
391 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Wrong volume value type: '%c'. An unsigned 32-bit integer was expected.", (char) arg_type);
392 return -1;
393 }
394
395 dbus_message_iter_get_basic(&struct_iter, &chan_vol);
396
397 if (chan_vol > PA_VOLUME_MAX) {
398 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u", chan_vol);
399 return -1;
400 }
401
402 if (map->channels < PA_CHANNELS_MAX) {
403 map->map[map->channels] = chan_pos;
404 vol->values[map->channels] = chan_vol;
405 }
406 ++map->channels;
407 ++vol->channels;
408
409 dbus_message_iter_next(&array_iter);
410 }
411
412 if (map->channels > PA_CHANNELS_MAX) {
413 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too many channels: %u. The maximum is %u.", map->channels, PA_CHANNELS_MAX);
414 return -1;
415 }
416
417 dbus_message_iter_next(iter);
418
419 return 0;
420 }
421
422 static void append_volume(DBusMessageIter *iter, struct entry *e) {
423 DBusMessageIter array_iter;
424 DBusMessageIter struct_iter;
425 unsigned i;
426
427 pa_assert(iter);
428 pa_assert(e);
429
430 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(uu)", &array_iter));
431
432 if (!e->volume_valid) {
433 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
434 return;
435 }
436
437 for (i = 0; i < e->channel_map.channels; ++i) {
438 pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter));
439
440 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->channel_map.map[i]));
441 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->volume.values[i]));
442
443 pa_assert_se(dbus_message_iter_close_container(&array_iter, &struct_iter));
444 }
445
446 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
447 }
448
449 static void append_volume_variant(DBusMessageIter *iter, struct entry *e) {
450 DBusMessageIter variant_iter;
451
452 pa_assert(iter);
453 pa_assert(e);
454
455 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(uu)", &variant_iter));
456
457 append_volume(&variant_iter, e);
458
459 pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter));
460 }
461
462 static void send_new_entry_signal(struct dbus_entry *entry) {
463 DBusMessage *signal;
464
465 pa_assert(entry);
466
467 pa_assert_se(signal = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name));
468 pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
469 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal);
470 dbus_message_unref(signal);
471 }
472
473 static void send_entry_removed_signal(struct dbus_entry *entry) {
474 DBusMessage *signal;
475
476 pa_assert(entry);
477
478 pa_assert_se(signal = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name));
479 pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
480 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal);
481 dbus_message_unref(signal);
482 }
483
484 static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) {
485 DBusMessage *signal;
486 const char *device;
487
488 pa_assert(de);
489 pa_assert(e);
490
491 device = e->device_valid ? e->device : "";
492
493 pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name));
494 pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID));
495 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal);
496 dbus_message_unref(signal);
497 }
498
499 static void send_volume_updated_signal(struct dbus_entry *de, struct entry *e) {
500 DBusMessage *signal;
501 DBusMessageIter msg_iter;
502
503 pa_assert(de);
504 pa_assert(e);
505
506 pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name));
507 dbus_message_iter_init_append(signal, &msg_iter);
508 append_volume(&msg_iter, e);
509 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal);
510 dbus_message_unref(signal);
511 }
512
513 static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) {
514 DBusMessage *signal;
515 dbus_bool_t muted;
516
517 pa_assert(de);
518 pa_assert(e);
519
520 pa_assert(e->muted_valid);
521
522 muted = e->muted;
523
524 pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name));
525 pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID));
526 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal);
527 dbus_message_unref(signal);
528 }
529
530 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) {
531 dbus_uint32_t interface_revision = DBUS_INTERFACE_REVISION;
532
533 pa_assert(conn);
534 pa_assert(msg);
535
536 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &interface_revision);
537 }
538
539 /* The caller frees the array, but not the strings. */
540 static const char **get_entries(struct userdata *u, unsigned *n) {
541 const char **entries;
542 unsigned i = 0;
543 void *state = NULL;
544 struct dbus_entry *de;
545
546 pa_assert(u);
547 pa_assert(n);
548
549 *n = pa_hashmap_size(u->dbus_entries);
550
551 if (*n == 0)
552 return NULL;
553
554 entries = pa_xnew(const char *, *n);
555
556 while ((de = pa_hashmap_iterate(u->dbus_entries, &state, NULL))) {
557 entries[i] = de->object_path;
558 ++i;
559 }
560
561 return entries;
562 }
563
564 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata) {
565 struct userdata *u = userdata;
566 const char **entries;
567 unsigned n;
568
569 pa_assert(conn);
570 pa_assert(msg);
571 pa_assert(u);
572
573 entries = get_entries(u, &n);
574
575 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, entries, n);
576
577 pa_xfree(entries);
578 }
579
580 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
581 struct userdata *u = userdata;
582 DBusMessage *reply = NULL;
583 DBusMessageIter msg_iter;
584 DBusMessageIter dict_iter;
585 dbus_uint32_t interface_revision;
586 const char **entries;
587 unsigned n_entries;
588
589 pa_assert(conn);
590 pa_assert(msg);
591 pa_assert(u);
592
593 interface_revision = DBUS_INTERFACE_REVISION;
594 entries = get_entries(u, &n_entries);
595
596 pa_assert_se((reply = dbus_message_new_method_return(msg)));
597
598 dbus_message_iter_init_append(reply, &msg_iter);
599 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
600
601 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INTERFACE_REVISION].property_name, DBUS_TYPE_UINT32, &interface_revision);
602 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ENTRIES].property_name, DBUS_TYPE_OBJECT_PATH, entries, n_entries);
603
604 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
605
606 pa_assert_se(dbus_connection_send(conn, reply, NULL));
607
608 dbus_message_unref(reply);
609
610 pa_xfree(entries);
611 }
612
613 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata) {
614 struct userdata *u = userdata;
615 DBusMessageIter msg_iter;
616 const char *name;
617 const char *device;
618 pa_channel_map map;
619 pa_cvolume vol;
620 dbus_bool_t muted;
621 dbus_bool_t apply_immediately;
622 pa_datum key;
623 pa_datum value;
624 struct dbus_entry *dbus_entry;
625 struct entry *e;
626
627 pa_assert(conn);
628 pa_assert(msg);
629 pa_assert(u);
630
631 if (!dbus_message_iter_init(msg, &msg_iter)) {
632 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments.");
633 return;
634 }
635
636 if (pa_dbus_get_basic_arg(conn, msg, &msg_iter, DBUS_TYPE_STRING, &name) < 0)
637 return;
638
639 if (pa_dbus_get_basic_arg(conn, msg, &msg_iter, DBUS_TYPE_STRING, &device) < 0)
640 return;
641
642 if (get_volume_arg(conn, msg, &msg_iter, &map, &vol) < 0)
643 return;
644
645 if (pa_dbus_get_basic_arg(conn, msg, &msg_iter, DBUS_TYPE_BOOLEAN, &muted) < 0)
646 return;
647
648 if (pa_dbus_get_basic_arg(conn, msg, &msg_iter, DBUS_TYPE_BOOLEAN, &apply_immediately) < 0)
649 return;
650
651 if (!*name) {
652 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "An empty string was given as the entry name.");
653 return;
654 }
655
656 if ((dbus_entry = pa_hashmap_get(u->dbus_entries, name))) {
657 pa_bool_t mute_updated = FALSE;
658 pa_bool_t volume_updated = FALSE;
659 pa_bool_t device_updated = FALSE;
660
661 pa_assert_se(e = read_entry(u, name));
662 mute_updated = e->muted != muted;
663 e->muted = muted;
664 e->muted_valid = TRUE;
665
666 volume_updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
667 e->volume = vol;
668 e->channel_map = map;
669 e->volume_valid = !!map.channels;
670
671 device_updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
672 pa_strlcpy(e->device, device, sizeof(e->device));
673 e->device_valid = !!device[0];
674
675 if (mute_updated)
676 send_mute_updated_signal(dbus_entry, e);
677 if (volume_updated)
678 send_volume_updated_signal(dbus_entry, e);
679 if (device_updated)
680 send_device_updated_signal(dbus_entry, e);
681
682 } else {
683 dbus_entry = dbus_entry_new(u, name);
684 pa_assert(pa_hashmap_put(u->dbus_entries, dbus_entry->entry_name, dbus_entry) >= 0);
685
686 e->muted_valid = TRUE;
687 e->volume_valid = !!map.channels;
688 e->device_valid = !!device[0];
689 e->muted = muted;
690 e->volume = vol;
691 e->channel_map = map;
692 pa_strlcpy(e->device, device, sizeof(e->device));
693
694 send_new_entry_signal(dbus_entry);
695 }
696
697 key.data = (char *) name;
698 key.size = strlen(name);
699
700 value.data = e;
701 value.size = sizeof(struct entry);
702
703 pa_assert_se(pa_database_set(u->database, &key, &value, TRUE) == 0);
704 if (apply_immediately)
705 apply_entry(u, name, e);
706
707 trigger_save(u);
708
709 pa_dbus_send_empty_reply(conn, msg);
710
711 pa_xfree(e);
712 }
713
714 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
715 struct userdata *u = userdata;
716 const char *name;
717 struct dbus_entry *de;
718 DBusError error;
719
720 pa_assert(conn);
721 pa_assert(msg);
722 pa_assert(u);
723
724 dbus_error_init(&error);
725
726 if (!dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
727 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
728 dbus_error_free(&error);
729 return;
730 }
731
732 if (!(de = pa_hashmap_get(u->dbus_entries, name))) {
733 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such stream restore entry.");
734 return;
735 }
736
737 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &de->object_path);
738 }
739
740 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) {
741 struct dbus_entry *de = userdata;
742
743 pa_assert(conn);
744 pa_assert(msg);
745 pa_assert(de);
746
747 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &de->index);
748 }
749
750 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
751 struct dbus_entry *de = userdata;
752
753 pa_assert(conn);
754 pa_assert(msg);
755 pa_assert(de);
756
757 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &de->entry_name);
758 }
759
760 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
761 struct dbus_entry *de = userdata;
762 struct entry *e;
763 const char *device;
764
765 pa_assert(conn);
766 pa_assert(msg);
767 pa_assert(de);
768
769 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
770
771 device = e->device_valid ? e->device : "";
772
773 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &device);
774
775 pa_xfree(e);
776 }
777
778 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
779 struct dbus_entry *de = userdata;
780 const char *device;
781 struct entry *e;
782 pa_bool_t updated;
783
784 pa_assert(conn);
785 pa_assert(msg);
786 pa_assert(de);
787
788 if (pa_dbus_get_basic_set_property_arg(conn, msg, DBUS_TYPE_STRING, &device) < 0)
789 return;
790
791 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
792
793 updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
794
795 if (updated) {
796 pa_datum key;
797 pa_datum value;
798
799 pa_strlcpy(e->device, device, sizeof(e->device));
800 e->device_valid = !!device[0];
801
802 key.data = de->entry_name;
803 key.size = strlen(de->entry_name);
804 value.data = e;
805 value.size = sizeof(struct entry);
806 pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
807
808 send_device_updated_signal(de, e);
809 trigger_save(de->userdata);
810 }
811
812 pa_dbus_send_empty_reply(conn, msg);
813
814 pa_xfree(e);
815 }
816
817 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
818 struct dbus_entry *de = userdata;
819 DBusMessage *reply;
820 DBusMessageIter msg_iter;
821 struct entry *e;
822
823 pa_assert(conn);
824 pa_assert(msg);
825 pa_assert(de);
826
827 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
828
829 pa_assert_se(reply = dbus_message_new_method_return(msg));
830
831 dbus_message_iter_init_append(reply, &msg_iter);
832 append_volume_variant(&msg_iter, e);
833
834 pa_assert_se(dbus_connection_send(conn, reply, NULL));
835
836 pa_xfree(e);
837 }
838
839 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
840 struct dbus_entry *de = userdata;
841 DBusMessageIter msg_iter;
842 pa_channel_map map;
843 pa_cvolume vol;
844 struct entry *e;
845 pa_bool_t updated;
846
847 pa_assert(conn);
848 pa_assert(msg);
849 pa_assert(de);
850
851 /* Skip the interface and property name arguments. */
852 if (!dbus_message_iter_init(msg, &msg_iter) || !dbus_message_iter_next(&msg_iter) || !dbus_message_iter_next(&msg_iter)) {
853 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments.");
854 return;
855 }
856
857 if (get_volume_arg(conn, msg, &msg_iter, &map, &vol) < 0)
858 return;
859
860 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
861
862 updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
863
864 if (updated) {
865 pa_datum key;
866 pa_datum value;
867
868 e->volume = vol;
869 e->channel_map = map;
870 e->volume_valid = !!map.channels;
871
872 key.data = de->entry_name;
873 key.size = strlen(de->entry_name);
874 value.data = e;
875 value.size = sizeof(struct entry);
876 pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
877
878 send_volume_updated_signal(de, e);
879 trigger_save(de->userdata);
880 }
881
882 pa_dbus_send_empty_reply(conn, msg);
883
884 pa_xfree(e);
885 }
886
887 static void handle_entry_get_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata) {
888 struct dbus_entry *de = userdata;
889 struct entry *e;
890 dbus_bool_t muted;
891
892 pa_assert(conn);
893 pa_assert(msg);
894 pa_assert(de);
895
896 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
897
898 muted = e->muted_valid ? e->muted : FALSE;
899
900 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &muted);
901
902 pa_xfree(e);
903 }
904
905 static void handle_entry_set_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata) {
906 struct dbus_entry *de = userdata;
907 pa_bool_t muted;
908 struct entry *e;
909 pa_bool_t updated;
910
911 pa_assert(conn);
912 pa_assert(msg);
913 pa_assert(de);
914
915 if (pa_dbus_get_basic_set_property_arg(conn, msg, DBUS_TYPE_BOOLEAN, &muted) < 0)
916 return;
917
918 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
919
920 updated = !e->muted_valid || e->muted != muted;
921
922 if (updated) {
923 pa_datum key;
924 pa_datum value;
925
926 e->muted = muted;
927 e->muted_valid = TRUE;
928
929 key.data = de->entry_name;
930 key.size = strlen(de->entry_name);
931 value.data = e;
932 value.size = sizeof(struct entry);
933 pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
934
935 send_mute_updated_signal(de, e);
936 trigger_save(de->userdata);
937 }
938
939 pa_dbus_send_empty_reply(conn, msg);
940
941 pa_xfree(e);
942 }
943
944 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
945 struct dbus_entry *de = userdata;
946 struct entry *e;
947 DBusMessage *reply = NULL;
948 DBusMessageIter msg_iter;
949 DBusMessageIter dict_iter;
950 DBusMessageIter dict_entry_iter;
951 const char *device;
952 dbus_bool_t muted;
953
954 pa_assert(conn);
955 pa_assert(msg);
956 pa_assert(de);
957
958 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
959
960 device = e->device_valid ? e->device : "";
961 muted = e->muted_valid ? e->muted : FALSE;
962
963 pa_assert_se((reply = dbus_message_new_method_return(msg)));
964
965 dbus_message_iter_init_append(reply, &msg_iter);
966 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
967
968 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &de->index);
969 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &de->entry_name);
970 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_STRING, &device);
971
972 pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter));
973
974 pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &entry_property_handlers[ENTRY_PROPERTY_HANDLER_VOLUME].property_name));
975 append_volume_variant(&dict_entry_iter, e);
976
977 pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter));
978
979 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_IS_MUTED].property_name, DBUS_TYPE_BOOLEAN, &muted);
980
981 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
982
983 pa_assert_se(dbus_connection_send(conn, reply, NULL));
984
985 dbus_message_unref(reply);
986
987 pa_xfree(e);
988 }
989
990 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata) {
991 struct dbus_entry *de = userdata;
992 pa_datum key;
993
994 pa_assert(conn);
995 pa_assert(msg);
996 pa_assert(de);
997
998 key.data = de->entry_name;
999 key.size = strlen(de->entry_name);
1000
1001 pa_assert_se(pa_database_unset(de->userdata->database, &key) == 0);
1002
1003 send_entry_removed_signal(de);
1004 trigger_save(de->userdata);
1005
1006 pa_assert_se(pa_hashmap_remove(de->userdata->dbus_entries, de->entry_name));
1007 dbus_entry_free(de);
1008
1009 pa_dbus_send_empty_reply(conn, msg);
1010 }
1011
1012 #endif /* HAVE_DBUS */
1013
1014 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
1015 struct userdata *u = userdata;
1016
1017 pa_assert(a);
1018 pa_assert(e);
1019 pa_assert(u);
1020
1021 pa_assert(e == u->save_time_event);
1022 u->core->mainloop->time_free(u->save_time_event);
1023 u->save_time_event = NULL;
1024
1025 pa_database_sync(u->database);
1026 pa_log_info("Synced.");
1027 }
1028
1029 static char *get_name(pa_proplist *p, const char *prefix) {
1030 const char *r;
1031 char *t;
1032
1033 if (!p)
1034 return NULL;
1035
1036 if ((r = pa_proplist_gets(p, IDENTIFICATION_PROPERTY)))
1037 return pa_xstrdup(r);
1038
1039 if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE)))
1040 t = pa_sprintf_malloc("%s-by-media-role:%s", prefix, r);
1041 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_ID)))
1042 t = pa_sprintf_malloc("%s-by-application-id:%s", prefix, r);
1043 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME)))
1044 t = pa_sprintf_malloc("%s-by-application-name:%s", prefix, r);
1045 else if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_NAME)))
1046 t = pa_sprintf_malloc("%s-by-media-name:%s", prefix, r);
1047 else
1048 t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
1049
1050 pa_proplist_sets(p, IDENTIFICATION_PROPERTY, t);
1051 return t;
1052 }
1053
1054 static struct entry *read_entry(struct userdata *u, const char *name) {
1055 pa_datum key, data;
1056 struct entry *e;
1057
1058 pa_assert(u);
1059 pa_assert(name);
1060
1061 key.data = (char*) name;
1062 key.size = strlen(name);
1063
1064 pa_zero(data);
1065
1066 if (!pa_database_get(u->database, &key, &data))
1067 goto fail;
1068
1069 if (data.size != sizeof(struct entry)) {
1070 /* This is probably just a database upgrade, hence let's not
1071 * consider this more than a debug message */
1072 pa_log_debug("Database contains entry for stream %s of wrong size %lu != %lu. Probably due to uprade, ignoring.", name, (unsigned long) data.size, (unsigned long) sizeof(struct entry));
1073 goto fail;
1074 }
1075
1076 e = (struct entry*) data.data;
1077
1078 if (e->version != ENTRY_VERSION) {
1079 pa_log_debug("Version of database entry for stream %s doesn't match our version. Probably due to upgrade, ignoring.", name);
1080 goto fail;
1081 }
1082
1083 if (!memchr(e->device, 0, sizeof(e->device))) {
1084 pa_log_warn("Database contains entry for stream %s with missing NUL byte in device name", name);
1085 goto fail;
1086 }
1087
1088 if (e->device_valid && !pa_namereg_is_valid_name(e->device)) {
1089 pa_log_warn("Invalid device name stored in database for stream %s", name);
1090 goto fail;
1091 }
1092
1093 if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) {
1094 pa_log_warn("Invalid channel map stored in database for stream %s", name);
1095 goto fail;
1096 }
1097
1098 if (e->volume_valid && (!pa_cvolume_valid(&e->volume) || !pa_cvolume_compatible_with_channel_map(&e->volume, &e->channel_map))) {
1099 pa_log_warn("Invalid volume stored in database for stream %s", name);
1100 goto fail;
1101 }
1102
1103 return e;
1104
1105 fail:
1106
1107 pa_datum_free(&data);
1108 return NULL;
1109 }
1110
1111 static void trigger_save(struct userdata *u) {
1112 pa_native_connection *c;
1113 uint32_t idx;
1114
1115 for (c = pa_idxset_first(u->subscribed, &idx); c; c = pa_idxset_next(u->subscribed, &idx)) {
1116 pa_tagstruct *t;
1117
1118 t = pa_tagstruct_new(NULL, 0);
1119 pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
1120 pa_tagstruct_putu32(t, 0);
1121 pa_tagstruct_putu32(t, u->module->index);
1122 pa_tagstruct_puts(t, u->module->name);
1123 pa_tagstruct_putu32(t, SUBCOMMAND_EVENT);
1124
1125 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
1126 }
1127
1128 if (u->save_time_event)
1129 return;
1130
1131 u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
1132 }
1133
1134 static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) {
1135 pa_cvolume t;
1136
1137 pa_assert(a);
1138 pa_assert(b);
1139
1140 if (a->device_valid != b->device_valid ||
1141 (a->device_valid && strncmp(a->device, b->device, sizeof(a->device))))
1142 return FALSE;
1143
1144 if (a->muted_valid != b->muted_valid ||
1145 (a->muted_valid && (a->muted != b->muted)))
1146 return FALSE;
1147
1148 t = b->volume;
1149 if (a->volume_valid != b->volume_valid ||
1150 (a->volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->volume)))
1151 return FALSE;
1152
1153 return TRUE;
1154 }
1155
1156 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
1157 struct userdata *u = userdata;
1158 struct entry entry, *old;
1159 char *name;
1160 pa_datum key, data;
1161
1162 /* These are only used when D-Bus is enabled, but in order to reduce ifdef
1163 * clutter these are defined here unconditionally. */
1164 pa_bool_t created_new_entry = TRUE;
1165 pa_bool_t device_updated = FALSE;
1166 pa_bool_t volume_updated = FALSE;
1167 pa_bool_t mute_updated = FALSE;
1168
1169 #ifdef HAVE_DBUS
1170 struct dbus_entry *de = NULL;
1171 #endif
1172
1173 pa_assert(c);
1174 pa_assert(u);
1175
1176 if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1177 t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
1178 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1179 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
1180 return;
1181
1182 pa_zero(entry);
1183 entry.version = ENTRY_VERSION;
1184
1185 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
1186 pa_sink_input *sink_input;
1187
1188 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx)))
1189 return;
1190
1191 if (!(name = get_name(sink_input->proplist, "sink-input")))
1192 return;
1193
1194 if ((old = read_entry(u, name))) {
1195 entry = *old;
1196 created_new_entry = FALSE;
1197 }
1198
1199 if (sink_input->save_volume) {
1200 entry.channel_map = sink_input->channel_map;
1201 pa_sink_input_get_volume(sink_input, &entry.volume, FALSE);
1202 entry.volume_valid = TRUE;
1203
1204 volume_updated = !created_new_entry
1205 && (!old->volume_valid
1206 || !pa_channel_map_equal(&entry.channel_map, &old->channel_map)
1207 || !pa_cvolume_equal(&entry.volume, &old->volume));
1208 }
1209
1210 if (sink_input->save_muted) {
1211 entry.muted = pa_sink_input_get_mute(sink_input);
1212 entry.muted_valid = TRUE;
1213
1214 mute_updated = !created_new_entry && (!old->muted_valid || entry.muted != old->muted);
1215 }
1216
1217 if (sink_input->save_sink) {
1218 pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device));
1219 entry.device_valid = TRUE;
1220
1221 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry.device, old->device));
1222 }
1223
1224 } else {
1225 pa_source_output *source_output;
1226
1227 pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);
1228
1229 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx)))
1230 return;
1231
1232 if (!(name = get_name(source_output->proplist, "source-output")))
1233 return;
1234
1235 if ((old = read_entry(u, name))) {
1236 entry = *old;
1237 created_new_entry = FALSE;
1238 }
1239
1240 if (source_output->save_source) {
1241 pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device));
1242 entry.device_valid = source_output->save_source;
1243
1244 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry.device, old->device));
1245 }
1246 }
1247
1248 if (old) {
1249
1250 if (entries_equal(old, &entry)) {
1251 pa_xfree(old);
1252 pa_xfree(name);
1253 return;
1254 }
1255
1256 pa_xfree(old);
1257 }
1258
1259 key.data = name;
1260 key.size = strlen(name);
1261
1262 data.data = &entry;
1263 data.size = sizeof(entry);
1264
1265 pa_log_info("Storing volume/mute/device for stream %s.", name);
1266
1267 pa_database_set(u->database, &key, &data, TRUE);
1268
1269 #ifdef HAVE_DBUS
1270 if (created_new_entry) {
1271 de = dbus_entry_new(u, name);
1272 pa_hashmap_put(u->dbus_entries, de->entry_name, de);
1273 send_new_entry_signal(de);
1274 } else {
1275 pa_assert((de = pa_hashmap_get(u->dbus_entries, name)));
1276
1277 if (device_updated)
1278 send_device_updated_signal(de, &entry);
1279 if (volume_updated)
1280 send_volume_updated_signal(de, &entry);
1281 if (mute_updated)
1282 send_mute_updated_signal(de, &entry);
1283 }
1284 #endif
1285
1286 pa_xfree(name);
1287
1288 trigger_save(u);
1289 }
1290
1291 static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1292 char *name;
1293 struct entry *e;
1294
1295 pa_assert(c);
1296 pa_assert(new_data);
1297 pa_assert(u);
1298 pa_assert(u->restore_device);
1299
1300 if (!(name = get_name(new_data->proplist, "sink-input")))
1301 return PA_HOOK_OK;
1302
1303 if ((e = read_entry(u, name))) {
1304
1305 if (e->device_valid) {
1306 pa_sink *s;
1307
1308 if ((s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK))) {
1309 if (!new_data->sink) {
1310 pa_log_info("Restoring device for stream %s.", name);
1311 new_data->sink = s;
1312 new_data->save_sink = TRUE;
1313 } else
1314 pa_log_debug("Not restoring device for stream %s, because already set.", name);
1315 }
1316 }
1317
1318 pa_xfree(e);
1319 }
1320
1321 pa_xfree(name);
1322
1323 return PA_HOOK_OK;
1324 }
1325
1326 static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1327 char *name;
1328 struct entry *e;
1329
1330 pa_assert(c);
1331 pa_assert(new_data);
1332 pa_assert(u);
1333 pa_assert(u->restore_volume || u->restore_muted);
1334
1335 if (!(name = get_name(new_data->proplist, "sink-input")))
1336 return PA_HOOK_OK;
1337
1338 if ((e = read_entry(u, name))) {
1339
1340 if (u->restore_volume && e->volume_valid) {
1341
1342 if (!new_data->volume_is_set) {
1343 pa_cvolume v;
1344
1345 pa_log_info("Restoring volume for sink input %s.", name);
1346
1347 v = e->volume;
1348 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1349 pa_sink_input_new_data_set_volume(new_data, &v);
1350
1351 new_data->volume_is_absolute = FALSE;
1352 new_data->save_volume = TRUE;
1353 } else
1354 pa_log_debug("Not restoring volume for sink input %s, because already set.", name);
1355 }
1356
1357 if (u->restore_muted && e->muted_valid) {
1358
1359 if (!new_data->muted_is_set) {
1360 pa_log_info("Restoring mute state for sink input %s.", name);
1361 pa_sink_input_new_data_set_muted(new_data, e->muted);
1362 new_data->save_muted = TRUE;
1363 } else
1364 pa_log_debug("Not restoring mute state for sink input %s, because already set.", name);
1365 }
1366
1367 pa_xfree(e);
1368 }
1369
1370 pa_xfree(name);
1371
1372 return PA_HOOK_OK;
1373 }
1374
1375 static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1376 char *name;
1377 struct entry *e;
1378
1379 pa_assert(c);
1380 pa_assert(new_data);
1381 pa_assert(u);
1382 pa_assert(u->restore_device);
1383
1384 if (new_data->direct_on_input)
1385 return PA_HOOK_OK;
1386
1387 if (!(name = get_name(new_data->proplist, "source-output")))
1388 return PA_HOOK_OK;
1389
1390 if ((e = read_entry(u, name))) {
1391 pa_source *s;
1392
1393 if (e->device_valid) {
1394 if ((s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE))) {
1395 if (!new_data->source) {
1396 pa_log_info("Restoring device for stream %s.", name);
1397 new_data->source = s;
1398 new_data->save_source = TRUE;
1399 } else
1400 pa_log_debug("Not restoring device for stream %s, because already set", name);
1401 }
1402 }
1403
1404 pa_xfree(e);
1405 }
1406
1407 pa_xfree(name);
1408
1409 return PA_HOOK_OK;
1410 }
1411
1412 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1413 pa_sink_input *si;
1414 uint32_t idx;
1415
1416 pa_assert(c);
1417 pa_assert(sink);
1418 pa_assert(u);
1419 pa_assert(u->on_hotplug && u->restore_device);
1420
1421 PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
1422 char *name;
1423 struct entry *e;
1424
1425 if (si->sink == sink)
1426 continue;
1427
1428 if (si->save_sink)
1429 continue;
1430
1431 if (!(name = get_name(si->proplist, "sink-input")))
1432 continue;
1433
1434 if ((e = read_entry(u, name))) {
1435 if (e->device_valid && pa_streq(e->device, sink->name))
1436 pa_sink_input_move_to(si, sink, TRUE);
1437
1438 pa_xfree(e);
1439 }
1440
1441 pa_xfree(name);
1442 }
1443
1444 return PA_HOOK_OK;
1445 }
1446
1447 static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1448 pa_source_output *so;
1449 uint32_t idx;
1450
1451 pa_assert(c);
1452 pa_assert(source);
1453 pa_assert(u);
1454 pa_assert(u->on_hotplug && u->restore_device);
1455
1456 PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
1457 char *name;
1458 struct entry *e;
1459
1460 if (so->source == source)
1461 continue;
1462
1463 if (so->save_source)
1464 continue;
1465
1466 if (so->direct_on_input)
1467 continue;
1468
1469 if (!(name = get_name(so->proplist, "source-input")))
1470 continue;
1471
1472 if ((e = read_entry(u, name))) {
1473 if (e->device_valid && pa_streq(e->device, source->name))
1474 pa_source_output_move_to(so, source, TRUE);
1475
1476 pa_xfree(e);
1477 }
1478
1479 pa_xfree(name);
1480 }
1481
1482 return PA_HOOK_OK;
1483 }
1484
1485 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1486 pa_sink_input *si;
1487 uint32_t idx;
1488
1489 pa_assert(c);
1490 pa_assert(sink);
1491 pa_assert(u);
1492 pa_assert(u->on_rescue && u->restore_device);
1493
1494 /* There's no point in doing anything if the core is shut down anyway */
1495 if (c->state == PA_CORE_SHUTDOWN)
1496 return PA_HOOK_OK;
1497
1498 PA_IDXSET_FOREACH(si, sink->inputs, idx) {
1499 char *name;
1500 struct entry *e;
1501
1502 if (!(name = get_name(si->proplist, "sink-input")))
1503 continue;
1504
1505 if ((e = read_entry(u, name))) {
1506
1507 if (e->device_valid) {
1508 pa_sink *d;
1509
1510 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) && d != sink)
1511 pa_sink_input_move_to(si, d, TRUE);
1512 }
1513
1514 pa_xfree(e);
1515 }
1516
1517 pa_xfree(name);
1518 }
1519
1520 return PA_HOOK_OK;
1521 }
1522
1523 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1524 pa_source_output *so;
1525 uint32_t idx;
1526
1527 pa_assert(c);
1528 pa_assert(source);
1529 pa_assert(u);
1530 pa_assert(u->on_rescue && u->restore_device);
1531
1532 /* There's no point in doing anything if the core is shut down anyway */
1533 if (c->state == PA_CORE_SHUTDOWN)
1534 return PA_HOOK_OK;
1535
1536 PA_IDXSET_FOREACH(so, source->outputs, idx) {
1537 char *name;
1538 struct entry *e;
1539
1540 if (!(name = get_name(so->proplist, "source-output")))
1541 continue;
1542
1543 if ((e = read_entry(u, name))) {
1544
1545 if (e->device_valid) {
1546 pa_source *d;
1547
1548 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) && d != source)
1549 pa_source_output_move_to(so, d, TRUE);
1550 }
1551
1552 pa_xfree(e);
1553 }
1554
1555 pa_xfree(name);
1556 }
1557
1558 return PA_HOOK_OK;
1559 }
1560
1561 #define EXT_VERSION 1
1562
1563 static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
1564 pa_sink_input *si;
1565 pa_source_output *so;
1566 uint32_t idx;
1567
1568 pa_assert(u);
1569 pa_assert(name);
1570 pa_assert(e);
1571
1572 for (si = pa_idxset_first(u->core->sink_inputs, &idx); si; si = pa_idxset_next(u->core->sink_inputs, &idx)) {
1573 char *n;
1574 pa_sink *s;
1575
1576 if (!(n = get_name(si->proplist, "sink-input")))
1577 continue;
1578
1579 if (!pa_streq(name, n)) {
1580 pa_xfree(n);
1581 continue;
1582 }
1583 pa_xfree(n);
1584
1585 if (u->restore_volume && e->volume_valid) {
1586 pa_cvolume v;
1587
1588 v = e->volume;
1589 pa_log_info("Restoring volume for sink input %s.", name);
1590 pa_sink_input_set_volume(si, pa_cvolume_remap(&v, &e->channel_map, &si->channel_map), FALSE, FALSE);
1591 }
1592
1593 if (u->restore_muted && e->muted_valid) {
1594 pa_log_info("Restoring mute state for sink input %s.", name);
1595 pa_sink_input_set_mute(si, e->muted, FALSE);
1596 }
1597
1598 if (u->restore_device &&
1599 e->device_valid &&
1600 (s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SINK))) {
1601
1602 pa_log_info("Restoring device for stream %s.", name);
1603 pa_sink_input_move_to(si, s, FALSE);
1604 }
1605 }
1606
1607 for (so = pa_idxset_first(u->core->source_outputs, &idx); so; so = pa_idxset_next(u->core->source_outputs, &idx)) {
1608 char *n;
1609 pa_source *s;
1610
1611 if (!(n = get_name(so->proplist, "source-output")))
1612 continue;
1613
1614 if (!pa_streq(name, n)) {
1615 pa_xfree(n);
1616 continue;
1617 }
1618 pa_xfree(n);
1619
1620 if (u->restore_device &&
1621 e->device_valid &&
1622 (s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE))) {
1623
1624 pa_log_info("Restoring device for stream %s.", name);
1625 pa_source_output_move_to(so, s, FALSE);
1626 }
1627 }
1628 }
1629
1630 #if 0
1631 static void dump_database(struct userdata *u) {
1632 pa_datum key;
1633 pa_bool_t done;
1634
1635 done = !pa_database_first(u->database, &key, NULL);
1636
1637 while (!done) {
1638 pa_datum next_key;
1639 struct entry *e;
1640 char *name;
1641
1642 done = !pa_database_next(u->database, &key, &next_key, NULL);
1643
1644 name = pa_xstrndup(key.data, key.size);
1645 pa_datum_free(&key);
1646
1647 if ((e = read_entry(u, name))) {
1648 char t[256];
1649 pa_log("name=%s", name);
1650 pa_log("device=%s %s", e->device, pa_yes_no(e->device_valid));
1651 pa_log("channel_map=%s", pa_channel_map_snprint(t, sizeof(t), &e->channel_map));
1652 pa_log("volume=%s %s", pa_cvolume_snprint(t, sizeof(t), &e->volume), pa_yes_no(e->volume_valid));
1653 pa_log("mute=%s %s", pa_yes_no(e->muted), pa_yes_no(e->volume_valid));
1654 pa_xfree(e);
1655 }
1656
1657 pa_xfree(name);
1658
1659 key = next_key;
1660 }
1661 }
1662 #endif
1663
1664 static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
1665 struct userdata *u;
1666 uint32_t command;
1667 pa_tagstruct *reply = NULL;
1668
1669 pa_assert(p);
1670 pa_assert(m);
1671 pa_assert(c);
1672 pa_assert(t);
1673
1674 u = m->userdata;
1675
1676 if (pa_tagstruct_getu32(t, &command) < 0)
1677 goto fail;
1678
1679 reply = pa_tagstruct_new(NULL, 0);
1680 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1681 pa_tagstruct_putu32(reply, tag);
1682
1683 switch (command) {
1684 case SUBCOMMAND_TEST: {
1685 if (!pa_tagstruct_eof(t))
1686 goto fail;
1687
1688 pa_tagstruct_putu32(reply, EXT_VERSION);
1689 break;
1690 }
1691
1692 case SUBCOMMAND_READ: {
1693 pa_datum key;
1694 pa_bool_t done;
1695
1696 if (!pa_tagstruct_eof(t))
1697 goto fail;
1698
1699 done = !pa_database_first(u->database, &key, NULL);
1700
1701 while (!done) {
1702 pa_datum next_key;
1703 struct entry *e;
1704 char *name;
1705
1706 done = !pa_database_next(u->database, &key, &next_key, NULL);
1707
1708 name = pa_xstrndup(key.data, key.size);
1709 pa_datum_free(&key);
1710
1711 if ((e = read_entry(u, name))) {
1712 pa_cvolume r;
1713 pa_channel_map cm;
1714
1715 pa_tagstruct_puts(reply, name);
1716 pa_tagstruct_put_channel_map(reply, e->volume_valid ? &e->channel_map : pa_channel_map_init(&cm));
1717 pa_tagstruct_put_cvolume(reply, e->volume_valid ? &e->volume : pa_cvolume_init(&r));
1718 pa_tagstruct_puts(reply, e->device_valid ? e->device : NULL);
1719 pa_tagstruct_put_boolean(reply, e->muted_valid ? e->muted : FALSE);
1720
1721 pa_xfree(e);
1722 }
1723
1724 pa_xfree(name);
1725
1726 key = next_key;
1727 }
1728
1729 break;
1730 }
1731
1732 case SUBCOMMAND_WRITE: {
1733 uint32_t mode;
1734 pa_bool_t apply_immediately = FALSE;
1735
1736 if (pa_tagstruct_getu32(t, &mode) < 0 ||
1737 pa_tagstruct_get_boolean(t, &apply_immediately) < 0)
1738 goto fail;
1739
1740 if (mode != PA_UPDATE_MERGE &&
1741 mode != PA_UPDATE_REPLACE &&
1742 mode != PA_UPDATE_SET)
1743 goto fail;
1744
1745 if (mode == PA_UPDATE_SET) {
1746 #ifdef HAVE_DBUS
1747 struct dbus_entry *de;
1748 void *state = NULL;
1749
1750 while ((de = pa_hashmap_iterate(u->dbus_entries, &state, NULL))) {
1751 send_entry_removed_signal(de);
1752 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, de->entry_name));
1753 }
1754 #endif
1755 pa_database_clear(u->database);
1756 }
1757
1758 while (!pa_tagstruct_eof(t)) {
1759 const char *name, *device;
1760 pa_bool_t muted;
1761 struct entry entry;
1762 pa_datum key, data;
1763 #ifdef HAVE_DBUS
1764 struct entry *old;
1765 #endif
1766
1767 pa_zero(entry);
1768 entry.version = ENTRY_VERSION;
1769
1770 if (pa_tagstruct_gets(t, &name) < 0 ||
1771 pa_tagstruct_get_channel_map(t, &entry.channel_map) ||
1772 pa_tagstruct_get_cvolume(t, &entry.volume) < 0 ||
1773 pa_tagstruct_gets(t, &device) < 0 ||
1774 pa_tagstruct_get_boolean(t, &muted) < 0)
1775 goto fail;
1776
1777 if (!name || !*name)
1778 goto fail;
1779
1780 entry.volume_valid = entry.volume.channels > 0;
1781
1782 if (entry.volume_valid)
1783 if (!pa_cvolume_compatible_with_channel_map(&entry.volume, &entry.channel_map))
1784 goto fail;
1785
1786 entry.muted = muted;
1787 entry.muted_valid = TRUE;
1788
1789 if (device)
1790 pa_strlcpy(entry.device, device, sizeof(entry.device));
1791 entry.device_valid = !!entry.device[0];
1792
1793 if (entry.device_valid &&
1794 !pa_namereg_is_valid_name(entry.device))
1795 goto fail;
1796
1797 #ifdef HAVE_DBUS
1798 old = read_entry(u, name);
1799 #endif
1800
1801 key.data = (char*) name;
1802 key.size = strlen(name);
1803
1804 data.data = &entry;
1805 data.size = sizeof(entry);
1806
1807 if (pa_database_set(u->database, &key, &data, mode == PA_UPDATE_REPLACE) == 0) {
1808 #ifdef HAVE_DBUS
1809 struct dbus_entry *de;
1810
1811 if (old) {
1812 pa_assert_se((de = pa_hashmap_get(u->dbus_entries, name)));
1813
1814 if ((old->device_valid != entry.device_valid)
1815 || (entry.device_valid && !pa_streq(entry.device, old->device)))
1816 send_device_updated_signal(de, &entry);
1817
1818 if ((old->volume_valid != entry.volume_valid)
1819 || (entry.volume_valid
1820 && (!pa_cvolume_equal(&entry.volume, &old->volume) || !pa_channel_map_equal(&entry.channel_map, &old->channel_map))))
1821 send_volume_updated_signal(de, &entry);
1822
1823 if (!old->muted_valid || (entry.muted != old->muted))
1824 send_mute_updated_signal(de, &entry);
1825
1826 } else {
1827 de = dbus_entry_new(u, name);
1828 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de));
1829 send_new_entry_signal(de);
1830 }
1831 #endif
1832
1833 if (apply_immediately)
1834 apply_entry(u, name, &entry);
1835 }
1836
1837 #ifdef HAVE_DBUS
1838 if (old)
1839 pa_xfree(old);
1840 #endif
1841 }
1842
1843 trigger_save(u);
1844
1845 break;
1846 }
1847
1848 case SUBCOMMAND_DELETE:
1849
1850 while (!pa_tagstruct_eof(t)) {
1851 const char *name;
1852 pa_datum key;
1853 #ifdef HAVE_DBUS
1854 struct dbus_entry *de;
1855 #endif
1856
1857 if (pa_tagstruct_gets(t, &name) < 0)
1858 goto fail;
1859
1860 #ifdef HAVE_DBUS
1861 if ((de = pa_hashmap_get(u->dbus_entries, name))) {
1862 send_entry_removed_signal(de);
1863 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, name));
1864 }
1865 #endif
1866
1867 key.data = (char*) name;
1868 key.size = strlen(name);
1869
1870 pa_database_unset(u->database, &key);
1871 }
1872
1873 trigger_save(u);
1874
1875 break;
1876
1877 case SUBCOMMAND_SUBSCRIBE: {
1878
1879 pa_bool_t enabled;
1880
1881 if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
1882 !pa_tagstruct_eof(t))
1883 goto fail;
1884
1885 if (enabled)
1886 pa_idxset_put(u->subscribed, c, NULL);
1887 else
1888 pa_idxset_remove_by_data(u->subscribed, c, NULL);
1889
1890 break;
1891 }
1892
1893 default:
1894 goto fail;
1895 }
1896
1897 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
1898 return 0;
1899
1900 fail:
1901
1902 if (reply)
1903 pa_tagstruct_free(reply);
1904
1905 return -1;
1906 }
1907
1908 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
1909 pa_assert(p);
1910 pa_assert(c);
1911 pa_assert(u);
1912
1913 pa_idxset_remove_by_data(u->subscribed, c, NULL);
1914 return PA_HOOK_OK;
1915 }
1916
1917 int pa__init(pa_module*m) {
1918 pa_modargs *ma = NULL;
1919 struct userdata *u;
1920 char *fname;
1921 pa_sink_input *si;
1922 pa_source_output *so;
1923 uint32_t idx;
1924 pa_bool_t restore_device = TRUE, restore_volume = TRUE, restore_muted = TRUE, on_hotplug = TRUE, on_rescue = TRUE;
1925 #ifdef HAVE_DBUS
1926 pa_datum key;
1927 pa_bool_t done;
1928 #endif
1929
1930 pa_assert(m);
1931
1932 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1933 pa_log("Failed to parse module arguments");
1934 goto fail;
1935 }
1936
1937 if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
1938 pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
1939 pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
1940 pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
1941 pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
1942 pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments");
1943 goto fail;
1944 }
1945
1946 if (!restore_muted && !restore_volume && !restore_device)
1947 pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!");
1948
1949 m->userdata = u = pa_xnew0(struct userdata, 1);
1950 u->core = m->core;
1951 u->module = m;
1952 u->restore_device = restore_device;
1953 u->restore_volume = restore_volume;
1954 u->restore_muted = restore_muted;
1955 u->on_hotplug = on_hotplug;
1956 u->on_rescue = on_rescue;
1957 u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
1958
1959 u->protocol = pa_native_protocol_get(m->core);
1960 pa_native_protocol_install_ext(u->protocol, m, extension_cb);
1961
1962 u->connection_unlink_hook_slot = pa_hook_connect(&pa_native_protocol_hooks(u->protocol)[PA_NATIVE_HOOK_CONNECTION_UNLINK], PA_HOOK_NORMAL, (pa_hook_cb_t) connection_unlink_hook_cb, u);
1963
1964 u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
1965
1966 if (restore_device) {
1967 /* A little bit earlier than module-intended-roles ... */
1968 u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_new_hook_callback, u);
1969 u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_new_hook_callback, u);
1970 }
1971
1972 if (restore_device && on_hotplug) {
1973 /* A little bit earlier than module-intended-roles ... */
1974 u->sink_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE, (pa_hook_cb_t) sink_put_hook_callback, u);
1975 u->source_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE, (pa_hook_cb_t) source_put_hook_callback, u);
1976 }
1977
1978 if (restore_device && on_rescue) {
1979 /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */
1980 u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_unlink_hook_callback, u);
1981 u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) source_unlink_hook_callback, u);
1982 }
1983
1984 if (restore_volume || restore_muted)
1985 u->sink_input_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_fixate_hook_callback, u);
1986
1987 if (!(fname = pa_state_path("stream-volumes", TRUE)))
1988 goto fail;
1989
1990 if (!(u->database = pa_database_open(fname, TRUE))) {
1991 pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
1992 pa_xfree(fname);
1993 goto fail;
1994 }
1995
1996 pa_log_info("Sucessfully opened database file '%s'.", fname);
1997 pa_xfree(fname);
1998
1999 #ifdef HAVE_DBUS
2000 u->dbus_protocol = pa_dbus_protocol_get(u->core);
2001 u->dbus_entries = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
2002
2003 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, OBJECT_PATH, &stream_restore_interface_info, u) >= 0);
2004 pa_assert_se(pa_dbus_protocol_register_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2005
2006 /* Create the initial dbus entries. */
2007 done = !pa_database_first(u->database, &key, NULL);
2008 while (!done) {
2009 pa_datum next_key;
2010 char *name;
2011 struct dbus_entry *de;
2012
2013 done = !pa_database_next(u->database, &key, &next_key, NULL);
2014
2015 name = pa_xstrndup(key.data, key.size);
2016 pa_datum_free(&key);
2017
2018 de = dbus_entry_new(u, name);
2019 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) >= 0);
2020
2021 pa_xfree(name);
2022
2023 key = next_key;
2024 }
2025 #endif
2026
2027 PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx)
2028 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u);
2029
2030 PA_IDXSET_FOREACH(so, m->core->source_outputs, idx)
2031 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, so->index, u);
2032
2033 pa_modargs_free(ma);
2034 return 0;
2035
2036 fail:
2037 pa__done(m);
2038
2039 if (ma)
2040 pa_modargs_free(ma);
2041
2042 return -1;
2043 }
2044
2045 #ifdef HAVE_DBUS
2046 static void free_dbus_entry_cb(void *p, void *userdata) {
2047 struct dbus_entry *de = p;
2048
2049 pa_assert(de);
2050
2051 dbus_entry_free(de);
2052 }
2053 #endif
2054
2055 void pa__done(pa_module*m) {
2056 struct userdata* u;
2057
2058 pa_assert(m);
2059
2060 if (!(u = m->userdata))
2061 return;
2062
2063 #ifdef HAVE_DBUS
2064 if (u->dbus_protocol) {
2065 pa_assert(u->dbus_entries);
2066
2067 pa_assert_se(pa_dbus_protocol_unregister_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2068 pa_assert_se(pa_dbus_protocol_remove_interface(u->dbus_protocol, OBJECT_PATH, stream_restore_interface_info.name) >= 0);
2069
2070 pa_hashmap_free(u->dbus_entries, free_dbus_entry_cb, NULL);
2071
2072 pa_dbus_protocol_unref(u->dbus_protocol);
2073 }
2074 #endif
2075
2076 if (u->subscription)
2077 pa_subscription_free(u->subscription);
2078
2079 if (u->sink_input_new_hook_slot)
2080 pa_hook_slot_free(u->sink_input_new_hook_slot);
2081 if (u->sink_input_fixate_hook_slot)
2082 pa_hook_slot_free(u->sink_input_fixate_hook_slot);
2083 if (u->source_output_new_hook_slot)
2084 pa_hook_slot_free(u->source_output_new_hook_slot);
2085
2086 if (u->sink_put_hook_slot)
2087 pa_hook_slot_free(u->sink_put_hook_slot);
2088 if (u->source_put_hook_slot)
2089 pa_hook_slot_free(u->source_put_hook_slot);
2090
2091 if (u->sink_unlink_hook_slot)
2092 pa_hook_slot_free(u->sink_unlink_hook_slot);
2093 if (u->source_unlink_hook_slot)
2094 pa_hook_slot_free(u->source_unlink_hook_slot);
2095
2096 if (u->connection_unlink_hook_slot)
2097 pa_hook_slot_free(u->connection_unlink_hook_slot);
2098
2099 if (u->save_time_event)
2100 u->core->mainloop->time_free(u->save_time_event);
2101
2102 if (u->database)
2103 pa_database_close(u->database);
2104
2105 if (u->protocol) {
2106 pa_native_protocol_remove_ext(u->protocol, m);
2107 pa_native_protocol_unref(u->protocol);
2108 }
2109
2110 if (u->subscribed)
2111 pa_idxset_free(u->subscribed, NULL, NULL);
2112
2113 pa_xfree(u);
2114 }