diff options
Diffstat (limited to 'src/pulsecore')
-rw-r--r-- | src/pulsecore/atomic.h | 46 | ||||
-rw-r--r-- | src/pulsecore/authkey.c | 12 | ||||
-rw-r--r-- | src/pulsecore/core-util.c | 49 | ||||
-rw-r--r-- | src/pulsecore/core-util.h | 36 | ||||
-rw-r--r-- | src/pulsecore/log.c | 49 | ||||
-rw-r--r-- | src/pulsecore/log.h | 4 | ||||
-rw-r--r-- | src/pulsecore/memblockq.h | 2 | ||||
-rw-r--r-- | src/pulsecore/module.c | 4 | ||||
-rw-r--r-- | src/pulsecore/object.h | 2 | ||||
-rw-r--r-- | src/pulsecore/pid.c | 4 | ||||
-rw-r--r-- | src/pulsecore/protocol-native.c | 193 | ||||
-rw-r--r-- | src/pulsecore/resampler.c | 6 | ||||
-rw-r--r-- | src/pulsecore/sample-util.c | 33 | ||||
-rw-r--r-- | src/pulsecore/sample-util.h | 3 | ||||
-rw-r--r-- | src/pulsecore/shm.c | 6 | ||||
-rw-r--r-- | src/pulsecore/sink-input.c | 5 | ||||
-rw-r--r-- | src/pulsecore/sink.c | 16 | ||||
-rw-r--r-- | src/pulsecore/socket-client.c | 2 | ||||
-rw-r--r-- | src/pulsecore/sound-file.c | 4 | ||||
-rw-r--r-- | src/pulsecore/source-output.c | 5 | ||||
-rw-r--r-- | src/pulsecore/source.c | 3 | ||||
-rw-r--r-- | src/pulsecore/tagstruct.c | 4 |
22 files changed, 352 insertions, 136 deletions
diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index a91c4d56..9c58c661 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -23,6 +23,8 @@ USA. ***/ +#include <pulsecore/macro.h> + /* * atomic_ops guarantees us that sizeof(AO_t) == sizeof(void*). It is * not guaranteed however, that sizeof(AO_t) == sizeof(size_t). @@ -35,7 +37,7 @@ * On gcc >= 4.1 we use the builtin atomic functions. otherwise we use * libatomic_ops */ -# + #ifndef PACKAGE #error "Please include config.h before including this file!" #endif @@ -80,8 +82,8 @@ static inline int pa_atomic_dec(pa_atomic_t *a) { return pa_atomic_sub(a, 1); } -/* Returns non-zero when the operation was successful. */ -static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { +/* Returns TRUE when the operation was successful. */ +static inline pa_bool_t pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { return __sync_bool_compare_and_swap(&a->value, old_i, new_i); } @@ -101,13 +103,13 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { __sync_synchronize(); } -static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { return __sync_bool_compare_and_swap(&a->value, (long) old_p, (long) new_p); } #elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)) -#error "The native atomic operations implementation for AMD64 has not been tested. libatomic_ops is known to not work properly on AMD64 and your gcc version is too old for the gcc-builtin atomic ops support. You have three options now: make the native atomic operations implementation for AMD64 work, fix libatomic_ops, or upgrade your GCC." +#warn "The native atomic operations implementation for AMD64 has not been tested thoroughly. libatomic_ops is known to not work properly on AMD64 and your gcc version is too old for the gcc-builtin atomic ops support. You have three options now: test the native atomic operations implementation for AMD64, fix libatomic_ops, or upgrade your GCC." /* Addapted from glibc */ @@ -147,14 +149,14 @@ static inline int pa_atomic_dec(pa_atomic_t *a) { return pa_atomic_sub(a, 1); } -static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { +static inline pa_bool_t pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { int result; __asm__ __volatile__ ("lock; cmpxchgl %2, %1" : "=a" (result), "=m" (a->value) : "r" (new_i), "m" (a->value), "0" (old_i)); - return result == oldval; + return result == old_i; } typedef struct pa_atomic_ptr { @@ -171,14 +173,14 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { a->value = (unsigned long) p; } -static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { void *result; __asm__ __volatile__ ("lock; cmpxchgq %q2, %1" : "=a" (result), "=m" (a->value) : "r" (new_p), "m" (a->value), "0" (old_p)); - return result; + return result == old_p; } #elif defined(ATOMIC_ARM_INLINE_ASM) @@ -255,7 +257,7 @@ static inline int pa_atomic_dec(pa_atomic_t *a) { return pa_atomic_sub(a, 1); } -static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { +static inline pa_bool_t pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { unsigned long not_equal, not_exclusive; pa_memory_barrier(); @@ -289,7 +291,7 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { pa_memory_barrier(); } -static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { unsigned long not_equal, not_exclusive; pa_memory_barrier(); @@ -377,8 +379,8 @@ static inline int pa_atomic_dec(pa_atomic_t *a) { return pa_atomic_sub(a, 1); } -/* Returns non-zero when the operation was successful. */ -static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { +/* Returns TRUE when the operation was successful. */ +static inline pa_bool_t pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { pa_bool_t failed; do { failed = !!__kernel_cmpxchg(old_i, new_i, &a->value); @@ -402,7 +404,7 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { pa_memory_barrier(); } -static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { pa_bool_t failed; do { failed = !!__kernel_cmpxchg_u((unsigned long) old_p, (unsigned long) new_p, &a->value); @@ -420,7 +422,7 @@ typedef struct pa_atomic { volatile AO_t value; } pa_atomic_t; -#define PA_ATOMIC_INIT(v) { .value = (v) } +#define PA_ATOMIC_INIT(v) { .value = (AO_t) (v) } static inline int pa_atomic_load(const pa_atomic_t *a) { return (int) AO_load_full((AO_t*) &a->value); @@ -431,23 +433,23 @@ static inline void pa_atomic_store(pa_atomic_t *a, int i) { } static inline int pa_atomic_add(pa_atomic_t *a, int i) { - return AO_fetch_and_add_full(&a->value, (AO_t) i); + return (int) AO_fetch_and_add_full(&a->value, (AO_t) i); } static inline int pa_atomic_sub(pa_atomic_t *a, int i) { - return AO_fetch_and_add_full(&a->value, (AO_t) -i); + return (int) AO_fetch_and_add_full(&a->value, (AO_t) -i); } static inline int pa_atomic_inc(pa_atomic_t *a) { - return AO_fetch_and_add1_full(&a->value); + return (int) AO_fetch_and_add1_full(&a->value); } static inline int pa_atomic_dec(pa_atomic_t *a) { - return AO_fetch_and_sub1_full(&a->value); + return (int) AO_fetch_and_sub1_full(&a->value); } -static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { - return AO_compare_and_swap_full(&a->value, old_i, new_i); +static inline pa_bool_t pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { + return AO_compare_and_swap_full(&a->value, (unsigned long) old_i, (unsigned long) new_i); } typedef struct pa_atomic_ptr { @@ -464,7 +466,7 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { AO_store_full(&a->value, (AO_t) p); } -static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { return AO_compare_and_swap_full(&a->value, (AO_t) old_p, (AO_t) new_p); } diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c index f3f40f80..b122feee 100644 --- a/src/pulsecore/authkey.c +++ b/src/pulsecore/authkey.c @@ -54,8 +54,8 @@ static int generate(int fd, void *ret_data, size_t length) { pa_random(ret_data, length); - lseek(fd, 0, SEEK_SET); - (void) ftruncate(fd, 0); + lseek(fd, (off_t) 0, SEEK_SET); + (void) ftruncate(fd, (off_t) 0); if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) { pa_log("Failed to write cookie file: %s", pa_cstrerror(errno)); @@ -88,7 +88,7 @@ static int load(const char *fn, void *data, size_t length) { if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) { if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY|O_NOCTTY)) < 0) { - pa_log("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } else writable = 0; @@ -105,7 +105,7 @@ static int load(const char *fn, void *data, size_t length) { pa_log_debug("Got %d bytes from cookie file '%s', expected %d", (int) r, fn, (int) length); if (!writable) { - pa_log("Unable to write cookie to read only file"); + pa_log_warn("Unable to write cookie to read-only file"); goto finish; } @@ -140,7 +140,7 @@ int pa_authkey_load(const char *path, void *data, size_t length) { pa_assert(length > 0); if ((ret = load(path, data, length)) < 0) - pa_log("Failed to load authorization key '%s': %s", path, (ret < 0) ? pa_cstrerror(errno) : "File corrupt"); + pa_log_warn("Failed to load authorization key '%s': %s", path, (ret < 0) ? pa_cstrerror(errno) : "File corrupt"); return ret; } @@ -206,7 +206,7 @@ int pa_authkey_save(const char *fn, const void *data, size_t length) { return -2; if ((fd = open(p, O_RDWR|O_CREAT|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) { - pa_log("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); + pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno)); goto finish; } diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 41a31042..ad00f4f4 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -398,7 +398,15 @@ int pa_close(int fd) { } #endif - return close(fd); + for (;;) { + int r; + + if ((r = close(fd)) >= 0) + return r; + + if (errno != EINTR) + return r; + } } /* Print a warning messages in case that the given signal is not @@ -2041,7 +2049,7 @@ void *pa_will_need(const void *p, size_t l) { return (void*) p; } - bs = PA_PAGE_ALIGN(rlim.rlim_cur); + bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur); #else bs = PA_PAGE_SIZE*4; #endif @@ -2383,18 +2391,29 @@ char *pa_machine_id(void) { FILE *f; size_t l; + /* The returned value is supposed be some kind of ascii identifier + * that is unique and stable across reboots. */ + + /* First we try the D-Bus UUID, which is the best option we have, + * since it fits perfectly our needs and is not as volatile as the + * hostname which might be set from dhcp. */ + if ((f = fopen(PA_MACHINE_ID, "r"))) { char ln[34] = "", *r; r = fgets(ln, sizeof(ln)-1, f); fclose(f); - if (r) - return pa_xstrdup(pa_strip_nl(ln)); + pa_strip_nl(ln); + + if (ln[0]) + return pa_xstrdup(ln); } - l = 100; + /* The we fall back to the host name. It supposed to be somewhat + * unique, at least in a network, but may change. */ + l = 100; for (;;) { char *c; @@ -2402,17 +2421,18 @@ char *pa_machine_id(void) { if (!pa_get_host_name(c, l)) { - if (errno == EINVAL || errno == ENAMETOOLONG) { + if (errno != EINVAL && errno != ENAMETOOLONG) + break; + + } else if (strlen(c) < l-1) { + + if (*c == 0) { pa_xfree(c); - l *= 2; - continue; + break; } - return NULL; - } - - if (strlen(c) < l-1) return c; + } /* Hmm, the hostname is as long the space we offered the * function, we cannot know if it fully fit in, so let's play @@ -2421,4 +2441,9 @@ char *pa_machine_id(void) { pa_xfree(c); l *= 2; } + + /* If no hostname was set we use the POSIX hostid. It's usually + * the IPv4 address. Mit not be that stable. */ + return pa_sprintf_malloc("%08lx", (unsigned long) gethostid); + } diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 7167972b..c9e307f5 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -142,29 +142,35 @@ static inline int pa_is_power_of_two(unsigned n) { return !(n & (n - 1)); } -static inline unsigned pa_make_power_of_two(unsigned n) { - unsigned j = n; +static inline unsigned pa_ulog2(unsigned n) { - if (pa_is_power_of_two(n)) - return n; + if (n <= 1) + return 0; - while (j) { - j = j >> 1; - n = n | j; - } +#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + return 8U * (unsigned) sizeof(unsigned) - (unsigned) __builtin_clz(n) - 1; +#else +{ + unsigned r = 0; - return n + 1; -} + for (;;) { + n = n >> 1; -static inline unsigned pa_ulog2(unsigned n) { - unsigned r = 0; + if (!n) + return r; - while (n) { r++; - n = n >> 1; } +} +#endif +} + +static inline unsigned pa_make_power_of_two(unsigned n) { + + if (pa_is_power_of_two(n)) + return n; - return r; + return 1U << (pa_ulog2(n) + 1); } void pa_close_pipe(int fds[2]); diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 5eda4f65..d7318081 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -37,19 +37,23 @@ #include <pulse/utf8.h> #include <pulse/xmalloc.h> #include <pulse/util.h> +#include <pulse/timeval.h> #include <pulsecore/macro.h> #include <pulsecore/core-util.h> +#include <pulsecore/rtclock.h> +#include <pulsecore/once.h> #include "log.h" #define ENV_LOGLEVEL "PULSE_LOG" #define ENV_LOGMETA "PULSE_LOG_META" +#define ENV_LOGTIME "PULSE_LOG_TIME" static char *log_ident = NULL, *log_ident_local = NULL; static pa_log_target_t log_target = PA_LOG_STDERR; -static void (*user_log_func)(pa_log_level_t l, const char *s) = NULL; -static pa_log_level_t maximal_level = PA_LOG_NOTICE; +static pa_log_func_t user_log_func = NULL; +static pa_log_level_t maximal_level = PA_LOG_ERROR; #ifdef HAVE_SYSLOG_H static const int level_to_syslog[] = { @@ -91,7 +95,7 @@ void pa_log_set_maximal_level(pa_log_level_t l) { maximal_level = l; } -void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t l, const char*s)) { +void pa_log_set_target(pa_log_target_t t, pa_log_func_t func) { pa_assert(t == PA_LOG_USER || !func); log_target = t; @@ -112,7 +116,7 @@ void pa_log_levelv_meta( /* We don't use dynamic memory allocation here to minimize the hit * in RT threads */ - char text[1024], location[128]; + char text[1024], location[128], timestamp[32]; pa_assert(level < PA_LOG_LEVEL_MAX); pa_assert(format); @@ -134,6 +138,33 @@ void pa_log_levelv_meta( else location[0] = 0; + if (getenv(ENV_LOGTIME)) { + static pa_usec_t start, last; + pa_usec_t u, a, r; + + u = pa_rtclock_usec(); + + PA_ONCE_BEGIN { + start = u; + last = u; + } PA_ONCE_END; + + r = u - last; + a = u - start; + + /* This is not thread safe, but this is a debugging tool only + * anyway. */ + last = u; + + pa_snprintf(timestamp, sizeof(timestamp), "(%4llu.%03llu|%4llu.%03llu) ", + (unsigned long long) (a / PA_USEC_PER_SEC), + (unsigned long long) (((a / PA_USEC_PER_MSEC)) % 1000), + (unsigned long long) (r / PA_USEC_PER_SEC), + (unsigned long long) (((r / PA_USEC_PER_MSEC)) % 1000)); + + } else + timestamp[0] = 0; + if (!pa_utf8_valid(text)) pa_log_level(level, __FILE__": invalid UTF-8 string following below:"); @@ -168,9 +199,9 @@ void pa_log_levelv_meta( * minimize the hit in RT threads */ local_t = pa_utf8_to_locale(t); if (!local_t) - fprintf(stderr, "%c: %s%s%s%s\n", level_to_char[level], location, prefix, t, suffix); + fprintf(stderr, "%s%c: %s%s%s%s\n", timestamp, level_to_char[level], location, prefix, t, suffix); else { - fprintf(stderr, "%c: %s%s%s%s\n", level_to_char[level], location, prefix, local_t, suffix); + fprintf(stderr, "%s%c: %s%s%s%s\n", timestamp, level_to_char[level], location, prefix, local_t, suffix); pa_xfree(local_t); } @@ -185,9 +216,9 @@ void pa_log_levelv_meta( local_t = pa_utf8_to_locale(t); if (!local_t) - syslog(level_to_syslog[level], "%s%s", location, t); + syslog(level_to_syslog[level], "%s%s%s", timestamp, location, t); else { - syslog(level_to_syslog[level], "%s%s", location, local_t); + syslog(level_to_syslog[level], "%s%s%s", timestamp, location, local_t); pa_xfree(local_t); } @@ -199,7 +230,7 @@ void pa_log_levelv_meta( case PA_LOG_USER: { char x[1024]; - pa_snprintf(x, sizeof(x), "%s%s", location, t); + pa_snprintf(x, sizeof(x), "%s%s%s", timestamp, location, t); user_log_func(level, x); break; diff --git a/src/pulsecore/log.h b/src/pulsecore/log.h index 2047696e..633227f3 100644 --- a/src/pulsecore/log.h +++ b/src/pulsecore/log.h @@ -49,8 +49,10 @@ typedef enum pa_log_level { /* Set an identification for the current daemon. Used when logging to syslog. */ void pa_log_set_ident(const char *p); +typedef void (*pa_log_func_t)(pa_log_level_t t, const char*s); + /* Set another log target. If t is PA_LOG_USER you may specify a function that is called every log string */ -void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t t, const char*s)); +void pa_log_set_target(pa_log_target_t t, pa_log_func_t func); /* Minimal log level */ void pa_log_set_maximal_level(pa_log_level_t l); diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h index 4b9450f6..31f908df 100644 --- a/src/pulsecore/memblockq.h +++ b/src/pulsecore/memblockq.h @@ -155,7 +155,7 @@ void pa_memblockq_set_maxlength(pa_memblockq *memblockq, size_t maxlength); /* m void pa_memblockq_set_tlength(pa_memblockq *memblockq, size_t tlength); /* might modify minreq, too */ void pa_memblockq_set_prebuf(pa_memblockq *memblockq, size_t prebuf); /* might modify minreq, too */ void pa_memblockq_set_minreq(pa_memblockq *memblockq, size_t minreq); -void pa_memblockq_set_maxrewind(pa_memblockq *memblockq, size_t rewind); /* Set the maximum history size */ +void pa_memblockq_set_maxrewind(pa_memblockq *memblockq, size_t maxrewind); /* Set the maximum history size */ void pa_memblockq_set_silence(pa_memblockq *memblockq, pa_memchunk *silence); /* Call pa_memchunk_willneed() for every chunk in the queue from the current read pointer to the end */ diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c index 29003af8..9b17cb91 100644 --- a/src/pulsecore/module.c +++ b/src/pulsecore/module.c @@ -59,7 +59,7 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, const struct t pa_module_unload_unused(c); pa_gettimeofday(&ntv); - pa_timeval_add(&ntv, UNLOAD_POLL_TIME*1000000); + pa_timeval_add(&ntv, UNLOAD_POLL_TIME*PA_USEC_PER_SEC); m->time_restart(e, &ntv); } @@ -124,7 +124,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) { if (m->auto_unload && !c->module_auto_unload_event) { struct timeval ntv; pa_gettimeofday(&ntv); - pa_timeval_add(&ntv, UNLOAD_POLL_TIME*1000000); + pa_timeval_add(&ntv, UNLOAD_POLL_TIME*PA_USEC_PER_SEC); c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c); } diff --git a/src/pulsecore/object.h b/src/pulsecore/object.h index 7dcfa2eb..2ee4fc31 100644 --- a/src/pulsecore/object.h +++ b/src/pulsecore/object.h @@ -42,7 +42,7 @@ struct pa_object { pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(const char *type_name)); #define pa_object_new(type) ((type*) pa_object_new_internal(sizeof(type), #type, type##_check_type) -#define pa_object_free ((void (*) (pa_object* o)) pa_xfree) +#define pa_object_free ((void (*) (pa_object* _obj)) pa_xfree) int pa_object_check_type(const char *type); diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c index 1c0851ba..ce8ef19b 100644 --- a/src/pulsecore/pid.c +++ b/src/pulsecore/pid.c @@ -235,7 +235,7 @@ int pa_pid_file_create(const char *procname) { } /* Overwrite the current PID file */ - if (lseek(fd, 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, 0) < 0) { + if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1 || ftruncate(fd, (off_t) 0) < 0) { pa_log("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } @@ -288,7 +288,7 @@ int pa_pid_file_remove(void) { goto fail; } - if (ftruncate(fd, 0) < 0) { + if (ftruncate(fd, (off_t) 0) < 0) { pa_log_warn("Failed to truncate PID file '%s': %s", fn, pa_cstrerror(errno)); goto fail; } diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index d4694a05..6ccee571 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -469,44 +469,95 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i return 0; } -static void fix_record_buffer_attr_pre(record_stream *s, pa_bool_t adjust_latency, uint32_t *maxlength, uint32_t *fragsize) { +static void fix_record_buffer_attr_pre( + record_stream *s, + pa_bool_t adjust_latency, + pa_bool_t early_requests, + uint32_t *maxlength, + uint32_t *fragsize) { + + size_t frame_size; + pa_usec_t orig_fragsize_usec, fragsize_usec, source_usec; + pa_assert(s); pa_assert(maxlength); pa_assert(fragsize); + frame_size = pa_frame_size(&s->source_output->sample_spec); + if (*maxlength == (uint32_t) -1 || *maxlength > MAX_MEMBLOCKQ_LENGTH) *maxlength = MAX_MEMBLOCKQ_LENGTH; if (*maxlength <= 0) - *maxlength = (uint32_t) pa_frame_size(&s->source_output->sample_spec); + *maxlength = (uint32_t) frame_size; if (*fragsize == (uint32_t) -1) *fragsize = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec); if (*fragsize <= 0) - *fragsize = (uint32_t) pa_frame_size(&s->source_output->sample_spec); + *fragsize = (uint32_t) frame_size; + + orig_fragsize_usec = fragsize_usec = pa_bytes_to_usec(*fragsize, &s->source_output->sample_spec); + + if (early_requests) { - if (adjust_latency) { - pa_usec_t fragsize_usec; + /* In early request mode we need to emulate the classic + * fragment-based playback model. We do this setting the source + * latency to the fragment size. */ + + source_usec = fragsize_usec; + + } else if (adjust_latency) { /* So, the user asked us to adjust the latency according to * what the source can provide. Half the latency will be * spent on the hw buffer, half of it in the async buffer * queue we maintain for each client. */ - fragsize_usec = pa_bytes_to_usec(*fragsize, &s->source_output->sample_spec); + source_usec = fragsize_usec/2; + + } else { + + /* Ok, the user didn't ask us to adjust the latency, hence we + * don't */ + + source_usec = 0; + } + + if (source_usec > 0) + s->source_latency = pa_source_output_set_requested_latency(s->source_output, source_usec); + else + s->source_latency = 0; + + if (early_requests) { + + /* Ok, we didn't necessarily get what we were asking for, so + * let's tell the user */ - s->source_latency = pa_source_output_set_requested_latency(s->source_output, fragsize_usec/2); + fragsize_usec = s->source_latency; + + } else if (adjust_latency) { + + /* Now subtract what we actually got */ if (fragsize_usec >= s->source_latency*2) fragsize_usec -= s->source_latency; else fragsize_usec = s->source_latency; + } + + if (pa_usec_to_bytes(orig_fragsize_usec, &s->source_output->sample_spec) != + pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec)) *fragsize = (uint32_t) pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec); - } else - s->source_latency = 0; + + if (*fragsize <= 0) + *fragsize = (uint32_t) frame_size; } -static void fix_record_buffer_attr_post(record_stream *s, uint32_t *maxlength, uint32_t *fragsize) { +static void fix_record_buffer_attr_post( + record_stream *s, + uint32_t *maxlength, + uint32_t *fragsize) { + size_t base; pa_assert(s); @@ -538,7 +589,8 @@ static record_stream* record_stream_new( pa_source_output_flags_t flags, pa_proplist *p, pa_bool_t adjust_latency, - pa_sink_input *direct_on_input) { + pa_sink_input *direct_on_input, + pa_bool_t early_requests) { record_stream *s; pa_source_output *source_output; @@ -584,7 +636,7 @@ static record_stream* record_stream_new( s->source_output->suspend = source_output_suspend_cb; s->source_output->userdata = s; - fix_record_buffer_attr_pre(s, adjust_latency, maxlength, fragsize); + fix_record_buffer_attr_pre(s, adjust_latency, early_requests, maxlength, fragsize); s->memblockq = pa_memblockq_new( 0, @@ -690,6 +742,8 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: { pa_tagstruct *t; +/* pa_log("signalling underflow"); */ + /* Report that we're empty */ t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW); @@ -734,9 +788,17 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, return 0; } -static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_latency, uint32_t *maxlength, uint32_t *tlength, uint32_t* prebuf, uint32_t* minreq) { +static void fix_playback_buffer_attr_pre( + playback_stream *s, + pa_bool_t adjust_latency, + pa_bool_t early_requests, + uint32_t *maxlength, + uint32_t *tlength, + uint32_t* prebuf, + uint32_t* minreq) { + size_t frame_size; - pa_usec_t tlength_usec, minreq_usec, sink_usec; + pa_usec_t orig_tlength_usec, tlength_usec, orig_minreq_usec, minreq_usec, sink_usec; pa_assert(s); pa_assert(maxlength); @@ -752,26 +814,36 @@ static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_la *maxlength = (uint32_t) frame_size; if (*tlength == (uint32_t) -1) - *tlength = (uint32_t) pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec); + *tlength = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec); if (*tlength <= 0) *tlength = (uint32_t) frame_size; if (*minreq == (uint32_t) -1) - *minreq = (uint32_t) pa_usec_to_bytes(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec); + *minreq = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec); if (*minreq <= 0) *minreq = (uint32_t) frame_size; if (*tlength < *minreq+frame_size) *tlength = *minreq+(uint32_t) frame_size; - tlength_usec = pa_bytes_to_usec(*tlength, &s->sink_input->sample_spec); - minreq_usec = pa_bytes_to_usec(*minreq, &s->sink_input->sample_spec); + orig_tlength_usec = tlength_usec = pa_bytes_to_usec(*tlength, &s->sink_input->sample_spec); + orig_minreq_usec = minreq_usec = pa_bytes_to_usec(*minreq, &s->sink_input->sample_spec); pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms", (double) tlength_usec / PA_USEC_PER_MSEC, (double) minreq_usec / PA_USEC_PER_MSEC); - if (adjust_latency) { + if (early_requests) { + + /* In early request mode we need to emulate the classic + * fragment-based playback model. We do this setting the sink + * latency to the fragment size. */ + + sink_usec = minreq_usec; + + pa_log_debug("Early requests mode enabled, configuring sink latency to minreq."); + + } else if (adjust_latency) { /* So, the user asked us to adjust the latency of the stream * buffer according to the what the sink can provide. The @@ -795,6 +867,8 @@ static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_la else sink_usec = 0; + pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency."); + } else { /* Ok, the user didn't ask us to adjust the latency, but we @@ -805,11 +879,21 @@ static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_la sink_usec = (tlength_usec - minreq_usec*2); else sink_usec = 0; + + pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq."); } s->sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec); - if (adjust_latency) { + if (early_requests) { + + /* Ok, we didn't necessarily get what we were asking for, so + * let's tell the user */ + + minreq_usec = s->sink_latency; + + } else if (adjust_latency) { + /* Ok, we didn't necessarily get what we were asking for, so * let's subtract from what we asked for for the remaining * buffer space */ @@ -823,11 +907,16 @@ static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_la if (tlength_usec < s->sink_latency + 2*minreq_usec) tlength_usec = s->sink_latency + 2*minreq_usec; - *tlength = (uint32_t) pa_usec_to_bytes(tlength_usec, &s->sink_input->sample_spec); - *minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec); + if (pa_usec_to_bytes_round_up(orig_tlength_usec, &s->sink_input->sample_spec) != + pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec)) + *tlength = (uint32_t) pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec); + + if (pa_usec_to_bytes(orig_minreq_usec, &s->sink_input->sample_spec) != + pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec)) + *minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec); if (*minreq <= 0) { - *minreq += (uint32_t) frame_size; + *minreq = (uint32_t) frame_size; *tlength += (uint32_t) frame_size*2; } @@ -838,7 +927,13 @@ static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_la *prebuf = *tlength; } -static void fix_playback_buffer_attr_post(playback_stream *s, uint32_t *maxlength, uint32_t *tlength, uint32_t* prebuf, uint32_t* minreq) { +static void fix_playback_buffer_attr_post( + playback_stream *s, + uint32_t *maxlength, + uint32_t *tlength, + uint32_t* prebuf, + uint32_t* minreq) { + pa_assert(s); pa_assert(maxlength); pa_assert(tlength); @@ -868,7 +963,8 @@ static playback_stream* playback_stream_new( uint32_t *missing, pa_sink_input_flags_t flags, pa_proplist *p, - pa_bool_t adjust_latency) { + pa_bool_t adjust_latency, + pa_bool_t early_requests) { playback_stream *s, *ssync; pa_sink_input *sink_input; @@ -949,7 +1045,7 @@ static playback_stream* playback_stream_new( start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0; - fix_playback_buffer_attr_pre(s, adjust_latency, maxlength, tlength, prebuf, minreq); + fix_playback_buffer_attr_pre(s, adjust_latency, early_requests, maxlength, tlength, prebuf, minreq); pa_sink_input_get_silence(sink_input, &silence); s->memblockq = pa_memblockq_new( @@ -982,7 +1078,6 @@ static playback_stream* playback_stream_new( return s; } - /* Called from thread context */ static void playback_stream_request_bytes(playback_stream *s) { size_t m, previous_missing; @@ -1142,7 +1237,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) { pa_log_debug("Requesting rewind due to end of underrun."); pa_sink_input_request_rewind(s->sink_input, - s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for, + (size_t) (s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for), FALSE, TRUE); } @@ -1426,7 +1521,7 @@ static void sink_input_moved_cb(pa_sink_input *i) { prebuf = (uint32_t) pa_memblockq_get_prebuf(s->memblockq); minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq); - fix_playback_buffer_attr_pre(s, TRUE, &maxlength, &tlength, &prebuf, &minreq); + fix_playback_buffer_attr_pre(s, TRUE, FALSE, &maxlength, &tlength, &prebuf, &minreq); pa_memblockq_set_maxlength(s->memblockq, maxlength); pa_memblockq_set_tlength(s->memblockq, tlength); pa_memblockq_set_prebuf(s->memblockq, prebuf); @@ -1525,7 +1620,7 @@ static void source_output_moved_cb(pa_source_output *o) { fragsize = (uint32_t) s->fragment_size; maxlength = (uint32_t) pa_memblockq_get_length(s->memblockq); - fix_record_buffer_attr_pre(s, TRUE, &maxlength, &fragsize); + fix_record_buffer_attr_pre(s, TRUE, FALSE, &maxlength, &fragsize); pa_memblockq_set_maxlength(s->memblockq, maxlength); fix_record_buffer_attr_post(s, &maxlength, &fragsize); @@ -1592,7 +1687,8 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u no_move = FALSE, variable_rate = FALSE, muted = FALSE, - adjust_latency = FALSE; + adjust_latency = FALSE, + early_requests = FALSE; pa_sink_input_flags_t flags = 0; pa_proplist *p; @@ -1665,7 +1761,8 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u if (c->version >= 14) { - if (pa_tagstruct_get_boolean(t, &volume_set) < 0) { + if (pa_tagstruct_get_boolean(t, &volume_set) < 0 || + pa_tagstruct_get_boolean(t, &early_requests) < 0) { protocol_error(c); pa_proplist_free(p); return; @@ -1705,7 +1802,7 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u (no_move ? PA_SINK_INPUT_DONT_MOVE : 0) | (variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0); - s = playback_stream_new(c, sink, &ss, &map, &maxlength, &tlength, &prebuf, &minreq, volume_set ? &volume : NULL, muted, syncid, &missing, flags, p, adjust_latency); + s = playback_stream_new(c, sink, &ss, &map, &maxlength, &tlength, &prebuf, &minreq, volume_set ? &volume : NULL, muted, syncid, &missing, flags, p, adjust_latency, early_requests); pa_proplist_free(p); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); @@ -1825,7 +1922,8 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin no_move = FALSE, variable_rate = FALSE, adjust_latency = FALSE, - peak_detect = FALSE; + peak_detect = FALSE, + early_requests = FALSE; pa_source_output_flags_t flags = 0; pa_proplist *p; uint32_t direct_on_input_idx = PA_INVALID_INDEX; @@ -1888,6 +1986,15 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin } } + if (c->version >= 14) { + + if (pa_tagstruct_get_boolean(t, &early_requests) < 0) { + protocol_error(c); + pa_proplist_free(p); + return; + } + } + if (!pa_tagstruct_eof(t)) { protocol_error(c); pa_proplist_free(p); @@ -1930,7 +2037,7 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin (no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) | (variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0); - s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency, direct_on_input); + s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency, direct_on_input, early_requests); pa_proplist_free(p); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID); @@ -1990,7 +2097,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta pa_native_connection *c = PA_NATIVE_CONNECTION(userdata); const void*cookie; pa_tagstruct *reply; - pa_bool_t shm_on_remote, do_shm; + pa_bool_t shm_on_remote = FALSE, do_shm; pa_native_connection_assert_ref(c); pa_assert(t); @@ -2684,7 +2791,7 @@ static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, p pa_sink_input *si = NULL; pa_source_output *so = NULL; pa_scache_entry *sce = NULL; - const char *name; + const char *name = NULL; pa_tagstruct *reply; pa_native_connection_assert_ref(c); @@ -3167,7 +3274,7 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) { playback_stream *s; - pa_bool_t adjust_latency = FALSE; + pa_bool_t adjust_latency = FALSE, early_requests = FALSE; s = pa_idxset_get_by_index(c->output_streams, idx); CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY); @@ -3181,12 +3288,13 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u PA_TAG_U32, &minreq, PA_TAG_INVALID) < 0 || (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) || + (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - fix_playback_buffer_attr_pre(s, adjust_latency, &maxlength, &tlength, &prebuf, &minreq); + fix_playback_buffer_attr_pre(s, adjust_latency, early_requests, &maxlength, &tlength, &prebuf, &minreq); pa_memblockq_set_maxlength(s->memblockq, maxlength); pa_memblockq_set_tlength(s->memblockq, tlength); pa_memblockq_set_prebuf(s->memblockq, prebuf); @@ -3204,7 +3312,7 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u } else { record_stream *s; - pa_bool_t adjust_latency = FALSE; + pa_bool_t adjust_latency = FALSE, early_requests = FALSE; pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR); s = pa_idxset_get_by_index(c->record_streams, idx); @@ -3216,12 +3324,13 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u PA_TAG_U32, &fragsize, PA_TAG_INVALID) < 0 || (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) || + (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) || !pa_tagstruct_eof(t)) { protocol_error(c); return; } - fix_record_buffer_attr_pre(s, adjust_latency, &maxlength, &fragsize); + fix_record_buffer_attr_pre(s, adjust_latency, early_requests, &maxlength, &fragsize); pa_memblockq_set_maxlength(s->memblockq, maxlength); fix_record_buffer_attr_post(s, &maxlength, &fragsize); @@ -3947,6 +4056,8 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o return; } +/* pa_log("got %lu bytes", (unsigned long) chunk->length); */ + if (playback_stream_isinstance(stream)) { playback_stream *ps = PLAYBACK_STREAM(stream); diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index ee953652..45cd68c1 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -1047,7 +1047,7 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) { (int16_t*) dst + oc, o_skip, (int16_t*) src + ic, i_skip, (int) n_frames, - 1.0, r->map_table[oc][ic]); + 1.0f, r->map_table[oc][ic]); } } @@ -1178,10 +1178,10 @@ static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, un memset(&data, 0, sizeof(data)); data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); - data.input_frames = in_n_frames; + data.input_frames = (long int) in_n_frames; data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index); - data.output_frames = *out_n_frames; + data.output_frames = (long int) *out_n_frames; data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate; data.end_of_input = 0; diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index 4b2efe5e..b4234af5 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -31,6 +31,8 @@ #include <liboil/liboilfuncs.h> #include <liboil/liboil.h> +#include <pulse/timeval.h> + #include <pulsecore/log.h> #include <pulsecore/macro.h> #include <pulsecore/g711.h> @@ -981,3 +983,34 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo } } } + +/* Similar to pa_bytes_to_usec() but rounds up, not down */ + +pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec) { + size_t fs; + pa_usec_t usec; + + pa_assert(spec); + + fs = pa_frame_size(spec); + length = (length + fs - 1) / fs; + + usec = (pa_usec_t) length * PA_USEC_PER_SEC; + + return (usec + spec->rate - 1) / spec->rate; +} + +/* Similar to pa_usec_to_bytes() but rounds up, not down */ + +size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec) { + uint64_t u; + pa_assert(spec); + + u = (uint64_t) t * (uint64_t) spec->rate; + + u = (u + PA_USEC_PER_SEC - 1) / PA_USEC_PER_SEC; + + u *= pa_frame_size(spec); + + return (size_t) u; +} diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h index cef70750..06ecb724 100644 --- a/src/pulsecore/sample-util.h +++ b/src/pulsecore/sample-util.h @@ -78,4 +78,7 @@ void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n); +pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec); +size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec); + #endif diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c index b0870202..b2997575 100644 --- a/src/pulsecore/shm.c +++ b/src/pulsecore/shm.c @@ -105,7 +105,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, pa_bool_t shared, mode_t mode) { m->size = size; #ifdef MAP_ANONYMOUS - if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { + if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (off_t) 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } @@ -143,7 +143,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, pa_bool_t shared, mode_t mode) { goto fail; } - if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { + if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t) 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } @@ -291,7 +291,7 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) { m->size = (size_t) st.st_size; - if ((m->ptr = mmap(NULL, m->size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + if ((m->ptr = mmap(NULL, m->size, PROT_READ, MAP_SHARED, fd, (off_t) 0)) == MAP_FAILED) { pa_log("mmap() failed: %s", pa_cstrerror(errno)); goto fail; } diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index f4e803d0..7d80242f 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -756,14 +756,11 @@ pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) if (PA_SINK_INPUT_IS_LINKED(i->state)) pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0); - else { + else /* If this sink input is not realized yet, we have to touch * the thread info data directly */ - usec = fixup_latency(i->sink, usec); i->thread_info.requested_sink_latency = usec; - i->sink->thread_info.requested_latency_valid = FALSE; - } return usec; } diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 24fb8913..6fa22dc2 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -1042,11 +1042,15 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse pa_sink_input_set_state_within_thread(i, i->state); + /* The requested latency of the sink input needs to be + * fixed up and then configured on the sink */ + + if (i->thread_info.requested_sink_latency != (pa_usec_t) -1) + pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency); + pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind); pa_sink_input_update_max_request(i, s->thread_info.max_request); - pa_sink_invalidate_requested_latency(s); - /* We don't rewind here automatically. This is left to the * sink input implementor because some sink inputs need a * slow start, i.e. need some time to buffer client @@ -1158,11 +1162,12 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse if (i->attach) i->attach(i); + if (i->thread_info.requested_sink_latency != (pa_usec_t) -1) + pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency); + pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind); pa_sink_input_update_max_request(i, s->thread_info.max_request); - pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency); - if (i->thread_info.state != PA_SINK_INPUT_CORKED) { pa_usec_t usec = 0; size_t nbytes; @@ -1424,7 +1429,6 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) { /* Called from IO thread */ void pa_sink_set_max_request(pa_sink *s, size_t max_request) { - pa_sink_input *i; void *state = NULL; pa_sink_assert_ref(s); @@ -1435,6 +1439,8 @@ void pa_sink_set_max_request(pa_sink *s, size_t max_request) { s->thread_info.max_request = max_request; if (PA_SINK_IS_LINKED(s->thread_info.state)) { + pa_sink_input *i; + while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) pa_sink_input_update_max_request(i, s->thread_info.max_request); } diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c index 3bde40d0..6739effd 100644 --- a/src/pulsecore/socket-client.c +++ b/src/pulsecore/socket-client.c @@ -437,7 +437,7 @@ static void start_timeout(pa_socket_client *c) { pa_assert(!c->timeout_event); pa_gettimeofday(&tv); - pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000); + pa_timeval_add(&tv, CONNECT_TIMEOUT * PA_USEC_PER_SEC); c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c); } diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c index 74338f9a..380cef16 100644 --- a/src/pulsecore/sound-file.c +++ b/src/pulsecore/sound-file.c @@ -89,7 +89,7 @@ int pa_sound_file_load( case SF_FORMAT_PCM_U8: case SF_FORMAT_PCM_S8: ss->format = PA_SAMPLE_S16NE; - readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_short; + readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *_ptr, sf_count_t frames)) sf_readf_short; break; case SF_FORMAT_ULAW: @@ -104,7 +104,7 @@ int pa_sound_file_load( case SF_FORMAT_DOUBLE: default: ss->format = PA_SAMPLE_FLOAT32NE; - readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float; + readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *_ptr, sf_count_t frames)) sf_readf_float; break; } diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 4257154e..5df950a8 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -511,14 +511,11 @@ pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t if (PA_SOURCE_OUTPUT_IS_LINKED(o->state)) pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0); - else { + else /* If this source output is not realized yet, we have to touch * the thread info data directly */ - usec = fixup_latency(o->source, usec); o->thread_info.requested_source_latency = usec; - o->source->thread_info.requested_latency_valid = FALSE; - } return usec; } diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 7ed32e92..edbbf017 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -670,6 +670,9 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_ pa_source_output_set_state_within_thread(o, o->state); + if (o->thread_info.requested_source_latency != (pa_usec_t) -1) + pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency); + pa_source_output_update_max_rewind(o, s->thread_info.max_rewind); /* We don't just invalidate the requested latency here, diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c index e5b228e9..62a30144 100644 --- a/src/pulsecore/tagstruct.c +++ b/src/pulsecore/tagstruct.c @@ -435,9 +435,9 @@ int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv) { return -1; memcpy(&tv->tv_sec, t->data+t->rindex+1, 4); - tv->tv_sec = ntohl((uint32_t) tv->tv_sec); + tv->tv_sec = (time_t) ntohl((uint32_t) tv->tv_sec); memcpy(&tv->tv_usec, t->data+t->rindex+5, 4); - tv->tv_usec = ntohl((uint32_t) tv->tv_usec); + tv->tv_usec = (suseconds_t) ntohl((uint32_t) tv->tv_usec); t->rindex += 9; return 0; } |