]> code.delx.au - pulseaudio/blob - src/modules/module-stream-restore.c
5a4bce7b89e762caef4a76e47b6a8aaacbcb98ab
[pulseaudio] / src / modules / module-stream-restore.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2008 Lennart Poettering
5 Copyright 2009 Tanu Kaskinen
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <unistd.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33
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>
39
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>
55
56 #ifdef HAVE_DBUS
57 #include <pulsecore/dbus-util.h>
58 #include <pulsecore/protocol-dbus.h>
59 #endif
60
61 #include "module-stream-restore-symdef.h"
62
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);
67 PA_MODULE_USAGE(
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>");
74
75 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
76 #define IDENTIFICATION_PROPERTY "module-stream-restore.id"
77
78 #define DEFAULT_FALLBACK_FILE PA_DEFAULT_CONFIG_DIR"/stream-restore.table"
79 #define DEFAULT_FALLBACK_FILE_USER "stream-restore.table"
80
81 #define WHITESPACE "\n\r \t"
82
83 static const char* const valid_modargs[] = {
84 "restore_device",
85 "restore_volume",
86 "restore_muted",
87 "on_hotplug",
88 "on_rescue",
89 "fallback_table",
90 NULL
91 };
92
93 struct userdata {
94 pa_core *core;
95 pa_module *module;
96 pa_subscription *subscription;
97 pa_hook_slot
98 *sink_input_new_hook_slot,
99 *sink_input_fixate_hook_slot,
100 *source_output_new_hook_slot,
101 *source_output_fixate_hook_slot,
102 *sink_put_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;
109
110 bool restore_device:1;
111 bool restore_volume:1;
112 bool restore_muted:1;
113 bool on_hotplug:1;
114 bool on_rescue:1;
115
116 pa_native_protocol *protocol;
117 pa_idxset *subscribed;
118
119 #ifdef HAVE_DBUS
120 pa_dbus_protocol *dbus_protocol;
121 pa_hashmap *dbus_entries;
122 uint32_t next_index; /* For generating object paths for entries. */
123 #endif
124 };
125
126 #define ENTRY_VERSION 1
127
128 struct entry {
129 uint8_t version;
130 bool muted_valid, volume_valid, device_valid, card_valid;
131 bool muted;
132 pa_channel_map channel_map;
133 pa_cvolume volume;
134 char* device;
135 char* card;
136 };
137
138 enum {
139 SUBCOMMAND_TEST,
140 SUBCOMMAND_READ,
141 SUBCOMMAND_WRITE,
142 SUBCOMMAND_DELETE,
143 SUBCOMMAND_SUBSCRIBE,
144 SUBCOMMAND_EVENT
145 };
146
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);
154
155 #ifdef HAVE_DBUS
156
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"
161
162 #define DBUS_INTERFACE_REVISION 0
163
164 struct dbus_entry {
165 struct userdata *userdata;
166
167 char *entry_name;
168 uint32_t index;
169 char *object_path;
170 };
171
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);
174
175 static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
176
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);
179
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);
188
189 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
190
191 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata);
192
193 enum property_handler_index {
194 PROPERTY_HANDLER_INTERFACE_REVISION,
195 PROPERTY_HANDLER_ENTRIES,
196 PROPERTY_HANDLER_MAX
197 };
198
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
206 };
207
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 }
211 };
212
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 }
219 };
220
221 enum method_handler_index {
222 METHOD_HANDLER_ADD_ENTRY,
223 METHOD_HANDLER_GET_ENTRY_BY_NAME,
224 METHOD_HANDLER_MAX
225 };
226
227 enum entry_method_handler_index {
228 ENTRY_METHOD_HANDLER_REMOVE,
229 ENTRY_METHOD_HANDLER_MAX
230 };
231
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" } };
239
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 }
251 };
252
253 static pa_dbus_method_handler entry_method_handlers[ENTRY_METHOD_HANDLER_MAX] = {
254 [ENTRY_METHOD_HANDLER_REMOVE] = {
255 .method_name = "Remove",
256 .arguments = NULL,
257 .n_arguments = 0,
258 .receive_cb = handle_entry_remove }
259 };
260
261 enum signal_index {
262 SIGNAL_NEW_ENTRY,
263 SIGNAL_ENTRY_REMOVED,
264 SIGNAL_MAX
265 };
266
267 enum entry_signal_index {
268 ENTRY_SIGNAL_DEVICE_UPDATED,
269 ENTRY_SIGNAL_VOLUME_UPDATED,
270 ENTRY_SIGNAL_MUTE_UPDATED,
271 ENTRY_SIGNAL_MAX
272 };
273
274 static pa_dbus_arg_info new_entry_args[] = { { "entry", "o", NULL } };
275 static pa_dbus_arg_info entry_removed_args[] = { { "entry", "o", NULL } };
276
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 } };
280
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 }
284 };
285
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 }
290 };
291
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,
299 .signals = signals,
300 .n_signals = SIGNAL_MAX
301 };
302
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
312 };
313
314 static struct dbus_entry *dbus_entry_new(struct userdata *u, const char *entry_name) {
315 struct dbus_entry *de;
316
317 pa_assert(u);
318 pa_assert(entry_name);
319 pa_assert(*entry_name);
320
321 de = pa_xnew(struct dbus_entry, 1);
322 de->userdata = u;
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);
326
327 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, de->object_path, &entry_interface_info, de) >= 0);
328
329 return de;
330 }
331
332 static void dbus_entry_free(struct dbus_entry *de) {
333 pa_assert(de);
334
335 pa_assert_se(pa_dbus_protocol_remove_interface(de->userdata->dbus_protocol, de->object_path, entry_interface_info.name) >= 0);
336
337 pa_xfree(de->entry_name);
338 pa_xfree(de->object_path);
339 pa_xfree(de);
340 }
341
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;
353
354 pa_assert(conn);
355 pa_assert(msg);
356 pa_assert(iter);
357 pa_assert(pa_streq(dbus_message_iter_get_signature(iter), "a(uu)"));
358 pa_assert(map);
359 pa_assert(vol);
360
361 pa_channel_map_init(map);
362 pa_cvolume_init(vol);
363
364 map->channels = 0;
365 vol->channels = 0;
366
367 dbus_message_iter_recurse(iter, &array_iter);
368
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;
372
373 dbus_message_iter_recurse(&array_iter, &struct_iter);
374
375 dbus_message_iter_get_basic(&struct_iter, &chan_pos);
376
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);
379 return -1;
380 }
381
382 pa_assert_se(dbus_message_iter_next(&struct_iter));
383 dbus_message_iter_get_basic(&struct_iter, &chan_vol);
384
385 if (!PA_VOLUME_IS_VALID(chan_vol)) {
386 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u", chan_vol);
387 return -1;
388 }
389
390 if (map->channels < PA_CHANNELS_MAX) {
391 map->map[map->channels] = chan_pos;
392 vol->values[map->channels] = chan_vol;
393 }
394 ++map->channels;
395 ++vol->channels;
396
397 dbus_message_iter_next(&array_iter);
398 }
399
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);
402 return -1;
403 }
404
405 dbus_message_iter_next(iter);
406
407 return 0;
408 }
409
410 static void append_volume(DBusMessageIter *iter, struct entry *e) {
411 DBusMessageIter array_iter;
412 DBusMessageIter struct_iter;
413 unsigned i;
414
415 pa_assert(iter);
416 pa_assert(e);
417
418 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(uu)", &array_iter));
419
420 if (!e->volume_valid) {
421 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
422 return;
423 }
424
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));
427
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]));
430
431 pa_assert_se(dbus_message_iter_close_container(&array_iter, &struct_iter));
432 }
433
434 pa_assert_se(dbus_message_iter_close_container(iter, &array_iter));
435 }
436
437 static void append_volume_variant(DBusMessageIter *iter, struct entry *e) {
438 DBusMessageIter variant_iter;
439
440 pa_assert(iter);
441 pa_assert(e);
442
443 pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(uu)", &variant_iter));
444
445 append_volume(&variant_iter, e);
446
447 pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter));
448 }
449
450 static void send_new_entry_signal(struct dbus_entry *entry) {
451 DBusMessage *signal_msg;
452
453 pa_assert(entry);
454
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);
459 }
460
461 static void send_entry_removed_signal(struct dbus_entry *entry) {
462 DBusMessage *signal_msg;
463
464 pa_assert(entry);
465
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);
470 }
471
472 static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) {
473 DBusMessage *signal_msg;
474 const char *device;
475
476 pa_assert(de);
477 pa_assert(e);
478
479 device = e->device_valid ? e->device : "";
480
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);
485 }
486
487 static void send_volume_updated_signal(struct dbus_entry *de, struct entry *e) {
488 DBusMessage *signal_msg;
489 DBusMessageIter msg_iter;
490
491 pa_assert(de);
492 pa_assert(e);
493
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);
499 }
500
501 static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) {
502 DBusMessage *signal_msg;
503 dbus_bool_t muted;
504
505 pa_assert(de);
506 pa_assert(e);
507
508 pa_assert(e->muted_valid);
509
510 muted = e->muted;
511
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);
516 }
517
518 static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) {
519 dbus_uint32_t interface_revision = DBUS_INTERFACE_REVISION;
520
521 pa_assert(conn);
522 pa_assert(msg);
523
524 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &interface_revision);
525 }
526
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;
530 unsigned i = 0;
531 void *state = NULL;
532 struct dbus_entry *de;
533
534 pa_assert(u);
535 pa_assert(n);
536
537 *n = pa_hashmap_size(u->dbus_entries);
538
539 if (*n == 0)
540 return NULL;
541
542 entries = pa_xnew(const char *, *n);
543
544 PA_HASHMAP_FOREACH(de, u->dbus_entries, state)
545 entries[i++] = de->object_path;
546
547 return entries;
548 }
549
550 static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata) {
551 struct userdata *u = userdata;
552 const char **entries;
553 unsigned n;
554
555 pa_assert(conn);
556 pa_assert(msg);
557 pa_assert(u);
558
559 entries = get_entries(u, &n);
560
561 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, entries, n);
562
563 pa_xfree(entries);
564 }
565
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;
573 unsigned n_entries;
574
575 pa_assert(conn);
576 pa_assert(msg);
577 pa_assert(u);
578
579 interface_revision = DBUS_INTERFACE_REVISION;
580 entries = get_entries(u, &n_entries);
581
582 pa_assert_se((reply = dbus_message_new_method_return(msg)));
583
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));
586
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);
589
590 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
591
592 pa_assert_se(dbus_connection_send(conn, reply, NULL));
593
594 dbus_message_unref(reply);
595
596 pa_xfree(entries);
597 }
598
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;
604 pa_channel_map map;
605 pa_cvolume vol;
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;
610
611 pa_assert(conn);
612 pa_assert(msg);
613 pa_assert(u);
614
615 pa_assert_se(dbus_message_iter_init(msg, &msg_iter));
616 dbus_message_iter_get_basic(&msg_iter, &name);
617
618 pa_assert_se(dbus_message_iter_next(&msg_iter));
619 dbus_message_iter_get_basic(&msg_iter, &device);
620
621 pa_assert_se(dbus_message_iter_next(&msg_iter));
622 if (get_volume_arg(conn, msg, &msg_iter, &map, &vol) < 0)
623 return;
624
625 dbus_message_iter_get_basic(&msg_iter, &muted);
626
627 pa_assert_se(dbus_message_iter_next(&msg_iter));
628 dbus_message_iter_get_basic(&msg_iter, &apply_immediately);
629
630 if (!*name) {
631 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "An empty string was given as the entry name.");
632 return;
633 }
634
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;
639
640 pa_assert_se(e = entry_read(u, name));
641 mute_updated = e->muted != muted;
642 e->muted = muted;
643 e->muted_valid = true;
644
645 volume_updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
646 e->volume = vol;
647 e->channel_map = map;
648 e->volume_valid = !!map.channels;
649
650 device_updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
651 pa_xfree(e->device);
652 e->device = pa_xstrdup(device);
653 e->device_valid = !!device[0];
654
655 if (mute_updated)
656 send_mute_updated_signal(dbus_entry, e);
657 if (volume_updated)
658 send_volume_updated_signal(dbus_entry, e);
659 if (device_updated)
660 send_device_updated_signal(dbus_entry, e);
661
662 } else {
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);
665
666 e = entry_new();
667 e->muted_valid = true;
668 e->volume_valid = !!map.channels;
669 e->device_valid = !!device[0];
670 e->muted = muted;
671 e->volume = vol;
672 e->channel_map = map;
673 e->device = pa_xstrdup(device);
674
675 send_new_entry_signal(dbus_entry);
676 }
677
678 pa_assert_se(entry_write(u, name, e, true));
679
680 if (apply_immediately)
681 entry_apply(u, name, e);
682
683 trigger_save(u);
684
685 pa_dbus_send_empty_reply(conn, msg);
686
687 entry_free(e);
688 }
689
690 static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
691 struct userdata *u = userdata;
692 const char *name;
693 struct dbus_entry *de;
694
695 pa_assert(conn);
696 pa_assert(msg);
697 pa_assert(u);
698
699 pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID));
700
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.");
703 return;
704 }
705
706 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &de->object_path);
707 }
708
709 static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) {
710 struct dbus_entry *de = userdata;
711
712 pa_assert(conn);
713 pa_assert(msg);
714 pa_assert(de);
715
716 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &de->index);
717 }
718
719 static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) {
720 struct dbus_entry *de = userdata;
721
722 pa_assert(conn);
723 pa_assert(msg);
724 pa_assert(de);
725
726 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &de->entry_name);
727 }
728
729 static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
730 struct dbus_entry *de = userdata;
731 struct entry *e;
732 const char *device;
733
734 pa_assert(conn);
735 pa_assert(msg);
736 pa_assert(de);
737
738 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
739
740 device = e->device_valid ? e->device : "";
741
742 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &device);
743
744 entry_free(e);
745 }
746
747 static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
748 struct dbus_entry *de = userdata;
749 const char *device;
750 struct entry *e;
751 bool updated;
752
753 pa_assert(conn);
754 pa_assert(msg);
755 pa_assert(iter);
756 pa_assert(de);
757
758 dbus_message_iter_get_basic(iter, &device);
759
760 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
761
762 updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device);
763
764 if (updated) {
765 pa_xfree(e->device);
766 e->device = pa_xstrdup(device);
767 e->device_valid = !!device[0];
768
769 pa_assert_se(entry_write(de->userdata, de->entry_name, e, true));
770
771 entry_apply(de->userdata, de->entry_name, e);
772 send_device_updated_signal(de, e);
773 trigger_save(de->userdata);
774 }
775
776 pa_dbus_send_empty_reply(conn, msg);
777
778 entry_free(e);
779 }
780
781 static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) {
782 struct dbus_entry *de = userdata;
783 DBusMessage *reply;
784 DBusMessageIter msg_iter;
785 struct entry *e;
786
787 pa_assert(conn);
788 pa_assert(msg);
789 pa_assert(de);
790
791 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
792
793 pa_assert_se(reply = dbus_message_new_method_return(msg));
794
795 dbus_message_iter_init_append(reply, &msg_iter);
796 append_volume_variant(&msg_iter, e);
797
798 pa_assert_se(dbus_connection_send(conn, reply, NULL));
799
800 entry_free(e);
801 }
802
803 static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
804 struct dbus_entry *de = userdata;
805 pa_channel_map map;
806 pa_cvolume vol;
807 struct entry *e = NULL;
808 bool updated = false;
809
810 pa_assert(conn);
811 pa_assert(msg);
812 pa_assert(iter);
813 pa_assert(de);
814
815 if (get_volume_arg(conn, msg, iter, &map, &vol) < 0)
816 return;
817
818 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
819
820 updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol);
821
822 if (updated) {
823 e->volume = vol;
824 e->channel_map = map;
825 e->volume_valid = !!map.channels;
826
827 pa_assert_se(entry_write(de->userdata, de->entry_name, e, true));
828
829 entry_apply(de->userdata, de->entry_name, e);
830 send_volume_updated_signal(de, e);
831 trigger_save(de->userdata);
832 }
833
834 pa_dbus_send_empty_reply(conn, msg);
835
836 entry_free(e);
837 }
838
839 static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
840 struct dbus_entry *de = userdata;
841 struct entry *e;
842 dbus_bool_t mute;
843
844 pa_assert(conn);
845 pa_assert(msg);
846 pa_assert(de);
847
848 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
849
850 mute = e->muted_valid ? e->muted : FALSE;
851
852 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &mute);
853
854 entry_free(e);
855 }
856
857 static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) {
858 struct dbus_entry *de = userdata;
859 dbus_bool_t mute;
860 struct entry *e;
861 bool updated;
862
863 pa_assert(conn);
864 pa_assert(msg);
865 pa_assert(iter);
866 pa_assert(de);
867
868 dbus_message_iter_get_basic(iter, &mute);
869
870 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
871
872 updated = !e->muted_valid || e->muted != mute;
873
874 if (updated) {
875 e->muted = mute;
876 e->muted_valid = true;
877
878 pa_assert_se(entry_write(de->userdata, de->entry_name, e, true));
879
880 entry_apply(de->userdata, de->entry_name, e);
881 send_mute_updated_signal(de, e);
882 trigger_save(de->userdata);
883 }
884
885 pa_dbus_send_empty_reply(conn, msg);
886
887 entry_free(e);
888 }
889
890 static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
891 struct dbus_entry *de = userdata;
892 struct entry *e;
893 DBusMessage *reply = NULL;
894 DBusMessageIter msg_iter;
895 DBusMessageIter dict_iter;
896 DBusMessageIter dict_entry_iter;
897 const char *device;
898 dbus_bool_t mute;
899
900 pa_assert(conn);
901 pa_assert(msg);
902 pa_assert(de);
903
904 pa_assert_se(e = entry_read(de->userdata, de->entry_name));
905
906 device = e->device_valid ? e->device : "";
907 mute = e->muted_valid ? e->muted : FALSE;
908
909 pa_assert_se((reply = dbus_message_new_method_return(msg)));
910
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));
913
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);
917
918 pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter));
919
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);
922
923 pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter));
924
925 pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &mute);
926
927 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
928
929 pa_assert_se(dbus_connection_send(conn, reply, NULL));
930
931 dbus_message_unref(reply);
932
933 entry_free(e);
934 }
935
936 static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata) {
937 struct dbus_entry *de = userdata;
938 pa_datum key;
939
940 pa_assert(conn);
941 pa_assert(msg);
942 pa_assert(de);
943
944 key.data = de->entry_name;
945 key.size = strlen(de->entry_name);
946
947 pa_assert_se(pa_database_unset(de->userdata->database, &key) == 0);
948
949 send_entry_removed_signal(de);
950 trigger_save(de->userdata);
951
952 pa_assert_se(pa_hashmap_remove(de->userdata->dbus_entries, de->entry_name));
953 dbus_entry_free(de);
954
955 pa_dbus_send_empty_reply(conn, msg);
956 }
957
958 #endif /* HAVE_DBUS */
959
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;
962
963 pa_assert(a);
964 pa_assert(e);
965 pa_assert(u);
966
967 pa_assert(e == u->save_time_event);
968 u->core->mainloop->time_free(u->save_time_event);
969 u->save_time_event = NULL;
970
971 pa_database_sync(u->database);
972 pa_log_info("Synced.");
973 }
974
975 static struct entry* entry_new(void) {
976 struct entry *r = pa_xnew0(struct entry, 1);
977 r->version = ENTRY_VERSION;
978 return r;
979 }
980
981 static void entry_free(struct entry* e) {
982 pa_assert(e);
983
984 pa_xfree(e->device);
985 pa_xfree(e->card);
986 pa_xfree(e);
987 }
988
989 static bool entry_write(struct userdata *u, const char *name, const struct entry *e, bool replace) {
990 pa_tagstruct *t;
991 pa_datum key, data;
992 bool r;
993
994 pa_assert(u);
995 pa_assert(name);
996 pa_assert(e);
997
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);
1009
1010 key.data = (char *) name;
1011 key.size = strlen(name);
1012
1013 data.data = (void*)pa_tagstruct_data(t, &data.size);
1014
1015 r = (pa_database_set(u->database, &key, &data, replace) == 0);
1016
1017 pa_tagstruct_free(t);
1018
1019 return r;
1020 }
1021
1022 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
1023
1024 #define LEGACY_ENTRY_VERSION 3
1025 static struct entry *legacy_entry_read(struct userdata *u, const char *name) {
1026 struct legacy_entry {
1027 uint8_t version;
1028 bool muted_valid:1, volume_valid:1, device_valid:1, card_valid:1;
1029 bool muted:1;
1030 pa_channel_map channel_map;
1031 pa_cvolume volume;
1032 char device[PA_NAME_MAX];
1033 char card[PA_NAME_MAX];
1034 } PA_GCC_PACKED;
1035
1036 pa_datum key;
1037 pa_datum data;
1038 struct legacy_entry *le;
1039 struct entry *e;
1040
1041 pa_assert(u);
1042 pa_assert(name);
1043
1044 key.data = (char *) name;
1045 key.size = strlen(name);
1046
1047 pa_zero(data);
1048
1049 if (!pa_database_get(u->database, &key, &data))
1050 goto fail;
1051
1052 if (data.size != sizeof(struct legacy_entry)) {
1053 pa_log_debug("Size does not match.");
1054 goto fail;
1055 }
1056
1057 le = (struct legacy_entry *) data.data;
1058
1059 if (le->version != LEGACY_ENTRY_VERSION) {
1060 pa_log_debug("Version mismatch.");
1061 goto fail;
1062 }
1063
1064 if (!memchr(le->device, 0, sizeof(le->device))) {
1065 pa_log_warn("Device has missing NUL byte.");
1066 goto fail;
1067 }
1068
1069 if (!memchr(le->card, 0, sizeof(le->card))) {
1070 pa_log_warn("Card has missing NUL byte.");
1071 goto fail;
1072 }
1073
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");
1076 goto fail;
1077 }
1078
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");
1081 goto fail;
1082 }
1083
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");
1086 goto fail;
1087 }
1088
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");
1091 goto fail;
1092 }
1093
1094 e = entry_new();
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);
1104 return e;
1105
1106 fail:
1107 pa_datum_free(&data);
1108
1109 return NULL;
1110 }
1111 #endif
1112
1113 static struct entry *entry_read(struct userdata *u, const char *name) {
1114 pa_datum key, data;
1115 struct entry *e = NULL;
1116 pa_tagstruct *t = NULL;
1117 const char *device, *card;
1118
1119 pa_assert(u);
1120 pa_assert(name);
1121
1122 key.data = (char*) name;
1123 key.size = strlen(name);
1124
1125 pa_zero(data);
1126
1127 if (!pa_database_get(u->database, &key, &data))
1128 goto fail;
1129
1130 t = pa_tagstruct_new(data.data, data.size);
1131 e = entry_new();
1132
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) {
1144
1145 goto fail;
1146 }
1147
1148 e->device = pa_xstrdup(device);
1149 e->card = pa_xstrdup(card);
1150
1151 if (!pa_tagstruct_eof(t))
1152 goto fail;
1153
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);
1156 goto fail;
1157 }
1158
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);
1161 goto fail;
1162 }
1163
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);
1166 goto fail;
1167 }
1168
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);
1171 goto fail;
1172 }
1173
1174 pa_tagstruct_free(t);
1175 pa_datum_free(&data);
1176
1177 return e;
1178
1179 fail:
1180 if (e)
1181 entry_free(e);
1182 if (t)
1183 pa_tagstruct_free(t);
1184
1185 pa_datum_free(&data);
1186 return NULL;
1187 }
1188
1189 static struct entry* entry_copy(const struct entry *e) {
1190 struct entry* r;
1191
1192 pa_assert(e);
1193 r = entry_new();
1194 *r = *e;
1195 r->device = pa_xstrdup(e->device);
1196 r->card = pa_xstrdup(e->card);
1197 return r;
1198 }
1199
1200 static void trigger_save(struct userdata *u) {
1201 pa_native_connection *c;
1202 uint32_t idx;
1203
1204 PA_IDXSET_FOREACH(c, u->subscribed, idx) {
1205 pa_tagstruct *t;
1206
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);
1213
1214 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
1215 }
1216
1217 if (u->save_time_event)
1218 return;
1219
1220 u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
1221 }
1222
1223 static bool entries_equal(const struct entry *a, const struct entry *b) {
1224 pa_cvolume t;
1225
1226 pa_assert(a);
1227 pa_assert(b);
1228
1229 if (a->device_valid != b->device_valid ||
1230 (a->device_valid && !pa_streq(a->device, b->device)))
1231 return false;
1232
1233 if (a->card_valid != b->card_valid ||
1234 (a->card_valid && !pa_streq(a->card, b->card)))
1235 return false;
1236
1237 if (a->muted_valid != b->muted_valid ||
1238 (a->muted_valid && (a->muted != b->muted)))
1239 return false;
1240
1241 t = b->volume;
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)))
1244 return false;
1245
1246 return true;
1247 }
1248
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;
1252 char *name = NULL;
1253
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;
1260
1261 #ifdef HAVE_DBUS
1262 struct dbus_entry *de = NULL;
1263 #endif
1264
1265 pa_assert(c);
1266 pa_assert(u);
1267
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))
1272 return;
1273
1274 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
1275 pa_sink_input *sink_input;
1276
1277 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx)))
1278 return;
1279
1280 if (!(name = pa_proplist_get_stream_group(sink_input->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1281 return;
1282
1283 if ((old = entry_read(u, name))) {
1284 entry = entry_copy(old);
1285 created_new_entry = false;
1286 } else
1287 entry = entry_new();
1288
1289 if (sink_input->save_volume && pa_sink_input_is_volume_readable(sink_input)) {
1290 pa_assert(sink_input->volume_writable);
1291
1292 entry->channel_map = sink_input->channel_map;
1293 pa_sink_input_get_volume(sink_input, &entry->volume, false);
1294 entry->volume_valid = true;
1295
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));
1300 }
1301
1302 if (sink_input->save_muted) {
1303 entry->muted = pa_sink_input_get_mute(sink_input);
1304 entry->muted_valid = true;
1305
1306 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted);
1307 }
1308
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;
1313
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;
1319 }
1320 }
1321
1322 } else {
1323 pa_source_output *source_output;
1324
1325 pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);
1326
1327 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx)))
1328 return;
1329
1330 if (!(name = pa_proplist_get_stream_group(source_output->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1331 return;
1332
1333 if ((old = entry_read(u, name))) {
1334 entry = entry_copy(old);
1335 created_new_entry = false;
1336 } else
1337 entry = entry_new();
1338
1339 if (source_output->save_volume && pa_source_output_is_volume_readable(source_output)) {
1340 pa_assert(source_output->volume_writable);
1341
1342 entry->channel_map = source_output->channel_map;
1343 pa_source_output_get_volume(source_output, &entry->volume, false);
1344 entry->volume_valid = true;
1345
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));
1350 }
1351
1352 if (source_output->save_muted) {
1353 entry->muted = pa_source_output_get_mute(source_output);
1354 entry->muted_valid = true;
1355
1356 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted);
1357 }
1358
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;
1363
1364 device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry->device, old->device));
1365
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;
1370 }
1371 }
1372 }
1373
1374 pa_assert(entry);
1375
1376 if (old) {
1377
1378 if (entries_equal(old, entry)) {
1379 entry_free(old);
1380 entry_free(entry);
1381 pa_xfree(name);
1382 return;
1383 }
1384
1385 entry_free(old);
1386 }
1387
1388 pa_log_info("Storing volume/mute/device for stream %s.", name);
1389
1390 if (entry_write(u, name, entry, true))
1391 trigger_save(u);
1392
1393 #ifdef HAVE_DBUS
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);
1398 } else {
1399 pa_assert_se(de = pa_hashmap_get(u->dbus_entries, name));
1400
1401 if (device_updated)
1402 send_device_updated_signal(de, entry);
1403 if (volume_updated)
1404 send_volume_updated_signal(de, entry);
1405 if (mute_updated)
1406 send_mute_updated_signal(de, entry);
1407 }
1408 #endif
1409
1410 entry_free(entry);
1411 pa_xfree(name);
1412 }
1413
1414 static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1415 char *name;
1416 struct entry *e;
1417
1418 pa_assert(c);
1419 pa_assert(new_data);
1420 pa_assert(u);
1421 pa_assert(u->restore_device);
1422
1423 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1424 return PA_HOOK_OK;
1425
1426 if (new_data->sink)
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))) {
1429 pa_sink *s = NULL;
1430
1431 if (e->device_valid)
1432 s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK);
1433
1434 if (!s && e->card_valid) {
1435 pa_card *card;
1436
1437 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1438 s = pa_idxset_first(card->sinks, NULL);
1439 }
1440
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);
1447
1448 entry_free(e);
1449 }
1450
1451 pa_xfree(name);
1452
1453 return PA_HOOK_OK;
1454 }
1455
1456 static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
1457 char *name;
1458 struct entry *e;
1459
1460 pa_assert(c);
1461 pa_assert(new_data);
1462 pa_assert(u);
1463 pa_assert(u->restore_volume || u->restore_muted);
1464
1465 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1466 return PA_HOOK_OK;
1467
1468 if ((e = entry_read(u, name))) {
1469
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);
1475 else {
1476 pa_cvolume v;
1477
1478 pa_log_info("Restoring volume for sink input %s.", name);
1479
1480 v = e->volume;
1481 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1482 pa_sink_input_new_data_set_volume(new_data, &v);
1483
1484 new_data->volume_is_absolute = false;
1485 new_data->save_volume = true;
1486 }
1487 }
1488
1489 if (u->restore_muted && e->muted_valid) {
1490
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;
1495 } else
1496 pa_log_debug("Not restoring mute state for sink input %s, because already set.", name);
1497 }
1498
1499 entry_free(e);
1500 }
1501
1502 pa_xfree(name);
1503
1504 return PA_HOOK_OK;
1505 }
1506
1507 static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1508 char *name;
1509 struct entry *e;
1510
1511 pa_assert(c);
1512 pa_assert(new_data);
1513 pa_assert(u);
1514 pa_assert(u->restore_device);
1515
1516 if (new_data->direct_on_input)
1517 return PA_HOOK_OK;
1518
1519 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1520 return PA_HOOK_OK;
1521
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;
1526
1527 if (e->device_valid)
1528 s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE);
1529
1530 if (!s && e->card_valid) {
1531 pa_card *card;
1532
1533 if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
1534 s = pa_idxset_first(card->sources, NULL);
1535 }
1536
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);
1543 }
1544
1545 entry_free(e);
1546 }
1547
1548 pa_xfree(name);
1549
1550 return PA_HOOK_OK;
1551 }
1552
1553 static pa_hook_result_t source_output_fixate_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
1554 char *name;
1555 struct entry *e;
1556
1557 pa_assert(c);
1558 pa_assert(new_data);
1559 pa_assert(u);
1560 pa_assert(u->restore_volume || u->restore_muted);
1561
1562 if (!(name = pa_proplist_get_stream_group(new_data->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1563 return PA_HOOK_OK;
1564
1565 if ((e = entry_read(u, name))) {
1566
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);
1572 else {
1573 pa_cvolume v;
1574
1575 pa_log_info("Restoring volume for source output %s.", name);
1576
1577 v = e->volume;
1578 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
1579 pa_source_output_new_data_set_volume(new_data, &v);
1580
1581 new_data->volume_is_absolute = false;
1582 new_data->save_volume = true;
1583 }
1584 }
1585
1586 if (u->restore_muted && e->muted_valid) {
1587
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;
1592 } else
1593 pa_log_debug("Not restoring mute state for source output %s, because already set.", name);
1594 }
1595
1596 entry_free(e);
1597 }
1598
1599 pa_xfree(name);
1600
1601 return PA_HOOK_OK;
1602 }
1603
1604 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1605 pa_sink_input *si;
1606 uint32_t idx;
1607
1608 pa_assert(c);
1609 pa_assert(sink);
1610 pa_assert(u);
1611 pa_assert(u->on_hotplug && u->restore_device);
1612
1613 PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
1614 char *name;
1615 struct entry *e;
1616
1617 if (si->sink == sink)
1618 continue;
1619
1620 if (si->save_sink)
1621 continue;
1622
1623 /* Skip this if it is already in the process of being moved
1624 * anyway */
1625 if (!si->sink)
1626 continue;
1627
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)))
1632 continue;
1633
1634 if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1635 continue;
1636
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);
1640
1641 entry_free(e);
1642 }
1643
1644 pa_xfree(name);
1645 }
1646
1647 return PA_HOOK_OK;
1648 }
1649
1650 static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1651 pa_source_output *so;
1652 uint32_t idx;
1653
1654 pa_assert(c);
1655 pa_assert(source);
1656 pa_assert(u);
1657 pa_assert(u->on_hotplug && u->restore_device);
1658
1659 PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
1660 char *name;
1661 struct entry *e;
1662
1663 if (so->source == source)
1664 continue;
1665
1666 if (so->save_source)
1667 continue;
1668
1669 if (so->direct_on_input)
1670 continue;
1671
1672 /* Skip this if it is already in the process of being moved anyway */
1673 if (!so->source)
1674 continue;
1675
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)))
1680 continue;
1681
1682 if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1683 continue;
1684
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);
1688
1689 entry_free(e);
1690 }
1691
1692 pa_xfree(name);
1693 }
1694
1695 return PA_HOOK_OK;
1696 }
1697
1698 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1699 pa_sink_input *si;
1700 uint32_t idx;
1701
1702 pa_assert(c);
1703 pa_assert(sink);
1704 pa_assert(u);
1705 pa_assert(u->on_rescue && u->restore_device);
1706
1707 /* There's no point in doing anything if the core is shut down anyway */
1708 if (c->state == PA_CORE_SHUTDOWN)
1709 return PA_HOOK_OK;
1710
1711 PA_IDXSET_FOREACH(si, sink->inputs, idx) {
1712 char *name;
1713 struct entry *e;
1714
1715 if (!si->sink)
1716 continue;
1717
1718 if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1719 continue;
1720
1721 if ((e = entry_read(u, name))) {
1722
1723 if (e->device_valid) {
1724 pa_sink *d;
1725
1726 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) &&
1727 d != sink &&
1728 PA_SINK_IS_LINKED(pa_sink_get_state(d)))
1729 pa_sink_input_move_to(si, d, true);
1730 }
1731
1732 entry_free(e);
1733 }
1734
1735 pa_xfree(name);
1736 }
1737
1738 return PA_HOOK_OK;
1739 }
1740
1741 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1742 pa_source_output *so;
1743 uint32_t idx;
1744
1745 pa_assert(c);
1746 pa_assert(source);
1747 pa_assert(u);
1748 pa_assert(u->on_rescue && u->restore_device);
1749
1750 /* There's no point in doing anything if the core is shut down anyway */
1751 if (c->state == PA_CORE_SHUTDOWN)
1752 return PA_HOOK_OK;
1753
1754 PA_IDXSET_FOREACH(so, source->outputs, idx) {
1755 char *name;
1756 struct entry *e;
1757
1758 if (so->direct_on_input)
1759 continue;
1760
1761 if (!so->source)
1762 continue;
1763
1764 if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1765 continue;
1766
1767 if ((e = entry_read(u, name))) {
1768
1769 if (e->device_valid) {
1770 pa_source *d;
1771
1772 if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) &&
1773 d != source &&
1774 PA_SOURCE_IS_LINKED(pa_source_get_state(d)))
1775 pa_source_output_move_to(so, d, true);
1776 }
1777
1778 entry_free(e);
1779 }
1780
1781 pa_xfree(name);
1782 }
1783
1784 return PA_HOOK_OK;
1785 }
1786
1787 static int fill_db(struct userdata *u, const char *filename) {
1788 FILE *f;
1789 int n = 0;
1790 int ret = -1;
1791 char *fn = NULL;
1792
1793 pa_assert(u);
1794
1795 if (filename)
1796 f = fopen(fn = pa_xstrdup(filename), "r");
1797 else
1798 f = pa_open_config_file(DEFAULT_FALLBACK_FILE, DEFAULT_FALLBACK_FILE_USER, NULL, &fn);
1799
1800 if (!f) {
1801 if (filename)
1802 pa_log("Failed to open %s: %s", filename, pa_cstrerror(errno));
1803 else
1804 ret = 0;
1805
1806 goto finish;
1807 }
1808
1809 while (!feof(f)) {
1810 char ln[256];
1811 char *d, *v;
1812 double db;
1813
1814 if (!fgets(ln, sizeof(ln), f))
1815 break;
1816
1817 n++;
1818
1819 pa_strip_nl(ln);
1820
1821 if (!*ln || ln[0] == '#' || ln[0] == ';')
1822 continue;
1823
1824 d = ln+strcspn(ln, WHITESPACE);
1825 v = d+strspn(d, WHITESPACE);
1826
1827 if (!*v) {
1828 pa_log("[%s:%u] failed to parse line - too few words", fn, n);
1829 goto finish;
1830 }
1831
1832 *d = 0;
1833 if (pa_atod(v, &db) >= 0) {
1834 if (db <= 0.0) {
1835 pa_datum key, data;
1836 struct entry e;
1837
1838 pa_zero(e);
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);
1843
1844 key.data = (void *) ln;
1845 key.size = strlen(ln);
1846
1847 data.data = (void *) &e;
1848 data.size = sizeof(e);
1849
1850 if (pa_database_set(u->database, &key, &data, false) == 0)
1851 pa_log_debug("Setting %s to %0.2f dB.", ln, db);
1852 } else
1853 pa_log_warn("[%s:%u] Positive dB values are not allowed, not setting entry %s.", fn, n, ln);
1854 } else
1855 pa_log_warn("[%s:%u] Couldn't parse '%s' as a double, not setting entry %s.", fn, n, v, ln);
1856 }
1857
1858 trigger_save(u);
1859 ret = 0;
1860
1861 finish:
1862 if (f)
1863 fclose(f);
1864
1865 pa_xfree(fn);
1866
1867 return ret;
1868 }
1869
1870 static void entry_apply(struct userdata *u, const char *name, struct entry *e) {
1871 pa_sink_input *si;
1872 pa_source_output *so;
1873 uint32_t idx;
1874
1875 pa_assert(u);
1876 pa_assert(name);
1877 pa_assert(e);
1878
1879 PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
1880 char *n;
1881 pa_sink *s;
1882
1883 if (!(n = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
1884 continue;
1885
1886 if (!pa_streq(name, n)) {
1887 pa_xfree(n);
1888 continue;
1889 }
1890 pa_xfree(n);
1891
1892 if (u->restore_volume && e->volume_valid && si->volume_writable) {
1893 pa_cvolume v;
1894
1895 v = e->volume;
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);
1899 }
1900
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);
1904 }
1905
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 its 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);
1919 }
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);
1923 }
1924 }
1925 }
1926
1927 PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
1928 char *n;
1929 pa_source *s;
1930
1931 if (!(n = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
1932 continue;
1933
1934 if (!pa_streq(name, n)) {
1935 pa_xfree(n);
1936 continue;
1937 }
1938 pa_xfree(n);
1939
1940 if (u->restore_volume && e->volume_valid && so->volume_writable) {
1941 pa_cvolume v;
1942
1943 v = e->volume;
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);
1947 }
1948
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);
1952 }
1953
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 its 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);
1967 }
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);
1971 }
1972 }
1973 }
1974 }
1975
1976 #ifdef DEBUG_VOLUME
1977 PA_GCC_UNUSED static void stream_restore_dump_database(struct userdata *u) {
1978 pa_datum key;
1979 bool done;
1980
1981 done = !pa_database_first(u->database, &key, NULL);
1982
1983 while (!done) {
1984 pa_datum next_key;
1985 struct entry *e;
1986 char *name;
1987
1988 done = !pa_database_next(u->database, &key, &next_key, NULL);
1989
1990 name = pa_xstrndup(key.data, key.size);
1991 pa_datum_free(&key);
1992
1993 if ((e = entry_read(u, name))) {
1994 char t[256];
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));
2002 entry_free(e);
2003 }
2004
2005 pa_xfree(name);
2006
2007 key = next_key;
2008 }
2009 }
2010 #endif
2011
2012 #define EXT_VERSION 1
2013
2014 static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
2015 struct userdata *u;
2016 uint32_t command;
2017 pa_tagstruct *reply = NULL;
2018
2019 pa_assert(p);
2020 pa_assert(m);
2021 pa_assert(c);
2022 pa_assert(t);
2023
2024 u = m->userdata;
2025
2026 if (pa_tagstruct_getu32(t, &command) < 0)
2027 goto fail;
2028
2029 reply = pa_tagstruct_new(NULL, 0);
2030 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
2031 pa_tagstruct_putu32(reply, tag);
2032
2033 switch (command) {
2034 case SUBCOMMAND_TEST: {
2035 if (!pa_tagstruct_eof(t))
2036 goto fail;
2037
2038 pa_tagstruct_putu32(reply, EXT_VERSION);
2039 break;
2040 }
2041
2042 case SUBCOMMAND_READ: {
2043 pa_datum key;
2044 bool done;
2045
2046 if (!pa_tagstruct_eof(t))
2047 goto fail;
2048
2049 done = !pa_database_first(u->database, &key, NULL);
2050
2051 while (!done) {
2052 pa_datum next_key;
2053 struct entry *e;
2054 char *name;
2055
2056 done = !pa_database_next(u->database, &key, &next_key, NULL);
2057
2058 name = pa_xstrndup(key.data, key.size);
2059 pa_datum_free(&key);
2060
2061 if ((e = entry_read(u, name))) {
2062 pa_cvolume r;
2063 pa_channel_map cm;
2064
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);
2070
2071 entry_free(e);
2072 }
2073
2074 pa_xfree(name);
2075
2076 key = next_key;
2077 }
2078
2079 break;
2080 }
2081
2082 case SUBCOMMAND_WRITE: {
2083 uint32_t mode;
2084 bool apply_immediately = false;
2085
2086 if (pa_tagstruct_getu32(t, &mode) < 0 ||
2087 pa_tagstruct_get_boolean(t, &apply_immediately) < 0)
2088 goto fail;
2089
2090 if (mode != PA_UPDATE_MERGE &&
2091 mode != PA_UPDATE_REPLACE &&
2092 mode != PA_UPDATE_SET)
2093 goto fail;
2094
2095 if (mode == PA_UPDATE_SET) {
2096 #ifdef HAVE_DBUS
2097 struct dbus_entry *de;
2098 void *state = NULL;
2099
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));
2103 }
2104 #endif
2105 pa_database_clear(u->database);
2106 }
2107
2108 while (!pa_tagstruct_eof(t)) {
2109 const char *name, *device;
2110 bool muted;
2111 struct entry *entry;
2112 #ifdef HAVE_DBUS
2113 struct entry *old;
2114 #endif
2115
2116 entry = entry_new();
2117
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) {
2123 entry_free(entry);
2124 goto fail;
2125 }
2126
2127 if (!name || !*name) {
2128 entry_free(entry);
2129 goto fail;
2130 }
2131
2132 entry->volume_valid = entry->volume.channels > 0;
2133
2134 if (entry->volume_valid)
2135 if (!pa_cvolume_compatible_with_channel_map(&entry->volume, &entry->channel_map)) {
2136 entry_free(entry);
2137 goto fail;
2138 }
2139
2140 entry->muted = muted;
2141 entry->muted_valid = true;
2142
2143 entry->device = pa_xstrdup(device);
2144 entry->device_valid = device && !!entry->device[0];
2145
2146 if (entry->device_valid && !pa_namereg_is_valid_name(entry->device)) {
2147 entry_free(entry);
2148 goto fail;
2149 }
2150
2151 #ifdef HAVE_DBUS
2152 old = entry_read(u, name);
2153 #endif
2154
2155 pa_log_debug("Client %s changes entry %s.",
2156 pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)),
2157 name);
2158
2159 if (entry_write(u, name, entry, mode == PA_UPDATE_REPLACE)) {
2160 #ifdef HAVE_DBUS
2161 struct dbus_entry *de;
2162
2163 if (old) {
2164 pa_assert_se((de = pa_hashmap_get(u->dbus_entries, name)));
2165
2166 if ((old->device_valid != entry->device_valid)
2167 || (entry->device_valid && !pa_streq(entry->device, old->device)))
2168 send_device_updated_signal(de, entry);
2169
2170 if ((old->volume_valid != entry->volume_valid)
2171 || (entry->volume_valid && (!pa_cvolume_equal(&entry->volume, &old->volume)
2172 || !pa_channel_map_equal(&entry->channel_map, &old->channel_map))))
2173 send_volume_updated_signal(de, entry);
2174
2175 if (!old->muted_valid || (entry->muted != old->muted))
2176 send_mute_updated_signal(de, entry);
2177
2178 } else {
2179 de = dbus_entry_new(u, name);
2180 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
2181 send_new_entry_signal(de);
2182 }
2183 #endif
2184
2185 if (apply_immediately)
2186 entry_apply(u, name, entry);
2187 }
2188
2189 #ifdef HAVE_DBUS
2190 if (old)
2191 entry_free(old);
2192 #endif
2193 entry_free(entry);
2194 }
2195
2196 trigger_save(u);
2197
2198 break;
2199 }
2200
2201 case SUBCOMMAND_DELETE:
2202
2203 while (!pa_tagstruct_eof(t)) {
2204 const char *name;
2205 pa_datum key;
2206 #ifdef HAVE_DBUS
2207 struct dbus_entry *de;
2208 #endif
2209
2210 if (pa_tagstruct_gets(t, &name) < 0)
2211 goto fail;
2212
2213 #ifdef HAVE_DBUS
2214 if ((de = pa_hashmap_get(u->dbus_entries, name))) {
2215 send_entry_removed_signal(de);
2216 dbus_entry_free(pa_hashmap_remove(u->dbus_entries, name));
2217 }
2218 #endif
2219
2220 key.data = (char*) name;
2221 key.size = strlen(name);
2222
2223 pa_database_unset(u->database, &key);
2224 }
2225
2226 trigger_save(u);
2227
2228 break;
2229
2230 case SUBCOMMAND_SUBSCRIBE: {
2231
2232 bool enabled;
2233
2234 if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
2235 !pa_tagstruct_eof(t))
2236 goto fail;
2237
2238 if (enabled)
2239 pa_idxset_put(u->subscribed, c, NULL);
2240 else
2241 pa_idxset_remove_by_data(u->subscribed, c, NULL);
2242
2243 break;
2244 }
2245
2246 default:
2247 goto fail;
2248 }
2249
2250 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
2251 return 0;
2252
2253 fail:
2254
2255 if (reply)
2256 pa_tagstruct_free(reply);
2257
2258 return -1;
2259 }
2260
2261 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
2262 pa_assert(p);
2263 pa_assert(c);
2264 pa_assert(u);
2265
2266 pa_idxset_remove_by_data(u->subscribed, c, NULL);
2267 return PA_HOOK_OK;
2268 }
2269
2270 static void clean_up_db(struct userdata *u) {
2271 struct clean_up_item {
2272 PA_LLIST_FIELDS(struct clean_up_item);
2273 char *entry_name;
2274 struct entry *entry;
2275 };
2276
2277 PA_LLIST_HEAD(struct clean_up_item, to_be_removed);
2278 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2279 PA_LLIST_HEAD(struct clean_up_item, to_be_converted);
2280 #endif
2281 bool done = false;
2282 pa_datum key;
2283 struct clean_up_item *item = NULL;
2284 struct clean_up_item *next = NULL;
2285
2286 pa_assert(u);
2287
2288 /* It would be convenient to remove or replace the entries in the database
2289 * in the same loop that iterates through the database, but modifying the
2290 * database is not supported while iterating through it. That's why we
2291 * collect the entries that need to be removed or replaced to these
2292 * lists. */
2293 PA_LLIST_HEAD_INIT(struct clean_up_item, to_be_removed);
2294 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2295 PA_LLIST_HEAD_INIT(struct clean_up_item, to_be_converted);
2296 #endif
2297
2298 done = !pa_database_first(u->database, &key, NULL);
2299 while (!done) {
2300 pa_datum next_key;
2301 char *entry_name = NULL;
2302 struct entry *e = NULL;
2303
2304 entry_name = pa_xstrndup(key.data, key.size);
2305
2306 /* Use entry_read() to check whether this entry is valid. */
2307 if (!(e = entry_read(u, entry_name))) {
2308 item = pa_xnew0(struct clean_up_item, 1);
2309 PA_LLIST_INIT(struct clean_up_item, item);
2310 item->entry_name = entry_name;
2311
2312 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2313 /* entry_read() failed, but what about legacy_entry_read()? */
2314 if (!(e = legacy_entry_read(u, entry_name)))
2315 /* Not a legacy entry either, let's remove this. */
2316 PA_LLIST_PREPEND(struct clean_up_item, to_be_removed, item);
2317 else {
2318 /* Yay, it's valid after all! Now let's convert the entry to the current format. */
2319 item->entry = e;
2320 PA_LLIST_PREPEND(struct clean_up_item, to_be_converted, item);
2321 }
2322 #else
2323 /* Invalid entry, let's remove this. */
2324 PA_LLIST_PREPEND(struct clean_up_item, to_be_removed, item);
2325 #endif
2326 } else {
2327 pa_xfree(entry_name);
2328 entry_free(e);
2329 }
2330
2331 done = !pa_database_next(u->database, &key, &next_key, NULL);
2332 pa_datum_free(&key);
2333 key = next_key;
2334 }
2335
2336 PA_LLIST_FOREACH_SAFE(item, next, to_be_removed) {
2337 key.data = item->entry_name;
2338 key.size = strlen(item->entry_name);
2339
2340 pa_log_debug("Removing an invalid entry: %s", item->entry_name);
2341
2342 pa_assert_se(pa_database_unset(u->database, &key) >= 0);
2343 trigger_save(u);
2344
2345 PA_LLIST_REMOVE(struct clean_up_item, to_be_removed, item);
2346 pa_xfree(item->entry_name);
2347 pa_xfree(item);
2348 }
2349
2350 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
2351 PA_LLIST_FOREACH_SAFE(item, next, to_be_converted) {
2352 pa_log_debug("Upgrading a legacy entry to the current format: %s", item->entry_name);
2353
2354 pa_assert_se(entry_write(u, item->entry_name, item->entry, true) >= 0);
2355 trigger_save(u);
2356
2357 PA_LLIST_REMOVE(struct clean_up_item, to_be_converted, item);
2358 pa_xfree(item->entry_name);
2359 entry_free(item->entry);
2360 pa_xfree(item);
2361 }
2362 #endif
2363 }
2364
2365 int pa__init(pa_module*m) {
2366 pa_modargs *ma = NULL;
2367 struct userdata *u;
2368 char *fname;
2369 pa_sink_input *si;
2370 pa_source_output *so;
2371 uint32_t idx;
2372 bool restore_device = true, restore_volume = true, restore_muted = true, on_hotplug = true, on_rescue = true;
2373 #ifdef HAVE_DBUS
2374 pa_datum key;
2375 bool done;
2376 #endif
2377
2378 pa_assert(m);
2379
2380 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
2381 pa_log("Failed to parse module arguments");
2382 goto fail;
2383 }
2384
2385 if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
2386 pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
2387 pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
2388 pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
2389 pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
2390 pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments");
2391 goto fail;
2392 }
2393
2394 if (!restore_muted && !restore_volume && !restore_device)
2395 pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!");
2396
2397 m->userdata = u = pa_xnew0(struct userdata, 1);
2398 u->core = m->core;
2399 u->module = m;
2400 u->restore_device = restore_device;
2401 u->restore_volume = restore_volume;
2402 u->restore_muted = restore_muted;
2403 u->on_hotplug = on_hotplug;
2404 u->on_rescue = on_rescue;
2405 u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
2406
2407 u->protocol = pa_native_protocol_get(m->core);
2408 pa_native_protocol_install_ext(u->protocol, m, extension_cb);
2409
2410 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);
2411
2412 u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
2413
2414 if (restore_device) {
2415 /* A little bit earlier than module-intended-roles ... */
2416 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);
2417 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 }
2419
2420 if (restore_device && on_hotplug) {
2421 /* A little bit earlier than module-intended-roles ... */
2422 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);
2423 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 }
2425
2426 if (restore_device && on_rescue) {
2427 /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */
2428 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);
2429 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 }
2431
2432 if (restore_volume || restore_muted) {
2433 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);
2434 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 }
2436
2437 if (!(fname = pa_state_path("stream-volumes", true)))
2438 goto fail;
2439
2440 if (!(u->database = pa_database_open(fname, true))) {
2441 pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
2442 pa_xfree(fname);
2443 goto fail;
2444 }
2445
2446 pa_log_info("Successfully opened database file '%s'.", fname);
2447 pa_xfree(fname);
2448
2449 clean_up_db(u);
2450
2451 if (fill_db(u, pa_modargs_get_value(ma, "fallback_table", NULL)) < 0)
2452 goto fail;
2453
2454 #ifdef HAVE_DBUS
2455 u->dbus_protocol = pa_dbus_protocol_get(u->core);
2456 u->dbus_entries = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) dbus_entry_free);
2457
2458 pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, OBJECT_PATH, &stream_restore_interface_info, u) >= 0);
2459 pa_assert_se(pa_dbus_protocol_register_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2460
2461 /* Create the initial dbus entries. */
2462 done = !pa_database_first(u->database, &key, NULL);
2463 while (!done) {
2464 pa_datum next_key;
2465 char *name;
2466 struct dbus_entry *de;
2467
2468 name = pa_xstrndup(key.data, key.size);
2469 de = dbus_entry_new(u, name);
2470 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0);
2471 pa_xfree(name);
2472
2473 done = !pa_database_next(u->database, &key, &next_key, NULL);
2474 pa_datum_free(&key);
2475 key = next_key;
2476 }
2477 #endif
2478
2479 PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx)
2480 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u);
2481
2482 PA_IDXSET_FOREACH(so, m->core->source_outputs, idx)
2483 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, so->index, u);
2484
2485 pa_modargs_free(ma);
2486 return 0;
2487
2488 fail:
2489 pa__done(m);
2490
2491 if (ma)
2492 pa_modargs_free(ma);
2493
2494 return -1;
2495 }
2496
2497 void pa__done(pa_module*m) {
2498 struct userdata* u;
2499
2500 pa_assert(m);
2501
2502 if (!(u = m->userdata))
2503 return;
2504
2505 #ifdef HAVE_DBUS
2506 if (u->dbus_protocol) {
2507 pa_assert(u->dbus_entries);
2508
2509 pa_assert_se(pa_dbus_protocol_unregister_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0);
2510 pa_assert_se(pa_dbus_protocol_remove_interface(u->dbus_protocol, OBJECT_PATH, stream_restore_interface_info.name) >= 0);
2511
2512 pa_hashmap_free(u->dbus_entries);
2513
2514 pa_dbus_protocol_unref(u->dbus_protocol);
2515 }
2516 #endif
2517
2518 if (u->subscription)
2519 pa_subscription_free(u->subscription);
2520
2521 if (u->sink_input_new_hook_slot)
2522 pa_hook_slot_free(u->sink_input_new_hook_slot);
2523 if (u->sink_input_fixate_hook_slot)
2524 pa_hook_slot_free(u->sink_input_fixate_hook_slot);
2525 if (u->source_output_new_hook_slot)
2526 pa_hook_slot_free(u->source_output_new_hook_slot);
2527 if (u->source_output_fixate_hook_slot)
2528 pa_hook_slot_free(u->source_output_fixate_hook_slot);
2529
2530 if (u->sink_put_hook_slot)
2531 pa_hook_slot_free(u->sink_put_hook_slot);
2532 if (u->source_put_hook_slot)
2533 pa_hook_slot_free(u->source_put_hook_slot);
2534
2535 if (u->sink_unlink_hook_slot)
2536 pa_hook_slot_free(u->sink_unlink_hook_slot);
2537 if (u->source_unlink_hook_slot)
2538 pa_hook_slot_free(u->source_unlink_hook_slot);
2539
2540 if (u->connection_unlink_hook_slot)
2541 pa_hook_slot_free(u->connection_unlink_hook_slot);
2542
2543 if (u->save_time_event)
2544 u->core->mainloop->time_free(u->save_time_event);
2545
2546 if (u->database)
2547 pa_database_close(u->database);
2548
2549 if (u->protocol) {
2550 pa_native_protocol_remove_ext(u->protocol, m);
2551 pa_native_protocol_unref(u->protocol);
2552 }
2553
2554 if (u->subscribed)
2555 pa_idxset_free(u->subscribed, NULL);
2556
2557 pa_xfree(u);
2558 }