]> code.delx.au - pulseaudio/commitdiff
introduce default channel map in addition to the default sample spec
authorLennart Poettering <lennart@poettering.net>
Sat, 21 Feb 2009 15:32:42 +0000 (16:32 +0100)
committerLennart Poettering <lennart@poettering.net>
Sat, 21 Feb 2009 15:32:42 +0000 (16:32 +0100)
24 files changed:
man/pulse-daemon.conf.5.xml.in
src/daemon/daemon-conf.c
src/daemon/daemon-conf.h
src/daemon/daemon.conf.in
src/daemon/main.c
src/modules/alsa/alsa-sink.c
src/modules/alsa/alsa-source.c
src/modules/module-combine.c
src/modules/module-jack-sink.c
src/modules/module-jack-source.c
src/modules/module-null-sink.c
src/modules/module-pipe-sink.c
src/modules/module-pipe-source.c
src/modules/module-tunnel.c
src/modules/module-zeroconf-discover.c
src/modules/oss/module-oss.c
src/pulse/introspect.c
src/pulse/introspect.h
src/pulsecore/cli-command.c
src/pulsecore/core.c
src/pulsecore/core.h
src/pulsecore/modargs.c
src/pulsecore/protocol-native.c
src/utils/pactl.c

index 9ddcd6ae0d7739ccc3ee212b0699db64cdd77cfb..afa7ca00c8cd3e2bc29b8cfa7e8725000db370d5 100644 (file)
@@ -388,6 +388,10 @@ USA.
       <p><opt>default-sample-channels</opt> The default number of channels.</p>
     </option>
 
+    <option>
+      <p><opt>default-channel-map</opt> The default channel map.</p>
+    </option>
+
   </section>
 
   <section name="Default Fragment Settings">
index 7dfef27fc7f9e301fa7edb6b7e5ae758f87b3acc..10144ea45b302718ef84548a161f5204818017e0 100644 (file)
@@ -88,6 +88,7 @@ static const pa_daemon_conf default_conf = {
     .default_n_fragments = 4,
     .default_fragment_size_msec = 25,
     .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
+    .default_channel_map = { .channels = 2, .map = { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } },
     .shm_size = 0
 #ifdef HAVE_SYS_RESOURCE_H
    ,.rlimit_fsize = { .value = 0, .is_set = FALSE },
@@ -313,8 +314,14 @@ static int parse_sample_rate(const char *filename, unsigned line, const char *se
     return 0;
 }
 
+struct channel_conf_info {
+    pa_daemon_conf *conf;
+    pa_bool_t default_sample_spec_set;
+    pa_bool_t default_channel_map_set;
+};
+
 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;
+    struct channel_conf_info *i = data;
     int32_t n;
 
     pa_assert(filename);
@@ -327,7 +334,25 @@ static int parse_sample_channels(const char *filename, unsigned line, const char
         return -1;
     }
 
-    c->default_sample_spec.channels = (uint8_t) n;
+    i->conf->default_sample_spec.channels = (uint8_t) n;
+    i->default_sample_spec_set = TRUE;
+    return 0;
+}
+
+static int parse_channel_map(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+    struct channel_conf_info *i = data;
+
+    pa_assert(filename);
+    pa_assert(lvalue);
+    pa_assert(rvalue);
+    pa_assert(data);
+
+    if (!pa_channel_map_parse(&i->conf->default_channel_map, rvalue)) {
+        pa_log(_("[%s:%u] Invalid channel map '%s'."), filename, line, rvalue);
+        return -1;
+    }
+
+    i->default_channel_map_set = TRUE;
     return 0;
 }
 
