summaryrefslogtreecommitdiffstats
path: root/src/pulsecore
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulsecore')
-rw-r--r--src/pulsecore/atomic.h46
-rw-r--r--src/pulsecore/authkey.c12
-rw-r--r--src/pulsecore/core-util.c49
-rw-r--r--src/pulsecore/core-util.h36
-rw-r--r--src/pulsecore/log.c49
-rw-r--r--src/pulsecore/log.h4
-rw-r--r--src/pulsecore/memblockq.h2
-rw-r--r--src/pulsecore/module.c4
-rw-r--r--src/pulsecore/object.h2
-rw-r--r--src/pulsecore/pid.c4
-rw-r--r--src/pulsecore/protocol-native.c193
-rw-r--r--src/pulsecore/resampler.c6
-rw-r--r--src/pulsecore/sample-util.c33
-rw-r--r--src/pulsecore/sample-util.h3
-rw-r--r--src/pulsecore/shm.c6
-rw-r--r--src/pulsecore/sink-input.c5
-rw-r--r--src/pulsecore/sink.c16
-rw-r--r--src/pulsecore/socket-client.c2
-rw-r--r--src/pulsecore/sound-file.c4
-rw-r--r--src/pulsecore/source-output.c5
-rw-r--r--src/pulsecore/source.c3
-rw-r--r--src/pulsecore/tagstruct.c4
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;
}