hashmap: Use pa_free_cb_t instead of pa_free2_cb_t
[platform/upstream/pulseaudio.git] / src / modules / module-device-manager.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2006-2008 Lennart Poettering
5   Copyright 2009 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
34 #include <pulse/gccmacro.h>
35 #include <pulse/xmalloc.h>
36 #include <pulse/timeval.h>
37 #include <pulse/rtclock.h>
38
39 #include <pulsecore/core-error.h>
40 #include <pulsecore/module.h>
41 #include <pulsecore/core-util.h>
42 #include <pulsecore/modargs.h>
43 #include <pulsecore/log.h>
44 #include <pulsecore/core-subscribe.h>
45 #include <pulsecore/sink-input.h>
46 #include <pulsecore/source-output.h>
47 #include <pulsecore/namereg.h>
48 #include <pulsecore/protocol-native.h>
49 #include <pulsecore/pstream.h>
50 #include <pulsecore/pstream-util.h>
51 #include <pulsecore/database.h>
52 #include <pulsecore/tagstruct.h>
53
54 #include "module-device-manager-symdef.h"
55
56 PA_MODULE_AUTHOR("Colin Guthrie");
57 PA_MODULE_DESCRIPTION("Keep track of devices (and their descriptions) both past and present and prioritise by role");
58 PA_MODULE_VERSION(PACKAGE_VERSION);
59 PA_MODULE_LOAD_ONCE(TRUE);
60 PA_MODULE_USAGE(
61     "do_routing=<Automatically route streams based on a priority list (unique per-role)?> "
62     "on_hotplug=<When new device becomes available, recheck streams?> "
63     "on_rescue=<When device becomes unavailable, recheck streams?>");
64
65 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
66 #define DUMP_DATABASE
67
68 static const char* const valid_modargs[] = {
69     "do_routing",
70     "on_hotplug",
71     "on_rescue",
72     NULL
73 };
74
75 #define NUM_ROLES 9
76 enum {
77     ROLE_NONE,
78     ROLE_VIDEO,
79     ROLE_MUSIC,
80     ROLE_GAME,
81     ROLE_EVENT,
82     ROLE_PHONE,
83     ROLE_ANIMATION,
84     ROLE_PRODUCTION,
85     ROLE_A11Y,
86     ROLE_MAX
87 };
88
89 typedef uint32_t role_indexes_t[NUM_ROLES];
90
91 static const char* role_names[NUM_ROLES] = {
92     "none",
93     "video",
94     "music",
95     "game",
96     "event",
97     "phone",
98     "animation",
99     "production",
100     "a11y",
101 };
102
103 struct userdata {
104     pa_core *core;
105     pa_module *module;
106     pa_subscription *subscription;
107     pa_hook_slot
108         *sink_new_hook_slot,
109         *source_new_hook_slot,
110         *sink_input_new_hook_slot,
111         *source_output_new_hook_slot,
112         *sink_put_hook_slot,
113         *source_put_hook_slot,
114         *sink_unlink_hook_slot,
115         *source_unlink_hook_slot,
116         *connection_unlink_hook_slot;
117     pa_time_event *save_time_event;
118     pa_database *database;
119
120     pa_native_protocol *protocol;
121     pa_idxset *subscribed;
122
123     pa_bool_t on_hotplug;
124     pa_bool_t on_rescue;
125     pa_bool_t do_routing;
126
127     role_indexes_t preferred_sinks;
128     role_indexes_t preferred_sources;
129 };
130
131 #define ENTRY_VERSION 1
132
133 struct entry {
134     uint8_t version;
135     char *description;
136     pa_bool_t user_set_description;
137     char *icon;
138     role_indexes_t priority;
139 };
140
141 enum {
142     SUBCOMMAND_TEST,
143     SUBCOMMAND_READ,
144     SUBCOMMAND_RENAME,
145     SUBCOMMAND_DELETE,
146     SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING,
147     SUBCOMMAND_REORDER,
148     SUBCOMMAND_SUBSCRIBE,
149     SUBCOMMAND_EVENT
150 };
151
152
153 /* Forward declarations */
154 #ifdef DUMP_DATABASE
155 static void dump_database(struct userdata *);
156 #endif
157 static void notify_subscribers(struct userdata *);
158
159
160 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
161     struct userdata *u = userdata;
162
163     pa_assert(a);
164     pa_assert(e);
165     pa_assert(u);
166
167     pa_assert(e == u->save_time_event);
168     u->core->mainloop->time_free(u->save_time_event);
169     u->save_time_event = NULL;
170
171     pa_database_sync(u->database);
172     pa_log_info("Synced.");
173
174 #ifdef DUMP_DATABASE
175     dump_database(u);
176 #endif
177 }
178
179 static void trigger_save(struct userdata *u) {
180
181     pa_assert(u);
182
183     notify_subscribers(u);
184
185     if (u->save_time_event)
186         return;
187
188     u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
189 }
190
191 static struct entry* entry_new(void) {
192     struct entry *r = pa_xnew0(struct entry, 1);
193     r->version = ENTRY_VERSION;
194     return r;
195 }
196
197 static void entry_free(struct entry* e) {
198     pa_assert(e);
199
200     pa_xfree(e->description);
201     pa_xfree(e->icon);
202     pa_xfree(e);
203 }
204
205 static pa_bool_t entry_write(struct userdata *u, const char *name, const struct entry *e) {
206     pa_tagstruct *t;
207     pa_datum key, data;
208     pa_bool_t r;
209
210     pa_assert(u);
211     pa_assert(name);
212     pa_assert(e);
213
214     t = pa_tagstruct_new(NULL, 0);
215     pa_tagstruct_putu8(t, e->version);
216     pa_tagstruct_puts(t, e->description);
217     pa_tagstruct_put_boolean(t, e->user_set_description);
218     pa_tagstruct_puts(t, e->icon);
219     for (uint8_t i=0; i<ROLE_MAX; ++i)
220         pa_tagstruct_putu32(t, e->priority[i]);
221
222     key.data = (char *) name;
223     key.size = strlen(name);
224
225     data.data = (void*)pa_tagstruct_data(t, &data.size);
226
227     r = (pa_database_set(u->database, &key, &data, TRUE) == 0);
228
229     pa_tagstruct_free(t);
230
231     return r;
232 }
233
234 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
235
236 #define LEGACY_ENTRY_VERSION 1
237 static struct entry* legacy_entry_read(struct userdata *u, pa_datum *data) {
238     struct legacy_entry {
239         uint8_t version;
240         char description[PA_NAME_MAX];
241         pa_bool_t user_set_description;
242         char icon[PA_NAME_MAX];
243         role_indexes_t priority;
244     } PA_GCC_PACKED;
245     struct legacy_entry *le;
246     struct entry *e;
247
248     pa_assert(u);
249     pa_assert(data);
250
251     if (data->size != sizeof(struct legacy_entry)) {
252         pa_log_debug("Size does not match.");
253         return NULL;
254     }
255
256     le = (struct legacy_entry*)data->data;
257
258     if (le->version != LEGACY_ENTRY_VERSION) {
259         pa_log_debug("Version mismatch.");
260         return NULL;
261     }
262
263     if (!memchr(le->description, 0, sizeof(le->description))) {
264         pa_log_warn("Description has missing NUL byte.");
265         return NULL;
266     }
267
268     if (!memchr(le->icon, 0, sizeof(le->icon))) {
269         pa_log_warn("Icon has missing NUL byte.");
270         return NULL;
271     }
272
273     e = entry_new();
274     e->description = pa_xstrdup(le->description);
275     e->icon = pa_xstrdup(le->icon);
276     return e;
277 }
278 #endif
279
280 static struct entry* entry_read(struct userdata *u, const char *name) {
281     pa_datum key, data;
282     struct entry *e = NULL;
283     pa_tagstruct *t = NULL;
284     const char *description, *icon;
285
286     pa_assert(u);
287     pa_assert(name);
288
289     key.data = (char*) name;
290     key.size = strlen(name);
291
292     pa_zero(data);
293
294     if (!pa_database_get(u->database, &key, &data))
295         goto fail;
296
297     t = pa_tagstruct_new(data.data, data.size);
298     e = entry_new();
299
300     if (pa_tagstruct_getu8(t, &e->version) < 0 ||
301         e->version > ENTRY_VERSION ||
302         pa_tagstruct_gets(t, &description) < 0 ||
303         pa_tagstruct_get_boolean(t, &e->user_set_description) < 0 ||
304         pa_tagstruct_gets(t, &icon) < 0) {
305
306         goto fail;
307     }
308
309     e->description = pa_xstrdup(description);
310     e->icon = pa_xstrdup(icon);
311
312     for (uint8_t i=0; i<ROLE_MAX; ++i) {
313         if (pa_tagstruct_getu32(t, &e->priority[i]) < 0)
314             goto fail;
315     }
316
317     if (!pa_tagstruct_eof(t))
318         goto fail;
319
320     pa_tagstruct_free(t);
321     pa_datum_free(&data);
322
323     return e;
324
325 fail:
326     pa_log_debug("Database contains invalid data for key: %s (probably pre-v1.0 data)", name);
327
328     if (e)
329         entry_free(e);
330     if (t)
331         pa_tagstruct_free(t);
332
333 #ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
334     pa_log_debug("Attempting to load legacy (pre-v1.0) data for key: %s", name);
335     if ((e = legacy_entry_read(u, &data))) {
336         pa_log_debug("Success. Saving new format for key: %s", name);
337         if (entry_write(u, name, e))
338             trigger_save(u);
339         pa_datum_free(&data);
340         return e;
341     } else
342         pa_log_debug("Unable to load legacy (pre-v1.0) data for key: %s. Ignoring.", name);
343 #endif
344
345     pa_datum_free(&data);
346     return NULL;
347 }
348
349 #ifdef DUMP_DATABASE
350 static void dump_database_helper(struct userdata *u, uint32_t role_index, const char* human, pa_bool_t sink_mode) {
351     pa_assert(u);
352     pa_assert(human);
353
354     if (sink_mode) {
355         pa_sink *s;
356         if (PA_INVALID_INDEX != u->preferred_sinks[role_index] && (s = pa_idxset_get_by_index(u->core->sinks, u->preferred_sinks[role_index])))
357             pa_log_debug("   %s %s (%s)", human, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION)), s->name);
358         else
359             pa_log_debug("   %s No sink specified", human);
360     } else {
361         pa_source *s;
362         if (PA_INVALID_INDEX != u->preferred_sources[role_index] && (s = pa_idxset_get_by_index(u->core->sources, u->preferred_sources[role_index])))
363             pa_log_debug("   %s %s (%s)", human, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION)), s->name);
364         else
365             pa_log_debug("   %s No source specified", human);
366     }
367 }
368
369 static void dump_database(struct userdata *u) {
370     pa_datum key;
371     pa_bool_t done;
372
373     pa_assert(u);
374
375     done = !pa_database_first(u->database, &key, NULL);
376
377     pa_log_debug("Dumping database");
378     while (!done) {
379         char *name;
380         struct entry *e;
381         pa_datum next_key;
382
383         done = !pa_database_next(u->database, &key, &next_key, NULL);
384
385         name = pa_xstrndup(key.data, key.size);
386
387         if ((e = entry_read(u, name))) {
388             pa_log_debug(" Got entry: %s", name);
389             pa_log_debug("  Description: %s", e->description);
390             pa_log_debug("  Priorities: None:   %3u, Video: %3u, Music:  %3u, Game: %3u, Event: %3u",
391                          e->priority[ROLE_NONE], e->priority[ROLE_VIDEO], e->priority[ROLE_MUSIC], e->priority[ROLE_GAME], e->priority[ROLE_EVENT]);
392             pa_log_debug("              Phone:  %3u, Anim:  %3u, Prodtn: %3u, A11y: %3u",
393                          e->priority[ROLE_PHONE], e->priority[ROLE_ANIMATION], e->priority[ROLE_PRODUCTION], e->priority[ROLE_A11Y]);
394             entry_free(e);
395         }
396
397         pa_xfree(name);
398
399         pa_datum_free(&key);
400         key = next_key;
401     }
402
403     if (u->do_routing) {
404         pa_log_debug(" Highest priority devices per-role:");
405
406         pa_log_debug("  Sinks:");
407         for (uint32_t role = ROLE_NONE; role < NUM_ROLES; ++role) {
408             char name[13];
409             uint32_t len = PA_MIN(12u, strlen(role_names[role]));
410             strncpy(name, role_names[role], len);
411             for (int i = len+1; i < 12; ++i) name[i] = ' ';
412             name[len] = ':'; name[0] -= 32; name[12] = '\0';
413             dump_database_helper(u, role, name, TRUE);
414         }
415
416         pa_log_debug("  Sources:");
417         for (uint32_t role = ROLE_NONE; role < NUM_ROLES; ++role) {
418             char name[13];
419             uint32_t len = PA_MIN(12u, strlen(role_names[role]));
420             strncpy(name, role_names[role], len);
421             for (int i = len+1; i < 12; ++i) name[i] = ' ';
422             name[len] = ':'; name[0] -= 32; name[12] = '\0';
423             dump_database_helper(u, role, name, FALSE);
424         }
425     }
426
427     pa_log_debug("Completed database dump");
428 }
429 #endif
430
431 static void notify_subscribers(struct userdata *u) {
432
433     pa_native_connection *c;
434     uint32_t idx;
435
436     pa_assert(u);
437
438     PA_IDXSET_FOREACH(c, u->subscribed, idx) {
439         pa_tagstruct *t;
440
441         t = pa_tagstruct_new(NULL, 0);
442         pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
443         pa_tagstruct_putu32(t, 0);
444         pa_tagstruct_putu32(t, u->module->index);
445         pa_tagstruct_puts(t, u->module->name);
446         pa_tagstruct_putu32(t, SUBCOMMAND_EVENT);
447
448         pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
449     }
450 }
451
452 static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) {
453
454     pa_assert(a);
455     pa_assert(b);
456
457     if (!pa_streq(a->description, b->description)
458         || a->user_set_description != b->user_set_description
459         || !pa_streq(a->icon, b->icon))
460         return FALSE;
461
462     for (int i=0; i < NUM_ROLES; ++i)
463         if (a->priority[i] != b->priority[i])
464             return FALSE;
465
466     return TRUE;
467 }
468
469 static char *get_name(const char *key, const char *prefix) {
470     char *t;
471
472     if (strncmp(key, prefix, strlen(prefix)))
473         return NULL;
474
475     t = pa_xstrdup(key + strlen(prefix));
476     return t;
477 }
478
479 static inline struct entry *load_or_initialize_entry(struct userdata *u, struct entry *entry, const char *name, const char *prefix) {
480     struct entry *old;
481
482     pa_assert(u);
483     pa_assert(entry);
484     pa_assert(name);
485     pa_assert(prefix);
486
487     if ((old = entry_read(u, name))) {
488         *entry = *old;
489         entry->description = pa_xstrdup(old->description);
490         entry->icon = pa_xstrdup(old->icon);
491     } else {
492         /* This is a new device, so make sure we write it's priority list correctly */
493         role_indexes_t max_priority;
494         pa_datum key;
495         pa_bool_t done;
496
497         pa_zero(max_priority);
498         done = !pa_database_first(u->database, &key, NULL);
499
500         /* Find all existing devices with the same prefix so we calculate the current max priority for each role */
501         while (!done) {
502             pa_datum next_key;
503
504             done = !pa_database_next(u->database, &key, &next_key, NULL);
505
506             if (key.size > strlen(prefix) && strncmp(key.data, prefix, strlen(prefix)) == 0) {
507                 char *name2;
508                 struct entry *e;
509
510                 name2 = pa_xstrndup(key.data, key.size);
511
512                 if ((e = entry_read(u, name2))) {
513                     for (uint32_t i = 0; i < NUM_ROLES; ++i) {
514                         max_priority[i] = PA_MAX(max_priority[i], e->priority[i]);
515                     }
516
517                     entry_free(e);
518                 }
519
520                 pa_xfree(name2);
521             }
522             pa_datum_free(&key);
523             key = next_key;
524         }
525
526         /* Actually initialise our entry now we've calculated it */
527         for (uint32_t i = 0; i < NUM_ROLES; ++i) {
528             entry->priority[i] = max_priority[i] + 1;
529         }
530         entry->user_set_description = FALSE;
531     }
532
533     return old;
534 }
535
536 static uint32_t get_role_index(const char* role) {
537     pa_assert(role);
538
539     for (uint32_t i = ROLE_NONE; i < NUM_ROLES; ++i)
540         if (pa_streq(role, role_names[i]))
541             return i;
542
543     return PA_INVALID_INDEX;
544 }
545
546 static void update_highest_priority_device_indexes(struct userdata *u, const char *prefix, void *ignore_device) {
547     role_indexes_t *indexes, highest_priority_available;
548     pa_datum key;
549     pa_bool_t done, sink_mode;
550
551     pa_assert(u);
552     pa_assert(prefix);
553
554     sink_mode = pa_streq(prefix, "sink:");
555
556     if (sink_mode)
557         indexes = &u->preferred_sinks;
558     else
559         indexes = &u->preferred_sources;
560
561     for (uint32_t i = 0; i < NUM_ROLES; ++i) {
562         (*indexes)[i] = PA_INVALID_INDEX;
563     }
564     pa_zero(highest_priority_available);
565
566     done = !pa_database_first(u->database, &key, NULL);
567
568     /* Find all existing devices with the same prefix so we find the highest priority device for each role */
569     while (!done) {
570         pa_datum next_key;
571
572         done = !pa_database_next(u->database, &key, &next_key, NULL);
573
574         if (key.size > strlen(prefix) && strncmp(key.data, prefix, strlen(prefix)) == 0) {
575             char *name, *device_name;
576             struct entry *e;
577
578             name = pa_xstrndup(key.data, key.size);
579             pa_assert_se(device_name = get_name(name, prefix));
580
581             if ((e = entry_read(u, name))) {
582                 for (uint32_t i = 0; i < NUM_ROLES; ++i) {
583                     if (!highest_priority_available[i] || e->priority[i] < highest_priority_available[i]) {
584                         /* We've found a device with a higher priority than that we've currently got,
585                            so see if it is currently available or not and update our list */
586                         uint32_t idx;
587                         pa_bool_t found = FALSE;
588
589                         if (sink_mode) {
590                             pa_sink *sink;
591
592                             PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
593                                 if ((pa_sink*) ignore_device == sink)
594                                     continue;
595                                 if (pa_streq(sink->name, device_name)) {
596                                     found = TRUE;
597                                     idx = sink->index; /* Is this needed? */
598                                     break;
599                                 }
600                             }
601                         } else {
602                             pa_source *source;
603
604                             PA_IDXSET_FOREACH(source, u->core->sources, idx) {
605                                 if ((pa_source*) ignore_device == source)
606                                     continue;
607                                 if (pa_streq(source->name, device_name)) {
608                                     found = TRUE;
609                                     idx = source->index; /* Is this needed? */
610                                     break;
611                                 }
612                             }
613                         }
614                         if (found) {
615                             highest_priority_available[i] = e->priority[i];
616                             (*indexes)[i] = idx;
617                         }
618
619                     }
620                 }
621
622                 entry_free(e);
623             }
624
625             pa_xfree(name);
626             pa_xfree(device_name);
627         }
628
629         pa_datum_free(&key);
630         key = next_key;
631     }
632 }
633
634
635 static void route_sink_input(struct userdata *u, pa_sink_input *si) {
636     const char *role;
637     uint32_t role_index, device_index;
638     pa_sink *sink;
639
640     pa_assert(u);
641     pa_assert(u->do_routing);
642
643     if (si->save_sink)
644         return;
645
646     /* Skip this if it is already in the process of being moved anyway */
647     if (!si->sink)
648         return;
649
650     /* It might happen that a stream and a sink are set up at the
651     same time, in which case we want to make sure we don't
652     interfere with that */
653     if (!PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(si)))
654         return;
655
656     if (!(role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE)))
657         role_index = get_role_index("none");
658     else
659         role_index = get_role_index(role);
660
661     if (PA_INVALID_INDEX == role_index)
662         return;
663
664     device_index = u->preferred_sinks[role_index];
665     if (PA_INVALID_INDEX == device_index)
666         return;
667
668     if (!(sink = pa_idxset_get_by_index(u->core->sinks, device_index)))
669         return;
670
671     if (si->sink != sink)
672         pa_sink_input_move_to(si, sink, FALSE);
673 }
674
675 static pa_hook_result_t route_sink_inputs(struct userdata *u, pa_sink *ignore_sink) {
676     pa_sink_input *si;
677     uint32_t idx;
678
679     pa_assert(u);
680
681     if (!u->do_routing)
682         return PA_HOOK_OK;
683
684     update_highest_priority_device_indexes(u, "sink:", ignore_sink);
685
686     PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
687         route_sink_input(u, si);
688     }
689
690     return PA_HOOK_OK;
691 }
692
693 static void route_source_output(struct userdata *u, pa_source_output *so) {
694     const char *role;
695     uint32_t role_index, device_index;
696     pa_source *source;
697
698     pa_assert(u);
699     pa_assert(u->do_routing);
700
701     if (so->save_source)
702         return;
703
704     if (so->direct_on_input)
705         return;
706
707     /* Skip this if it is already in the process of being moved anyway */
708     if (!so->source)
709         return;
710
711     /* It might happen that a stream and a source are set up at the
712     same time, in which case we want to make sure we don't
713     interfere with that */
714     if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
715         return;
716
717     if (!(role = pa_proplist_gets(so->proplist, PA_PROP_MEDIA_ROLE)))
718         role_index = get_role_index("none");
719     else
720         role_index = get_role_index(role);
721
722     if (PA_INVALID_INDEX == role_index)
723         return;
724
725     device_index = u->preferred_sources[role_index];
726     if (PA_INVALID_INDEX == device_index)
727         return;
728
729     if (!(source = pa_idxset_get_by_index(u->core->sources, device_index)))
730         return;
731
732     if (so->source != source)
733         pa_source_output_move_to(so, source, FALSE);
734 }
735
736 static pa_hook_result_t route_source_outputs(struct userdata *u, pa_source* ignore_source) {
737     pa_source_output *so;
738     uint32_t idx;
739
740     pa_assert(u);
741
742     if (!u->do_routing)
743         return PA_HOOK_OK;
744
745     update_highest_priority_device_indexes(u, "source:", ignore_source);
746
747     PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) {
748         route_source_output(u, so);
749     }
750
751     return PA_HOOK_OK;
752 }
753
754 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
755     struct userdata *u = userdata;
756     struct entry *entry, *old = NULL;
757     char *name = NULL;
758
759     pa_assert(c);
760     pa_assert(u);
761
762     if (t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW) &&
763         t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE) &&
764         t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW) &&
765         t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE) &&
766
767         /*t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&*/
768         t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
769         /*t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) &&*/
770         t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
771         return;
772
773     if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
774         pa_sink_input *si;
775
776         if (!u->do_routing)
777             return;
778         if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx)))
779             return;
780
781         /* The role may change mid-stream, so we reroute */
782         route_sink_input(u, si);
783
784         return;
785     } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT) {
786         pa_source_output *so;
787
788         if (!u->do_routing)
789             return;
790         if (!(so = pa_idxset_get_by_index(c->source_outputs, idx)))
791             return;
792
793         /* The role may change mid-stream, so we reroute */
794         route_source_output(u, so);
795
796         return;
797     } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) {
798         pa_sink *sink;
799
800         if (!(sink = pa_idxset_get_by_index(c->sinks, idx)))
801             return;
802
803         entry = entry_new();
804         name = pa_sprintf_malloc("sink:%s", sink->name);
805
806         old = load_or_initialize_entry(u, entry, name, "sink:");
807
808         if (!entry->user_set_description) {
809             pa_xfree(entry->description);
810             entry->description = pa_xstrdup(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION));
811         } else if (!pa_streq(entry->description, pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION))) {
812             /* Warning: If two modules fight over the description, this could cause an infinite loop.
813                by changing the description here, we retrigger this subscription callback. The only thing stopping us from
814                looping is the fact that the string comparison will fail on the second iteration. If another module tries to manage
815                the description, this will fail... */
816             pa_sink_set_description(sink, entry->description);
817         }
818
819         pa_xfree(entry->icon);
820         entry->icon = pa_xstrdup(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_ICON_NAME));
821
822     } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE) {
823         pa_source *source;
824
825         pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE);
826
827         if (!(source = pa_idxset_get_by_index(c->sources, idx)))
828             return;
829
830         if (source->monitor_of)
831             return;
832
833         entry = entry_new();
834         name = pa_sprintf_malloc("source:%s", source->name);
835
836         old = load_or_initialize_entry(u, entry, name, "source:");
837
838         if (!entry->user_set_description) {
839             pa_xfree(entry->description);
840             entry->description = pa_xstrdup(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION));
841         } else if (!pa_streq(entry->description, pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION))) {
842             /* Warning: If two modules fight over the description, this could cause an infinite loop.
843                by changing the description here, we retrigger this subscription callback. The only thing stopping us from
844                looping is the fact that the string comparison will fail on the second iteration. If another module tries to manage
845                the description, this will fail... */
846             pa_source_set_description(source, entry->description);
847         }
848
849         pa_xfree(entry->icon);
850         entry->icon = pa_xstrdup(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_ICON_NAME));
851     } else {
852         pa_assert_not_reached();
853     }
854
855     pa_assert(name);
856
857     if (old) {
858
859         if (entries_equal(old, entry)) {
860             entry_free(old);
861             entry_free(entry);
862             pa_xfree(name);
863
864             return;
865         }
866
867         entry_free(old);
868     }
869
870     pa_log_info("Storing device %s.", name);
871
872     if (entry_write(u, name, entry))
873         trigger_save(u);
874     else
875         pa_log_warn("Could not save device");;
876
877     entry_free(entry);
878     pa_xfree(name);
879 }
880
881 static pa_hook_result_t sink_new_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) {
882     char *name;
883     struct entry *e;
884
885     pa_assert(c);
886     pa_assert(new_data);
887     pa_assert(u);
888
889     name = pa_sprintf_malloc("sink:%s", new_data->name);
890
891     if ((e = entry_read(u, name))) {
892         if (e->user_set_description && strncmp(e->description, pa_proplist_gets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION), sizeof(e->description)) != 0) {
893             pa_log_info("Restoring description for sink %s.", new_data->name);
894             pa_proplist_sets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION, e->description);
895         }
896
897         entry_free(e);
898     }
899
900     pa_xfree(name);
901
902     return PA_HOOK_OK;
903 }
904
905 static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) {
906     char *name;
907     struct entry *e;
908
909     pa_assert(c);
910     pa_assert(new_data);
911     pa_assert(u);
912
913     name = pa_sprintf_malloc("source:%s", new_data->name);
914
915     if ((e = entry_read(u, name))) {
916         if (e->user_set_description && strncmp(e->description, pa_proplist_gets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION), sizeof(e->description)) != 0) {
917             /* NB, We cannot detect if we are a monitor here... this could mess things up a bit... */
918             pa_log_info("Restoring description for source %s.", new_data->name);
919             pa_proplist_sets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION, e->description);
920         }
921
922         entry_free(e);
923     }
924
925     pa_xfree(name);
926
927     return PA_HOOK_OK;
928 }
929
930 static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
931     const char *role;
932     uint32_t role_index;
933
934     pa_assert(c);
935     pa_assert(new_data);
936     pa_assert(u);
937
938     if (!u->do_routing)
939         return PA_HOOK_OK;
940
941     if (new_data->sink)
942         pa_log_debug("Not restoring device for stream because already set.");
943     else {
944         if (!(role = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_ROLE)))
945             role_index = get_role_index("none");
946         else
947             role_index = get_role_index(role);
948
949         if (PA_INVALID_INDEX != role_index) {
950             uint32_t device_index;
951
952             device_index = u->preferred_sinks[role_index];
953             if (PA_INVALID_INDEX != device_index) {
954                 pa_sink *sink;
955
956                 if ((sink = pa_idxset_get_by_index(u->core->sinks, device_index))) {
957                     if (!pa_sink_input_new_data_set_sink(new_data, sink, FALSE))
958                         pa_log_debug("Not restoring device for stream because no supported format was found");
959                 }
960             }
961         }
962     }
963
964     return PA_HOOK_OK;
965 }
966
967 static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) {
968     const char *role;
969     uint32_t role_index;
970
971     pa_assert(c);
972     pa_assert(new_data);
973     pa_assert(u);
974
975     if (!u->do_routing)
976         return PA_HOOK_OK;
977
978     if (new_data->direct_on_input)
979         return PA_HOOK_OK;
980
981     if (new_data->source)
982         pa_log_debug("Not restoring device for stream because already set.");
983     else {
984         if (!(role = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_ROLE)))
985             role_index = get_role_index("none");
986         else
987             role_index = get_role_index(role);
988
989         if (PA_INVALID_INDEX != role_index) {
990             uint32_t device_index;
991
992             device_index = u->preferred_sources[role_index];
993             if (PA_INVALID_INDEX != device_index) {
994                 pa_source *source;
995
996                 if ((source = pa_idxset_get_by_index(u->core->sources, device_index)))
997                     if (!pa_source_output_new_data_set_source(new_data, source, FALSE))
998                         pa_log_debug("Not restoring device for stream because no supported format was found");
999             }
1000         }
1001     }
1002
1003     return PA_HOOK_OK;
1004 }
1005
1006
1007 static pa_hook_result_t sink_put_hook_callback(pa_core *c, PA_GCC_UNUSED pa_sink *sink, struct userdata *u) {
1008     pa_assert(c);
1009     pa_assert(u);
1010     pa_assert(u->core == c);
1011     pa_assert(u->on_hotplug);
1012
1013     notify_subscribers(u);
1014
1015     return route_sink_inputs(u, NULL);
1016 }
1017
1018 static pa_hook_result_t source_put_hook_callback(pa_core *c, PA_GCC_UNUSED pa_source *source, struct userdata *u) {
1019     pa_assert(c);
1020     pa_assert(u);
1021     pa_assert(u->core == c);
1022     pa_assert(u->on_hotplug);
1023
1024     notify_subscribers(u);
1025
1026     return route_source_outputs(u, NULL);
1027 }
1028
1029 static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
1030     pa_assert(c);
1031     pa_assert(sink);
1032     pa_assert(u);
1033     pa_assert(u->core == c);
1034     pa_assert(u->on_rescue);
1035
1036     /* There's no point in doing anything if the core is shut down anyway */
1037     if (c->state == PA_CORE_SHUTDOWN)
1038         return PA_HOOK_OK;
1039
1040     notify_subscribers(u);
1041
1042     return route_sink_inputs(u, sink);
1043 }
1044
1045 static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
1046     pa_assert(c);
1047     pa_assert(source);
1048     pa_assert(u);
1049     pa_assert(u->core == c);
1050     pa_assert(u->on_rescue);
1051
1052     /* There's no point in doing anything if the core is shut down anyway */
1053     if (c->state == PA_CORE_SHUTDOWN)
1054         return PA_HOOK_OK;
1055
1056     notify_subscribers(u);
1057
1058     return route_source_outputs(u, source);
1059 }
1060
1061
1062 static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
1063     uint32_t idx;
1064     char *n;
1065
1066     pa_assert(u);
1067     pa_assert(name);
1068     pa_assert(e);
1069
1070     if (!e->user_set_description)
1071         return;
1072
1073     if ((n = get_name(name, "sink:"))) {
1074         pa_sink *s;
1075         PA_IDXSET_FOREACH(s, u->core->sinks, idx) {
1076             if (!pa_streq(s->name, n)) {
1077                 continue;
1078             }
1079
1080             pa_log_info("Setting description for sink %s to '%s'", s->name, e->description);
1081             pa_sink_set_description(s, e->description);
1082         }
1083         pa_xfree(n);
1084     }
1085     else if ((n = get_name(name, "source:"))) {
1086         pa_source *s;
1087         PA_IDXSET_FOREACH(s, u->core->sources, idx) {
1088             if (!pa_streq(s->name, n)) {
1089                 continue;
1090             }
1091
1092             if (s->monitor_of) {
1093                 pa_log_warn("Cowardly refusing to set the description for monitor source %s.", s->name);
1094                 continue;
1095             }
1096
1097             pa_log_info("Setting description for source %s to '%s'", s->name, e->description);
1098             pa_source_set_description(s, e->description);
1099         }
1100         pa_xfree(n);
1101     }
1102 }
1103
1104
1105 #define EXT_VERSION 1
1106
1107 static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
1108   struct userdata *u;
1109   uint32_t command;
1110   pa_tagstruct *reply = NULL;
1111
1112   pa_assert(p);
1113   pa_assert(m);
1114   pa_assert(c);
1115   pa_assert(t);
1116
1117   u = m->userdata;
1118
1119   if (pa_tagstruct_getu32(t, &command) < 0)
1120     goto fail;
1121
1122   reply = pa_tagstruct_new(NULL, 0);
1123   pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1124   pa_tagstruct_putu32(reply, tag);
1125
1126   switch (command) {
1127     case SUBCOMMAND_TEST: {
1128       if (!pa_tagstruct_eof(t))
1129         goto fail;
1130
1131       pa_tagstruct_putu32(reply, EXT_VERSION);
1132       break;
1133     }
1134
1135     case SUBCOMMAND_READ: {
1136       pa_datum key;
1137       pa_bool_t done;
1138
1139       if (!pa_tagstruct_eof(t))
1140         goto fail;
1141
1142       done = !pa_database_first(u->database, &key, NULL);
1143
1144       while (!done) {
1145         pa_datum next_key;
1146         struct entry *e;
1147         char *name;
1148
1149         done = !pa_database_next(u->database, &key, &next_key, NULL);
1150
1151         name = pa_xstrndup(key.data, key.size);
1152         pa_datum_free(&key);
1153
1154         if ((e = entry_read(u, name))) {
1155             uint32_t idx;
1156             char *device_name;
1157             uint32_t found_index = PA_INVALID_INDEX;
1158
1159             if ((device_name = get_name(name, "sink:"))) {
1160                 pa_sink* s;
1161                 PA_IDXSET_FOREACH(s, u->core->sinks, idx) {
1162                     if (pa_streq(s->name, device_name)) {
1163                         found_index = s->index;
1164                         break;
1165                     }
1166                 }
1167                 pa_xfree(device_name);
1168             } else if ((device_name = get_name(name, "source:"))) {
1169                 pa_source* s;
1170                 PA_IDXSET_FOREACH(s, u->core->sources, idx) {
1171                     if (pa_streq(s->name, device_name)) {
1172                         found_index = s->index;
1173                         break;
1174                     }
1175                 }
1176                 pa_xfree(device_name);
1177             }
1178
1179             pa_tagstruct_puts(reply, name);
1180             pa_tagstruct_puts(reply, e->description);
1181             pa_tagstruct_puts(reply, e->icon);
1182             pa_tagstruct_putu32(reply, found_index);
1183             pa_tagstruct_putu32(reply, NUM_ROLES);
1184
1185             for (uint32_t i = ROLE_NONE; i < NUM_ROLES; ++i) {
1186                 pa_tagstruct_puts(reply, role_names[i]);
1187                 pa_tagstruct_putu32(reply, e->priority[i]);
1188             }
1189
1190             entry_free(e);
1191         }
1192
1193         pa_xfree(name);
1194
1195         key = next_key;
1196       }
1197
1198       break;
1199     }
1200
1201     case SUBCOMMAND_RENAME: {
1202
1203         struct entry *e;
1204         const char *device, *description;
1205
1206         if (pa_tagstruct_gets(t, &device) < 0 ||
1207           pa_tagstruct_gets(t, &description) < 0)
1208           goto fail;
1209
1210         if (!device || !*device || !description || !*description)
1211           goto fail;
1212
1213         if ((e = entry_read(u, device))) {
1214             pa_xfree(e->description);
1215             e->description = pa_xstrdup(description);
1216             e->user_set_description = TRUE;
1217
1218             if (entry_write(u, (char *)device, e)) {
1219                 apply_entry(u, device, e);
1220
1221                 trigger_save(u);
1222             }
1223             else
1224                 pa_log_warn("Could not save device");
1225
1226             entry_free(e);
1227         }
1228         else
1229             pa_log_warn("Could not rename device %s, no entry in database", device);
1230
1231       break;
1232     }
1233
1234     case SUBCOMMAND_DELETE:
1235
1236       while (!pa_tagstruct_eof(t)) {
1237         const char *name;
1238         pa_datum key;
1239
1240         if (pa_tagstruct_gets(t, &name) < 0)
1241           goto fail;
1242
1243         key.data = (char*) name;
1244         key.size = strlen(name);
1245
1246         /** @todo: Reindex the priorities */
1247         pa_database_unset(u->database, &key);
1248       }
1249
1250       trigger_save(u);
1251
1252       break;
1253
1254     case SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING: {
1255
1256         pa_bool_t enable;
1257
1258         if (pa_tagstruct_get_boolean(t, &enable) < 0)
1259             goto fail;
1260
1261         if ((u->do_routing = enable)) {
1262             /* Update our caches */
1263             update_highest_priority_device_indexes(u, "sink:", NULL);
1264             update_highest_priority_device_indexes(u, "source:", NULL);
1265         }
1266
1267         break;
1268     }
1269
1270     case SUBCOMMAND_REORDER: {
1271
1272         const char *role;
1273         struct entry *e;
1274         uint32_t role_index, n_devices;
1275         pa_datum key;
1276         pa_bool_t done, sink_mode = TRUE;
1277         struct device_t { uint32_t prio; char *device; };
1278         struct device_t *device;
1279         struct device_t **devices;
1280         uint32_t i, idx, offset;
1281         pa_hashmap *h;
1282         /*void *state;*/
1283         pa_bool_t first;
1284
1285         if (pa_tagstruct_gets(t, &role) < 0 ||
1286             pa_tagstruct_getu32(t, &n_devices) < 0 ||
1287             n_devices < 1)
1288             goto fail;
1289
1290         if (PA_INVALID_INDEX == (role_index = get_role_index(role)))
1291             goto fail;
1292
1293         /* Cycle through the devices given and make sure they exist */
1294         h = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
1295         first = TRUE;
1296         idx = 0;
1297         for (i = 0; i < n_devices; ++i) {
1298             const char *s;
1299             if (pa_tagstruct_gets(t, &s) < 0) {
1300                 while ((device = pa_hashmap_steal_first(h))) {
1301                     pa_xfree(device->device);
1302                     pa_xfree(device);
1303                 }
1304
1305                 pa_hashmap_free(h, NULL);
1306                 pa_log_error("Protocol error on reorder");
1307                 goto fail;
1308             }
1309
1310             /* Ensure this is a valid entry */
1311             if (!(e = entry_read(u, s))) {
1312                 while ((device = pa_hashmap_steal_first(h))) {
1313                     pa_xfree(device->device);
1314                     pa_xfree(device);
1315                 }
1316
1317                 pa_hashmap_free(h, NULL);
1318                 pa_log_error("Client specified an unknown device in it's reorder list.");
1319                 goto fail;
1320             }
1321             entry_free(e);
1322
1323             if (first) {
1324                 first = FALSE;
1325                 sink_mode = (0 == strncmp("sink:", s, 5));
1326             } else if ((sink_mode && 0 != strncmp("sink:", s, 5)) || (!sink_mode && 0 != strncmp("source:", s, 7))) {
1327                 while ((device = pa_hashmap_steal_first(h))) {
1328                     pa_xfree(device->device);
1329                     pa_xfree(device);
1330                 }
1331
1332                 pa_hashmap_free(h, NULL);
1333                 pa_log_error("Attempted to reorder mixed devices (sinks and sources)");
1334                 goto fail;
1335             }
1336
1337             /* Add the device to our hashmap. If it's already in it, free it now and carry on */
1338             device = pa_xnew(struct device_t, 1);
1339             device->device = pa_xstrdup(s);
1340             if (pa_hashmap_put(h, device->device, device) == 0) {
1341                 device->prio = idx;
1342                 idx++;
1343             } else {
1344                 pa_xfree(device->device);
1345                 pa_xfree(device);
1346             }
1347         }
1348
1349         /*pa_log_debug("Hashmap contents (received from client)");
1350         PA_HASHMAP_FOREACH(device, h, state) {
1351             pa_log_debug("  - %s (%d)", device->device, device->prio);
1352         }*/
1353
1354         /* Now cycle through our list and add all the devices.
1355            This has the effect of adding in any in our DB,
1356            not specified in the device list (and thus will be
1357            tacked on at the end) */
1358         offset = idx;
1359         done = !pa_database_first(u->database, &key, NULL);
1360
1361         while (!done && idx < 256) {
1362             pa_datum next_key;
1363
1364             done = !pa_database_next(u->database, &key, &next_key, NULL);
1365
1366             device = pa_xnew(struct device_t, 1);
1367             device->device = pa_xstrndup(key.data, key.size);
1368             if ((sink_mode && 0 == strncmp("sink:", device->device, 5))
1369                 || (!sink_mode && 0 == strncmp("source:", device->device, 7))) {
1370
1371                 /* Add the device to our hashmap. If it's already in it, free it now and carry on */
1372                 if (pa_hashmap_put(h, device->device, device) == 0
1373                     && (e = entry_read(u, device->device))) {
1374                     /* We add offset on to the existing priority so that when we order, the
1375                        existing entries are always lower priority than the new ones. */
1376                     device->prio = (offset + e->priority[role_index]);
1377                     pa_xfree(e);
1378                 }
1379                 else {
1380                     pa_xfree(device->device);
1381                     pa_xfree(device);
1382                 }
1383             } else {
1384                 pa_xfree(device->device);
1385                 pa_xfree(device);
1386             }
1387
1388             pa_datum_free(&key);
1389
1390             key = next_key;
1391         }
1392
1393         /*pa_log_debug("Hashmap contents (combined with database)");
1394         PA_HASHMAP_FOREACH(device, h, state) {
1395             pa_log_debug("  - %s (%d)", device->device, device->prio);
1396         }*/
1397
1398         /* Now we put all the entries in a simple list for sorting it. */
1399         n_devices = pa_hashmap_size(h);
1400         devices = pa_xnew(struct device_t *,  n_devices);
1401         idx = 0;
1402         while ((device = pa_hashmap_steal_first(h))) {
1403             devices[idx++] = device;
1404         }
1405         pa_hashmap_free(h, NULL);
1406
1407         /* Simple bubble sort */
1408         for (i = 0; i < n_devices; ++i) {
1409             for (uint32_t j = i; j < n_devices; ++j) {
1410                 if (devices[i]->prio > devices[j]->prio) {
1411                     struct device_t *tmp;
1412                     tmp = devices[i];
1413                     devices[i] = devices[j];
1414                     devices[j] = tmp;
1415                 }
1416             }
1417         }
1418
1419         /*pa_log_debug("Sorted device list");
1420         for (i = 0; i < n_devices; ++i) {
1421             pa_log_debug("  - %s (%d)", devices[i]->device, devices[i]->prio);
1422         }*/
1423
1424         /* Go through in order and write the new entry and cleanup our own list */
1425         idx = 1;
1426         first = TRUE;
1427         for (i = 0; i < n_devices; ++i) {
1428             if ((e = entry_read(u, devices[i]->device))) {
1429                 if (e->priority[role_index] == idx)
1430                     idx++;
1431                 else {
1432                     e->priority[role_index] = idx;
1433
1434                     if (entry_write(u, (char *) devices[i]->device, e)) {
1435                         first = FALSE;
1436                         idx++;
1437                     }
1438                 }
1439
1440                 pa_xfree(e);
1441             }
1442             pa_xfree(devices[i]->device);
1443             pa_xfree(devices[i]);
1444         }
1445
1446         pa_xfree(devices);
1447
1448         if (!first) {
1449             trigger_save(u);
1450
1451             if (sink_mode)
1452                 route_sink_inputs(u, NULL);
1453             else
1454                 route_source_outputs(u, NULL);
1455         }
1456
1457         break;
1458     }
1459
1460     case SUBCOMMAND_SUBSCRIBE: {
1461
1462       pa_bool_t enabled;
1463
1464       if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
1465         !pa_tagstruct_eof(t))
1466         goto fail;
1467
1468       if (enabled)
1469         pa_idxset_put(u->subscribed, c, NULL);
1470       else
1471         pa_idxset_remove_by_data(u->subscribed, c, NULL);
1472
1473       break;
1474     }
1475
1476     default:
1477       goto fail;
1478   }
1479
1480   pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
1481   return 0;
1482
1483   fail:
1484
1485   if (reply)
1486     pa_tagstruct_free(reply);
1487
1488   return -1;
1489 }
1490
1491 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
1492     pa_assert(p);
1493     pa_assert(c);
1494     pa_assert(u);
1495
1496     pa_idxset_remove_by_data(u->subscribed, c, NULL);
1497     return PA_HOOK_OK;
1498 }
1499
1500 struct prioritised_indexes {
1501     uint32_t index;
1502     int32_t priority;
1503 };
1504
1505 int pa__init(pa_module*m) {
1506     pa_modargs *ma = NULL;
1507     struct userdata *u;
1508     char *fname;
1509     pa_sink *sink;
1510     pa_source *source;
1511     uint32_t idx;
1512     pa_bool_t do_routing = FALSE, on_hotplug = TRUE, on_rescue = TRUE;
1513     uint32_t total_devices;
1514
1515     pa_assert(m);
1516
1517     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1518         pa_log("Failed to parse module arguments");
1519         goto fail;
1520     }
1521
1522     if (pa_modargs_get_value_boolean(ma, "do_routing", &do_routing) < 0 ||
1523         pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
1524         pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
1525         pa_log("on_hotplug= and on_rescue= expect boolean arguments");
1526         goto fail;
1527     }
1528
1529     m->userdata = u = pa_xnew0(struct userdata, 1);
1530     u->core = m->core;
1531     u->module = m;
1532     u->do_routing = do_routing;
1533     u->on_hotplug = on_hotplug;
1534     u->on_rescue = on_rescue;
1535     u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
1536
1537     u->protocol = pa_native_protocol_get(m->core);
1538     pa_native_protocol_install_ext(u->protocol, m, extension_cb);
1539
1540     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);
1541
1542     u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE|PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
1543
1544     /* Used to handle device description management */
1545     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);
1546     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);
1547
1548     /* The following slots are used to deal with routing */
1549     /* A little bit later than module-stream-restore, but before module-intended-roles */
1550     u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY+5, (pa_hook_cb_t) sink_input_new_hook_callback, u);
1551     u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY+5, (pa_hook_cb_t) source_output_new_hook_callback, u);
1552
1553     if (on_hotplug) {
1554         /* A little bit later than module-stream-restore, but before module-intended-roles */
1555         u->sink_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+5, (pa_hook_cb_t) sink_put_hook_callback, u);
1556         u->source_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+5, (pa_hook_cb_t) source_put_hook_callback, u);
1557     }
1558
1559     if (on_rescue) {
1560         /* A little bit later than module-stream-restore, a little bit earlier than module-intended-roles, module-rescue-streams, ... */
1561         u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) sink_unlink_hook_callback, u);
1562         u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) source_unlink_hook_callback, u);
1563     }
1564
1565     if (!(fname = pa_state_path("device-manager", TRUE)))
1566         goto fail;
1567
1568     if (!(u->database = pa_database_open(fname, TRUE))) {
1569         pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
1570         pa_xfree(fname);
1571         goto fail;
1572     }
1573
1574     pa_log_info("Successfully opened database file '%s'.", fname);
1575     pa_xfree(fname);
1576
1577     /* Attempt to inject the devices into the list in priority order */
1578     total_devices = PA_MAX(pa_idxset_size(m->core->sinks), pa_idxset_size(m->core->sources));
1579     if (total_devices > 0 && total_devices < 128) {
1580         uint32_t i;
1581         struct prioritised_indexes p_i[128];
1582
1583         /* We cycle over all the available sinks so that they are added to our database if they are not in it yet */
1584         i = 0;
1585         PA_IDXSET_FOREACH(sink, m->core->sinks, idx) {
1586             pa_log_debug("Found sink index %u", sink->index);
1587             p_i[i  ].index = sink->index;
1588             p_i[i++].priority = sink->priority;
1589         }
1590         /* Bubble sort it (only really useful for first time creation) */
1591         if (i > 1)
1592           for (uint32_t j = 0; j < i; ++j)
1593               for (uint32_t k = 0; k < i; ++k)
1594                   if (p_i[j].priority > p_i[k].priority) {
1595                       struct prioritised_indexes tmp_pi = p_i[k];
1596                       p_i[k] = p_i[j];
1597                       p_i[j] = tmp_pi;
1598                   }
1599         /* Register it */
1600         for (uint32_t j = 0; j < i; ++j)
1601             subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, p_i[j].index, u);
1602
1603
1604         /* We cycle over all the available sources so that they are added to our database if they are not in it yet */
1605         i = 0;
1606         PA_IDXSET_FOREACH(source, m->core->sources, idx) {
1607             p_i[i  ].index = source->index;
1608             p_i[i++].priority = source->priority;
1609         }
1610         /* Bubble sort it (only really useful for first time creation) */
1611         if (i > 1)
1612           for (uint32_t j = 0; j < i; ++j)
1613               for (uint32_t k = 0; k < i; ++k)
1614                   if (p_i[j].priority > p_i[k].priority) {
1615                       struct prioritised_indexes tmp_pi = p_i[k];
1616                       p_i[k] = p_i[j];
1617                       p_i[j] = tmp_pi;
1618                   }
1619         /* Register it */
1620         for (uint32_t j = 0; j < i; ++j)
1621             subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW, p_i[j].index, u);
1622     }
1623     else if (total_devices > 0) {
1624         /* This user has a *lot* of devices... */
1625         PA_IDXSET_FOREACH(sink, m->core->sinks, idx)
1626             subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, sink->index, u);
1627
1628         PA_IDXSET_FOREACH(source, m->core->sources, idx)
1629             subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW, source->index, u);
1630     }
1631
1632     /* Perform the routing (if it's enabled) which will update our priority list cache too */
1633     for (uint32_t i = 0; i < NUM_ROLES; ++i) {
1634         u->preferred_sinks[i] = u->preferred_sources[i] = PA_INVALID_INDEX;
1635     }
1636
1637     route_sink_inputs(u, NULL);
1638     route_source_outputs(u, NULL);
1639
1640 #ifdef DUMP_DATABASE
1641     dump_database(u);
1642 #endif
1643
1644     pa_modargs_free(ma);
1645     return 0;
1646
1647 fail:
1648     pa__done(m);
1649
1650     if (ma)
1651         pa_modargs_free(ma);
1652
1653     return -1;
1654 }
1655
1656 void pa__done(pa_module*m) {
1657     struct userdata* u;
1658
1659     pa_assert(m);
1660
1661     if (!(u = m->userdata))
1662         return;
1663
1664     if (u->subscription)
1665         pa_subscription_free(u->subscription);
1666
1667     if (u->sink_new_hook_slot)
1668         pa_hook_slot_free(u->sink_new_hook_slot);
1669     if (u->source_new_hook_slot)
1670         pa_hook_slot_free(u->source_new_hook_slot);
1671
1672     if (u->sink_input_new_hook_slot)
1673         pa_hook_slot_free(u->sink_input_new_hook_slot);
1674     if (u->source_output_new_hook_slot)
1675         pa_hook_slot_free(u->source_output_new_hook_slot);
1676
1677     if (u->sink_put_hook_slot)
1678         pa_hook_slot_free(u->sink_put_hook_slot);
1679     if (u->source_put_hook_slot)
1680         pa_hook_slot_free(u->source_put_hook_slot);
1681
1682     if (u->sink_unlink_hook_slot)
1683         pa_hook_slot_free(u->sink_unlink_hook_slot);
1684     if (u->source_unlink_hook_slot)
1685         pa_hook_slot_free(u->source_unlink_hook_slot);
1686
1687     if (u->connection_unlink_hook_slot)
1688         pa_hook_slot_free(u->connection_unlink_hook_slot);
1689
1690     if (u->save_time_event)
1691         u->core->mainloop->time_free(u->save_time_event);
1692
1693     if (u->database)
1694         pa_database_close(u->database);
1695
1696     if (u->protocol) {
1697         pa_native_protocol_remove_ext(u->protocol, m);
1698         pa_native_protocol_unref(u->protocol);
1699     }
1700
1701     if (u->subscribed)
1702         pa_idxset_free(u->subscribed, NULL, NULL);
1703
1704     pa_xfree(u);
1705 }