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
30 #include <sys/types.h>
34 #include <pulse/gccmacro.h>
35 #include <pulse/xmalloc.h>
36 #include <pulse/volume.h>
37 #include <pulse/timeval.h>
38 #include <pulse/rtclock.h>
40 #include <pulsecore/core-error.h>
41 #include <pulsecore/module.h>
42 #include <pulsecore/core-util.h>
43 #include <pulsecore/modargs.h>
44 #include <pulsecore/log.h>
45 #include <pulsecore/core-subscribe.h>
46 #include <pulsecore/sink-input.h>
47 #include <pulsecore/source-output.h>
48 #include <pulsecore/namereg.h>
49 #include <pulsecore/protocol-native.h>
50 #include <pulsecore/pstream.h>
51 #include <pulsecore/pstream-util.h>
52 #include <pulsecore/database.h>
53 #include <pulsecore/tagstruct.h>
54 #include <pulsecore/proplist-util.h>
57 #include <pulsecore/dbus-util.h>
58 #include <pulsecore/protocol-dbus.h>
61 #include "module-stream-restore-symdef.h"
63 PA_MODULE_AUTHOR("Lennart Poettering");
64 PA_MODULE_DESCRIPTION("Automatically restore the volume/mute/device state of streams");
65 PA_MODULE_VERSION(PACKAGE_VERSION);
66 PA_MODULE_LOAD_ONCE(true);
68 "restore_device=<Save/restore sinks/sources?> "
69 "restore_volume=<Save/restore volumes?> "
70 "restore_muted=<Save/restore muted states?> "
71 "on_hotplug=<When new device becomes available, recheck streams?> "
72 "on_rescue=<When device becomes unavailable, recheck streams?> "
73 "fallback_table=<filename>");
75 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
76 #define IDENTIFICATION_PROPERTY "module-stream-restore.id"
78 #define DEFAULT_FALLBACK_FILE PA_DEFAULT_CONFIG_DIR"/stream-restore.table"
79 #define DEFAULT_FALLBACK_FILE_USER "stream-restore.table"
81 #define WHITESPACE "\n\r \t"
83 static const char* const valid_modargs[] = {
96 pa_subscription *subscription;
98 *sink_input_new_hook_slot,
99 *sink_input_fixate_hook_slot,
100 *source_output_new_hook_slot,
101 *source_output_fixate_hook_slot,
103 *source_put_hook_slot,
104 *sink_unlink_hook_slot,
105 *source_unlink_hook_slot,
106 *connection_unlink_hook_slot;
107 pa_time_event *save_time_event;
108 pa_database* database;
110 bool restore_device:1;
111 bool restore_volume:1;
112 bool restore_muted:1;
116 pa_native_protocol *protocol;
117 pa_idxset *subscribed;
120 pa_dbus_protocol *dbus_protocol;
121 pa_hashmap *dbus_entries;
122 uint32_t next_index; /* For generating object paths for entries. */
126 #define ENTRY_VERSION 1
130 bool muted_valid, volume_valid, device_valid, card_valid;
132 pa_channel_map channel_map;
143 SUBCOMMAND_SUBSCRIBE,
147 static struct entry* entry_new(void);
148 static void entry_free(struct entry *e);
149 static struct entry *entry_read(struct userdata *u, const char *name);
150 static bool entry_write(struct userdata *u, const char *name, const struct entry *e, bool replace);
151 static struct entry* entry_copy(const struct entry *e);
152 static void entry_apply(struct userdata *u, const char *name, struct entry *e);
153 static void trigger_save(struct userdata *u);
157 #define OBJECT_PATH "/org/pulseaudio/stream_restore1"
158 #define ENTRY_OBJECT_NAME "entry"
159 #define INTERFACE_STREAM_RESTORE "org.PulseAudio.Ext.StreamRestore1"
160 #define INTERFACE_ENTRY INTERFACE_STREAM_RESTORE ".RestoreEntry"
162 #define DBUS_INTERFACE_REVISION 0
165 struct userdata *userdata;
172 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata);
173 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata);
175 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
177 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata);
178 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
180 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata);
181 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
182 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
183 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
184 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
185 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
186 static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
187 static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
189 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
191 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata);
193 enum property_handler_index {
194 PROPERTY_HANDLER_INTERFACE_REVISION,
195 PROPERTY_HANDLER_ENTRIES,
199 enum entry_property_handler_index {
200 ENTRY_PROPERTY_HANDLER_INDEX,
201 ENTRY_PROPERTY_HANDLER_NAME,
202 ENTRY_PROPERTY_HANDLER_DEVICE,
203 ENTRY_PROPERTY_HANDLER_VOLUME,
204 ENTRY_PROPERTY_HANDLER_MUTE,
205 ENTRY_PROPERTY_HANDLER_MAX
208 static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = {
209 [PROPERTY_HANDLER_INTERFACE_REVISION] = { .property_name = "InterfaceRevision", .type = "u", .get_cb = handle_get_interface_revision, .set_cb = NULL },
210 [PROPERTY_HANDLER_ENTRIES] = { .property_name = "Entries", .type = "ao", .get_cb = handle_get_entries, .set_cb = NULL }
213 static pa_dbus_property_handler entry_property_handlers[ENTRY_PROPERTY_HANDLER_MAX] = {
214 [ENTRY_PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_entry_get_index, .set_cb = NULL },
215 [ENTRY_PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_entry_get_name, .set_cb = NULL },
216 [ENTRY_PROPERTY_HANDLER_DEVICE] = { .property_name = "Device", .type = "s", .get_cb = handle_entry_get_device, .set_cb = handle_entry_set_device },
217 [ENTRY_PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "a(uu)", .get_cb = handle_entry_get_volume, .set_cb = handle_entry_set_volume },
218 [ENTRY_PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_entry_get_mute, .set_cb = handle_entry_set_mute }
221 enum method_handler_index {
222 METHOD_HANDLER_ADD_ENTRY,
223 METHOD_HANDLER_GET_ENTRY_BY_NAME,
227 enum entry_method_handler_index {
228 ENTRY_METHOD_HANDLER_REMOVE,
229 ENTRY_METHOD_HANDLER_MAX
232 static pa_dbus_arg_info add_entry_args[] = { { "name", "s", "in" },
233 { "device", "s", "in" },
234 { "volume", "a(uu)", "in" },
235 { "mute", "b", "in" },
236 { "apply_immediately", "b", "in" },
237 { "entry", "o", "out" } };
238 static pa_dbus_arg_info get_entry_by_name_args[] = { { "name", "s", "in" }, { "entry", "o", "out" } };
240 static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
241 [METHOD_HANDLER_ADD_ENTRY] = {
242 .method_name = "AddEntry",
243 .arguments = add_entry_args,
244 .n_arguments = sizeof(add_entry_args) / sizeof(pa_dbus_arg_info),
245 .receive_cb = handle_add_entry },
246 [METHOD_HANDLER_GET_ENTRY_BY_NAME] = {
247 .method_name = "GetEntryByName",
248 .arguments = get_entry_by_name_args,
249 .n_arguments = sizeof(get_entry_by_name_args) / sizeof(pa_dbus_arg_info),
250 .receive_cb = handle_get_entry_by_name }
253 static pa_dbus_method_handler entry_method_handlers[ENTRY_METHOD_HANDLER_MAX] = {
254 [ENTRY_METHOD_HANDLER_REMOVE] = {
255 .method_name = "Remove",
258 .receive_cb = handle_entry_remove }
263 SIGNAL_ENTRY_REMOVED,
267 enum entry_signal_index {
268 ENTRY_SIGNAL_DEVICE_UPDATED,
269 ENTRY_SIGNAL_VOLUME_UPDATED,
270 ENTRY_SIGNAL_MUTE_UPDATED,
274 static pa_dbus_arg_info new_entry_args[] = { { "entry", "o", NULL } };
275 static pa_dbus_arg_info entry_removed_args[] = { { "entry", "o", NULL } };
277 static pa_dbus_arg_info entry_device_updated_args[] = { { "device", "s", NULL } };
278 static pa_dbus_arg_info entry_volume_updated_args[] = { { "volume", "a(uu)", NULL } };
279 static pa_dbus_arg_info entry_mute_updated_args[] = { { "muted", "b", NULL } };
281 static pa_dbus_signal_info signals[SIGNAL_MAX] = {
282 [SIGNAL_NEW_ENTRY] = { .name = "NewEntry", .arguments = new_entry_args, .n_arguments = 1 },
283 [SIGNAL_ENTRY_REMOVED] = { .name = "EntryRemoved", .arguments = entry_removed_args, .n_arguments = 1 }
286 static pa_dbus_signal_info entry_signals[ENTRY_SIGNAL_MAX] = {
287 [ENTRY_SIGNAL_DEVICE_UPDATED] = { .name = "DeviceUpdated", .arguments = entry_device_updated_args, .n_arguments = 1 },
288 [ENTRY_SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = entry_volume_updated_args, .n_arguments = 1 },
289 [ENTRY_SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = entry_mute_updated_args, .n_arguments = 1 }
292 static pa_dbus_interface_info stream_restore_interface_info = {
293 .name = INTERFACE_STREAM_RESTORE,
294 .method_handlers = method_handlers,
295 .n_method_handlers = METHOD_HANDLER_MAX,
296 .property_handlers = property_handlers,
297 .n_property_handlers = PROPERTY_HANDLER_MAX,
298 .get_all_properties_cb = handle_get_all,
300 .n_signals = SIGNAL_MAX
303 static pa_dbus_interface_info entry_interface_info = {
304 .name = INTERFACE_ENTRY,
305 .method_handlers = entry_method_handlers,
306 .n_method_handlers = ENTRY_METHOD_HANDLER_MAX,
307 .property_handlers = entry_property_handlers,
308 .n_property_handlers = ENTRY_PROPERTY_HANDLER_MAX,
309 .get_all_properties_cb = handle_entry_get_all,
310 .signals = entry_signals,
311 .n_signals = ENTRY_SIGNAL_MAX
314 static struct dbus_entry *dbus_entry_new(struct userdata *u, const char *entry_name) {
315 struct dbus_entry *de;
318 pa_assert(entry_name);
319 pa_assert(*entry_name);
321 de = pa_xnew(struct dbus_entry, 1);
323 de->entry_name = pa_xstrdup(entry_name);
324 de->index = u->next_index++;
325 de->object_path = pa_sprintf_malloc("%s/%s%u", OBJECT_PATH, ENTRY_OBJECT_NAME, de->index);
327 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, de->object_path, &entry_interface_info, de) >= 0);
332 static void dbus_entry_free(struct dbus_entry *de) {
335 pa_assert_se(pa_dbus_protocol_remove_interface(de->userdata->dbus_protocol, de->object_path, entry_interface_info.name) >= 0);
337 pa_xfree(de->entry_name);
338 pa_xfree(de->object_path);
342 /* Reads an array [(UInt32, UInt32)] from the iterator. The struct items are
343 * are a channel position and a volume value, respectively. The result is
344 * stored in the map and vol arguments. The iterator must point to a "a(uu)"
345 * element. If the data is invalid, an error reply is sent and a negative
346 * number is returned. In case of a failure we make no guarantees about the
347 * state of map and vol. In case of an empty array the channels field of both
348 * map and vol are set to 0. This function calls dbus_message_iter_next(iter)
349 * before returning. */
350 static int get_volume_arg(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, pa_channel_map *map, pa_cvolume *vol) {
351 DBusMessageIter array_iter;
352 DBusMessageIter struct_iter;
357 pa_assert(pa_streq(dbus_message_iter_get_signature(iter), "a(uu)"));
361 pa_channel_map_init(map);
362 pa_cvolume_init(vol);
367 dbus_message_iter_recurse(iter, &array_iter);
369 while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
370 dbus_uint32_t chan_pos;
371 dbus_uint32_t chan_vol;
373 dbus_message_iter_recurse(&array_iter, &struct_iter);
375 dbus_message_iter_get_basic(&struct_iter, &chan_pos);
377 if (chan_pos >= PA_CHANNEL_POSITION_MAX) {
378 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position: %u", chan_pos);
382 pa_assert_se(dbus_message_iter_next(&struct_iter));
383 dbus_message_iter_get_basic(&struct_iter, &chan_vol);
385 if (!PA_VOLUME_IS_VALID(chan_vol)) {
386 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u", chan_vol);
390 if (map->channels < PA_CHANNELS_MAX) {
391 map->map[map->channels] = chan_pos;
392 vol->values[map->channels] = chan_vol;
397 dbus_message_iter_next(&array_iter);
400 if (map->channels > PA_CHANNELS_MAX) {
401 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too many channels: %u. The maximum is %u.", map->channels, PA_CHANNELS_MAX);
405 dbus_message_iter_next(iter);
410 static void append_volume(DBusMessageIter *iter, struct entry *e) {
411 DBusMessageIter array_iter;
412 DBusMessageIter struct_iter;
418 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(uu)", &array_iter));
420 if (!e->volume_valid) {
421 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
425 for (i = 0; i < e->channel_map.channels; ++i) {
426 pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter));
428 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->channel_map.map[i]));
429 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->volume.values[i]));
431 pa_assert_se(dbus_message_iter_close_container(&array_iter, &struct_iter));
434 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
437 static void append_volume_variant(DBusMessageIter *iter, struct entry *e) {
438 DBusMessageIter variant_iter;
443 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(uu)", &variant_iter));
445 append_volume(&variant_iter, e);
447 pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter));
450 static void send_new_entry_signal(struct dbus_entry *entry) {
451 DBusMessage *signal_msg;
455 pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name));
456 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
457 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg);
458 dbus_message_unref(signal_msg);
461 static void send_entry_removed_signal(struct dbus_entry *entry) {
462 DBusMessage *signal_msg;
466 pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name));
467 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
468 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg);
469 dbus_message_unref(signal_msg);
472 static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) {
473 DBusMessage *signal_msg;
479 device = e->device_valid ? e->device : "";
481 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name));
482 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID));
483 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
484 dbus_message_unref(signal_msg);
487 static void send_volume_updated_signal(struct dbus_entry *de, struct entry *e) {
488 DBusMessage *signal_msg;
489 DBusMessageIter msg_iter;
494 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name));
495 dbus_message_iter_init_append(signal_msg, &msg_iter);
496 append_volume(&msg_iter, e);
497 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
498 dbus_message_unref(signal_msg);
501 static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) {
502 DBusMessage *signal_msg;
508 pa_assert(e->muted_valid);
512 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name));
513 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID));
514 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
515 dbus_message_unref(signal_msg);
518 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) {
519 dbus_uint32_t interface_revision = DBUS_INTERFACE_REVISION;
524 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &interface_revision);
527 /* The caller frees the array, but not the strings. */
528 static const char **get_entries(struct userdata *u, unsigned *n) {
529 const char **entries;
532 struct dbus_entry *de;
537 *n = pa_hashmap_size(u->dbus_entries);
542 entries = pa_xnew(const char *, *n);
544 PA_HASHMAP_FOREACH(de, u->dbus_entries, state)
545 entries[i++] = de->object_path;
550 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata) {
551 struct userdata *u = userdata;
552 const char **entries;
559 entries = get_entries(u, &n);
561 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, entries, n);
566 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
567 struct userdata *u = userdata;
568 DBusMessage *reply = NULL;
569 DBusMessageIter msg_iter;
570 DBusMessageIter dict_iter;
571 dbus_uint32_t interface_revision;
572 const char **entries;
579 interface_revision = DBUS_INTERFACE_REVISION;
580 entries = get_entries(u, &n_entries);
582 pa_assert_se((reply = dbus_message_new_method_return(msg)));
584 dbus_message_iter_init_append(reply, &msg_iter);
585 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
587 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INTERFACE_REVISION].property_name, DBUS_TYPE_UINT32, &interface_revision);
588 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ENTRIES].property_name, DBUS_TYPE_OBJECT_PATH, entries, n_entries);
590 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
592 pa_assert_se(dbus_connection_send(conn, reply, NULL));
594 dbus_message_unref(reply);
599 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata) {
600 struct userdata *u = userdata;
601 DBusMessageIter msg_iter;
602 const char *name = NULL;
603 const char *device = NULL;
606 dbus_bool_t muted = FALSE;
607 dbus_bool_t apply_immediately = FALSE;
608 struct dbus_entry *dbus_entry = NULL;
609 struct entry *e = NULL;
615 pa_assert_se(dbus_message_iter_init(msg, &msg_iter));
616 dbus_message_iter_get_basic(&msg_iter, &name);
618 pa_assert_se(dbus_message_iter_next(&msg_iter));
619 dbus_message_iter_get_basic(&msg_iter, &device);
621 pa_assert_se(dbus_message_iter_next(&msg_iter));
622 if (get_volume_arg(conn, msg, &msg_iter, &map, &vol) < 0)
625 dbus_message_iter_get_basic(&msg_iter, &muted);
627 pa_assert_se(dbus_message_iter_next(&msg_iter));
628 dbus_message_iter_get_basic(&msg_iter, &apply_immediately);
631 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "An empty string was given as the entry name.");
635 if ((dbus_entry = pa_hashmap_get(u->dbus_entries, name))) {
636 bool mute_updated = false;
637 bool volume_updated = false;
638 bool device_updated = false;
640 pa_assert_se(e = entry_read(u, name));
641 mute_updated = e->muted != muted;
643 e->muted_valid = true;
645 volume_updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
647 e->channel_map = map;
648 e->volume_valid = !!map.channels;
650 device_updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
652 e->device = pa_xstrdup(device);
653 e->device_valid = !!device[0];
656 send_mute_updated_signal(dbus_entry, e);
658 send_volume_updated_signal(dbus_entry, e);
660 send_device_updated_signal(dbus_entry, e);
663 dbus_entry = dbus_entry_new(u, name);
664 pa_assert_se(pa_hashmap_put(u->dbus_entries, dbus_entry->entry_name, dbus_entry) == 0);
667 e->muted_valid = true;
668 e->volume_valid = !!map.channels;
669 e->device_valid = !!device[0];
672 e->channel_map = map;
673 e->device = pa_xstrdup(device);
675 send_new_entry_signal(dbus_entry);
678 pa_assert_se(entry_write(u, name, e, true));
680 if (apply_immediately)
681 entry_apply(u, name, e);
685 pa_dbus_send_empty_reply(conn, msg);
690 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
691 struct userdata *u = userdata;
693 struct dbus_entry *de;
699 pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID));
701 if (!(de = pa_hashmap_get(u->dbus_entries, name))) {
702 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such stream restore entry.");
706 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &de->object_path);
709 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) {
710 struct dbus_entry *de = userdata;
716 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &de->index);
719 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
720 struct dbus_entry *de = userdata;
726 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &de->entry_name);
729 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
730 struct dbus_entry *de = userdata;
738 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
740 device = e->device_valid ? e->device : "";
742 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &device);
747 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
748 struct dbus_entry *de = userdata;
758 dbus_message_iter_get_basic(iter, &device);
760 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
762 updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
766 e->device = pa_xstrdup(device);
767 e->device_valid = !!device[0];
769 pa_assert_se(entry_write(de->userdata, de->entry_name, e, true));
771 entry_apply(de->userdata, de->entry_name, e);
772 send_device_updated_signal(de, e);
773 trigger_save(de->userdata);
776 pa_dbus_send_empty_reply(conn, msg);
781 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
782 struct dbus_entry *de = userdata;
784 DBusMessageIter msg_iter;
791 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
793 pa_assert_se(reply = dbus_message_new_method_return(msg));
795 dbus_message_iter_init_append(reply, &msg_iter);
796 append_volume_variant(&msg_iter, e);
798 pa_assert_se(dbus_connection_send(conn, reply, NULL));
803 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
804 struct dbus_entry *de = userdata;
807 struct entry *e = NULL;
808 bool updated = false;
815 if (get_volume_arg(conn, msg, iter, &map, &vol) < 0)
818 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
820 updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
824 e->channel_map = map;
825 e->volume_valid = !!map.channels;
827 pa_assert_se(entry_write(de->userdata, de->entry_name, e, true));
829 entry_apply(de->userdata, de->entry_name, e);
830 send_volume_updated_signal(de, e);
831 trigger_save(de->userdata);
834 pa_dbus_send_empty_reply(conn, msg);
839 static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
840 struct dbus_entry *de = userdata;
848 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
850 mute = e->muted_valid ? e->muted : FALSE;
852 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &mute);
857 static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
858 struct dbus_entry *de = userdata;
868 dbus_message_iter_get_basic(iter, &mute);
870 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
872 updated = !e->muted_valid || e->muted != mute;
876 e->muted_valid = true;
878 pa_assert_se(entry_write(de->userdata, de->entry_name, e, true));
880 entry_apply(de->userdata, de->entry_name, e);
881 send_mute_updated_signal(de, e);
882 trigger_save(de->userdata);
885 pa_dbus_send_empty_reply(conn, msg);
890 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
891 struct dbus_entry *de = userdata;
893 DBusMessage *reply = NULL;
894 DBusMessageIter msg_iter;
895 DBusMessageIter dict_iter;
896 DBusMessageIter dict_entry_iter;
904 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
906 device = e->device_valid ? e->device : "";
907 mute = e->muted_valid ? e->muted : FALSE;
909 pa_assert_se((reply = dbus_message_new_method_return(msg)));
911 dbus_message_iter_init_append(reply, &msg_iter);
912 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
914 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &de->index);
915 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &de->entry_name);
916 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_STRING, &device);
918 pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter));
920 pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &entry_property_handlers[ENTRY_PROPERTY_HANDLER_VOLUME].property_name));
921 append_volume_variant(&dict_entry_iter, e);
923 pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter));
925 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &mute);
927 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
929 pa_assert_se(dbus_connection_send(conn, reply, NULL));
931 dbus_message_unref(reply);
936 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata) {
937 struct dbus_entry *de = userdata;
944 key.data = de->entry_name;
945 key.size = strlen(de->entry_name);
947 pa_assert_se(pa_database_unset(de->userdata->database, &key) == 0);
949 send_entry_removed_signal(de);
950 trigger_save(de->userdata);
952 pa_assert_se(pa_hashmap_remove(de->userdata->dbus_entries, de->entry_name));
955 pa_dbus_send_empty_reply(conn, msg);
958 #endif /* HAVE_DBUS */
960 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
961 struct userdata *u = userdata;
967 pa_assert(e == u->save_time_event);
968 u->core->mainloop->time_free(u->save_time_event);
969 u->save_time_event = NULL;
971 pa_database_sync(u->database);
972 pa_log_info("Synced.");
975 static struct entry* entry_new(void) {
976 struct entry *r = pa_xnew0(struct entry, 1);
977 r->version = ENTRY_VERSION;
981 static void entry_free(struct entry* e) {
989 static bool entry_write(struct userdata *u, const char *name, const struct entry *e, bool replace) {
998 t = pa_tagstruct_new(NULL, 0);
999 pa_tagstruct_putu8(t, e->version);
1000 pa_tagstruct_put_boolean(t, e->volume_valid);
1001 pa_tagstruct_put_channel_map(t, &e->channel_map);
1002 pa_tagstruct_put_cvolume(t, &e->volume);
1003 pa_tagstruct_put_boolean(t, e->muted_valid);
1004 pa_tagstruct_put_boolean(t, e->muted);
1005 pa_tagstruct_put_boolean(t, e->device_valid);
1006 pa_tagstruct_puts(t, e->device);
1007 pa_tagstruct_put_boolean(t, e->card_valid);
1008 pa_tagstruct_puts(t, e->card);
1010 key.data = (char *) name;
1011 key.size = strlen(name);
1013 data.data = (void*)pa_tagstruct_data(t, &data.size);
1015 r = (pa_database_set(u->database, &key, &data, replace) == 0);
1017 pa_tagstruct_free(t);
1022 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
1024 #define LEGACY_ENTRY_VERSION 3
1025 static struct entry *legacy_entry_read(struct userdata *u, const char *name) {
1026 struct legacy_entry {
1028 bool muted_valid:1, volume_valid:1, device_valid:1, card_valid:1;
1030 pa_channel_map channel_map;
1032 char device[PA_NAME_MAX];
1033 char card[PA_NAME_MAX];
1038 struct legacy_entry *le;
1044 key.data = (char *) name;
1045 key.size = strlen(name);
1049 if (!pa_database_get(u->database, &key, &data))
1052 if (data.size != sizeof(struct legacy_entry)) {
1053 pa_log_debug("Size does not match.");
1057 le = (struct legacy_entry *) data.data;
1059 if (le->version != LEGACY_ENTRY_VERSION) {
1060 pa_log_debug("Version mismatch.");
1064 if (!memchr(le->device, 0, sizeof(le->device))) {
1065 pa_log_warn("Device has missing NUL byte.");
1069 if (!memchr(le->card, 0, sizeof(le->card))) {
1070 pa_log_warn("Card has missing NUL byte.");
1074 if (le->device_valid && !pa_namereg_is_valid_name(le->device)) {
1075 pa_log_warn("Invalid device name stored in database for legacy stream");
1079 if (le->card_valid && !pa_namereg_is_valid_name(le->card)) {
1080 pa_log_warn("Invalid card name stored in database for legacy stream");
1084 if (le->volume_valid && !pa_channel_map_valid(&le->channel_map)) {
1085 pa_log_warn("Invalid channel map stored in database for legacy stream");
1089 if (le->volume_valid && (!pa_cvolume_valid(&le->volume) || !pa_cvolume_compatible_with_channel_map(&le->volume, &le->channel_map))) {
1090 pa_log_warn("Invalid volume stored in database for legacy stream");
1095 e->muted_valid = le->muted_valid;
1096 e->muted = le->muted;
1097 e->volume_valid = le->volume_valid;
1098 e->channel_map = le->channel_map;
1099 e->volume = le->volume;
1100 e->device_valid = le->device_valid;
1101 e->device = pa_xstrdup(le->device);
1102 e->card_valid = le->card_valid;
1103 e->card = pa_xstrdup(le->card);
1107 pa_datum_free(&data);
1113 static struct entry *entry_read(struct userdata *u, const char *name) {
1115 struct entry *e = NULL;
1116 pa_tagstruct *t = NULL;
1117 const char *device, *card;
1122 key.data = (char*) name;
1123 key.size = strlen(name);
1127 if (!pa_database_get(u->database, &key, &data))
1130 t = pa_tagstruct_new(data.data, data.size);
1133 if (pa_tagstruct_getu8(t, &e->version) < 0 ||
1134 e->version > ENTRY_VERSION ||
1135 pa_tagstruct_get_boolean(t, &e->volume_valid) < 0 ||
1136 pa_tagstruct_get_channel_map(t, &e->channel_map) < 0 ||
1137 pa_tagstruct_get_cvolume(t, &e->volume) < 0 ||
1138 pa_tagstruct_get_boolean(t, &e->muted_valid) < 0 ||
1139 pa_tagstruct_get_boolean(t, &e->muted) < 0 ||
1140 pa_tagstruct_get_boolean(t, &e->device_valid) < 0 ||
1141 pa_tagstruct_gets(t, &device) < 0 ||
1142 pa_tagstruct_get_boolean(t, &e->card_valid) < 0 ||
1143 pa_tagstruct_gets(t, &card) < 0) {
1148 e->device = pa_xstrdup(device);
1149 e->card = pa_xstrdup(card);
1151 if (!pa_tagstruct_eof(t))
1154 if (e->device_valid && !pa_namereg_is_valid_name(e->device)) {
1155 pa_log_warn("Invalid device name stored in database for stream %s", name);
1159 if (e->card_valid && !pa_namereg_is_valid_name(e->card)) {
1160 pa_log_warn("Invalid card name stored in database for stream %s", name);
1164 if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) {
1165 pa_log_warn("Invalid channel map stored in database for stream %s", name);
1169 if (e->volume_valid && (!pa_cvolume_valid(&e->volume) || !pa_cvolume_compatible_with_channel_map(&e->volume, &e->channel_map))) {
1170 pa_log_warn("Invalid volume stored in database for stream %s", name);
1174 pa_tagstruct_free(t);
1175 pa_datum_free(&data);
1183 pa_tagstruct_free(t);
1185 pa_datum_free(&data);
1189 static struct entry* entry_copy(const struct entry *e) {
1195 r->device = pa_xstrdup(e->device);
1196 r->card = pa_xstrdup(e->card);
1200 static void trigger_save(struct userdata *u) {
1201 pa_native_connection *c;
1204 PA_IDXSET_FOREACH(c, u->subscribed, idx) {
1207 t = pa_tagstruct_new(NULL, 0);
1208 pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
1209 pa_tagstruct_putu32(t, 0);
1210 pa_tagstruct_putu32(t, u->module->index);
1211 pa_tagstruct_puts(t, u->module->name);
1212 pa_tagstruct_putu32(t, SUBCOMMAND_EVENT);
1214 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
1217 if (u->save_time_event)
1220 u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
1223 static bool entries_equal(const struct entry *a, const struct entry *b) {
1229 if (a->device_valid != b->device_valid ||
1230 (a->device_valid && !pa_streq(a->device, b->device)))
1233 if (a->card_valid != b->card_valid ||
1234 (a->card_valid && !pa_streq(a->card, b->card)))
1237 if (a->muted_valid != b->muted_valid ||
1238 (a->muted_valid && (a->muted != b->muted)))
1242 if (a->volume_valid != b->volume_valid ||
1243 (a->volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->volume)))
1249 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
1250 struct userdata *u = userdata;
1251 struct entry *entry, *old = NULL;
1254 /* These are only used when D-Bus is enabled, but in order to reduce ifdef
1255 * clutter these are defined here unconditionally. */
1256 bool created_new_entry = true;
1257 bool device_updated = false;
1258 bool volume_updated = false;
1259 bool mute_updated = false;
1262 struct dbus_entry *de = NULL;
1268 if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1269 t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
1270 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1271 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
1274 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
1275 pa_sink_input *sink_input;
1277 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx)))
1280 if (!(name = pa_proplist_get_stream_group(sink_input->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1283 if ((old = entry_read(u, name))) {
1284 entry = entry_copy(old);
1285 created_new_entry = false;
1287 entry = entry_new();
1289 if (sink_input->save_volume && pa_sink_input_is_volume_readable(sink_input)) {
1290 pa_assert(sink_input->volume_writable);
1292 entry->channel_map = sink_input->channel_map;
1293 pa_sink_input_get_volume(sink_input, &entry->volume, false);
1294 entry->volume_valid = true;
1296 volume_updated = !created_new_entry
1297 && (!old->volume_valid
1298 || !pa_channel_map_equal(&entry->channel_map, &old->channel_map)
1299 || !pa_cvolume_equal(&entry->volume, &old->volume));
1302 if (sink_input->save_muted) {
1303 entry->muted = pa_sink_input_get_mute(sink_input);
1304 entry->muted_valid = true;
1306 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted);
1309 if (sink_input->save_sink) {
1310 pa_xfree(entry->device);
1311 entry->device = pa_xstrdup(sink_input->sink->name);
1312 entry->device_valid = true;
1314 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry->device, old->device));
1315 if (sink_input->sink->card) {
1316 pa_xfree(entry->card);
1317 entry->card = pa_xstrdup(sink_input->sink->card->name);
1318 entry->card_valid = true;
1323 pa_source_output *source_output;
1325 pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);
1327 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx)))
1330 if (!(name = pa_proplist_get_stream_group(source_output->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1333 if ((old = entry_read(u, name))) {
1334 entry = entry_copy(old);
1335 created_new_entry = false;
1337 entry = entry_new();
1339 if (source_output->save_volume && pa_source_output_is_volume_readable(source_output)) {
1340 pa_assert(source_output->volume_writable);
1342 entry->channel_map = source_output->channel_map;
1343 pa_source_output_get_volume(source_output, &entry->volume, false);
1344 entry->volume_valid = true;
1346 volume_updated = !created_new_entry
1347 && (!old->volume_valid
1348 || !pa_channel_map_equal(&entry->channel_map, &old->channel_map)
1349 || !pa_cvolume_equal(&entry->volume, &old->volume));
1352 if (source_output->save_muted) {
1353 entry->muted = pa_source_output_get_mute(source_output);
1354 entry->muted_valid = true;
1356 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted);
1359 if (source_output->save_source) {
1360 pa_xfree(entry->device);
1361 entry->device = pa_xstrdup(source_output->source->name);
1362 entry->device_valid = true;
1364 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry->device, old->device));
1366 if (source_output->source->card) {
1367 pa_xfree(entry->card);
1368 entry->card = pa_xstrdup(source_output->source->card->name);
1369 entry->card_valid = true;
1378 if (entries_equal(old, entry)) {
1388 pa_log_info("Storing volume/mute/device for stream %s.", name);
1390 if (entry_write(u, name, entry, true))
1394 if (created_new_entry) {
1395 de = dbus_entry_new(u, name);
1396 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
1397 send_new_entry_signal(de);
1399 pa_assert_se(de = pa_hashmap_get(u->dbus_entries, name));
1402 send_device_updated_signal(de, entry);
1404 send_volume_updated_signal(de, entry);
1406 send_mute_updated_signal(de, entry);
1414 static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1419 pa_assert(new_data);
1421 pa_assert(u->restore_device);
1423 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1427 pa_log_debug("Not restoring device for stream %s, because already set to '%s'.", name, new_data->sink->name);
1428 else if ((e = entry_read(u, name))) {
1431 if (e->device_valid)
1432 s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK);
1434 if (!s && e->card_valid) {
1437 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1438 s = pa_idxset_first(card->sinks, NULL);
1441 /* It might happen that a stream and a sink are set up at the
1442 same time, in which case we want to make sure we don't
1443 interfere with that */
1444 if (s && PA_SINK_IS_LINKED(pa_sink_get_state(s)))
1445 if (pa_sink_input_new_data_set_sink(new_data, s, true))
1446 pa_log_info("Restoring device for stream %s.", name);
1456 static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1461 pa_assert(new_data);
1463 pa_assert(u->restore_volume || u->restore_muted);
1465 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1468 if ((e = entry_read(u, name))) {
1470 if (u->restore_volume && e->volume_valid) {
1471 if (!new_data->volume_writable)
1472 pa_log_debug("Not restoring volume for sink input %s, because its volume can't be changed.", name);
1473 else if (new_data->volume_is_set)
1474 pa_log_debug("Not restoring volume for sink input %s, because already set.", name);
1478 pa_log_info("Restoring volume for sink input %s.", name);
1481 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1482 pa_sink_input_new_data_set_volume(new_data, &v);
1484 new_data->volume_is_absolute = false;
1485 new_data->save_volume = true;
1489 if (u->restore_muted && e->muted_valid) {
1491 if (!new_data->muted_is_set) {
1492 pa_log_info("Restoring mute state for sink input %s.", name);
1493 pa_sink_input_new_data_set_muted(new_data, e->muted);
1494 new_data->save_muted = true;
1496 pa_log_debug("Not restoring mute state for sink input %s, because already set.", name);
1507 static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1512 pa_assert(new_data);
1514 pa_assert(u->restore_device);
1516 if (new_data->direct_on_input)
1519 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1522 if (new_data->source)
1523 pa_log_debug("Not restoring device for stream %s, because already set", name);
1524 else if ((e = entry_read(u, name))) {
1525 pa_source *s = NULL;
1527 if (e->device_valid)
1528 s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE);
1530 if (!s && e->card_valid) {
1533 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1534 s = pa_idxset_first(card->sources, NULL);
1537 /* It might happen that a stream and a sink are set up at the
1538 same time, in which case we want to make sure we don't
1539 interfere with that */
1540 if (s && PA_SOURCE_IS_LINKED(pa_source_get_state(s))) {
1541 pa_log_info("Restoring device for stream %s.", name);
1542 pa_source_output_new_data_set_source(new_data, s, true);
1553 static pa_hook_result_t source_output_fixate_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1558 pa_assert(new_data);
1560 pa_assert(u->restore_volume || u->restore_muted);
1562 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1565 if ((e = entry_read(u, name))) {
1567 if (u->restore_volume && e->volume_valid) {
1568 if (!new_data->volume_writable)
1569 pa_log_debug("Not restoring volume for source output %s, because its volume can't be changed.", name);
1570 else if (new_data->volume_is_set)
1571 pa_log_debug("Not restoring volume for source output %s, because already set.", name);
1575 pa_log_info("Restoring volume for source output %s.", name);
1578 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1579 pa_source_output_new_data_set_volume(new_data, &v);
1581 new_data->volume_is_absolute = false;
1582 new_data->save_volume = true;
1586 if (u->restore_muted && e->muted_valid) {
1588 if (!new_data->muted_is_set) {
1589 pa_log_info("Restoring mute state for source output %s.", name);
1590 pa_source_output_new_data_set_muted(new_data, e->muted);
1591 new_data->save_muted = true;
1593 pa_log_debug("Not restoring mute state for source output %s, because already set.", name);
1604 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1611 pa_assert(u->on_hotplug && u->restore_device);
1613 PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
1617 if (si->sink == sink)
1623 /* Skip this if it is already in the process of being moved
1628 /* It might happen that a stream and a sink are set up at the
1629 same time, in which case we want to make sure we don't
1630 interfere with that */
1631 if (!PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(si)))
1634 if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1637 if ((e = entry_read(u, name))) {
1638 if (e->device_valid && pa_streq(e->device, sink->name))
1639 pa_sink_input_move_to(si, sink, true);
1650 static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1651 pa_source_output *so;
1657 pa_assert(u->on_hotplug && u->restore_device);
1659 PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
1663 if (so->source == source)
1666 if (so->save_source)
1669 if (so->direct_on_input)
1672 /* Skip this if it is already in the process of being moved anyway */
1676 /* It might happen that a stream and a source are set up at the
1677 same time, in which case we want to make sure we don't
1678 interfere with that */
1679 if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
1682 if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1685 if ((e = entry_read(u, name))) {
1686 if (e->device_valid && pa_streq(e->device, source->name))
1687 pa_source_output_move_to(so, source, true);
1698 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1705 pa_assert(u->on_rescue && u->restore_device);
1707 /* There's no point in doing anything if the core is shut down anyway */
1708 if (c->state == PA_CORE_SHUTDOWN)
1711 PA_IDXSET_FOREACH(si, sink->inputs, idx) {
1718 if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1721 if ((e = entry_read(u, name))) {
1723 if (e->device_valid) {
1726 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) &&
1728 PA_SINK_IS_LINKED(pa_sink_get_state(d)))
1729 pa_sink_input_move_to(si, d, true);
1741 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1742 pa_source_output *so;
1748 pa_assert(u->on_rescue && u->restore_device);
1750 /* There's no point in doing anything if the core is shut down anyway */
1751 if (c->state == PA_CORE_SHUTDOWN)
1754 PA_IDXSET_FOREACH(so, source->outputs, idx) {
1758 if (so->direct_on_input)
1764 if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1767 if ((e = entry_read(u, name))) {
1769 if (e->device_valid) {
1772 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) &&
1774 PA_SOURCE_IS_LINKED(pa_source_get_state(d)))
1775 pa_source_output_move_to(so, d, true);
1787 static int fill_db(struct userdata *u, const char *filename) {
1796 f = fopen(fn = pa_xstrdup(filename), "r");
1798 f = pa_open_config_file(DEFAULT_FALLBACK_FILE, DEFAULT_FALLBACK_FILE_USER, NULL, &fn);
1802 pa_log("Failed to open %s: %s", filename, pa_cstrerror(errno));
1814 if (!fgets(ln, sizeof(ln), f))
1821 if (!*ln || ln[0] == '#' || ln[0] == ';')
1824 d = ln+strcspn(ln, WHITESPACE);
1825 v = d+strspn(d, WHITESPACE);
1828 pa_log("[%s:%u] failed to parse line - too few words", fn, n);
1833 if (pa_atod(v, &db) >= 0) {
1839 e.version = ENTRY_VERSION;
1840 e.volume_valid = true;
1841 pa_cvolume_set(&e.volume, 1, pa_sw_volume_from_dB(db));
1842 pa_channel_map_init_mono(&e.channel_map);
1844 key.data = (void *) ln;
1845 key.size = strlen(ln);
1847 data.data = (void *) &e;
1848 data.size = sizeof(e);
1850 if (pa_database_set(u->database, &key, &data, false) == 0)
1851 pa_log_debug("Setting %s to %0.2f dB.", ln, db);
1853 pa_log_warn("[%s:%u] Positive dB values are not allowed, not setting entry %s.", fn, n, ln);
1855 pa_log_warn("[%s:%u] Couldn't parse '%s' as a double, not setting entry %s.", fn, n, v, ln);
1870 static void entry_apply(struct userdata *u, const char *name, struct entry *e) {
1872 pa_source_output *so;
1879 PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
1883 if (!(n = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1886 if (!pa_streq(name, n)) {
1892 if (u->restore_volume && e->volume_valid && si->volume_writable) {
1896 pa_log_info("Restoring volume for sink input %s.", name);
1897 pa_cvolume_remap(&v, &e->channel_map, &si->channel_map);
1898 pa_sink_input_set_volume(si, &v, true, false);
1901 if (u->restore_muted && e->muted_valid) {
1902 pa_log_info("Restoring mute state for sink input %s.", name);
1903 pa_sink_input_set_mute(si, e->muted, true);
1906 if (u->restore_device) {
1907 if (!e->device_valid) {
1908 if (si->save_sink) {
1909 pa_log_info("Ensuring device is not saved for stream %s.", name);
1910 /* If the device is not valid we should make sure the
1911 save flag is cleared as the user may have specifically
1912 removed the sink element from the rule. */
1913 si->save_sink = false;
1914 /* This is cheating a bit. The sink input itself has not changed
1915 but the rules governing it's routing have, so we fire this event
1916 such that other routing modules (e.g. module-device-manager)
1917 will pick up the change and reapply their routing */
1918 pa_subscription_post(si->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, si->index);
1920 } else if ((s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SINK))) {
1921 pa_log_info("Restoring device for stream %s.", name);
1922 pa_sink_input_move_to(si, s, true);
1927 PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
1931 if (!(n = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1934 if (!pa_streq(name, n)) {
1940 if (u->restore_volume && e->volume_valid && so->volume_writable) {
1944 pa_log_info("Restoring volume for source output %s.", name);
1945 pa_cvolume_remap(&v, &e->channel_map, &so->channel_map);
1946 pa_source_output_set_volume(so, &v, true, false);
1949 if (u->restore_muted && e->muted_valid) {
1950 pa_log_info("Restoring mute state for source output %s.", name);
1951 pa_source_output_set_mute(so, e->muted, true);
1954 if (u->restore_device) {
1955 if (!e->device_valid) {
1956 if (so->save_source) {
1957 pa_log_info("Ensuring device is not saved for stream %s.", name);
1958 /* If the device is not valid we should make sure the
1959 save flag is cleared as the user may have specifically
1960 removed the source element from the rule. */
1961 so->save_source = false;
1962 /* This is cheating a bit. The source output itself has not changed
1963 but the rules governing it's routing have, so we fire this event
1964 such that other routing modules (e.g. module-device-manager)
1965 will pick up the change and reapply their routing */
1966 pa_subscription_post(so->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, so->index);
1968 } else if ((s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE))) {
1969 pa_log_info("Restoring device for stream %s.", name);
1970 pa_source_output_move_to(so, s, true);
1977 PA_GCC_UNUSED static void stream_restore_dump_database(struct userdata *u) {
1981 done = !pa_database_first(u->database, &key, NULL);
1988 done = !pa_database_next(u->database, &key, &next_key, NULL);
1990 name = pa_xstrndup(key.data, key.size);
1991 pa_datum_free(&key);
1993 if ((e = entry_read(u, name))) {
1995 pa_log("name=%s", name);
1996 pa_log("device=%s %s", e->device, pa_yes_no(e->device_valid));
1997 pa_log("channel_map=%s", pa_channel_map_snprint(t, sizeof(t), &e->channel_map));
1998 pa_log("volume=%s %s",
1999 pa_cvolume_snprint_verbose(t, sizeof(t), &e->volume, &e->channel_map, true),
2000 pa_yes_no(e->volume_valid));
2001 pa_log("mute=%s %s", pa_yes_no(e->muted), pa_yes_no(e->volume_valid));
2012 #define EXT_VERSION 1
2014 static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
2017 pa_tagstruct *reply = NULL;
2026 if (pa_tagstruct_getu32(t, &command) < 0)
2029 reply = pa_tagstruct_new(NULL, 0);
2030 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
2031 pa_tagstruct_putu32(reply, tag);
2034 case SUBCOMMAND_TEST: {
2035 if (!pa_tagstruct_eof(t))
2038 pa_tagstruct_putu32(reply, EXT_VERSION);
2042 case SUBCOMMAND_READ: {
2046 if (!pa_tagstruct_eof(t))
2049 done = !pa_database_first(u->database, &key, NULL);
2056 done = !pa_database_next(u->database, &key, &next_key, NULL);
2058 name = pa_xstrndup(key.data, key.size);
2059 pa_datum_free(&key);
2061 if ((e = entry_read(u, name))) {
2065 pa_tagstruct_puts(reply, name);
2066 pa_tagstruct_put_channel_map(reply, e->volume_valid ? &e->channel_map : pa_channel_map_init(&cm));
2067 pa_tagstruct_put_cvolume(reply, e->volume_valid ? &e->volume : pa_cvolume_init(&r));
2068 pa_tagstruct_puts(reply, e->device_valid ? e->device : NULL);
2069 pa_tagstruct_put_boolean(reply, e->muted_valid ? e->muted : false);
2082 case SUBCOMMAND_WRITE: {
2084 bool apply_immediately = false;
2086 if (pa_tagstruct_getu32(t, &mode) < 0 ||
2087 pa_tagstruct_get_boolean(t, &apply_immediately) < 0)
2090 if (mode != PA_UPDATE_MERGE &&
2091 mode != PA_UPDATE_REPLACE &&
2092 mode != PA_UPDATE_SET)
2095 if (mode == PA_UPDATE_SET) {
2097 struct dbus_entry *de;
2100 PA_HASHMAP_FOREACH(de, u->dbus_entries, state) {
2101 send_entry_removed_signal(de);
2102 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, de->entry_name));
2105 pa_database_clear(u->database);
2108 while (!pa_tagstruct_eof(t)) {
2109 const char *name, *device;
2111 struct entry *entry;
2116 entry = entry_new();
2118 if (pa_tagstruct_gets(t, &name) < 0 ||
2119 pa_tagstruct_get_channel_map(t, &entry->channel_map) ||
2120 pa_tagstruct_get_cvolume(t, &entry->volume) < 0 ||
2121 pa_tagstruct_gets(t, &device) < 0 ||
2122 pa_tagstruct_get_boolean(t, &muted) < 0)
2125 if (!name || !*name) {
2130 entry->volume_valid = entry->volume.channels > 0;
2132 if (entry->volume_valid)
2133 if (!pa_cvolume_compatible_with_channel_map(&entry->volume, &entry->channel_map)) {
2138 entry->muted = muted;
2139 entry->muted_valid = true;
2141 entry->device = pa_xstrdup(device);
2142 entry->device_valid = device && !!entry->device[0];
2144 if (entry->device_valid && !pa_namereg_is_valid_name(entry->device)) {
2150 old = entry_read(u, name);
2153 pa_log_debug("Client %s changes entry %s.",
2154 pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)),
2157 if (entry_write(u, name, entry, mode == PA_UPDATE_REPLACE)) {
2159 struct dbus_entry *de;
2162 pa_assert_se((de = pa_hashmap_get(u->dbus_entries, name)));
2164 if ((old->device_valid != entry->device_valid)
2165 || (entry->device_valid && !pa_streq(entry->device, old->device)))
2166 send_device_updated_signal(de, entry);
2168 if ((old->volume_valid != entry->volume_valid)
2169 || (entry->volume_valid && (!pa_cvolume_equal(&entry->volume, &old->volume)
2170 || !pa_channel_map_equal(&entry->channel_map, &old->channel_map))))
2171 send_volume_updated_signal(de, entry);
2173 if (!old->muted_valid || (entry->muted != old->muted))
2174 send_mute_updated_signal(de, entry);
2177 de = dbus_entry_new(u, name);
2178 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
2179 send_new_entry_signal(de);
2183 if (apply_immediately)
2184 entry_apply(u, name, entry);
2199 case SUBCOMMAND_DELETE:
2201 while (!pa_tagstruct_eof(t)) {
2205 struct dbus_entry *de;
2208 if (pa_tagstruct_gets(t, &name) < 0)
2212 if ((de = pa_hashmap_get(u->dbus_entries, name))) {
2213 send_entry_removed_signal(de);
2214 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, name));
2218 key.data = (char*) name;
2219 key.size = strlen(name);
2221 pa_database_unset(u->database, &key);
2228 case SUBCOMMAND_SUBSCRIBE: {
2232 if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
2233 !pa_tagstruct_eof(t))
2237 pa_idxset_put(u->subscribed, c, NULL);
2239 pa_idxset_remove_by_data(u->subscribed, c, NULL);
2248 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
2254 pa_tagstruct_free(reply);
2259 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
2264 pa_idxset_remove_by_data(u->subscribed, c, NULL);
2268 static void clean_up_db(struct userdata *u) {
2269 struct clean_up_item {
2270 PA_LLIST_FIELDS(struct clean_up_item);
2272 struct entry *entry;
2275 PA_LLIST_HEAD(struct clean_up_item, to_be_removed);
2276 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2277 PA_LLIST_HEAD(struct clean_up_item, to_be_converted);
2281 struct clean_up_item *item = NULL;
2282 struct clean_up_item *next = NULL;
2286 /* It would be convenient to remove or replace the entries in the database
2287 * in the same loop that iterates through the database, but modifying the
2288 * database is not supported while iterating through it. That's why we
2289 * collect the entries that need to be removed or replaced to these
2291 PA_LLIST_HEAD_INIT(struct clean_up_item, to_be_removed);
2292 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2293 PA_LLIST_HEAD_INIT(struct clean_up_item, to_be_converted);
2296 done = !pa_database_first(u->database, &key, NULL);
2299 char *entry_name = NULL;
2300 struct entry *e = NULL;
2302 entry_name = pa_xstrndup(key.data, key.size);
2304 /* Use entry_read() to check whether this entry is valid. */
2305 if (!(e = entry_read(u, entry_name))) {
2306 item = pa_xnew0(struct clean_up_item, 1);
2307 PA_LLIST_INIT(struct clean_up_item, item);
2308 item->entry_name = entry_name;
2310 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2311 /* entry_read() failed, but what about legacy_entry_read()? */
2312 if (!(e = legacy_entry_read(u, entry_name)))
2313 /* Not a legacy entry either, let's remove this. */
2314 PA_LLIST_PREPEND(struct clean_up_item, to_be_removed, item);
2316 /* Yay, it's valid after all! Now let's convert the entry to the current format. */
2318 PA_LLIST_PREPEND(struct clean_up_item, to_be_converted, item);
2321 /* Invalid entry, let's remove this. */
2322 PA_LLIST_PREPEND(struct clean_up_item, to_be_removed, item);
2325 pa_xfree(entry_name);
2329 done = !pa_database_next(u->database, &key, &next_key, NULL);
2330 pa_datum_free(&key);
2334 PA_LLIST_FOREACH_SAFE(item, next, to_be_removed) {
2335 key.data = item->entry_name;
2336 key.size = strlen(item->entry_name);
2338 pa_log_debug("Removing an invalid entry: %s", item->entry_name);
2340 pa_assert_se(pa_database_unset(u->database, &key) >= 0);
2343 PA_LLIST_REMOVE(struct clean_up_item, to_be_removed, item);
2344 pa_xfree(item->entry_name);
2348 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2349 PA_LLIST_FOREACH_SAFE(item, next, to_be_converted) {
2350 pa_log_debug("Upgrading a legacy entry to the current format: %s", item->entry_name);
2352 pa_assert_se(entry_write(u, item->entry_name, item->entry, true) >= 0);
2355 PA_LLIST_REMOVE(struct clean_up_item, to_be_converted, item);
2356 pa_xfree(item->entry_name);
2357 entry_free(item->entry);
2363 int pa__init(pa_module*m) {
2364 pa_modargs *ma = NULL;
2368 pa_source_output *so;
2370 bool restore_device = true, restore_volume = true, restore_muted = true, on_hotplug = true, on_rescue = true;
2378 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
2379 pa_log("Failed to parse module arguments");
2383 if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
2384 pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
2385 pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
2386 pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
2387 pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
2388 pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments");
2392 if (!restore_muted && !restore_volume && !restore_device)
2393 pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!");
2395 m->userdata = u = pa_xnew0(struct userdata, 1);
2398 u->restore_device = restore_device;
2399 u->restore_volume = restore_volume;
2400 u->restore_muted = restore_muted;
2401 u->on_hotplug = on_hotplug;
2402 u->on_rescue = on_rescue;
2403 u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
2405 u->protocol = pa_native_protocol_get(m->core);
2406 pa_native_protocol_install_ext(u->protocol, m, extension_cb);
2408 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);
2410 u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
2412 if (restore_device) {
2413 /* A little bit earlier than module-intended-roles ... */
2414 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);
2415 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);
2418 if (restore_device && on_hotplug) {
2419 /* A little bit earlier than module-intended-roles ... */
2420 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);
2421 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);
2424 if (restore_device && on_rescue) {
2425 /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */
2426 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);
2427 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);
2430 if (restore_volume || restore_muted) {
2431 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);
2432 u->source_output_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_fixate_hook_callback, u);
2435 if (!(fname = pa_state_path("stream-volumes", true)))
2438 if (!(u->database = pa_database_open(fname, true))) {
2439 pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
2444 pa_log_info("Successfully opened database file '%s'.", fname);
2449 if (fill_db(u, pa_modargs_get_value(ma, "fallback_table", NULL)) < 0)
2453 u->dbus_protocol = pa_dbus_protocol_get(u->core);
2454 u->dbus_entries = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
2456 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, OBJECT_PATH, &stream_restore_interface_info, u) >= 0);
2457 pa_assert_se(pa_dbus_protocol_register_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2459 /* Create the initial dbus entries. */
2460 done = !pa_database_first(u->database, &key, NULL);
2464 struct dbus_entry *de;
2466 name = pa_xstrndup(key.data, key.size);
2467 de = dbus_entry_new(u, name);
2468 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
2471 done = !pa_database_next(u->database, &key, &next_key, NULL);
2472 pa_datum_free(&key);
2477 PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx)
2478 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u);
2480 PA_IDXSET_FOREACH(so, m->core->source_outputs, idx)
2481 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, so->index, u);
2483 pa_modargs_free(ma);
2490 pa_modargs_free(ma);
2495 void pa__done(pa_module*m) {
2500 if (!(u = m->userdata))
2504 if (u->dbus_protocol) {
2505 pa_assert(u->dbus_entries);
2507 pa_assert_se(pa_dbus_protocol_unregister_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2508 pa_assert_se(pa_dbus_protocol_remove_interface(u->dbus_protocol, OBJECT_PATH, stream_restore_interface_info.name) >= 0);
2510 pa_hashmap_free(u->dbus_entries, (pa_free_cb_t) dbus_entry_free);
2512 pa_dbus_protocol_unref(u->dbus_protocol);
2516 if (u->subscription)
2517 pa_subscription_free(u->subscription);
2519 if (u->sink_input_new_hook_slot)
2520 pa_hook_slot_free(u->sink_input_new_hook_slot);
2521 if (u->sink_input_fixate_hook_slot)
2522 pa_hook_slot_free(u->sink_input_fixate_hook_slot);
2523 if (u->source_output_new_hook_slot)
2524 pa_hook_slot_free(u->source_output_new_hook_slot);
2525 if (u->source_output_fixate_hook_slot)
2526 pa_hook_slot_free(u->source_output_fixate_hook_slot);
2528 if (u->sink_put_hook_slot)
2529 pa_hook_slot_free(u->sink_put_hook_slot);
2530 if (u->source_put_hook_slot)
2531 pa_hook_slot_free(u->source_put_hook_slot);
2533 if (u->sink_unlink_hook_slot)
2534 pa_hook_slot_free(u->sink_unlink_hook_slot);
2535 if (u->source_unlink_hook_slot)
2536 pa_hook_slot_free(u->source_unlink_hook_slot);
2538 if (u->connection_unlink_hook_slot)
2539 pa_hook_slot_free(u->connection_unlink_hook_slot);
2541 if (u->save_time_event)
2542 u->core->mainloop->time_free(u->save_time_event);
2545 pa_database_close(u->database);
2548 pa_native_protocol_remove_ext(u->protocol, m);
2549 pa_native_protocol_unref(u->protocol);
2553 pa_idxset_free(u->subscribed, NULL);