@@ -406,155 +431,82 @@ static int parse_rtprio(const char *filename, unsigned line, const char *section
 int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
     int r = -1;
     FILE *f = NULL;
-    unsigned i = 0;
-
+    struct channel_conf_info ci;
     pa_config_item table[] = {
-        { "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 },
+        { "daemonize",                  pa_config_parse_bool,     &c->daemonize, NULL },
+        { "fail",                       pa_config_parse_bool,     &c->fail, NULL },
+        { "high-priority",              pa_config_parse_bool,     &c->high_priority, NULL },
+        { "realtime-scheduling",        pa_config_parse_bool,     &c->realtime_scheduling, NULL },
+        { "disallow-module-loading",    pa_config_parse_bool,     &c->disallow_module_loading, NULL },
+        { "disallow-exit",              pa_config_parse_bool,     &c->disallow_exit, NULL },
+        { "use-pid-file",               pa_config_parse_bool,     &c->use_pid_file, NULL },
+        { "system-instance",            pa_config_parse_bool,     &c->system_instance, NULL },
+        { "no-cpu-limit",               pa_config_parse_bool,     &c->no_cpu_limit, NULL },
+        { "disable-shm",                pa_config_parse_bool,     &c->disable_shm, NULL },
+        { "flat-volumes",               pa_config_parse_bool,     &c->flat_volumes, NULL },
+        { "exit-idle-time",             pa_config_parse_int,      &c->exit_idle_time, NULL },
+        { "scache-idle-time",           pa_config_parse_int,      &c->scache_idle_time, NULL },
+        { "realtime-priority",          parse_rtprio,             c, NULL },
+        { "dl-search-path",             pa_config_parse_string,   &c->dl_search_path, NULL },
+        { "default-script-file",        pa_config_parse_string,   &c->default_script_file, NULL },
+        { "log-target",                 parse_log_target,         c, NULL },
+        { "log-level",                  parse_log_level,          c, NULL },
+        { "verbose",                    parse_log_level,          c, NULL },
+        { "resample-method",            parse_resample_method,    c, NULL },
+        { "default-sample-format",      parse_sample_format,      c, NULL },
+        { "default-sample-rate",        parse_sample_rate,        c, NULL },
+        { "default-sample-channels",    parse_sample_channels,    &ci,  NULL },
+        { "default-channel-map",        parse_channel_map,        &ci,  NULL },
+        { "default-fragments",          parse_fragments,          c, NULL },
+        { "default-fragment-size-msec", parse_fragment_size_msec, c, NULL },
+        { "nice-level",                 parse_nice_level,         c, NULL },
+        { "disable-remixing",           pa_config_parse_bool,     &c->disable_remixing, NULL },
+        { "disable-lfe-remixing",       pa_config_parse_bool,     &c->disable_lfe_remixing, NULL },
+        { "load-default-script-file",   pa_config_parse_bool,     &c->load_default_script_file, NULL },
+        { "shm-size-bytes",             pa_config_parse_size,     &c->shm_size, NULL },
+        { "log-meta",                   pa_config_parse_bool,     &c->log_meta, NULL },
+        { "log-time",                   pa_config_parse_bool,     &c->log_time, NULL },
+        { "log-backtrace",              pa_config_parse_unsigned, &c->log_backtrace, NULL },
 #ifdef HAVE_SYS_RESOURCE_H
-        { "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 },
+        { "rlimit-fsize",               parse_rlimit,             &c->rlimit_fsize, NULL },
+        { "rlimit-data",                parse_rlimit,             &c->rlimit_data, NULL },
+        { "rlimit-stack",               parse_rlimit,             &c->rlimit_stack, NULL },
+        { "rlimit-core",                parse_rlimit,             &c->rlimit_core, NULL },
+        { "rlimit-rss",                 parse_rlimit,             &c->rlimit_rss, NULL },
 #ifdef RLIMIT_NOFILE
-        { "rlimit-nofile",              parse_rlimit,             NULL, NULL },
+        { "rlimit-nofile",              parse_rlimit,             &c->rlimit_nofile, NULL },
 #endif
 #ifdef RLIMIT_AS
-        { "rlimit-as",                  parse_rlimit,             NULL, NULL },
+        { "rlimit-as",                  parse_rlimit,             &c->rlimit_as, NULL },
 #endif
 #ifdef RLIMIT_NPROC
-        { "rlimit-nproc",               parse_rlimit,             NULL, NULL },
+        { "rlimit-nproc",               parse_rlimit,             &c->rlimit_nproc, NULL },
 #endif
 #ifdef RLIMIT_MEMLOCK
-        { "rlimit-memlock",             parse_rlimit,             NULL, NULL },
+        { "rlimit-memlock",             parse_rlimit,             &c->rlimit_memlock, NULL },
 #endif
 #ifdef RLIMIT_LOCKS
-        { "rlimit-locks",               parse_rlimit,             NULL, NULL },
+        { "rlimit-locks",               parse_rlimit,             &c->rlimit_locks, NULL },
 #endif
 #ifdef RLIMIT_SIGPENDING
-        { "rlimit-sigpending",          parse_rlimit,             NULL, NULL },
+        { "rlimit-sigpending",          parse_rlimit,             &c->rlimit_sigpending, NULL },
 #endif
 #ifdef RLIMIT_MSGQUEUE
-        { "rlimit-msgqueue",            parse_rlimit,             NULL, NULL },
+        { "rlimit-msgqueue",            parse_rlimit,             &c->rlimit_msgqueue, NULL },
 #endif
 #ifdef RLIMIT_NICE
-        { "rlimit-nice",                parse_rlimit,             NULL, NULL },
+        { "rlimit-nice",                parse_rlimit,             &c->rlimit_nice, NULL },
 #endif
 #ifdef RLIMIT_RTPRIO
-        { "rlimit-rtprio",              parse_rlimit,             NULL, NULL },
+        { "rlimit-rtprio",              parse_rlimit,             &c->rlimit_rtprio, NULL },
 #endif
 #ifdef RLIMIT_RTTIME
-        { "rlimit-rttime",              parse_rlimit,             NULL, NULL },
+        { "rlimit-rttime",              parse_rlimit,             &c->rlimit_rttime, NULL },
 #endif
 #endif
         { NULL,                         NULL,                     NULL, NULL },
     };
 
-    table[i++].data = &c->daemonize;
-    table[i++].data = &c->fail;
-    table[i++].data = &c->high_priority;
-    table[i++].data = &c->realtime_scheduling;
-    table[i++].data = &c->disallow_module_loading;
-    table[i++].data = &c->disallow_exit;
-    table[i++].data = &c->use_pid_file;
-    table[i++].data = &c->system_instance;
-    table[i++].data = &c->no_cpu_limit;
-    table[i++].data = &c->disable_shm;
-    table[i++].data = &c->flat_volumes;
-    table[i++].data = &c->exit_idle_time;
-    table[i++].data = &c->scache_idle_time;
-    table[i++].data = c;
-    table[i++].data = &c->dl_search_path;
-    table[i++].data = &c->default_script_file;
-    table[i++].data = c;
-    table[i++].data = c;
-    table[i++].data = c;
-    table[i++].data = c;
-    table[i++].data = c;
-    table[i++].data = c;
-    table[i++].data = c;
-    table[i++].data = c;
-    table[i++].data = c;
-    table[i++].data = c;
-    table[i++].data = &c->disable_remixing;
-    table[i++].data = &c->disable_lfe_remixing;
-    table[i++].data = &c->load_default_script_file;
-    table[i++].data = &c->shm_size;
-    table[i++].data = &c->log_meta;
-    table[i++].data = &c->log_time;
-    table[i++].data = &c->log_backtrace;
-#ifdef HAVE_SYS_RESOURCE_H
-    table[i++].data = &c->rlimit_fsize;
-    table[i++].data = &c->rlimit_data;
-    table[i++].data = &c->rlimit_stack;
-    table[i++].data = &c->rlimit_core;
-    table[i++].data = &c->rlimit_rss;
-#ifdef RLIMIT_NOFILE
-    table[i++].data = &c->rlimit_nofile;
-#endif
-#ifdef RLIMIT_AS
-    table[i++].data = &c->rlimit_as;
-#endif
-#ifdef RLIMIT_NPROC
-    table[i++].data = &c->rlimit_nproc;
-#endif
-#ifdef RLIMIT_MEMLOCK
-    table[i++].data = &c->rlimit_memlock;
-#endif
-#ifdef RLIMIT_LOCKS
-    table[i++].data = &c->rlimit_locks;
-#endif
-#ifdef RLIMIT_SIGPENDING
-    table[i++].data = &c->rlimit_sigpending;
-#endif
-#ifdef RLIMIT_MSGQUEUE
-    table[i++].data = &c->rlimit_msgqueue;
-#endif
-#ifdef RLIMIT_NICE
-    table[i++].data = &c->rlimit_nice;
-#endif
-#ifdef RLIMIT_RTPRIO
-    table[i++].data = &c->rlimit_rtprio;
-#endif
-#ifdef RLIMIT_RTTIME
-    table[i++].data = &c->rlimit_rttime;
-#endif
-#endif
-
-    pa_assert(i == PA_ELEMENTSOF(table)-1);
-
     pa_xfree(c->config_file);
     c->config_file = NULL;
 
@@ -567,8 +519,27 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
         goto finish;
     }
 
+    ci.default_channel_map_set = ci.default_sample_spec_set = FALSE;
+    ci.conf = c;
+
     r = f ? pa_config_parse(c->config_file, f, table, NULL) : 0;
 
+    if (r >= 0) {
+
+        /* Make sure that channel map and sample spec fit together */
+
+        if (ci.default_sample_spec_set &&
+            ci.default_channel_map_set &&
+            c->default_channel_map.channels != c->default_sample_spec.channels) {
+            pa_log_error(_("The specified default channel map has a different number of channels than the specified default number of channels."));
+            r = -1;
+            goto finish;
+        } else if (ci.default_sample_spec_set)
+            pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
+        else if (ci.default_channel_map_set)
+            c->default_sample_spec.channels = c->default_channel_map.channels;
+    }
+
 finish:
     if (f)
         fclose(f);
@@ -631,6 +602,7 @@ static const char* const log_level_to_string[] = {
 
 char *pa_daemon_conf_dump(pa_daemon_conf *c) {
     pa_strbuf *s;
+    char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
 
     pa_assert(c);
 
@@ -667,6 +639,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
     pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
     pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate);
     pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels);
+    pa_strbuf_printf(s, "default-channel-map = %s\n", pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
     pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments);
     pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec);
     pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size);
