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>
56 #include <pulsecore/dbus-util.h>
57 #include <pulsecore/protocol-dbus.h>
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);
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[] = {
88 pa_subscription *subscription;
90 *sink_input_new_hook_slot,
91 *sink_input_fixate_hook_slot,
92 *source_output_new_hook_slot,
93 *source_output_fixate_hook_slot,
95 *source_put_hook_slot,
96 *sink_unlink_hook_slot,
97 *source_unlink_hook_slot,
98 *connection_unlink_hook_slot;
99 pa_time_event *save_time_event;
100 pa_database* database;
102 pa_bool_t restore_device:1;
103 pa_bool_t restore_volume:1;
104 pa_bool_t restore_muted:1;
105 pa_bool_t on_hotplug:1;
106 pa_bool_t on_rescue:1;
108 pa_native_protocol *protocol;
109 pa_idxset *subscribed;
112 pa_dbus_protocol *dbus_protocol;
113 pa_hashmap *dbus_entries;
114 uint32_t next_index; /* For generating object paths for entries. */
118 #define ENTRY_VERSION 1
122 pa_bool_t muted_valid, volume_valid, device_valid, card_valid;
124 pa_channel_map channel_map;
135 SUBCOMMAND_SUBSCRIBE,
140 static struct entry* entry_new(void);
141 static void entry_free(struct entry *e);
142 static struct entry *entry_read(struct userdata *u, const char *name);
143 static pa_bool_t entry_write(struct userdata *u, const char *name, const struct entry *e, pa_bool_t replace);
144 static struct entry* entry_copy(const struct entry *e);
145 static void entry_apply(struct userdata *u, const char *name, struct entry *e);
146 static void trigger_save(struct userdata *u);
150 #define OBJECT_PATH "/org/pulseaudio/stream_restore1"
151 #define ENTRY_OBJECT_NAME "entry"
152 #define INTERFACE_STREAM_RESTORE "org.PulseAudio.Ext.StreamRestore1"
153 #define INTERFACE_ENTRY INTERFACE_STREAM_RESTORE ".RestoreEntry"
155 #define DBUS_INTERFACE_REVISION 0
158 struct userdata *userdata;
165 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata);
166 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata);
168 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
170 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata);
171 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
173 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata);
174 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata);
175 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
176 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
177 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata);
178 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
179 static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
180 static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata);
182 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
184 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata);
186 enum property_handler_index {
187 PROPERTY_HANDLER_INTERFACE_REVISION,
188 PROPERTY_HANDLER_ENTRIES,
192 enum entry_property_handler_index {
193 ENTRY_PROPERTY_HANDLER_INDEX,
194 ENTRY_PROPERTY_HANDLER_NAME,
195 ENTRY_PROPERTY_HANDLER_DEVICE,
196 ENTRY_PROPERTY_HANDLER_VOLUME,
197 ENTRY_PROPERTY_HANDLER_MUTE,
198 ENTRY_PROPERTY_HANDLER_MAX
201 static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = {
202 [PROPERTY_HANDLER_INTERFACE_REVISION] = { .property_name = "InterfaceRevision", .type = "u", .get_cb = handle_get_interface_revision, .set_cb = NULL },
203 [PROPERTY_HANDLER_ENTRIES] = { .property_name = "Entries", .type = "ao", .get_cb = handle_get_entries, .set_cb = NULL }
206 static pa_dbus_property_handler entry_property_handlers[ENTRY_PROPERTY_HANDLER_MAX] = {
207 [ENTRY_PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_entry_get_index, .set_cb = NULL },
208 [ENTRY_PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_entry_get_name, .set_cb = NULL },
209 [ENTRY_PROPERTY_HANDLER_DEVICE] = { .property_name = "Device", .type = "s", .get_cb = handle_entry_get_device, .set_cb = handle_entry_set_device },
210 [ENTRY_PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "a(uu)", .get_cb = handle_entry_get_volume, .set_cb = handle_entry_set_volume },
211 [ENTRY_PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_entry_get_mute, .set_cb = handle_entry_set_mute }
214 enum method_handler_index {
215 METHOD_HANDLER_ADD_ENTRY,
216 METHOD_HANDLER_GET_ENTRY_BY_NAME,
220 enum entry_method_handler_index {
221 ENTRY_METHOD_HANDLER_REMOVE,
222 ENTRY_METHOD_HANDLER_MAX
225 static pa_dbus_arg_info add_entry_args[] = { { "name", "s", "in" },
226 { "device", "s", "in" },
227 { "volume", "a(uu)", "in" },
228 { "mute", "b", "in" },
229 { "entry", "o", "out" } };
230 static pa_dbus_arg_info get_entry_by_name_args[] = { { "name", "s", "in" }, { "entry", "o", "out" } };
232 static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
233 [METHOD_HANDLER_ADD_ENTRY] = {
234 .method_name = "AddEntry",
235 .arguments = add_entry_args,
236 .n_arguments = sizeof(add_entry_args) / sizeof(pa_dbus_arg_info),
237 .receive_cb = handle_add_entry },
238 [METHOD_HANDLER_GET_ENTRY_BY_NAME] = {
239 .method_name = "GetEntryByName",
240 .arguments = get_entry_by_name_args,
241 .n_arguments = sizeof(get_entry_by_name_args) / sizeof(pa_dbus_arg_info),
242 .receive_cb = handle_get_entry_by_name }
245 static pa_dbus_method_handler entry_method_handlers[ENTRY_METHOD_HANDLER_MAX] = {
246 [ENTRY_METHOD_HANDLER_REMOVE] = {
247 .method_name = "Remove",
250 .receive_cb = handle_entry_remove }
255 SIGNAL_ENTRY_REMOVED,
259 enum entry_signal_index {
260 ENTRY_SIGNAL_DEVICE_UPDATED,
261 ENTRY_SIGNAL_VOLUME_UPDATED,
262 ENTRY_SIGNAL_MUTE_UPDATED,
266 static pa_dbus_arg_info new_entry_args[] = { { "entry", "o", NULL } };
267 static pa_dbus_arg_info entry_removed_args[] = { { "entry", "o", NULL } };
269 static pa_dbus_arg_info entry_device_updated_args[] = { { "device", "s", NULL } };
270 static pa_dbus_arg_info entry_volume_updated_args[] = { { "volume", "a(uu)", NULL } };
271 static pa_dbus_arg_info entry_mute_updated_args[] = { { "muted", "b", NULL } };
273 static pa_dbus_signal_info signals[SIGNAL_MAX] = {
274 [SIGNAL_NEW_ENTRY] = { .name = "NewEntry", .arguments = new_entry_args, .n_arguments = 1 },
275 [SIGNAL_ENTRY_REMOVED] = { .name = "EntryRemoved", .arguments = entry_removed_args, .n_arguments = 1 }
278 static pa_dbus_signal_info entry_signals[ENTRY_SIGNAL_MAX] = {
279 [ENTRY_SIGNAL_DEVICE_UPDATED] = { .name = "DeviceUpdated", .arguments = entry_device_updated_args, .n_arguments = 1 },
280 [ENTRY_SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = entry_volume_updated_args, .n_arguments = 1 },
281 [ENTRY_SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = entry_mute_updated_args, .n_arguments = 1 }
284 static pa_dbus_interface_info stream_restore_interface_info = {
285 .name = INTERFACE_STREAM_RESTORE,
286 .method_handlers = method_handlers,
287 .n_method_handlers = METHOD_HANDLER_MAX,
288 .property_handlers = property_handlers,
289 .n_property_handlers = PROPERTY_HANDLER_MAX,
290 .get_all_properties_cb = handle_get_all,
292 .n_signals = SIGNAL_MAX
295 static pa_dbus_interface_info entry_interface_info = {
296 .name = INTERFACE_ENTRY,
297 .method_handlers = entry_method_handlers,
298 .n_method_handlers = ENTRY_METHOD_HANDLER_MAX,
299 .property_handlers = entry_property_handlers,
300 .n_property_handlers = ENTRY_PROPERTY_HANDLER_MAX,
301 .get_all_properties_cb = handle_entry_get_all,
302 .signals = entry_signals,
303 .n_signals = ENTRY_SIGNAL_MAX
306 static struct dbus_entry *dbus_entry_new(struct userdata *u, const char *entry_name) {
307 struct dbus_entry *de;
310 pa_assert(entry_name);
311 pa_assert(*entry_name);
313 de = pa_xnew(struct dbus_entry, 1);
315 de->entry_name = pa_xstrdup(entry_name);
316 de->index = u->next_index++;
317 de->object_path = pa_sprintf_malloc("%s/%s%u", OBJECT_PATH, ENTRY_OBJECT_NAME, de->index);
319 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, de->object_path, &entry_interface_info, de) >= 0);
324 static void dbus_entry_free(struct dbus_entry *de) {
327 pa_assert_se(pa_dbus_protocol_remove_interface(de->userdata->dbus_protocol, de->object_path, entry_interface_info.name) >= 0);
329 pa_xfree(de->entry_name);
330 pa_xfree(de->object_path);
334 /* Reads an array [(UInt32, UInt32)] from the iterator. The struct items are
335 * are a channel position and a volume value, respectively. The result is
336 * stored in the map and vol arguments. The iterator must point to a "a(uu)"
337 * element. If the data is invalid, an error reply is sent and a negative
338 * number is returned. In case of a failure we make no guarantees about the
339 * state of map and vol. In case of an empty array the channels field of both
340 * map and vol are set to 0. This function calls dbus_message_iter_next(iter)
341 * before returning. */
342 static int get_volume_arg(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, pa_channel_map *map, pa_cvolume *vol) {
343 DBusMessageIter array_iter;
344 DBusMessageIter struct_iter;
349 pa_assert(pa_streq(dbus_message_iter_get_signature(iter), "a(uu)"));
353 pa_channel_map_init(map);
354 pa_cvolume_init(vol);
359 dbus_message_iter_recurse(iter, &array_iter);
361 while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
362 dbus_uint32_t chan_pos;
363 dbus_uint32_t chan_vol;
365 dbus_message_iter_recurse(&array_iter, &struct_iter);
367 dbus_message_iter_get_basic(&struct_iter, &chan_pos);
369 if (chan_pos >= PA_CHANNEL_POSITION_MAX) {
370 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position: %u", chan_pos);
374 pa_assert_se(dbus_message_iter_next(&struct_iter));
375 dbus_message_iter_get_basic(&struct_iter, &chan_vol);
377 if (!PA_VOLUME_IS_VALID(chan_vol)) {
378 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u", chan_vol);
382 if (map->channels < PA_CHANNELS_MAX) {
383 map->map[map->channels] = chan_pos;
384 vol->values[map->channels] = chan_vol;
389 dbus_message_iter_next(&array_iter);
392 if (map->channels > PA_CHANNELS_MAX) {
393 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too many channels: %u. The maximum is %u.", map->channels, PA_CHANNELS_MAX);
397 dbus_message_iter_next(iter);
402 static void append_volume(DBusMessageIter *iter, struct entry *e) {
403 DBusMessageIter array_iter;
404 DBusMessageIter struct_iter;
410 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(uu)", &array_iter));
412 if (!e->volume_valid) {
413 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
417 for (i = 0; i < e->channel_map.channels; ++i) {
418 pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter));
420 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->channel_map.map[i]));
421 pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->volume.values[i]));
423 pa_assert_se(dbus_message_iter_close_container(&array_iter, &struct_iter));
426 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
429 static void append_volume_variant(DBusMessageIter *iter, struct entry *e) {
430 DBusMessageIter variant_iter;
435 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(uu)", &variant_iter));
437 append_volume(&variant_iter, e);
439 pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter));
442 static void send_new_entry_signal(struct dbus_entry *entry) {
443 DBusMessage *signal_msg;
447 pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name));
448 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
449 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg);
450 dbus_message_unref(signal_msg);
453 static void send_entry_removed_signal(struct dbus_entry *entry) {
454 DBusMessage *signal_msg;
458 pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name));
459 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID));
460 pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg);
461 dbus_message_unref(signal_msg);
464 static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) {
465 DBusMessage *signal_msg;
471 device = e->device_valid ? e->device : "";
473 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name));
474 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID));
475 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
476 dbus_message_unref(signal_msg);
479 static void send_volume_updated_signal(struct dbus_entry *de, struct entry *e) {
480 DBusMessage *signal_msg;
481 DBusMessageIter msg_iter;
486 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name));
487 dbus_message_iter_init_append(signal_msg, &msg_iter);
488 append_volume(&msg_iter, e);
489 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
490 dbus_message_unref(signal_msg);
493 static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) {
494 DBusMessage *signal_msg;
500 pa_assert(e->muted_valid);
504 pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name));
505 pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID));
506 pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg);
507 dbus_message_unref(signal_msg);
510 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) {
511 dbus_uint32_t interface_revision = DBUS_INTERFACE_REVISION;
516 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &interface_revision);
519 /* The caller frees the array, but not the strings. */
520 static const char **get_entries(struct userdata *u, unsigned *n) {
521 const char **entries;
524 struct dbus_entry *de;
529 *n = pa_hashmap_size(u->dbus_entries);
534 entries = pa_xnew(const char *, *n);
536 PA_HASHMAP_FOREACH(de, u->dbus_entries, state)
537 entries[i++] = de->object_path;
542 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata) {
543 struct userdata *u = userdata;
544 const char **entries;
551 entries = get_entries(u, &n);
553 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, entries, n);
558 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
559 struct userdata *u = userdata;
560 DBusMessage *reply = NULL;
561 DBusMessageIter msg_iter;
562 DBusMessageIter dict_iter;
563 dbus_uint32_t interface_revision;
564 const char **entries;
571 interface_revision = DBUS_INTERFACE_REVISION;
572 entries = get_entries(u, &n_entries);
574 pa_assert_se((reply = dbus_message_new_method_return(msg)));
576 dbus_message_iter_init_append(reply, &msg_iter);
577 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
579 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INTERFACE_REVISION].property_name, DBUS_TYPE_UINT32, &interface_revision);
580 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ENTRIES].property_name, DBUS_TYPE_OBJECT_PATH, entries, n_entries);
582 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
584 pa_assert_se(dbus_connection_send(conn, reply, NULL));
586 dbus_message_unref(reply);
591 static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata) {
592 struct userdata *u = userdata;
593 DBusMessageIter msg_iter;
594 const char *name = NULL;
595 const char *device = NULL;
598 dbus_bool_t muted = FALSE;
599 dbus_bool_t apply_immediately = FALSE;
600 struct dbus_entry *dbus_entry = NULL;
601 struct entry *e = NULL;
607 pa_assert_se(dbus_message_iter_init(msg, &msg_iter));
608 dbus_message_iter_get_basic(&msg_iter, &name);
610 pa_assert_se(dbus_message_iter_next(&msg_iter));
611 dbus_message_iter_get_basic(&msg_iter, &device);
613 pa_assert_se(dbus_message_iter_next(&msg_iter));
614 if (get_volume_arg(conn, msg, &msg_iter, &map, &vol) < 0)
617 dbus_message_iter_get_basic(&msg_iter, &muted);
619 pa_assert_se(dbus_message_iter_next(&msg_iter));
620 dbus_message_iter_get_basic(&msg_iter, &apply_immediately);
623 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "An empty string was given as the entry name.");
627 if ((dbus_entry = pa_hashmap_get(u->dbus_entries, name))) {
628 pa_bool_t mute_updated = FALSE;
629 pa_bool_t volume_updated = FALSE;
630 pa_bool_t device_updated = FALSE;
632 pa_assert_se(e = entry_read(u, name));
633 mute_updated = e->muted != muted;
635 e->muted_valid = TRUE;
637 volume_updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
639 e->channel_map = map;
640 e->volume_valid = !!map.channels;
642 device_updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
644 e->device = pa_xstrdup(device);
645 e->device_valid = !!device[0];
648 send_mute_updated_signal(dbus_entry, e);
650 send_volume_updated_signal(dbus_entry, e);
652 send_device_updated_signal(dbus_entry, e);
655 dbus_entry = dbus_entry_new(u, name);
656 pa_assert_se(pa_hashmap_put(u->dbus_entries, dbus_entry->entry_name, dbus_entry) == 0);
659 e->muted_valid = TRUE;
660 e->volume_valid = !!map.channels;
661 e->device_valid = !!device[0];
664 e->channel_map = map;
665 e->device = pa_xstrdup(device);
667 send_new_entry_signal(dbus_entry);
670 pa_assert_se(entry_write(u, name, e, TRUE));
672 if (apply_immediately)
673 entry_apply(u, name, e);
677 pa_dbus_send_empty_reply(conn, msg);
682 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
683 struct userdata *u = userdata;
685 struct dbus_entry *de;
691 pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID));
693 if (!(de = pa_hashmap_get(u->dbus_entries, name))) {
694 pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such stream restore entry.");
698 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &de->object_path);
701 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) {
702 struct dbus_entry *de = userdata;
708 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &de->index);
711 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
712 struct dbus_entry *de = userdata;
718 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &de->entry_name);
721 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
722 struct dbus_entry *de = userdata;
730 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
732 device = e->device_valid ? e->device : "";
734 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &device);
739 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
740 struct dbus_entry *de = userdata;
750 dbus_message_iter_get_basic(iter, &device);
752 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
754 updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
758 e->device = pa_xstrdup(device);
759 e->device_valid = !!device[0];
761 pa_assert_se(entry_write(de->userdata, de->entry_name, e, TRUE));
763 entry_apply(de->userdata, de->entry_name, e);
764 send_device_updated_signal(de, e);
765 trigger_save(de->userdata);
768 pa_dbus_send_empty_reply(conn, msg);
773 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
774 struct dbus_entry *de = userdata;
776 DBusMessageIter msg_iter;
783 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
785 pa_assert_se(reply = dbus_message_new_method_return(msg));
787 dbus_message_iter_init_append(reply, &msg_iter);
788 append_volume_variant(&msg_iter, e);
790 pa_assert_se(dbus_connection_send(conn, reply, NULL));
795 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
796 struct dbus_entry *de = userdata;
799 struct entry *e = NULL;
800 pa_bool_t updated = FALSE;
807 if (get_volume_arg(conn, msg, iter, &map, &vol) < 0)
810 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
812 updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
816 e->channel_map = map;
817 e->volume_valid = !!map.channels;
819 pa_assert_se(entry_write(de->userdata, de->entry_name, e, TRUE));
821 entry_apply(de->userdata, de->entry_name, e);
822 send_volume_updated_signal(de, e);
823 trigger_save(de->userdata);
826 pa_dbus_send_empty_reply(conn, msg);
831 static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
832 struct dbus_entry *de = userdata;
840 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
842 mute = e->muted_valid ? e->muted : FALSE;
844 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &mute);
849 static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
850 struct dbus_entry *de = userdata;
860 dbus_message_iter_get_basic(iter, &mute);
862 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
864 updated = !e->muted_valid || e->muted != mute;
868 e->muted_valid = TRUE;
870 pa_assert_se(entry_write(de->userdata, de->entry_name, e, TRUE));
872 entry_apply(de->userdata, de->entry_name, e);
873 send_mute_updated_signal(de, e);
874 trigger_save(de->userdata);
877 pa_dbus_send_empty_reply(conn, msg);
882 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
883 struct dbus_entry *de = userdata;
885 DBusMessage *reply = NULL;
886 DBusMessageIter msg_iter;
887 DBusMessageIter dict_iter;
888 DBusMessageIter dict_entry_iter;
896 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
898 device = e->device_valid ? e->device : "";
899 mute = e->muted_valid ? e->muted : FALSE;
901 pa_assert_se((reply = dbus_message_new_method_return(msg)));
903 dbus_message_iter_init_append(reply, &msg_iter);
904 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
906 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &de->index);
907 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &de->entry_name);
908 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_STRING, &device);
910 pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter));
912 pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &entry_property_handlers[ENTRY_PROPERTY_HANDLER_VOLUME].property_name));
913 append_volume_variant(&dict_entry_iter, e);
915 pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter));
917 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &mute);
919 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
921 pa_assert_se(dbus_connection_send(conn, reply, NULL));
923 dbus_message_unref(reply);
928 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata) {
929 struct dbus_entry *de = userdata;
936 key.data = de->entry_name;
937 key.size = strlen(de->entry_name);
939 pa_assert_se(pa_database_unset(de->userdata->database, &key) == 0);
941 send_entry_removed_signal(de);
942 trigger_save(de->userdata);
944 pa_assert_se(pa_hashmap_remove(de->userdata->dbus_entries, de->entry_name));
947 pa_dbus_send_empty_reply(conn, msg);
950 #endif /* HAVE_DBUS */
952 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
953 struct userdata *u = userdata;
959 pa_assert(e == u->save_time_event);
960 u->core->mainloop->time_free(u->save_time_event);
961 u->save_time_event = NULL;
963 pa_database_sync(u->database);
964 pa_log_info("Synced.");
967 static char *get_name(pa_proplist *p, const char *prefix) {
974 if ((r = pa_proplist_gets(p, IDENTIFICATION_PROPERTY)))
975 return pa_xstrdup(r);
977 if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE)))
978 t = pa_sprintf_malloc("%s-by-media-role:%s", prefix, r);
979 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_ID)))
980 t = pa_sprintf_malloc("%s-by-application-id:%s", prefix, r);
981 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME)))
982 t = pa_sprintf_malloc("%s-by-application-name:%s", prefix, r);
983 else if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_NAME)))
984 t = pa_sprintf_malloc("%s-by-media-name:%s", prefix, r);
986 t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
988 pa_proplist_sets(p, IDENTIFICATION_PROPERTY, t);
992 static struct entry* entry_new(void) {
993 struct entry *r = pa_xnew0(struct entry, 1);
994 r->version = ENTRY_VERSION;
998 static void entry_free(struct entry* e) {
1001 pa_xfree(e->device);
1006 static pa_bool_t entry_write(struct userdata *u, const char *name, const struct entry *e, pa_bool_t replace) {
1015 t = pa_tagstruct_new(NULL, 0);
1016 pa_tagstruct_putu8(t, e->version);
1017 pa_tagstruct_put_boolean(t, e->volume_valid);
1018 pa_tagstruct_put_channel_map(t, &e->channel_map);
1019 pa_tagstruct_put_cvolume(t, &e->volume);
1020 pa_tagstruct_put_boolean(t, e->muted_valid);
1021 pa_tagstruct_put_boolean(t, e->muted);
1022 pa_tagstruct_put_boolean(t, e->device_valid);
1023 pa_tagstruct_puts(t, e->device);
1024 pa_tagstruct_put_boolean(t, e->card_valid);
1025 pa_tagstruct_puts(t, e->card);
1027 key.data = (char *) name;
1028 key.size = strlen(name);
1030 data.data = (void*)pa_tagstruct_data(t, &data.size);
1032 r = (pa_database_set(u->database, &key, &data, replace) == 0);
1034 pa_tagstruct_free(t);
1039 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
1041 #define LEGACY_ENTRY_VERSION 3
1042 static struct entry* legacy_entry_read(struct userdata *u, pa_datum *data) {
1043 struct legacy_entry {
1045 pa_bool_t muted_valid:1, volume_valid:1, device_valid:1, card_valid:1;
1047 pa_channel_map channel_map;
1049 char device[PA_NAME_MAX];
1050 char card[PA_NAME_MAX];
1052 struct legacy_entry *le;
1058 if (data->size != sizeof(struct legacy_entry)) {
1059 pa_log_debug("Size does not match.");
1063 le = (struct legacy_entry*)data->data;
1065 if (le->version != LEGACY_ENTRY_VERSION) {
1066 pa_log_debug("Version mismatch.");
1070 if (!memchr(le->device, 0, sizeof(le->device))) {
1071 pa_log_warn("Device has missing NUL byte.");
1075 if (!memchr(le->card, 0, sizeof(le->card))) {
1076 pa_log_warn("Card has missing NUL byte.");
1080 if (le->device_valid && !pa_namereg_is_valid_name(le->device)) {
1081 pa_log_warn("Invalid device name stored in database for legacy stream");
1085 if (le->card_valid && !pa_namereg_is_valid_name(le->card)) {
1086 pa_log_warn("Invalid card name stored in database for legacy stream");
1090 if (le->volume_valid && !pa_channel_map_valid(&le->channel_map)) {
1091 pa_log_warn("Invalid channel map stored in database for legacy stream");
1095 if (le->volume_valid && (!pa_cvolume_valid(&le->volume) || !pa_cvolume_compatible_with_channel_map(&le->volume, &le->channel_map))) {
1096 pa_log_warn("Invalid volume stored in database for legacy stream");
1101 e->muted_valid = le->muted_valid;
1102 e->muted = le->muted;
1103 e->volume_valid = le->volume_valid;
1104 e->channel_map = le->channel_map;
1105 e->volume = le->volume;
1106 e->device_valid = le->device_valid;
1107 e->device = pa_xstrdup(le->device);
1108 e->card_valid = le->card_valid;
1109 e->card = pa_xstrdup(le->card);
1114 static struct entry *entry_read(struct userdata *u, const char *name) {
1116 struct entry *e = NULL;
1117 pa_tagstruct *t = NULL;
1118 const char *device, *card;
1123 key.data = (char*) name;
1124 key.size = strlen(name);
1128 if (!pa_database_get(u->database, &key, &data))
1131 t = pa_tagstruct_new(data.data, data.size);
1134 if (pa_tagstruct_getu8(t, &e->version) < 0 ||
1135 e->version > ENTRY_VERSION ||
1136 pa_tagstruct_get_boolean(t, &e->volume_valid) < 0 ||
1137 pa_tagstruct_get_channel_map(t, &e->channel_map) < 0 ||
1138 pa_tagstruct_get_cvolume(t, &e->volume) < 0 ||
1139 pa_tagstruct_get_boolean(t, &e->muted_valid) < 0 ||
1140 pa_tagstruct_get_boolean(t, &e->muted) < 0 ||
1141 pa_tagstruct_get_boolean(t, &e->device_valid) < 0 ||
1142 pa_tagstruct_gets(t, &device) < 0 ||
1143 pa_tagstruct_get_boolean(t, &e->card_valid) < 0 ||
1144 pa_tagstruct_gets(t, &card) < 0) {
1149 e->device = pa_xstrdup(device);
1150 e->card = pa_xstrdup(card);
1152 if (!pa_tagstruct_eof(t))
1155 if (e->device_valid && !pa_namereg_is_valid_name(e->device)) {
1156 pa_log_warn("Invalid device name stored in database for stream %s", name);
1160 if (e->card_valid && !pa_namereg_is_valid_name(e->card)) {
1161 pa_log_warn("Invalid card name stored in database for stream %s", name);
1165 if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) {
1166 pa_log_warn("Invalid channel map stored in database for stream %s", name);
1170 if (e->volume_valid && (!pa_cvolume_valid(&e->volume) || !pa_cvolume_compatible_with_channel_map(&e->volume, &e->channel_map))) {
1171 pa_log_warn("Invalid volume stored in database for stream %s", name);
1175 pa_tagstruct_free(t);
1176 pa_datum_free(&data);
1182 pa_log_debug("Database contains invalid data for key: %s (probably pre-v1.0 data)", name);
1187 pa_tagstruct_free(t);
1189 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
1190 pa_log_debug("Attempting to load legacy (pre-v1.0) data for key: %s", name);
1191 if ((e = legacy_entry_read(u, &data))) {
1192 pa_log_debug("Success. Saving new format for key: %s", name);
1193 if (entry_write(u, name, e, TRUE))
1195 pa_datum_free(&data);
1198 pa_log_debug("Unable to load legacy (pre-v1.0) data for key: %s. Ignoring.", name);
1201 pa_datum_free(&data);
1205 static struct entry* entry_copy(const struct entry *e) {
1211 r->device = pa_xstrdup(e->device);
1212 r->card = pa_xstrdup(e->card);
1216 static void trigger_save(struct userdata *u) {
1217 pa_native_connection *c;
1220 for (c = pa_idxset_first(u->subscribed, &idx); c; c = pa_idxset_next(u->subscribed, &idx)) {
1223 t = pa_tagstruct_new(NULL, 0);
1224 pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
1225 pa_tagstruct_putu32(t, 0);
1226 pa_tagstruct_putu32(t, u->module->index);
1227 pa_tagstruct_puts(t, u->module->name);
1228 pa_tagstruct_putu32(t, SUBCOMMAND_EVENT);
1230 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
1233 if (u->save_time_event)
1236 u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
1239 static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) {
1245 if (a->device_valid != b->device_valid ||
1246 (a->device_valid && !pa_streq(a->device, b->device)))
1249 if (a->card_valid != b->card_valid ||
1250 (a->card_valid && !pa_streq(a->card, b->card)))
1253 if (a->muted_valid != b->muted_valid ||
1254 (a->muted_valid && (a->muted != b->muted)))
1258 if (a->volume_valid != b->volume_valid ||
1259 (a->volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->volume)))
1265 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
1266 struct userdata *u = userdata;
1267 struct entry *entry, *old = NULL;
1270 /* These are only used when D-Bus is enabled, but in order to reduce ifdef
1271 * clutter these are defined here unconditionally. */
1272 pa_bool_t created_new_entry = TRUE;
1273 pa_bool_t device_updated = FALSE;
1274 pa_bool_t volume_updated = FALSE;
1275 pa_bool_t mute_updated = FALSE;
1278 struct dbus_entry *de = NULL;
1284 if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1285 t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
1286 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) &&
1287 t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
1290 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
1291 pa_sink_input *sink_input;
1293 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx)))
1296 if (!(name = get_name(sink_input->proplist, "sink-input")))
1299 if ((old = entry_read(u, name))) {
1300 entry = entry_copy(old);
1301 created_new_entry = FALSE;
1303 entry = entry_new();
1305 if (sink_input->save_volume && pa_sink_input_is_volume_readable(sink_input)) {
1306 pa_assert(sink_input->volume_writable);
1308 entry->channel_map = sink_input->channel_map;
1309 pa_sink_input_get_volume(sink_input, &entry->volume, FALSE);
1310 entry->volume_valid = TRUE;
1312 volume_updated = !created_new_entry
1313 && (!old->volume_valid
1314 || !pa_channel_map_equal(&entry->channel_map, &old->channel_map)
1315 || !pa_cvolume_equal(&entry->volume, &old->volume));
1318 if (sink_input->save_muted) {
1319 entry->muted = pa_sink_input_get_mute(sink_input);
1320 entry->muted_valid = TRUE;
1322 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted);
1325 if (sink_input->save_sink) {
1326 pa_xfree(entry->device);
1327 entry->device = pa_xstrdup(sink_input->sink->name);
1328 entry->device_valid = TRUE;
1330 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry->device, old->device));
1331 if (sink_input->sink->card) {
1332 pa_xfree(entry->card);
1333 entry->card = pa_xstrdup(sink_input->sink->card->name);
1334 entry->card_valid = TRUE;
1339 pa_source_output *source_output;
1341 pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);
1343 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx)))
1346 if (!(name = get_name(source_output->proplist, "source-output")))
1349 if ((old = entry_read(u, name))) {
1350 entry = entry_copy(old);
1351 created_new_entry = FALSE;
1353 entry = entry_new();
1355 if (source_output->save_volume && pa_source_output_is_volume_readable(source_output)) {
1356 pa_assert(source_output->volume_writable);
1358 entry->channel_map = source_output->channel_map;
1359 pa_source_output_get_volume(source_output, &entry->volume, FALSE);
1360 entry->volume_valid = TRUE;
1362 volume_updated = !created_new_entry
1363 && (!old->volume_valid
1364 || !pa_channel_map_equal(&entry->channel_map, &old->channel_map)
1365 || !pa_cvolume_equal(&entry->volume, &old->volume));
1368 if (source_output->save_muted) {
1369 entry->muted = pa_source_output_get_mute(source_output);
1370 entry->muted_valid = TRUE;
1372 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted);
1375 if (source_output->save_source) {
1376 pa_xfree(entry->device);
1377 entry->device = pa_xstrdup(source_output->source->name);
1378 entry->device_valid = TRUE;
1380 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry->device, old->device));
1382 if (source_output->source->card) {
1383 pa_xfree(entry->card);
1384 entry->card = pa_xstrdup(source_output->source->card->name);
1385 entry->card_valid = TRUE;
1394 if (entries_equal(old, entry)) {
1404 pa_log_info("Storing volume/mute/device for stream %s.", name);
1406 if (entry_write(u, name, entry, TRUE))
1410 if (created_new_entry) {
1411 de = dbus_entry_new(u, name);
1412 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
1413 send_new_entry_signal(de);
1415 pa_assert_se(de = pa_hashmap_get(u->dbus_entries, name));
1418 send_device_updated_signal(de, entry);
1420 send_volume_updated_signal(de, entry);
1422 send_mute_updated_signal(de, entry);
1430 static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1435 pa_assert(new_data);
1437 pa_assert(u->restore_device);
1439 if (!(name = get_name(new_data->proplist, "sink-input")))
1443 pa_log_debug("Not restoring device for stream %s, because already set to '%s'.", name, new_data->sink->name);
1444 else if ((e = entry_read(u, name))) {
1447 if (e->device_valid)
1448 s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK);
1450 if (!s && e->card_valid) {
1453 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1454 s = pa_idxset_first(card->sinks, NULL);
1457 /* It might happen that a stream and a sink are set up at the
1458 same time, in which case we want to make sure we don't
1459 interfere with that */
1460 if (s && PA_SINK_IS_LINKED(pa_sink_get_state(s)))
1461 if (pa_sink_input_new_data_set_sink(new_data, s, TRUE))
1462 pa_log_info("Restoring device for stream %s.", name);
1472 static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1477 pa_assert(new_data);
1479 pa_assert(u->restore_volume || u->restore_muted);
1481 if (!(name = get_name(new_data->proplist, "sink-input")))
1484 if ((e = entry_read(u, name))) {
1486 if (u->restore_volume && e->volume_valid) {
1487 if (!new_data->volume_writable)
1488 pa_log_debug("Not restoring volume for sink input %s, because its volume can't be changed.", name);
1489 else if (new_data->volume_is_set)
1490 pa_log_debug("Not restoring volume for sink input %s, because already set.", name);
1494 pa_log_info("Restoring volume for sink input %s.", name);
1497 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1498 pa_sink_input_new_data_set_volume(new_data, &v);
1500 new_data->volume_is_absolute = FALSE;
1501 new_data->save_volume = TRUE;
1505 if (u->restore_muted && e->muted_valid) {
1507 if (!new_data->muted_is_set) {
1508 pa_log_info("Restoring mute state for sink input %s.", name);
1509 pa_sink_input_new_data_set_muted(new_data, e->muted);
1510 new_data->save_muted = TRUE;
1512 pa_log_debug("Not restoring mute state for sink input %s, because already set.", name);
1523 static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1528 pa_assert(new_data);
1530 pa_assert(u->restore_device);
1532 if (new_data->direct_on_input)
1535 if (!(name = get_name(new_data->proplist, "source-output")))
1538 if (new_data->source)
1539 pa_log_debug("Not restoring device for stream %s, because already set", name);
1540 else if ((e = entry_read(u, name))) {
1541 pa_source *s = NULL;
1543 if (e->device_valid)
1544 s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE);
1546 if (!s && e->card_valid) {
1549 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1550 s = pa_idxset_first(card->sources, NULL);
1553 /* It might happen that a stream and a sink are set up at the
1554 same time, in which case we want to make sure we don't
1555 interfere with that */
1556 if (s && PA_SOURCE_IS_LINKED(pa_source_get_state(s))) {
1557 pa_log_info("Restoring device for stream %s.", name);
1558 pa_source_output_new_data_set_source(new_data, s, TRUE);
1569 static pa_hook_result_t source_output_fixate_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1574 pa_assert(new_data);
1576 pa_assert(u->restore_volume || u->restore_muted);
1578 if (!(name = get_name(new_data->proplist, "source-output")))
1581 if ((e = entry_read(u, name))) {
1583 if (u->restore_volume && e->volume_valid) {
1584 if (!new_data->volume_writable)
1585 pa_log_debug("Not restoring volume for source output %s, because its volume can't be changed.", name);
1586 else if (new_data->volume_is_set)
1587 pa_log_debug("Not restoring volume for source output %s, because already set.", name);
1591 pa_log_info("Restoring volume for source output %s.", name);
1594 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1595 pa_source_output_new_data_set_volume(new_data, &v);
1597 new_data->volume_is_absolute = FALSE;
1598 new_data->save_volume = TRUE;
1602 if (u->restore_muted && e->muted_valid) {
1604 if (!new_data->muted_is_set) {
1605 pa_log_info("Restoring mute state for source output %s.", name);
1606 pa_source_output_new_data_set_muted(new_data, e->muted);
1607 new_data->save_muted = TRUE;
1609 pa_log_debug("Not restoring mute state for source output %s, because already set.", name);
1620 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1627 pa_assert(u->on_hotplug && u->restore_device);
1629 PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
1633 if (si->sink == sink)
1639 /* Skip this if it is already in the process of being moved
1644 /* It might happen that a stream and a sink are set up at the
1645 same time, in which case we want to make sure we don't
1646 interfere with that */
1647 if (!PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(si)))
1650 if (!(name = get_name(si->proplist, "sink-input")))
1653 if ((e = entry_read(u, name))) {
1654 if (e->device_valid && pa_streq(e->device, sink->name))
1655 pa_sink_input_move_to(si, sink, TRUE);
1666 static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1667 pa_source_output *so;
1673 pa_assert(u->on_hotplug && u->restore_device);
1675 PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
1679 if (so->source == source)
1682 if (so->save_source)
1685 if (so->direct_on_input)
1688 /* Skip this if it is already in the process of being moved anyway */
1692 /* It might happen that a stream and a source are set up at the
1693 same time, in which case we want to make sure we don't
1694 interfere with that */
1695 if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
1698 if (!(name = get_name(so->proplist, "source-output")))
1701 if ((e = entry_read(u, name))) {
1702 if (e->device_valid && pa_streq(e->device, source->name))
1703 pa_source_output_move_to(so, source, TRUE);
1714 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1721 pa_assert(u->on_rescue && u->restore_device);
1723 /* There's no point in doing anything if the core is shut down anyway */
1724 if (c->state == PA_CORE_SHUTDOWN)
1727 PA_IDXSET_FOREACH(si, sink->inputs, idx) {
1734 if (!(name = get_name(si->proplist, "sink-input")))
1737 if ((e = entry_read(u, name))) {
1739 if (e->device_valid) {
1742 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) &&
1744 PA_SINK_IS_LINKED(pa_sink_get_state(d)))
1745 pa_sink_input_move_to(si, d, TRUE);
1757 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1758 pa_source_output *so;
1764 pa_assert(u->on_rescue && u->restore_device);
1766 /* There's no point in doing anything if the core is shut down anyway */
1767 if (c->state == PA_CORE_SHUTDOWN)
1770 PA_IDXSET_FOREACH(so, source->outputs, idx) {
1774 if (so->direct_on_input)
1780 if (!(name = get_name(so->proplist, "source-output")))
1783 if ((e = entry_read(u, name))) {
1785 if (e->device_valid) {
1788 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) &&
1790 PA_SOURCE_IS_LINKED(pa_source_get_state(d)))
1791 pa_source_output_move_to(so, d, TRUE);
1803 #define EXT_VERSION 1
1805 static void entry_apply(struct userdata *u, const char *name, struct entry *e) {
1807 pa_source_output *so;
1814 PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
1818 if (!(n = get_name(si->proplist, "sink-input")))
1821 if (!pa_streq(name, n)) {
1827 if (u->restore_volume && e->volume_valid && si->volume_writable) {
1831 pa_log_info("Restoring volume for sink input %s.", name);
1832 pa_cvolume_remap(&v, &e->channel_map, &si->channel_map);
1833 pa_sink_input_set_volume(si, &v, TRUE, FALSE);
1836 if (u->restore_muted && e->muted_valid) {
1837 pa_log_info("Restoring mute state for sink input %s.", name);
1838 pa_sink_input_set_mute(si, e->muted, TRUE);
1841 if (u->restore_device) {
1842 if (!e->device_valid) {
1843 if (si->save_sink) {
1844 pa_log_info("Ensuring device is not saved for stream %s.", name);
1845 /* If the device is not valid we should make sure the
1846 save flag is cleared as the user may have specifically
1847 removed the sink element from the rule. */
1848 si->save_sink = FALSE;
1849 /* This is cheating a bit. The sink input itself has not changed
1850 but the rules governing it's routing have, so we fire this event
1851 such that other routing modules (e.g. module-device-manager)
1852 will pick up the change and reapply their routing */
1853 pa_subscription_post(si->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, si->index);
1855 } else if ((s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SINK))) {
1856 pa_log_info("Restoring device for stream %s.", name);
1857 pa_sink_input_move_to(si, s, TRUE);
1862 PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
1866 if (!(n = get_name(so->proplist, "source-output")))
1869 if (!pa_streq(name, n)) {
1875 if (u->restore_volume && e->volume_valid && so->volume_writable) {
1879 pa_log_info("Restoring volume for source output %s.", name);
1880 pa_cvolume_remap(&v, &e->channel_map, &so->channel_map);
1881 pa_source_output_set_volume(so, &v, TRUE, FALSE);
1884 if (u->restore_muted && e->muted_valid) {
1885 pa_log_info("Restoring mute state for source output %s.", name);
1886 pa_source_output_set_mute(so, e->muted, TRUE);
1889 if (u->restore_device) {
1890 if (!e->device_valid) {
1891 if (so->save_source) {
1892 pa_log_info("Ensuring device is not saved for stream %s.", name);
1893 /* If the device is not valid we should make sure the
1894 save flag is cleared as the user may have specifically
1895 removed the source element from the rule. */
1896 so->save_source = FALSE;
1897 /* This is cheating a bit. The source output itself has not changed
1898 but the rules governing it's routing have, so we fire this event
1899 such that other routing modules (e.g. module-device-manager)
1900 will pick up the change and reapply their routing */
1901 pa_subscription_post(so->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, so->index);
1903 } else if ((s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE))) {
1904 pa_log_info("Restoring device for stream %s.", name);
1905 pa_source_output_move_to(so, s, TRUE);
1912 PA_GCC_UNUSED static void stream_restore_dump_database(struct userdata *u) {
1916 done = !pa_database_first(u->database, &key, NULL);
1923 done = !pa_database_next(u->database, &key, &next_key, NULL);
1925 name = pa_xstrndup(key.data, key.size);
1926 pa_datum_free(&key);
1928 if ((e = entry_read(u, name))) {
1930 pa_log("name=%s", name);
1931 pa_log("device=%s %s", e->device, pa_yes_no(e->device_valid));
1932 pa_log("channel_map=%s", pa_channel_map_snprint(t, sizeof(t), &e->channel_map));
1933 pa_log("volume=%s %s", pa_cvolume_snprint(t, sizeof(t), &e->volume), pa_yes_no(e->volume_valid));
1934 pa_log("mute=%s %s", pa_yes_no(e->muted), pa_yes_no(e->volume_valid));
1945 static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
1948 pa_tagstruct *reply = NULL;
1957 if (pa_tagstruct_getu32(t, &command) < 0)
1960 reply = pa_tagstruct_new(NULL, 0);
1961 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1962 pa_tagstruct_putu32(reply, tag);
1965 case SUBCOMMAND_TEST: {
1966 if (!pa_tagstruct_eof(t))
1969 pa_tagstruct_putu32(reply, EXT_VERSION);
1973 case SUBCOMMAND_READ: {
1977 if (!pa_tagstruct_eof(t))
1980 done = !pa_database_first(u->database, &key, NULL);
1987 done = !pa_database_next(u->database, &key, &next_key, NULL);
1989 name = pa_xstrndup(key.data, key.size);
1990 pa_datum_free(&key);
1992 if ((e = entry_read(u, name))) {
1996 pa_tagstruct_puts(reply, name);
1997 pa_tagstruct_put_channel_map(reply, e->volume_valid ? &e->channel_map : pa_channel_map_init(&cm));
1998 pa_tagstruct_put_cvolume(reply, e->volume_valid ? &e->volume : pa_cvolume_init(&r));
1999 pa_tagstruct_puts(reply, e->device_valid ? e->device : NULL);
2000 pa_tagstruct_put_boolean(reply, e->muted_valid ? e->muted : FALSE);
2013 case SUBCOMMAND_WRITE: {
2015 pa_bool_t apply_immediately = FALSE;
2017 if (pa_tagstruct_getu32(t, &mode) < 0 ||
2018 pa_tagstruct_get_boolean(t, &apply_immediately) < 0)
2021 if (mode != PA_UPDATE_MERGE &&
2022 mode != PA_UPDATE_REPLACE &&
2023 mode != PA_UPDATE_SET)
2026 if (mode == PA_UPDATE_SET) {
2028 struct dbus_entry *de;
2031 PA_HASHMAP_FOREACH(de, u->dbus_entries, state) {
2032 send_entry_removed_signal(de);
2033 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, de->entry_name));
2036 pa_database_clear(u->database);
2039 while (!pa_tagstruct_eof(t)) {
2040 const char *name, *device;
2042 struct entry *entry;
2047 entry = entry_new();
2049 if (pa_tagstruct_gets(t, &name) < 0 ||
2050 pa_tagstruct_get_channel_map(t, &entry->channel_map) ||
2051 pa_tagstruct_get_cvolume(t, &entry->volume) < 0 ||
2052 pa_tagstruct_gets(t, &device) < 0 ||
2053 pa_tagstruct_get_boolean(t, &muted) < 0)
2056 if (!name || !*name) {
2061 entry->volume_valid = entry->volume.channels > 0;
2063 if (entry->volume_valid)
2064 if (!pa_cvolume_compatible_with_channel_map(&entry->volume, &entry->channel_map)) {
2069 entry->muted = muted;
2070 entry->muted_valid = TRUE;
2072 entry->device = pa_xstrdup(device);
2073 entry->device_valid = device && !!entry->device[0];
2075 if (entry->device_valid && !pa_namereg_is_valid_name(entry->device)) {
2081 old = entry_read(u, name);
2084 pa_log_debug("Client %s changes entry %s.",
2085 pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)),
2088 if (entry_write(u, name, entry, mode == PA_UPDATE_REPLACE)) {
2090 struct dbus_entry *de;
2093 pa_assert_se((de = pa_hashmap_get(u->dbus_entries, name)));
2095 if ((old->device_valid != entry->device_valid)
2096 || (entry->device_valid && !pa_streq(entry->device, old->device)))
2097 send_device_updated_signal(de, entry);
2099 if ((old->volume_valid != entry->volume_valid)
2100 || (entry->volume_valid && (!pa_cvolume_equal(&entry->volume, &old->volume)
2101 || !pa_channel_map_equal(&entry->channel_map, &old->channel_map))))
2102 send_volume_updated_signal(de, entry);
2104 if (!old->muted_valid || (entry->muted != old->muted))
2105 send_mute_updated_signal(de, entry);
2108 de = dbus_entry_new(u, name);
2109 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
2110 send_new_entry_signal(de);
2114 if (apply_immediately)
2115 entry_apply(u, name, entry);
2130 case SUBCOMMAND_DELETE:
2132 while (!pa_tagstruct_eof(t)) {
2136 struct dbus_entry *de;
2139 if (pa_tagstruct_gets(t, &name) < 0)
2143 if ((de = pa_hashmap_get(u->dbus_entries, name))) {
2144 send_entry_removed_signal(de);
2145 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, name));
2149 key.data = (char*) name;
2150 key.size = strlen(name);
2152 pa_database_unset(u->database, &key);
2159 case SUBCOMMAND_SUBSCRIBE: {
2163 if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
2164 !pa_tagstruct_eof(t))
2168 pa_idxset_put(u->subscribed, c, NULL);
2170 pa_idxset_remove_by_data(u->subscribed, c, NULL);
2179 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
2185 pa_tagstruct_free(reply);
2190 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
2195 pa_idxset_remove_by_data(u->subscribed, c, NULL);
2199 int pa__init(pa_module*m) {
2200 pa_modargs *ma = NULL;
2204 pa_source_output *so;
2206 pa_bool_t restore_device = TRUE, restore_volume = TRUE, restore_muted = TRUE, on_hotplug = TRUE, on_rescue = TRUE;
2214 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
2215 pa_log("Failed to parse module arguments");
2219 if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
2220 pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
2221 pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
2222 pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
2223 pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
2224 pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments");
2228 if (!restore_muted && !restore_volume && !restore_device)
2229 pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!");
2231 m->userdata = u = pa_xnew0(struct userdata, 1);
2234 u->restore_device = restore_device;
2235 u->restore_volume = restore_volume;
2236 u->restore_muted = restore_muted;
2237 u->on_hotplug = on_hotplug;
2238 u->on_rescue = on_rescue;
2239 u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
2241 u->protocol = pa_native_protocol_get(m->core);
2242 pa_native_protocol_install_ext(u->protocol, m, extension_cb);
2244 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);
2246 u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
2248 if (restore_device) {
2249 /* A little bit earlier than module-intended-roles ... */
2250 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);
2251 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);
2254 if (restore_device && on_hotplug) {
2255 /* A little bit earlier than module-intended-roles ... */
2256 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);
2257 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);
2260 if (restore_device && on_rescue) {
2261 /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */
2262 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);
2263 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);
2266 if (restore_volume || restore_muted) {
2267 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);
2268 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);
2271 if (!(fname = pa_state_path("stream-volumes", TRUE)))
2274 if (!(u->database = pa_database_open(fname, TRUE))) {
2275 pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
2280 pa_log_info("Successfully opened database file '%s'.", fname);
2284 u->dbus_protocol = pa_dbus_protocol_get(u->core);
2285 u->dbus_entries = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
2287 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, OBJECT_PATH, &stream_restore_interface_info, u) >= 0);
2288 pa_assert_se(pa_dbus_protocol_register_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2290 /* Create the initial dbus entries. */
2291 done = !pa_database_first(u->database, &key, NULL);
2295 struct dbus_entry *de;
2298 done = !pa_database_next(u->database, &key, &next_key, NULL);
2300 name = pa_xstrndup(key.data, key.size);
2301 pa_datum_free(&key);
2303 /* Use entry_read() for checking that the entry is valid. */
2304 if ((e = entry_read(u, name))) {
2305 de = dbus_entry_new(u, name);
2306 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
2316 PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx)
2317 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u);
2319 PA_IDXSET_FOREACH(so, m->core->source_outputs, idx)
2320 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, so->index, u);
2322 pa_modargs_free(ma);
2329 pa_modargs_free(ma);
2335 static void free_dbus_entry_cb(void *p, void *userdata) {
2336 struct dbus_entry *de = p;
2340 dbus_entry_free(de);
2344 void pa__done(pa_module*m) {
2349 if (!(u = m->userdata))
2353 if (u->dbus_protocol) {
2354 pa_assert(u->dbus_entries);
2356 pa_assert_se(pa_dbus_protocol_unregister_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2357 pa_assert_se(pa_dbus_protocol_remove_interface(u->dbus_protocol, OBJECT_PATH, stream_restore_interface_info.name) >= 0);
2359 pa_hashmap_free(u->dbus_entries, free_dbus_entry_cb, NULL);
2361 pa_dbus_protocol_unref(u->dbus_protocol);
2365 if (u->subscription)
2366 pa_subscription_free(u->subscription);
2368 if (u->sink_input_new_hook_slot)
2369 pa_hook_slot_free(u->sink_input_new_hook_slot);
2370 if (u->sink_input_fixate_hook_slot)
2371 pa_hook_slot_free(u->sink_input_fixate_hook_slot);
2372 if (u->source_output_new_hook_slot)
2373 pa_hook_slot_free(u->source_output_new_hook_slot);
2374 if (u->source_output_fixate_hook_slot)
2375 pa_hook_slot_free(u->source_output_fixate_hook_slot);
2377 if (u->sink_put_hook_slot)
2378 pa_hook_slot_free(u->sink_put_hook_slot);
2379 if (u->source_put_hook_slot)
2380 pa_hook_slot_free(u->source_put_hook_slot);
2382 if (u->sink_unlink_hook_slot)
2383 pa_hook_slot_free(u->sink_unlink_hook_slot);
2384 if (u->source_unlink_hook_slot)
2385 pa_hook_slot_free(u->source_unlink_hook_slot);
2387 if (u->connection_unlink_hook_slot)
2388 pa_hook_slot_free(u->connection_unlink_hook_slot);
2390 if (u->save_time_event)
2391 u->core->mainloop->time_free(u->save_time_event);
2394 pa_database_close(u->database);
2397 pa_native_protocol_remove_ext(u->protocol, m);
2398 pa_native_protocol_unref(u->protocol);
2402 pa_idxset_free(u->subscribed, NULL, NULL);