diff options
author | Lennart Poettering <lennart@poettering.net> | 2008-05-01 19:51:05 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2008-05-01 19:51:05 +0000 |
commit | 52e3628c3edd98ae3402605e7f44a0fc4545dd0a (patch) | |
tree | 843a7bb1a077141baea5ac29e62d163c90b4acc6 /src/modules | |
parent | f94fae3da3e3201afc060d3ae24c96fd9bba56ab (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.c | 20 | ||||
-rw-r--r-- | src/modules/module-alsa-sink.c | 18 | ||||
-rw-r--r-- | src/modules/module-alsa-source.c | 6 | ||||
-rw-r--r-- | src/modules/module-combine.c | 31 | ||||
-rw-r--r-- | src/modules/module-default-device-restore.c | 154 | ||||
-rw-r--r-- | src/modules/module-device-restore.c | 9 | ||||
-rw-r--r-- | src/modules/module-esound-sink.c | 6 | ||||
-rw-r--r-- | src/modules/module-ladspa-sink.c | 53 | ||||
-rw-r--r-- | src/modules/module-match.c | 10 | ||||
-rw-r--r-- | src/modules/module-null-sink.c | 120 | ||||
-rw-r--r-- | src/modules/module-oss.c | 22 | ||||
-rw-r--r-- | src/modules/module-protocol-stub.c | 70 | ||||
-rw-r--r-- | src/modules/module-remap-sink.c | 39 | ||||
-rw-r--r-- | src/modules/module-suspend-on-idle.c | 4 | ||||
-rw-r--r-- | src/modules/module-tunnel.c | 14 | ||||
-rw-r--r-- | src/modules/module-volume-restore.c | 18 |
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; |