[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.15-test1-13-g9f39a44

Lennart Poettering gitmailer-noreply at 0pointer.de
Wed Feb 4 19:14:36 PST 2009


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  f6ffd2dd5a019e6ea5b2cbd1d19c3a4417043e59 (commit)

- Log -----------------------------------------------------------------
9f39a44... add new module-augment-properties module for augmenting properties from .desktop files
d6201cf... parse ini-style sections properly
ee5abc3... make native protocol use pa_{sink_input|source_output|card}_update_proplist()
524d78f... add missing hook
291589e... allow overwriting of process properties with environment variables
f42afc4... make return value of pa_{sink_input|source_output}_update_proplist() void
a67406d... add pa_client_update_proplist() call
63e2343... handle default volume initialization properly
-----------------------------------------------------------------------

Summary of changes:
 src/Makefile.am                         |   13 ++-
 src/daemon/daemon-conf.c                |  120 +++++++-------
 src/daemon/default.pa.in                |    4 +
 src/modules/module-augment-properties.c |  286 +++++++++++++++++++++++++++++++
 src/modules/module-match.c              |    1 -
 src/pulse/client-conf.c                 |   20 +-
 src/pulsecore/client.c                  |   13 ++
 src/pulsecore/client.h                  |    2 +
 src/pulsecore/conf-parser.c             |   55 ++++--
 src/pulsecore/conf-parser.h             |   15 +-
 src/pulsecore/core.h                    |    1 +
 src/pulsecore/proplist-util.c           |    7 +-
 src/pulsecore/protocol-native.c         |   13 +-
 src/pulsecore/sink-input.c              |   23 ++--
 src/pulsecore/sink-input.h              |    2 +-
 src/pulsecore/source-output.c           |   18 +-
 src/pulsecore/source-output.h           |    2 +-
 17 files changed, 461 insertions(+), 134 deletions(-)
 create mode 100644 src/modules/module-augment-properties.c

-----------------------------------------------------------------------

commit 63e234335fd3362328db34cfc59d27e9899db82b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 5 04:05:47 2009 +0100

    handle default volume initialization properly

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 37d40eb..fa2a383 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -179,8 +179,11 @@ int pa_sink_input_new(
         if (data->sink->flags & PA_SINK_FLAT_VOLUME) {
             data->volume = *pa_sink_get_volume(data->sink, FALSE);
             pa_cvolume_remap(&data->volume, &data->sink->channel_map, &data->channel_map);
-        } else
+            data->volume_is_absolute = TRUE;
+        } else {
             pa_cvolume_reset(&data->volume, data->sample_spec.channels);
+            data->volume_is_absolute = FALSE;
+        }
 
         data->save_volume = FALSE;
     }

commit a67406db936d3db85b819a1126d858c9efe672c2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 5 04:06:50 2009 +0100

    add pa_client_update_proplist() call

diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c
index 1800441..6f3e08e 100644
--- a/src/pulsecore/client.c
+++ b/src/pulsecore/client.c
@@ -126,8 +126,21 @@ void pa_client_kill(pa_client *c) {
 
 void pa_client_set_name(pa_client *c, const char *name) {
     pa_assert(c);
+    pa_assert(name);
 
     pa_log_info("Client %u changed name from \"%s\" to \"%s\"", c->index, pa_strnull(pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME)), name);
     pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
+
+    pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CLIENT_PROPLIST_CHANGED], c);
+    pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->index);
+}
+
+void pa_client_update_proplist(pa_client *c, pa_update_mode_t mode, pa_proplist *p) {
+    pa_assert(c);
+    pa_assert(p);
+
+    pa_proplist_update(c->proplist, mode, p);
+
+    pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CLIENT_PROPLIST_CHANGED], c);
     pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->index);
 }
diff --git a/src/pulsecore/client.h b/src/pulsecore/client.h
index 48e9bc7..8ac80dd 100644
--- a/src/pulsecore/client.h
+++ b/src/pulsecore/client.h
@@ -71,4 +71,6 @@ void pa_client_kill(pa_client *c);
 /* Rename the client */
 void pa_client_set_name(pa_client *c, const char *name);
 
+void pa_client_update_proplist(pa_client *c, pa_update_mode_t mode, pa_proplist *p);
+
 #endif

commit f42afc4883f4a6670e6fff7719beeca481831f9b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 5 04:07:27 2009 +0100

    make return value of pa_{sink_input|source_output}_update_proplist() void

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index fa2a383..9c0bf76 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -940,18 +940,16 @@ pa_bool_t pa_sink_input_get_mute(pa_sink_input *i) {
 }
 
 /* Called from main thread */