index aa9d2981d9a9d78742a19634009b1190445d0583..9331280b5121461b4de3c48f11be803234282db6 100644 (file)
   USA.
 ***/
 
+#include <pulse/sample.h>
+#include <pulse/channelmap.h>
+
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/core-util.h>
-#include <pulse/sample.h>
 
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
@@ -121,6 +123,7 @@ typedef struct pa_daemon_conf {
 
     unsigned default_n_fragments, default_fragment_size_msec;
     pa_sample_spec default_sample_spec;
+    pa_channel_map default_channel_map;
     size_t shm_size;
 } pa_daemon_conf;
 
index 69d17f26141de44848bcffe4804b4a4587689efc..fcd2513a6c8bfb96df1cf6d8ffc73279a2ad5885 100644 (file)
@@ -76,6 +76,7 @@
 ; default-sample-format = s16le
 ; default-sample-rate = 44100
 ; default-sample-channels = 2
+; default-channel-map = front-left,front-right
 
 ; default-fragments = 4
 ; default-fragment-size-msec = 25
index 5f94ec66501b3e80ace50e9f9eca000b718ab6b9..d176f458af6917c2a2ec17a1e02ab65dd99035b9 100644 (file)
@@ -908,6 +908,7 @@ int main(int argc, char *argv[]) {
     }
 
     c->default_sample_spec = conf->default_sample_spec;
