summaryrefslogtreecommitdiffstats
path: root/src/modules
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2008-05-01 19:51:05 +0000
committerLennart Poettering <lennart@poettering.net>2008-05-01 19:51:05 +0000
commit52e3628c3edd98ae3402605e7f44a0fc4545dd0a (patch)
tree843a7bb1a077141baea5ac29e62d163c90b4acc6 /src/modules
parentf94fae3da3e3201afc060d3ae24c96fd9bba56ab (diff)
Yes, yet another evil all-in-one commit of intervowen changes. I suck.
* Drop "state" directory, fold that into "runtime directory" * No longer automatically rewind when a new stream connects * Rework sound file stream, to cause a rewind on initialisation, shorten _pop() code a bit * Fix reference counting of pa_socket_server in the protocol implementations * Rework daemon initialization code to be compatible with non-SUID-root setups where RLIMIT_RTPRIO is non-zero * Print warning if RT/HP is enabled in the config, but due to missing caps, rlimits, policy we cannot enable it. * Fix potential memory leak in pa_open_config_file() * Add pa_find_config_file() which works much like pa_open_config_file() but doesn't actually open the config file in question. Just searches for it. * Add portable pa_is_path_absolute() * Add pa_close_all() and use it on daemon startup to close leaking file descriptors (inspired from what I did for libdaemon) * Add pa_unblock_sigs() and use it on daemon startup to unblock all signals (inspired from libdaemon, too) * Add pa_reset_sigs() and use it on daemon startup to reset all signal handlers (inspired from libdaemon as well) * Implement pa_set_env() * Define RLIMIT_RTTIME and friends if not defined by glibc * Add pa_strempty() * rename state testing macros to include _IS_, to make clearer that they are no states, but testing macros * Implement pa_source_output_set_requested_latency_within_thread() to be able to forward latency info to sources from within the IO thread * Similar for sink inputs * generelize since_underrun counter in sink inputs to "playing_for" and "underrun_for". Use only this for ignore potential rewind requests over underruns * Add new native protocol message PLAYBACK_STREAM_MESSAGE_STARTED for notification about the end of an underrun * Port native protocol to use underrun_for/playing_for which is maintained by the sink input anyway * Pass underrun_for/playing_for in timing info to client * Drop pa_sink_skip() since it breaks underrun detection code * Move PID file and unix sockets to the runtime dir (i.e. ~/.pulse). This fixes a potention DoS attack from other users stealing dirs in /tmp from us so that we cannot take them anymore) * Allow setting of more resource limits from the config file. Set RTTIME by default * Streamline daemon startup code * Rework algorithm to find default configuration files * If run in system mode use "system.pa" instead of "default.pa" as default script file * Change ladspa sink to use pa_clamp_samples() for clamping samples * Teach module-null-sink how to deal with rewinding * Try to support ALSA devices with no implicit channel map. Synthesize one by padding with PA_CHANNEL_POSITION_AUX channels. This is not tested since I lack hardware with these problems. * Make use of time smoother in the client libraries. * Add new pa_stream_is_corked() and pa_stream_set_started_callback() functions to public API * Since our native socket moved, add some code for finding sockets created by old versions of PA. This should ease upgrades git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2329 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/alsa-util.c20
-rw-r--r--src/modules/module-alsa-sink.c18
-rw-r--r--src/modules/module-alsa-source.c6
-rw-r--r--src/modules/module-combine.c31
-rw-r--r--src/modules/module-default-device-restore.c154
-rw-r--r--src/modules/module-device-restore.c9
-rw-r--r--src/modules/module-esound-sink.c6
-rw-r--r--src/modules/module-ladspa-sink.c53
-rw-r--r--src/modules/module-match.c10
-rw-r--r--src/modules/module-null-sink.c120
-rw-r--r--src/modules/module-oss.c22
-rw-r--r--src/modules/module-protocol-stub.c70
-rw-r--r--src/modules/module-remap-sink.c39
-rw-r--r--src/modules/module-suspend-on-idle.c4
-rw-r--r--src/modules/module-tunnel.c14
-rw-r--r--src/modules/module-volume-restore.c18
16 files changed, 380 insertions, 214 deletions
diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 0c4c020b..47ed9ace 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -671,8 +671,24 @@ snd_pcm_t *pa_alsa_open_by_device_string(
*dev = d;
if (ss->channels != map->channels) {
- pa_assert_se(pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_AUX));
- pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_ALSA);
+ if (!pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_ALSA)) {
+ unsigned c;
+ pa_channel_position_t pos;
+
+ pa_log_warn("Device has an unknown channel mapping. This is a limitation of ALSA. Synthesizing channel map.");
+
+ for (c = ss->channels; c > 0; c--)
+ if (pa_channel_map_init_auto(map, c, PA_CHANNEL_MAP_ALSA))
+ break;
+
+ pa_assert(c > 0);
+
+ pos = PA_CHANNEL_POSITION_AUX0;
+ for (; c < map->channels; c ++)
+ map->map[c] = pos++;
+
+ map->channels = ss->channels;
+ }
}
return pcm_handle;
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 5cc27f11..efb0fd8a 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -665,7 +665,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
case PA_SINK_SUSPENDED:
- pa_assert(PA_SINK_OPENED(u->sink->thread_info.state));
+ pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
if (suspend(u) < 0)
return -1;
@@ -836,9 +836,20 @@ static int sink_set_mute_cb(pa_sink *s) {
static void sink_update_requested_latency_cb(pa_sink *s) {
struct userdata *u = s->userdata;
+ snd_pcm_sframes_t before;
pa_assert(u);
+ before = u->hwbuf_unused_frames;
update_sw_params(u);
+
+ /* Let's check whether we now use only a smaller part of the
+ buffer then before. If so, we need to make sure that subsequent
+ rewinds are relative to the new maxium fill level and not to the
+ current fill level. Thus, let's do a full rewind once, to clear
+ things up. */
+
+ if (u->hwbuf_unused_frames > before)
+ pa_sink_request_rewind(s, 0);
}
static int process_rewind(struct userdata *u) {
@@ -846,6 +857,7 @@ static int process_rewind(struct userdata *u) {
size_t rewind_nbytes, unused_nbytes, limit_nbytes;
pa_assert(u);
+ /* Figure out how much we shall rewind and reset the counter */
rewind_nbytes = u->sink->thread_info.rewind_nbytes;
u->sink->thread_info.rewind_nbytes = 0;
@@ -917,7 +929,7 @@ static void thread_func(void *userdata) {
/* pa_log_debug("loop"); */
/* Render some data and write it to the dsp */
- if (PA_SINK_OPENED(u->sink->thread_info.state)) {
+ if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
int work_done = 0;
if (u->sink->thread_info.rewind_nbytes > 0)
@@ -982,7 +994,7 @@ static void thread_func(void *userdata) {
goto finish;
/* Tell ALSA about this and process its response */
- if (PA_SINK_OPENED(u->sink->thread_info.state)) {
+ if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
struct pollfd *pollfd;
unsigned short revents = 0;
int err;
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 3c6b8dba..9eb6f06b 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -621,7 +621,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
case PA_SOURCE_SUSPENDED:
- pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state));
+ pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
if (suspend(u) < 0)
return -1;
@@ -819,7 +819,7 @@ static void thread_func(void *userdata) {
pa_log_debug("loop");
/* Read some data and pass it to the sources */
- if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
+ if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
int work_done = 0;
if (u->use_mmap)
@@ -867,7 +867,7 @@ static void thread_func(void *userdata) {
goto finish;
/* Tell ALSA about this and process its response */
- if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
+ if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
struct pollfd *pollfd;
unsigned short revents = 0;
int err;
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index e15654fa..2409ef8f 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -162,13 +162,13 @@ static void adjust_rates(struct userdata *u) {
if (!u->master)
return;
- if (!PA_SINK_OPENED(pa_sink_get_state(u->sink)))
+ if (!PA_SINK_IS_OPENED(pa_sink_get_state(u->sink)))
return;
for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
pa_usec_t sink_latency;
- if (!o->sink_input || !PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+ if (!o->sink_input || !PA_SINK_IS_OPENED(pa_sink_get_state(o->sink)))
continue;
sink_latency = pa_sink_get_latency(o->sink);
@@ -194,7 +194,7 @@ static void adjust_rates(struct userdata *u) {
for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
uint32_t r = base_rate;
- if (!o->sink_input || !PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+ if (!o->sink_input || !PA_SINK_IS_OPENED(pa_sink_get_state(o->sink)))
continue;
if (o->total_latency < target_latency)
@@ -258,7 +258,10 @@ static void thread_func(void *userdata) {
pa_rtclock_get(&now);
if (!u->thread_info.in_null_mode || pa_timeval_cmp(&u->thread_info.timestamp, &now) <= 0) {
- pa_sink_skip(u->sink, u->block_size);
+ pa_memchunk chunk;
+
+ pa_sink_render_full(u->sink, u->block_size, &chunk);
+ pa_memblock_unref(chunk.memblock);
if (!u->thread_info.in_null_mode)
u->thread_info.timestamp = now;
@@ -432,7 +435,7 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
case SINK_INPUT_MESSAGE_POST:
- if (PA_SINK_OPENED(o->sink_input->sink->thread_info.state))
+ if (PA_SINK_IS_OPENED(o->sink_input->sink->thread_info.state))
pa_memblockq_push_align(o->memblockq, chunk);
else
pa_memblockq_flush(o->memblockq);
@@ -471,7 +474,7 @@ static void enable_output(struct output *o) {
pa_sink_input_put(o->sink_input);
- if (o->userdata->sink && PA_SINK_LINKED(pa_sink_get_state(o->userdata->sink)))
+ if (o->userdata->sink && PA_SINK_IS_LINKED(pa_sink_get_state(o->userdata->sink)))
pa_asyncmsgq_send(o->userdata->sink->asyncmsgq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_ADD_OUTPUT, o, 0, NULL);
}
}
@@ -504,7 +507,7 @@ static void unsuspend(struct userdata *u) {
pa_sink_suspend(o->sink, FALSE);
- if (PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+ if (PA_SINK_IS_OPENED(pa_sink_get_state(o->sink)))
enable_output(o);
}
@@ -525,7 +528,7 @@ static int sink_set_state(pa_sink *sink, pa_sink_state_t state) {
switch (state) {
case PA_SINK_SUSPENDED:
- pa_assert(PA_SINK_OPENED(pa_sink_get_state(u->sink)));
+ pa_assert(PA_SINK_IS_OPENED(pa_sink_get_state(u->sink)));
suspend(u);
break;
@@ -697,7 +700,7 @@ static void pick_master(struct userdata *u, struct output *except) {
if (u->master &&
u->master != except &&
u->master->sink_input &&
- PA_SINK_OPENED(pa_sink_get_state(u->master->sink))) {
+ PA_SINK_IS_OPENED(pa_sink_get_state(u->master->sink))) {
update_master(u, u->master);
return;
}
@@ -705,7 +708,7 @@ static void pick_master(struct userdata *u, struct output *except) {
for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx))
if (o != except &&
o->sink_input &&
- PA_SINK_OPENED(pa_sink_get_state(o->sink))) {
+ PA_SINK_IS_OPENED(pa_sink_get_state(o->sink))) {
update_master(u, o);
return;
}
@@ -780,7 +783,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
pa_assert_se(pa_idxset_put(u->outputs, o, NULL) == 0);
- if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink)))
+ if (u->sink && PA_SINK_IS_LINKED(pa_sink_get_state(u->sink)))
pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_ADD_OUTPUT, o, 0, NULL);
else {
/* If the sink is not yet started, we need to do the activation ourselves */
@@ -792,10 +795,10 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
o->outq);
}
- if (PA_SINK_OPENED(pa_sink_get_state(u->sink)) || pa_sink_get_state(u->sink) == PA_SINK_INIT) {
+ if (PA_SINK_IS_OPENED(pa_sink_get_state(u->sink)) || pa_sink_get_state(u->sink) == PA_SINK_INIT) {
pa_sink_suspend(sink, FALSE);
- if (PA_SINK_OPENED(pa_sink_get_state(sink)))
+ if (PA_SINK_IS_OPENED(pa_sink_get_state(sink)))
if (output_create_sink_input(o) < 0)
goto fail;
}
@@ -898,7 +901,7 @@ static pa_hook_result_t sink_state_changed_hook_cb(pa_core *c, pa_sink *s, struc
state = pa_sink_get_state(s);
- if (PA_SINK_OPENED(state) && PA_SINK_OPENED(pa_sink_get_state(u->sink)) && !o->sink_input) {
+ if (PA_SINK_IS_OPENED(state) && PA_SINK_IS_OPENED(pa_sink_get_state(u->sink)) && !o->sink_input) {
enable_output(o);
pick_master(u, NULL);
}
diff --git a/src/modules/module-default-device-restore.c b/src/modules/module-default-device-restore.c
index b550ae78..a7fc3a3f 100644
--- a/src/modules/module-default-device-restore.c
+++ b/src/modules/module-default-device-restore.c
@@ -3,7 +3,7 @@
/***
This file is part of PulseAudio.
- Copyright 2006 Lennart Poettering
+ Copyright 2006-2008 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
@@ -25,10 +25,16 @@
#include <config.h>
#endif
+#include <errno.h>
+#include <stdio.h>
+
+#include <pulse/timeval.h>
+
#include <pulsecore/core-util.h>
#include <pulsecore/module.h>
#include <pulsecore/log.h>
#include <pulsecore/namereg.h>
+#include <pulsecore/core-error.h>
#include "module-default-device-restore-symdef.h"
@@ -39,15 +45,24 @@ PA_MODULE_LOAD_ONCE(TRUE);
#define DEFAULT_SINK_FILE "default-sink"
#define DEFAULT_SOURCE_FILE "default-source"
+#define DEFAULT_SAVE_INTERVAL 5
-int pa__init(pa_module *m) {
+struct userdata {
+ pa_core *core;
+ pa_subscription *subscription;
+ pa_time_event *time_event;
+ char *sink_filename, *source_filename;
+ pa_bool_t modified;
+};
+
+static void load(struct userdata *u) {
FILE *f;
/* We never overwrite manually configured settings */
- if (m->core->default_sink_name)
+ if (u->core->default_sink_name)
pa_log_info("Manually configured default sink, not overwriting.");
- else if ((f = pa_open_config_file(NULL, DEFAULT_SINK_FILE, NULL, NULL, "r"))) {
+ else if ((f = fopen(u->sink_filename, "r"))) {
char ln[256] = "";
fgets(ln, sizeof(ln)-1, f);
@@ -55,17 +70,19 @@ int pa__init(pa_module *m) {
fclose(f);
if (!ln[0])
- pa_log_debug("No previous default sink setting, ignoring.");
- else if (pa_namereg_get(m->core, ln, PA_NAMEREG_SINK, 1)) {
- pa_namereg_set_default(m->core, ln, PA_NAMEREG_SINK);
- pa_log_debug("Restored default sink '%s'.", ln);
+ pa_log_info("No previous default sink setting, ignoring.");
+ else if (pa_namereg_get(u->core, ln, PA_NAMEREG_SINK, TRUE)) {
+ pa_namereg_set_default(u->core, ln, PA_NAMEREG_SINK);
+ pa_log_info("Restored default sink '%s'.", ln);
} else
pa_log_info("Saved default sink '%s' not existant, not restoring default sink setting.", ln);
- }
- if (m->core->default_source_name)
+ } else if (errno != ENOENT)
+ pa_log("Failed to load default sink: %s", pa_cstrerror(errno));
+
+ if (u->core->default_source_name)
pa_log_info("Manually configured default source, not overwriting.");
- else if ((f = pa_open_config_file(NULL, DEFAULT_SOURCE_FILE, NULL, NULL, "r"))) {
+ else if ((f = fopen(u->source_filename, "r"))) {
char ln[256] = "";
fgets(ln, sizeof(ln)-1, f);
@@ -73,29 +90,114 @@ int pa__init(pa_module *m) {
fclose(f);
if (!ln[0])
- pa_log_debug("No previous default source setting, ignoring.");
- else if (pa_namereg_get(m->core, ln, PA_NAMEREG_SOURCE, 1)) {
- pa_namereg_set_default(m->core, ln, PA_NAMEREG_SOURCE);
- pa_log_debug("Restored default source '%s'.", ln);
+ pa_log_info("No previous default source setting, ignoring.");
+ else if (pa_namereg_get(u->core, ln, PA_NAMEREG_SOURCE, TRUE)) {
+ pa_namereg_set_default(u->core, ln, PA_NAMEREG_SOURCE);
+ pa_log_info("Restored default source '%s'.", ln);
} else
pa_log_info("Saved default source '%s' not existant, not restoring default source setting.", ln);
- }
- return 0;
+ } else if (errno != ENOENT)
+ pa_log("Failed to load default sink: %s", pa_cstrerror(errno));
}
-void pa__done(pa_module*m) {
+static void save(struct userdata *u) {
FILE *f;
- if ((f = pa_open_config_file(NULL, DEFAULT_SINK_FILE, NULL, NULL, "w"))) {
- const char *n = pa_namereg_get_default_sink_name(m->core);
- fprintf(f, "%s\n", n ? n : "");
- fclose(f);
+ if (!u->modified)
+ return;
+
+ if (u->sink_filename) {
+ if ((f = fopen(u->sink_filename, "w"))) {
+ const char *n = pa_namereg_get_default_sink_name(u->core);
+ fprintf(f, "%s\n", pa_strempty(n));
+ fclose(f);
+ } else
+ pa_log("Failed to save default sink: %s", pa_cstrerror(errno));
}
- if ((f = pa_open_config_file(NULL, DEFAULT_SOURCE_FILE, NULL, NULL, "w"))) {
- const char *n = pa_namereg_get_default_source_name(m->core);
- fprintf(f, "%s\n", n ? n : "");
- fclose(f);
+ if (u->source_filename) {
+ if ((f = fopen(u->source_filename, "w"))) {
+ const char *n = pa_namereg_get_default_source_name(u->core);
+ fprintf(f, "%s\n", pa_strempty(n));
+ fclose(f);
+ } else
+ pa_log("Failed to save default source: %s", pa_cstrerror(errno));
+ }
+
+ u->modified = FALSE;
+}
+
+static void time_cb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *tv, void *userdata) {
+ struct userdata *u = userdata;
+
+ pa_assert(u);
+ save(u);
+
+ if (u->time_event) {
+ u->core->mainloop->time_free(u->time_event);
+ u->time_event = NULL;
+ }
+}
+
+static void subscribe_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
+ struct userdata *u = userdata;
+
+ pa_assert(u);
+
+ u->modified = TRUE;
+
+ if (!u->time_event) {
+ struct timeval tv;
+ pa_gettimeofday(&tv);
+ pa_timeval_add(&tv, DEFAULT_SAVE_INTERVAL*PA_USEC_PER_SEC);
+ u->time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, time_cb, u);
}
}
+
+int pa__init(pa_module *m) {
+ struct userdata *u;
+
+ pa_assert(u);
+
+ u = pa_xnew0(struct userdata, 1);
+ u->core = m->core;
+
+ if (!(u->sink_filename = pa_runtime_path(DEFAULT_SINK_FILE)))
+ goto fail;
+
+ if (!(u->source_filename = pa_runtime_path(DEFAULT_SOURCE_FILE)))
+ goto fail;
+
+ load(u);
+
+ u->subscription = pa_subscription_new(u->core, PA_SUBSCRIPTION_MASK_SERVER, subscribe_cb, u);
+
+ return 0;
+
+fail:
+ pa__done(m);
+
+ return -1;
+}
+
+void pa__done(pa_module*m) {
+ struct userdata *u;
+
+ pa_assert(m);
+
+ if (!(u = m->userdata))
+ return;
+
+ save(u);
+
+ if (u->subscription)
+ pa_subscription_free(u->subscription);
+
+ if (u->time_event)
+ m->core->mainloop->time_free(u->time_event);
+
+ pa_xfree(u->sink_filename);
+ pa_xfree(u->source_filename);
+ pa_xfree(u);
+}
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index 27c69f31..0a41b84a 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -263,7 +263,7 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
- char *fname, *state_dir;
+ char *fname, *runtime_dir;
char hn[256];
pa_sink *sink;
pa_source *source;
@@ -290,11 +290,11 @@ int pa__init(pa_module*m) {
if (!pa_get_host_name(hn, sizeof(hn)))
goto fail;
- if (!(state_dir = pa_get_state_dir()))
+ if (!(runtime_dir = pa_get_runtime_dir()))
goto fail;
- fname = pa_sprintf_malloc("%s/device-volumes.%s.gdbm", state_dir, hn);
- pa_xfree(state_dir);
+ fname = pa_sprintf_malloc("%s/device-volumes.%s.gdbm", runtime_dir, hn);
+ pa_xfree(runtime_dir);
if (!(u->gdbm_file = gdbm_open(fname, 0, GDBM_WRCREAT, 0600, NULL))) {
pa_log("Failed to open volume database '%s': %s", fname, gdbm_strerror(gdbm_errno));
@@ -316,6 +316,7 @@ int pa__init(pa_module*m) {
fail:
pa__done(m);
+
if (ma)
pa_modargs_free(ma);
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 9a4ba58e..2206e2bc 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -143,7 +143,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
case PA_SINK_SUSPENDED:
- pa_assert(PA_SINK_OPENED(u->sink->thread_info.state));
+ pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
pa_smoother_pause(u->smoother, pa_rtclock_usec());
break;
@@ -211,7 +211,7 @@ static void thread_func(void *userdata) {
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
/* Render some data and write it to the fifo */
- if (PA_SINK_OPENED(u->sink->thread_info.state) && pollfd->revents) {
+ if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
pa_usec_t usec;
int64_t n;
@@ -294,7 +294,7 @@ static void thread_func(void *userdata) {
}
/* Hmm, nothing to do. Let's sleep */
- pollfd->events = PA_SINK_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
+ pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
}
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index aa398a28..6e0faac7 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -102,10 +102,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
case PA_SINK_MESSAGE_GET_LATENCY: {
pa_usec_t usec = 0;
+ /* Get the latency of the master sink */
if (PA_MSGOBJECT(u->master)->process_msg(PA_MSGOBJECT(u->master), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
usec = 0;
- *((pa_usec_t*) data) = usec /* + pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec) */;
+ /* Add the latency internal to our sink input on top */
+ usec += pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->master->sample_spec);
+
+ *((pa_usec_t*) data) = usec;
return 0;
}
}
@@ -120,7 +124,10 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
pa_sink_assert_ref(s);
pa_assert_se(u = s->userdata);
- if (PA_SINK_LINKED(state) && u->sink_input && PA_SINK_INPUT_LINKED(pa_sink_input_get_state(u->sink_input)))
+ if (PA_SINK_IS_LINKED(state) &&
+ u->sink_input &&
+ PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
+
pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
return 0;
@@ -134,7 +141,7 @@ static void sink_request_rewind(pa_sink *s) {
pa_assert_se(u = s->userdata);
/* Just hand this one over to the master sink */
- pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE);
+ pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE, FALSE);
}
/* Called from I/O thread context */
@@ -145,24 +152,9 @@ static void sink_update_requested_latency(pa_sink *s) {
pa_assert_se(u = s->userdata);
/* Just hand this one over to the master sink */
- u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency_within_thread(s);
- pa_sink_invalidate_requested_latency(u->master);
-}
-
-/* Called from I/O thread context */
-static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
- struct userdata *u = PA_SINK_INPUT(o)->userdata;
-
- switch (code) {
- case PA_SINK_INPUT_MESSAGE_GET_LATENCY:
- *((pa_usec_t*) data) = 0 /*pa_bytes_to_usec(u->memchunk.length, &u->sink_input->sample_spec)*/;
-
- /* Fall through, the default handler will add in the extra
- * latency added by the resampler */
- break;
- }
-
- return pa_sink_input_process_msg(o, code, data, offset, chunk);
+ pa_sink_input_set_requested_latency_within_thread(
+ u->sink_input,
+ pa_sink_get_requested_latency_within_thread(s));
}
/* Called from I/O thread context */
@@ -192,20 +184,9 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
dst = (float*) pa_memblock_acquire(chunk->memblock);
for (c = 0; c < u->channels; c++) {
- unsigned j;
- float *p, *q;
-
- p = src + c;
- q = u->input;
- for (j = 0; j < n; j++, p += u->channels, q++)
- *q = PA_CLAMP_UNLIKELY(*p, -1.0, 1.0);
-
+ pa_sample_clamp(PA_SAMPLE_FLOAT32NE, u->input, sizeof(float), src+c, u->channels*sizeof(float), n);
u->descriptor->run(u->handle[c], n);
-
- q = u->output;
- p = dst + c;
- for (j = 0; j < n; j++, q++, p += u->channels)
- *p = PA_CLAMP_UNLIKELY(*q, -1.0, 1.0);
+ pa_sample_clamp(PA_SAMPLE_FLOAT32NE, dst+c, u->channels*sizeof(float), u->output, sizeof(float), n);
}
pa_memblock_release(tchunk.memblock);
@@ -245,6 +226,9 @@ static void sink_input_detach_cb(pa_sink_input *i) {
pa_assert_se(u = i->userdata);
pa_sink_detach_within_thread(u->sink);
+
+ pa_sink_set_asyncmsgq(u->sink, NULL);
+ pa_sink_set_rtpoll(u->sink, NULL);
}
/* Called from I/O thread context */
@@ -648,7 +632,6 @@ int pa__init(pa_module*m) {
if (!u->sink_input)
goto fail;
- u->sink_input->parent.process_msg = sink_input_process_msg;
u->sink_input->pop = sink_input_pop_cb;
u->sink_input->process_rewind = sink_input_process_rewind_cb;
u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
diff --git a/src/modules/module-match.c b/src/modules/module-match.c
index 0411dcdc..d0265455 100644
--- a/src/modules/module-match.c
+++ b/src/modules/module-match.c
@@ -82,12 +82,14 @@ static int load_rules(struct userdata *u, const char *filename) {
pa_assert(u);
- f = filename ?
- fopen(fn = pa_xstrdup(filename), "r") :
- pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn, "r");
+ if (filename)
+ f = fopen(fn = pa_xstrdup(filename), "r");
+ else
+ f = pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn);
if (!f) {
- pa_log("failed to open file '%s': %s", fn, pa_cstrerror(errno));
+ pa_xfree(fn);
+ pa_log("Failed to open file config file: %s", pa_cstrerror(errno));
goto finish;
}
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 2301f088..606b87d0 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -3,7 +3,7 @@
/***
This file is part of PulseAudio.
- Copyright 2004-2006 Lennart Poettering
+ Copyright 2004-2008 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
@@ -64,6 +64,7 @@ PA_MODULE_USAGE(
"description=<description for the sink>");
#define DEFAULT_SINK_NAME "null"
+#define MAX_LATENCY_USEC (PA_USEC_PER_SEC * 2)
struct userdata {
pa_core *core;
@@ -76,7 +77,8 @@ struct userdata {
size_t block_size;
- struct timeval timestamp;
+ pa_usec_t block_usec;
+ pa_usec_t timestamp;
};
static const char* const valid_modargs[] = {
@@ -96,26 +98,93 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
case PA_SINK_MESSAGE_SET_STATE:
if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING)
- pa_rtclock_get(&u->timestamp);
+ u->timestamp = pa_rtclock_usec();
break;
case PA_SINK_MESSAGE_GET_LATENCY: {
- struct timeval now;
+ pa_usec_t now;
- pa_rtclock_get(&now);
+ now = pa_rtclock_usec();
+ *((pa_usec_t*) data) = u->timestamp > now ? u->timestamp - now : 0;
- if (pa_timeval_cmp(&u->timestamp, &now) > 0)
- *((pa_usec_t*) data) = 0;
- else
- *((pa_usec_t*) data) = pa_timeval_diff(&u->timestamp, &now);
- break;
+ return 0;
}
}
return pa_sink_process_msg(o, code, data, offset, chunk);
}
+static void sink_update_requested_latency_cb(pa_sink *s) {
+ struct userdata *u;
+
+ pa_sink_assert_ref(s);
+ u = s->userdata;
+ pa_assert(u);
+
+ u->block_usec = pa_sink_get_requested_latency_within_thread(s);
+}
+
+static void process_rewind(struct userdata *u, pa_usec_t now) {
+ size_t rewind_nbytes, in_buffer;
+ pa_usec_t delay;
+
+ pa_assert(u);
+
+ /* Figure out how much we shall rewind and reset the counter */
+ rewind_nbytes = u->sink->thread_info.rewind_nbytes;
+ u->sink->thread_info.rewind_nbytes = 0;
+
+ pa_assert(rewind_nbytes > 0);
+ pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
+
+ if (u->timestamp <= now)
+ return;
+
+ delay = u->timestamp - now;
+ in_buffer = pa_usec_to_bytes(delay, &u->sink->sample_spec);
+
+ if (in_buffer <= 0)
+ return;
+
+ if (rewind_nbytes > in_buffer)
+ rewind_nbytes = in_buffer;
+
+ pa_sink_process_rewind(u->sink, rewind_nbytes);
+ u->timestamp -= pa_bytes_to_usec(rewind_nbytes, &u->sink->sample_spec);
+
+ pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
+}
+
+static void process_render(struct userdata *u, pa_usec_t now) {
+ size_t nbytes;
+ size_t ate = 0;
+
+ /* This is the configured latency. Sink inputs connected to us
+ might not have a single frame more than this value queued. Hence:
+ at maximum read this many bytes from the sink inputs. */
+
+ nbytes = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
+
+ /* Fill the buffer up the the latency size */
+ while (u->timestamp < now + u->block_usec) {
+ pa_memchunk chunk;
+
+ pa_sink_render(u->sink, nbytes, &chunk);
+ pa_memblock_unref(chunk.memblock);
+
+ pa_log_debug("Ate %lu bytes.", (unsigned long) chunk.length);
+ u->timestamp += pa_bytes_to_usec(chunk.length, &u->sink->sample_spec);
+
+ ate += chunk.length;
+
+ if (ate >= nbytes)
+ break;
+ }
+
+ pa_log_debug("Ate in sum %lu bytes (of %lu)", (unsigned long) ate, (unsigned long) nbytes);
+}
+
static void thread_func(void *userdata) {
struct userdata *u = userdata;
@@ -126,23 +195,24 @@ static void thread_func(void *userdata) {
pa_thread_mq_install(&u->thread_mq);
pa_rtpoll_install(u->rtpoll);
- pa_rtclock_get(&u->timestamp);
+ u->timestamp = pa_rtclock_usec();
for (;;) {
int ret;
/* Render some data and drop it immediately */
if (u->sink->thread_info.state == PA_SINK_RUNNING) {
- struct timeval now;
+ pa_usec_t now;
- pa_rtclock_get(&now);
+ now = pa_rtclock_usec();
- if (pa_timeval_cmp(&u->timestamp, &now) <= 0) {
- pa_sink_skip(u->sink, u->block_size);
- pa_timeval_add(&u->timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
- }
+ if (u->sink->thread_info.rewind_nbytes > 0)
+ process_rewind(u, now);
- pa_rtpoll_set_timer_absolute(u->rtpoll, &u->timestamp);
+ if (u->timestamp <= now)
+ process_render(u, now);
+
+ pa_rtpoll_set_timer_absolute(u->rtpoll, u->timestamp);
} else
pa_rtpoll_set_timer_disabled(u->rtpoll);
@@ -197,26 +267,26 @@ int pa__init(pa_module*m) {
pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
pa_sink_new_data_set_sample_spec(&data, &ss);
pa_sink_new_data_set_channel_map(&data, &map);
- pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "NULL sink"));
+ pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "Null Output"));
- u->sink = pa_sink_new(m->core, &data, 0);
+ u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY);
pa_sink_new_data_done(&data);
if (!u->sink) {
- pa_log("Failed to create sink.");
+ pa_log("Failed to create sink object.");
goto fail;
}
u->sink->parent.process_msg = sink_process_msg;
+ u->sink->update_requested_latency = sink_update_requested_latency_cb;
u->sink->userdata = u;
- u->sink->flags = PA_SINK_LATENCY;
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
pa_sink_set_rtpoll(u->sink, u->rtpoll);
- u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
- if (u->block_size <= 0)
- u->block_size = pa_frame_size(&ss);
+ u->block_usec = u->sink->max_latency = MAX_LATENCY_USEC;
+
+ u->sink->thread_info.max_rewind = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
if (!(u->thread = pa_thread_new(thread_func, u))) {
pa_log("Failed to create thread.");
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index f07d82a0..3dd4508e 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -161,10 +161,10 @@ static void trigger(struct userdata *u, pa_bool_t quick) {
pa_log_debug("trigger");
- if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state))
+ if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state))
enable_bits |= PCM_ENABLE_INPUT;
- if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state))
+ if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state))
enable_bits |= PCM_ENABLE_OUTPUT;
pa_log_debug("trigger: %i", enable_bits);
@@ -202,7 +202,7 @@ static void trigger(struct userdata *u, pa_bool_t quick) {
* register the fd as ready.
*/
- if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) {
+ if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
uint8_t *buf = pa_xnew(uint8_t, u->in_fragment_size);
pa_read(u->fd, buf, u->in_fragment_size, NULL);
pa_xfree(buf);
@@ -641,7 +641,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
case PA_SINK_SUSPENDED:
- pa_assert(PA_SINK_OPENED(u->sink->thread_info.state));
+ pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
if (!u->source || u->source_suspended) {
if (suspend(u) < 0)
@@ -658,7 +658,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
if (u->sink->thread_info.state == PA_SINK_INIT) {
do_trigger = TRUE;
- quick = u->source && PA_SOURCE_OPENED(u->source->thread_info.state);
+ quick = u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state);
}
if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
@@ -721,7 +721,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
case PA_SOURCE_SUSPENDED:
- pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state));
+ pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
if (!u->sink || u->sink_suspended) {
if (suspend(u) < 0)
@@ -738,7 +738,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
if (u->source->thread_info.state == PA_SOURCE_INIT) {
do_trigger = TRUE;
- quick = u->sink && PA_SINK_OPENED(u->sink->thread_info.state);
+ quick = u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state);
}
if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
@@ -877,7 +877,7 @@ static void thread_func(void *userdata) {
/* Render some data and write it to the dsp */
- if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state) && ((revents & POLLOUT) || u->use_mmap || u->use_getospace)) {
+ if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state) && ((revents & POLLOUT) || u->use_mmap || u->use_getospace)) {
if (u->use_mmap) {
@@ -985,7 +985,7 @@ static void thread_func(void *userdata) {
/* Try to read some data and pass it on to the source driver. */
- if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state) && ((revents & POLLIN) || u->use_mmap || u->use_getispace)) {
+ if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state) && ((revents & POLLIN) || u->use_mmap || u->use_getispace)) {
if (u->use_mmap) {
@@ -1095,8 +1095,8 @@ static void thread_func(void *userdata) {
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
pollfd->events =
- ((u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) ? POLLIN : 0) |
- ((u->sink && PA_SINK_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0);
+ ((u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0) |
+ ((u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0);
}
/* Hmm, nothing to do. Let's sleep */
diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index 600201b4..8bcc19b1 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -215,15 +215,6 @@ int pa__init(pa_module*m) {
#else
pa_socket_server *s;
int r;
- char tmp[PATH_MAX];
-
-#if defined(USE_PROTOCOL_ESOUND)
-#if defined(USE_PER_USER_ESOUND_SOCKET)
- char esdsocketpath[PATH_MAX];
-#else
- const char esdsocketpath[] = "/tmp/.esd/socket";
-#endif
-#endif
#endif
pa_assert(m);
@@ -255,27 +246,28 @@ int pa__init(pa_module*m) {
goto fail;
if (s_ipv4)
- if (!(u->protocol_ipv4 = protocol_new(m->core, s_ipv4, m, ma)))
- pa_socket_server_unref(s_ipv4);
-
+ u->protocol_ipv4 = protocol_new(m->core, s_ipv4, m, ma);
if (s_ipv6)
- if (!(u->protocol_ipv6 = protocol_new(m->core, s_ipv6, m, ma)))
- pa_socket_server_unref(s_ipv6);
+ u->protocol_ipv6 = protocol_new(m->core, s_ipv6, m, ma);
if (!u->protocol_ipv4 && !u->protocol_ipv6)
goto fail;
+ if (s_ipv6)
+ pa_socket_server_unref(s_ipv6);
+ if (s_ipv6)
+ pa_socket_server_unref(s_ipv4);
+
#else
#if defined(USE_PROTOCOL_ESOUND)
#if defined(USE_PER_USER_ESOUND_SOCKET)
- snprintf(esdsocketpath, sizeof(esdsocketpath), "/tmp/.esd-%lu/socket", (unsigned long) getuid());
+ u->socket_path = pa_sprintf_malloc("/tmp/.esd-%lu/socket", (unsigned long) getuid());
+#else
+ u->socket_path = pa_xstrdup("/tmp/.esd/socket");
#endif
- pa_runtime_path(pa_modargs_get_value(ma, "socket", esdsocketpath), tmp, sizeof(tmp));
- u->socket_path = pa_xstrdup(tmp);
-
/* This socket doesn't reside in our own runtime dir but in
* /tmp/.esd/, hence we have to create the dir first */
@@ -285,24 +277,26 @@ int pa__init(pa_module*m) {
}
#else
- pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET), tmp, sizeof(tmp));
- u->socket_path = pa_xstrdup(tmp);
-#endif
-
- if ((r = pa_unix_socket_remove_stale(tmp)) < 0) {
- pa_log("Failed to remove stale UNIX socket '%s': %s", tmp, pa_cstrerror(errno));
+ if (!(u->socket_path = pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET)))) {
+ pa_log("Failed to generate socket path.");
goto fail;
}
+#endif
- if (r)
- pa_log("Removed stale UNIX socket '%s'.", tmp);
+ if ((r = pa_unix_socket_remove_stale(u->socket_path)) < 0) {
+ pa_log("Failed to remove stale UNIX socket '%s': %s", u->socket_path, pa_cstrerror(errno));
+ goto fail;
+ } else if (r > 0)
+ pa_log_info("Removed stale UNIX socket '%s'.", u->socket_path);
- if (!(s = pa_socket_server_new_unix(m->core->mainloop, tmp)))
+ if (!(s = pa_socket_server_new_unix(m->core->mainloop, u->socket_path)))
goto fail;
if (!(u->protocol_unix = protocol_new(m->core, s, m, ma)))
goto fail;
+ pa_socket_server_unref(s);
+
#endif
m->userdata = u;
@@ -325,23 +319,21 @@ fail:
#else
if (u->protocol_unix)
protocol_free(u->protocol_unix);
-
- if (u->socket_path)
- pa_xfree(u->socket_path);
+ pa_xfree(u->socket_path);
#endif
pa_xfree(u);
- } else {
+ }
+
#if defined(USE_TCP_SOCKETS)
- if (s_ipv4)
- pa_socket_server_unref(s_ipv4);
- if (s_ipv6)
- pa_socket_server_unref(s_ipv6);
+ if (s_ipv4)
+ pa_socket_server_unref(s_ipv4);
+ if (s_ipv6)
+ pa_socket_server_unref(s_ipv6);
#else
- if (s)
- pa_socket_server_unref(s);
+ if (s)
+ pa_socket_server_unref(s);
#endif
- }
goto finish;
}
@@ -362,7 +354,7 @@ void pa__done(pa_module*m) {
if (u->protocol_unix)
protocol_free(u->protocol_unix);
-#if defined(USE_PROTOCOL_ESOUND)
+#if defined(USE_PROTOCOL_ESOUND) && !defined(USE_PER_USER_ESOUND_SOCKET)
if (u->socket_path) {
char *p = pa_parent_dir(u->socket_path);
rmdir(p);
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 6a16321d..f68b7191 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -81,10 +81,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
case PA_SINK_MESSAGE_GET_LATENCY: {
pa_usec_t usec = 0;
+ /* Get the latency of the master sink */
if (PA_MSGOBJECT(u->master)->process_msg(PA_MSGOBJECT(u->master), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
usec = 0;
- *((pa_usec_t*) data) = usec/* + pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec)*/;
+ /* Add the latency internal to our sink input on top */
+ usec += pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->master->sample_spec);
+
+ *((pa_usec_t*) data) = usec;
return 0;
}
}
@@ -99,7 +103,10 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
pa_sink_assert_ref(s);
pa_assert_se(u = s->userdata);
- if (PA_SINK_LINKED(state) && u->sink_input && PA_SINK_INPUT_LINKED(pa_sink_input_get_state(u->sink_input)))
+ if (PA_SINK_IS_LINKED(state) &&
+ u->sink_input &&
+ PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
+
pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
return 0;
@@ -112,7 +119,7 @@ static void sink_request_rewind(pa_sink *s) {
pa_sink_assert_ref(s);
pa_assert_se(u = s->userdata);
- pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE);
+ pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE, FALSE);
}
/* Called from I/O thread context */
@@ -123,24 +130,9 @@ static void sink_update_requested_latency(pa_sink *s) {
pa_assert_se(u = s->userdata);
/* Just hand this one over to the master sink */
- u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency_within_thread(s);
- pa_sink_invalidate_requested_latency(u->master);
-}
-
-/* Called from I/O thread context */
-static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
- struct userdata *u = PA_SINK_INPUT(o)->userdata;
-
- switch (code) {
- case PA_SINK_INPUT_MESSAGE_GET_LATENCY:
- *((pa_usec_t*) data) = 0; /*pa_bytes_to_usec(u->memchunk.length, &u->sink_input->sample_spec);*/
-
- /* Fall through, the default handler will add in the extra
- * latency added by the resampler */
- break;
- }
-
- return pa_sink_input_process_msg(o, code, data, offset, chunk);
+ pa_sink_input_set_requested_latency_within_thread(
+ u->sink_input,
+ pa_sink_get_requested_latency_within_thread(s));
}
/* Called from I/O thread context */
@@ -152,7 +144,6 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
pa_assert_se(u = i->userdata);
pa_sink_render(u->sink, nbytes, chunk);
-
return 0;
}
@@ -185,6 +176,9 @@ static void sink_input_detach_cb(pa_sink_input *i) {
pa_assert_se(u = i->userdata);
pa_sink_detach_within_thread(u->sink);
+
+ pa_sink_set_asyncmsgq(u->sink, NULL);
+ pa_sink_set_rtpoll(u->sink, NULL);
}
/* Called from I/O thread context */
@@ -317,7 +311,6 @@ int pa__init(pa_module*m) {
if (!u->sink_input)
goto fail;
- u->sink_input->parent.process_msg = sink_input_process_msg;
u->sink_input->pop = sink_input_pop_cb;
u->sink_input->process_rewind = sink_input_process_rewind_cb;
u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index ef8239d0..a3985974 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -317,7 +317,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
if (pa_sink_used_by(s) <= 0) {
- if (PA_SINK_OPENED(state))
+ if (PA_SINK_IS_OPENED(state))
restart(d);
}
@@ -328,7 +328,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
if (pa_source_used_by(s) <= 0) {
- if (PA_SOURCE_OPENED(state))
+ if (PA_SOURCE_IS_OPENED(state))
restart(d);
}
}
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index 74d5a826..e3ae5e1f 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -303,7 +303,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
/* First, change the state, because otherwide pa_sink_render() would fail */
if ((r = pa_sink_process_msg(o, code, data, offset, chunk)) >= 0)
- if (PA_SINK_OPENED((pa_sink_state_t) PA_PTR_TO_UINT(data)))
+ if (PA_SINK_IS_OPENED((pa_sink_state_t) PA_PTR_TO_UINT(data)))
send_data(u);
return r;
@@ -314,7 +314,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
pa_assert(offset > 0);
u->requested_bytes += (size_t) offset;
- if (PA_SINK_OPENED(u->sink->thread_info.state))
+ if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
send_data(u);
return 0;
@@ -343,7 +343,7 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
switch ((pa_sink_state_t) state) {
case PA_SINK_SUSPENDED:
- pa_assert(PA_SINK_OPENED(s->state));
+ pa_assert(PA_SINK_IS_OPENED(s->state));
stream_cork(u, TRUE);
break;
@@ -369,7 +369,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
switch (code) {
case SOURCE_MESSAGE_POST:
- if (PA_SOURCE_OPENED(u->source->thread_info.state))
+ if (PA_SOURCE_IS_OPENED(u->source->thread_info.state))
pa_source_post(u->source, chunk);
return 0;
}
@@ -385,7 +385,7 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
switch ((pa_source_state_t) state) {
case PA_SOURCE_SUSPENDED:
- pa_assert(PA_SOURCE_OPENED(s->state));
+ pa_assert(PA_SOURCE_IS_OPENED(s->state));
stream_cork(u, TRUE);
break;
@@ -1066,7 +1066,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
pa_tagstruct_putu32(reply, PA_INVALID_INDEX);
pa_tagstruct_puts(reply, u->sink_name);
pa_tagstruct_putu32(reply, u->maxlength);
- pa_tagstruct_put_boolean(reply, !PA_SINK_OPENED(pa_sink_get_state(u->sink)));
+ pa_tagstruct_put_boolean(reply, !PA_SINK_IS_OPENED(pa_sink_get_state(u->sink)));
pa_tagstruct_putu32(reply, u->tlength);
pa_tagstruct_putu32(reply, u->prebuf);
pa_tagstruct_putu32(reply, u->minreq);
@@ -1082,7 +1082,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
pa_tagstruct_putu32(reply, PA_INVALID_INDEX);
pa_tagstruct_puts(reply, u->source_name);
pa_tagstruct_putu32(reply, u->maxlength);
- pa_tagstruct_put_boolean(reply, !PA_SOURCE_OPENED(pa_source_get_state(u->source)));
+ pa_tagstruct_put_boolean(reply, !PA_SOURCE_IS_OPENED(pa_source_get_state(u->source)));
pa_tagstruct_putu32(reply, u->fragsize);
#endif
diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c
index 0dc8dcfd..336bcac9 100644
--- a/src/modules/module-volume-restore.c
+++ b/src/modules/module-volume-restore.c
@@ -134,16 +134,12 @@ static int load_rules(struct userdata *u) {
char buf_name[256], buf_volume[256], buf_sink[256], buf_source[256];
char *ln = buf_name;
- f = u->table_file ?
- fopen(u->table_file, "r") :
- pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "r");
-
- if (!f) {
+ if (!(f = fopen(u->table_file, "r"))) {
if (errno == ENOENT) {
- pa_log_info("starting with empty ruleset.");
+ pa_log_info("Starting with empty ruleset.");
ret = 0;
} else
- pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno));
+ pa_log("Failed to open file '%s': %s", u->table_file, pa_cstrerror(errno));
goto finish;
}
@@ -236,11 +232,7 @@ static int save_rules(struct userdata *u) {
pa_log_info("Saving rules...");
- f = u->table_file ?
- fopen(u->table_file, "w") :
- pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w");
-
- if (!f) {
+ if (!(f = fopen(u->table_file, "w"))) {
pa_log("Failed to open file '%s': %s", u->table_file, pa_cstrerror(errno));
goto finish;
}
@@ -496,7 +488,7 @@ int pa__init(pa_module*m) {
u = pa_xnew(struct userdata, 1);
u->core = m->core;
u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL));
+ u->table_file = pa_runtime_path(pa_modargs_get_value(ma, "table", DEFAULT_VOLUME_TABLE_FILE));
u->modified = FALSE;
u->subscription = NULL;
u->sink_input_new_hook_slot = u->sink_input_fixate_hook_slot = u->source_output_new_hook_slot = NULL;