-pa_bool_t pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
-
-  pa_sink_input_assert_ref(i);
-
-  pa_proplist_update(i->proplist, mode, p);
+void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p) {
+    pa_sink_input_assert_ref(i);
+    pa_assert(p);
 
-  if (PA_SINK_IS_LINKED(i->state)) {
-      pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
-      pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
-  }
+    pa_proplist_update(i->proplist, mode, p);
 
-  return TRUE;
+    if (PA_SINK_IS_LINKED(i->state)) {
+        pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
+        pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+    }
 }
 
 /* Called from main context */
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 889ee84..20e2cfa 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -294,7 +294,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo
 const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i);
 void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save);
 pa_bool_t pa_sink_input_get_mute(pa_sink_input *i);
-pa_bool_t pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p);
+void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p);
 
 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i);
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 63d56d5..f2f2593 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -615,18 +615,16 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) {
 }
 
 /* Called from main thread */
-pa_bool_t pa_source_output_update_proplist(pa_source_output *o, pa_update_mode_t mode, pa_proplist *p) {
-
-  pa_source_output_assert_ref(o);
-
-  pa_proplist_update(o->proplist, mode, p);
+void pa_source_output_update_proplist(pa_source_output *o, pa_update_mode_t mode, pa_proplist *p) {
+    pa_source_output_assert_ref(o);
+    pa_assert(p);
 
-  if (PA_SINK_IS_LINKED(o->state)) {
-    pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], o);
-    pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
-  }
+    pa_proplist_update(o->proplist, mode, p);
 
-  return TRUE;
+    if (PA_SINK_IS_LINKED(o->state)) {
+        pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], o);
+        pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
+    }
 }
 
 /* Called from main context */
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 91f28f9..aba2510 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -229,7 +229,7 @@ void pa_source_output_kill(pa_source_output*o);
 
 pa_usec_t pa_source_output_get_latency(pa_source_output *o, pa_usec_t *source_latency);
 
-pa_bool_t pa_source_output_update_proplist(pa_source_output *o, pa_update_mode_t mode, pa_proplist *p);
+void pa_source_output_update_proplist(pa_source_output *o, pa_update_mode_t mode, pa_proplist *p);
 
 pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o);
 

commit 291589ecc1ce237b5e43d28cfd890305d815fc89
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 5 04:09:09 2009 +0100

    allow overwriting of process properties with environment variables

diff --git a/src/pulsecore/proplist-util.c b/src/pulsecore/proplist-util.c
index 522c7af..c09c8af 100644
--- a/src/pulsecore/proplist-util.c
+++ b/src/pulsecore/proplist-util.c
@@ -65,11 +65,6 @@ void pa_init_proplist(pa_proplist *p) {
 
                 k = pa_xstrndup(*e+11, kl);
 
-                if (pa_proplist_contains(p, k)) {
-                    pa_xfree(k);
-                    continue;
-                }
-
                 pa_proplist_sets(p, k, *e+11+kl+1);
                 pa_xfree(k);
             }
@@ -80,7 +75,7 @@ void pa_init_proplist(pa_proplist *p) {
         pa_proplist *t;
 
         if ((t = pa_proplist_from_string(pp))) {
-            pa_proplist_update(p, PA_UPDATE_MERGE, t);
+            pa_proplist_update(p, PA_UPDATE_REPLACE, t);
             pa_proplist_free(t);
         }
     }

commit 524d78fc7af4b0d060dab5cb9f968710bf2f1835
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 5 04:09:27 2009 +0100

    add missing hook

diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 2b8f819..1407b1b 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -85,6 +85,7 @@ typedef enum pa_core_hook {
     PA_CORE_HOOK_CLIENT_NEW,
     PA_CORE_HOOK_CLIENT_PUT,
     PA_CORE_HOOK_CLIENT_UNLINK,
+    PA_CORE_HOOK_CLIENT_PROPLIST_CHANGED,
     PA_CORE_HOOK_CARD_NEW,
     PA_CORE_HOOK_CARD_PUT,
     PA_CORE_HOOK_CARD_UNLINK,

commit ee5abc3d64a1270b641f0cdbf1fdbb2ccd5e1c05
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 5 04:10:08 2009 +0100

    make native protocol use pa_{sink_input|source_output|card}_update_proplist()

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 39c834d..65b2bb9 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2295,11 +2295,9 @@ static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t
             return;
         }
 
-    pa_proplist_update(c->client->proplist, PA_UPDATE_REPLACE, p);
+    pa_client_update_proplist(c->client, PA_UPDATE_REPLACE, p);
     pa_proplist_free(p);
 
-    pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
-
     reply = reply_new(tag);
 
     if (c->version >= 13)
@@ -3551,8 +3549,7 @@ static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t
         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
 
-        pa_proplist_update(s->sink_input->proplist, mode, p);
-        pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
+        pa_sink_input_update_proplist(s->sink_input, mode, p);
 
     } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
         record_stream *s;
@@ -3560,13 +3557,11 @@ static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t
         s = pa_idxset_get_by_index(c->record_streams, idx);
         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
 
-        pa_proplist_update(s->source_output->proplist, mode, p);
-        pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
+        pa_source_output_update_proplist(s->source_output, mode, p);
     } else {
         pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
 
-        pa_proplist_update(c->client->proplist, mode, p);
-        pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
+        pa_client_update_proplist(c->client, mode, p);
     }
 
     pa_pstream_send_simple_ack(c->pstream, tag);

