From b3e16559fceaef151226b82408c118cef448993b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 14 May 2006 00:41:56 +0000 Subject: add new module module-volume-restore which saves and restores volume of playback streams git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@859 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 361 ++++++++++++++++++++++++++++++++++++ 1 file changed, 361 insertions(+) create mode 100644 src/modules/module-volume-restore.c (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c new file mode 100644 index 00000000..c32bb3a9 --- /dev/null +++ b/src/modules/module-volume-restore.c @@ -0,0 +1,361 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-volume-restore-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Playback stream automatic volume restore module") +PA_MODULE_USAGE("table=") +PA_MODULE_VERSION(PACKAGE_VERSION) + +#define WHITESPACE "\n\r \t" + +#define DEFAULT_VOLUME_TABLE_FILE ".polypaudio/volume.table" + +static const char* const valid_modargs[] = { + "table", + NULL, +}; + +struct rule { + char* name; + pa_cvolume volume; +}; + +struct userdata { + pa_hashmap *hashmap; + pa_subscription *subscription; + int modified; + char *table_file; +}; + +static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { + char *p; + long k; + unsigned i; + + assert(s); + assert(v); + + if (!isdigit(*s)) + return NULL; + + k = strtol(s, &p, 0); + if (k <= 0 || k > PA_CHANNELS_MAX) + return NULL; + + v->channels = (unsigned) k; + + for (i = 0; i < v->channels; i++) { + p += strspn(p, WHITESPACE); + + if (!isdigit(*p)) + return NULL; + + k = strtol(p, &p, 0); + + if (k < PA_VOLUME_MUTED) + return NULL; + + v->values[i] = (pa_volume_t) k; + } + + if (*p != 0) + return NULL; + + return v; +} + +static int load_rules(struct userdata *u) { + FILE *f; + int n = 0; + int ret = -1; + char buf_name[256], buf_volume[256]; + char *ln = buf_name; + + f = u->table_file ? + fopen(u->table_file, "r") : + pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "r"); + + if (!f) { + if (errno == ENOENT) { + pa_log(__FILE__": starting with empty ruleset."); + ret = 0; + } else + pa_log(__FILE__": failed to open file '%s': %s", u->table_file, strerror(errno)); + + goto finish; + } + + while (!feof(f)) { + struct rule *rule; + pa_cvolume v; + + if (!fgets(ln, sizeof(buf_name), f)) + break; + + n++; + + pa_strip_nl(ln); + + if (ln[0] == '#' || !*ln ) + continue; + + if (ln == buf_name) { + ln = buf_volume; + continue; + } + + assert(ln == buf_volume); + + if (!parse_volume(buf_volume, &v)) { + pa_log(__FILE__": parse failure in %s:%u, stopping parsing", u->table_file, n); + goto finish; + } + + ln = buf_name; + + if (pa_hashmap_get(u->hashmap, buf_name)) { + pa_log(__FILE__": double entry in %s:%u, ignoring", u->table_file, n); + goto finish; + } + + rule = pa_xnew(struct rule, 1); + rule->name = pa_xstrdup(buf_name); + rule->volume = v; + + pa_hashmap_put(u->hashmap, rule->name, rule); + } + + if (ln == buf_volume) { + pa_log(__FILE__": invalid number of lines in %s.", u->table_file); + goto finish; + } + + ret = 0; + +finish: + if (f) + fclose(f); + + return ret; +} + +static int save_rules(struct userdata *u) { + FILE *f; + int ret = -1; + void *state = NULL; + struct rule *rule; + + f = u->table_file ? + fopen(u->table_file, "w") : + pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w"); + + if (!f) { + pa_log(__FILE__": failed to open file '%s': %s", u->table_file, strerror(errno)); + goto finish; + } + + while ((rule = pa_hashmap_iterate(u->hashmap, &state, NULL))) { + unsigned i; + + fprintf(f, "%s\n%u", rule->name, rule->volume.channels); + + for (i = 0; i < rule->volume.channels; i++) + fprintf(f, " %u", rule->volume.values[i]); + + + fprintf(f, "\n"); + } + + ret = 0; + +finish: + if (f) + fclose(f); + + return ret; +} + +static char* client_name(pa_client *c) { + char *t, *e; + + if (!c->name || !c->driver) + return NULL; + + t = pa_sprintf_malloc("%s$%s", c->driver, c->name); + t[strcspn(t, "\n\r#")] = 0; + + if (!*t) + return NULL; + + if ((e = strrchr(t, '('))) { + char *k = e + 1 + strspn(e + 1, "0123456789-"); + + /* Dirty trick: truncate all trailing parens with numbers in + * between, since they are usually used to identify multiple + * sessions of the same application, which is something we + * explicitly don't want. Besides other stuff this makes xmms + * with esound work properly for us. */ + + if (*k == ')' && *(k+1) == 0) + *e = 0; + } + + return t; +} + +static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + struct userdata *u = userdata; + pa_sink_input *si; + struct rule *r; + char *name; + + assert(c); + assert(u); + + if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) && + t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE)) + return; + + if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) + return; + + if (!si->client || !(name = client_name(si->client))) + return; + + if ((r = pa_hashmap_get(u->hashmap, name))) { + pa_xfree(name); + + if (((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) && si->sample_spec.channels == r->volume.channels) { + pa_log_info(__FILE__": Restoring volume for <%s>", r->name); + pa_sink_input_set_volume(si, &r->volume); + } else if (!pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { + pa_log_info(__FILE__": Saving volume for <%s>", r->name); + r->volume = *pa_sink_input_get_volume(si); + u->modified = 1; + } + + } else { + pa_log_info(__FILE__": Creating new entry for <%s>", name); + + r = pa_xnew(struct rule, 1); + r->name = name; + r->volume = *pa_sink_input_get_volume(si); + pa_hashmap_put(u->hashmap, r->name, r); + + u->modified = 1; + } +} + +int pa__init(pa_core *c, pa_module*m) { + pa_modargs *ma = NULL; + struct userdata *u; + + assert(c); + assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": Failed to parse module arguments"); + goto fail; + } + + u = pa_xnew(struct userdata, 1); + u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + u->subscription = NULL; + u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL)); + u->modified = 0; + + m->userdata = u; + + if (load_rules(u) < 0) + goto fail; + + u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); + + pa_modargs_free(ma); + return 0; + +fail: + pa__done(c, m); + + if (ma) + pa_modargs_free(ma); + + return -1; +} + +static void free_func(void *p, void *userdata) { + struct rule *r = p; + assert(r); + + pa_xfree(r->name); + pa_xfree(r); +} + +void pa__done(pa_core *c, pa_module*m) { + struct userdata* u; + + assert(c); + assert(m); + + if (!(u = m->userdata)) + return; + + if (u->subscription) + pa_subscription_free(u->subscription); + + if (u->hashmap) { + + if (u->modified) + save_rules(u); + + pa_hashmap_free(u->hashmap, free_func, NULL); + } + + pa_xfree(u->table_file); + pa_xfree(u); +} + + -- cgit From 147da3e36ff8c1ce07a14d44e9c8747069f90c18 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 May 2006 12:33:43 +0000 Subject: remove regex.h from include, since it is actually not used git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@869 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index c32bb3a9..b4606bc3 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include -- cgit From 724cd9d811c3847c6e46233185f27b4c5201c260 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 May 2006 00:04:47 +0000 Subject: downgrade a log message git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@875 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index b4606bc3..b379e53c 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -119,7 +119,7 @@ static int load_rules(struct userdata *u) { if (!f) { if (errno == ENOENT) { - pa_log(__FILE__": starting with empty ruleset."); + pa_log_info(__FILE__": starting with empty ruleset."); ret = 0; } else pa_log(__FILE__": failed to open file '%s': %s", u->table_file, strerror(errno)); @@ -204,7 +204,6 @@ static int save_rules(struct userdata *u) { for (i = 0; i < rule->volume.channels; i++) fprintf(f, " %u", rule->volume.values[i]); - fprintf(f, "\n"); } -- cgit From e0bf4a32f3ca7b9cf472a37c31be4a6202d39fa8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 15:21:08 +0000 Subject: add proper locking when accessing the file volume.table git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@905 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index b379e53c..f9e7d013 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "module-volume-restore-symdef.h" @@ -116,7 +117,7 @@ static int load_rules(struct userdata *u) { f = u->table_file ? fopen(u->table_file, "r") : pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "r"); - + if (!f) { if (errno == ENOENT) { pa_log_info(__FILE__": starting with empty ruleset."); @@ -127,6 +128,8 @@ static int load_rules(struct userdata *u) { goto finish; } + pa_lock_fd(fileno(f), 1); + while (!feof(f)) { struct rule *rule; pa_cvolume v; @@ -175,8 +178,10 @@ static int load_rules(struct userdata *u) { ret = 0; finish: - if (f) + if (f) { + pa_lock_fd(fileno(f), 0); fclose(f); + } return ret; } @@ -196,6 +201,8 @@ static int save_rules(struct userdata *u) { goto finish; } + pa_lock_fd(fileno(f), 1); + while ((rule = pa_hashmap_iterate(u->hashmap, &state, NULL))) { unsigned i; @@ -210,8 +217,10 @@ static int save_rules(struct userdata *u) { ret = 0; finish: - if (f) + if (f) { + pa_lock_fd(fileno(f), 0); fclose(f); + } return ret; } -- cgit From d9cc2cfcb97c1b0449bcbfb6ab0301a58d77bd55 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 17 May 2006 16:34:18 +0000 Subject: Move xmalloc to the public side (libpolyp). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@908 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index f9e7d013..ea40d862 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -32,12 +32,13 @@ #include #include +#include + #include #include #include #include #include -#include #include #include #include -- cgit From c47e937011f00eebab7230cedb58fd59f16487b4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 May 2006 20:09:57 +0000 Subject: split polypcore/util.[ch] into polypcore/core-util.[ch] and polyp/util.[ch] git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@917 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index ea40d862..e74567bc 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -35,12 +35,12 @@ #include #include -#include +#include #include #include #include #include -#include +#include #include #include "module-volume-restore-symdef.h" -- cgit From 4e3dc7ce68561c16254712d713b2ccd472b8afe7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 22 May 2006 15:20:46 +0000 Subject: Wrap strerror() in a function that makes it thread safe and converts the output to UTF-8. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@945 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index e74567bc..796e43a3 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -124,7 +125,7 @@ static int load_rules(struct userdata *u) { pa_log_info(__FILE__": starting with empty ruleset."); ret = 0; } else - pa_log(__FILE__": failed to open file '%s': %s", u->table_file, strerror(errno)); + pa_log(__FILE__": failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); goto finish; } @@ -198,7 +199,7 @@ static int save_rules(struct userdata *u) { pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w"); if (!f) { - pa_log(__FILE__": failed to open file '%s': %s", u->table_file, strerror(errno)); + pa_log(__FILE__": failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); goto finish; } -- cgit From 4413b89d7a45587b545a31463ad2196767f45563 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 May 2006 17:16:55 +0000 Subject: * split pa_cstrerror() into its own file polypcore/core-error.[ch] * fix building of padsp * remove a warning when compiling padsp.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@972 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 796e43a3..435f0c96 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -32,9 +32,9 @@ #include #include -#include #include +#include #include #include #include -- cgit From f44ba092651aa75055e109e04b4164ea92ae7fdc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 21:53:48 +0000 Subject: big s/polyp/pulse/g git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1033 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 435f0c96..ede2fcf2 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -1,20 +1,20 @@ /* $Id$ */ /*** - This file is part of polypaudio. + This file is part of PulseAudio. - polypaudio is free software; you can redistribute it and/or modify + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - polypaudio is distributed in the hope that it will be useful, but + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with polypaudio; if not, write to the Free Software + along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ @@ -32,17 +32,17 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "module-volume-restore-symdef.h" @@ -53,7 +53,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#define DEFAULT_VOLUME_TABLE_FILE ".polypaudio/volume.table" +#define DEFAULT_VOLUME_TABLE_FILE ".pulseaudio/volume.table" static const char* const valid_modargs[] = { "table", -- cgit From 3cf16214334b4a1c51e56b0536abd8223d6813dd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 23:51:58 +0000 Subject: * more s/pulseaudio/PulseAudio/ replacements * name the per-user dir ~/.pulse (instead of .pulseaudio), just like /etc/pulse/ git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1039 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index ede2fcf2..2f45082b 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -53,7 +53,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#define DEFAULT_VOLUME_TABLE_FILE ".pulseaudio/volume.table" +#define DEFAULT_VOLUME_TABLE_FILE ".pulse/volume.table" static const char* const valid_modargs[] = { "table", -- cgit From a382492204ad3588c0c837e120e5bc31578df72a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 21:48:35 +0000 Subject: * add new function pa_check_in_group() * abstract credential APis a little bit by introducing HAVE_CREDS and a structure pa_creds * rework credential authentication * fix module-volume-restore and friends for usage in system-wide instance * remove loopback= argument from moulde-*-protocol-tcp since it is a superset of listen= and usually a bad idea anyway since the user shouldn't load the TCP module at all if he doesn't want remote access * rename a few variables in the jack modules to make sure they don't conflict with symbols defined in the system headers * add server address for system-wide daemons to the default server list for the the client libs * update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1109 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 2f45082b..d0956509 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -53,7 +53,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#define DEFAULT_VOLUME_TABLE_FILE ".pulse/volume.table" +#define DEFAULT_VOLUME_TABLE_FILE "volume.table" static const char* const valid_modargs[] = { "table", -- cgit From b37ad1ffd37b2e590191c3dced2b92bb72071dd2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 16:21:20 +0000 Subject: modify module-volume-restore to change the initial volume of a sink input from a hook instead of an asyncronous subscription event. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1238 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index d0956509..d49cceb0 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -68,6 +68,7 @@ struct rule { struct userdata { pa_hashmap *hashmap; pa_subscription *subscription; + pa_hook_slot *hook_slot; int modified; char *table_file; }; @@ -255,7 +256,7 @@ static char* client_name(pa_client *c) { return t; } -static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { +static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = userdata; pa_sink_input *si; struct rule *r; @@ -277,15 +278,11 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v if ((r = pa_hashmap_get(u->hashmap, name))) { pa_xfree(name); - if (((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) && si->sample_spec.channels == r->volume.channels) { - pa_log_info(__FILE__": Restoring volume for <%s>", r->name); - pa_sink_input_set_volume(si, &r->volume); - } else if (!pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { + if (!pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { pa_log_info(__FILE__": Saving volume for <%s>", r->name); r->volume = *pa_sink_input_get_volume(si); u->modified = 1; } - } else { pa_log_info(__FILE__": Creating new entry for <%s>", name); @@ -298,6 +295,26 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v } } +static pa_hook_result_t hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { + struct rule *r; + char *name; + + assert(data); + + if (!data->client || !(name = client_name(data->client))) + return PA_HOOK_OK; + + if ((r = pa_hashmap_get(u->hashmap, name))) { + + if (data->sample_spec_is_set && data->sample_spec.channels == r->volume.channels) { + pa_log_info(__FILE__": Restoring volume for <%s>", r->name); + pa_sink_input_new_data_set_volume(data, &r->volume); + } + } + + return PA_HOOK_OK; +} + int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; @@ -321,7 +338,8 @@ int pa__init(pa_core *c, pa_module*m) { if (load_rules(u) < 0) goto fail; - u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); + u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, subscribe_callback, u); + u->hook_slot = pa_hook_connect(&c->hook_sink_input_new, (pa_hook_cb_t) hook_callback, u); pa_modargs_free(ma); return 0; @@ -355,6 +373,9 @@ void pa__done(pa_core *c, pa_module*m) { if (u->subscription) pa_subscription_free(u->subscription); + if (u->hook_slot) + pa_hook_slot_free(u->hook_slot); + if (u->hashmap) { if (u->modified) -- cgit From 87e64d58454f73bfa1e979b0fedfea7e0827d845 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 13 Aug 2006 17:32:35 +0000 Subject: Clean up module description a little git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1242 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index d49cceb0..bdead0f6 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -47,7 +47,7 @@ #include "module-volume-restore-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Playback stream automatic volume restore module") +PA_MODULE_DESCRIPTION("Automatically restore volume of playback streams") PA_MODULE_USAGE("table=") PA_MODULE_VERSION(PACKAGE_VERSION) -- cgit From e385d93e5aad6a6fce754c00c804ff1d6a6746d4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 21:38:40 +0000 Subject: remove all occurences of pa_logXXX(__FILE__": and replace them by pa_logXXX(" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1272 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index bdead0f6..0e4f278c 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -123,10 +123,10 @@ static int load_rules(struct userdata *u) { if (!f) { if (errno == ENOENT) { - pa_log_info(__FILE__": starting with empty ruleset."); + pa_log_info("starting with empty ruleset."); ret = 0; } else - pa_log(__FILE__": failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); + pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); goto finish; } @@ -155,14 +155,14 @@ static int load_rules(struct userdata *u) { assert(ln == buf_volume); if (!parse_volume(buf_volume, &v)) { - pa_log(__FILE__": parse failure in %s:%u, stopping parsing", u->table_file, n); + pa_log("parse failure in %s:%u, stopping parsing", u->table_file, n); goto finish; } ln = buf_name; if (pa_hashmap_get(u->hashmap, buf_name)) { - pa_log(__FILE__": double entry in %s:%u, ignoring", u->table_file, n); + pa_log("double entry in %s:%u, ignoring", u->table_file, n); goto finish; } @@ -174,7 +174,7 @@ static int load_rules(struct userdata *u) { } if (ln == buf_volume) { - pa_log(__FILE__": invalid number of lines in %s.", u->table_file); + pa_log("invalid number of lines in %s.", u->table_file); goto finish; } @@ -200,7 +200,7 @@ static int save_rules(struct userdata *u) { pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w"); if (!f) { - pa_log(__FILE__": failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); + pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); goto finish; } @@ -279,12 +279,12 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 pa_xfree(name); if (!pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { - pa_log_info(__FILE__": Saving volume for <%s>", r->name); + pa_log_info("Saving volume for <%s>", r->name); r->volume = *pa_sink_input_get_volume(si); u->modified = 1; } } else { - pa_log_info(__FILE__": Creating new entry for <%s>", name); + pa_log_info("Creating new entry for <%s>", name); r = pa_xnew(struct rule, 1); r->name = name; @@ -307,7 +307,7 @@ static pa_hook_result_t hook_callback(pa_core *c, pa_sink_input_new_data *data, if ((r = pa_hashmap_get(u->hashmap, name))) { if (data->sample_spec_is_set && data->sample_spec.channels == r->volume.channels) { - pa_log_info(__FILE__": Restoring volume for <%s>", r->name); + pa_log_info("Restoring volume for <%s>", r->name); pa_sink_input_new_data_set_volume(data, &r->volume); } } @@ -323,7 +323,7 @@ int pa__init(pa_core *c, pa_module*m) { assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log(__FILE__": Failed to parse module arguments"); + pa_log("Failed to parse module arguments"); goto fail; } -- cgit From 521d15babb5be8f3ce47d2e73b1b3470c71159ba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 02:23:11 +0000 Subject: fix a memory leak git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1290 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 0e4f278c..59c47743 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -237,8 +237,10 @@ static char* client_name(pa_client *c) { t = pa_sprintf_malloc("%s$%s", c->driver, c->name); t[strcspn(t, "\n\r#")] = 0; - if (!*t) + if (!*t) { + pa_xfree(t); return NULL; + } if ((e = strrchr(t, '('))) { char *k = e + 1 + strspn(e + 1, "0123456789-"); -- cgit From 3dbc4ae973070760bcc2d525fdb9dcbaecfd1835 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 23:08:50 +0000 Subject: restore the sink/source for a client in addition to the playback volume. This changes the file format of the table file. To avoid parse errors ~/.pulse/volume.table has been renamed to ~/.pulse/volume-restore.table git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1304 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 176 ++++++++++++++++++++++++++++-------- 1 file changed, 140 insertions(+), 36 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 59c47743..efa59f40 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -41,19 +41,21 @@ #include #include #include +#include #include +#include #include #include "module-volume-restore-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Automatically restore volume of playback streams") +PA_MODULE_DESCRIPTION("Automatically restore the volume and the devices of streams") PA_MODULE_USAGE("table=") PA_MODULE_VERSION(PACKAGE_VERSION) #define WHITESPACE "\n\r \t" -#define DEFAULT_VOLUME_TABLE_FILE "volume.table" +#define DEFAULT_VOLUME_TABLE_FILE "volume-restore.table" static const char* const valid_modargs[] = { "table", @@ -62,13 +64,16 @@ static const char* const valid_modargs[] = { struct rule { char* name; + int volume_is_set; pa_cvolume volume; + char *sink; + char *source; }; struct userdata { pa_hashmap *hashmap; pa_subscription *subscription; - pa_hook_slot *hook_slot; + pa_hook_slot *sink_input_hook_slot, *source_output_hook_slot; int modified; char *table_file; }; @@ -114,7 +119,7 @@ static int load_rules(struct userdata *u) { FILE *f; int n = 0; int ret = -1; - char buf_name[256], buf_volume[256]; + char buf_name[256], buf_volume[256], buf_sink[256], buf_source[256]; char *ln = buf_name; f = u->table_file ? @@ -136,6 +141,7 @@ static int load_rules(struct userdata *u) { while (!feof(f)) { struct rule *rule; pa_cvolume v; + int v_is_set; if (!fgets(ln, sizeof(buf_name), f)) break; @@ -144,7 +150,7 @@ static int load_rules(struct userdata *u) { pa_strip_nl(ln); - if (ln[0] == '#' || !*ln ) + if (ln[0] == '#') continue; if (ln == buf_name) { @@ -152,28 +158,46 @@ static int load_rules(struct userdata *u) { continue; } - assert(ln == buf_volume); + if (ln == buf_volume) { + ln = buf_sink; + continue; + } - if (!parse_volume(buf_volume, &v)) { - pa_log("parse failure in %s:%u, stopping parsing", u->table_file, n); - goto finish; + if (ln == buf_sink) { + ln = buf_source; + continue; } + assert(ln == buf_source); + + if (buf_volume[0]) { + if (!parse_volume(buf_volume, &v)) { + pa_log("parse failure in %s:%u, stopping parsing", u->table_file, n); + goto finish; + } + + v_is_set = 1; + } else + v_is_set = 0; + ln = buf_name; if (pa_hashmap_get(u->hashmap, buf_name)) { pa_log("double entry in %s:%u, ignoring", u->table_file, n); - goto finish; + continue; } rule = pa_xnew(struct rule, 1); rule->name = pa_xstrdup(buf_name); - rule->volume = v; + if ((rule->volume_is_set = v_is_set)) + rule->volume = v; + rule->sink = buf_sink[0] ? pa_xstrdup(buf_sink) : NULL; + rule->source = buf_source[0] ? pa_xstrdup(buf_source) : NULL; pa_hashmap_put(u->hashmap, rule->name, rule); } - if (ln == buf_volume) { + if (ln != buf_name) { pa_log("invalid number of lines in %s.", u->table_file); goto finish; } @@ -209,12 +233,18 @@ static int save_rules(struct userdata *u) { while ((rule = pa_hashmap_iterate(u->hashmap, &state, NULL))) { unsigned i; - fprintf(f, "%s\n%u", rule->name, rule->volume.channels); - - for (i = 0; i < rule->volume.channels; i++) - fprintf(f, " %u", rule->volume.values[i]); + fprintf(f, "%s\n", rule->name); - fprintf(f, "\n"); + if (rule->volume_is_set) { + fprintf(f, "%u", rule->volume.channels); + + for (i = 0; i < rule->volume.channels; i++) + fprintf(f, " %u", rule->volume.values[i]); + } + + fprintf(f, "\n%s\n%s\n", + rule->sink ? rule->sink : "", + rule->source ? rule->source : ""); } ret = 0; @@ -260,7 +290,8 @@ static char* client_name(pa_client *c) { static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = userdata; - pa_sink_input *si; + pa_sink_input *si = NULL; + pa_source_output *so = NULL; struct rule *r; char *name; @@ -268,36 +299,80 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 assert(u); if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) && - t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE)) + t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) && + t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) && + t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE)) return; + + if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) { + if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) + return; - if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) - return; - - if (!si->client || !(name = client_name(si->client))) - return; + if (!si->client || !(name = client_name(si->client))) + return; + } else { + assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT); + + if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) + return; + + if (!so->client || !(name = client_name(so->client))) + return; + } if ((r = pa_hashmap_get(u->hashmap, name))) { pa_xfree(name); - if (!pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { - pa_log_info("Saving volume for <%s>", r->name); - r->volume = *pa_sink_input_get_volume(si); - u->modified = 1; + if (si) { + + if (!r->volume_is_set || !pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { + pa_log_info("Saving volume for <%s>", r->name); + r->volume = *pa_sink_input_get_volume(si); + r->volume_is_set = 1; + u->modified = 1; + } + + if (!r->sink || strcmp(si->sink->name, r->sink) != 0) { + pa_log_info("Saving sink for <%s>", r->name); + pa_xfree(r->sink); + r->sink = pa_xstrdup(si->sink->name); + u->modified = 1; + } + } else { + assert(so); + + if (!r->source || strcmp(so->source->name, r->source) != 0) { + pa_log_info("Saving source for <%s>", r->name); + pa_xfree(r->source); + r->source = pa_xstrdup(so->source->name); + u->modified = 1; + } } + } else { pa_log_info("Creating new entry for <%s>", name); r = pa_xnew(struct rule, 1); r->name = name; - r->volume = *pa_sink_input_get_volume(si); - pa_hashmap_put(u->hashmap, r->name, r); + if (si) { + r->volume = *pa_sink_input_get_volume(si); + r->volume_is_set = 1; + r->sink = pa_xstrdup(si->sink->name); + r->source = NULL; + } else { + assert(so); + r->volume_is_set = 0; + r->sink = NULL; + r->source = pa_xstrdup(so->source->name); + } + + pa_hashmap_put(u->hashmap, r->name, r); u->modified = 1; } } -static pa_hook_result_t hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { +static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { struct rule *r; char *name; @@ -308,10 +383,34 @@ static pa_hook_result_t hook_callback(pa_core *c, pa_sink_input_new_data *data, if ((r = pa_hashmap_get(u->hashmap, name))) { - if (data->sample_spec_is_set && data->sample_spec.channels == r->volume.channels) { + if (r->volume_is_set && data->sample_spec.channels == r->volume.channels) { pa_log_info("Restoring volume for <%s>", r->name); pa_sink_input_new_data_set_volume(data, &r->volume); } + + if (!data->sink && r->sink) { + if ((data->sink = pa_namereg_get(c, r->sink, PA_NAMEREG_SINK, 1))) + pa_log_info("Restoring sink for <%s>", r->name); + } + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output_new_data *data, struct userdata *u) { + struct rule *r; + char *name; + + assert(data); + + if (!data->client || !(name = client_name(data->client))) + return PA_HOOK_OK; + + if ((r = pa_hashmap_get(u->hashmap, name))) { + if (!data->source && r->source) { + if ((data->source = pa_namereg_get(c, r->source, PA_NAMEREG_SOURCE, 1))) + pa_log_info("Restoring source for <%s>", r->name); + } } return PA_HOOK_OK; @@ -340,8 +439,9 @@ int pa__init(pa_core *c, pa_module*m) { if (load_rules(u) < 0) goto fail; - u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, subscribe_callback, u); - u->hook_slot = pa_hook_connect(&c->hook_sink_input_new, (pa_hook_cb_t) hook_callback, u); + u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u); + u->sink_input_hook_slot = pa_hook_connect(&c->hook_sink_input_new, (pa_hook_cb_t) sink_input_hook_callback, u); + u->source_output_hook_slot = pa_hook_connect(&c->hook_source_output_new, (pa_hook_cb_t) source_output_hook_callback, u); pa_modargs_free(ma); return 0; @@ -360,6 +460,8 @@ static void free_func(void *p, void *userdata) { assert(r); pa_xfree(r->name); + pa_xfree(r->sink); + pa_xfree(r->source); pa_xfree(r); } @@ -375,8 +477,10 @@ void pa__done(pa_core *c, pa_module*m) { if (u->subscription) pa_subscription_free(u->subscription); - if (u->hook_slot) - pa_hook_slot_free(u->hook_slot); + if (u->sink_input_hook_slot) + pa_hook_slot_free(u->sink_input_hook_slot); + if (u->source_output_hook_slot) + pa_hook_slot_free(u->source_output_hook_slot); if (u->hashmap) { -- cgit From 521daf6f0ac4fa6a2fbfb5d523c0c743342dca2b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 13:43:45 +0000 Subject: Huge trailing whitespace cleanup. Let's keep the tree pure from here on, mmmkay? git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1418 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 64 ++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index efa59f40..877d17c7 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -82,7 +82,7 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { char *p; long k; unsigned i; - + assert(s); assert(v); @@ -92,7 +92,7 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { k = strtol(s, &p, 0); if (k <= 0 || k > PA_CHANNELS_MAX) return NULL; - + v->channels = (unsigned) k; for (i = 0; i < v->channels; i++) { @@ -105,7 +105,7 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { if (k < PA_VOLUME_MUTED) return NULL; - + v->values[i] = (pa_volume_t) k; } @@ -132,22 +132,22 @@ static int load_rules(struct userdata *u) { ret = 0; } else pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); - + goto finish; } pa_lock_fd(fileno(f), 1); - + while (!feof(f)) { struct rule *rule; pa_cvolume v; int v_is_set; - + if (!fgets(ln, sizeof(buf_name), f)) break; n++; - + pa_strip_nl(ln); if (ln[0] == '#') @@ -181,12 +181,12 @@ static int load_rules(struct userdata *u) { v_is_set = 0; ln = buf_name; - + if (pa_hashmap_get(u->hashmap, buf_name)) { pa_log("double entry in %s:%u, ignoring", u->table_file, n); continue; } - + rule = pa_xnew(struct rule, 1); rule->name = pa_xstrdup(buf_name); if ((rule->volume_is_set = v_is_set)) @@ -203,7 +203,7 @@ static int load_rules(struct userdata *u) { } ret = 0; - + finish: if (f) { pa_lock_fd(fileno(f), 0); @@ -218,7 +218,7 @@ static int save_rules(struct userdata *u) { int ret = -1; void *state = NULL; struct rule *rule; - + f = u->table_file ? fopen(u->table_file, "w") : pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w"); @@ -232,7 +232,7 @@ static int save_rules(struct userdata *u) { while ((rule = pa_hashmap_iterate(u->hashmap, &state, NULL))) { unsigned i; - + fprintf(f, "%s\n", rule->name); if (rule->volume_is_set) { @@ -241,14 +241,14 @@ static int save_rules(struct userdata *u) { for (i = 0; i < rule->volume.channels; i++) fprintf(f, " %u", rule->volume.values[i]); } - + fprintf(f, "\n%s\n%s\n", rule->sink ? rule->sink : "", rule->source ? rule->source : ""); } - + ret = 0; - + finish: if (f) { pa_lock_fd(fileno(f), 0); @@ -260,7 +260,7 @@ finish: static char* client_name(pa_client *c) { char *t, *e; - + if (!c->name || !c->driver) return NULL; @@ -280,11 +280,11 @@ static char* client_name(pa_client *c) { * sessions of the same application, which is something we * explicitly don't want. Besides other stuff this makes xmms * with esound work properly for us. */ - + if (*k == ')' && *(k+1) == 0) *e = 0; } - + return t; } @@ -294,7 +294,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 pa_source_output *so = NULL; struct rule *r; char *name; - + assert(c); assert(u); @@ -307,7 +307,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) { if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) return; - + if (!si->client || !(name = client_name(si->client))) return; } else { @@ -315,7 +315,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) return; - + if (!so->client || !(name = client_name(so->client))) return; } @@ -348,7 +348,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 u->modified = 1; } } - + } else { pa_log_info("Creating new entry for <%s>", name); @@ -366,7 +366,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 r->sink = NULL; r->source = pa_xstrdup(so->source->name); } - + pa_hashmap_put(u->hashmap, r->name, r); u->modified = 1; } @@ -419,7 +419,7 @@ static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output int pa__init(pa_core *c, pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; - + assert(c); assert(m); @@ -433,9 +433,9 @@ int pa__init(pa_core *c, pa_module*m) { u->subscription = NULL; u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL)); u->modified = 0; - + m->userdata = u; - + if (load_rules(u) < 0) goto fail; @@ -451,7 +451,7 @@ fail: if (ma) pa_modargs_free(ma); - + return -1; } @@ -467,7 +467,7 @@ static void free_func(void *p, void *userdata) { void pa__done(pa_core *c, pa_module*m) { struct userdata* u; - + assert(c); assert(m); @@ -486,7 +486,7 @@ void pa__done(pa_core *c, pa_module*m) { if (u->modified) save_rules(u); - + pa_hashmap_free(u->hashmap, free_func, NULL); } -- cgit From 06211b7c8fd329137ae9003818543912a87d9898 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Feb 2007 15:35:19 +0000 Subject: Add copyright notices to all relevant files. (based on svn log) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1426 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 877d17c7..0df270df 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -3,6 +3,8 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, -- cgit From 30c52e56c34268d992384aa0cd3370150d90ec43 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 23 May 2007 17:12:07 +0000 Subject: add a missing initialization that causes a crash when parsing invalid volume restoration tables (Problem identified by Luigi Auriemma, re #67) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1451 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 0df270df..61a17aef 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -435,6 +435,7 @@ int pa__init(pa_core *c, pa_module*m) { u->subscription = NULL; u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL)); u->modified = 0; + u->sink_input_hook_slot = u->source_output_hook_slot = NULL; m->userdata = u; -- cgit From a67c21f093202f142438689d3f7cfbdf4ea82eea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 28 Oct 2007 19:13:50 +0000 Subject: merge 'lennart' branch back into trunk. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1971 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 47 +++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 61a17aef..77e6174f 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -26,7 +26,6 @@ #endif #include -#include #include #include #include @@ -35,6 +34,7 @@ #include #include +#include #include #include @@ -44,9 +44,7 @@ #include #include #include -#include #include -#include #include "module-volume-restore-symdef.h" @@ -85,8 +83,8 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { long k; unsigned i; - assert(s); - assert(v); + pa_assert(s); + pa_assert(v); if (!isdigit(*s)) return NULL; @@ -170,7 +168,7 @@ static int load_rules(struct userdata *u) { continue; } - assert(ln == buf_source); + pa_assert(ln == buf_source); if (buf_volume[0]) { if (!parse_volume(buf_volume, &v)) { @@ -297,8 +295,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 struct rule *r; char *name; - assert(c); - assert(u); + pa_assert(c); + pa_assert(u); if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) && t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) && @@ -313,7 +311,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!si->client || !(name = client_name(si->client))) return; } else { - assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT); + pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT); if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) return; @@ -341,7 +339,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 u->modified = 1; } } else { - assert(so); + pa_assert(so); if (!r->source || strcmp(so->source->name, r->source) != 0) { pa_log_info("Saving source for <%s>", r->name); @@ -363,7 +361,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 r->sink = pa_xstrdup(si->sink->name); r->source = NULL; } else { - assert(so); + pa_assert(so); r->volume_is_set = 0; r->sink = NULL; r->source = pa_xstrdup(so->source->name); @@ -378,7 +376,7 @@ static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_d struct rule *r; char *name; - assert(data); + pa_assert(data); if (!data->client || !(name = client_name(data->client))) return PA_HOOK_OK; @@ -396,6 +394,8 @@ static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_d } } + pa_xfree(name); + return PA_HOOK_OK; } @@ -403,7 +403,7 @@ static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output struct rule *r; char *name; - assert(data); + pa_assert(data); if (!data->client || !(name = client_name(data->client))) return PA_HOOK_OK; @@ -418,12 +418,11 @@ static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output return PA_HOOK_OK; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; - assert(c); - assert(m); + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); @@ -442,16 +441,15 @@ int pa__init(pa_core *c, pa_module*m) { if (load_rules(u) < 0) goto fail; - u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u); - u->sink_input_hook_slot = pa_hook_connect(&c->hook_sink_input_new, (pa_hook_cb_t) sink_input_hook_callback, u); - u->source_output_hook_slot = pa_hook_connect(&c->hook_source_output_new, (pa_hook_cb_t) source_output_hook_callback, u); + u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u); + u->sink_input_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], (pa_hook_cb_t) sink_input_hook_callback, u); + u->source_output_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], (pa_hook_cb_t) source_output_hook_callback, u); pa_modargs_free(ma); return 0; fail: - pa__done(c, m); - + pa__done(m); if (ma) pa_modargs_free(ma); @@ -460,7 +458,7 @@ fail: static void free_func(void *p, void *userdata) { struct rule *r = p; - assert(r); + pa_assert(r); pa_xfree(r->name); pa_xfree(r->sink); @@ -468,11 +466,10 @@ static void free_func(void *p, void *userdata) { pa_xfree(r); } -void pa__done(pa_core *c, pa_module*m) { +void pa__done(pa_module*m) { struct userdata* u; - assert(c); - assert(m); + pa_assert(m); if (!(u = m->userdata)) return; -- cgit From faf1fd76a9bb9e47c867f9aa4ea18a7a70a14aae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 4 Nov 2007 16:50:23 +0000 Subject: pa_boolization git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2021 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 77e6174f..8ef72b2a 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -64,7 +64,7 @@ static const char* const valid_modargs[] = { struct rule { char* name; - int volume_is_set; + pa_bool_t volume_is_set; pa_cvolume volume; char *sink; char *source; @@ -74,7 +74,7 @@ struct userdata { pa_hashmap *hashmap; pa_subscription *subscription; pa_hook_slot *sink_input_hook_slot, *source_output_hook_slot; - int modified; + pa_bool_t modified; char *table_file; }; @@ -141,7 +141,7 @@ static int load_rules(struct userdata *u) { while (!feof(f)) { struct rule *rule; pa_cvolume v; - int v_is_set; + pa_bool_t v_is_set; if (!fgets(ln, sizeof(buf_name), f)) break; @@ -176,9 +176,9 @@ static int load_rules(struct userdata *u) { goto finish; } - v_is_set = 1; + v_is_set = TRUE; } else - v_is_set = 0; + v_is_set = FALSE; ln = buf_name; @@ -328,15 +328,15 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!r->volume_is_set || !pa_cvolume_equal(pa_sink_input_get_volume(si), &r->volume)) { pa_log_info("Saving volume for <%s>", r->name); r->volume = *pa_sink_input_get_volume(si); - r->volume_is_set = 1; - u->modified = 1; + r->volume_is_set = TRUE; + u->modified = TRUE; } if (!r->sink || strcmp(si->sink->name, r->sink) != 0) { pa_log_info("Saving sink for <%s>", r->name); pa_xfree(r->sink); r->sink = pa_xstrdup(si->sink->name); - u->modified = 1; + u->modified = TRUE; } } else { pa_assert(so); @@ -345,7 +345,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 pa_log_info("Saving source for <%s>", r->name); pa_xfree(r->source); r->source = pa_xstrdup(so->source->name); - u->modified = 1; + u->modified = TRUE; } } @@ -357,18 +357,18 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (si) { r->volume = *pa_sink_input_get_volume(si); - r->volume_is_set = 1; + r->volume_is_set = TRUE; r->sink = pa_xstrdup(si->sink->name); r->source = NULL; } else { pa_assert(so); - r->volume_is_set = 0; + r->volume_is_set = FALSE; r->sink = NULL; r->source = pa_xstrdup(so->source->name); } pa_hashmap_put(u->hashmap, r->name, r); - u->modified = 1; + u->modified = TRUE; } } @@ -433,7 +433,7 @@ int pa__init(pa_module*m) { u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); u->subscription = NULL; u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL)); - u->modified = 0; + u->modified = FALSE; u->sink_input_hook_slot = u->source_output_hook_slot = NULL; m->userdata = u; @@ -493,5 +493,3 @@ void pa__done(pa_module*m) { pa_xfree(u->table_file); pa_xfree(u); } - - -- cgit From e313fe1b3d0d9f9945c41c151d72edbe9cf1ec54 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 18:25:40 +0000 Subject: tag modules that may only be loaded once at most especially, and enforce that in the module loader git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2043 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 8ef72b2a..422bc7f2 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -48,10 +48,11 @@ #include "module-volume-restore-symdef.h" -PA_MODULE_AUTHOR("Lennart Poettering") -PA_MODULE_DESCRIPTION("Automatically restore the volume and the devices of streams") -PA_MODULE_USAGE("table=") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Automatically restore the volume and the devices of streams"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE("table="); #define WHITESPACE "\n\r \t" -- cgit From 14a9b80afbb0bddc216462b72156f14e032e1b5e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 01:30:40 +0000 Subject: - Check process name when dealing with PID files - Add new PA_STREAM_FIX_CHANNELS, FIX_RATE, FIX_FORMAT, DONT_MOVE, VARIABLE_RATES to pa_sream_flags_t adn implement it - Expose those flags in pacat - Add notifications about device suspend/resume to the protocol and expose them in libpulse - Allow changing of buffer_attr during playback - allow disabling for remixing globally - hookup polkit support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2067 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-volume-restore.c | 134 +++++++++++++++++++++++++++++------- 1 file changed, 109 insertions(+), 25 deletions(-) (limited to 'src/modules/module-volume-restore.c') diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c index 422bc7f2..192a2a78 100644 --- a/src/modules/module-volume-restore.c +++ b/src/modules/module-volume-restore.c @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -52,14 +53,20 @@ PA_MODULE_AUTHOR("Lennart Poettering"); PA_MODULE_DESCRIPTION("Automatically restore the volume and the devices of streams"); PA_MODULE_VERSION(PACKAGE_VERSION); PA_MODULE_LOAD_ONCE(TRUE); -PA_MODULE_USAGE("table="); +PA_MODULE_USAGE( + "table= " + "restore_device= " + "restore_volume=" +); #define WHITESPACE "\n\r \t" - #define DEFAULT_VOLUME_TABLE_FILE "volume-restore.table" +#define SAVE_INTERVAL 10 static const char* const valid_modargs[] = { "table", + "restore_device", + "restore_volume", NULL, }; @@ -67,16 +74,20 @@ struct rule { char* name; pa_bool_t volume_is_set; pa_cvolume volume; - char *sink; - char *source; + char *sink, *source; }; struct userdata { + pa_core *core; pa_hashmap *hashmap; pa_subscription *subscription; - pa_hook_slot *sink_input_hook_slot, *source_output_hook_slot; + pa_hook_slot + *sink_input_new_hook_slot, + *sink_input_fixate_hook_slot, + *source_output_new_hook_slot; pa_bool_t modified; char *table_file; + pa_time_event *save_time_event; }; static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) { @@ -220,12 +231,17 @@ static int save_rules(struct userdata *u) { void *state = NULL; struct rule *rule; + if (!u->modified) + return 0; + + pa_log_info("Saving rules..."); + f = u->table_file ? fopen(u->table_file, "w") : pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w"); if (!f) { - pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); + pa_log("Failed to open file '%s': %s", u->table_file, pa_cstrerror(errno)); goto finish; } @@ -249,6 +265,8 @@ static int save_rules(struct userdata *u) { } ret = 0; + u->modified = FALSE; + pa_log_debug("Successfully saved rules..."); finish: if (f) { @@ -289,6 +307,21 @@ static char* client_name(pa_client *c) { return t; } +static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + + pa_assert(a); + pa_assert(e); + pa_assert(tv); + pa_assert(u); + + pa_assert(e == u->save_time_event); + u->core->mainloop->time_free(u->save_time_event); + u->save_time_event = NULL; + + save_rules(u); +} + static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = userdata; pa_sink_input *si = NULL; @@ -371,14 +404,48 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 pa_hashmap_put(u->hashmap, r->name, r); u->modified = TRUE; } + + if (u->modified && !u->save_time_event) { + struct timeval tv; + pa_gettimeofday(&tv); + tv.tv_sec += SAVE_INTERVAL; + u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u); + } } -static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { +static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { struct rule *r; char *name; pa_assert(data); + /* In the NEW hook we only adjust the device. Adjusting the volume + * is left for the FIXATE hook */ + + if (!data->client || !(name = client_name(data->client))) + return PA_HOOK_OK; + + if ((r = pa_hashmap_get(u->hashmap, name))) { + if (!data->sink && r->sink) { + if ((data->sink = pa_namereg_get(c, r->sink, PA_NAMEREG_SINK, 1))) + pa_log_info("Restoring sink for <%s>", r->name); + } + } + + pa_xfree(name); + + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_input_new_data *data, struct userdata *u) { + struct rule *r; + char *name; + + pa_assert(data); + + /* In the FIXATE hook we only adjust the volum. Adjusting the device + * is left for the NEW hook */ + if (!data->client || !(name = client_name(data->client))) return PA_HOOK_OK; @@ -388,11 +455,6 @@ static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_d pa_log_info("Restoring volume for <%s>", r->name); pa_sink_input_new_data_set_volume(data, &r->volume); } - - if (!data->sink && r->sink) { - if ((data->sink = pa_namereg_get(c, r->sink, PA_NAMEREG_SINK, 1))) - pa_log_info("Restoring sink for <%s>", r->name); - } } pa_xfree(name); @@ -400,7 +462,7 @@ static pa_hook_result_t sink_input_hook_callback(pa_core *c, pa_sink_input_new_d return PA_HOOK_OK; } -static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output_new_data *data, struct userdata *u) { +static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *data, struct userdata *u) { struct rule *r; char *name; @@ -422,6 +484,7 @@ static pa_hook_result_t source_output_hook_callback(pa_core *c, pa_source_output int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; + pa_bool_t restore_device = TRUE, restore_volume = TRUE; pa_assert(m); @@ -431,20 +494,39 @@ int pa__init(pa_module*m) { } u = pa_xnew(struct userdata, 1); + u->core = m->core; u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - u->subscription = NULL; u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL)); u->modified = FALSE; - u->sink_input_hook_slot = u->source_output_hook_slot = NULL; + u->subscription = NULL; + u->sink_input_new_hook_slot = u->sink_input_fixate_hook_slot = u->source_output_new_hook_slot = NULL; + u->save_time_event = NULL; m->userdata = u; + if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 || + pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0) { + pa_log("restore_volume= and restore_device= expect boolean arguments"); + goto fail; + } + + if (!(restore_device || restore_volume)) { + pa_log("Both restrong the volume and restoring the device are disabled. There's no point in using this module at all then, failing."); + goto fail; + } + if (load_rules(u) < 0) goto fail; u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u); - u->sink_input_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], (pa_hook_cb_t) sink_input_hook_callback, u); - u->source_output_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], (pa_hook_cb_t) source_output_hook_callback, u); + + if (restore_device) { + u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], (pa_hook_cb_t) sink_input_new_hook_callback, u); + u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], (pa_hook_cb_t) source_output_new_hook_callback, u); + } + + if (restore_volume) + u->sink_input_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], (pa_hook_cb_t) sink_input_fixate_hook_callback, u); pa_modargs_free(ma); return 0; @@ -478,19 +560,21 @@ void pa__done(pa_module*m) { if (u->subscription) pa_subscription_free(u->subscription); - if (u->sink_input_hook_slot) - pa_hook_slot_free(u->sink_input_hook_slot); - if (u->source_output_hook_slot) - pa_hook_slot_free(u->source_output_hook_slot); + if (u->sink_input_new_hook_slot) + pa_hook_slot_free(u->sink_input_new_hook_slot); + if (u->sink_input_fixate_hook_slot) + pa_hook_slot_free(u->sink_input_fixate_hook_slot); + if (u->source_output_new_hook_slot) + pa_hook_slot_free(u->source_output_new_hook_slot); if (u->hashmap) { - - if (u->modified) - save_rules(u); - + save_rules(u); pa_hashmap_free(u->hashmap, free_func, NULL); } + if (u->save_time_event) + u->core->mainloop->time_free(u->save_time_event); + pa_xfree(u->table_file); pa_xfree(u); } -- cgit