Add "Rear Mic" to alsa mixer paths.
[profile/ivi/pulseaudio.git] / src / modules / module-device-restore.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2006-2008 Lennart Poettering
5
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2.1 of the License,
9   or (at your option) any later version.
10
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <unistd.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33
34 #include <pulse/xmalloc.h>
35 #include <pulse/volume.h>
36 #include <pulse/timeval.h>
37 #include <pulse/util.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/database.h>
50
51 #include "module-device-restore-symdef.h"
52
53 PA_MODULE_AUTHOR("Lennart Poettering");
54 PA_MODULE_DESCRIPTION("Automatically restore the volume/mute state of devices");
55 PA_MODULE_VERSION(PACKAGE_VERSION);
56 PA_MODULE_LOAD_ONCE(TRUE);
57 PA_MODULE_USAGE(
58         "restore_port=<Save/restore port?> "
59         "restore_volume=<Save/restore volumes?> "
60         "restore_muted=<Save/restore muted states?>");
61
62 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
63
64 static const char* const valid_modargs[] = {
65     "restore_volume",
66     "restore_muted",
67     "restore_port",
68     NULL
69 };
70
71 struct userdata {
72     pa_core *core;
73     pa_module *module;
74     pa_subscription *subscription;
75     pa_hook_slot
76         *sink_new_hook_slot,
77         *sink_fixate_hook_slot,
78         *source_new_hook_slot,
79         *source_fixate_hook_slot;
80     pa_time_event *save_time_event;
81     pa_database *database;
82
83     pa_bool_t restore_volume:1;
84     pa_bool_t restore_muted:1;
85     pa_bool_t restore_port:1;
86 };
87
88 #define ENTRY_VERSION 2
89
90 struct entry {
91     uint8_t version;
92     pa_bool_t muted_valid:1, volume_valid:1, port_valid:1;
93     pa_bool_t muted:1;
94     pa_channel_map channel_map;
95     pa_cvolume volume;
96     char port[PA_NAME_MAX];
97 } PA_GCC_PACKED;
98
99 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
100     struct userdata *u = userdata;
101
102     pa_assert(a);
103     pa_assert(e);
104     pa_assert(u);
105
106     pa_assert(e == u->save_time_event);
107     u->core->mainloop->time_free(u->save_time_event);
108     u->save_time_event = NULL;
109
110     pa_database_sync(u->database);
111     pa_log_info("Synced.");
112 }
113
114 static struct entry* read_entry(struct userdata *u, const char *name) {
115     pa_datum key, data;
116     struct entry *e;
117
118     pa_assert(u);
119     pa_assert(name);
120
121     key.data = (char*) name;
122     key.size = strlen(name);
123
124     pa_zero(data);
125
126     if (!pa_database_get(u->database, &key, &data))
127         goto fail;
128
129     if (data.size != sizeof(struct entry)) {
130         pa_log_debug("Database contains entry for device %s of wrong size %lu != %lu. Probably due to upgrade, ignoring.", name, (unsigned long) data.size, (unsigned long) sizeof(struct entry));
131         goto fail;
132     }
133
134     e = (struct entry*) data.data;
135
136     if (e->version != ENTRY_VERSION) {
137         pa_log_debug("Version of database entry for device %s doesn't match our version. Probably due to upgrade, ignoring.", name);
138         goto fail;
139     }
140
141     if (!memchr(e->port, 0, sizeof(e->port))) {
142         pa_log_warn("Database contains entry for device %s with missing NUL byte in port name", name);
143         goto fail;
144     }
145
146     if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) {
147         pa_log_warn("Invalid channel map stored in database for device %s", name);
148         goto fail;
149     }
150
151     if (e->volume_valid && (!pa_cvolume_valid(&e->volume) || !pa_cvolume_compatible_with_channel_map(&e->volume, &e->channel_map))) {
152         pa_log_warn("Volume and channel map don't match in database entry for device %s", name);
153         goto fail;
154     }
155
156     return e;
157
158 fail:
159
160     pa_datum_free(&data);
161     return NULL;
162 }
163
164 static void trigger_save(struct userdata *u) {
165     if (u->save_time_event)
166         return;
167
168     u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u);
169 }
170
171 static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) {
172     pa_cvolume t;
173
174     if (a->port_valid != b->port_valid ||
175         (a->port_valid && strncmp(a->port, b->port, sizeof(a->port))))
176         return FALSE;
177
178     if (a->muted_valid != b->muted_valid ||
179         (a->muted_valid && (a->muted != b->muted)))
180         return FALSE;
181
182     t = b->volume;
183     if (a->volume_valid != b->volume_valid ||
184         (a->volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->volume)))
185         return FALSE;
186
187     return TRUE;
188 }
189
190 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
191     struct userdata *u = userdata;
192     struct entry entry, *old;
193     char *name;
194     pa_datum key, data;
195
196     pa_assert(c);
197     pa_assert(u);
198
199     if (t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW) &&
200         t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE) &&
201         t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW) &&
202         t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE))
203         return;
204
205     pa_zero(entry);
206     entry.version = ENTRY_VERSION;
207
208     if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) {
209         pa_sink *sink;
210
211         if (!(sink = pa_idxset_get_by_index(c->sinks, idx)))
212             return;
213
214         name = pa_sprintf_malloc("sink:%s", sink->name);
215
216         if ((old = read_entry(u, name)))
217             entry = *old;
218
219         if (sink->save_volume) {
220             entry.channel_map = sink->channel_map;
221             entry.volume = *pa_sink_get_volume(sink, FALSE);
222             entry.volume_valid = TRUE;
223         }
224
225         if (sink->save_muted) {
226             entry.muted = pa_sink_get_mute(sink, FALSE);
227             entry.muted_valid = TRUE;
228         }
229
230         if (sink->save_port) {
231             pa_strlcpy(entry.port, sink->active_port ? sink->active_port->name : "", sizeof(entry.port));
232             entry.port_valid = TRUE;
233         }
234
235     } else {
236         pa_source *source;
237
238         pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE);
239
240         if (!(source = pa_idxset_get_by_index(c->sources, idx)))
241             return;
242
243         name = pa_sprintf_malloc("source:%s", source->name);
244
245         if ((old = read_entry(u, name)))
246             entry = *old;
247
248         if (source->save_volume) {
249             entry.channel_map = source->channel_map;
250             entry.volume = *pa_source_get_volume(source, FALSE);
251             entry.volume_valid = TRUE;
252         }
253
254         if (source->save_muted) {
255             entry.muted = pa_source_get_mute(source, FALSE);
256             entry.muted_valid = TRUE;
257         }
258
259         if (source->save_port) {
260             pa_strlcpy(entry.port, source->active_port ? source->active_port->name : "", sizeof(entry.port));
261             entry.port_valid = TRUE;
262         }
263     }
264
265     if (old) {
266
267         if (entries_equal(old, &entry)) {
268             pa_xfree(old);
269             pa_xfree(name);
270             return;
271         }
272
273         pa_xfree(old);
274     }
275
276     key.data = name;
277     key.size = strlen(name);
278
279     data.data = &entry;
280     data.size = sizeof(entry);
281
282     pa_log_info("Storing volume/mute/port for device %s.", name);
283
284     pa_database_set(u->database, &key, &data, TRUE);
285
286     pa_xfree(name);
287
288     trigger_save(u);
289 }
290
291 static pa_hook_result_t sink_new_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) {
292     char *name;
293     struct entry *e;
294
295     pa_assert(c);
296     pa_assert(new_data);
297     pa_assert(u);
298     pa_assert(u->restore_port);
299
300     name = pa_sprintf_malloc("sink:%s", new_data->name);
301
302     if ((e = read_entry(u, name))) {
303
304         if (e->port_valid) {
305             if (!new_data->active_port) {
306                 pa_log_info("Restoring port for sink %s.", name);
307                 pa_sink_new_data_set_port(new_data, e->port);
308                 new_data->save_port = TRUE;
309             } else
310                 pa_log_debug("Not restoring port for sink %s, because already set.", name);
311         }
312
313         pa_xfree(e);
314     }
315
316     pa_xfree(name);
317
318     return PA_HOOK_OK;
319 }
320
321 static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) {
322     char *name;
323     struct entry *e;
324
325     pa_assert(c);
326     pa_assert(new_data);
327     pa_assert(u);
328     pa_assert(u->restore_volume || u->restore_muted);
329
330     name = pa_sprintf_malloc("sink:%s", new_data->name);
331
332     if ((e = read_entry(u, name))) {
333
334         if (u->restore_volume && e->volume_valid) {
335
336             if (!new_data->volume_is_set) {
337                 pa_cvolume v;
338
339                 pa_log_info("Restoring volume for sink %s.", new_data->name);
340
341                 v = e->volume;
342                 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
343                 pa_sink_new_data_set_volume(new_data, &v);
344
345                 new_data->save_volume = TRUE;
346             } else
347                 pa_log_debug("Not restoring volume for sink %s, because already set.", new_data->name);
348         }
349
350         if (u->restore_muted && e->muted_valid) {
351
352             if (!new_data->muted_is_set) {
353                 pa_log_info("Restoring mute state for sink %s.", new_data->name);
354                 pa_sink_new_data_set_muted(new_data, e->muted);
355                 new_data->save_muted = TRUE;
356             } else
357                 pa_log_debug("Not restoring mute state for sink %s, because already set.", new_data->name);
358         }
359
360         pa_xfree(e);
361     }
362
363     pa_xfree(name);
364
365     return PA_HOOK_OK;
366 }
367
368 static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) {
369     char *name;
370     struct entry *e;
371
372     pa_assert(c);
373     pa_assert(new_data);
374     pa_assert(u);
375     pa_assert(u->restore_port);
376
377     name = pa_sprintf_malloc("source:%s", new_data->name);
378
379     if ((e = read_entry(u, name))) {
380
381         if (e->port_valid) {
382             if (!new_data->active_port) {
383                 pa_log_info("Restoring port for source %s.", name);
384                 pa_source_new_data_set_port(new_data, e->port);
385                 new_data->save_port = TRUE;
386             } else
387                 pa_log_debug("Not restoring port for source %s, because already set.", name);
388         }
389
390         pa_xfree(e);
391     }
392
393     pa_xfree(name);
394
395     return PA_HOOK_OK;
396 }
397
398 static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) {
399     char *name;
400     struct entry *e;
401
402     pa_assert(c);
403     pa_assert(new_data);
404     pa_assert(u);
405     pa_assert(u->restore_volume || u->restore_muted);
406
407     name = pa_sprintf_malloc("source:%s", new_data->name);
408
409     if ((e = read_entry(u, name))) {
410
411         if (u->restore_volume && e->volume_valid) {
412
413             if (!new_data->volume_is_set) {
414                 pa_cvolume v;
415
416                 pa_log_info("Restoring volume for source %s.", new_data->name);
417
418                 v = e->volume;
419                 pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map);
420                 pa_source_new_data_set_volume(new_data, &v);
421
422                 new_data->save_volume = TRUE;
423             } else
424                 pa_log_debug("Not restoring volume for source %s, because already set.", new_data->name);
425         }
426
427         if (u->restore_muted && e->muted_valid) {
428
429             if (!new_data->muted_is_set) {
430                 pa_log_info("Restoring mute state for source %s.", new_data->name);
431                 pa_source_new_data_set_muted(new_data, e->muted);
432                 new_data->save_muted = TRUE;
433             } else
434                 pa_log_debug("Not restoring mute state for source %s, because already set.", new_data->name);
435         }
436
437         pa_xfree(e);
438     }
439
440     pa_xfree(name);
441
442     return PA_HOOK_OK;
443 }
444
445 int pa__init(pa_module*m) {
446     pa_modargs *ma = NULL;
447     struct userdata *u;
448     char *fname;
449     pa_sink *sink;
450     pa_source *source;
451     uint32_t idx;
452     pa_bool_t restore_volume = TRUE, restore_muted = TRUE, restore_port = TRUE;
453
454     pa_assert(m);
455
456     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
457         pa_log("Failed to parse module arguments");
458         goto fail;
459     }
460
461     if (pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
462         pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
463         pa_modargs_get_value_boolean(ma, "restore_port", &restore_port) < 0) {
464         pa_log("restore_port=, restore_volume= and restore_muted= expect boolean arguments");
465         goto fail;
466     }
467
468     if (!restore_muted && !restore_volume && !restore_port)
469         pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring port enabled!");
470
471     m->userdata = u = pa_xnew0(struct userdata, 1);
472     u->core = m->core;
473     u->module = m;
474     u->restore_volume = restore_volume;
475     u->restore_muted = restore_muted;
476     u->restore_port = restore_port;
477
478     u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE, subscribe_callback, u);
479
480     if (restore_port) {
481         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);
482         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);
483     }
484
485     if (restore_muted || restore_volume) {
486         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);
487         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);
488     }
489
490     if (!(fname = pa_state_path("device-volumes", TRUE)))
491         goto fail;
492
493     if (!(u->database = pa_database_open(fname, TRUE))) {
494         pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
495         pa_xfree(fname);
496         goto fail;
497     }
498
499     pa_log_info("Sucessfully opened database file '%s'.", fname);
500     pa_xfree(fname);
501
502     for (sink = pa_idxset_first(m->core->sinks, &idx); sink; sink = pa_idxset_next(m->core->sinks, &idx))
503         subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, sink->index, u);
504
505     for (source = pa_idxset_first(m->core->sources, &idx); source; source = pa_idxset_next(m->core->sources, &idx))
506         subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW, source->index, u);
507
508     pa_modargs_free(ma);
509     return 0;
510
511 fail:
512     pa__done(m);
513
514     if (ma)
515         pa_modargs_free(ma);
516
517     return  -1;
518 }
519
520 void pa__done(pa_module*m) {
521     struct userdata* u;
522
523     pa_assert(m);
524
525     if (!(u = m->userdata))
526         return;
527
528     if (u->subscription)
529         pa_subscription_free(u->subscription);
530
531     if (u->sink_fixate_hook_slot)
532         pa_hook_slot_free(u->sink_fixate_hook_slot);
533     if (u->source_fixate_hook_slot)
534         pa_hook_slot_free(u->source_fixate_hook_slot);
535     if (u->sink_new_hook_slot)
536         pa_hook_slot_free(u->sink_new_hook_slot);
537     if (u->source_new_hook_slot)
538         pa_hook_slot_free(u->source_new_hook_slot);
539
540     if (u->save_time_event)
541         u->core->mainloop->time_free(u->save_time_event);
542
543     if (u->database)
544         pa_database_close(u->database);
545
546     pa_xfree(u);
547 }