commit d6201cfc3ac2c16a4a0fc942be31ce753b9770bd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 5 04:11:26 2009 +0100

    parse ini-style sections properly

diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index 279fb7b..7d3b89f 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -200,7 +200,7 @@ int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {
     return 0;
 }
 
-static int parse_log_target(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_log_target(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     pa_daemon_conf *c = data;
 
     pa_assert(filename);
@@ -216,7 +216,7 @@ static int parse_log_target(const char *filename, unsigned line, const char *lva
     return 0;
 }
 
-static int parse_log_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_log_level(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     pa_daemon_conf *c = data;
 
     pa_assert(filename);
@@ -232,7 +232,7 @@ static int parse_log_level(const char *filename, unsigned line, const char *lval
     return 0;
 }
 
-static int parse_resample_method(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_resample_method(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     pa_daemon_conf *c = data;
 
     pa_assert(filename);
@@ -248,7 +248,7 @@ static int parse_resample_method(const char *filename, unsigned line, const char
     return 0;
 }
 
-static int parse_rlimit(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_rlimit(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
 #ifdef HAVE_SYS_RESOURCE_H
     struct pa_rlimit *r = data;
 
@@ -277,7 +277,7 @@ static int parse_rlimit(const char *filename, unsigned line, const char *lvalue,
     return 0;
 }
 
-static int parse_sample_format(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_sample_format(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     pa_daemon_conf *c = data;
     pa_sample_format_t f;
 
@@ -295,7 +295,7 @@ static int parse_sample_format(const char *filename, unsigned line, const char *
     return 0;
 }
 
-static int parse_sample_rate(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_sample_rate(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     pa_daemon_conf *c = data;
     uint32_t r;
 
@@ -313,7 +313,7 @@ static int parse_sample_rate(const char *filename, unsigned line, const char *lv
     return 0;
 }
 
-static int parse_sample_channels(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_sample_channels(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     pa_daemon_conf *c = data;
     int32_t n;
 
@@ -331,7 +331,7 @@ static int parse_sample_channels(const char *filename, unsigned line, const char
     return 0;
 }
 
-static int parse_fragments(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_fragments(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     pa_daemon_conf *c = data;
     int32_t n;
 
@@ -349,7 +349,7 @@ static int parse_fragments(const char *filename, unsigned line, const char *lval
     return 0;
 }
 
-static int parse_fragment_size_msec(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_fragment_size_msec(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     pa_daemon_conf *c = data;
     int32_t n;
 
@@ -367,7 +367,7 @@ static int parse_fragment_size_msec(const char *filename, unsigned line, const c
     return 0;
 }
 
-static int parse_nice_level(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_nice_level(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     pa_daemon_conf *c = data;
     int32_t level;
 
@@ -385,7 +385,7 @@ static int parse_nice_level(const char *filename, unsigned line, const char *lva
     return 0;
 }
 
-static int parse_rtprio(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+static int parse_rtprio(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     pa_daemon_conf *c = data;
     int32_t rtprio;
 
@@ -409,77 +409,77 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
     unsigned i = 0;
 
     pa_config_item table[] = {
-        { "daemonize",                  pa_config_parse_bool,     NULL },
-        { "fail",                       pa_config_parse_bool,     NULL },
-        { "high-priority",              pa_config_parse_bool,     NULL },
-        { "realtime-scheduling",        pa_config_parse_bool,     NULL },
-        { "disallow-module-loading",    pa_config_parse_bool,     NULL },
-        { "disallow-exit",              pa_config_parse_bool,     NULL },
-        { "use-pid-file",               pa_config_parse_bool,     NULL },
-        { "system-instance",            pa_config_parse_bool,     NULL },
-        { "no-cpu-limit",               pa_config_parse_bool,     NULL },
-        { "disable-shm",                pa_config_parse_bool,     NULL },
-        { "flat-volumes",               pa_config_parse_bool,     NULL },
-        { "exit-idle-time",             pa_config_parse_int,      NULL },
-        { "scache-idle-time",           pa_config_parse_int,      NULL },
-        { "realtime-priority",          parse_rtprio,             NULL },
-        { "dl-search-path",             pa_config_parse_string,   NULL },
-        { "default-script-file",        pa_config_parse_string,   NULL },
-        { "log-target",                 parse_log_target,         NULL },
-        { "log-level",                  parse_log_level,          NULL },
-        { "verbose",                    parse_log_level,          NULL },
-        { "resample-method",            parse_resample_method,    NULL },
-        { "default-sample-format",      parse_sample_format,      NULL },
-        { "default-sample-rate",        parse_sample_rate,        NULL },
-        { "default-sample-channels",    parse_sample_channels,    NULL },
-        { "default-fragments",          parse_fragments,          NULL },
-        { "default-fragment-size-msec", parse_fragment_size_msec, NULL },
-        { "nice-level",                 parse_nice_level,         NULL },
-        { "disable-remixing",           pa_config_parse_bool,     NULL },
-        { "disable-lfe-remixing",       pa_config_parse_bool,     NULL },
-        { "load-default-script-file",   pa_config_parse_bool,     NULL },
-        { "shm-size-bytes",             pa_config_parse_size,     NULL },
-        { "log-meta",                   pa_config_parse_bool,     NULL },
-        { "log-time",                   pa_config_parse_bool,     NULL },
-        { "log-backtrace",              pa_config_parse_unsigned, NULL },
+        { "daemonize",                  pa_config_parse_bool,     NULL, NULL },
+        { "fail",                       pa_config_parse_bool,     NULL, NULL },
+        { "high-priority",              pa_config_parse_bool,     NULL, NULL },
+        { "realtime-scheduling",        pa_config_parse_bool,     NULL, NULL },
+        { "disallow-module-loading",    pa_config_parse_bool,     NULL, NULL },
+        { "disallow-exit",              pa_config_parse_bool,     NULL, NULL },
+        { "use-pid-file",               pa_config_parse_bool,     NULL, NULL },
+        { "system-instance",            pa_config_parse_bool,     NULL, NULL },
+        { "no-cpu-limit",               pa_config_parse_bool,     NULL, NULL },
+        { "disable-shm",                pa_config_parse_bool,     NULL, NULL },
+        { "flat-volumes",               pa_config_parse_bool,     NULL, NULL },
+        { "exit-idle-time",             pa_config_parse_int,      NULL, NULL },
+        { "scache-idle-time",           pa_config_parse_int,      NULL, NULL },
+        { "realtime-priority",          parse_rtprio,             NULL, NULL },
+        { "dl-search-path",             pa_config_parse_string,   NULL, NULL },
+        { "default-script-file",        pa_config_parse_string,   NULL, NULL },
+        { "log-target",                 parse_log_target,         NULL, NULL },
+        { "log-level",                  parse_log_level,          NULL, NULL },
+        { "verbose",                    parse_log_level,          NULL, NULL },
+        { "resample-method",            parse_resample_method,    NULL, NULL },
+        { "default-sample-format",      parse_sample_format,      NULL, NULL },
+        { "default-sample-rate",        parse_sample_rate,        NULL, NULL },
+        { "default-sample-channels",    parse_sample_channels,    NULL, NULL },
+        { "default-fragments",          parse_fragments,          NULL, NULL },
+        { "default-fragment-size-msec", parse_fragment_size_msec, NULL, NULL },
+        { "nice-level",                 parse_nice_level,         NULL, NULL },
+        { "disable-remixing",           pa_config_parse_bool,     NULL, NULL },
+        { "disable-lfe-remixing",       pa_config_parse_bool,     NULL, NULL },
+        { "load-default-script-file",   pa_config_parse_bool,     NULL, NULL },
+        { "shm-size-bytes",             pa_config_parse_size,     NULL, NULL },
+        { "log-meta",                   pa_config_parse_bool,     NULL, NULL },
+        { "log-time",                   pa_config_parse_bool,     NULL, NULL },
+        { "log-backtrace",              pa_config_parse_unsigned, NULL, NULL },
 #ifdef HAVE_SYS_RESOURCE_H
-        { "rlimit-fsize",               parse_rlimit,             NULL },
-        { "rlimit-data",                parse_rlimit,             NULL },
-        { "rlimit-stack",               parse_rlimit,             NULL },
-        { "rlimit-core",                parse_rlimit,             NULL },
-        { "rlimit-rss",                 parse_rlimit,             NULL },
+        { "rlimit-fsize",               parse_rlimit,             NULL, NULL },
+        { "rlimit-data",                parse_rlimit,             NULL, NULL },
+        { "rlimit-stack",               parse_rlimit,             NULL, NULL },
+        { "rlimit-core",                parse_rlimit,             NULL, NULL },
+        { "rlimit-rss",                 parse_rlimit,             NULL, NULL },
 #ifdef RLIMIT_NOFILE
-        { "rlimit-nofile",              parse_rlimit,             NULL },
+        { "rlimit-nofile",              parse_rlimit,             NULL, NULL },
 #endif
 #ifdef RLIMIT_AS
-        { "rlimit-as",                  parse_rlimit,             NULL },
+        { "rlimit-as",                  parse_rlimit,             NULL, NULL },
 #endif
 #ifdef RLIMIT_NPROC
-        { "rlimit-nproc",               parse_rlimit,             NULL },
+        { "rlimit-nproc",               parse_rlimit,             NULL, NULL },
 #endif
 #ifdef RLIMIT_MEMLOCK
-        { "rlimit-memlock",             parse_rlimit,             NULL },
+        { "rlimit-memlock",             parse_rlimit,             NULL, NULL },
 #endif
 #ifdef RLIMIT_LOCKS
-        { "rlimit-locks",               parse_rlimit,             NULL },
+        { "rlimit-locks",               parse_rlimit,             NULL, NULL },
 #endif
 #ifdef RLIMIT_SIGPENDING
-        { "rlimit-sigpending",          parse_rlimit,             NULL },
+        { "rlimit-sigpending",          parse_rlimit,             NULL, NULL },
 #endif
 #ifdef RLIMIT_MSGQUEUE
-        { "rlimit-msgqueue",            parse_rlimit,             NULL },
+        { "rlimit-msgqueue",            parse_rlimit,             NULL, NULL },
 #endif
 #ifdef RLIMIT_NICE
-        { "rlimit-nice",                parse_rlimit,             NULL },
+        { "rlimit-nice",                parse_rlimit,             NULL, NULL },
 #endif
 #ifdef RLIMIT_RTPRIO
-        { "rlimit-rtprio",              parse_rlimit,             NULL },
+        { "rlimit-rtprio",              parse_rlimit,             NULL, NULL },
 #endif
 #ifdef RLIMIT_RTTIME
-        { "rlimit-rttime",              parse_rlimit,             NULL },
+        { "rlimit-rttime",              parse_rlimit,             NULL, NULL },
 #endif
 #endif
-        { NULL,                         NULL,                     NULL },
+        { NULL,                         NULL,                     NULL, NULL },
     };
 
     table[i++].data = &c->daemonize;
diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c
index 58d6464..71f8443 100644
--- a/src/pulse/client-conf.c
+++ b/src/pulse/client-conf.c
@@ -92,16 +92,16 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
 
     /* Prepare the configuration parse table */
     pa_config_item table[] = {
-        { "daemon-binary",          pa_config_parse_string,  NULL },
-        { "extra-arguments",        pa_config_parse_string,  NULL },
-        { "default-sink",           pa_config_parse_string,  NULL },
-        { "default-source",         pa_config_parse_string,  NULL },
-        { "default-server",         pa_config_parse_string,  NULL },
-        { "autospawn",              pa_config_parse_bool,    NULL },
-        { "cookie-file",            pa_config_parse_string,  NULL },
-        { "disable-shm",            pa_config_parse_bool,    NULL },
-        { "shm-size-bytes",         pa_config_parse_size,    NULL },
-        { NULL,                     NULL,                    NULL },
+        { "daemon-binary",          pa_config_parse_string,  NULL, NULL },
+        { "extra-arguments",        pa_config_parse_string,  NULL, NULL },
+        { "default-sink",           pa_config_parse_string,  NULL, NULL },
+        { "default-source",         pa_config_parse_string,  NULL, NULL },
+        { "default-server",         pa_config_parse_string,  NULL, NULL },
+        { "autospawn",              pa_config_parse_bool,    NULL, NULL },
+        { "cookie-file",            pa_config_parse_string,  NULL, NULL },
+        { "disable-shm",            pa_config_parse_bool,    NULL, NULL },
+        { "shm-size-bytes",         pa_config_parse_size,    NULL, NULL },
+        { NULL,                     NULL,                    NULL, NULL },
     };
 
     table[0].data = &c->daemon_binary;
diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c
index ef6d6bb..b7ec2b3 100644
--- a/src/pulsecore/conf-parser.c
+++ b/src/pulsecore/conf-parser.c
@@ -40,17 +40,19 @@
 #define COMMENTS "#;\n"
 
 /* Run the user supplied parser for an assignment */
-static int next_assignment(const char *filename, unsigned line, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) {
+static int next_assignment(const char *filename, unsigned line, const char *section, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) {
     pa_assert(filename);
     pa_assert(t);
     pa_assert(lvalue);
     pa_assert(rvalue);
 
     for (; t->parse; t++)
-        if (!strcmp(lvalue, t->lvalue))
-            return t->parse(filename, line, lvalue, rvalue, t->data, userdata);
+        if (!t->lvalue ||
+            (pa_streq(lvalue, t->lvalue) &&
+             ((!section && !t->section) || pa_streq(section, t->section))))
+            return t->parse(filename, line, section, lvalue, rvalue, t->data, userdata);
 
-    pa_log("[%s:%u] Unknown lvalue '%s'.", filename, line, lvalue);
+    pa_log("[%s:%u] Unknown lvalue '%s' in section '%s'.", filename, line, lvalue, pa_strnull(section));
 
     return -1;
 }
@@ -83,8 +85,10 @@ static char *strip(char *s) {
 }
 
 /* Parse a variable assignment line */
-static int parse_line(const char *filename, unsigned line, const pa_config_item *t, char *l, void *userdata) {
-    char *e, *c, *b = l+strspn(l, WHITESPACE);
+static int parse_line(const char *filename, unsigned line, char **section, const pa_config_item *t, char *l, void *userdata) {
+    char *e, *c, *b;
+
+    b = l+strspn(l, WHITESPACE);
 
     if ((c = strpbrk(b, COMMENTS)))
         *c = 0;
@@ -92,6 +96,22 @@ static int parse_line(const char *filename, unsigned line, const pa_config_item
     if (!*b)
         return 0;
 
+    if (*b == '[') {
+        size_t k;
+
+        k = strlen(b);
+        pa_assert(k > 0);
+
+        if (b[k-1] != ']') {
+            pa_log("[%s:%u] Invalid section header.", filename, line);
+            return -1;
+        }
+
+        pa_xfree(*section);
+        *section = pa_xstrndup(b+1, k-2);
+        return 0;
+    }
+
     if (!(e = strchr(b, '='))) {
         pa_log("[%s:%u] Missing '='.", filename, line);
         return -1;
@@ -100,7 +120,7 @@ static int parse_line(const char *filename, unsigned line, const pa_config_item
     *e = 0;
     e++;
 
-    return next_assignment(filename, line, t, strip(b), strip(e), userdata);
+    return next_assignment(filename, line, *section, t, strip(b), strip(e), userdata);
 }
 
 /* Go through the file and parse each line */
@@ -108,6 +128,7 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void
     int r = -1;
     unsigned line = 0;
     int do_close = !f;
+    char *section = NULL;
 
     pa_assert(filename);
     pa_assert(t);
@@ -118,29 +139,29 @@ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void
             goto finish;
         }
 
-        pa_log_warn("Failed to open configuration file '%s': %s",
-            filename, pa_cstrerror(errno));
+        pa_log_warn("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno));
         goto finish;
     }
 
     while (!feof(f)) {
         char l[256];
+
         if (!fgets(l, sizeof(l), f)) {
             if (feof(f))
                 break;
 
-            pa_log_warn("Failed to read configuration file '%s': %s",
-                filename, pa_cstrerror(errno));
+            pa_log_warn("Failed to read configuration file '%s': %s", filename, pa_cstrerror(errno));
             goto finish;
         }
 
-        if (parse_line(filename, ++line, t,  l, userdata) < 0)
+        if (parse_line(filename, ++line, &section, t, l, userdata) < 0)
             goto finish;
     }
 
     r = 0;
 
 finish:
+    pa_xfree(section);
 
     if (do_close && f)
         fclose(f);
@@ -148,7 +169,7 @@ finish:
     return r;
 }
 
-int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+int pa_config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     int *i = data;
     int32_t k;
 
@@ -166,7 +187,7 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue,
     return 0;
 }
 
-int pa_config_parse_unsigned(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+int pa_config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     unsigned *u = data;
     uint32_t k;
 
@@ -184,7 +205,7 @@ int pa_config_parse_unsigned(const char *filename, unsigned line, const char *lv
     return 0;
 }
 
-int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+int pa_config_parse_size(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     size_t *i = data;
     uint32_t k;
 
@@ -202,7 +223,7 @@ int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue
     return 0;
 }
 
-int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+int pa_config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     int k;
     pa_bool_t *b = data;
 
@@ -221,7 +242,7 @@ int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue
     return 0;
 }
 
-int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+int pa_config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     char **s = data;
 
     pa_assert(filename);
diff --git a/src/pulsecore/conf-parser.h b/src/pulsecore/conf-parser.h
index 48a0fd2..f8f059f 100644
--- a/src/pulsecore/conf-parser.h
+++ b/src/pulsecore/conf-parser.h
@@ -27,11 +27,14 @@
 /* An abstract parser for simple, line based, shallow configuration
  * files consisting of variable assignments only. */
 
+typedef int (*pa_config_parser_cb_t)(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
+
 /* Wraps info for parsing a specific configuration variable */
 typedef struct pa_config_item {
     const char *lvalue; /* name of the variable */
-    int (*parse)(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); /* Function that is called to parse the variable's value */
+    pa_config_parser_cb_t parse; /* Function that is called to parse the variable's value */
     void *data; /* Where to store the variable's data */
+    const char *section;
 } pa_config_item;
 
 /* The configuration file parsing routine. Expects a table of
@@ -40,10 +43,10 @@ typedef struct pa_config_item {
 int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata);
 
 /* Generic parsers for integers, size_t, booleans and strings */
-int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
-int pa_config_parse_unsigned(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
-int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
-int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
-int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
+int pa_config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
+int pa_config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
+int pa_config_parse_size(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
+int pa_config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
+int pa_config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata);
 
 #endif

commit 9f39a44488644e8d54e9c8a4096abf2d39040c1f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 5 04:14:30 2009 +0100

    add new module-augment-properties module for augmenting properties from .desktop files

diff --git a/src/Makefile.am b/src/Makefile.am
index 1910a82..ca8240f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -895,7 +895,8 @@ modlibexec_LTLIBRARIES += \
 		module-esound-sink.la \
 		module-tunnel-sink.la \
 		module-tunnel-source.la \
-		module-position-event-sounds.la
+		module-position-event-sounds.la \
+		module-augment-properties.la
 
 
 # See comment at librtp.la above
@@ -1084,6 +1085,7 @@ SYMDEF_FILES = \
 		modules/module-raop-discover-symdef.h \
 		modules/gconf/module-gconf-symdef.h \
 		modules/module-position-event-sounds-symdef.h \
+		modules/module-augment-properties-symdef.h \
 		modules/module-console-kit-symdef.h
 
 EXTRA_DIST += $(SYMDEF_FILES)
@@ -1336,7 +1338,14 @@ module_volume_restore_la_CFLAGS = $(AM_CFLAGS)
 module_position_event_sounds_la_SOURCES = modules/module-position-event-sounds.c
 module_position_event_sounds_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_position_event_sounds_la_LIBADD = $(AM_LIBADD) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
-module_position_event_sounds_CFLAGS = $(AM_CFLAGS)
+module_position_event_sounds_la_CFLAGS = $(AM_CFLAGS)
+
+# Augment properties from XDG .desktop files
+module_augment_properties_la_SOURCES = modules/module-augment-properties.c
+module_augment_properties_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_augment_properties_la_LIBADD = $(AM_LIBADD) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
+#module_augment_properties_la_CFLAGS = $(AM_CFLAGS) -DDESKTOPFILEDIR=\"$(datadir)/applications\"
+module_augment_properties_la_CFLAGS = $(AM_CFLAGS) -DDESKTOPFILEDIR=\"/usr/share/applications\"
 
 # Device volume/muted restore module
 module_device_restore_la_SOURCES = modules/module-device-restore.c
diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 91a1c61..2606190 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -34,6 +34,10 @@ load-module module-device-restore
 load-module module-stream-restore
 load-module module-card-restore
 
+### Automatically augment property information from .desktop files
+### stored in /usr/share/application
+load-module module-augment-properties
+
 ### Load audio drivers statically (it's probably better to not load
 ### these drivers manually, but instead use module-hal-detect --
 ### see below -- for doing this automatically)
diff --git a/src/modules/module-augment-properties.c b/src/modules/module-augment-properties.c
new file mode 100644
index 0000000..a2475db
--- /dev/null
+++ b/src/modules/module-augment-properties.c
@@ -0,0 +1,286 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2009 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,
+  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
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/stat.h>
+
+#include <pulse/xmalloc.h>
+#include <pulse/volume.h>
+#include <pulse/channelmap.h>
+
+#include <pulsecore/core-error.h>
+#include <pulsecore/module.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/log.h>
+#include <pulsecore/client.h>
+#include <pulsecore/conf-parser.h>
+
+#include "module-augment-properties-symdef.h"
+
+PA_MODULE_AUTHOR("Lennart Poettering");
+PA_MODULE_DESCRIPTION("Augment the property sets of streams with additional static information");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(TRUE);
+
+#define STAT_INTERVAL 30
+#define MAX_CACHE_SIZE 50
+
+static const char* const valid_modargs[] = {
+    NULL
+};
+
+struct rule {
+    time_t timestamp;
+    pa_bool_t good;
+    time_t mtime;
+    char *process_name;
+    char *application_name;
+    char *icon_name;
+    pa_proplist *proplist;
+};
+
+struct userdata {
+    pa_hashmap *cache;
+    pa_hook_slot *client_new_slot, *client_proplist_changed_slot;
+};
+
+static void rule_free(struct rule *r) {
+    pa_assert(r);
+
+    pa_xfree(r->process_name);
+    pa_xfree(r->application_name);
+    pa_xfree(r->icon_name);
+    if (r->proplist)
+        pa_proplist_free(r->proplist);
+    pa_xfree(r);
+}
+
+static int parse_properties(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+    struct rule *r = userdata;
+    pa_proplist *n;
+
+    if (!(n = pa_proplist_from_string(rvalue)))
+        return -1;
+
+    if (r->proplist) {
+        pa_proplist_update(r->proplist, PA_UPDATE_MERGE, n);
+        pa_proplist_free(n);
+    } else
+        r->proplist = n;
+
+    return 0;
+}
+
+static int check_type(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+    return pa_streq(rvalue, "Application") ? 0 : -1;
+}
+
+static int catch_all(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+    return 0;
+}
+
+static void update_rule(struct rule *r) {
+    char *fn;
+    struct stat st;
+    static pa_config_item table[] = {
+        { "Name", pa_config_parse_string,              NULL, "Desktop Entry" },
+        { "Icon", pa_config_parse_string,              NULL, "Desktop Entry" },
+        { "Type", check_type,                          NULL, "Desktop Entry" },
+        { "X-PulseAudio-Properties", parse_properties, NULL, "Desktop Entry" },
+        { NULL,  catch_all, NULL, NULL },
+        { NULL, NULL, NULL, NULL },
+    };
+
+    pa_assert(r);
+    fn = pa_sprintf_malloc(DESKTOPFILEDIR PA_PATH_SEP "%s.desktop", r->process_name);
+
+    if (stat(fn, &st) < 0) {
+        r->good = FALSE;
+        pa_xfree(fn);
+        return;
+    }
+
+    if (r->good && st.st_mtime == r->mtime) {
+        pa_xfree(fn);
+        return;
+    }
+
+    r->good = TRUE;
+    r->mtime = st.st_mtime;
+    pa_xfree(r->application_name);
+    pa_xfree(r->icon_name);
+    r->application_name = r->icon_name = NULL;
+    if (r->proplist)
+        pa_proplist_clear(r->proplist);
+
+    table[0].data = &r->application_name;
+    table[1].data = &r->icon_name;
+
+    if (pa_config_parse(fn, NULL, table, r) < 0)
+        pa_log_warn("Failed to parse .desktop file %s.", fn);
+
+    pa_xfree(fn);
+}
+
+static void apply_rule(struct rule *r, pa_proplist *p) {
+    pa_assert(r);
+    pa_assert(p);
+
+    if (!r->good)
+        return;
+
+    if (r->icon_name)
+        if (!pa_proplist_contains(p, PA_PROP_APPLICATION_ICON_NAME))
+            pa_proplist_sets(p, PA_PROP_APPLICATION_ICON_NAME, r->icon_name);
+
+    if (r->application_name) {
+        const char *t;
+
+        t = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME);
+
+        if (!t || pa_streq(t, r->process_name))
+            pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, r->application_name);
+    }
+
+    if (r->proplist)
+        pa_proplist_update(p, PA_UPDATE_MERGE, r->proplist);
+}
+
+static void make_room(pa_hashmap *cache) {
+    pa_assert(cache);
+
+    while (pa_hashmap_size(cache) >= MAX_CACHE_SIZE) {
+        struct rule *r;
+
+        pa_assert_se(r = pa_hashmap_steal_first(cache));
+        rule_free(r);
+    }
+}
+
+static pa_hook_result_t process(struct userdata *u, pa_proplist *p) {
+    struct rule *r;
+    time_t now;
+    const char *pn;
+
+    pa_assert(u);
+    pa_assert(p);
+
+    if (!(pn = pa_proplist_gets(p, PA_PROP_APPLICATION_PROCESS_BINARY)))
+        return PA_HOOK_OK;
+
+    if (*pn == '.' || strchr(pn, '/'))
+        return PA_HOOK_OK;
+
+    time(&now);
+
+    if ((r = pa_hashmap_get(u->cache, pn))) {
+        if (now-r->timestamp > STAT_INTERVAL) {
+            r->timestamp = now;
+            update_rule(r);
+        }
+    } else {
+        make_room(u->cache);
+
+        r = pa_xnew0(struct rule, 1);
+        r->process_name = pa_xstrdup(pn);
+        r->timestamp = now;
+        pa_hashmap_put(u->cache, r->process_name, r);
+        update_rule(r);
+    }
+
+    apply_rule(r, p);
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t client_new_cb(pa_core *core, pa_client_new_data *data, struct userdata *u) {
+    pa_core_assert_ref(core);
+    pa_assert(data);
+    pa_assert(u);
+
+    return process(u, data->proplist);
+}
+
+static pa_hook_result_t client_proplist_changed_cb(pa_core *core, pa_client *client, struct userdata *u) {
+    pa_core_assert_ref(core);
+    pa_assert(client);
+    pa_assert(u);
+
+    return process(u, client->proplist);
+}
+
+int pa__init(pa_module*m) {
+    pa_modargs *ma = NULL;
+    struct userdata *u;
+
+    pa_assert(m);
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log("Failed to parse module arguments");
+        goto fail;
+    }
+
+    m->userdata = u = pa_xnew(struct userdata, 1);
+
+    u->cache = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+    u->client_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_CLIENT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) client_new_cb, u);
+    u->client_proplist_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_CLIENT_PROPLIST_CHANGED], PA_HOOK_EARLY, (pa_hook_cb_t) client_proplist_changed_cb, u);
+
+    pa_modargs_free(ma);
+
+    return 0;
+
+fail:
+    pa__done(m);
+
+    if (ma)
+        pa_modargs_free(ma);
+
+    return  -1;
+}
+
+void pa__done(pa_module*m) {
+    struct userdata* u;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if (u->client_new_slot)
+        pa_hook_slot_free(u->client_new_slot);
+    if (u->client_proplist_changed_slot)
+        pa_hook_slot_free(u->client_proplist_changed_slot);
+
+    if (u->cache) {
+        struct rule *r;
+
+        while ((r = pa_hashmap_steal_first(u->cache)))
+            rule_free(r);
+
+        pa_hashmap_free(u->cache, NULL, NULL);
+    }
+
+    pa_xfree(u);
+}
diff --git a/src/modules/module-match.c b/src/modules/module-match.c
index cbf6268..1793611 100644
--- a/src/modules/module-match.c
+++ b/src/modules/module-match.c
@@ -233,7 +233,6 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-
     u = pa_xnew(struct userdata, 1);
     u->rules = NULL;
     u->subscription = NULL;

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list