diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/daemon/default.pa.in | 2 | ||||
-rw-r--r-- | src/modules/alsa/alsa-sink.c | 56 | ||||
-rw-r--r-- | src/modules/module-loopback.c | 27 | ||||
-rw-r--r-- | src/modules/module-tunnel.c | 4 | ||||
-rw-r--r-- | src/pulse/stream.c | 4 | ||||
-rw-r--r-- | src/pulsecore/dbus-util.c | 7 | ||||
-rw-r--r-- | src/pulsecore/flist.c | 4 | ||||
-rw-r--r-- | src/pulsecore/flist.h | 4 | ||||
-rw-r--r-- | src/pulsecore/sink.c | 33 | ||||
-rw-r--r-- | src/utils/padsp.c | 61 |
10 files changed, 142 insertions, 60 deletions
diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index f9b9eadd..ace0f09e 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -111,7 +111,9 @@ load-module module-suspend-on-idle ### If autoexit on idle is enabled we want to make sure we only quit ### when no local session needs us anymore. +.ifexists module-console-kit@PA_SOEXT@ load-module module-console-kit +.endif ### Enable positioned event sounds load-module module-position-event-sounds diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 53c14b80..f861904f 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -1281,15 +1281,17 @@ static void sink_write_volume_cb(pa_sink *s) { (pa_cvolume_max(&tmp_vol) <= (PA_VOLUME_NORM + VOLUME_ACCURACY)); if (!accurate_enough) { - char vol_str_pcnt[PA_CVOLUME_SNPRINT_MAX]; - char vol_str_db[PA_SW_CVOLUME_SNPRINT_DB_MAX]; + union { + char db[2][PA_SW_CVOLUME_SNPRINT_DB_MAX]; + char pcnt[2][PA_CVOLUME_SNPRINT_MAX]; + } vol; pa_log_debug("Written HW volume did not match with the request: %s (request) != %s", - pa_cvolume_snprint(vol_str_pcnt, sizeof(vol_str_pcnt), &s->thread_info.current_hw_volume), - pa_cvolume_snprint(vol_str_pcnt, sizeof(vol_str_pcnt), &hw_vol)); + pa_cvolume_snprint(vol.pcnt[0], sizeof(vol.pcnt[0]), &s->thread_info.current_hw_volume), + pa_cvolume_snprint(vol.pcnt[1], sizeof(vol.pcnt[1]), &hw_vol)); pa_log_debug(" in dB: %s (request) != %s", - pa_sw_cvolume_snprint_dB(vol_str_db, sizeof(vol_str_db), &s->thread_info.current_hw_volume), - pa_sw_cvolume_snprint_dB(vol_str_db, sizeof(vol_str_db), &hw_vol)); + pa_sw_cvolume_snprint_dB(vol.db[0], sizeof(vol.db[0]), &s->thread_info.current_hw_volume), + pa_sw_cvolume_snprint_dB(vol.db[1], sizeof(vol.db[1]), &hw_vol)); } } } @@ -1670,8 +1672,6 @@ fail: } static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_volume) { - int (*mixer_callback)(snd_mixer_elem_t *, unsigned int); - pa_assert(u); if (!u->mixer_handle) @@ -1760,29 +1760,31 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_v pa_log_info("Using hardware mute control."); } - if (sync_volume) { - u->mixer_pd = pa_alsa_mixer_pdata_new(); - mixer_callback = io_mixer_callback; - - if (pa_alsa_set_mixer_rtpoll(u->mixer_pd, u->mixer_handle, u->rtpoll) < 0) { - pa_log("Failed to initialize file descriptor monitoring"); - return -1; - } + if (u->sink->flags & (PA_SINK_HW_VOLUME_CTRL|PA_SINK_HW_MUTE_CTRL)) { + int (*mixer_callback)(snd_mixer_elem_t *, unsigned int); + if (u->sink->flags & PA_SINK_SYNC_VOLUME) { + u->mixer_pd = pa_alsa_mixer_pdata_new(); + mixer_callback = io_mixer_callback; - } else { - u->mixer_fdl = pa_alsa_fdlist_new(); - mixer_callback = ctl_mixer_callback; + if (pa_alsa_set_mixer_rtpoll(u->mixer_pd, u->mixer_handle, u->rtpoll) < 0) { + pa_log("Failed to initialize file descriptor monitoring"); + return -1; + } + } else { + u->mixer_fdl = pa_alsa_fdlist_new(); + mixer_callback = ctl_mixer_callback; - if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, u->core->mainloop) < 0) { - pa_log("Failed to initialize file descriptor monitoring"); - return -1; + if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, u->core->mainloop) < 0) { + pa_log("Failed to initialize file descriptor monitoring"); + return -1; + } } - } - if (u->mixer_path_set) - pa_alsa_path_set_set_callback(u->mixer_path_set, u->mixer_handle, mixer_callback, u); - else - pa_alsa_path_set_callback(u->mixer_path, u->mixer_handle, mixer_callback, u); + if (u->mixer_path_set) + pa_alsa_path_set_set_callback(u->mixer_path_set, u->mixer_handle, mixer_callback, u); + else + pa_alsa_path_set_callback(u->mixer_path, u->mixer_handle, mixer_callback, u); + } return 0; } diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c index 55716b2f..a6553f7d 100644 --- a/src/modules/module-loopback.c +++ b/src/modules/module-loopback.c @@ -57,7 +57,9 @@ PA_MODULE_USAGE( "sink_input_name=<custom name for the sink input> " "source_output_name=<custom name for the source output> " "sink_input_role=<media.role for the sink input> " - "source_output_role=<media.role for the source output>"); + "source_output_role=<media.role for the source output> " + "source_dont_move=<boolean> " + "sink_dont_move=<boolean>"); #define DEFAULT_LATENCY_MSEC 200 @@ -115,6 +117,8 @@ static const char* const valid_modargs[] = { "source_output_name", "sink_input_role", "source_output_role", + "source_dont_move", + "sink_dont_move", NULL, }; @@ -618,8 +622,10 @@ int pa__init(pa_module *m) { struct userdata *u; pa_sink *sink; pa_sink_input_new_data sink_input_data; + pa_bool_t sink_dont_move; pa_source *source; pa_source_output_new_data source_output_data; + pa_bool_t source_dont_move; uint32_t latency_msec; pa_sample_spec ss; pa_channel_map map; @@ -696,6 +702,15 @@ int pa__init(pa_module *m) { pa_sink_input_new_data_set_channel_map(&sink_input_data, &map); sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE; + sink_dont_move = FALSE; + if (pa_modargs_get_value_boolean(ma, "sink_dont_move", &sink_dont_move) < 0) { + pa_log("sink_dont_move= expects a boolean argument."); + goto fail; + } + + if (sink_dont_move) + sink_input_data.flags |= PA_SINK_INPUT_DONT_MOVE; + pa_sink_input_new(&u->sink_input, m->core, &sink_input_data); pa_sink_input_new_data_done(&sink_input_data); @@ -737,6 +752,16 @@ int pa__init(pa_module *m) { pa_source_output_new_data_set_sample_spec(&source_output_data, &ss); pa_sink_input_new_data_set_channel_map(&sink_input_data, &map); + source_output_data.flags = (pa_source_output_flags_t)0; + + source_dont_move = FALSE; + if (pa_modargs_get_value_boolean(ma, "source_dont_move", &source_dont_move) < 0) { + pa_log("source_dont_move= expects a boolean argument."); + goto fail; + } + + if (source_dont_move) + source_output_data.flags |= PA_SOURCE_OUTPUT_DONT_MOVE; pa_source_output_new(&u->source_output, m->core, &source_output_data); pa_source_output_new_data_done(&source_output_data); diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index ce5f8d55..176c2c00 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -1919,7 +1919,7 @@ int pa__init(pa_module*m) { #ifdef TUNNEL_SINK if (!(dn = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL)))) - dn = pa_sprintf_malloc("tunnel.%s", u->server_name); + dn = pa_sprintf_malloc("tunnel-sink.%s", u->server_name); pa_sink_new_data_init(&data); data.driver = __FILE__; @@ -1963,7 +1963,7 @@ int pa__init(pa_module*m) { #else if (!(dn = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL)))) - dn = pa_sprintf_malloc("tunnel.%s", u->server_name); + dn = pa_sprintf_malloc("tunnel-source.%s", u->server_name); pa_source_new_data_init(&data); data.driver = __FILE__; diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 87c24ba8..addc36ae 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -1733,8 +1733,8 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, i->read_index -= (int64_t) pa_memblockq_get_length(o->stream->record_memblockq); } - /* Update smoother */ - if (o->stream->smoother) { + /* Update smoother if we're not corked */ + if (o->stream->smoother && !o->stream->corked) { pa_usec_t u, x; u = x = pa_rtclock_now() - i->transport_usec; diff --git a/src/pulsecore/dbus-util.c b/src/pulsecore/dbus-util.c index 8b203051..09ab071b 100644 --- a/src/pulsecore/dbus-util.c +++ b/src/pulsecore/dbus-util.c @@ -595,14 +595,19 @@ void pa_dbus_send_proplist_variant_reply(DBusConnection *c, DBusMessage *in_repl void pa_dbus_append_basic_array(DBusMessageIter *iter, int item_type, const void *array, unsigned n) { DBusMessageIter array_iter; + unsigned i; + unsigned item_size; pa_assert(iter); pa_assert(dbus_type_is_basic(item_type)); pa_assert(array || n == 0); + item_size = basic_type_size(item_type); + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, signature_from_basic_type(item_type), &array_iter)); - pa_assert_se(dbus_message_iter_append_fixed_array(&array_iter, item_type, array, n)); + for (i = 0; i < n; ++i) + pa_assert_se(dbus_message_iter_append_basic(&array_iter, item_type, &((uint8_t*) array)[i * item_size])); pa_assert_se(dbus_message_iter_close_container(iter, &array_iter)); }; diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c index 1867525b..23af5dd4 100644 --- a/src/pulsecore/flist.c +++ b/src/pulsecore/flist.c @@ -83,13 +83,14 @@ static void stack_push(pa_atomic_ptr_t *list, pa_flist_elem *new_elem) { pa_flist *pa_flist_new_with_name(unsigned size, const char *name) { pa_flist *l; unsigned i; + pa_assert(name); if (!size) size = FLIST_SIZE; l = pa_xmalloc0(sizeof(pa_flist) + sizeof(pa_flist_elem) * size); - l->name = name; + l->name = pa_xstrdup(name); l->size = size; pa_atomic_ptr_store(&l->stored, NULL); pa_atomic_ptr_store(&l->empty, NULL); @@ -105,6 +106,7 @@ pa_flist *pa_flist_new(unsigned size) { void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) { pa_assert(l); + pa_assert(l->name); if (free_cb) { pa_flist_elem *elem; diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h index 7fb50359..915b1135 100644 --- a/src/pulsecore/flist.h +++ b/src/pulsecore/flist.h @@ -33,8 +33,8 @@ typedef struct pa_flist pa_flist; pa_flist * pa_flist_new(unsigned size); -/* Freeing the name is responsibility of caller. The name is only used - * for debug printing. */ +/* Name string is copied and added to flist structure. The original is + * responsibility of the caller. The name is only used for debug printing. */ pa_flist * pa_flist_new_with_name(unsigned size, const char *name); void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 7b4e626d..3cadbff6 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -751,8 +751,11 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) { if (s->thread_info.state == PA_SINK_SUSPENDED) return; - if (nbytes > 0) + if (nbytes > 0) { pa_log_debug("Processing rewind..."); + if (s->flags & PA_SINK_SYNC_VOLUME) + pa_sink_volume_change_rewind(s, nbytes); + } PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) { pa_sink_input_assert_ref(i); @@ -762,8 +765,6 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) { if (nbytes > 0) { if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state)) pa_source_process_rewind(s->monitor_source, nbytes); - if (s->flags & PA_SINK_SYNC_VOLUME) - pa_sink_volume_change_rewind(s, nbytes); } } @@ -2905,10 +2906,7 @@ void pa_sink_volume_change_push(pa_sink *s) { return; } - /* Get the latency of the sink */ - if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &nc->at, 0, NULL) < 0) - nc->at = 0; - + nc->at = pa_sink_get_latency_within_thread(s); nc->at += pa_rtclock_now() + s->thread_info.volume_change_extra_delay; if (s->thread_info.volume_changes_tail) { @@ -3006,20 +3004,25 @@ pa_bool_t pa_sink_volume_change_apply(pa_sink *s, pa_usec_t *usec_to_next) { static void pa_sink_volume_change_rewind(pa_sink *s, size_t nbytes) { /* All the queued volume events later than current latency are shifted to happen earlier. */ pa_sink_volume_change *c; + pa_volume_t prev_vol = pa_cvolume_avg(&s->thread_info.current_hw_volume); pa_usec_t rewound = pa_bytes_to_usec(nbytes, &s->sample_spec); - pa_usec_t limit; - - /* Get the latency of the sink */ - if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &limit, 0, NULL) < 0) - limit = 0; + pa_usec_t limit = pa_sink_get_latency_within_thread(s); + pa_log_debug("latency = %lld", limit); limit += pa_rtclock_now() + s->thread_info.volume_change_extra_delay; PA_LLIST_FOREACH(c, s->thread_info.volume_changes) { - if (c->at > limit) { + pa_usec_t modified_limit = limit; + if (prev_vol > pa_cvolume_avg(&c->hw_volume)) + modified_limit -= s->thread_info.volume_change_safety_margin; + else + modified_limit += s->thread_info.volume_change_safety_margin; + if (c->at > modified_limit) { c->at -= rewound; - if (c->at < limit) - c->at = limit; + if (c->at < modified_limit) + c->at = modified_limit; } + prev_vol = pa_cvolume_avg(&c->hw_volume); } + pa_sink_volume_change_apply(s, NULL); } diff --git a/src/utils/padsp.c b/src/utils/padsp.c index fb756d39..ec0c46d9 100644 --- a/src/utils/padsp.c +++ b/src/utils/padsp.c @@ -118,6 +118,7 @@ static PA_LLIST_HEAD(fd_info, fd_infos) = NULL; static int (*_ioctl)(int, int, void*) = NULL; static int (*_close)(int) = NULL; static int (*_open)(const char *, int, mode_t) = NULL; +static int (*___open_2)(const char *, int) = NULL; static FILE* (*_fopen)(const char *path, const char *mode) = NULL; static int (*_stat)(const char *, struct stat *) = NULL; #ifdef _STAT_VER @@ -125,6 +126,7 @@ static int (*___xstat)(int, const char *, struct stat *) = NULL; #endif #ifdef HAVE_OPEN64 static int (*_open64)(const char *, int, mode_t) = NULL; +static int (*___open64_2)(const char *, int) = NULL; static FILE* (*_fopen64)(const char *path, const char *mode) = NULL; static int (*_stat64)(const char *, struct stat64 *) = NULL; #ifdef _STAT_VER @@ -157,6 +159,14 @@ do { \ pthread_mutex_unlock(&func_mutex); \ } while(0) +#define LOAD___OPEN_2_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!___open_2) \ + ___open_2 = (int (*)(const char *, int)) dlsym_fn(RTLD_NEXT, "__open_2"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + #define LOAD_OPEN64_FUNC() \ do { \ pthread_mutex_lock(&func_mutex); \ @@ -165,6 +175,14 @@ do { \ pthread_mutex_unlock(&func_mutex); \ } while(0) +#define LOAD___OPEN64_2_FUNC() \ +do { \ + pthread_mutex_lock(&func_mutex); \ + if (!___open64_2) \ + ___open64_2 = (int (*)(const char *, int)) dlsym_fn(RTLD_NEXT, "__open64_2"); \ + pthread_mutex_unlock(&func_mutex); \ +} while(0) + #define LOAD_CLOSE_FUNC() \ do { \ pthread_mutex_lock(&func_mutex); \ @@ -1494,6 +1512,27 @@ int open(const char *filename, int flags, ...) { return real_open(filename, flags, mode); } +static pa_bool_t is_audio_device_node(const char *path) { + return + pa_streq(path, "/dev/dsp") || + pa_streq(path, "/dev/adsp") || + pa_streq(path, "/dev/audio") || + pa_streq(path, "/dev/sndstat") || + pa_streq(path, "/dev/mixer"); +} + +int __open_2(const char *filename, int flags) { + debug(DEBUG_LEVEL_VERBOSE, __FILE__": __open_2(%s)\n", filename?filename:"NULL"); + + if ((flags & O_CREAT) || + !filename || + !is_audio_device_node(filename)) { + LOAD___OPEN_2_FUNC(); + return ___open_2(filename, flags); + } + return real_open(filename, flags, 0); +} + static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) { int ret = -1; @@ -2383,15 +2422,6 @@ int close(int fd) { return 0; } -static pa_bool_t is_audio_device_node(const char *path) { - return - pa_streq(path, "/dev/dsp") || - pa_streq(path, "/dev/adsp") || - pa_streq(path, "/dev/audio") || - pa_streq(path, "/dev/sndstat") || - pa_streq(path, "/dev/mixer"); -} - int access(const char *pathname, int mode) { debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname?pathname:"NULL"); @@ -2527,6 +2557,19 @@ int open64(const char *filename, int flags, ...) { return real_open(filename, flags, mode); } +int __open64_2(const char *filename, int flags) { + debug(DEBUG_LEVEL_VERBOSE, __FILE__": __open64_2(%s)\n", filename?filename:"NULL"); + + if ((flags & O_CREAT) || + !filename || + !is_audio_device_node(filename)) { + LOAD___OPEN64_2_FUNC(); + return ___open64_2(filename, flags); + } + + return real_open(filename, flags, 0); +} + #endif #ifdef _STAT_VER |