diff options
Diffstat (limited to 'src/pulsecore')
-rw-r--r-- | src/pulsecore/conf-parser.c | 18 | ||||
-rw-r--r-- | src/pulsecore/conf-parser.h | 3 | ||||
-rw-r--r-- | src/pulsecore/core-scache.c | 31 | ||||
-rw-r--r-- | src/pulsecore/core-util.c | 54 | ||||
-rw-r--r-- | src/pulsecore/core-util.h | 13 | ||||
-rw-r--r-- | src/pulsecore/core.c | 8 | ||||
-rw-r--r-- | src/pulsecore/core.h | 2 | ||||
-rw-r--r-- | src/pulsecore/flist.h | 3 | ||||
-rw-r--r-- | src/pulsecore/idxset.c | 2 | ||||
-rw-r--r-- | src/pulsecore/log.c | 3 | ||||
-rw-r--r-- | src/pulsecore/macro.h | 2 | ||||
-rw-r--r-- | src/pulsecore/memblock.c | 36 | ||||
-rw-r--r-- | src/pulsecore/memblock.h | 2 | ||||
-rw-r--r-- | src/pulsecore/namereg.c | 3 | ||||
-rw-r--r-- | src/pulsecore/namereg.h | 2 | ||||
-rw-r--r-- | src/pulsecore/prioq.c | 256 | ||||
-rw-r--r-- | src/pulsecore/prioq.h | 64 | ||||
-rw-r--r-- | src/pulsecore/proplist-util.c | 2 | ||||
-rw-r--r-- | src/pulsecore/protocol-native.c | 6 | ||||
-rw-r--r-- | src/pulsecore/protocol-simple.c | 12 | ||||
-rw-r--r-- | src/pulsecore/sample-util.c | 197 | ||||
-rw-r--r-- | src/pulsecore/sconv-s16le.c | 20 | ||||
-rw-r--r-- | src/pulsecore/sconv.c | 4 | ||||
-rw-r--r-- | src/pulsecore/sink-input.c | 3 | ||||
-rw-r--r-- | src/pulsecore/sink.c | 1 | ||||
-rw-r--r-- | src/pulsecore/thread.h | 3 | ||||
-rw-r--r-- | src/pulsecore/time-smoother.c | 8 |
27 files changed, 579 insertions, 179 deletions
diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c index 6b0e1d56..58ceab91 100644 --- a/src/pulsecore/conf-parser.c +++ b/src/pulsecore/conf-parser.c @@ -166,6 +166,24 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, return 0; } +int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { + size_t *i = data; + uint32_t k; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_atou(rvalue, &k) < 0) { + pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue); + return -1; + } + + *i = (size_t) k; + return 0; +} + int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) { int k; pa_bool_t *b = data; diff --git a/src/pulsecore/conf-parser.h b/src/pulsecore/conf-parser.h index 7eb1fae2..a5174fce 100644 --- a/src/pulsecore/conf-parser.h +++ b/src/pulsecore/conf-parser.h @@ -39,8 +39,9 @@ typedef struct pa_config_item { * NULL */ int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata); -/* Generic parsers for integers, booleans and strings */ +/* Generic parsers for integers, size_t, booleans and strings */ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); +int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata); diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c index 814dff59..1d080e11 100644 --- a/src/pulsecore/core-scache.c +++ b/src/pulsecore/core-scache.c @@ -98,7 +98,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { pa_assert(c); pa_assert(name); - if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) { + if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, FALSE))) { if (e->memchunk.memblock) pa_memblock_unref(e->memchunk.memblock); @@ -111,7 +111,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { } else { e = pa_xnew(pa_scache_entry, 1); - if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, 1)) { + if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, TRUE)) { pa_xfree(e); return NULL; } @@ -134,9 +134,9 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) { e->lazy = FALSE; e->last_used_time = 0; - memset(&e->sample_spec, 0, sizeof(e->sample_spec)); + pa_sample_spec_init(&e->sample_spec); pa_channel_map_init(&e->channel_map); - pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX); + pa_cvolume_init(&e->volume); pa_proplist_sets(e->proplist, PA_PROP_MEDIA_ROLE, "event"); @@ -159,10 +159,12 @@ int pa_scache_add_item( pa_assert(c); pa_assert(name); pa_assert(!ss || pa_sample_spec_valid(ss)); - pa_assert(!map || (pa_channel_map_valid(map) && ss && ss->channels == map->channels)); + pa_assert(!map || (pa_channel_map_valid(map) && ss && pa_channel_map_compatible(map, ss))); - if (ss && !map) + if (ss && !map) { pa_channel_map_init_extend(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT); + map = &tmap; + } if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX) return -1; @@ -170,12 +172,13 @@ int pa_scache_add_item( if (!(e = scache_add_item(c, name))) return -1; - memset(&e->sample_spec, 0, sizeof(e->sample_spec)); + pa_sample_spec_init(&e->sample_spec); pa_channel_map_init(&e->channel_map); + pa_cvolume_init(&e->volume); if (ss) { e->sample_spec = *ss; - e->volume.channels = e->sample_spec.channels; + pa_cvolume_reset(&e->volume, ss->channels); } if (map) @@ -310,17 +313,21 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t pa_assert(name); pa_assert(sink); - if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1))) + if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, FALSE))) return -1; if (e->lazy && !e->memchunk.memblock) { + pa_channel_map old_channel_map = e->channel_map; + if (pa_sound_file_load(c->mempool, e->filename, &e->sample_spec, &e->channel_map, &e->memchunk) < 0) return -1; pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index); - if (e->volume.channels > e->sample_spec.channels) - e->volume.channels = e->sample_spec.channels; + if (pa_cvolume_valid(&e->volume)) + pa_cvolume_remap(&e->volume, &old_channel_map, &e->channel_map); + else + pa_cvolume_reset(&e->volume, e->sample_spec.channels); } if (!e->memchunk.memblock) @@ -383,7 +390,7 @@ uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) { pa_assert(c); pa_assert(name); - if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) + if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, FALSE))) return PA_IDXSET_INVALID; return e->index; diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 3e5ea492..dde34d7b 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -1315,31 +1315,43 @@ static char* make_random_dir(mode_t m) { "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; - char fn[24] = "/tmp/pulse-"; + const char *tmpdir; + char *fn; + size_t pathlen; - fn[sizeof(fn)-1] = 0; + 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); + pathlen = strlen(fn); for (;;) { - unsigned i; + size_t i; int r; mode_t u; int saved_errno; - for (i = 11; i < sizeof(fn)-1; i++) + for (i = pathlen - 12; i < pathlen; i++) fn[i] = table[rand() % (sizeof(table)-1)]; u = umask((~m) & 0777); r = mkdir(fn, m); + saved_errno = errno; umask(u); + errno = saved_errno; if (r >= 0) - return pa_xstrdup(fn); - - errno = saved_errno; + return fn; if (errno != EEXIST) { pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno)); + pa_xfree(fn); return NULL; } } @@ -1370,6 +1382,7 @@ static int make_random_dir_and_link(mode_t m, const char *k) { char *pa_get_runtime_dir(void) { char *d, *k = NULL, *p = NULL, *t = NULL, *mid; struct stat st; + mode_t m; /* The runtime directory shall contain dynamic data that needs NOT * to be kept accross reboots and is usuallly private to the user, @@ -1378,10 +1391,9 @@ char *pa_get_runtime_dir(void) { * this directory, we link it to a random subdir in /tmp, if it * was not explicitly configured. */ - if ((d = getenv("PULSE_RUNTIME_PATH"))) { - mode_t m; + m = pa_in_system_mode() ? 0755U : 0700U; - m = pa_in_system_mode() ? 0755U : 0700U; + if ((d = getenv("PULSE_RUNTIME_PATH"))) { if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) { pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno)); @@ -1394,6 +1406,11 @@ char *pa_get_runtime_dir(void) { if (!(d = get_pulse_home())) goto fail; + if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) { + pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno)); + goto fail; + } + if (!(mid = pa_machine_id())) { pa_xfree(d); goto fail; @@ -2334,7 +2351,7 @@ int pa_reset_sigs(int except, ...) { int pa_reset_sigsv(const int except[]) { int sig; - for (sig = 1; sig < _NSIG; sig++) { + for (sig = 1; sig < NSIG; sig++) { pa_bool_t reset = TRUE; switch (sig) { @@ -2455,3 +2472,18 @@ char *pa_uname_string(void) { return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version); } + +#ifdef HAVE_VALGRIND_MEMCHECK_H +pa_bool_t pa_in_valgrind(void) { + static int b = 0; + + /* To make heisenbugs a bit simpler to find we check for $VALGRIND + * here instead of really checking whether we run in valgrind or + * not. */ + + if (b < 1) + b = getenv("VALGRIND") ? 2 : 1; + + return b > 1; +} +#endif diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index df8ce3f8..fd6ee896 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -35,6 +35,10 @@ #include <pulse/gccmacro.h> #include <pulsecore/macro.h> +#ifndef PACKAGE +#error "Please include config.h before including this file!" +#endif + struct timeval; /* These resource limits are pretty new on Linux, let's define them @@ -193,4 +197,13 @@ pa_bool_t pa_in_system_mode(void); char *pa_machine_id(void); char *pa_uname_string(void); + +#ifdef HAVE_VALGRIND_MEMCHECK_H +pa_bool_t pa_in_valgrind(void); +#else +static inline pa_bool_t pa_in_valgrind(void) { + return FALSE; +} +#endif + #endif diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index bd956ae0..5761bbc7 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -66,7 +66,7 @@ static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t o static void core_free(pa_object *o); -pa_core* pa_core_new(pa_mainloop_api *m, int shared) { +pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) { pa_core* c; pa_mempool *pool; int j; @@ -74,14 +74,14 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) { pa_assert(m); if (shared) { - if (!(pool = pa_mempool_new(shared))) { + if (!(pool = pa_mempool_new(shared, shm_size))) { pa_log_warn("failed to allocate shared memory pool. Falling back to a normal memory pool."); - shared = 0; + shared = FALSE; } } if (!shared) { - if (!(pool = pa_mempool_new(shared))) { + if (!(pool = pa_mempool_new(shared, shm_size))) { pa_log("pa_mempool_new() failed."); return NULL; } diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index fb4490f2..39559082 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -141,7 +141,7 @@ enum { PA_CORE_MESSAGE_MAX }; -pa_core* pa_core_new(pa_mainloop_api *m, int shared); +pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size); /* Check whether noone is connected to this core */ void pa_core_check_idle(pa_core *c); diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h index 2d8422f9..512dd357 100644 --- a/src/pulsecore/flist.h +++ b/src/pulsecore/flist.h @@ -26,6 +26,7 @@ #include <pulse/gccmacro.h> #include <pulsecore/once.h> +#include <pulsecore/core-util.h> /* A multiple-reader multipler-write lock-free free list implementation */ @@ -56,6 +57,8 @@ void* pa_flist_pop(pa_flist*l); } \ static void name##_flist_destructor(void) PA_GCC_DESTRUCTOR; \ static void name##_flist_destructor(void) { \ + if (!pa_in_valgrind()) \ + return; \ if (name##_flist.flist) \ pa_flist_free(name##_flist.flist, (free_cb)); \ } \ diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c index 2de64069..24a28db7 100644 --- a/src/pulsecore/idxset.c +++ b/src/pulsecore/idxset.c @@ -80,7 +80,7 @@ unsigned pa_idxset_trivial_hash_func(const void *p) { } int pa_idxset_trivial_compare_func(const void *a, const void *b) { - return a != b; + return a < b ? -1 : (a > b ? 1 : 0); } pa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) { diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index d7318081..b1de6966 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -85,6 +85,9 @@ void pa_log_set_ident(const char *p) { /* To make valgrind shut up. */ static void ident_destructor(void) PA_GCC_DESTRUCTOR; static void ident_destructor(void) { + if (!pa_in_valgrind()) + return; + pa_xfree(log_ident); pa_xfree(log_ident_local); } diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h index fd33b7bb..39e9b587 100644 --- a/src/pulsecore/macro.h +++ b/src/pulsecore/macro.h @@ -208,7 +208,7 @@ typedef int pa_bool_t; #define PA_PATH_SEP_CHAR '/' #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && defined(__ELF__) #define PA_WARN_REFERENCE(sym, msg) \ __asm__(".section .gnu.warning." #sym); \ diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index 6d12acdc..d9e1bf1c 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -261,9 +261,11 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) { } } -#ifdef HAVE_VALGRIND_MEMCHECK_H - VALGRIND_MALLOCLIKE_BLOCK(slot, p->block_size, 0, 0); -#endif +/* #ifdef HAVE_VALGRIND_MEMCHECK_H */ +/* if (PA_UNLIKELY(pa_in_valgrind())) { */ +/* VALGRIND_MALLOCLIKE_BLOCK(slot, p->block_size, 0, 0); */ +/* } */ +/* #endif */ return slot; } @@ -534,16 +536,18 @@ static void memblock_free(pa_memblock *b) { call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL; +/* #ifdef HAVE_VALGRIND_MEMCHECK_H */ +/* if (PA_UNLIKELY(pa_in_valgrind())) { */ +/* VALGRIND_FREELIKE_BLOCK(slot, b->pool->block_size); */ +/* } */ +/* #endif */ + /* The free list dimensions should easily allow all slots * to fit in, hence try harder if pushing this slot into * the free list fails */ while (pa_flist_push(b->pool->free_slots, slot) < 0) ; -#ifdef HAVE_VALGRIND_MEMCHECK_H - VALGRIND_FREELIKE_BLOCK(slot, b->pool->block_size); -#endif - if (call_free) if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0) pa_xfree(b); @@ -680,8 +684,9 @@ static void memblock_replace_import(pa_memblock *b) { pa_mutex_unlock(seg->import->mutex); } -pa_mempool* pa_mempool_new(pa_bool_t shared) { +pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size) { pa_mempool *p; + char t1[64], t2[64]; p = pa_xnew(pa_mempool, 1); @@ -692,13 +697,26 @@ pa_mempool* pa_mempool_new(pa_bool_t shared) { if (p->block_size < PA_PAGE_SIZE) p->block_size = PA_PAGE_SIZE; - p->n_blocks = PA_MEMPOOL_SLOTS_MAX; + if (size <= 0) + p->n_blocks = PA_MEMPOOL_SLOTS_MAX; + else { + p->n_blocks = (unsigned) (size / p->block_size); + + if (p->n_blocks < 2) + p->n_blocks = 2; + } if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) { pa_xfree(p); return NULL; } + pa_log_debug("Using %s memory pool with %u slots of size %s each, total size is %s", + p->memory.shared ? "shared" : "private", + p->n_blocks, + pa_bytes_snprint(t1, sizeof(t1), (unsigned) p->block_size), + pa_bytes_snprint(t2, sizeof(t2), (unsigned) (p->n_blocks * p->block_size))); + memset(&p->stat, 0, sizeof(p->stat)); pa_atomic_store(&p->n_init, 0); diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h index efe55b02..b1eab2a9 100644 --- a/src/pulsecore/memblock.h +++ b/src/pulsecore/memblock.h @@ -117,7 +117,7 @@ pa_mempool * pa_memblock_get_pool(pa_memblock *b); pa_memblock *pa_memblock_will_need(pa_memblock *b); /* The memory block manager */ -pa_mempool* pa_mempool_new(pa_bool_t shared); +pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size); void pa_mempool_free(pa_mempool *p); const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p); void pa_mempool_vacuum(pa_mempool *p); diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index ad697ed5..ecd8def8 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -51,6 +51,7 @@ static pa_bool_t is_valid_char(char c) { (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || + c == '-' || c == '_'; } @@ -97,7 +98,7 @@ void pa_namereg_free(pa_core *c) { pa_hashmap_free(c->namereg, NULL, NULL); } -const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail) { +const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, pa_bool_t fail) { struct namereg_entry *e; char *n = NULL; diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index 3c1de8e7..f4581006 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -35,7 +35,7 @@ typedef enum pa_namereg_type { void pa_namereg_free(pa_core *c); -const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail); +const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, pa_bool_t fail); void pa_namereg_unregister(pa_core *c, const char *name); void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, pa_bool_t autoload); int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type); diff --git a/src/pulsecore/prioq.c b/src/pulsecore/prioq.c new file mode 100644 index 00000000..693dc517 --- /dev/null +++ b/src/pulsecore/prioq.c @@ -0,0 +1,256 @@ +/*** + This file is part of PulseAudio. + + Copyright 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 + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <pulse/xmalloc.h> + +#include <pulsecore/flist.h> + +#include "prioq.h" + +struct pa_prioq_item { + void *value; + unsigned idx; +}; + +struct pa_prioq { + pa_prioq_item **items; + unsigned n_items; + unsigned n_allocated; + pa_compare_func_t compare_func; +}; + +PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree); + +pa_prioq *pa_prioq_new(pa_compare_func_t compare_func) { + + pa_prioq *q; + + q = pa_xnew(pa_prioq, 1); + q->compare_func = compare_func; + q->n_items = 0; + q->n_allocated = 64; + q->items = pa_xnew(pa_prioq_item*, q->n_allocated); + + return q; +} + +void pa_prioq_free(pa_prioq *q, pa_free2_cb_t free_cb, void *userdata) { + pa_prioq_item **i, **e; + + pa_assert(q); + + for (i = q->items, e = q->items + q->n_items; i < e; i++) { + + if (!*i) + continue; + + if (free_cb) + free_cb((*i)->value, userdata); + + pa_xfree(*i); + } + + pa_xfree(q->items); + pa_xfree(q); +} + +static void shuffle_up(pa_prioq *q, pa_prioq_item *i) { + unsigned j; + + pa_assert(q); + pa_assert(i); + + j = i->idx; + + while (j > 0) { + unsigned k; + + k = (j-1)/2; + + if (q->compare_func(q->items[k]->value, i->value) < 0) + break; + + q->items[k]->idx = j; + q->items[j] = q->items[k]; + + j = k; + } + + i->idx = j; + q->items[j] = i; + +} + +pa_prioq_item* pa_prioq_put(pa_prioq *q, void *p) { + pa_prioq_item *i; + + pa_assert(q); + + if (q->n_items >= q->n_allocated) { + q->n_allocated = PA_MAX(q->n_items+1, q->n_allocated)*2; + q->items = pa_xrealloc(q->items, sizeof(pa_prioq_item*) * q->n_allocated); + } + + if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items)))) + i = pa_xnew(pa_prioq_item, 1); + + i->value = p; + i->idx = q->n_items++; + + shuffle_up(q, i); + + return i; +} + +void* pa_prioq_peek(pa_prioq *q) { + pa_assert(q); + + if (q->n_items <= 0) + return NULL; + + return q->items[0]->value; +} + +void* pa_prioq_pop(pa_prioq *q){ + pa_assert(q); + + if (q->n_items <= 0) + return NULL; + + return pa_prioq_remove(q, q->items[0]); +} + +static void swap(pa_prioq *q, unsigned j, unsigned k) { + pa_prioq_item *t; + + pa_assert(q); + pa_assert(j < q->n_items); + pa_assert(k < q->n_items); + + pa_assert(q->items[j]->idx == j); + pa_assert(q->items[k]->idx == k); + + t = q->items[j]; + + q->items[j]->idx = k; + q->items[j] = q->items[k]; + + q->items[k]->idx = j; + q->items[k] = t; +} + +static void shuffle_down(pa_prioq *q, unsigned idx) { + + pa_assert(q); + pa_assert(idx < q->n_items); + + for (;;) { + unsigned j, k, s; + + k = (idx+1)*2; /* right child */ + j = k-1; /* left child */ + + if (j >= q->n_items) + break; + + if (q->compare_func(q->items[j]->value, q->items[idx]->value) < 0) + + /* So our left child is smaller than we are, let's + * remember this fact */ + s = j; + else + s = idx; + + if (k < q->n_items && + q->compare_func(q->items[k]->value, q->items[s]->value) < 0) + + /* So our right child is smaller than we are, let's + * remember this fact */ + s = k; + + /* s now points to the smallest of the three items */ + + if (s == idx) + /* No swap necessary, we're done */ + break; + + swap(q, idx, s); + idx = s; + } +} + +void* pa_prioq_remove(pa_prioq *q, pa_prioq_item *i) { + void *p; + + pa_assert(q); + pa_assert(i); + pa_assert(q->n_items >= 1); + + p = i->value; + + if (q->n_items-1 == i->idx) { + /* We are the last entry, so let's just remove us and good */ + q->n_items--; + + } else { + + /* We are not the last entry, we need to replace ourselves + * with the last node and reshuffle */ + + q->items[i->idx] = q->items[q->n_items-1]; + q->items[i->idx]->idx = i->idx; + q->n_items--; + + shuffle_down(q, i->idx); + } + + if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0) + pa_xfree(i); + + return p; +} + +unsigned pa_prioq_size(pa_prioq *q) { + pa_assert(q); + + return q->n_items; +} + +pa_bool_t pa_prioq_isempty(pa_prioq *q) { + pa_assert(q); + + return q->n_items == 0; +} + +void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i) { + pa_assert(q); + pa_assert(i); + + /* This will move the entry down as far as necessary */ + shuffle_down(q, i->idx); + + /* And this will move the entry up as far as necessary */ + shuffle_up(q, i); +} diff --git a/src/pulsecore/prioq.h b/src/pulsecore/prioq.h new file mode 100644 index 00000000..fd3550b7 --- /dev/null +++ b/src/pulsecore/prioq.h @@ -0,0 +1,64 @@ +#ifndef foopulsecoreprioqhfoo +#define foopulsecoreprioqhfoo + +/*** + This file is part of PulseAudio. + + Copyright 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 by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include <inttypes.h> + +#include <pulsecore/macro.h> +#include <pulsecore/idxset.h> + +/* A heap-based priority queue. Removal and insertion is O(log + * n). Removal can happen a the top or at any position referenced by a + * pa_prioq_item. */ + +typedef struct pa_prioq pa_prioq; +typedef struct pa_prioq_item pa_prioq_item; + +/* Instantiate a new prioq with the specified comparison functions */ +pa_prioq* pa_prioq_new(pa_compare_func_t compare_func); + +/* Free the prioq. When the prioq is not empty the specified function is called for every entry contained */ +void pa_prioq_free(pa_prioq *q, pa_free2_cb_t free_cb, void *userdata); + +/* Store a new item in the prioq. */ +pa_prioq_item* pa_prioq_put(pa_prioq *q, void* data); + +/* Get the item on the top of the queue, but don't remove it from the queue*/ +void* pa_prioq_peek(pa_prioq*q); + +/* Get the item on the top of the queue, and remove it from thq queue */ +void* pa_prioq_pop(pa_prioq*q); + +/* Remove an arbitrary from theq prioq, returning it's data */ +void* pa_prioq_remove(pa_prioq*q, pa_prioq_item *i); + +/* The priority of an item was modified. Adjustthe queue to that */ +void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i); + +/* Return the current number of items in the prioq */ +unsigned pa_prioq_size(pa_prioq*s); + +/* Return TRUE of the prioq is empty */ +pa_bool_t pa_prioq_isempty(pa_prioq *s); + +#endif diff --git a/src/pulsecore/proplist-util.c b/src/pulsecore/proplist-util.c index 6005775e..4d505f57 100644 --- a/src/pulsecore/proplist-util.c +++ b/src/pulsecore/proplist-util.c @@ -37,7 +37,7 @@ void pa_init_proplist(pa_proplist *p) { int a, b; -#ifndef HAVE_DECL_ENVIRON +#if !HAVE_DECL_ENVIRON extern char **environ; #endif char **e; diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 6ccee571..778aab57 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2192,6 +2192,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta if (c->version < 10 || (c->version >= 13 && !shm_on_remote)) do_shm = FALSE; +#ifdef HAVE_CREDS if (do_shm) { /* Only enable SHM if both sides are owned by the same * user. This is a security measure because otherwise data @@ -2201,6 +2202,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid) do_shm = FALSE; } +#endif pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm)); pa_pstream_enable_shm(c->pstream, do_shm); @@ -3166,6 +3168,10 @@ static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uin CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY); pa_sink_input_cork(s->sink_input, b); + + if (b) + s->is_underrun = TRUE; + pa_pstream_send_simple_ack(c->pstream, tag); } diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 65e67737..743bf2ee 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -173,7 +173,7 @@ static int do_read(connection *c) { } if (!c->playback.current_memblock) { - pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, 0)); + pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, (size_t) -1)); c->playback.memblock_index = 0; space = pa_memblock_get_length(c->playback.current_memblock); @@ -492,6 +492,8 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp c->parent.parent.free = connection_free; c->parent.process_msg = connection_process_msg; c->io = io; + pa_iochannel_set_callback(c->io, io_callback, c); + c->sink_input = NULL; c->source_output = NULL; c->input_memblockq = c->output_memblockq = NULL; @@ -610,7 +612,6 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp pa_source_output_put(c->source_output); } - pa_iochannel_set_callback(c->io, io_callback, c); pa_idxset_put(p->connections, c, NULL); return; @@ -689,6 +690,9 @@ pa_simple_options* pa_simple_options_new(void) { o = pa_xnew0(pa_simple_options, 1); PA_REFCNT_INIT(o); + o->record = FALSE; + o->playback = TRUE; + return o; } @@ -733,14 +737,14 @@ int pa_simple_options_parse(pa_simple_options *o, pa_core *c, pa_modargs *ma) { pa_xfree(o->default_sink); o->default_sink = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); - enabled = FALSE; + enabled = o->record; if (pa_modargs_get_value_boolean(ma, "record", &enabled) < 0) { pa_log("record= expects a boolean argument."); return -1; } o->record = enabled; - enabled = TRUE; + enabled = o->playback; if (pa_modargs_get_value_boolean(ma, "playback", &enabled) < 0) { pa_log("playback= expects a boolean argument."); return -1; diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index b4234af5..7b9ac7bc 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -98,56 +98,62 @@ void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) { return p; } -static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) { - unsigned k; - - pa_assert(streams); - pa_assert(spec); +static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) { + unsigned channel; - for (k = 0; k < nstreams; k++) { - unsigned channel; + pa_assert(linear); + pa_assert(volume); - for (channel = 0; channel < spec->channels; channel++) { - pa_mix_info *m = streams + k; - m->linear[channel].i = (int32_t) (pa_sw_volume_to_linear(m->volume.values[channel]) * 0x10000); - } - } + for (channel = 0; channel < volume->channels; channel++) + linear[channel] = (int32_t) lrint(pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); } -static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) { +static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) { unsigned channel; pa_assert(linear); pa_assert(volume); for (channel = 0; channel < volume->channels; channel++) - linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000); + linear[channel] = (float) pa_sw_volume_to_linear(volume->values[channel]); } -static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) { - unsigned k; +static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) { + unsigned k, channel; + float linear[PA_CHANNELS_MAX]; pa_assert(streams); pa_assert(spec); + pa_assert(volume); + + calc_linear_float_volume(linear, volume); for (k = 0; k < nstreams; k++) { - unsigned channel; for (channel = 0; channel < spec->channels; channel++) { pa_mix_info *m = streams + k; - m->linear[channel].f = (float) pa_sw_volume_to_linear(m->volume.values[channel]); + m->linear[channel].i = (int32_t) lrint(pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel] * 0x10000); } } } -static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) { - unsigned channel; +static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) { + unsigned k, channel; + float linear[PA_CHANNELS_MAX]; - pa_assert(linear); + pa_assert(streams); + pa_assert(spec); pa_assert(volume); - for (channel = 0; channel < volume->channels; channel++) - linear[channel] = (float) pa_sw_volume_to_linear(volume->values[channel]); + calc_linear_float_volume(linear, volume); + + for (k = 0; k < nstreams; k++) { + + for (channel = 0; channel < spec->channels; channel++) { + pa_mix_info *m = streams + k; + m->linear[channel].f = (float) (pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel]); + } + } } size_t pa_mix( @@ -190,10 +196,8 @@ size_t pa_mix( case PA_SAMPLE_S16NE:{ unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); while (data < end) { int32_t sum = 0; @@ -203,18 +207,16 @@ size_t pa_mix( pa_mix_info *m = streams + i; int32_t v, cv = m->linear[channel].i; - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = *((int16_t*) m->ptr); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = *((int16_t*) m->ptr); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int16_t); } - sum = (sum * linear[channel]) / 0x10000; sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); *((int16_t*) data) = (int16_t) sum; @@ -229,10 +231,8 @@ size_t pa_mix( case PA_SAMPLE_S16RE:{ unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); while (data < end) { int32_t sum = 0; @@ -242,18 +242,16 @@ size_t pa_mix( pa_mix_info *m = streams + i; int32_t v, cv = m->linear[channel].i; - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = PA_INT16_SWAP(*((int16_t*) m->ptr)); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = PA_INT16_SWAP(*((int16_t*) m->ptr)); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int16_t); } - sum = (sum * linear[channel]) / 0x10000; sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum); @@ -268,10 +266,8 @@ size_t pa_mix( case PA_SAMPLE_S32NE:{ unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); while (data < end) { int64_t sum = 0; @@ -279,21 +275,19 @@ size_t pa_mix( for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; - int64_t v; int32_t cv = m->linear[channel].i; + int64_t v; - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = *((int32_t*) m->ptr); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = *((int32_t*) m->ptr); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); } - sum = (sum * linear[channel]) / 0x10000; sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); *((int32_t*) data) = (int32_t) sum; @@ -308,10 +302,8 @@ size_t pa_mix( case PA_SAMPLE_S32RE:{ unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); while (data < end) { int64_t sum = 0; @@ -319,21 +311,19 @@ size_t pa_mix( for (i = 0; i < nstreams; i++) { pa_mix_info *m = streams + i; - int64_t v; int32_t cv = m->linear[channel].i; + int64_t v; - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = PA_INT32_SWAP(*((int32_t*) m->ptr)); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = PA_INT32_SWAP(*((int32_t*) m->ptr)); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(int32_t); } - sum = (sum * linear[channel]) / 0x10000; sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL); *((int32_t*) data) = PA_INT32_SWAP((int32_t) sum); @@ -348,10 +338,8 @@ size_t pa_mix( case PA_SAMPLE_U8: { unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); while (data < end) { int32_t sum = 0; @@ -361,18 +349,16 @@ size_t pa_mix( pa_mix_info *m = streams + i; int32_t v, cv = m->linear[channel].i; - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = (int32_t) *((uint8_t*) m->ptr) - 0x80; - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = (int32_t) *((uint8_t*) m->ptr) - 0x80; + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + 1; } - sum = (sum * linear[channel]) / 0x10000; sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F); *((uint8_t*) data) = (uint8_t) (sum + 0x80); @@ -387,10 +373,8 @@ size_t pa_mix( case PA_SAMPLE_ULAW: { unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); while (data < end) { int32_t sum = 0; @@ -400,18 +384,16 @@ size_t pa_mix( pa_mix_info *m = streams + i; int32_t v, cv = m->linear[channel].i; - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr)); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr)); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + 1; } - sum = (sum * linear[channel]) / 0x10000; sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); *((uint8_t*) data) = (uint8_t) st_14linear2ulaw((int16_t) sum >> 2); @@ -426,10 +408,8 @@ size_t pa_mix( case PA_SAMPLE_ALAW: { unsigned channel = 0; - int32_t linear[PA_CHANNELS_MAX]; - calc_linear_integer_stream_volumes(streams, nstreams, spec); - calc_linear_integer_volume(linear, volume); + calc_linear_integer_stream_volumes(streams, nstreams, volume, spec); while (data < end) { int32_t sum = 0; @@ -439,18 +419,16 @@ size_t pa_mix( pa_mix_info *m = streams + i; int32_t v, cv = m->linear[channel].i; - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr)); - v = (v * cv) / 0x10000; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr)); + v = (v * cv) / 0x10000; sum += v; + m->ptr = (uint8_t*) m->ptr + 1; } - sum = (sum * linear[channel]) / 0x10000; sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF); *((uint8_t*) data) = (uint8_t) st_13linear2alaw((int16_t) sum >> 3); @@ -465,10 +443,8 @@ size_t pa_mix( case PA_SAMPLE_FLOAT32NE: { unsigned channel = 0; - float linear[PA_CHANNELS_MAX]; - calc_linear_float_stream_volumes(streams, nstreams, spec); - calc_linear_float_volume(linear, volume); + calc_linear_float_stream_volumes(streams, nstreams, volume, spec); while (data < end) { float sum = 0; @@ -478,18 +454,16 @@ size_t pa_mix( pa_mix_info *m = streams + i; float v, cv = m->linear[channel].f; - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else { - v = *((float*) m->ptr); - v *= cv; - } + if (PA_UNLIKELY(cv <= 0)) + continue; + v = *((float*) m->ptr); + v *= cv; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(float); } - sum *= linear[channel]; *((float*) data) = sum; data = (uint8_t*) data + sizeof(float); @@ -505,8 +479,7 @@ size_t pa_mix( unsigned channel = 0; float linear[PA_CHANNELS_MAX]; - calc_linear_float_stream_volumes(streams, nstreams, spec); - calc_linear_float_volume(linear, volume); + calc_linear_float_stream_volumes(streams, nstreams, volume, spec); while (data < end) { float sum = 0; @@ -516,16 +489,16 @@ size_t pa_mix( pa_mix_info *m = streams + i; float v, cv = m->linear[channel].f; - if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0)) - v = 0; - else - v = PA_FLOAT32_SWAP(*(float*) m->ptr) *cv; + if (PA_UNLIKELY(cv <= 0)) + continue; + v = PA_FLOAT32_SWAP(*(float*) m->ptr); + v *= cv; sum += v; + m->ptr = (uint8_t*) m->ptr + sizeof(float); } - sum *= linear[channel]; *((float*) data) = PA_FLOAT32_SWAP(sum); data = (uint8_t*) data + sizeof(float); diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c index 693d529b..159c4655 100644 --- a/src/pulsecore/sconv-s16le.c +++ b/src/pulsecore/sconv-s16le.c @@ -111,7 +111,7 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) { float v = *(a++); v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.f); - s = (int16_t) (v * 0x7FFF); + s = (int16_t) lrintf(v * 0x7FFF); *(b++) = INT16_TO(s); } @@ -134,7 +134,7 @@ void pa_sconv_s32le_from_float32ne(unsigned n, const float *a, int32_t *b) { float v = *(a++); v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); - s = (int32_t) ((double) v * (double) 0x7FFFFFFF); + s = (int32_t) lrint((double) v * (double) 0x7FFFFFFF); *(b++) = INT32_TO(s); } @@ -153,8 +153,7 @@ void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) { for (; n > 0; n--) { int16_t s = *(a++); float k = ((float) INT16_FROM(s))/0x7FFF; - uint32_t *j = (uint32_t*) &k; - *j = PA_UINT32_SWAP(*j); + k = PA_FLOAT32_SWAP(k); *(b++) = k; } } @@ -166,8 +165,7 @@ void pa_sconv_s32le_to_float32re(unsigned n, const int32_t *a, float *b) { for (; n > 0; n--) { int32_t s = *(a++); float k = (float) (((double) INT32_FROM(s))/0x7FFFFFFF); - uint32_t *j = (uint32_t*) &k; - *j = PA_UINT32_SWAP(*j); + k = PA_FLOAT32_SWAP(k); *(b++) = k; } } @@ -179,10 +177,9 @@ void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) { for (; n > 0; n--) { int16_t s; float v = *(a++); - uint32_t *j = (uint32_t*) &v; - *j = PA_UINT32_SWAP(*j); + v = PA_FLOAT32_SWAP(v); v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); - s = (int16_t) (v * 0x7FFF); + s = (int16_t) lrintf(v * 0x7FFF); *(b++) = INT16_TO(s); } } @@ -194,10 +191,9 @@ void pa_sconv_s32le_from_float32re(unsigned n, const float *a, int32_t *b) { for (; n > 0; n--) { int32_t s; float v = *(a++); - uint32_t *j = (uint32_t*) &v; - *j = PA_UINT32_SWAP(*j); + v = PA_FLOAT32_SWAP(v); v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); - s = (int32_t) ((double) v * 0x7FFFFFFF); + s = (int32_t) lrint((double) v * 0x7FFFFFFF); *(b++) = INT32_TO(s); } } diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index 733a46ae..6c4d420e 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -130,7 +130,7 @@ static void ulaw_from_float32ne(unsigned n, const float *a, uint8_t *b) { float v = *(a++); v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); v *= 0x1FFF; - *(b++) = st_14linear2ulaw((int16_t) v); + *(b++) = st_14linear2ulaw((int16_t) lrintf(v)); } } @@ -168,7 +168,7 @@ static void alaw_from_float32ne(unsigned n, const float *a, uint8_t *b) { float v = *a; v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); v *= 0xFFF; - *b = st_13linear2alaw((int16_t) v); + *b = st_13linear2alaw((int16_t) lrintf(v)); } } diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 326a7e2c..4f70347f 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -1030,6 +1030,9 @@ void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state } else if (uncorking) { + i->thread_info.underrun_for = (uint64_t) -1; + i->thread_info.playing_for = 0; + pa_log_debug("Requesting rewind due to uncorking"); /* OK, we're being uncorked. Make sure we're not rewound when diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 6fa22dc2..e04fc08a 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -663,7 +663,6 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume); if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) { - pa_log("adjusting volume "); pa_memchunk_make_writable(result, 0); if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) pa_silence_memchunk(result, &s->sample_spec); diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h index 87e850d6..eabe9ba4 100644 --- a/src/pulsecore/thread.h +++ b/src/pulsecore/thread.h @@ -25,6 +25,7 @@ #include <pulse/def.h> #include <pulsecore/once.h> +#include <pulsecore/core-util.h> #ifndef PACKAGE #error "Please include config.h before including this file!" @@ -69,6 +70,8 @@ void *pa_tls_set(pa_tls *t, void *userdata); static void name##_tls_destructor(void) PA_GCC_DESTRUCTOR; \ static void name##_tls_destructor(void) { \ static void (*_free_cb)(void*) = free_cb; \ + if (!pa_in_valgrind()) \ + return; \ if (!name##_tls.tls) \ return; \ if (_free_cb) { \ diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c index b165f4a8..6a2ffaa6 100644 --- a/src/pulsecore/time-smoother.c +++ b/src/pulsecore/time-smoother.c @@ -284,7 +284,7 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) { /* The requested point is right of the point where we wanted * to be on track again, thus just linearly estimate */ - t = (int64_t) s->py + (int64_t) (s->dp * (double) (x - s->px)); + t = (int64_t) s->py + (int64_t) llrint(s->dp * (double) (x - s->px)); if (t < 0) t = 0; @@ -313,7 +313,7 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) { /* Move back from origin */ ty += (double) s->ey; - *y = ty >= 0 ? (pa_usec_t) ty : 0; + *y = ty >= 0 ? (pa_usec_t) lrint(ty) : 0; /* Horner scheme */ if (deriv) @@ -360,7 +360,7 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) { /* And calculate when we want to be on track again */ s->px = s->ex + s->adjust_time; - s->py = s->ry + (pa_usec_t) (s->dp * (double) s->adjust_time); + s->py = s->ry + (pa_usec_t) lrint(s->dp * (double) s->adjust_time); s->abc_valid = FALSE; @@ -456,7 +456,7 @@ pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay) /* pa_log_debug("translate(%llu) = %llu (%0.2f)", (unsigned long long) y_delay, (unsigned long long) ((double) y_delay / nde), nde); */ - return (pa_usec_t) ((double) y_delay / nde); + return (pa_usec_t) lrint((double) y_delay / nde); } void pa_smoother_reset(pa_smoother *s) { |