]> code.delx.au - pulseaudio/blob - src/modules/module-device-restore.c
495a91124d6c7541d7927af7c267ea9a5a33b900
[pulseaudio] / src / modules / module-device-restore.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2006-2008 Lennart Poettering
5 Copyright 2011 Colin Guthrie
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <unistd.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34
35 #include <pulse/xmalloc.h>
36 #include <pulse/volume.h>
37 #include <pulse/timeval.h>
38 #include <pulse/util.h>
39 #include <pulse/rtclock.h>
40 #include <pulse/format.h>
41 #include <pulse/internal.h>
42
43 #include <pulsecore/core-error.h>
44 #include <pulsecore/module.h>
45 #include <pulsecore/core-util.h>
46 #include <pulsecore/modargs.h>
47 #include <pulsecore/log.h>
48 #include <pulsecore/core-subscribe.h>
49 #include <pulsecore/sink-input.h>
50 #include <pulsecore/source-output.h>
51 #include <pulsecore/namereg.h>
52 #include <pulsecore/protocol-native.h>
53 #include <pulsecore/pstream.h>
54 #include <pulsecore/pstream-util.h>
55 #include <pulsecore/database.h>
56 #include <pulsecore/tagstruct.h>
57
58 #include "module-device-restore-symdef.h"
59
60 PA_MODULE_AUTHOR("Lennart Poettering");
61 PA_MODULE_DESCRIPTION("Automatically restore the volume/mute state of devices");
62 PA_MODULE_VERSION(PACKAGE_VERSION);
63 PA_MODULE_LOAD_ONCE(TRUE);
64 PA_MODULE_USAGE(
65 "restore_port=<Save/restore port?> "
66 "restore_volume=<Save/restore volumes?> "
67 "restore_muted=<Save/restore muted states?>");
68
69 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
70
71 static const char* const valid_modargs[] = {
72 "restore_volume",
73 "restore_muted",
74 "restore_port",
75 NULL
76 };
77
78 struct userdata {
79 pa_core *core;
80 pa_module *module;
81 pa_subscription *subscription;
82 pa_hook_slot
83 *sink_new_hook_slot,
84 *sink_fixate_hook_slot,
85 *source_new_hook_slot,
86 *source_fixate_hook_slot,
87 *connection_unlink_hook_slot;
88 pa_time_event *save_time_event;
89 pa_database *database;
90
91 pa_native_protocol *protocol;
92 pa_idxset *subscribed;
93
94 pa_bool_t restore_volume:1;
95 pa_bool_t restore_muted:1;
96 pa_bool_t restore_port:1;
97 };
98
99 /* Protocol extention commands */
100 enum {
101 SUBCOMMAND_TEST,
102 SUBCOMMAND_SUBSCRIBE,
103 SUBCOMMAND_EVENT,
104 SUBCOMMAND_READ_SINK_FORMATS_ALL,
105 SUBCOMMAND_READ_SINK_FORMATS,
106 SUBCOMMAND_SAVE_SINK_FORMATS
107 };
108
109
110 #define ENTRY_VERSION 1
111
112 struct entry {
113 uint8_t version;
114 pa_bool_t muted_valid, volume_valid, port_valid;
115 pa_bool_t muted;
116 pa_channel_map channel_map;
117 pa_cvolume volume;
118 char *port;
119 pa_idxset *formats;
120 };
121
122 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
123 struct userdata *u = userdata;
124
125 pa_assert(a);
126 pa_assert(e);
127 pa_assert(u);
128
129 pa_assert(e == u->save_time_event);
130 u->core->mainloop->time_free(u->save_time_event);
131 u->save_time_event = NULL;
132
133 pa_database_sync(u->database);
134 pa_log_info("Synced.");
135 }
136
137 static void trigger_save(struct userdata *u) {
138 if (u->save_time_event)
139 return;
140
141 u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
142 }
143
144 static struct entry* entry_new(pa_bool_t add_pcm_format) {
145 struct entry *r = pa_xnew0(struct entry, 1);
146 r->version = ENTRY_VERSION;
147 r->formats = pa_idxset_new(NULL, NULL);
148 if (add_pcm_format) {
149 pa_format_info *f = pa_format_info_new();
150 f->encoding = PA_ENCODING_PCM;
151 pa_idxset_put(r->formats, f, NULL);
152 }
153 return r;
154 }
155
156 static void entry_free(struct entry* e) {
157 pa_assert(e);
158
159 pa_idxset_free(e->formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
160 pa_xfree(e->port);
161 pa_xfree(e);
162 }
163
164 static pa_bool_t entry_write(struct userdata *u, const char *name, const struct entry *e) {
165 pa_tagstruct *t;
166 pa_datum key, data;
167 pa_bool_t r;
168 uint32_t i;
169 pa_format_info *f;
170 uint8_t n_formats;
171
172 pa_assert(u);
173 pa_assert(name);
174 pa_assert(e);
175
176 n_formats = pa_idxset_size(e->formats);
177 pa_assert(n_formats > 0);
178
179 t = pa_tagstruct_new(NULL, 0);
180 pa_tagstruct_putu8(t, e->version);
181 pa_tagstruct_put_boolean(t, e->volume_valid);
182 pa_tagstruct_put_channel_map(t, &e->channel_map);
183 pa_tagstruct_put_cvolume(t, &e->volume);
184 pa_tagstruct_put_boolean(t, e->muted_valid);
185 pa_tagstruct_put_boolean(t, e->muted);
186 pa_tagstruct_put_boolean(t, e->port_valid);
187 pa_tagstruct_puts(t, e->port);
188 pa_tagstruct_putu8(t, n_formats);
189
190 PA_IDXSET_FOREACH(f, e->formats, i) {
191 pa_tagstruct_put_format_info(t, f);
192 }
193
194 key.data = (char *) name;
195 key.size = strlen(name);
196
197 data.data = (void*)pa_tagstruct_data(t, &data.size);
198
199 r = (pa_database_set(u->database, &key, &data, TRUE) == 0);
200
201 pa_tagstruct_free(t);
202
203 return r;
204 }
205
206 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
207
208 #define LEGACY_ENTRY_VERSION 2
209 static struct entry* legacy_entry_read(struct userdata *u, pa_datum *data) {
210 struct legacy_entry {
211 uint8_t version;
212 pa_bool_t muted_valid:1, volume_valid:1, port_valid:1;
213 pa_bool_t muted:1;
214 pa_channel_map channel_map;
215 pa_cvolume volume;
216 char port[PA_NAME_MAX];
217 } PA_GCC_PACKED;
218 struct legacy_entry *le;
219 struct entry *e;
220
221 pa_assert(u);
222 pa_assert(data);
223
224 if (data->size != sizeof(struct legacy_entry)) {
225 pa_log_debug("Size does not match.");
226 return NULL;
227 }
228
229 le = (struct legacy_entry*)data->data;
230
231 if (le->version != LEGACY_ENTRY_VERSION) {
232 pa_log_debug("Version mismatch.");
233 return NULL;
234 }
235
236 if (!memchr(le->port, 0, sizeof(le->port))) {
237 pa_log_warn("Port has missing NUL byte.");
238 return NULL;
239 }
240
241 if (le->volume_valid && !pa_channel_map_valid(&le->channel_map)) {
242 pa_log_warn("Invalid channel map.");
243 return NULL;
244 }
245
246 if (le->volume_valid && (!pa_cvolume_valid(&le->volume) || !pa_cvolume_compatible_with_channel_map(&le->volume, &le->channel_map))) {
247 pa_log_warn("Volume and channel map don't match.");
248 return NULL;
249 }
250
251 e = entry_new(TRUE);
252 e->muted_valid = le->muted_valid;
253 e->volume_valid = le->volume_valid;
254 e->port_valid = le->port_valid;
255 e->muted = le->muted;
256 e->channel_map = le->channel_map;
257 e->volume = le->volume;
258 e->port = pa_xstrdup(le->port);
259 return e;
260 }
261 #endif
262
263 static struct entry* entry_read(struct userdata *u, const char *name) {
264 pa_datum key, data;
265 struct entry *e = NULL;
266 pa_tagstruct *t = NULL;
267 const char* port;
268 uint8_t i, n_formats;
269
270 pa_assert(u);
271 pa_assert(name);
272
273 key.data = (char*) name;
274 key.size = strlen(name);
275
276 pa_zero(data);
277
278 if (!pa_database_get(u->database, &key, &data))
279 goto fail;
280
281 t = pa_tagstruct_new(data.data, data.size);
282 e = entry_new(FALSE);
283
284 if (pa_tagstruct_getu8(t, &e->version) < 0 ||
285 e->version > ENTRY_VERSION ||
286 pa_tagstruct_get_boolean(t, &e->volume_valid) < 0 ||
287 pa_tagstruct_get_channel_map(t, &e->channel_map) < 0 ||
288 pa_tagstruct_get_cvolume(t, &e->volume) < 0 ||
289 pa_tagstruct_get_boolean(t, &e->muted_valid) < 0 ||
290 pa_tagstruct_get_boolean(t, &e->muted) < 0 ||
291 pa_tagstruct_get_boolean(t, &e->port_valid) < 0 ||
292 pa_tagstruct_gets(t, &port) < 0 ||
293 pa_tagstruct_getu8(t, &n_formats) < 0 || n_formats < 1) {
294
295 goto fail;
296 }
297
298 e->port = pa_xstrdup(port);
299
300 for (i = 0; i < n_formats; ++i) {
301 pa_format_info *f = pa_format_info_new();
302 if (pa_tagstruct_get_format_info(t, f) < 0) {
303 pa_format_info_free(f);
304 goto fail;
305 }
306 pa_idxset_put(e->formats, f, NULL);
307 }
308
309 if (!pa_tagstruct_eof(t))
310 goto fail;
311
312 if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) {
313 pa_log_warn("Invalid channel map stored in database for device %s", name);
314 goto fail;
315 }
316
317 if (e->volume_valid && (!pa_cvolume_valid(&e->volume) || !pa_cvolume_compatible_with_channel_map(&e->volume, &e->channel_map))) {
318 pa_log_warn("Volume and channel map don't match in database entry for device %s", name);
319 goto fail;
320 }
321
322 pa_tagstruct_free(t);
323 pa_datum_free(&data);
324
325 return e;
326
327 fail:
328
329 pa_log_debug("Database contains invalid data for key: %s (probably pre-v1.0 data)", name);
330
331 if (e)
332 entry_free(e);
333 if (t)
334 pa_tagstruct_free(t);
335
336 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
337 pa_log_debug("Attempting to load legacy (pre-v1.0) data for key: %s", name);
338 if ((e = legacy_entry_read(u, &data))) {
339 pa_log_debug("Success. Saving new format for key: %s", name);
340 if (entry_write(u, name, e))
341 trigger_save(u);
342 pa_datum_free(&data);
343 return e;
344 } else
345 pa_log_debug("Unable to load legacy (pre-v1.0) data for key: %s. Ignoring.", name);
346 #endif
347
348 pa_datum_free(&data);
349 return NULL;
350 }
351
352 static struct entry* entry_copy(const struct entry *e) {
353 struct entry* r;
354 uint32_t idx;
355 pa_format_info *f;
356
357 pa_assert(e);
358 r = entry_new(FALSE);
359 r->version = e->version;
360 r->muted_valid = e->muted_valid;
361 r->volume_valid = e->volume_valid;
362 r->port_valid = e->port_valid;
363 r->muted = e->muted;
364 r->channel_map = e->channel_map;
365 r->volume = e->volume;
366 r->port = pa_xstrdup(e->port);
367
368 PA_IDXSET_FOREACH(f, e->formats, idx) {
369 pa_idxset_put(r->formats, pa_format_info_copy(f), NULL);
370 }
371 return r;
372 }
373
374 static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) {
375 pa_cvolume t;
376
377 if (a->port_valid != b->port_valid ||
378 (a->port_valid && !pa_streq(a->port, b->port)))
379 return FALSE;
380
381 if (a->muted_valid != b->muted_valid ||
382 (a->muted_valid && (a->muted != b->muted)))
383 return FALSE;
384
385 t = b->volume;
386 if (a->volume_valid != b->volume_valid ||
387 (a->volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->volume)))
388 return FALSE;
389
390 if (pa_idxset_size(a->formats) != pa_idxset_size(b->formats))
391 return FALSE;
392
393 /** TODO: Compare a bit better */
394
395 return TRUE;
396 }
397
398 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
399 struct userdata *u = userdata;
400 struct entry *entry, *old;
401 char *name;
402
403 pa_assert(c);
404 pa_assert(u);
405
406 if (t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW) &&
407 t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE) &&
408 t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW) &&
409 t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE))
410 return;
411
412 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) {
413 pa_sink *sink;
414
415 if (!(sink = pa_idxset_get_by_index(c->sinks, idx)))
416 return;
417
418 name = pa_sprintf_malloc("sink:%s", sink->name);
419
420 if ((old = entry_read(u, name)))
421 entry = entry_copy(old);
422 else
423 entry = entry_new(TRUE);
424
425 if (sink->save_volume) {
426 entry->channel_map = sink->channel_map;
427 entry->volume = *pa_sink_get_volume(sink, FALSE);
428 entry->volume_valid = TRUE;
429 }
430
431 if (sink->save_muted) {
432 entry->muted = pa_sink_get_mute(sink, FALSE);
433 entry->muted_valid = TRUE;
434 }
435
436 if (sink->save_port) {
437 pa_xfree(entry->port);
438 entry->port = pa_xstrdup(sink->active_port ? sink->active_port->name : "");
439 entry->port_valid = TRUE;
440 }
441
442 } else {
443 pa_source *source;
444
445 pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE);
446
447 if (!(source = pa_idxset_get_by_index(c->sources, idx)))
448 return;
449
450 name = pa_sprintf_malloc("source:%s", source->name);
451
452 if ((old = entry_read(u, name)))
453 entry = entry_copy(old);
454 else
455 entry = entry_new(TRUE);
456
457 if (source->save_volume) {
458 entry->channel_map = source->channel_map;
459 entry->volume = *pa_source_get_volume(source, FALSE);
460 entry->volume_valid = TRUE;
461 }
462
463 if (source->save_muted) {
464 entry->muted = pa_source_get_mute(source, FALSE);
465 entry->muted_valid = TRUE;
466 }
467
468 if (source->save_port) {
469 pa_xfree(entry->port);
470 entry->port = pa_xstrdup(source->active_port ? source->active_port->name : "");
471 entry->port_valid = TRUE;
472 }
473 }
474
475 pa_assert(entry);
476
477 if (old) {
478
479 if (entries_equal(old, entry)) {
480 entry_free(old);
481 entry_free(entry);
482 pa_xfree(name);
483 return;
484 }
485
486 entry_free(old);
487 }
488
489 pa_log_info("Storing volume/mute/port for device %s.", name);
490
491 if (entry_write(u, name, entry))
492 trigger_save(u);
493
494 entry_free(entry);
495 pa_xfree(name);
496 }
497
498 static pa_hook_result_t sink_new_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) {
499 char *name;
500 struct entry *e;
501
502 pa_assert(c);
503 pa_assert(new_data);
504 pa_assert(u);
505 pa_assert(u->restore_port);
506
507 name = pa_sprintf_malloc("sink:%s", new_data->name);
508
509 if ((e = entry_read(u, name))) {
510
511 if (e->port_valid) {
512 if (!new_data->active_port) {
513 pa_log_info("Restoring port for sink %s.", name);
514 pa_sink_new_data_set_port(new_data, e->port);
515 new_data->save_port = TRUE;
516 } else
517 pa_log_debug("Not restoring port for sink %s, because already set.", name);
518 }
519
520 entry_free(e);
521 }
522
523 pa_xfree(name);
524
525 return PA_HOOK_OK;
526 }
527
528 static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) {
529 char *name;
530 struct entry *e;
531
532 pa_assert(c);
533 pa_assert(new_data);
534 pa_assert(u);
535 pa_assert(u->restore_volume || u->restore_muted);
536
537 name = pa_sprintf_malloc("sink:%s", new_data->name);
538
539 if ((e = entry_read(u, name))) {
540
541 if (u->restore_volume && e->volume_valid) {
542
543 if (!new_data->volume_is_set) {
544 pa_cvolume v;
545
546 pa_log_info("Restoring volume for sink %s.", new_data->name);
547
548 v = e->volume;
549 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
550 pa_sink_new_data_set_volume(new_data, &v);
551
552 new_data->save_volume = TRUE;
553 } else
554 pa_log_debug("Not restoring volume for sink %s, because already set.", new_data->name);
555 }
556
557 if (u->restore_muted && e->muted_valid) {
558
559 if (!new_data->muted_is_set) {
560 pa_log_info("Restoring mute state for sink %s.", new_data->name);
561 pa_sink_new_data_set_muted(new_data, e->muted);
562 new_data->save_muted = TRUE;
563 } else
564 pa_log_debug("Not restoring mute state for sink %s, because already set.", new_data->name);
565 }
566
567 entry_free(e);
568 }
569
570 pa_xfree(name);
571
572 return PA_HOOK_OK;
573 }
574
575 static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) {
576 char *name;
577 struct entry *e;
578
579 pa_assert(c);
580 pa_assert(new_data);
581 pa_assert(u);
582 pa_assert(u->restore_port);
583
584 name = pa_sprintf_malloc("source:%s", new_data->name);
585
586 if ((e = entry_read(u, name))) {
587
588 if (e->port_valid) {
589 if (!new_data->active_port) {
590 pa_log_info("Restoring port for source %s.", name);
591 pa_source_new_data_set_port(new_data, e->port);
592 new_data->save_port = TRUE;
593 } else
594 pa_log_debug("Not restoring port for source %s, because already set.", name);
595 }
596
597 entry_free(e);
598 }
599
600 pa_xfree(name);
601
602 return PA_HOOK_OK;
603 }
604
605 static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) {
606 char *name;
607 struct entry *e;
608
609 pa_assert(c);
610 pa_assert(new_data);
611 pa_assert(u);
612 pa_assert(u->restore_volume || u->restore_muted);
613
614 name = pa_sprintf_malloc("source:%s", new_data->name);
615
616 if ((e = entry_read(u, name))) {
617
618 if (u->restore_volume && e->volume_valid) {
619
620 if (!new_data->volume_is_set) {
621 pa_cvolume v;
622
623 pa_log_info("Restoring volume for source %s.", new_data->name);
624
625 v = e->volume;
626 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
627 pa_source_new_data_set_volume(new_data, &v);
628
629 new_data->save_volume = TRUE;
630 } else
631 pa_log_debug("Not restoring volume for source %s, because already set.", new_data->name);
632 }
633
634 if (u->restore_muted && e->muted_valid) {
635
636 if (!new_data->muted_is_set) {
637 pa_log_info("Restoring mute state for source %s.", new_data->name);
638 pa_source_new_data_set_muted(new_data, e->muted);
639 new_data->save_muted = TRUE;
640 } else
641 pa_log_debug("Not restoring mute state for source %s, because already set.", new_data->name);
642 }
643
644 entry_free(e);
645 }
646
647 pa_xfree(name);
648
649 return PA_HOOK_OK;
650 }
651
652 #define EXT_VERSION 1
653
654 static void read_sink_format_reply(struct userdata *u, pa_tagstruct *reply, pa_sink *sink) {
655 struct entry *e;
656 char *name;
657
658 pa_assert(u);
659 pa_assert(reply);
660 pa_assert(sink);
661
662 pa_tagstruct_putu32(reply, sink->index);
663
664 /* Read or create an entry */
665 name = pa_sprintf_malloc("sink:%s", sink->name);
666 if (!(e = entry_read(u, name))) {
667 /* Fake a reply with PCM encoding supported */
668 pa_format_info *f = pa_format_info_new();
669
670 pa_tagstruct_putu8(reply, 1);
671 f->encoding = PA_ENCODING_PCM;
672 pa_tagstruct_put_format_info(reply, f);
673
674 pa_format_info_free(f);
675 } else {
676 uint32_t idx;
677 pa_format_info *f;
678
679 /* Write all the formats from the entry to the reply */
680 pa_tagstruct_putu8(reply, pa_idxset_size(e->formats));
681 PA_IDXSET_FOREACH(f, e->formats, idx) {
682 pa_tagstruct_put_format_info(reply, f);
683 }
684 }
685 pa_xfree(name);
686 }
687
688 static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
689 struct userdata *u;
690 uint32_t command;
691 pa_tagstruct *reply = NULL;
692
693 pa_assert(p);
694 pa_assert(m);
695 pa_assert(c);
696 pa_assert(t);
697
698 u = m->userdata;
699
700 if (pa_tagstruct_getu32(t, &command) < 0)
701 goto fail;
702
703 reply = pa_tagstruct_new(NULL, 0);
704 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
705 pa_tagstruct_putu32(reply, tag);
706
707 switch (command) {
708 case SUBCOMMAND_TEST: {
709 if (!pa_tagstruct_eof(t))
710 goto fail;
711
712 pa_tagstruct_putu32(reply, EXT_VERSION);
713 break;
714 }
715
716 case SUBCOMMAND_SUBSCRIBE: {
717
718 pa_bool_t enabled;
719
720 if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
721 !pa_tagstruct_eof(t))
722 goto fail;
723
724 if (enabled)
725 pa_idxset_put(u->subscribed, c, NULL);
726 else
727 pa_idxset_remove_by_data(u->subscribed, c, NULL);
728
729 break;
730 }
731
732 case SUBCOMMAND_READ_SINK_FORMATS_ALL: {
733 pa_sink *sink;
734 uint32_t idx;
735
736 if (!pa_tagstruct_eof(t))
737 goto fail;
738
739 PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
740 read_sink_format_reply(u, reply, sink);
741 }
742
743 break;
744 }
745 case SUBCOMMAND_READ_SINK_FORMATS: {
746 uint32_t sink_index;
747 pa_sink *sink;
748
749 pa_assert(reply);
750
751 /* Get the sink index and the number of formats from the tagstruct */
752 if (pa_tagstruct_getu32(t, &sink_index) < 0)
753 goto fail;
754
755 if (!pa_tagstruct_eof(t))
756 goto fail;
757
758 /* Now find our sink */
759 if (!(sink = pa_idxset_get_by_index(u->core->sinks, sink_index)))
760 goto fail;
761
762 read_sink_format_reply(u, reply, sink);
763
764 break;
765 }
766
767 case SUBCOMMAND_SAVE_SINK_FORMATS: {
768
769 struct entry *e;
770 uint32_t sink_index;
771 char *name;
772 pa_sink *sink;
773 uint8_t i, n_formats;
774
775 /* Get the sink index and the number of formats from the tagstruct */
776 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
777 pa_tagstruct_getu8(t, &n_formats) < 0 || n_formats < 1) {
778
779 goto fail;
780 }
781
782 /* Now find our sink */
783 if (!(sink = pa_idxset_get_by_index(u->core->sinks, sink_index)))
784 goto fail;
785
786 /* Read or create an entry */
787 name = pa_sprintf_malloc("sink:%s", sink->name);
788 if (!(e = entry_read(u, name)))
789 e = entry_new(FALSE);
790
791 /* Read all the formats from our tagstruct */
792 for (i = 0; i < n_formats; ++i) {
793 pa_format_info *f = pa_format_info_new();
794 if (pa_tagstruct_get_format_info(t, f) < 0) {
795 pa_format_info_free(f);
796 pa_xfree(name);
797 goto fail;
798 }
799 pa_idxset_put(e->formats, f, NULL);
800 }
801
802 if (!pa_tagstruct_eof(t)) {
803 entry_free(e);
804 pa_xfree(name);
805 goto fail;
806 }
807
808 if (entry_write(u, name, e))
809 trigger_save(u);
810 else
811 pa_log_warn("Could not save format info for sink %s", sink->name);
812
813 pa_xfree(name);
814 entry_free(e);
815
816 break;
817 }
818
819 default:
820 goto fail;
821 }
822
823 pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
824 return 0;
825
826 fail:
827
828 if (reply)
829 pa_tagstruct_free(reply);
830
831 return -1;
832 }
833
834 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
835 pa_assert(p);
836 pa_assert(c);
837 pa_assert(u);
838
839 pa_idxset_remove_by_data(u->subscribed, c, NULL);
840 return PA_HOOK_OK;
841 }
842
843 int pa__init(pa_module*m) {
844 pa_modargs *ma = NULL;
845 struct userdata *u;
846 char *fname;
847 pa_sink *sink;
848 pa_source *source;
849 uint32_t idx;
850 pa_bool_t restore_volume = TRUE, restore_muted = TRUE, restore_port = TRUE;
851
852 pa_assert(m);
853
854 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
855 pa_log("Failed to parse module arguments");
856 goto fail;
857 }
858
859 if (pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
860 pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
861 pa_modargs_get_value_boolean(ma, "restore_port", &restore_port) < 0) {
862 pa_log("restore_port=, restore_volume= and restore_muted= expect boolean arguments");
863 goto fail;
864 }
865
866 if (!restore_muted && !restore_volume && !restore_port)
867 pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring port enabled!");
868
869 m->userdata = u = pa_xnew0(struct userdata, 1);
870 u->core = m->core;
871 u->module = m;
872 u->restore_volume = restore_volume;
873 u->restore_muted = restore_muted;
874 u->restore_port = restore_port;
875
876 u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
877
878 u->protocol = pa_native_protocol_get(m->core);
879 pa_native_protocol_install_ext(u->protocol, m, extension_cb);
880
881 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);
882
883 u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE, subscribe_callback, u);
884
885 if (restore_port) {
886 u->sink_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) sink_new_hook_callback, u);
887 u->source_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_new_hook_callback, u);
888 }
889
890 if (restore_muted || restore_volume) {
891 u->sink_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_fixate_hook_callback, u);
892 u->source_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_fixate_hook_callback, u);
893 }
894
895 if (!(fname = pa_state_path("device-volumes", TRUE)))
896 goto fail;
897
898 if (!(u->database = pa_database_open(fname, TRUE))) {
899 pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
900 pa_xfree(fname);
901 goto fail;
902 }
903
904 pa_log_info("Successfully opened database file '%s'.", fname);
905 pa_xfree(fname);
906
907 for (sink = pa_idxset_first(m->core->sinks, &idx); sink; sink = pa_idxset_next(m->core->sinks, &idx))
908 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, sink->index, u);
909
910 for (source = pa_idxset_first(m->core->sources, &idx); source; source = pa_idxset_next(m->core->sources, &idx))
911 subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW, source->index, u);
912
913 pa_modargs_free(ma);
914 return 0;
915
916 fail:
917 pa__done(m);
918
919 if (ma)
920 pa_modargs_free(ma);
921
922 return -1;
923 }
924
925 void pa__done(pa_module*m) {
926 struct userdata* u;
927
928 pa_assert(m);
929
930 if (!(u = m->userdata))
931 return;
932
933 if (u->subscription)
934 pa_subscription_free(u->subscription);
935
936 if (u->sink_fixate_hook_slot)
937 pa_hook_slot_free(u->sink_fixate_hook_slot);
938 if (u->source_fixate_hook_slot)
939 pa_hook_slot_free(u->source_fixate_hook_slot);
940 if (u->sink_new_hook_slot)
941 pa_hook_slot_free(u->sink_new_hook_slot);
942 if (u->source_new_hook_slot)
943 pa_hook_slot_free(u->source_new_hook_slot);
944
945 if (u->connection_unlink_hook_slot)
946 pa_hook_slot_free(u->connection_unlink_hook_slot);
947
948 if (u->save_time_event)
949 u->core->mainloop->time_free(u->save_time_event);
950
951 if (u->database)
952 pa_database_close(u->database);
953
954 if (u->protocol) {
955 pa_native_protocol_remove_ext(u->protocol, m);
956 pa_native_protocol_unref(u->protocol);
957 }
958
959 if (u->subscribed)
960 pa_idxset_free(u->subscribed, NULL, NULL);
961
962 pa_xfree(u);
963 }