+    c->default_channel_map = conf->default_channel_map;
     c->default_n_fragments = conf->default_n_fragments;
     c->default_fragment_size_msec = conf->default_fragment_size_msec;
     c->exit_idle_time = conf->exit_idle_time;
index 239a9d786422469e21e3237c44836dabd73e8508..ed25a6f3139c345f76abfa455640b74446de52a2 100644 (file)
@@ -1378,6 +1378,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     pa_assert(ma);
 
     ss = m->core->default_sample_spec;
+    map = m->core->default_channel_map;
     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) {
         pa_log("Failed to parse sample specification and channel map");
         goto fail;
index 50cdb31092140eb4213cc154f04208f6b8de3424..4562689637d92078f83f7260eb23331aeb534ffc 100644 (file)
@@ -1229,6 +1229,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     pa_assert(ma);
 
     ss = m->core->default_sample_spec;
+    map = m->core->default_channel_map;
     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) {
         pa_log("Failed to parse sample specification");
         goto fail;
index 7f1ef24c04f8ac23605141bb4de5d812a92407fb..6ed4f1413e2412efe05a0db7477afb8d4343f001 100644 (file)
@@ -1052,8 +1052,9 @@ int pa__init(pa_module*m) {
 
     slaves = pa_modargs_get_value(ma, "slaves", NULL);
     u->automatic = !slaves;
-    ss = m->core->default_sample_spec;
 
+    ss = m->core->default_sample_spec;
+    map = m->core->default_channel_map;
     if ((pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0)) {
         pa_log("Invalid sample specification.");
         goto fail;
index b448e84e238d0f848982f7ff3ad22f0230b3a5f8..1739f46a815906b1fb7f78a71336704721f771e3 100644 (file)
@@ -329,12 +329,18 @@ int pa__init(pa_module*m) {
     if (!channels)
         channels = m->core->default_sample_spec.channels;
 
-    if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) {
+    if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 ||
+        channels <= 0 ||
+        channels > PA_CHANNELS_MAX) {
         pa_log("Failed to parse channels= argument.");
         goto fail;
     }
 
-    pa_channel_map_init_extend(&map, channels, PA_CHANNEL_MAP_ALSA);
+    if (channels == m->core->default_channel_map.channels)
+        map = m->core->default_channel_map;
+    else
+        pa_channel_map_init_extend(&map, channels, PA_CHANNEL_MAP_ALSA);
+
     if (pa_modargs_get_channel_map(ma, NULL, &map) < 0 || map.channels != channels) {
         pa_log("Failed to parse channel_map= argument.");
         goto fail;
index 0c7ee535143209da60c5a52a589f9da411834220..38b63751a6e84c67d12c1e4c71829228eed56f38 100644 (file)
@@ -296,12 +296,18 @@ int pa__init(pa_module*m) {
     if (!channels)
         channels = m->core->default_sample_spec.channels;
 
-    if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) {
+    if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 ||
+        channels <= 0 ||
+        channels >= PA_CHANNELS_MAX) {
         pa_log("failed to parse channels= argument.");
         goto fail;
     }
 
-    pa_channel_map_init_extend(&map, channels, PA_CHANNEL_MAP_ALSA);
+    if (channels == m->core->default_channel_map.channels)
+        map = m->core->default_channel_map;
+    else
+        pa_channel_map_init_extend(&map, channels, PA_CHANNEL_MAP_ALSA);
+
     if (pa_modargs_get_channel_map(ma, NULL, &map) < 0 || map.channels != channels) {
         pa_log("failed to parse channel_map= argument.");
         goto fail;
index 570f8be44ad7dc9dc3a2558164e860979b6a8843..e18da5fd180022d3f9c34accf85395c0ee26bf46 100644 (file)
@@ -262,6 +262,7 @@ int pa__init(pa_module*m) {
     }
 
     ss = m->core->default_sample_spec;
+    map = m->core->default_channel_map;
     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
         pa_log("Invalid sample format specification or channel map");
         goto fail;
index 7dd4409892514ef0f451e1b37f8d6d10a47d2049..f3b0e8b0e6297d819c737e60414931f7fd741015 100644 (file)
@@ -234,6 +234,7 @@ int pa__init(pa_module*m) {
     }
 
     ss = m->core->default_sample_spec;
+    map = m->core->default_channel_map;
     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
         pa_log("Invalid sample format specification or channel map");
         goto fail;
index 975090c2da5308fb242ddf5ec769e4e104dc1453..a42c53c365f555da12b3376d90c71730a965a51c 100644 (file)
@@ -221,6 +221,7 @@ int pa__init(pa_module*m) {
     }
 
     ss = m->core->default_sample_spec;
+    map = m->core->default_channel_map;
     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
         pa_log("invalid sample format specification or channel map");
         goto fail;
index 26da2575a80bd07a72e6f1ce6c4c928be01b44db..63ae740aba6ebb92c83c0488a95dd72a030ee1b3 100644 (file)
@@ -1717,6 +1717,7 @@ int pa__init(pa_module*m) {
     }
 
     ss = m->core->default_sample_spec;
+    map = m->core->default_channel_map;
     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
         pa_log("Invalid sample format specification");
         goto fail;
index 9a867cb51b7ca61cedac018321afeccb8f355791..5123ead897185ae1b6f0ccb42e13ec27945f51c5 100644 (file)
@@ -162,7 +162,7 @@ static void resolver_cb(
         pa_module *m;
 
         ss = u->core->default_sample_spec;
-        pa_channel_map_init_extend(&cm, ss.channels, PA_CHANNEL_MAP_DEFAULT);
+        cm = u->core->default_channel_map;
 
         for (l = txt; l; l = l->next) {
             char *key, *value;
index eac0c8e635a27a676ba4b2cd2dac7427113610b9..54d1679f74f9e90f767a988ecfc8478cac658b9a 100644 (file)
@@ -1185,6 +1185,7 @@ int pa__init(pa_module*m) {
     mode = (playback && record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
 
     ss = m->core->default_sample_spec;
+    map = m->core->default_channel_map;
     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_OSS) < 0) {
         pa_log("Failed to parse sample specification or channel map");
         goto fail;
index 04bcd4f5c4409f505753727dffc4a243b3451dcb..befeb242fe201f79e33715337c8156f6324975be 100644 (file)
@@ -110,12 +110,17 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command,
                pa_tagstruct_gets(t, &i.default_sink_name) < 0 ||
                pa_tagstruct_gets(t, &i.default_source_name) < 0 ||
                pa_tagstruct_getu32(t, &i.cookie) < 0 ||
+               (o->context->version >= 15 &&
+                pa_tagstruct_get_channel_map(t, &i.channel_map) < 0) ||
                !pa_tagstruct_eof(t)) {
 
         pa_context_fail(o->context, PA_ERR_PROTOCOL);
         goto finish;
     }
 
+    if (p && o->context->version < 15)
+        pa_channel_map_init_extend(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
+
     if (o->callback) {
         pa_server_info_cb_t cb = (pa_server_info_cb_t) o->callback;
         cb(o->context, p, o->userdata);
index b873a84a1272b0d4dfe311d37b91b6ecbfc21f0e..aa67e43d5b92db5ec917b4528e0a09464e956049 100644 (file)
@@ -317,6 +317,7 @@ typedef struct pa_server_info {
     const char *default_sink_name;      /**< Name of default sink. */
     const char *default_source_name;    /**< Name of default sink. */
     uint32_t cookie;                    /**< A random cookie for identifying this instance of PulseAudio. */
+    pa_channel_map channel_map;         /**< Default channel map. \since 0.9.15 */
 } pa_server_info;
 
 /** Callback prototype for pa_context_get_server_info() */
index 5e45c1aa041fce3afc5a3bbc5a748e1defdcef07..7066e7e713c19a971f4641c4ffdabc44a8e35f57 100644 (file)
@@ -321,6 +321,8 @@ static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf
 }
 
 static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
+    char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
+    char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
     char s[256];
     const pa_mempool_stat *stat;
     unsigned k;
@@ -363,7 +365,10 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
                      pa_bytes_snprint(s, sizeof(s), (unsigned) pa_scache_total_size(c)));
 
     pa_strbuf_printf(buf, "Default sample spec: %s\n",
-                     pa_sample_spec_snprint(s, sizeof(s), &c->default_sample_spec));
+                     pa_sample_spec_snprint(ss, sizeof(ss), &c->default_sample_spec));
+
+    pa_strbuf_printf(buf, "Default channel map: %s\n",
+                     pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
 
     def_sink = pa_namereg_get_default_sink(c);
     def_source = pa_namereg_get_default_source(c);
index 5fd2bdfb4359cc90056f819efb2d9154ef9dc211..eef967a660973c5997c73f949e035237dbcf5a40 100644 (file)
@@ -111,6 +111,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) {
     c->default_sample_spec.format = PA_SAMPLE_S16NE;
     c->default_sample_spec.rate = 44100;
     c->default_sample_spec.channels = 2;
+    pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
     c->default_n_fragments = 4;
     c->default_fragment_size_msec = 25;
 
index 53e2d2c3c4ca158cd5551a790a6e8d7564cca808..7660bd3b92876667ca952ef9958a112b4b1213b7 100644 (file)
@@ -122,6 +122,7 @@ struct pa_core {
     pa_source *default_source;
     pa_sink *default_sink;
 
+    pa_channel_map default_channel_map;
     pa_sample_spec default_sample_spec;
     unsigned default_n_fragments, default_fragment_size_msec;
 
index 866e6e0ce8df9de63b272a4cc8af5e964b8d4730..4a30f52a0ca880b05414155ac8cc590891e7fe95 100644 (file)
@@ -274,11 +274,15 @@ int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) {
     pa_assert(rss);
 
     ss = *rss;
-    if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0)
+    if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0 ||
+        ss.rate <= 0 ||
+        ss.rate > PA_RATE_MAX)
         return -1;
 
     channels = ss.channels;
-    if ((pa_modargs_get_value_u32(ma, "channels", &channels)) < 0)
+    if ((pa_modargs_get_value_u32(ma, "channels", &channels)) < 0 ||
+        channels <= 0 ||
+        channels >= PA_CHANNELS_MAX)
         return -1;
     ss.channels = (uint8_t) channels;
 
@@ -314,7 +318,12 @@ int pa_modargs_get_channel_map(pa_modargs *ma, const char *name, pa_channel_map
     return 0;
 }
 
-int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *rss, pa_channel_map *rmap, pa_channel_map_def_t def) {
+int pa_modargs_get_sample_spec_and_channel_map(
+        pa_modargs *ma,
+        pa_sample_spec *rss,
+        pa_channel_map *rmap,
+        pa_channel_map_def_t def) {
+
     pa_sample_spec ss;
     pa_channel_map map;
 
@@ -327,7 +336,10 @@ int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *r
     if (pa_modargs_get_sample_spec(ma, &ss) < 0)
         return -1;
 
-    pa_channel_map_init_extend(&map, ss.channels, def);
+    map = *rmap;
+
+    if (ss.channels != map.channels)
+        pa_channel_map_init_extend(&map, ss.channels, def);
 
     if (pa_modargs_get_channel_map(ma, NULL, &map) < 0)
         return -1;
index a963f78ad0e944e462dfc9d9842c6afc15347a98..10b9e7da330909ef5ad6ed9506ebba0a9862c21d 100644 (file)
@@ -3125,6 +3125,9 @@ static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t
 
     pa_tagstruct_putu32(reply, c->protocol->core->cookie);
 
+    if (c->version >= 15)
+        pa_tagstruct_put_channel_map(reply, &c->protocol->core->default_channel_map);
+
     pa_pstream_send_tagstruct(c->pstream, reply);
 }
 
index d3da90e636467a2e919ae780ed928195aa1bfaab..6524bf9007d9f3a57f561436b3f2ad109af5c458 100644 (file)
@@ -123,7 +123,7 @@ static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata)
 }
 
 static void get_server_info_callback(pa_context *c, const pa_server_info *i, void *useerdata) {
-    char s[PA_SAMPLE_SPEC_SNPRINT_MAX];
+    char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
 
     if (!i) {
         fprintf(stderr, _("Failed to get server information: %s\n"), pa_strerror(pa_context_errno(c)));
@@ -131,21 +131,24 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
         return;
     }
 
-    pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
+    pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec);
+    pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map);
 
     printf(_("User name: %s\n"
-           "Host Name: %s\n"
-           "Server Name: %s\n"
-           "Server Version: %s\n"
-           "Default Sample Specification: %s\n"
-           "Default Sink: %s\n"
-           "Default Source: %s\n"
-           "Cookie: %08x\n"),
+             "Host Name: %s\n"
+             "Server Name: %s\n"
+             "Server Version: %s\n"
+             "Default Sample Specification: %s\n"
+             "Default Channel Map: %s\n"
+             "Default Sink: %s\n"
+             "Default Source: %s\n"
+             "Cookie: %08x\n"),
            i->user_name,
            i->host_name,
            i->server_name,
            i->server_version,
-           s,
+           ss,
+           cm,
            i->default_sink_name,
            i->default_source_name,
            i->cookie);