stream-restore: Fix a few assertion misuses with the D-Bus code.
[pulseaudio-raopUDP/pulseaudio-raop-alac.git] / src / modules / module-stream-restore.c
blobce92362122377c388c5c8553a035bfe75d967cb2
1 /***
2 This file is part of PulseAudio.
4 Copyright 2008 Lennart Poettering
5 Copyright 2009 Tanu Kaskinen
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.
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.
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 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
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>
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>
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>
55 #ifdef HAVE_DBUS
56 #include <pulsecore/dbus-util.h>
57 #include <pulsecore/protocol-dbus.h>
58 #endif
60 #include "module-stream-restore-symdef.h"
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?>");
73 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
74 #define IDENTIFICATION_PROPERTY "module-stream-restore.id"
76 static const char* const valid_modargs[] = {
77 "restore_device",
78 "restore_volume",
79 "restore_muted",
80 "on_hotplug",
81 "on_rescue",
82 NULL
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;
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;
107 pa_native_protocol *protocol;
108 pa_idxset *subscribed;
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
117 #define ENTRY_VERSION 3
119 struct entry {
120 uint8_t version;
121 pa_bool_t muted_valid:1, volume_valid:1, device_valid:1, card_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 char card[PA_NAME_MAX];
127 } PA_GCC_PACKED;
129 enum {
130 SUBCOMMAND_TEST,
131 SUBCOMMAND_READ,
132 SUBCOMMAND_WRITE,
133 SUBCOMMAND_DELETE,
134 SUBCOMMAND_SUBSCRIBE,
135 SUBCOMMAND_EVENT
138 static struct entry *read_entry(struct userdata *u, const char *name);
139 static void apply_entry(struct userdata *u, const char *name, struct entry *e);
140 static void trigger_save(struct userdata *u);
142 #ifdef HAVE_DBUS
144 #define OBJECT_PATH "/org/pulseaudio/stream_restore1"
145 #define ENTRY_OBJECT_NAME "entry"
146 #define INTERFACE_STREAM_RESTORE "org.PulseAudio.Ext.StreamRestore1"
147 #define INTERFACE_ENTRY INTERFACE_STREAM_RESTORE ".RestoreEntry"
149 #define DBUS_INTERFACE_REVISION 0
151 struct dbus_entry {
152 struct userdata *userdata;
154 char *entry_name;
155 uint32_t index;
156 char *object_path;
159 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata);
160 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata);
162 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
164 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata);
165 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
167 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata);
168 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
169 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
170 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
171 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
172 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
173 static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
174 static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
176 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
178 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata);
180 enum property_handler_index {
181 PROPERTY_HANDLER_INTERFACE_REVISION,
182 PROPERTY_HANDLER_ENTRIES,
183 PROPERTY_HANDLER_MAX
186 enum entry_property_handler_index {
187 ENTRY_PROPERTY_HANDLER_INDEX,
188 ENTRY_PROPERTY_HANDLER_NAME,
189 ENTRY_PROPERTY_HANDLER_DEVICE,
190 ENTRY_PROPERTY_HANDLER_VOLUME,
191 ENTRY_PROPERTY_HANDLER_MUTE,
192 ENTRY_PROPERTY_HANDLER_MAX
195 static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = {
196 [PROPERTY_HANDLER_INTERFACE_REVISION] = { .property_name = "InterfaceRevision", .type = "u", .get_cb = handle_get_interface_revision, .set_cb = NULL },
197 [PROPERTY_HANDLER_ENTRIES] = { .property_name = "Entries", .type = "ao", .get_cb = handle_get_entries, .set_cb = NULL }
200 static pa_dbus_property_handler entry_property_handlers[ENTRY_PROPERTY_HANDLER_MAX] = {
201 [ENTRY_PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_entry_get_index, .set_cb = NULL },
202 [ENTRY_PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_entry_get_name, .set_cb = NULL },
203 [ENTRY_PROPERTY_HANDLER_DEVICE] = { .property_name = "Device", .type = "s", .get_cb = handle_entry_get_device, .set_cb = handle_entry_set_device },
204 [ENTRY_PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "a(uu)", .get_cb = handle_entry_get_volume, .set_cb = handle_entry_set_volume },
205 [ENTRY_PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_entry_get_mute, .set_cb = handle_entry_set_mute }
208 enum method_handler_index {
209 METHOD_HANDLER_ADD_ENTRY,
210 METHOD_HANDLER_GET_ENTRY_BY_NAME,
211 METHOD_HANDLER_MAX
214 enum entry_method_handler_index {
215 ENTRY_METHOD_HANDLER_REMOVE,
216 ENTRY_METHOD_HANDLER_MAX
219 static pa_dbus_arg_info add_entry_args[] = { { "name", "s", "in" },
220 { "device", "s", "in" },
221 { "volume", "a(uu)", "in" },
222 { "mute", "b", "in" },
223 { "entry", "o", "out" } };
224 static pa_dbus_arg_info get_entry_by_name_args[] = { { "name", "s", "in" }, { "entry", "o", "out" } };
226 static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
227 [METHOD_HANDLER_ADD_ENTRY] = {
228 .method_name = "AddEntry",
229 .arguments = add_entry_args,
230 .n_arguments = sizeof(add_entry_args) / sizeof(pa_dbus_arg_info),
231 .receive_cb = handle_add_entry },
232 [METHOD_HANDLER_GET_ENTRY_BY_NAME] = {
233 .method_name = "GetEntryByName",
234 .arguments = get_entry_by_name_args,
235 .n_arguments = sizeof(get_entry_by_name_args) / sizeof(pa_dbus_arg_info),
236 .receive_cb = handle_get_entry_by_name }
239 static pa_dbus_method_handler entry_method_handlers[ENTRY_METHOD_HANDLER_MAX] = {
240 [ENTRY_METHOD_HANDLER_REMOVE] = {
241 .method_name = "Remove",
242 .arguments = NULL,
243 .n_arguments = 0,
244 .receive_cb = handle_entry_remove }
247 enum signal_index {
248 SIGNAL_NEW_ENTRY,
249 SIGNAL_ENTRY_REMOVED,
250 SIGNAL_MAX
253 enum entry_signal_index {
254 ENTRY_SIGNAL_DEVICE_UPDATED,
255 ENTRY_SIGNAL_VOLUME_UPDATED,
256 ENTRY_SIGNAL_MUTE_UPDATED,
257 ENTRY_SIGNAL_MAX
260 static pa_dbus_arg_info new_entry_args[] = { { "entry", "o", NULL } };
261 static pa_dbus_arg_info entry_removed_args[] = { { "entry", "o", NULL } };
263 static pa_dbus_arg_info entry_device_updated_args[] = { { "device", "s", NULL } };
264 static pa_dbus_arg_info entry_volume_updated_args[] = { { "volume", "a(uu)", NULL } };
265 static pa_dbus_arg_info entry_mute_updated_args[] = { { "muted", "b", NULL } };
267 static pa_dbus_signal_info signals[SIGNAL_MAX] = {
268 [SIGNAL_NEW_ENTRY] = { .name = "NewEntry", .arguments = new_entry_args, .n_arguments = 1 },
269 [SIGNAL_ENTRY_REMOVED] = { .name = "EntryRemoved", .arguments = entry_removed_args, .n_arguments = 1 }
272 static pa_dbus_signal_info entry_signals[ENTRY_SIGNAL_MAX] = {
273 [ENTRY_SIGNAL_DEVICE_UPDATED] = { .name = "DeviceUpdated", .arguments = entry_device_updated_args, .n_arguments = 1 },
274 [ENTRY_SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = entry_volume_updated_args, .n_arguments = 1 },
275 [ENTRY_SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = entry_mute_updated_args, .n_arguments = 1 }
278 static pa_dbus_interface_info stream_restore_interface_info = {
279 .name = INTERFACE_STREAM_RESTORE,
280 .method_handlers = method_handlers,
281 .n_method_handlers = METHOD_HANDLER_MAX,
282 .property_handlers = property_handlers,
283 .n_property_handlers = PROPERTY_HANDLER_MAX,
284 .get_all_properties_cb = handle_get_all,
285 .signals = signals,
286 .n_signals = SIGNAL_MAX
289 static pa_dbus_interface_info entry_interface_info = {
290 .name = INTERFACE_ENTRY,
291 .method_handlers = entry_method_handlers,
292 .n_method_handlers = ENTRY_METHOD_HANDLER_MAX,
293 .property_handlers = entry_property_handlers,
294 .n_property_handlers = ENTRY_PROPERTY_HANDLER_MAX,
295 .get_all_properties_cb = handle_entry_get_all,
296 .signals = entry_signals,
297 .n_signals = ENTRY_SIGNAL_MAX
300 static struct dbus_entry *dbus_entry_new(struct userdata *u, const char *entry_name) {
301 struct dbus_entry *de;
303 pa_assert(u);
304 pa_assert(entry_name);
305 pa_assert(*entry_name);
307 de = pa_xnew(struct dbus_entry, 1);
308 de->userdata = u;
309 de->entry_name = pa_xstrdup(entry_name);
310 de->index = u->next_index++;
311 de->object_path = pa_sprintf_malloc("%s/%s%u", OBJECT_PATH, ENTRY_OBJECT_NAME, de->index);
313 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, de->object_path, &entry_interface_info, u) >= 0);
315 return de;
318 static void dbus_entry_free(struct dbus_entry *de) {
319 pa_assert(de);
321 pa_assert_se(pa_dbus_protocol_remove_interface(de->userdata->dbus_protocol, de->object_path, entry_interface_info.name) >= 0);
323 pa_xfree(de->entry_name);
324 pa_xfree(de->object_path);
327 /* Reads an array [(UInt32, UInt32)] from the iterator. The struct items are
328 * are a channel position and a volume value, respectively. The result is
329 * stored in the map and vol arguments. The iterator must point to a "a(uu)"
330 * element. If the data is invalid, an error reply is sent and a negative
331 * number is returned. In case of a failure we make no guarantees about the
332 * state of map and vol. In case of an empty array the channels field of both
333 * map and vol are set to 0. This function calls dbus_message_iter_next(iter)
334 * before returning. */
335 static int get_volume_arg(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, pa_channel_map *map, pa_cvolume *vol) {
336 DBusMessageIter array_iter;
337 DBusMessageIter struct_iter;
339 pa_assert(conn);
340 pa_assert(msg);
341 pa_assert(iter);
342 pa_assert(pa_streq(dbus_message_iter_get_signature(iter), "a(uu)"));
343 pa_assert(map);
344 pa_assert(vol);
346 pa_channel_map_init(map);
347 pa_cvolume_init(vol);
349 map->channels = 0;
350 vol->channels = 0;
352 dbus_message_iter_recurse(iter, &array_iter);
354 while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
355 dbus_uint32_t chan_pos;
356 dbus_uint32_t chan_vol;
358 dbus_message_iter_recurse(&array_iter, &struct_iter);
360 dbus_message_iter_get_basic(&struct_iter, &chan_pos);
362 if (chan_pos >= PA_CHANNEL_POSITION_MAX) {
363 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position: %u", chan_pos);
364 return -1;
367 pa_assert_se(dbus_message_iter_next(&struct_iter));
368 dbus_message_iter_get_basic(&struct_iter, &chan_vol);
370 if (chan_vol > PA_VOLUME_MAX) {
371 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u", chan_vol);
372 return -1;
375 if (map->channels < PA_CHANNELS_MAX) {
376 map->map[map->channels] = chan_pos;
377 vol->values[map->channels] = chan_vol;
379 ++map->channels;
380 ++vol->channels;
382 dbus_message_iter_next(&array_iter);
385 if (map->channels > PA_CHANNELS_MAX) {
386 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too many channels: %u. The maximum is %u.", map->channels, PA_CHANNELS_MAX);
387 return -1;
390 dbus_message_iter_next(iter);
392 return 0;
395 static void append_volume(DBusMessageIter *iter, struct entry *e) {
396 DBusMessageIter array_iter;
397 DBusMessageIter struct_iter;
398 unsigned i;
400 pa_assert(iter);
401 pa_assert(e);
403 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(uu)", &array_iter));
405 if (!e->volume_valid) {
406 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
407 return;
410 for (i = 0; i < e->channel_map.channels; ++i) {
411 pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter));
413 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->channel_map.map[i]));
414 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->volume.values[i]));
416 pa_assert_se(dbus_message_iter_close_container(&array_iter, &struct_iter));
419 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
422 static void append_volume_variant(DBusMessageIter *iter, struct entry *e) {
423 DBusMessageIter variant_iter;
425 pa_assert(iter);
426 pa_assert(e);
428 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(uu)", &variant_iter));
430 append_volume(&variant_iter, e);
432 pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter));
435 static void send_new_entry_signal(struct dbus_entry *entry) {
436 DBusMessage *signal_msg;
438 pa_assert(entry);
440 pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name));
441 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
442 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg);
443 dbus_message_unref(signal_msg);
446 static void send_entry_removed_signal(struct dbus_entry *entry) {
447 DBusMessage *signal_msg;
449 pa_assert(entry);
451 pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name));
452 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
453 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg);
454 dbus_message_unref(signal_msg);
457 static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) {
458 DBusMessage *signal_msg;
459 const char *device;
461 pa_assert(de);
462 pa_assert(e);
464 device = e->device_valid ? e->device : "";
466 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name));
467 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID));
468 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
469 dbus_message_unref(signal_msg);
472 static void send_volume_updated_signal(struct dbus_entry *de, struct entry *e) {
473 DBusMessage *signal_msg;
474 DBusMessageIter msg_iter;
476 pa_assert(de);
477 pa_assert(e);
479 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name));
480 dbus_message_iter_init_append(signal_msg, &msg_iter);
481 append_volume(&msg_iter, e);
482 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
483 dbus_message_unref(signal_msg);
486 static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) {
487 DBusMessage *signal_msg;
488 dbus_bool_t muted;
490 pa_assert(de);
491 pa_assert(e);
493 pa_assert(e->muted_valid);
495 muted = e->muted;
497 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name));
498 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID));
499 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
500 dbus_message_unref(signal_msg);
503 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) {
504 dbus_uint32_t interface_revision = DBUS_INTERFACE_REVISION;
506 pa_assert(conn);
507 pa_assert(msg);
509 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &interface_revision);
512 /* The caller frees the array, but not the strings. */
513 static const char **get_entries(struct userdata *u, unsigned *n) {
514 const char **entries;
515 unsigned i = 0;
516 void *state = NULL;
517 struct dbus_entry *de;
519 pa_assert(u);
520 pa_assert(n);
522 *n = pa_hashmap_size(u->dbus_entries);
524 if (*n == 0)
525 return NULL;
527 entries = pa_xnew(const char *, *n);
529 PA_HASHMAP_FOREACH(de, u->dbus_entries, state)
530 entries[i++] = de->object_path;
532 return entries;
535 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata) {
536 struct userdata *u = userdata;
537 const char **entries;
538 unsigned n;
540 pa_assert(conn);
541 pa_assert(msg);
542 pa_assert(u);
544 entries = get_entries(u, &n);
546 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, entries, n);
548 pa_xfree(entries);
551 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
552 struct userdata *u = userdata;
553 DBusMessage *reply = NULL;
554 DBusMessageIter msg_iter;
555 DBusMessageIter dict_iter;
556 dbus_uint32_t interface_revision;
557 const char **entries;
558 unsigned n_entries;
560 pa_assert(conn);
561 pa_assert(msg);
562 pa_assert(u);
564 interface_revision = DBUS_INTERFACE_REVISION;
565 entries = get_entries(u, &n_entries);
567 pa_assert_se((reply = dbus_message_new_method_return(msg)));
569 dbus_message_iter_init_append(reply, &msg_iter);
570 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
572 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INTERFACE_REVISION].property_name, DBUS_TYPE_UINT32, &interface_revision);
573 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ENTRIES].property_name, DBUS_TYPE_OBJECT_PATH, entries, n_entries);
575 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
577 pa_assert_se(dbus_connection_send(conn, reply, NULL));
579 dbus_message_unref(reply);
581 pa_xfree(entries);
584 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata) {
585 struct userdata *u = userdata;
586 DBusMessageIter msg_iter;
587 const char *name = NULL;
588 const char *device = NULL;
589 pa_channel_map map;
590 pa_cvolume vol;
591 dbus_bool_t muted = FALSE;
592 dbus_bool_t apply_immediately = FALSE;
593 pa_datum key;
594 pa_datum value;
595 struct dbus_entry *dbus_entry = NULL;
596 struct entry *e = NULL;
598 pa_assert(conn);
599 pa_assert(msg);
600 pa_assert(u);
602 pa_assert_se(dbus_message_iter_init(msg, &msg_iter));
603 dbus_message_iter_get_basic(&msg_iter, &name);
605 pa_assert_se(dbus_message_iter_next(&msg_iter));
606 dbus_message_iter_get_basic(&msg_iter, &device);
608 pa_assert_se(dbus_message_iter_next(&msg_iter));
609 if (get_volume_arg(conn, msg, &msg_iter, &map, &vol) < 0)
610 return;
612 dbus_message_iter_get_basic(&msg_iter, &muted);
614 pa_assert_se(dbus_message_iter_next(&msg_iter));
615 dbus_message_iter_get_basic(&msg_iter, &apply_immediately);
617 if (!*name) {
618 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "An empty string was given as the entry name.");
619 return;
622 if ((dbus_entry = pa_hashmap_get(u->dbus_entries, name))) {
623 pa_bool_t mute_updated = FALSE;
624 pa_bool_t volume_updated = FALSE;
625 pa_bool_t device_updated = FALSE;
627 pa_assert_se(e = read_entry(u, name));
628 mute_updated = e->muted != muted;
629 e->muted = muted;
630 e->muted_valid = TRUE;
632 volume_updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
633 e->volume = vol;
634 e->channel_map = map;
635 e->volume_valid = !!map.channels;
637 device_updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
638 pa_strlcpy(e->device, device, sizeof(e->device));
639 e->device_valid = !!device[0];
641 if (mute_updated)
642 send_mute_updated_signal(dbus_entry, e);
643 if (volume_updated)
644 send_volume_updated_signal(dbus_entry, e);
645 if (device_updated)
646 send_device_updated_signal(dbus_entry, e);
648 } else {
649 dbus_entry = dbus_entry_new(u, name);
650 pa_assert_se(pa_hashmap_put(u->dbus_entries, dbus_entry->entry_name, dbus_entry) == 0);
652 e->muted_valid = TRUE;
653 e->volume_valid = !!map.channels;
654 e->device_valid = !!device[0];
655 e->muted = muted;
656 e->volume = vol;
657 e->channel_map = map;
658 pa_strlcpy(e->device, device, sizeof(e->device));
660 send_new_entry_signal(dbus_entry);
663 key.data = (char *) name;
664 key.size = strlen(name);
666 value.data = e;
667 value.size = sizeof(struct entry);
669 pa_assert_se(pa_database_set(u->database, &key, &value, TRUE) == 0);
670 if (apply_immediately)
671 apply_entry(u, name, e);
673 trigger_save(u);
675 pa_dbus_send_empty_reply(conn, msg);
677 pa_xfree(e);
680 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
681 struct userdata *u = userdata;
682 const char *name;
683 struct dbus_entry *de;
685 pa_assert(conn);
686 pa_assert(msg);
687 pa_assert(u);
689 pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID));
691 if (!(de = pa_hashmap_get(u->dbus_entries, name))) {
692 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such stream restore entry.");
693 return;
696 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &de->object_path);
699 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) {
700 struct dbus_entry *de = userdata;
702 pa_assert(conn);
703 pa_assert(msg);
704 pa_assert(de);
706 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &de->index);
709 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
710 struct dbus_entry *de = userdata;
712 pa_assert(conn);
713 pa_assert(msg);
714 pa_assert(de);
716 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &de->entry_name);
719 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
720 struct dbus_entry *de = userdata;
721 struct entry *e;
722 const char *device;
724 pa_assert(conn);
725 pa_assert(msg);
726 pa_assert(de);
728 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
730 device = e->device_valid ? e->device : "";
732 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &device);
734 pa_xfree(e);
737 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
738 struct dbus_entry *de = userdata;
739 const char *device;
740 struct entry *e;
741 pa_bool_t updated;
743 pa_assert(conn);
744 pa_assert(msg);
745 pa_assert(iter);
746 pa_assert(de);
748 dbus_message_iter_get_basic(iter, &device);
750 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
752 updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
754 if (updated) {
755 pa_datum key;
756 pa_datum value;
758 pa_strlcpy(e->device, device, sizeof(e->device));
759 e->device_valid = !!device[0];
761 key.data = de->entry_name;
762 key.size = strlen(de->entry_name);
763 value.data = e;
764 value.size = sizeof(struct entry);
765 pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
767 send_device_updated_signal(de, e);
768 trigger_save(de->userdata);
771 pa_dbus_send_empty_reply(conn, msg);
773 pa_xfree(e);
776 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
777 struct dbus_entry *de = userdata;
778 DBusMessage *reply;
779 DBusMessageIter msg_iter;
780 struct entry *e;
782 pa_assert(conn);
783 pa_assert(msg);
784 pa_assert(de);
786 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
788 pa_assert_se(reply = dbus_message_new_method_return(msg));
790 dbus_message_iter_init_append(reply, &msg_iter);
791 append_volume_variant(&msg_iter, e);
793 pa_assert_se(dbus_connection_send(conn, reply, NULL));
795 pa_xfree(e);
798 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
799 struct dbus_entry *de = userdata;
800 pa_channel_map map;
801 pa_cvolume vol;
802 struct entry *e = NULL;
803 pa_bool_t updated = FALSE;
805 pa_assert(conn);
806 pa_assert(msg);
807 pa_assert(iter);
808 pa_assert(de);
810 if (get_volume_arg(conn, msg, iter, &map, &vol) < 0)
811 return;
813 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
815 updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
817 if (updated) {
818 pa_datum key;
819 pa_datum value;
821 e->volume = vol;
822 e->channel_map = map;
823 e->volume_valid = !!map.channels;
825 key.data = de->entry_name;
826 key.size = strlen(de->entry_name);
827 value.data = e;
828 value.size = sizeof(struct entry);
829 pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
831 send_volume_updated_signal(de, e);
832 trigger_save(de->userdata);
835 pa_dbus_send_empty_reply(conn, msg);
837 pa_xfree(e);
840 static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
841 struct dbus_entry *de = userdata;
842 struct entry *e;
843 dbus_bool_t mute;
845 pa_assert(conn);
846 pa_assert(msg);
847 pa_assert(de);
849 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
851 mute = e->muted_valid ? e->muted : FALSE;
853 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &mute);
855 pa_xfree(e);
858 static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
859 struct dbus_entry *de = userdata;
860 dbus_bool_t mute;
861 struct entry *e;
862 pa_bool_t updated;
864 pa_assert(conn);
865 pa_assert(msg);
866 pa_assert(iter);
867 pa_assert(de);
869 dbus_message_iter_get_basic(iter, &mute);
871 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
873 updated = !e->muted_valid || e->muted != mute;
875 if (updated) {
876 pa_datum key;
877 pa_datum value;
879 e->muted = mute;
880 e->muted_valid = TRUE;
882 key.data = de->entry_name;
883 key.size = strlen(de->entry_name);
884 value.data = e;
885 value.size = sizeof(struct entry);
886 pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
888 send_mute_updated_signal(de, e);
889 trigger_save(de->userdata);
892 pa_dbus_send_empty_reply(conn, msg);
894 pa_xfree(e);
897 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
898 struct dbus_entry *de = userdata;
899 struct entry *e;
900 DBusMessage *reply = NULL;
901 DBusMessageIter msg_iter;
902 DBusMessageIter dict_iter;
903 DBusMessageIter dict_entry_iter;
904 const char *device;
905 dbus_bool_t mute;
907 pa_assert(conn);
908 pa_assert(msg);
909 pa_assert(de);
911 pa_assert_se(e = read_entry(de->userdata, de->entry_name));
913 device = e->device_valid ? e->device : "";
914 mute = e->muted_valid ? e->muted : FALSE;
916 pa_assert_se((reply = dbus_message_new_method_return(msg)));
918 dbus_message_iter_init_append(reply, &msg_iter);
919 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
921 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &de->index);
922 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &de->entry_name);
923 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_STRING, &device);
925 pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter));
927 pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &entry_property_handlers[ENTRY_PROPERTY_HANDLER_VOLUME].property_name));
928 append_volume_variant(&dict_entry_iter, e);
930 pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter));
932 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &mute);
934 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
936 pa_assert_se(dbus_connection_send(conn, reply, NULL));
938 dbus_message_unref(reply);
940 pa_xfree(e);
943 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata) {
944 struct dbus_entry *de = userdata;
945 pa_datum key;
947 pa_assert(conn);
948 pa_assert(msg);
949 pa_assert(de);
951 key.data = de->entry_name;
952 key.size = strlen(de->entry_name);
954 pa_assert_se(pa_database_unset(de->userdata->database, &key) == 0);
956 send_entry_removed_signal(de);
957 trigger_save(de->userdata);
959 pa_assert_se(pa_hashmap_remove(de->userdata->dbus_entries, de->entry_name));
960 dbus_entry_free(de);
962 pa_dbus_send_empty_reply(conn, msg);
965 #endif /* HAVE_DBUS */
967 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
968 struct userdata *u = userdata;
970 pa_assert(a);
971 pa_assert(e);
972 pa_assert(u);
974 pa_assert(e == u->save_time_event);
975 u->core->mainloop->time_free(u->save_time_event);
976 u->save_time_event = NULL;
978 pa_database_sync(u->database);
979 pa_log_info("Synced.");
982 static char *get_name(pa_proplist *p, const char *prefix) {
983 const char *r;
984 char *t;
986 if (!p)
987 return NULL;
989 if ((r = pa_proplist_gets(p, IDENTIFICATION_PROPERTY)))
990 return pa_xstrdup(r);
992 if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE)))
993 t = pa_sprintf_malloc("%s-by-media-role:%s", prefix, r);
994 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_ID)))
995 t = pa_sprintf_malloc("%s-by-application-id:%s", prefix, r);
996 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME)))
997 t = pa_sprintf_malloc("%s-by-application-name:%s", prefix, r);
998 else if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_NAME)))
999 t = pa_sprintf_malloc("%s-by-media-name:%s", prefix, r);
1000 else
1001 t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
1003 pa_proplist_sets(p, IDENTIFICATION_PROPERTY, t);
1004 return t;
1007 static struct entry *read_entry(struct userdata *u, const char *name) {
1008 pa_datum key, data;
1009 struct entry *e;
1011 pa_assert(u);
1012 pa_assert(name);
1014 key.data = (char*) name;
1015 key.size = strlen(name);
1017 pa_zero(data);
1019 if (!pa_database_get(u->database, &key, &data))
1020 goto fail;
1022 if (data.size != sizeof(struct entry)) {
1023 /* This is probably just a database upgrade, hence let's not
1024 * consider this more than a debug message */
1025 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));
1026 goto fail;
1029 e = (struct entry*) data.data;
1031 if (e->version != ENTRY_VERSION) {
1032 pa_log_debug("Version of database entry for stream %s doesn't match our version. Probably due to upgrade, ignoring.", name);
1033 goto fail;
1036 if (!memchr(e->device, 0, sizeof(e->device))) {
1037 pa_log_warn("Database contains entry for stream %s with missing NUL byte in device name", name);
1038 goto fail;
1041 if (!memchr(e->card, 0, sizeof(e->card))) {
1042 pa_log_warn("Database contains entry for stream %s with missing NUL byte in card name", name);
1043 goto fail;
1046 if (e->device_valid && !pa_namereg_is_valid_name(e->device)) {
1047 pa_log_warn("Invalid device name stored in database for stream %s", name);
1048 goto fail;
1051 if (e->card_valid && !pa_namereg_is_valid_name(e->card)) {
1052 pa_log_warn("Invalid card name stored in database for stream %s", name);
1053 goto fail;
1056 if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) {
1057 pa_log_warn("Invalid channel map stored in database for stream %s", name);
1058 goto fail;
1061 if (e->volume_valid && (!pa_cvolume_valid(&e->volume) || !pa_cvolume_compatible_with_channel_map(&e->volume, &e->channel_map))) {
1062 pa_log_warn("Invalid volume stored in database for stream %s", name);
1063 goto fail;
1066 return e;
1068 fail:
1070 pa_datum_free(&data);
1071 return NULL;
1074 static void trigger_save(struct userdata *u) {
1075 pa_native_connection *c;
1076 uint32_t idx;
1078 for (c = pa_idxset_first(u->subscribed, &idx); c; c = pa_idxset_next(u->subscribed, &idx)) {
1079 pa_tagstruct *t;
1081 t = pa_tagstruct_new(NULL, 0);
1082 pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
1083 pa_tagstruct_putu32(t, 0);
1084 pa_tagstruct_putu32(t, u->module->index);
1085 pa_tagstruct_puts(t, u->module->name);
1086 pa_tagstruct_putu32(t, SUBCOMMAND_EVENT);
1088 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
1091 if (u->save_time_event)
1092 return;
1094 u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
1097 static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) {
1098 pa_cvolume t;
1100 pa_assert(a);
1101 pa_assert(b);
1103 if (a->device_valid != b->device_valid ||
1104 (a->device_valid && strncmp(a->device, b->device, sizeof(a->device))))
1105 return FALSE;
1107 if (a->card_valid != b->card_valid ||
1108 (a->card_valid && strncmp(a->card, b->card, sizeof(a->card))))
1109 return FALSE;
1111 if (a->muted_valid != b->muted_valid ||
1112 (a->muted_valid && (a->muted != b->muted)))
1113 return FALSE;
1115 t = b->volume;
1116 if (a->volume_valid != b->volume_valid ||
1117 (a->volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->volume)))
1118 return FALSE;
1120 return TRUE;
1123 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
1124 struct userdata *u = userdata;
1125 struct entry entry, *old = NULL;
1126 char *name = NULL;
1127 pa_datum key, data;
1129 /* These are only used when D-Bus is enabled, but in order to reduce ifdef
1130 * clutter these are defined here unconditionally. */
1131 pa_bool_t created_new_entry = TRUE;
1132 pa_bool_t device_updated = FALSE;
1133 pa_bool_t volume_updated = FALSE;
1134 pa_bool_t mute_updated = FALSE;
1136 #ifdef HAVE_DBUS
1137 struct dbus_entry *de = NULL;
1138 #endif
1140 pa_assert(c);
1141 pa_assert(u);
1143 if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1144 t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
1145 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1146 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
1147 return;
1149 pa_zero(entry);
1150 entry.version = ENTRY_VERSION;
1152 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
1153 pa_sink_input *sink_input;
1155 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx)))
1156 return;
1158 if (!(name = get_name(sink_input->proplist, "sink-input")))
1159 return;
1161 if ((old = read_entry(u, name))) {
1162 entry = *old;
1163 created_new_entry = FALSE;
1166 if (sink_input->save_volume) {
1167 entry.channel_map = sink_input->channel_map;
1168 pa_sink_input_get_volume(sink_input, &entry.volume, FALSE);
1169 entry.volume_valid = TRUE;
1171 volume_updated = !created_new_entry
1172 && (!old->volume_valid
1173 || !pa_channel_map_equal(&entry.channel_map, &old->channel_map)
1174 || !pa_cvolume_equal(&entry.volume, &old->volume));
1177 if (sink_input->save_muted) {
1178 entry.muted = pa_sink_input_get_mute(sink_input);
1179 entry.muted_valid = TRUE;
1181 mute_updated = !created_new_entry && (!old->muted_valid || entry.muted != old->muted);
1184 if (sink_input->save_sink) {
1185 pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device));
1186 entry.device_valid = TRUE;
1188 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry.device, old->device));
1189 if (sink_input->sink->card) {
1190 pa_strlcpy(entry.card, sink_input->sink->card->name, sizeof(entry.card));
1191 entry.card_valid = TRUE;
1195 } else {
1196 pa_source_output *source_output;
1198 pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);
1200 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx)))
1201 return;
1203 if (!(name = get_name(source_output->proplist, "source-output")))
1204 return;
1206 if ((old = read_entry(u, name))) {
1207 entry = *old;
1208 created_new_entry = FALSE;
1211 if (source_output->save_source) {
1212 pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device));
1213 entry.device_valid = source_output->save_source;
1215 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry.device, old->device));
1217 if (source_output->source->card) {
1218 pa_strlcpy(entry.card, source_output->source->card->name, sizeof(entry.card));
1219 entry.card_valid = TRUE;
1224 if (old) {
1226 if (entries_equal(old, &entry)) {
1227 pa_xfree(old);
1228 pa_xfree(name);
1229 return;
1232 pa_xfree(old);
1235 key.data = name;
1236 key.size = strlen(name);
1238 data.data = &entry;
1239 data.size = sizeof(entry);
1241 pa_log_info("Storing volume/mute/device for stream %s.", name);
1243 pa_database_set(u->database, &key, &data, TRUE);
1245 #ifdef HAVE_DBUS
1246 if (created_new_entry) {
1247 de = dbus_entry_new(u, name);
1248 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
1249 send_new_entry_signal(de);
1250 } else {
1251 pa_assert_se(de = pa_hashmap_get(u->dbus_entries, name));
1253 if (device_updated)
1254 send_device_updated_signal(de, &entry);
1255 if (volume_updated)
1256 send_volume_updated_signal(de, &entry);
1257 if (mute_updated)
1258 send_mute_updated_signal(de, &entry);
1260 #endif
1262 pa_xfree(name);
1264 trigger_save(u);
1267 static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1268 char *name;
1269 struct entry *e;
1271 pa_assert(c);
1272 pa_assert(new_data);
1273 pa_assert(u);
1274 pa_assert(u->restore_device);
1276 if (!(name = get_name(new_data->proplist, "sink-input")))
1277 return PA_HOOK_OK;
1279 if (new_data->sink)
1280 pa_log_debug("Not restoring device for stream %s, because already set.", name);
1281 else if ((e = read_entry(u, name))) {
1282 pa_sink *s = NULL;
1284 if (e->device_valid)
1285 s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK);
1287 if (!s && e->card_valid) {
1288 pa_card *card;
1290 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1291 s = pa_idxset_first(card->sinks, NULL);
1294 /* It might happen that a stream and a sink are set up at the
1295 same time, in which case we want to make sure we don't
1296 interfere with that */
1297 if (s && PA_SINK_IS_LINKED(pa_sink_get_state(s))) {
1298 pa_log_info("Restoring device for stream %s.", name);
1299 new_data->sink = s;
1300 new_data->save_sink = TRUE;
1303 pa_xfree(e);
1306 pa_xfree(name);
1308 return PA_HOOK_OK;
1311 static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1312 char *name;
1313 struct entry *e;
1315 pa_assert(c);
1316 pa_assert(new_data);
1317 pa_assert(u);
1318 pa_assert(u->restore_volume || u->restore_muted);
1320 if (!(name = get_name(new_data->proplist, "sink-input")))
1321 return PA_HOOK_OK;
1323 if ((e = read_entry(u, name))) {
1325 if (u->restore_volume && e->volume_valid) {
1327 if (!new_data->volume_is_set) {
1328 pa_cvolume v;
1330 pa_log_info("Restoring volume for sink input %s.", name);
1332 v = e->volume;
1333 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1334 pa_sink_input_new_data_set_volume(new_data, &v);
1336 new_data->volume_is_absolute = FALSE;
1337 new_data->save_volume = TRUE;
1338 } else
1339 pa_log_debug("Not restoring volume for sink input %s, because already set.", name);
1342 if (u->restore_muted && e->muted_valid) {
1344 if (!new_data->muted_is_set) {
1345 pa_log_info("Restoring mute state for sink input %s.", name);
1346 pa_sink_input_new_data_set_muted(new_data, e->muted);
1347 new_data->save_muted = TRUE;
1348 } else
1349 pa_log_debug("Not restoring mute state for sink input %s, because already set.", name);
1352 pa_xfree(e);
1355 pa_xfree(name);
1357 return PA_HOOK_OK;
1360 static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1361 char *name;
1362 struct entry *e;
1364 pa_assert(c);
1365 pa_assert(new_data);
1366 pa_assert(u);
1367 pa_assert(u->restore_device);
1369 if (new_data->direct_on_input)
1370 return PA_HOOK_OK;
1372 if (!(name = get_name(new_data->proplist, "source-output")))
1373 return PA_HOOK_OK;
1375 if (new_data->source)
1376 pa_log_debug("Not restoring device for stream %s, because already set", name);
1377 else if ((e = read_entry(u, name))) {
1378 pa_source *s = NULL;
1380 if (e->device_valid)
1381 s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE);
1383 if (!s && e->card_valid) {
1384 pa_card *card;
1386 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1387 s = pa_idxset_first(card->sources, NULL);
1390 /* It might happen that a stream and a sink are set up at the
1391 same time, in which case we want to make sure we don't
1392 interfere with that */
1393 if (s && PA_SOURCE_IS_LINKED(pa_source_get_state(s))) {
1394 pa_log_info("Restoring device for stream %s.", name);
1395 new_data->source = s;
1396 new_data->save_source = TRUE;
1399 pa_xfree(e);
1402 pa_xfree(name);
1404 return PA_HOOK_OK;
1407 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1408 pa_sink_input *si;
1409 uint32_t idx;
1411 pa_assert(c);
1412 pa_assert(sink);
1413 pa_assert(u);
1414 pa_assert(u->on_hotplug && u->restore_device);
1416 PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
1417 char *name;
1418 struct entry *e;
1420 if (si->sink == sink)
1421 continue;
1423 if (si->save_sink)
1424 continue;
1426 /* Skip this if it is already in the process of being moved
1427 * anyway */
1428 if (!si->sink)
1429 continue;
1431 /* It might happen that a stream and a sink are set up at the
1432 same time, in which case we want to make sure we don't
1433 interfere with that */
1434 if (!PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(si)))
1435 continue;
1437 if (!(name = get_name(si->proplist, "sink-input")))
1438 continue;
1440 if ((e = read_entry(u, name))) {
1441 if (e->device_valid && pa_streq(e->device, sink->name))
1442 pa_sink_input_move_to(si, sink, TRUE);
1444 pa_xfree(e);
1447 pa_xfree(name);
1450 return PA_HOOK_OK;
1453 static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1454 pa_source_output *so;
1455 uint32_t idx;
1457 pa_assert(c);
1458 pa_assert(source);
1459 pa_assert(u);
1460 pa_assert(u->on_hotplug && u->restore_device);
1462 PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
1463 char *name;
1464 struct entry *e;
1466 if (so->source == source)
1467 continue;
1469 if (so->save_source)
1470 continue;
1472 if (so->direct_on_input)
1473 continue;
1475 /* Skip this if it is already in the process of being moved anyway */
1476 if (!so->source)
1477 continue;
1479 /* It might happen that a stream and a source are set up at the
1480 same time, in which case we want to make sure we don't
1481 interfere with that */
1482 if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
1483 continue;
1485 if (!(name = get_name(so->proplist, "source-input")))
1486 continue;
1488 if ((e = read_entry(u, name))) {
1489 if (e->device_valid && pa_streq(e->device, source->name))
1490 pa_source_output_move_to(so, source, TRUE);
1492 pa_xfree(e);
1495 pa_xfree(name);
1498 return PA_HOOK_OK;
1501 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1502 pa_sink_input *si;
1503 uint32_t idx;
1505 pa_assert(c);
1506 pa_assert(sink);
1507 pa_assert(u);
1508 pa_assert(u->on_rescue && u->restore_device);
1510 /* There's no point in doing anything if the core is shut down anyway */
1511 if (c->state == PA_CORE_SHUTDOWN)
1512 return PA_HOOK_OK;
1514 PA_IDXSET_FOREACH(si, sink->inputs, idx) {
1515 char *name;
1516 struct entry *e;
1518 if (!si->sink)
1519 continue;
1521 if (!(name = get_name(si->proplist, "sink-input")))
1522 continue;
1524 if ((e = read_entry(u, name))) {
1526 if (e->device_valid) {
1527 pa_sink *d;
1529 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) &&
1530 d != sink &&
1531 PA_SINK_IS_LINKED(pa_sink_get_state(d)))
1532 pa_sink_input_move_to(si, d, TRUE);
1535 pa_xfree(e);
1538 pa_xfree(name);
1541 return PA_HOOK_OK;
1544 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1545 pa_source_output *so;
1546 uint32_t idx;
1548 pa_assert(c);
1549 pa_assert(source);
1550 pa_assert(u);
1551 pa_assert(u->on_rescue && u->restore_device);
1553 /* There's no point in doing anything if the core is shut down anyway */
1554 if (c->state == PA_CORE_SHUTDOWN)
1555 return PA_HOOK_OK;
1557 PA_IDXSET_FOREACH(so, source->outputs, idx) {
1558 char *name;
1559 struct entry *e;
1561 if (so->direct_on_input)
1562 continue;
1564 if (!so->source)
1565 continue;
1567 if (!(name = get_name(so->proplist, "source-output")))
1568 continue;
1570 if ((e = read_entry(u, name))) {
1572 if (e->device_valid) {
1573 pa_source *d;
1575 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) &&
1576 d != source &&
1577 PA_SOURCE_IS_LINKED(pa_source_get_state(d)))
1578 pa_source_output_move_to(so, d, TRUE);
1581 pa_xfree(e);
1584 pa_xfree(name);
1587 return PA_HOOK_OK;
1590 #define EXT_VERSION 1
1592 static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
1593 pa_sink_input *si;
1594 pa_source_output *so;
1595 uint32_t idx;
1597 pa_assert(u);
1598 pa_assert(name);
1599 pa_assert(e);
1601 PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
1602 char *n;
1603 pa_sink *s;
1605 if (!(n = get_name(si->proplist, "sink-input")))
1606 continue;
1608 if (!pa_streq(name, n)) {
1609 pa_xfree(n);
1610 continue;
1612 pa_xfree(n);
1614 if (u->restore_volume && e->volume_valid) {
1615 pa_cvolume v;
1617 v = e->volume;
1618 pa_log_info("Restoring volume for sink input %s.", name);
1619 pa_cvolume_remap(&v, &e->channel_map, &si->channel_map);
1620 pa_sink_input_set_volume(si, &v, TRUE, FALSE);
1623 if (u->restore_muted && e->muted_valid) {
1624 pa_log_info("Restoring mute state for sink input %s.", name);
1625 pa_sink_input_set_mute(si, e->muted, TRUE);
1628 if (u->restore_device &&
1629 e->device_valid &&
1630 (s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SINK))) {
1632 pa_log_info("Restoring device for stream %s.", name);
1633 pa_sink_input_move_to(si, s, TRUE);
1637 PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
1638 char *n;
1639 pa_source *s;
1641 if (!(n = get_name(so->proplist, "source-output")))
1642 continue;
1644 if (!pa_streq(name, n)) {
1645 pa_xfree(n);
1646 continue;
1648 pa_xfree(n);
1650 if (u->restore_device &&
1651 e->device_valid &&
1652 (s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE))) {
1654 pa_log_info("Restoring device for stream %s.", name);
1655 pa_source_output_move_to(so, s, TRUE);
1660 #if 0
1661 static void dump_database(struct userdata *u) {
1662 pa_datum key;
1663 pa_bool_t done;
1665 done = !pa_database_first(u->database, &key, NULL);
1667 while (!done) {
1668 pa_datum next_key;
1669 struct entry *e;
1670 char *name;
1672 done = !pa_database_next(u->database, &key, &next_key, NULL);
1674 name = pa_xstrndup(key.data, key.size);
1675 pa_datum_free(&key);
1677 if ((e = read_entry(u, name))) {
1678 char t[256];
1679 pa_log("name=%s", name);
1680 pa_log("device=%s %s", e->device, pa_yes_no(e->device_valid));
1681 pa_log("channel_map=%s", pa_channel_map_snprint(t, sizeof(t), &e->channel_map));
1682 pa_log("volume=%s %s", pa_cvolume_snprint(t, sizeof(t), &e->volume), pa_yes_no(e->volume_valid));
1683 pa_log("mute=%s %s", pa_yes_no(e->muted), pa_yes_no(e->volume_valid));
1684 pa_xfree(e);
1687 pa_xfree(name);
1689 key = next_key;
1692 #endif
1694 static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
1695 struct userdata *u;
1696 uint32_t command;
1697 pa_tagstruct *reply = NULL;
1699 pa_assert(p);
1700 pa_assert(m);
1701 pa_assert(c);
1702 pa_assert(t);
1704 u = m->userdata;
1706 if (pa_tagstruct_getu32(t, &command) < 0)
1707 goto fail;
1709 reply = pa_tagstruct_new(NULL, 0);
1710 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1711 pa_tagstruct_putu32(reply, tag);
1713 switch (command) {
1714 case SUBCOMMAND_TEST: {
1715 if (!pa_tagstruct_eof(t))
1716 goto fail;
1718 pa_tagstruct_putu32(reply, EXT_VERSION);
1719 break;
1722 case SUBCOMMAND_READ: {
1723 pa_datum key;
1724 pa_bool_t done;
1726 if (!pa_tagstruct_eof(t))
1727 goto fail;
1729 done = !pa_database_first(u->database, &key, NULL);
1731 while (!done) {
1732 pa_datum next_key;
1733 struct entry *e;
1734 char *name;
1736 done = !pa_database_next(u->database, &key, &next_key, NULL);
1738 name = pa_xstrndup(key.data, key.size);
1739 pa_datum_free(&key);
1741 if ((e = read_entry(u, name))) {
1742 pa_cvolume r;
1743 pa_channel_map cm;
1745 pa_tagstruct_puts(reply, name);
1746 pa_tagstruct_put_channel_map(reply, e->volume_valid ? &e->channel_map : pa_channel_map_init(&cm));
1747 pa_tagstruct_put_cvolume(reply, e->volume_valid ? &e->volume : pa_cvolume_init(&r));
1748 pa_tagstruct_puts(reply, e->device_valid ? e->device : NULL);
1749 pa_tagstruct_put_boolean(reply, e->muted_valid ? e->muted : FALSE);
1751 pa_xfree(e);
1754 pa_xfree(name);
1756 key = next_key;
1759 break;
1762 case SUBCOMMAND_WRITE: {
1763 uint32_t mode;
1764 pa_bool_t apply_immediately = FALSE;
1766 if (pa_tagstruct_getu32(t, &mode) < 0 ||
1767 pa_tagstruct_get_boolean(t, &apply_immediately) < 0)
1768 goto fail;
1770 if (mode != PA_UPDATE_MERGE &&
1771 mode != PA_UPDATE_REPLACE &&
1772 mode != PA_UPDATE_SET)
1773 goto fail;
1775 if (mode == PA_UPDATE_SET) {
1776 #ifdef HAVE_DBUS
1777 struct dbus_entry *de;
1778 void *state = NULL;
1780 PA_HASHMAP_FOREACH(de, u->dbus_entries, state) {
1781 send_entry_removed_signal(de);
1782 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, de->entry_name));
1784 #endif
1785 pa_database_clear(u->database);
1788 while (!pa_tagstruct_eof(t)) {
1789 const char *name, *device;
1790 pa_bool_t muted;
1791 struct entry entry;
1792 pa_datum key, data;
1793 #ifdef HAVE_DBUS
1794 struct entry *old;
1795 #endif
1797 pa_zero(entry);
1798 entry.version = ENTRY_VERSION;
1800 if (pa_tagstruct_gets(t, &name) < 0 ||
1801 pa_tagstruct_get_channel_map(t, &entry.channel_map) ||
1802 pa_tagstruct_get_cvolume(t, &entry.volume) < 0 ||
1803 pa_tagstruct_gets(t, &device) < 0 ||
1804 pa_tagstruct_get_boolean(t, &muted) < 0)
1805 goto fail;
1807 if (!name || !*name)
1808 goto fail;
1810 entry.volume_valid = entry.volume.channels > 0;
1812 if (entry.volume_valid)
1813 if (!pa_cvolume_compatible_with_channel_map(&entry.volume, &entry.channel_map))
1814 goto fail;
1816 entry.muted = muted;
1817 entry.muted_valid = TRUE;
1819 if (device)
1820 pa_strlcpy(entry.device, device, sizeof(entry.device));
1821 entry.device_valid = !!entry.device[0];
1823 if (entry.device_valid &&
1824 !pa_namereg_is_valid_name(entry.device))
1825 goto fail;
1827 #ifdef HAVE_DBUS
1828 old = read_entry(u, name);
1829 #endif
1831 key.data = (char*) name;
1832 key.size = strlen(name);
1834 data.data = &entry;
1835 data.size = sizeof(entry);
1837 pa_log_debug("Client %s changes entry %s.",
1838 pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)),
1839 name);
1841 if (pa_database_set(u->database, &key, &data, mode == PA_UPDATE_REPLACE) == 0) {
1842 #ifdef HAVE_DBUS
1843 struct dbus_entry *de;
1845 if (old) {
1846 pa_assert_se((de = pa_hashmap_get(u->dbus_entries, name)));
1848 if ((old->device_valid != entry.device_valid)
1849 || (entry.device_valid && !pa_streq(entry.device, old->device)))
1850 send_device_updated_signal(de, &entry);
1852 if ((old->volume_valid != entry.volume_valid)
1853 || (entry.volume_valid && (!pa_cvolume_equal(&entry.volume, &old->volume)
1854 || !pa_channel_map_equal(&entry.channel_map, &old->channel_map))))
1855 send_volume_updated_signal(de, &entry);
1857 if (!old->muted_valid || (entry.muted != old->muted))
1858 send_mute_updated_signal(de, &entry);
1860 } else {
1861 de = dbus_entry_new(u, name);
1862 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
1863 send_new_entry_signal(de);
1865 #endif
1867 if (apply_immediately)
1868 apply_entry(u, name, &entry);
1871 #ifdef HAVE_DBUS
1872 if (old)
1873 pa_xfree(old);
1874 #endif
1877 trigger_save(u);
1879 break;
1882 case SUBCOMMAND_DELETE:
1884 while (!pa_tagstruct_eof(t)) {
1885 const char *name;
1886 pa_datum key;
1887 #ifdef HAVE_DBUS
1888 struct dbus_entry *de;
1889 #endif
1891 if (pa_tagstruct_gets(t, &name) < 0)
1892 goto fail;
1894 #ifdef HAVE_DBUS
1895 if ((de = pa_hashmap_get(u->dbus_entries, name))) {
1896 send_entry_removed_signal(de);
1897 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, name));
1899 #endif
1901 key.data = (char*) name;
1902 key.size = strlen(name);
1904 pa_database_unset(u->database, &key);
1907 trigger_save(u);
1909 break;
1911 case SUBCOMMAND_SUBSCRIBE: {
1913 pa_bool_t enabled;
1915 if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
1916 !pa_tagstruct_eof(t))
1917 goto fail;
1919 if (enabled)
1920 pa_idxset_put(u->subscribed, c, NULL);
1921 else
1922 pa_idxset_remove_by_data(u->subscribed, c, NULL);
1924 break;
1927 default:
1928 goto fail;
1931 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
1932 return 0;
1934 fail:
1936 if (reply)
1937 pa_tagstruct_free(reply);
1939 return -1;
1942 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
1943 pa_assert(p);
1944 pa_assert(c);
1945 pa_assert(u);
1947 pa_idxset_remove_by_data(u->subscribed, c, NULL);
1948 return PA_HOOK_OK;
1951 int pa__init(pa_module*m) {
1952 pa_modargs *ma = NULL;
1953 struct userdata *u;
1954 char *fname;
1955 pa_sink_input *si;
1956 pa_source_output *so;
1957 uint32_t idx;
1958 pa_bool_t restore_device = TRUE, restore_volume = TRUE, restore_muted = TRUE, on_hotplug = TRUE, on_rescue = TRUE;
1959 #ifdef HAVE_DBUS
1960 pa_datum key;
1961 pa_bool_t done;
1962 #endif
1964 pa_assert(m);
1966 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1967 pa_log("Failed to parse module arguments");
1968 goto fail;
1971 if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
1972 pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
1973 pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
1974 pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
1975 pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
1976 pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments");
1977 goto fail;
1980 if (!restore_muted && !restore_volume && !restore_device)
1981 pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!");
1983 m->userdata = u = pa_xnew0(struct userdata, 1);
1984 u->core = m->core;
1985 u->module = m;
1986 u->restore_device = restore_device;
1987 u->restore_volume = restore_volume;
1988 u->restore_muted = restore_muted;
1989 u->on_hotplug = on_hotplug;
1990 u->on_rescue = on_rescue;
1991 u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
1993 u->protocol = pa_native_protocol_get(m->core);
1994 pa_native_protocol_install_ext(u->protocol, m, extension_cb);
1996 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);
1998 u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
2000 if (restore_device) {
2001 /* A little bit earlier than module-intended-roles ... */
2002 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);
2003 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);
2006 if (restore_device && on_hotplug) {
2007 /* A little bit earlier than module-intended-roles ... */
2008 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);
2009 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);
2012 if (restore_device && on_rescue) {
2013 /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */
2014 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);
2015 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);
2018 if (restore_volume || restore_muted)
2019 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);
2021 if (!(fname = pa_state_path("stream-volumes", TRUE)))
2022 goto fail;
2024 if (!(u->database = pa_database_open(fname, TRUE))) {
2025 pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
2026 pa_xfree(fname);
2027 goto fail;
2030 pa_log_info("Sucessfully opened database file '%s'.", fname);
2031 pa_xfree(fname);
2033 #ifdef HAVE_DBUS
2034 u->dbus_protocol = pa_dbus_protocol_get(u->core);
2035 u->dbus_entries = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
2037 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, OBJECT_PATH, &stream_restore_interface_info, u) >= 0);
2038 pa_assert_se(pa_dbus_protocol_register_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2040 /* Create the initial dbus entries. */
2041 done = !pa_database_first(u->database, &key, NULL);
2042 while (!done) {
2043 pa_datum next_key;
2044 char *name;
2045 struct dbus_entry *de;
2047 done = !pa_database_next(u->database, &key, &next_key, NULL);
2049 name = pa_xstrndup(key.data, key.size);
2050 pa_datum_free(&key);
2052 de = dbus_entry_new(u, name);
2053 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
2055 pa_xfree(name);
2057 key = next_key;
2059 #endif
2061 PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx)
2062 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u);
2064 PA_IDXSET_FOREACH(so, m->core->source_outputs, idx)
2065 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, so->index, u);
2067 pa_modargs_free(ma);
2068 return 0;
2070 fail:
2071 pa__done(m);
2073 if (ma)
2074 pa_modargs_free(ma);
2076 return -1;
2079 #ifdef HAVE_DBUS
2080 static void free_dbus_entry_cb(void *p, void *userdata) {
2081 struct dbus_entry *de = p;
2083 pa_assert(de);
2085 dbus_entry_free(de);
2087 #endif
2089 void pa__done(pa_module*m) {
2090 struct userdata* u;
2092 pa_assert(m);
2094 if (!(u = m->userdata))
2095 return;
2097 #ifdef HAVE_DBUS
2098 if (u->dbus_protocol) {
2099 pa_assert(u->dbus_entries);
2101 pa_assert_se(pa_dbus_protocol_unregister_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2102 pa_assert_se(pa_dbus_protocol_remove_interface(u->dbus_protocol, OBJECT_PATH, stream_restore_interface_info.name) >= 0);
2104 pa_hashmap_free(u->dbus_entries, free_dbus_entry_cb, NULL);
2106 pa_dbus_protocol_unref(u->dbus_protocol);
2108 #endif
2110 if (u->subscription)
2111 pa_subscription_free(u->subscription);
2113 if (u->sink_input_new_hook_slot)
2114 pa_hook_slot_free(u->sink_input_new_hook_slot);
2115 if (u->sink_input_fixate_hook_slot)
2116 pa_hook_slot_free(u->sink_input_fixate_hook_slot);
2117 if (u->source_output_new_hook_slot)
2118 pa_hook_slot_free(u->source_output_new_hook_slot);
2120 if (u->sink_put_hook_slot)
2121 pa_hook_slot_free(u->sink_put_hook_slot);
2122 if (u->source_put_hook_slot)
2123 pa_hook_slot_free(u->source_put_hook_slot);
2125 if (u->sink_unlink_hook_slot)
2126 pa_hook_slot_free(u->sink_unlink_hook_slot);
2127 if (u->source_unlink_hook_slot)
2128 pa_hook_slot_free(u->source_unlink_hook_slot);
2130 if (u->connection_unlink_hook_slot)
2131 pa_hook_slot_free(u->connection_unlink_hook_slot);
2133 if (u->save_time_event)
2134 u->core->mainloop->time_free(u->save_time_event);
2136 if (u->database)
2137 pa_database_close(u->database);
2139 if (u->protocol) {
2140 pa_native_protocol_remove_ext(u->protocol, m);
2141 pa_native_protocol_unref(u->protocol);
2144 if (u->subscribed)
2145 pa_idxset_free(u->subscribed, NULL, NULL);
2147 pa_xfree(u);