summaryrefslogtreecommitdiffstats
path: root/src/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon')
-rw-r--r--src/daemon/.gitignore2
-rw-r--r--src/daemon/cmdline.c6
-rw-r--r--src/daemon/daemon-conf.c223
-rw-r--r--src/daemon/daemon-conf.h5
-rw-r--r--src/daemon/daemon.conf.in1
-rw-r--r--src/daemon/main.c21
-rw-r--r--src/daemon/org.pulseaudio.policy.in (renamed from src/daemon/org.pulseaudio.policy)8
-rw-r--r--src/daemon/pulseaudio.desktop.in (renamed from src/daemon/pulseaudio.desktop)4
8 files changed, 127 insertions, 143 deletions
diff --git a/src/daemon/.gitignore b/src/daemon/.gitignore
new file mode 100644
index 00000000..0efa55ba
--- /dev/null
+++ b/src/daemon/.gitignore
@@ -0,0 +1,2 @@
+org.pulseaudio.policy
+pulseaudio.desktop
diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c
index 43a4a326..f4224ea8 100644
--- a/src/daemon/cmdline.c
+++ b/src/daemon/cmdline.c
@@ -299,7 +299,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
case ARG_DISALLOW_EXIT:
if ((conf->disallow_exit = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
- pa_log(_("--disallow-exit boolean argument"));
+ pa_log(_("--disallow-exit expects boolean argument"));
goto fail;
}
break;
@@ -330,14 +330,14 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
case ARG_LOG_TIME:
if ((conf->log_time = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
- pa_log(_("--log-time boolean argument"));
+ pa_log(_("--log-time expects boolean argument"));
goto fail;
}
break;
case ARG_LOG_META:
if ((conf->log_meta = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) {
- pa_log(_("--log-meta boolean argument"));
+ pa_log(_("--log-meta expects boolean argument"));
goto fail;
}
break;
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index 7dfef27f..10144ea4 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -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);
diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h
index aa9d2981..9331280b 100644
--- a/src/daemon/daemon-conf.h
+++ b/src/daemon/daemon-conf.h
@@ -23,10 +23,12 @@
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;
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index 69d17f26..fcd2513a 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -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
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 5f94ec66..b630bd17 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -351,8 +351,9 @@ int main(int argc, char *argv[]) {
int autospawn_fd = -1;
pa_bool_t autospawn_locked = FALSE;
- pa_log_set_maximal_level(PA_LOG_INFO);
pa_log_set_ident("pulseaudio");
+ pa_log_set_level(PA_LOG_INFO);
+ pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET);
#if defined(__linux__) && defined(__OPTIMIZE__)
/*
@@ -432,11 +433,13 @@ int main(int argc, char *argv[]) {
goto finish;
}
- pa_log_set_maximal_level(conf->log_level);
- pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL);
- pa_log_set_show_meta(conf->log_meta);
+ pa_log_set_level(conf->log_level);
+ pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target);
+ if (conf->log_meta)
+ pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET);
+ if (conf->log_time)
+ pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);
pa_log_set_show_backtrace(conf->log_backtrace);
- pa_log_set_show_time(conf->log_time);
pa_log_debug("Started as real root: %s, suid root: %s", pa_yes_no(real_root), pa_yes_no(suid_root));
@@ -506,8 +509,9 @@ int main(int argc, char *argv[]) {
if ((conf->high_priority && !allow_high_priority) ||
(conf->realtime_scheduling && !allow_realtime))
pa_log_notice(_("Called SUID root and real-time and/or high-priority scheduling was requested in the configuration. However, we lack the necessary privileges:\n"
- "We are not in group '"PA_REALTIME_GROUP"', PolicyKit refuse to grant us the requested privileges and we have no increase RLIMIT_NICE/RLIMIT_RTPRIO resource limits.\n"
- "For enabling real-time/high-priority scheduling please acquire the appropriate PolicyKit privileges, or become a member of '"PA_REALTIME_GROUP"', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."));
+ "We are not in group '%s', PolicyKit refuse to grant us the requested privileges and we have no increase RLIMIT_NICE/RLIMIT_RTPRIO resource limits.\n"
+ "For enabling real-time/high-priority scheduling please acquire the appropriate PolicyKit privileges, or become a member of '%s', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."),
+ PA_REALTIME_GROUP, PA_REALTIME_GROUP);
if (!allow_realtime)
@@ -770,7 +774,7 @@ int main(int argc, char *argv[]) {
#endif
if (conf->auto_log_target)
- pa_log_set_target(PA_LOG_SYSLOG, NULL);
+ pa_log_set_target(PA_LOG_SYSLOG);
#ifdef HAVE_SETSID
setsid();
@@ -908,6 +912,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;
diff --git a/src/daemon/org.pulseaudio.policy b/src/daemon/org.pulseaudio.policy.in
index 6cdeec68..1d0b6a7d 100644
--- a/src/daemon/org.pulseaudio.policy
+++ b/src/daemon/org.pulseaudio.policy.in
@@ -28,8 +28,8 @@ USA.
<icon_name>audio-card</icon_name>
<action id="org.pulseaudio.acquire-real-time">
- <description>Real-time scheduling for the PulseAudio daemon</description>
- <message>System policy prevents PulseAudio from acquiring real-time scheduling.</message>
+ <_description>Real-time scheduling for the PulseAudio daemon</_description>
+ <_message>System policy prevents PulseAudio from acquiring real-time scheduling.</_message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>no</allow_inactive>
@@ -38,8 +38,8 @@ USA.
</action>
<action id="org.pulseaudio.acquire-high-priority">
- <description>High-priority scheduling (negative Unix nice level) for the PulseAudio daemon</description>
- <message>System policy prevents PulseAudio from acquiring high-priority scheduling.</message>
+ <_description>High-priority scheduling (negative Unix nice level) for the PulseAudio daemon</_description>
+ <_message>System policy prevents PulseAudio from acquiring high-priority scheduling.</_message>
<defaults>
<allow_any>no</allow_any>
<allow_inactive>no</allow_inactive>
diff --git a/src/daemon/pulseaudio.desktop b/src/daemon/pulseaudio.desktop.in
index 57a7a6e4..99bdbd00 100644
--- a/src/daemon/pulseaudio.desktop
+++ b/src/daemon/pulseaudio.desktop.in
@@ -1,8 +1,8 @@
[Desktop Entry]
Version=1.0
Encoding=UTF-8
-Name=PulseAudio Sound System
-Comment=Start the PulseAudio Sound System
+_Name=PulseAudio Sound System
+_Comment=Start the PulseAudio Sound System
Exec=start-pulseaudio-x11
Terminal=false
Type=Application