mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-02 09:01:46 -05:00
Merge branch 'master' into dbus-work
Conflicts: src/daemon/daemon-conf.c
This commit is contained in:
commit
019331d25b
130 changed files with 24774 additions and 14714 deletions
|
|
@ -328,7 +328,7 @@ static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf
|
|||
static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
|
||||
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
|
||||
char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
|
||||
char s[256];
|
||||
char bytes[PA_BYTES_SNPRINT_MAX];
|
||||
const pa_mempool_stat *stat;
|
||||
unsigned k;
|
||||
pa_sink *def_sink;
|
||||
|
|
@ -352,22 +352,22 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
|
||||
pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_allocated),
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->allocated_size)));
|
||||
pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&stat->allocated_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_accumulated),
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->accumulated_size)));
|
||||
pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&stat->accumulated_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_imported),
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->imported_size)));
|
||||
pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&stat->imported_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n",
|
||||
(unsigned) pa_atomic_load(&stat->n_exported),
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->exported_size)));
|
||||
pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&stat->exported_size)));
|
||||
|
||||
pa_strbuf_printf(buf, "Total sample cache size: %s.\n",
|
||||
pa_bytes_snprint(s, sizeof(s), (unsigned) pa_scache_total_size(c)));
|
||||
pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_scache_total_size(c)));
|
||||
|
||||
pa_strbuf_printf(buf, "Default sample spec: %s\n",
|
||||
pa_sample_spec_snprint(ss, sizeof(ss), &c->default_sample_spec));
|
||||
|
|
@ -529,7 +529,7 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
|
|||
return -1;
|
||||
}
|
||||
|
||||
pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume);
|
||||
pa_cvolume_set(&cvolume, 1, volume);
|
||||
pa_sink_set_volume(sink, &cvolume, TRUE, TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -571,7 +571,7 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb
|
|||
return -1;
|
||||
}
|
||||
|
||||
pa_cvolume_set(&cvolume, si->sample_spec.channels, volume);
|
||||
pa_cvolume_set(&cvolume, 1, volume);
|
||||
pa_sink_input_set_volume(si, &cvolume, TRUE, TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -607,7 +607,7 @@ static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *
|
|||
return -1;
|
||||
}
|
||||
|
||||
pa_cvolume_set(&cvolume, source->sample_spec.channels, volume);
|
||||
pa_cvolume_set(&cvolume, 1, volume);
|
||||
pa_source_set_volume(source, &cvolume, TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1549,7 +1549,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
pa_sink *sink;
|
||||
pa_source *source;
|
||||
pa_card *card;
|
||||
int nl;
|
||||
pa_bool_t nl;
|
||||
uint32_t idx;
|
||||
char txt[256];
|
||||
time_t now;
|
||||
|
|
@ -1567,7 +1567,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
|
||||
#endif
|
||||
|
||||
for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) {
|
||||
PA_IDXSET_FOREACH(m, c->modules, idx) {
|
||||
|
||||
pa_strbuf_printf(buf, "load-module %s", m->name);
|
||||
|
||||
|
|
@ -1577,58 +1577,58 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
|
|||
pa_strbuf_puts(buf, "\n");
|
||||
}
|
||||
|
||||
nl = 0;
|
||||
|
||||
for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
|
||||
nl = FALSE;
|
||||
PA_IDXSET_FOREACH(sink, c->sinks, idx) {
|
||||
|
||||
if (!nl) {
|
||||
pa_strbuf_puts(buf, "\n");
|
||||
nl = 1;
|
||||
nl = TRUE;
|
||||
}
|
||||
|
||||
pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, FALSE)));
|
||||
pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_max(pa_sink_get_volume(sink, FALSE)));
|
||||
pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE)));
|
||||
pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED));
|
||||
}
|
||||
|
||||
for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
|
||||
nl = FALSE;
|
||||
PA_IDXSET_FOREACH(source, c->sources, idx) {
|
||||
|
||||
if (!nl) {
|
||||
pa_strbuf_puts(buf, "\n");
|
||||
nl = 1;
|
||||
nl = TRUE;
|
||||
}
|
||||
|
||||
pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source, FALSE)));
|
||||
pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_max(pa_source_get_volume(source, FALSE)));
|
||||
pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, FALSE)));
|
||||
pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED));
|
||||
}
|
||||
|
||||
for (card = pa_idxset_first(c->cards, &idx); card; card = pa_idxset_next(c->cards, &idx)) {
|
||||
nl = FALSE;
|
||||
PA_IDXSET_FOREACH(card, c->cards, idx) {
|
||||
|
||||
if (!nl) {
|
||||
pa_strbuf_puts(buf, "\n");
|
||||
nl = 1;
|
||||
nl = TRUE;
|
||||
}
|
||||
|
||||
if (card->active_profile)
|
||||
pa_strbuf_printf(buf, "set-card-profile %s %s\n", card->name, card->active_profile->name);
|
||||
}
|
||||
|
||||
nl = 0;
|
||||
|
||||
nl = FALSE;
|
||||
if ((sink = pa_namereg_get_default_sink(c))) {
|
||||
if (!nl) {
|
||||
pa_strbuf_puts(buf, "\n");
|
||||
nl = 1;
|
||||
nl = TRUE;
|
||||
}
|
||||
|
||||
pa_strbuf_printf(buf, "set-default-sink %s\n", sink->name);
|
||||
}
|
||||
|
||||
if ((source = pa_namereg_get_default_source(c))) {
|
||||
if (!nl) {
|
||||
if (!nl)
|
||||
pa_strbuf_puts(buf, "\n");
|
||||
nl = 1;
|
||||
}
|
||||
|
||||
pa_strbuf_printf(buf, "set-default-source %s\n", source->name);
|
||||
}
|
||||
|
||||
|
|
@ -1813,8 +1813,6 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_b
|
|||
|
||||
ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
|
||||
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
if (f)
|
||||
fclose(f);
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ static int parse_line(const char *filename, unsigned line, char **section, const
|
|||
return 0;
|
||||
|
||||
if (pa_startswith(b, ".include ")) {
|
||||
char *path, *fn;
|
||||
char *path = NULL, *fn;
|
||||
int r;
|
||||
|
||||
fn = strip(b+9);
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
|
|||
|
||||
pa_assert(tv);
|
||||
|
||||
/* pa_timeval_sub() saturates on underflow! */
|
||||
|
||||
if (pa_timeval_cmp(&wc_now, tv) < 0)
|
||||
pa_timeval_add(&rt_now, pa_timeval_diff(tv, &wc_now));
|
||||
else
|
||||
|
|
@ -144,13 +146,29 @@ struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
|
|||
}
|
||||
|
||||
pa_usec_t pa_timespec_load(const struct timespec *ts) {
|
||||
pa_assert(ts);
|
||||
|
||||
if (PA_UNLIKELY(!ts))
|
||||
return PA_USEC_INVALID;
|
||||
|
||||
return
|
||||
(pa_usec_t) ts->tv_sec * PA_USEC_PER_SEC +
|
||||
(pa_usec_t) ts->tv_nsec / PA_NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
struct timespec* pa_timespec_store(struct timespec *ts, pa_usec_t v) {
|
||||
pa_assert(ts);
|
||||
|
||||
if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
|
||||
ts->tv_sec = PA_INT_TYPE_MAX(time_t);
|
||||
ts->tv_nsec = (long) (PA_NSEC_PER_SEC-1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ts->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
|
||||
ts->tv_nsec = (long) ((v % PA_USEC_PER_SEC) * PA_NSEC_PER_USEC);
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
static struct timeval* wallclock_from_rtclock(struct timeval *tv) {
|
||||
|
||||
|
|
@ -162,6 +180,8 @@ static struct timeval* wallclock_from_rtclock(struct timeval *tv) {
|
|||
|
||||
pa_assert(tv);
|
||||
|
||||
/* pa_timeval_sub() saturates on underflow! */
|
||||
|
||||
if (pa_timeval_cmp(&rt_now, tv) < 0)
|
||||
pa_timeval_add(&wc_now, pa_timeval_diff(tv, &rt_now));
|
||||
else
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ void pa_rtclock_hrtimer_enable(void);
|
|||
struct timeval* pa_rtclock_from_wallclock(struct timeval *tv);
|
||||
|
||||
pa_usec_t pa_timespec_load(const struct timespec *ts);
|
||||
struct timespec* pa_timespec_store(struct timespec *ts, pa_usec_t v);
|
||||
|
||||
struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, pa_bool_t rtclock);
|
||||
|
||||
|
|
|
|||
|
|
@ -335,12 +335,12 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
|
|||
|
||||
pass_volume = TRUE;
|
||||
|
||||
if (e->volume_is_set && volume != (pa_volume_t) -1) {
|
||||
if (e->volume_is_set && volume != PA_VOLUME_INVALID) {
|
||||
pa_cvolume_set(&r, e->sample_spec.channels, volume);
|
||||
pa_sw_cvolume_multiply(&r, &r, &e->volume);
|
||||
} else if (e->volume_is_set)
|
||||
r = e->volume;
|
||||
else if (volume != (pa_volume_t) -1)
|
||||
else if (volume != PA_VOLUME_INVALID)
|
||||
pa_cvolume_set(&r, e->sample_spec.channels, volume);
|
||||
else
|
||||
pass_volume = FALSE;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@
|
|||
#include <pulsecore/thread.h>
|
||||
#include <pulsecore/strbuf.h>
|
||||
#include <pulsecore/usergroup.h>
|
||||
#include <pulsecore/strlist.h>
|
||||
|
||||
#include "core-util.h"
|
||||
|
||||
|
|
@ -124,6 +125,8 @@
|
|||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
static pa_strlist *recorded_env = NULL;
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
|
||||
#define PULSE_ROOTENV "PULSE_ROOT"
|
||||
|
|
@ -588,13 +591,13 @@ static int set_scheduler(int rtprio) {
|
|||
sp.sched_priority = rtprio;
|
||||
|
||||
#ifdef SCHED_RESET_ON_FORK
|
||||
if ((r = pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp)) == 0) {
|
||||
if (pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp) == 0) {
|
||||
pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((r = pthread_setschedparam(pthread_self(), SCHED_RR, &sp)) == 0) {
|
||||
if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == 0) {
|
||||
pa_log_debug("SCHED_RR worked.");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -609,6 +612,11 @@ static int set_scheduler(int rtprio) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* We need to disable exit on disconnect because otherwise
|
||||
* dbus_shutdown will kill us. See
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
|
||||
dbus_connection_set_exit_on_disconnect(bus, FALSE);
|
||||
|
||||
r = rtkit_make_realtime(bus, 0, rtprio);
|
||||
dbus_connection_unref(bus);
|
||||
|
||||
|
|
@ -677,6 +685,11 @@ static int set_nice(int nice_level) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* We need to disable exit on disconnect because otherwise
|
||||
* dbus_shutdown will kill us. See
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
|
||||
dbus_connection_set_exit_on_disconnect(bus, FALSE);
|
||||
|
||||
r = rtkit_make_high_priority(bus, 0, nice_level);
|
||||
dbus_connection_unref(bus);
|
||||
|
||||
|
|
@ -773,7 +786,6 @@ int pa_match(const char *expr, const char *v) {
|
|||
/* Try to parse a boolean string value.*/
|
||||
int pa_parse_boolean(const char *v) {
|
||||
const char *expr;
|
||||
int r;
|
||||
pa_assert(v);
|
||||
|
||||
/* First we check language independant */
|
||||
|
|
@ -785,12 +797,12 @@ int pa_parse_boolean(const char *v) {
|
|||
/* And then we check language dependant */
|
||||
if ((expr = nl_langinfo(YESEXPR)))
|
||||
if (expr[0])
|
||||
if ((r = pa_match(expr, v)) > 0)
|
||||
if (pa_match(expr, v) > 0)
|
||||
return 1;
|
||||
|
||||
if ((expr = nl_langinfo(NOEXPR)))
|
||||
if (expr[0])
|
||||
if ((r = pa_match(expr, v)) > 0)
|
||||
if (pa_match(expr, v) > 0)
|
||||
return 0;
|
||||
|
||||
errno = EINVAL;
|
||||
|
|
@ -1182,7 +1194,7 @@ char* pa_strip_nl(char *s) {
|
|||
|
||||
/* Create a temporary lock file and lock it. */
|
||||
int pa_lock_lockfile(const char *fn) {
|
||||
int fd = -1;
|
||||
int fd;
|
||||
pa_assert(fn);
|
||||
|
||||
for (;;) {
|
||||
|
|
@ -1225,8 +1237,6 @@ int pa_lock_lockfile(const char *fn) {
|
|||
fd = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
|
@ -1368,19 +1378,10 @@ static char* make_random_dir(mode_t m) {
|
|||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
|
||||
const char *tmpdir;
|
||||
char *fn;
|
||||
size_t pathlen;
|
||||
|
||||
if (!(tmpdir = getenv("TMPDIR")))
|
||||
if (!(tmpdir = getenv("TMP")))
|
||||
if (!(tmpdir = getenv("TEMP")))
|
||||
tmpdir = getenv("TEMPDIR");
|
||||
|
||||
if (!tmpdir || !pa_is_path_absolute(tmpdir))
|
||||
tmpdir = "/tmp";
|
||||
|
||||
fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir);
|
||||
fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
|
||||
pathlen = strlen(fn);
|
||||
|
||||
for (;;) {
|
||||
|
|
@ -2394,7 +2395,7 @@ int pa_reset_sigs(int except, ...) {
|
|||
p[i++] = except;
|
||||
|
||||
while ((sig = va_arg(ap, int)) >= 0)
|
||||
sig = p[i++];
|
||||
p[i++] = sig;
|
||||
}
|
||||
p[i] = -1;
|
||||
|
||||
|
|
@ -2451,9 +2452,38 @@ void pa_set_env(const char *key, const char *value) {
|
|||
pa_assert(key);
|
||||
pa_assert(value);
|
||||
|
||||
/* This is not thread-safe */
|
||||
|
||||
putenv(pa_sprintf_malloc("%s=%s", key, value));
|
||||
}
|
||||
|
||||
void pa_set_env_and_record(const char *key, const char *value) {
|
||||
pa_assert(key);
|
||||
pa_assert(value);
|
||||
|
||||
/* This is not thread-safe */
|
||||
|
||||
pa_set_env(key, value);
|
||||
recorded_env = pa_strlist_prepend(recorded_env, key);
|
||||
}
|
||||
|
||||
void pa_unset_env_recorded(void) {
|
||||
|
||||
/* This is not thread-safe */
|
||||
|
||||
for (;;) {
|
||||
char *s;
|
||||
|
||||
recorded_env = pa_strlist_pop(recorded_env, &s);
|
||||
|
||||
if (!s)
|
||||
break;
|
||||
|
||||
unsetenv(s);
|
||||
pa_xfree(s);
|
||||
}
|
||||
}
|
||||
|
||||
pa_bool_t pa_in_system_mode(void) {
|
||||
const char *e;
|
||||
|
||||
|
|
@ -2837,3 +2867,25 @@ pa_bool_t pa_run_from_build_tree(void) {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char *pa_get_temp_dir(void) {
|
||||
const char *t;
|
||||
|
||||
if ((t = getenv("TMPDIR")) &&
|
||||
pa_is_path_absolute(t))
|
||||
return t;
|
||||
|
||||
if ((t = getenv("TMP")) &&
|
||||
pa_is_path_absolute(t))
|
||||
return t;
|
||||
|
||||
if ((t = getenv("TEMP")) &&
|
||||
pa_is_path_absolute(t))
|
||||
return t;
|
||||
|
||||
if ((t = getenv("TEMPDIR")) &&
|
||||
pa_is_path_absolute(t))
|
||||
return t;
|
||||
|
||||
return "/tmp";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,6 +195,8 @@ int pa_reset_sigs(int except, ...);
|
|||
int pa_reset_sigsv(const int except[]);
|
||||
|
||||
void pa_set_env(const char *key, const char *value);
|
||||
void pa_set_env_and_record(const char *key, const char *value);
|
||||
void pa_unset_env_recorded(void);
|
||||
|
||||
pa_bool_t pa_in_system_mode(void);
|
||||
|
||||
|
|
@ -254,4 +256,6 @@ void pa_reset_personality(void);
|
|||
pa_bool_t pa_run_from_build_tree(void);
|
||||
#endif
|
||||
|
||||
const char *pa_get_temp_dir(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ void pa_cpu_init_x86 (void) {
|
|||
pa_remap_func_init_mmx (flags);
|
||||
}
|
||||
|
||||
if (flags & PA_CPU_X86_SSE) {
|
||||
if (flags & (PA_CPU_X86_SSE | PA_CPU_X86_SSE2)) {
|
||||
pa_volume_func_init_sse (flags);
|
||||
pa_remap_func_init_sse (flags);
|
||||
pa_convert_func_init_sse (flags);
|
||||
|
|
|
|||
|
|
@ -130,15 +130,22 @@ void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) {
|
|||
}
|
||||
|
||||
int pa_flist_push(pa_flist*l, void *p) {
|
||||
unsigned idx, n, len;
|
||||
unsigned idx, n;
|
||||
pa_atomic_ptr_t*cells;
|
||||
#ifdef PROFILE
|
||||
unsigned len;
|
||||
#endif
|
||||
|
||||
pa_assert(l);
|
||||
pa_assert(p);
|
||||
|
||||
cells = PA_FLIST_CELLS(l);
|
||||
|
||||
n = len = l->size + N_EXTRA_SCAN - (unsigned) pa_atomic_load(&l->length);
|
||||
n = l->size + N_EXTRA_SCAN - (unsigned) pa_atomic_load(&l->length);
|
||||
|
||||
#ifdef PROFILE
|
||||
len = n;
|
||||
#endif
|
||||
|
||||
_Y;
|
||||
idx = reduce(l, (unsigned) pa_atomic_load(&l->write_idx));
|
||||
|
|
@ -171,14 +178,21 @@ int pa_flist_push(pa_flist*l, void *p) {
|
|||
}
|
||||
|
||||
void* pa_flist_pop(pa_flist*l) {
|
||||
unsigned idx, len, n;
|
||||
unsigned idx, n;
|
||||
pa_atomic_ptr_t *cells;
|
||||
#ifdef PROFILE
|
||||
unsigned len;
|
||||
#endif
|
||||
|
||||
pa_assert(l);
|
||||
|
||||
cells = PA_FLIST_CELLS(l);
|
||||
|
||||
n = len = (unsigned) pa_atomic_load(&l->length) + N_EXTRA_SCAN;
|
||||
n = (unsigned) pa_atomic_load(&l->length) + N_EXTRA_SCAN;
|
||||
|
||||
#ifdef PROFILE
|
||||
len = n;
|
||||
#endif
|
||||
|
||||
_Y;
|
||||
idx = reduce(l, (unsigned) pa_atomic_load(&l->read_idx));
|
||||
|
|
|
|||
|
|
@ -304,6 +304,18 @@ typedef int pa_bool_t;
|
|||
#define pa_memzero(x,l) (memset((x), 0, (l)))
|
||||
#define pa_zero(x) (pa_memzero(&(x), sizeof(x)))
|
||||
|
||||
#define PA_INT_TYPE_SIGNED(type) (!!((type) 0 > (type) -1))
|
||||
|
||||
#define PA_INT_TYPE_MAX(type) \
|
||||
((type) (PA_INT_TYPE_SIGNED(type) \
|
||||
? ~(~(type) 0 << (8*sizeof(type)-1)) \
|
||||
: (type) -1))
|
||||
|
||||
#define PA_INT_TYPE_MIN(type) \
|
||||
((type) (PA_INT_TYPE_SIGNED(type) \
|
||||
? (~(type) 0 << (8*sizeof(type)-1)) \
|
||||
: (type) 0))
|
||||
|
||||
/* We include this at the very last place */
|
||||
#include <pulsecore/log.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -303,10 +303,17 @@ static struct mempool_slot* mempool_slot_by_ptr(pa_mempool *p, void *ptr) {
|
|||
pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
|
||||
pa_memblock *b = NULL;
|
||||
struct mempool_slot *slot;
|
||||
static int mempool_disable = 0;
|
||||
|
||||
pa_assert(p);
|
||||
pa_assert(length);
|
||||
|
||||
if (mempool_disable == 0)
|
||||
mempool_disable = getenv("PULSE_MEMPOOL_DISABLE") ? 1 : -1;
|
||||
|
||||
if (mempool_disable > 0)
|
||||
return NULL;
|
||||
|
||||
/* If -1 is passed as length we choose the size for the caller: we
|
||||
* take the largest size that fits in one of our slots. */
|
||||
|
||||
|
|
@ -361,6 +368,7 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, pa_boo
|
|||
|
||||
if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
|
||||
b = pa_xnew(pa_memblock, 1);
|
||||
|
||||
PA_REFCNT_INIT(b);
|
||||
b->pool = p;
|
||||
b->type = PA_MEMBLOCK_FIXED;
|
||||
|
|
@ -387,6 +395,7 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, pa_free
|
|||
|
||||
if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
|
||||
b = pa_xnew(pa_memblock, 1);
|
||||
|
||||
PA_REFCNT_INIT(b);
|
||||
b->pool = p;
|
||||
b->type = PA_MEMBLOCK_USER;
|
||||
|
|
@ -499,13 +508,19 @@ static void memblock_free(pa_memblock *b) {
|
|||
/* Fall through */
|
||||
|
||||
case PA_MEMBLOCK_FIXED:
|
||||
case PA_MEMBLOCK_APPENDED :
|
||||
if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0)
|
||||
pa_xfree(b);
|
||||
|
||||
break;
|
||||
|
||||
case PA_MEMBLOCK_IMPORTED : {
|
||||
case PA_MEMBLOCK_APPENDED:
|
||||
|
||||
/* We could attached it unused_memblocks, but that would
|
||||
* probably waste some considerable memory */
|
||||
pa_xfree(b);
|
||||
break;
|
||||
|
||||
case PA_MEMBLOCK_IMPORTED: {
|
||||
pa_memimport_segment *segment;
|
||||
pa_memimport *import;
|
||||
|
||||
|
|
@ -539,8 +554,7 @@ static void memblock_free(pa_memblock *b) {
|
|||
struct mempool_slot *slot;
|
||||
pa_bool_t call_free;
|
||||
|
||||
slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data));
|
||||
pa_assert(slot);
|
||||
pa_assert_se(slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data)));
|
||||
|
||||
call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL;
|
||||
|
||||
|
|
@ -694,7 +708,7 @@ static void memblock_replace_import(pa_memblock *b) {
|
|||
|
||||
pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size) {
|
||||
pa_mempool *p;
|
||||
char t1[64], t2[64];
|
||||
char t1[PA_BYTES_SNPRINT_MAX], t2[PA_BYTES_SNPRINT_MAX];
|
||||
|
||||
p = pa_xnew(pa_mempool, 1);
|
||||
|
||||
|
|
@ -891,7 +905,7 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) {
|
|||
if (pa_hashmap_size(i->segments) >= PA_MEMIMPORT_SEGMENTS_MAX)
|
||||
return NULL;
|
||||
|
||||
seg = pa_xnew(pa_memimport_segment, 1);
|
||||
seg = pa_xnew0(pa_memimport_segment, 1);
|
||||
|
||||
if (pa_shm_attach_ro(&seg->memory, shm_id) < 0) {
|
||||
pa_xfree(seg);
|
||||
|
|
@ -899,10 +913,9 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) {
|
|||
}
|
||||
|
||||
seg->import = i;
|
||||
seg->n_blocks = 0;
|
||||
seg->trap = pa_memtrap_add(seg->memory.ptr, seg->memory.size);
|
||||
|
||||
pa_hashmap_put(i->segments, PA_UINT32_TO_PTR(shm_id), seg);
|
||||
pa_hashmap_put(i->segments, PA_UINT32_TO_PTR(seg->memory.id), seg);
|
||||
return seg;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,10 @@ static void memtrap_link(pa_memtrap *m, unsigned j) {
|
|||
pa_assert(m);
|
||||
|
||||
m->prev[j] = NULL;
|
||||
m->next[j] = memtraps[j];
|
||||
|
||||
if ((m->next[j] = memtraps[j]))
|
||||
m->next[j]->prev[j] = m;
|
||||
|
||||
memtraps[j] = m;
|
||||
}
|
||||
|
||||
|
|
@ -200,13 +203,13 @@ pa_memtrap *pa_memtrap_update(pa_memtrap *m, const void *start, size_t size) {
|
|||
goto unlock;
|
||||
|
||||
memtrap_unlink(m, j);
|
||||
j = pa_aupdate_write_swap(aupdate);
|
||||
pa_aupdate_write_swap(aupdate);
|
||||
|
||||
m->start = (void*) start;
|
||||
m->size = size;
|
||||
pa_atomic_store(&m->bad, 0);
|
||||
|
||||
j = pa_aupdate_write_swap(aupdate);
|
||||
pa_assert_se(pa_aupdate_write_swap(aupdate) == j);
|
||||
memtrap_link(m, j);
|
||||
|
||||
unlock:
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ char* pa_namereg_make_valid_name(const char *name) {
|
|||
if (*name == 0)
|
||||
return NULL;
|
||||
|
||||
n = pa_xmalloc(strlen(name)+1);
|
||||
n = pa_xnew(char, strlen(name)+1);
|
||||
|
||||
for (a = name, b = n; *a && (a-name < PA_NAME_MAX); a++, b++)
|
||||
*b = (char) (is_valid_char(*a) ? *a : '_');
|
||||
|
|
@ -170,6 +170,17 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t
|
|||
|
||||
pa_assert_se(pa_hashmap_put(c->namereg, e->name, e) >= 0);
|
||||
|
||||
/* If a sink or source is registered and there was none registered
|
||||
* before we inform the clients which then can ask for the default
|
||||
* sink/source which is then assigned. We don't adjust the default
|
||||
* sink/source here right away to give the module the chance to
|
||||
* register more sinks/sources before we choose a new default
|
||||
* sink/source. */
|
||||
|
||||
if ((!c->default_sink && type == PA_NAMEREG_SINK) ||
|
||||
(!c->default_source && type == PA_NAMEREG_SOURCE))
|
||||
pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
|
||||
|
||||
return e->name;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ static pid_t read_pid(const char *fn, int fd) {
|
|||
}
|
||||
|
||||
static int open_pid_file(const char *fn, int mode) {
|
||||
int fd = -1;
|
||||
int fd;
|
||||
|
||||
pa_assert(fn);
|
||||
|
||||
|
|
@ -123,8 +123,6 @@ static int open_pid_file(const char *fn, int mode) {
|
|||
fd = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
|
|
|||
|
|
@ -771,7 +771,6 @@ static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void *
|
|||
|
||||
memcpy(&rvolume, data, sizeof(uint32_t));
|
||||
rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
|
||||
data = (const char*)data + sizeof(uint32_t);
|
||||
|
||||
if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx)) && conn->sink_input) {
|
||||
pa_cvolume volume;
|
||||
|
|
@ -809,7 +808,6 @@ static int esd_proto_sample_pan(connection *c, esd_proto_t request, const void *
|
|||
|
||||
memcpy(&rvolume, data, sizeof(uint32_t));
|
||||
rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
|
||||
data = (const char*)data + sizeof(uint32_t);
|
||||
|
||||
volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
|
||||
volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
|
||||
|
|
@ -1123,7 +1121,7 @@ static int do_read(connection *c) {
|
|||
ssize_t r;
|
||||
size_t l;
|
||||
void *p;
|
||||
size_t space;
|
||||
size_t space = 0;
|
||||
|
||||
pa_assert(c->input_memblockq);
|
||||
|
||||
|
|
|
|||
|
|
@ -628,7 +628,6 @@ static record_stream* record_stream_new(
|
|||
|
||||
record_stream *s;
|
||||
pa_source_output *source_output = NULL;
|
||||
size_t base;
|
||||
pa_source_output_new_data data;
|
||||
|
||||
pa_assert(c);
|
||||
|
|
@ -682,7 +681,7 @@ static record_stream* record_stream_new(
|
|||
0,
|
||||
s->buffer_attr.maxlength,
|
||||
0,
|
||||
base = pa_frame_size(&source_output->sample_spec),
|
||||
pa_frame_size(&source_output->sample_spec),
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
|
|
@ -827,24 +826,26 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
|
|||
pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
|
||||
break;
|
||||
|
||||
case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH: {
|
||||
pa_tagstruct *t;
|
||||
case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH:
|
||||
|
||||
s->buffer_attr.tlength = (uint32_t) offset;
|
||||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
|
||||
pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
|
||||
pa_tagstruct_putu32(t, s->index);
|
||||
pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
|
||||
pa_tagstruct_putu32(t, s->buffer_attr.tlength);
|
||||
pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
|
||||
pa_tagstruct_putu32(t, s->buffer_attr.minreq);
|
||||
pa_tagstruct_put_usec(t, s->configured_sink_latency);
|
||||
pa_pstream_send_tagstruct(s->connection->pstream, t);
|
||||
if (s->connection->version >= 15) {
|
||||
pa_tagstruct *t;
|
||||
|
||||
t = pa_tagstruct_new(NULL, 0);
|
||||
pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
|
||||
pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
|
||||
pa_tagstruct_putu32(t, s->index);
|
||||
pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
|
||||
pa_tagstruct_putu32(t, s->buffer_attr.tlength);
|
||||
pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
|
||||
pa_tagstruct_putu32(t, s->buffer_attr.minreq);
|
||||
pa_tagstruct_put_usec(t, s->configured_sink_latency);
|
||||
pa_pstream_send_tagstruct(s->connection->pstream, t);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -2274,6 +2275,8 @@ static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
|
|||
ret = pa_core_exit(c->protocol->core, FALSE, 0);
|
||||
CHECK_VALIDITY(c->pstream, ret >= 0, tag, PA_ERR_ACCESS);
|
||||
|
||||
pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)));
|
||||
|
||||
pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
|
||||
}
|
||||
|
||||
|
|
@ -3390,12 +3393,18 @@ static void command_set_volume(
|
|||
client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
|
||||
|
||||
if (sink) {
|
||||
CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &sink->sample_spec), tag, PA_ERR_INVALID);
|
||||
|
||||
pa_log_debug("Client %s changes volume of sink %s.", client_name, sink->name);
|
||||
pa_sink_set_volume(sink, &volume, TRUE, TRUE);
|
||||
} else if (source) {
|
||||
CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &source->sample_spec), tag, PA_ERR_INVALID);
|
||||
|
||||
pa_log_debug("Client %s changes volume of source %s.", client_name, source->name);
|
||||
pa_source_set_volume(source, &volume, TRUE);
|
||||
} else if (si) {
|
||||
CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &si->sample_spec), tag, PA_ERR_INVALID);
|
||||
|
||||
pa_log_debug("Client %s changes volume of sink input %s.",
|
||||
client_name,
|
||||
pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
|
||||
|
|
@ -3441,7 +3450,6 @@ static void command_set_mute(
|
|||
switch (command) {
|
||||
|
||||
case PA_COMMAND_SET_SINK_MUTE:
|
||||
|
||||
if (idx != PA_INVALID_INDEX)
|
||||
sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ static int do_read(connection *c) {
|
|||
ssize_t r;
|
||||
size_t l;
|
||||
void *p;
|
||||
size_t space;
|
||||
size_t space = 0;
|
||||
|
||||
connection_assert_ref(c);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,21 +26,31 @@
|
|||
#include <pulsecore/macro.h>
|
||||
|
||||
typedef struct pa_ratelimit {
|
||||
const pa_usec_t interval;
|
||||
const unsigned burst;
|
||||
pa_usec_t interval;
|
||||
unsigned burst;
|
||||
unsigned n_printed, n_missed;
|
||||
pa_usec_t begin;
|
||||
} pa_ratelimit;
|
||||
|
||||
#define PA_DEFINE_RATELIMIT(_name, _interval, _burst) \
|
||||
pa_ratelimit _name = { \
|
||||
.interval = _interval, \
|
||||
.burst = _burst, \
|
||||
.interval = (_interval), \
|
||||
.burst = (_burst), \
|
||||
.n_printed = 0, \
|
||||
.n_missed = 0, \
|
||||
.begin = 0 \
|
||||
}
|
||||
|
||||
#define PA_INIT_RATELIMIT(v, _interval, _burst) \
|
||||
do { \
|
||||
pa_ratelimit *r = &(v); \
|
||||
r->interval = (_interval); \
|
||||
r->burst = (_burst); \
|
||||
r->n_printed = 0; \
|
||||
r->n_missed = 0; \
|
||||
r->begin = 0; \
|
||||
} while (FALSE);
|
||||
|
||||
pa_bool_t pa_ratelimit_test(pa_ratelimit *r);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -65,16 +65,24 @@
|
|||
" add $32, %1 \n\t" \
|
||||
" add $64, %0 \n\t"
|
||||
|
||||
#define HANDLE_SINGLE(s) \
|
||||
#define HANDLE_SINGLE_dq() \
|
||||
" movd (%1), %%mm0 \n\t" \
|
||||
" punpckl"#s" %%mm0, %%mm0 \n\t" \
|
||||
" punpckldq %%mm0, %%mm0 \n\t" \
|
||||
" movq %%mm0, (%0) \n\t" \
|
||||
" add $4, %1 \n\t" \
|
||||
" add $8, %0 \n\t"
|
||||
|
||||
#define MONO_TO_STEREO(s) \
|
||||
" mov %3, %2 \n\t" \
|
||||
" sar $3, %2 \n\t" \
|
||||
#define HANDLE_SINGLE_wd() \
|
||||
" movw (%1), %w3 \n\t" \
|
||||
" movd %3, %%mm0 \n\t" \
|
||||
" punpcklwd %%mm0, %%mm0 \n\t" \
|
||||
" movd %%mm0, (%0) \n\t" \
|
||||
" add $2, %1 \n\t" \
|
||||
" add $4, %0 \n\t"
|
||||
|
||||
#define MONO_TO_STEREO(s,shift,mask) \
|
||||
" mov %4, %2 \n\t" \
|
||||
" sar $"#shift", %2 \n\t" \
|
||||
" cmp $0, %2 \n\t" \
|
||||
" je 2f \n\t" \
|
||||
"1: \n\t" \
|
||||
|
|
@ -84,11 +92,11 @@
|
|||
" dec %2 \n\t" \
|
||||
" jne 1b \n\t" \
|
||||
"2: \n\t" \
|
||||
" mov %3, %2 \n\t" \
|
||||
" and $7, %2 \n\t" \
|
||||
" mov %4, %2 \n\t" \
|
||||
" and $"#mask", %2 \n\t" \
|
||||
" je 4f \n\t" \
|
||||
"3: \n\t" \
|
||||
HANDLE_SINGLE(s) \
|
||||
HANDLE_SINGLE_##s() \
|
||||
" dec %2 \n\t" \
|
||||
" jne 3b \n\t" \
|
||||
"4: \n\t" \
|
||||
|
|
@ -96,14 +104,14 @@
|
|||
|
||||
#if defined (__i386__) || defined (__amd64__)
|
||||
static void remap_mono_to_stereo_mmx (pa_remap_t *m, void *dst, const void *src, unsigned n) {
|
||||
pa_reg_x86 temp;
|
||||
pa_reg_x86 temp, temp2;
|
||||
|
||||
switch (*m->format) {
|
||||
case PA_SAMPLE_FLOAT32NE:
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
MONO_TO_STEREO(dq) /* do doubles to quads */
|
||||
: "+r" (dst), "+r" (src), "=&r" (temp)
|
||||
MONO_TO_STEREO(dq,3,7) /* do doubles to quads */
|
||||
: "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
|
||||
: "r" ((pa_reg_x86)n)
|
||||
: "cc"
|
||||
);
|
||||
|
|
@ -112,8 +120,8 @@ static void remap_mono_to_stereo_mmx (pa_remap_t *m, void *dst, const void *src,
|
|||
case PA_SAMPLE_S16NE:
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
MONO_TO_STEREO(wd) /* do words to doubles */
|
||||
: "+r" (dst), "+r" (src), "=&r" (temp)
|
||||
MONO_TO_STEREO(wd,4,15) /* do words to doubles */
|
||||
: "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
|
||||
: "r" ((pa_reg_x86)n)
|
||||
: "cc"
|
||||
);
|
||||
|
|
@ -142,8 +150,12 @@ static void init_remap_mmx (pa_remap_t *m) {
|
|||
|
||||
void pa_remap_func_init_mmx (pa_cpu_x86_flag_t flags) {
|
||||
#if defined (__i386__) || defined (__amd64__)
|
||||
pa_log_info("Initialising MMX optimized remappers.");
|
||||
|
||||
pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_mmx);
|
||||
if (flags & PA_CPU_X86_MMX) {
|
||||
pa_log_info("Initialising MMX optimized remappers.");
|
||||
|
||||
pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_mmx);
|
||||
}
|
||||
|
||||
#endif /* defined (__i386__) || defined (__amd64__) */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,43 +65,52 @@
|
|||
" add $64, %1 \n\t" \
|
||||
" add $128, %0 \n\t"
|
||||
|
||||
#define HANDLE_SINGLE(s) \
|
||||
#define HANDLE_SINGLE_dq() \
|
||||
" movd (%1), %%xmm0 \n\t" \
|
||||
" punpckl"#s" %%xmm0, %%xmm0 \n\t" \
|
||||
" punpckldq %%xmm0, %%xmm0 \n\t" \
|
||||
" movq %%xmm0, (%0) \n\t" \
|
||||
" add $4, %1 \n\t" \
|
||||
" add $8, %0 \n\t"
|
||||
|
||||
#define MONO_TO_STEREO(s) \
|
||||
" mov %3, %2 \n\t" \
|
||||
" sar $4, %2 \n\t" \
|
||||
" cmp $0, %2 \n\t" \
|
||||
" je 2f \n\t" \
|
||||
"1: \n\t" \
|
||||
LOAD_SAMPLES \
|
||||
UNPACK_SAMPLES(s) \
|
||||
STORE_SAMPLES \
|
||||
" dec %2 \n\t" \
|
||||
" jne 1b \n\t" \
|
||||
"2: \n\t" \
|
||||
" mov %3, %2 \n\t" \
|
||||
" and $15, %2 \n\t" \
|
||||
" je 4f \n\t" \
|
||||
"3: \n\t" \
|
||||
HANDLE_SINGLE(s) \
|
||||
" dec %2 \n\t" \
|
||||
" jne 3b \n\t" \
|
||||
#define HANDLE_SINGLE_wd() \
|
||||
" movw (%1), %w3 \n\t" \
|
||||
" movd %3, %%xmm0 \n\t" \
|
||||
" punpcklwd %%xmm0, %%xmm0 \n\t" \
|
||||
" movd %%xmm0, (%0) \n\t" \
|
||||
" add $2, %1 \n\t" \
|
||||
" add $4, %0 \n\t"
|
||||
|
||||
#define MONO_TO_STEREO(s,shift,mask) \
|
||||
" mov %4, %2 \n\t" \
|
||||
" sar $"#shift", %2 \n\t" \
|
||||
" cmp $0, %2 \n\t" \
|
||||
" je 2f \n\t" \
|
||||
"1: \n\t" \
|
||||
LOAD_SAMPLES \
|
||||
UNPACK_SAMPLES(s) \
|
||||
STORE_SAMPLES \
|
||||
" dec %2 \n\t" \
|
||||
" jne 1b \n\t" \
|
||||
"2: \n\t" \
|
||||
" mov %4, %2 \n\t" \
|
||||
" and $"#mask", %2 \n\t" \
|
||||
" je 4f \n\t" \
|
||||
"3: \n\t" \
|
||||
HANDLE_SINGLE_##s() \
|
||||
" dec %2 \n\t" \
|
||||
" jne 3b \n\t" \
|
||||
"4: \n\t"
|
||||
|
||||
static void remap_mono_to_stereo_sse (pa_remap_t *m, void *dst, const void *src, unsigned n) {
|
||||
pa_reg_x86 temp;
|
||||
#if defined (__i386__) || defined (__amd64__)
|
||||
static void remap_mono_to_stereo_sse2 (pa_remap_t *m, void *dst, const void *src, unsigned n) {
|
||||
pa_reg_x86 temp, temp2;
|
||||
|
||||
switch (*m->format) {
|
||||
case PA_SAMPLE_FLOAT32NE:
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
MONO_TO_STEREO(dq) /* do doubles to quads */
|
||||
: "+r" (dst), "+r" (src), "=&r" (temp)
|
||||
MONO_TO_STEREO(dq, 4, 15) /* do doubles to quads */
|
||||
: "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
|
||||
: "r" ((pa_reg_x86)n)
|
||||
: "cc"
|
||||
);
|
||||
|
|
@ -110,8 +119,8 @@ static void remap_mono_to_stereo_sse (pa_remap_t *m, void *dst, const void *src,
|
|||
case PA_SAMPLE_S16NE:
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
MONO_TO_STEREO(wd) /* do words to doubles */
|
||||
: "+r" (dst), "+r" (src), "=&r" (temp)
|
||||
MONO_TO_STEREO(wd, 5, 31) /* do words to doubles */
|
||||
: "+r" (dst), "+r" (src), "=&r" (temp), "=&r" (temp2)
|
||||
: "r" ((pa_reg_x86)n)
|
||||
: "cc"
|
||||
);
|
||||
|
|
@ -123,7 +132,7 @@ static void remap_mono_to_stereo_sse (pa_remap_t *m, void *dst, const void *src,
|
|||
}
|
||||
|
||||
/* set the function that will execute the remapping based on the matrices */
|
||||
static void init_remap_sse (pa_remap_t *m) {
|
||||
static void init_remap_sse2 (pa_remap_t *m) {
|
||||
unsigned n_oc, n_ic;
|
||||
|
||||
n_oc = m->o_ss->channels;
|
||||
|
|
@ -132,15 +141,19 @@ static void init_remap_sse (pa_remap_t *m) {
|
|||
/* find some common channel remappings, fall back to full matrix operation. */
|
||||
if (n_ic == 1 && n_oc == 2 &&
|
||||
m->map_table_f[0][0] >= 1.0 && m->map_table_f[1][0] >= 1.0) {
|
||||
m->do_remap = (pa_do_remap_func_t) remap_mono_to_stereo_sse;
|
||||
m->do_remap = (pa_do_remap_func_t) remap_mono_to_stereo_sse2;
|
||||
pa_log_info("Using SSE mono to stereo remapping");
|
||||
}
|
||||
}
|
||||
#endif /* defined (__i386__) || defined (__amd64__) */
|
||||
|
||||
void pa_remap_func_init_sse (pa_cpu_x86_flag_t flags) {
|
||||
#if defined (__i386__) || defined (__amd64__)
|
||||
pa_log_info("Initialising SSE optimized remappers.");
|
||||
|
||||
pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_sse);
|
||||
if (flags & PA_CPU_X86_SSE2) {
|
||||
pa_log_info("Initialising SSE2 optimized remappers.");
|
||||
pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_sse2);
|
||||
}
|
||||
|
||||
#endif /* defined (__i386__) || defined (__amd64__) */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1056,3 +1056,13 @@ void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned
|
|||
calc_sine(p, c->length, freq * l / rate);
|
||||
pa_memblock_release(c->memblock);
|
||||
}
|
||||
|
||||
size_t pa_convert_size(size_t size, const pa_sample_spec *from, const pa_sample_spec *to) {
|
||||
pa_usec_t usec;
|
||||
|
||||
pa_assert(from);
|
||||
pa_assert(to);
|
||||
|
||||
usec = pa_bytes_to_usec_round_up(size, from);
|
||||
return pa_usec_to_bytes_round_up(usec, to);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ typedef void (*pa_do_volume_func_t) (void *samples, void *volumes, unsigned chan
|
|||
pa_do_volume_func_t pa_get_volume_func(pa_sample_format_t f);
|
||||
void pa_set_volume_func(pa_sample_format_t f, pa_do_volume_func_t func);
|
||||
|
||||
size_t pa_convert_size(size_t size, const pa_sample_spec *from, const pa_sample_spec *to);
|
||||
|
||||
#define PA_CHANNEL_POSITION_MASK_LEFT \
|
||||
(PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT) \
|
||||
| PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_LEFT) \
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ static void pa_sconv_s16le_from_f32ne_sse(unsigned n, const float *a, int16_t *b
|
|||
|
||||
"2: \n\t"
|
||||
" mov %4, %1 \n\t" /* prepare for leftovers */
|
||||
" and $15, %1 \n\t"
|
||||
" and $7, %1 \n\t"
|
||||
" je 4f \n\t"
|
||||
|
||||
"3: \n\t"
|
||||
|
|
@ -142,7 +142,7 @@ static void pa_sconv_s16le_from_f32ne_sse2(unsigned n, const float *a, int16_t *
|
|||
|
||||
"2: \n\t"
|
||||
" mov %4, %1 \n\t" /* prepare for leftovers */
|
||||
" and $15, %1 \n\t"
|
||||
" and $7, %1 \n\t"
|
||||
" je 4f \n\t"
|
||||
|
||||
"3: \n\t"
|
||||
|
|
@ -218,16 +218,18 @@ static void run_test (void) {
|
|||
|
||||
void pa_convert_func_init_sse (pa_cpu_x86_flag_t flags) {
|
||||
#if defined (__i386__) || defined (__amd64__)
|
||||
pa_log_info("Initialising SSE optimized conversions.");
|
||||
|
||||
#ifdef RUN_TEST
|
||||
run_test ();
|
||||
#endif
|
||||
|
||||
if (flags & PA_CPU_X86_SSE2)
|
||||
pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse2);
|
||||
else
|
||||
pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse);
|
||||
if (flags & PA_CPU_X86_SSE2) {
|
||||
pa_log_info("Initialising SSE2 optimized conversions.");
|
||||
pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse2);
|
||||
} else {
|
||||
pa_log_info("Initialising SSE optimized conversions.");
|
||||
pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse);
|
||||
}
|
||||
|
||||
#endif /* defined (__i386__) || defined (__amd64__) */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,18 @@ void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, co
|
|||
}
|
||||
}
|
||||
|
||||
void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) {
|
||||
pa_assert(data);
|
||||
pa_assert(volume_factor);
|
||||
|
||||
if (data->volume_factor_sink_is_set)
|
||||
pa_sw_cvolume_multiply(&data->volume_factor_sink, &data->volume_factor_sink, volume_factor);
|
||||
else {
|
||||
data->volume_factor_sink_is_set = TRUE;
|
||||
data->volume_factor_sink = *volume_factor;
|
||||
}
|
||||
}
|
||||
|
||||
void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
|
||||
pa_assert(data);
|
||||
|
||||
|
|
@ -141,6 +153,7 @@ int pa_sink_input_new(
|
|||
char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
|
||||
pa_channel_map original_cm;
|
||||
int r;
|
||||
char *pt;
|
||||
|
||||
pa_assert(_i);
|
||||
pa_assert(core);
|
||||
|
|
@ -176,7 +189,6 @@ int pa_sink_input_new(
|
|||
pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
|
||||
}
|
||||
|
||||
pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID);
|
||||
pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
|
||||
|
||||
if (!data->volume_is_set) {
|
||||
|
|
@ -185,15 +197,18 @@ int pa_sink_input_new(
|
|||
data->save_volume = FALSE;
|
||||
}
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(&data->volume), -PA_ERR_INVALID);
|
||||
pa_return_val_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec), -PA_ERR_INVALID);
|
||||
|
||||
if (!data->volume_factor_is_set)
|
||||
pa_cvolume_reset(&data->volume_factor, data->sample_spec.channels);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_valid(&data->volume_factor), -PA_ERR_INVALID);
|
||||
pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor, &data->sample_spec), -PA_ERR_INVALID);
|
||||
|
||||
if (!data->volume_factor_sink_is_set)
|
||||
pa_cvolume_reset(&data->volume_factor_sink, data->sink->sample_spec.channels);
|
||||
|
||||
pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor_sink, &data->sink->sample_spec), -PA_ERR_INVALID);
|
||||
|
||||
if (!data->muted_is_set)
|
||||
data->muted = FALSE;
|
||||
|
||||
|
|
@ -283,6 +298,7 @@ int pa_sink_input_new(
|
|||
i->volume = data->volume;
|
||||
|
||||
i->volume_factor = data->volume_factor;
|
||||
i->volume_factor_sink = data->volume_factor_sink;
|
||||
i->real_ratio = i->reference_ratio = data->volume;
|
||||
pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
|
||||
pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
|
||||
|
|
@ -338,12 +354,15 @@ int pa_sink_input_new(
|
|||
if (i->client)
|
||||
pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
|
||||
|
||||
pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s",
|
||||
pt = pa_proplist_to_string_sep(i->proplist, "\n ");
|
||||
pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
|
||||
i->index,
|
||||
pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
|
||||
i->sink->name,
|
||||
pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
|
||||
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map));
|
||||
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
|
||||
pt);
|
||||
pa_xfree(pt);
|
||||
|
||||
/* Don't forget to call pa_sink_input_put! */
|
||||
|
||||
|
|
@ -576,7 +595,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
|
|||
|
||||
/* Called from thread context */
|
||||
void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
|
||||
pa_bool_t do_volume_adj_here;
|
||||
pa_bool_t do_volume_adj_here, need_volume_factor_sink;
|
||||
pa_bool_t volume_is_norm;
|
||||
size_t block_size_max_sink, block_size_max_sink_input;
|
||||
size_t ilength;
|
||||
|
|
@ -624,6 +643,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
|
|||
|
||||
do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
|
||||
volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;
|
||||
need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);
|
||||
|
||||
while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
|
||||
pa_memchunk tchunk;
|
||||
|
|
@ -655,6 +675,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
|
|||
|
||||
while (tchunk.length > 0) {
|
||||
pa_memchunk wchunk;
|
||||
pa_bool_t nvfs = need_volume_factor_sink;
|
||||
|
||||
wchunk = tchunk;
|
||||
pa_memblock_ref(wchunk.memblock);
|
||||
|
|
@ -666,18 +687,41 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p
|
|||
if (do_volume_adj_here && !volume_is_norm) {
|
||||
pa_memchunk_make_writable(&wchunk, 0);
|
||||
|
||||
if (i->thread_info.muted)
|
||||
if (i->thread_info.muted) {
|
||||
pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
|
||||
else
|
||||
nvfs = FALSE;
|
||||
|
||||
} else if (!i->thread_info.resampler && nvfs) {
|
||||
pa_cvolume v;
|
||||
|
||||
/* If we don't need a resampler we can merge the
|
||||
* post and the pre volume adjustment into one */
|
||||
|
||||
pa_sw_cvolume_multiply(&v, &i->thread_info.soft_volume, &i->volume_factor_sink);
|
||||
pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &v);
|
||||
nvfs = FALSE;
|
||||
|
||||
} else
|
||||
pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);
|
||||
}
|
||||
|
||||
if (!i->thread_info.resampler)
|
||||
if (!i->thread_info.resampler) {
|
||||
|
||||
if (nvfs) {
|
||||
pa_memchunk_make_writable(&wchunk, 0);
|
||||
pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
|
||||
}
|
||||
|
||||
pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
|
||||
else {
|
||||
} else {
|
||||
pa_memchunk rchunk;
|
||||
pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
|
||||
|
||||
if (nvfs) {
|
||||
pa_memchunk_make_writable(&rchunk, 0);
|
||||
pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
|
||||
}
|
||||
|
||||
/* pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */
|
||||
|
||||
if (rchunk.memblock) {
|
||||
|
|
@ -941,12 +985,22 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo
|
|||
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
|
||||
pa_assert(volume);
|
||||
pa_assert(pa_cvolume_valid(volume));
|
||||
pa_assert(pa_cvolume_compatible(volume, &i->sample_spec));
|
||||
pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
|
||||
|
||||
if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) {
|
||||
v = i->sink->reference_volume;
|
||||
pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
|
||||
volume = pa_sw_cvolume_multiply(&v, &v, volume);
|
||||
|
||||
if (pa_cvolume_compatible(volume, &i->sample_spec))
|
||||
volume = pa_sw_cvolume_multiply(&v, &v, volume);
|
||||
else
|
||||
volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume));
|
||||
} else {
|
||||
|
||||
if (!pa_cvolume_compatible(volume, &i->sample_spec)) {
|
||||
v = i->volume;
|
||||
volume = pa_cvolume_scale(&v, pa_cvolume_max(volume));
|
||||
}
|
||||
}
|
||||
|
||||
if (pa_cvolume_equal(volume, &i->volume)) {
|
||||
|
|
@ -1142,7 +1196,6 @@ pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
|
|||
/* Called from main context */
|
||||
int pa_sink_input_start_move(pa_sink_input *i) {
|
||||
pa_source_output *o, *p = NULL;
|
||||
pa_sink *origin;
|
||||
int r;
|
||||
|
||||
pa_sink_input_assert_ref(i);
|
||||
|
|
@ -1156,8 +1209,6 @@ int pa_sink_input_start_move(pa_sink_input *i) {
|
|||
if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
|
||||
return r;
|
||||
|
||||
origin = i->sink;
|
||||
|
||||
/* Kill directly connected outputs */
|
||||
while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
|
||||
pa_assert(o != p);
|
||||
|
|
@ -1179,6 +1230,7 @@ int pa_sink_input_start_move(pa_sink_input *i) {
|
|||
pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
|
||||
|
||||
pa_sink_update_status(i->sink);
|
||||
pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);
|
||||
i->sink = NULL;
|
||||
|
||||
pa_sink_input_unref(i);
|
||||
|
|
@ -1233,6 +1285,8 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
|
|||
i->save_sink = save;
|
||||
pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
|
||||
|
||||
pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map);
|
||||
|
||||
if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
|
||||
i->sink->n_corked++;
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ struct pa_sink_input {
|
|||
pa_cvolume volume_factor; /* An internally used volume factor that can be used by modules to apply effects and suchlike without having that visible to the outside */
|
||||
pa_cvolume soft_volume; /* The internal software volume we apply to all PCM data while it passes through. Usually calculated as real_ratio * volume_factor */
|
||||
|
||||
pa_cvolume volume_factor_sink; /* A second volume factor in format of the sink this stream is connected to */
|
||||
|
||||
pa_bool_t muted:1;
|
||||
|
||||
/* if TRUE then the source we are connected to and/or the volume
|
||||
|
|
@ -273,13 +275,13 @@ typedef struct pa_sink_input_new_data {
|
|||
pa_sample_spec sample_spec;
|
||||
pa_channel_map channel_map;
|
||||
|
||||
pa_cvolume volume, volume_factor;
|
||||
pa_cvolume volume, volume_factor, volume_factor_sink;
|
||||
pa_bool_t muted:1;
|
||||
|
||||
pa_bool_t sample_spec_is_set:1;
|
||||
pa_bool_t channel_map_is_set:1;
|
||||
|
||||
pa_bool_t volume_is_set:1, volume_factor_is_set:1;
|
||||
pa_bool_t volume_is_set:1, volume_factor_is_set:1, volume_factor_sink_is_set:1;
|
||||
pa_bool_t muted_is_set:1;
|
||||
|
||||
pa_bool_t volume_is_absolute:1;
|
||||
|
|
@ -292,6 +294,7 @@ void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const
|
|||
void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map);
|
||||
void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume);
|
||||
void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, const pa_cvolume *volume_factor);
|
||||
void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor);
|
||||
void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute);
|
||||
void pa_sink_input_new_data_done(pa_sink_input_new_data *data);
|
||||
|
||||
|
|
|
|||
|
|
@ -778,7 +778,7 @@ static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, uns
|
|||
/* Called from IO thread context */
|
||||
static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *result) {
|
||||
pa_sink_input *i;
|
||||
void *state = NULL;
|
||||
void *state;
|
||||
unsigned p = 0;
|
||||
unsigned n_unreffed = 0;
|
||||
|
||||
|
|
@ -790,7 +790,7 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *
|
|||
|
||||
/* We optimize for the case where the order of the inputs has not changed */
|
||||
|
||||
while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
|
||||
PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
|
||||
unsigned j;
|
||||
pa_mix_info* m = NULL;
|
||||
|
||||
|
|
@ -884,8 +884,6 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
|
|||
pa_assert(pa_frame_aligned(length, &s->sample_spec));
|
||||
pa_assert(result);
|
||||
|
||||
pa_sink_ref(s);
|
||||
|
||||
pa_assert(!s->thread_info.rewind_requested);
|
||||
pa_assert(s->thread_info.rewind_nbytes == 0);
|
||||
|
||||
|
|
@ -896,6 +894,8 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
|
|||
return;
|
||||
}
|
||||
|
||||
pa_sink_ref(s);
|
||||
|
||||
if (length <= 0)
|
||||
length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
|
||||
|
||||
|
|
@ -973,8 +973,6 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
|
|||
pa_assert(target->length > 0);
|
||||
pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
|
||||
|
||||
pa_sink_ref(s);
|
||||
|
||||
pa_assert(!s->thread_info.rewind_requested);
|
||||
pa_assert(s->thread_info.rewind_nbytes == 0);
|
||||
|
||||
|
|
@ -983,6 +981,8 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
|
|||
return;
|
||||
}
|
||||
|
||||
pa_sink_ref(s);
|
||||
|
||||
length = target->length;
|
||||
block_size_max = pa_mempool_block_size_max(s->core->mempool);
|
||||
if (length > block_size_max)
|
||||
|
|
@ -1057,11 +1057,16 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
|
|||
pa_assert(target->length > 0);
|
||||
pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
|
||||
|
||||
pa_sink_ref(s);
|
||||
|
||||
pa_assert(!s->thread_info.rewind_requested);
|
||||
pa_assert(s->thread_info.rewind_nbytes == 0);
|
||||
|
||||
if (s->thread_info.state == PA_SINK_SUSPENDED) {
|
||||
pa_silence_memchunk(target, &s->sample_spec);
|
||||
return;
|
||||
}
|
||||
|
||||
pa_sink_ref(s);
|
||||
|
||||
l = target->length;
|
||||
d = 0;
|
||||
while (l > 0) {
|
||||
|
|
@ -1080,10 +1085,6 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
|
|||
|
||||
/* Called from IO thread context */
|
||||
void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
|
||||
pa_mix_info info[MAX_MIX_CHANNELS];
|
||||
size_t length1st = length;
|
||||
unsigned n;
|
||||
|
||||
pa_sink_assert_ref(s);
|
||||
pa_sink_assert_io_context(s);
|
||||
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
|
||||
|
|
@ -1091,81 +1092,24 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
|
|||
pa_assert(pa_frame_aligned(length, &s->sample_spec));
|
||||
pa_assert(result);
|
||||
|
||||
pa_sink_ref(s);
|
||||
|
||||
pa_assert(!s->thread_info.rewind_requested);
|
||||
pa_assert(s->thread_info.rewind_nbytes == 0);
|
||||
|
||||
pa_assert(length > 0);
|
||||
pa_sink_ref(s);
|
||||
|
||||
n = fill_mix_info(s, &length1st, info, MAX_MIX_CHANNELS);
|
||||
|
||||
if (n == 0) {
|
||||
pa_silence_memchunk_get(&s->core->silence_cache,
|
||||
s->core->mempool,
|
||||
result,
|
||||
&s->sample_spec,
|
||||
length1st);
|
||||
} else if (n == 1) {
|
||||
pa_cvolume volume;
|
||||
|
||||
*result = info[0].chunk;
|
||||
pa_memblock_ref(result->memblock);
|
||||
|
||||
if (result->length > length)
|
||||
result->length = length;
|
||||
|
||||
pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
|
||||
|
||||
if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) {
|
||||
if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) {
|
||||
pa_memblock_unref(result->memblock);
|
||||
pa_silence_memchunk_get(&s->core->silence_cache,
|
||||
s->core->mempool,
|
||||
result,
|
||||
&s->sample_spec,
|
||||
result->length);
|
||||
} else {
|
||||
pa_memchunk_make_writable(result, length);
|
||||
pa_volume_memchunk(result, &s->sample_spec, &volume);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
void *ptr;
|
||||
|
||||
result->index = 0;
|
||||
result->memblock = pa_memblock_new(s->core->mempool, length);
|
||||
|
||||
ptr = pa_memblock_acquire(result->memblock);
|
||||
|
||||
result->length = pa_mix(info, n,
|
||||
(uint8_t*) ptr + result->index, length1st,
|
||||
&s->sample_spec,
|
||||
&s->thread_info.soft_volume,
|
||||
s->thread_info.soft_muted);
|
||||
|
||||
pa_memblock_release(result->memblock);
|
||||
}
|
||||
|
||||
inputs_drop(s, info, n, result);
|
||||
pa_sink_render(s, length, result);
|
||||
|
||||
if (result->length < length) {
|
||||
pa_memchunk chunk;
|
||||
size_t l, d;
|
||||
|
||||
pa_memchunk_make_writable(result, length);
|
||||
|
||||
l = length - result->length;
|
||||
d = result->index + result->length;
|
||||
while (l > 0) {
|
||||
chunk = *result;
|
||||
chunk.index = d;
|
||||
chunk.length = l;
|
||||
chunk.memblock = result->memblock;
|
||||
chunk.index = result->index + result->length;
|
||||
chunk.length = length - result->length;
|
||||
|
||||
pa_sink_render_into(s, &chunk);
|
||||
pa_sink_render_into_full(s, &chunk);
|
||||
|
||||
d += chunk.length;
|
||||
l -= chunk.length;
|
||||
}
|
||||
result->length = length;
|
||||
}
|
||||
|
||||
|
|
@ -1408,8 +1352,11 @@ void pa_sink_set_volume(
|
|||
pa_assert_ctl_context();
|
||||
pa_assert(PA_SINK_IS_LINKED(s->state));
|
||||
pa_assert(!volume || pa_cvolume_valid(volume));
|
||||
pa_assert(!volume || pa_cvolume_compatible(volume, &s->sample_spec));
|
||||
pa_assert(volume || (s->flags & PA_SINK_FLAT_VOLUME));
|
||||
pa_assert(!volume || volume->channels == 1 || pa_cvolume_compatible(volume, &s->sample_spec));
|
||||
|
||||
/* As a special exception we accept mono volumes on all sinks --
|
||||
* even on those with more complex channel maps */
|
||||
|
||||
/* If volume is NULL we synchronize the sink's real and reference
|
||||
* volumes with the stream volumes. If it is not NULL we update
|
||||
|
|
@ -1419,7 +1366,10 @@ void pa_sink_set_volume(
|
|||
|
||||
if (volume) {
|
||||
|
||||
s->reference_volume = *volume;
|
||||
if (pa_cvolume_compatible(volume, &s->sample_spec))
|
||||
s->reference_volume = *volume;
|
||||
else
|
||||
pa_cvolume_scale(&s->reference_volume, pa_cvolume_max(volume));
|
||||
|
||||
if (s->flags & PA_SINK_FLAT_VOLUME) {
|
||||
/* OK, propagate this volume change back to the inputs */
|
||||
|
|
|
|||
|
|
@ -73,14 +73,18 @@
|
|||
|
||||
struct pa_socket_client {
|
||||
PA_REFCNT_DECLARE;
|
||||
pa_mainloop_api *mainloop;
|
||||
int fd;
|
||||
|
||||
pa_mainloop_api *mainloop;
|
||||
pa_io_event *io_event;
|
||||
pa_time_event *timeout_event;
|
||||
pa_defer_event *defer_event;
|
||||
|
||||
pa_socket_client_cb_t callback;
|
||||
void *userdata;
|
||||
|
||||
pa_bool_t local;
|
||||
|
||||
#ifdef HAVE_LIBASYNCNS
|
||||
asyncns_t *asyncns;
|
||||
asyncns_query_t * asyncns_query;
|
||||
|
|
@ -92,22 +96,10 @@ static pa_socket_client* socket_client_new(pa_mainloop_api *m) {
|
|||
pa_socket_client *c;
|
||||
pa_assert(m);
|
||||
|
||||
c = pa_xnew(pa_socket_client, 1);
|
||||
c = pa_xnew0(pa_socket_client, 1);
|
||||
PA_REFCNT_INIT(c);
|
||||
c->mainloop = m;
|
||||
c->fd = -1;
|
||||
c->io_event = NULL;
|
||||
c->timeout_event = NULL;
|
||||
c->defer_event = NULL;
|
||||
c->callback = NULL;
|
||||
c->userdata = NULL;
|
||||
c->local = FALSE;
|
||||
|
||||
#ifdef HAVE_LIBASYNCNS
|
||||
c->asyncns = NULL;
|
||||
c->asyncns_io_event = NULL;
|
||||
c->asyncns_query = NULL;
|
||||
#endif
|
||||
|
||||
return c;
|
||||
}
|
||||
|
|
@ -163,7 +155,6 @@ static void do_call(pa_socket_client *c) {
|
|||
}
|
||||
|
||||
io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
|
||||
pa_assert(io);
|
||||
|
||||
finish:
|
||||
if (!io && c->fd >= 0)
|
||||
|
|
@ -172,7 +163,6 @@ finish:
|
|||
|
||||
free_events(c);
|
||||
|
||||
pa_assert(c->callback);
|
||||
c->callback(c, io, c->userdata);
|
||||
|
||||
pa_socket_client_unref(c);
|
||||
|
|
@ -202,8 +192,6 @@ static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event
|
|||
}
|
||||
|
||||
static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) {
|
||||
int r;
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
pa_assert(sa);
|
||||
|
|
@ -211,7 +199,7 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t
|
|||
|
||||
pa_make_fd_nonblock(c->fd);
|
||||
|
||||
if ((r = connect(c->fd, sa, len)) < 0) {
|
||||
if (connect(c->fd, sa, len) < 0) {
|
||||
#ifdef OS_IS_WIN32
|
||||
if (WSAGetLastError() != EWOULDBLOCK) {
|
||||
pa_log_debug("connect(): %d", WSAGetLastError());
|
||||
|
|
@ -222,9 +210,9 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t
|
|||
return -1;
|
||||
}
|
||||
|
||||
pa_assert_se(c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c));
|
||||
c->io_event = c->mainloop->io_new(c->mainloop, c->fd, PA_IO_EVENT_OUTPUT, connect_io_cb, c);
|
||||
} else
|
||||
pa_assert_se(c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c));
|
||||
c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -235,7 +223,7 @@ pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address
|
|||
pa_assert(m);
|
||||
pa_assert(port > 0);
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
pa_zero(sa);
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
sa.sin_addr.s_addr = htonl(address);
|
||||
|
|
@ -243,28 +231,24 @@ pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address
|
|||
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
|
||||
pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
struct sockaddr_un sa;
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(filename);
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
pa_zero(sa);
|
||||
sa.sun_family = AF_UNIX;
|
||||
pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
|
||||
|
||||
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
|
||||
}
|
||||
|
||||
#else /* HAVE_SYS_UN_H */
|
||||
|
||||
pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SYS_UN_H */
|
||||
}
|
||||
|
||||
static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
|
||||
pa_assert(c);
|
||||
|
|
@ -302,7 +286,7 @@ pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct
|
|||
pa_assert(sa);
|
||||
pa_assert(salen > 0);
|
||||
|
||||
pa_assert_se(c = socket_client_new(m));
|
||||
c = socket_client_new(m);
|
||||
|
||||
if (sockaddr_prepare(c, sa, salen) < 0)
|
||||
goto fail;
|
||||
|
|
@ -359,22 +343,25 @@ void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on
|
|||
c->userdata = userdata;
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
|
||||
#ifdef HAVE_IPV6
|
||||
struct sockaddr_in6 sa;
|
||||
|
||||
pa_assert(m);
|
||||
pa_assert(address);
|
||||
pa_assert(port > 0);
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
pa_zero(sa);
|
||||
sa.sin6_family = AF_INET6;
|
||||
sa.sin6_port = htons(port);
|
||||
memcpy(&sa.sin6_addr, address, sizeof(sa.sin6_addr));
|
||||
|
||||
return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
|
||||
}
|
||||
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBASYNCNS
|
||||
|
||||
|
|
@ -468,14 +455,13 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_
|
|||
|
||||
case PA_PARSED_ADDRESS_TCP4: /* Fallthrough */
|
||||
case PA_PARSED_ADDRESS_TCP6: /* Fallthrough */
|
||||
case PA_PARSED_ADDRESS_TCP_AUTO:{
|
||||
|
||||
case PA_PARSED_ADDRESS_TCP_AUTO: {
|
||||
struct addrinfo hints;
|
||||
char port[12];
|
||||
|
||||
pa_snprintf(port, sizeof(port), "%u", (unsigned) a.port);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
pa_zero(hints);
|
||||
if (a.type == PA_PARSED_ADDRESS_TCP4)
|
||||
hints.ai_family = PF_INET;
|
||||
#ifdef HAVE_IPV6
|
||||
|
|
@ -494,11 +480,10 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_
|
|||
if (!(asyncns = asyncns_new(1)))
|
||||
goto finish;
|
||||
|
||||
pa_assert_se(c = socket_client_new(m));
|
||||
c = socket_client_new(m);
|
||||
c->asyncns = asyncns;
|
||||
c->asyncns_io_event = m->io_new(m, asyncns_fd(c->asyncns), PA_IO_EVENT_INPUT, asyncns_cb, c);
|
||||
c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints);
|
||||
pa_assert(c->asyncns_query);
|
||||
pa_assert_se(c->asyncns_query = asyncns_getaddrinfo(c->asyncns, a.path_or_host, port, &hints));
|
||||
start_timeout(c, use_rtclock);
|
||||
}
|
||||
#elif defined(HAVE_GETADDRINFO)
|
||||
|
|
@ -541,6 +526,7 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_
|
|||
if (!host)
|
||||
goto finish;
|
||||
|
||||
pa_zero(sa);
|
||||
s.sin_family = AF_INET;
|
||||
memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr));
|
||||
s.sin_port = htons(a.port);
|
||||
|
|
|
|||
|
|
@ -35,9 +35,7 @@ typedef struct pa_socket_client pa_socket_client;
|
|||
typedef void (*pa_socket_client_cb_t)(pa_socket_client *c, pa_iochannel*io, void *userdata);
|
||||
|
||||
pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port);
|
||||
#ifdef HAVE_IPV6
|
||||
pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port);
|
||||
#endif
|
||||
pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename);
|
||||
pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen);
|
||||
pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, pa_bool_t use_rtclock, const char *a, uint16_t default_port);
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ int pa_source_output_new(
|
|||
pa_resampler *resampler = NULL;
|
||||
char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
|
||||
int r;
|
||||
char *pt;
|
||||
|
||||
pa_assert(_o);
|
||||
pa_assert(core);
|
||||
|
|
@ -247,12 +248,15 @@ int pa_source_output_new(
|
|||
if (o->direct_on_input)
|
||||
pa_assert_se(pa_idxset_put(o->direct_on_input->direct_outputs, o, NULL) == 0);
|
||||
|
||||
pa_log_info("Created output %u \"%s\" on %s with sample spec %s and channel map %s",
|
||||
pt = pa_proplist_to_string_sep(o->proplist, "\n ");
|
||||
pa_log_info("Created output %u \"%s\" on %s with sample spec %s and channel map %s\n %s",
|
||||
o->index,
|
||||
pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME)),
|
||||
o->source->name,
|
||||
pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec),
|
||||
pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map));
|
||||
pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map),
|
||||
pt);
|
||||
pa_xfree(pt);
|
||||
|
||||
/* Don't forget to call pa_source_output_put! */
|
||||
|
||||
|
|
|
|||
|
|
@ -760,15 +760,22 @@ void pa_source_set_volume(
|
|||
pa_bool_t save) {
|
||||
|
||||
pa_bool_t real_changed;
|
||||
pa_cvolume old_volume;
|
||||
|
||||
pa_source_assert_ref(s);
|
||||
pa_assert_ctl_context();
|
||||
pa_assert(PA_SOURCE_IS_LINKED(s->state));
|
||||
pa_assert(pa_cvolume_valid(volume));
|
||||
pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
|
||||
pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &s->sample_spec));
|
||||
|
||||
real_changed = !pa_cvolume_equal(volume, &s->volume);
|
||||
s->volume = *volume;
|
||||
old_volume = s->volume;
|
||||
|
||||
if (pa_cvolume_compatible(volume, &s->sample_spec))
|
||||
s->volume = *volume;
|
||||
else
|
||||
pa_cvolume_scale(&s->volume, pa_cvolume_max(volume));
|
||||
|
||||
real_changed = !pa_cvolume_equal(&old_volume, &s->volume);
|
||||
s->save_volume = (!real_changed && s->save_volume) || save;
|
||||
|
||||
if (s->set_volume) {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,11 @@ int pa_start_child_for_read(const char *name, const char *argv1, pid_t *pid) {
|
|||
pa_reset_sigs(-1);
|
||||
pa_unblock_sigs(-1);
|
||||
pa_reset_priority();
|
||||
pa_unset_env_recorded();
|
||||
|
||||
/* Make sure our children are not influenced by the
|
||||
* LD_BIND_NOW we set for ourselves. */
|
||||
unsetenv("LD_BIND_NOW");
|
||||
|
||||
#ifdef PR_SET_PDEATHSIG
|
||||
/* On Linux we can use PR_SET_PDEATHSIG to have the helper
|
||||
|
|
|
|||
|
|
@ -57,14 +57,12 @@
|
|||
" punpcklwd %%mm4, "#s" \n\t" /* .. | 0 | p0 | */ \
|
||||
" pcmpgtw "#v", %%mm4 \n\t" /* .. | 0 | s(vl) | */ \
|
||||
" pand "#s", %%mm4 \n\t" /* .. | 0 | (p0) | (vl >> 15) & p */ \
|
||||
" movq %%mm6, %%mm5 \n\t" /* .. | ffff | 0 | */ \
|
||||
" pand "#v", %%mm5 \n\t" /* .. | vh | 0 | */ \
|
||||
" por %%mm5, %%mm4 \n\t" /* .. | vh | (p0) | */ \
|
||||
" pmulhw "#s", "#v" \n\t" /* .. | 0 | vl*p0 | */ \
|
||||
" paddw %%mm4, "#v" \n\t" /* .. | vh | vl*p0 | vh + sign correct */ \
|
||||
" pslld $16, "#s" \n\t" /* .. | p0 | 0 | */ \
|
||||
" por %%mm7, "#s" \n\t" /* .. | p0 | 1 | */ \
|
||||
" pmaddwd "#s", "#v" \n\t" /* .. | p0 * v0 | */ \
|
||||
" movq "#s", %%mm5 \n\t" \
|
||||
" pmulhw "#v", "#s" \n\t" /* .. | 0 | vl*p0 | */ \
|
||||
" paddw %%mm4, "#s" \n\t" /* .. | 0 | vl*p0 | + sign correct */ \
|
||||
" psrld $16, "#v" \n\t" /* .. | 0 | vh | */ \
|
||||
" pmaddwd %%mm5, "#v" \n\t" /* .. | p0 * vh | */ \
|
||||
" paddd "#s", "#v" \n\t" /* .. | p0 * v0 | */ \
|
||||
" packssdw "#v", "#v" \n\t" /* .. | p1*v1 | p0*v0 | */
|
||||
|
||||
/* approximately advances %3 = (%3 + a) % b. This function requires that
|
||||
|
|
@ -105,10 +103,6 @@ pa_volume_s16ne_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsi
|
|||
__asm__ __volatile__ (
|
||||
" xor %3, %3 \n\t"
|
||||
" sar $1, %2 \n\t" /* length /= sizeof (int16_t) */
|
||||
" pcmpeqw %%mm6, %%mm6 \n\t" /* .. | ffff | ffff | */
|
||||
" pcmpeqw %%mm7, %%mm7 \n\t" /* .. | ffff | ffff | */
|
||||
" pslld $16, %%mm6 \n\t" /* .. | ffff | 0 | */
|
||||
" psrld $31, %%mm7 \n\t" /* .. | 0 | 1 | */
|
||||
|
||||
" test $1, %2 \n\t" /* check for odd samples */
|
||||
" je 2f \n\t"
|
||||
|
|
@ -158,7 +152,7 @@ pa_volume_s16ne_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsi
|
|||
" emms \n\t"
|
||||
|
||||
: "+r" (samples), "+r" (volumes), "+r" (length), "=D" ((pa_reg_x86)channel), "=&r" (temp)
|
||||
: "r" ((pa_reg_x86)channels)
|
||||
: "X" ((pa_reg_x86)channels)
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
|
@ -234,7 +228,7 @@ pa_volume_s16re_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsi
|
|||
" emms \n\t"
|
||||
|
||||
: "+r" (samples), "+r" (volumes), "+r" (length), "=D" ((pa_reg_x86)channel), "=&r" (temp)
|
||||
: "r" ((pa_reg_x86)channels)
|
||||
: "X" ((pa_reg_x86)channels)
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
|
@ -301,13 +295,16 @@ static void run_test (void) {
|
|||
|
||||
void pa_volume_func_init_mmx (pa_cpu_x86_flag_t flags) {
|
||||
#if defined (__i386__) || defined (__amd64__)
|
||||
pa_log_info("Initialising MMX optimized functions.");
|
||||
|
||||
#ifdef RUN_TEST
|
||||
run_test ();
|
||||
#endif
|
||||
|
||||
pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_mmx);
|
||||
pa_set_volume_func (PA_SAMPLE_S16RE, (pa_do_volume_func_t) pa_volume_s16re_mmx);
|
||||
if (flags & PA_CPU_X86_MMX) {
|
||||
pa_log_info("Initialising MMX optimized functions.");
|
||||
|
||||
pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_mmx);
|
||||
pa_set_volume_func (PA_SAMPLE_S16RE, (pa_do_volume_func_t) pa_volume_s16re_mmx);
|
||||
}
|
||||
#endif /* defined (__i386__) || defined (__amd64__) */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
" movdqa "#s", %%xmm5 \n\t" \
|
||||
" pmulhuw "#v", "#s" \n\t" /* .. | 0 | vl*p0 | */ \
|
||||
" psubd %%xmm4, "#s" \n\t" /* .. | 0 | vl*p0 | + sign correct */ \
|
||||
" psrld $16, "#v" \n\t" /* .. | p0 | 0 | */ \
|
||||
" psrld $16, "#v" \n\t" /* .. | 0 | vh | */ \
|
||||
" pmaddwd %%xmm5, "#v" \n\t" /* .. | p0 * vh | */ \
|
||||
" paddd "#s", "#v" \n\t" /* .. | p0 * v0 | */ \
|
||||
" packssdw "#v", "#v" \n\t" /* .. | p1*v1 | p0*v0 | */
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
" por %%xmm5, "#s2" \n\t"
|
||||
|
||||
static void
|
||||
pa_volume_s16ne_sse (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
|
||||
pa_volume_s16ne_sse2 (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
|
||||
{
|
||||
pa_reg_x86 channel, temp;
|
||||
|
||||
|
|
@ -149,13 +149,13 @@ pa_volume_s16ne_sse (int16_t *samples, int32_t *volumes, unsigned channels, unsi
|
|||
"8: \n\t"
|
||||
|
||||
: "+r" (samples), "+r" (volumes), "+r" (length), "=D" (channel), "=&r" (temp)
|
||||
: "r" ((pa_reg_x86)channels)
|
||||
: "X" ((pa_reg_x86)channels)
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static void
|
||||
pa_volume_s16re_sse (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
|
||||
pa_volume_s16re_sse2 (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
|
||||
{
|
||||
pa_reg_x86 channel, temp;
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ pa_volume_s16re_sse (int16_t *samples, int32_t *volumes, unsigned channels, unsi
|
|||
"8: \n\t"
|
||||
|
||||
: "+r" (samples), "+r" (volumes), "+r" (length), "=D" (channel), "=&r" (temp)
|
||||
: "r" ((pa_reg_x86)channels)
|
||||
: "X" ((pa_reg_x86)channels)
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
|
@ -302,13 +302,16 @@ static void run_test (void) {
|
|||
|
||||
void pa_volume_func_init_sse (pa_cpu_x86_flag_t flags) {
|
||||
#if defined (__i386__) || defined (__amd64__)
|
||||
pa_log_info("Initialising SSE optimized functions.");
|
||||
|
||||
#ifdef RUN_TEST
|
||||
run_test ();
|
||||
#endif
|
||||
|
||||
pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_sse);
|
||||
pa_set_volume_func (PA_SAMPLE_S16RE, (pa_do_volume_func_t) pa_volume_s16re_sse);
|
||||
if (flags & PA_CPU_X86_SSE2) {
|
||||
pa_log_info("Initialising SSE2 optimized functions.");
|
||||
|
||||
pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_sse2);
|
||||
pa_set_volume_func (PA_SAMPLE_S16RE, (pa_do_volume_func_t) pa_volume_s16re_sse2);
|
||||
}
|
||||
#endif /* defined (__i386__) || defined (__amd64__) */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@
|
|||
#include <inttypes.h>
|
||||
|
||||
/* First, define HAVE_VECTOR if we have the gcc vector extensions at all */
|
||||
#if defined(__SSE2__) || defined(__ALTIVEC__)
|
||||
#if defined(__SSE2__)
|
||||
/* || defined(__ALTIVEC__)*/
|
||||
#define HAVE_VECTOR
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue