From ff252cb48d9bd827d262eb2633fecaff47c6fe5c Mon Sep 17 00:00:00 2001 From: Diego Elio 'Flameeyes' Pettenò Date: Sat, 4 Jul 2009 13:12:32 +0200 Subject: Check for the library containing the backtrace() function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On FreeBSD the backtrace() function as well as the execinfo.h headers are provided by libexecinfo (an optional package). PulseAudio “automagically” identifies execinfo.h and proceeds to use it, but then will fail to link against the library. Thanks to Alexis Ballier for reporting. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 00121f82..9c96d1c5 100644 --- a/configure.ac +++ b/configure.ac @@ -388,6 +388,7 @@ AC_SEARCH_LIBS([timer_create], [rt]) # BSD AC_SEARCH_LIBS([connect], [socket]) +AC_SEARCH_LIBS([backtrace], [execinfo]) # Non-standard -- cgit From 61fefd67dab01011d97a06b7e3dd51101d5f5749 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Sun, 12 Jul 2009 20:43:21 +0100 Subject: introspect: Fix two memory issues in port handling code. First one is a simple typo on an error condition that would have likely caused issues if it ever cropped up. Second issue is that port information is never actually freed if everything works fine. --- src/pulse/introspect.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c index 3414f7de..27a587cb 100644 --- a/src/pulse/introspect.c +++ b/src/pulse/introspect.c @@ -212,8 +212,8 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, u pa_tagstruct_getu32(t, &i.ports[0][j].priority) < 0) { pa_context_fail(o->context, PA_ERR_PROTOCOL); - pa_xfree(i.ports); pa_xfree(i.ports[0]); + pa_xfree(i.ports); pa_proplist_free(i.proplist); goto finish; } @@ -250,6 +250,10 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, u cb(o->context, &i, 0, o->userdata); } + if (i.ports) { + pa_xfree(i.ports[0]); + pa_xfree(i.ports); + } pa_proplist_free(i.proplist); } } @@ -479,6 +483,10 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, cb(o->context, &i, 0, o->userdata); } + if (i.ports) { + pa_xfree(i.ports[0]); + pa_xfree(i.ports); + } pa_proplist_free(i.proplist); } } -- cgit From 84200b423ebfa7e2dad9b1b65f64eac7bf3d2114 Mon Sep 17 00:00:00 2001 From: Diego Elio 'Flameeyes' Pettenò Date: Tue, 7 Jul 2009 20:51:53 +0200 Subject: Remove exploitable LD_BIND_NOW hack (CVE-2009-1894). Instead of trying to re-execute pulseaudio itself with LD_BIND_NOW set, just find the correct flag for the linker to request immediate bindings (all ELF files support that option), and use that when linking the daemon. Reduce the amount of compiled and executed code as well. --- configure.ac | 6 ++++++ src/Makefile.am | 4 ++-- src/daemon/main.c | 22 ---------------------- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index 9c96d1c5..cc7f674a 100644 --- a/configure.ac +++ b/configure.ac @@ -113,6 +113,12 @@ CC_CHECK_LDFLAGS([${tmp_ldflag}], [VERSIONING_LDFLAGS='-Wl,-version-script=$(srcdir)/map-file']) AC_SUBST([VERSIONING_LDFLAGS]) +dnl Use immediate (now) bindings; avoids the funky re-call in itself +dnl the -z now syntax is lifted from Sun's linker and works with GNU's too +dnl other linkes might be added later +CC_CHECK_LDFLAGS([-Wl,-z,now], [IMMEDIATE_LDFLAGS="-Wl,-z,now"]) +AC_SUBST([IMMEDIATE_LDFLAGS]) + dnl Check for the proper way to build libraries that have no undefined dnl symbols; on some hosts this needs to be avoided but the macro dnl takes care of it. diff --git a/src/Makefile.am b/src/Makefile.am index 7ebf1f8a..ac627c84 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -183,9 +183,9 @@ PREOPEN_LIBS = $(modlibexec_LTLIBRARIES) endif if FORCE_PREOPEN -pulseaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlpreopen force $(foreach f,$(PREOPEN_LIBS),-dlpreopen $(f)) +pulseaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(IMMEDIATE_LDFLAGS) -dlpreopen force $(foreach f,$(PREOPEN_LIBS),-dlpreopen $(f)) else -pulseaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f)) +pulseaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(IMMEDIATE_LDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f)) endif ################################### diff --git a/src/daemon/main.c b/src/daemon/main.c index eb378d24..0f6fc907 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -401,28 +401,6 @@ int main(int argc, char *argv[]) { pa_log_set_level(PA_LOG_NOTICE); pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET); -#if defined(__linux__) && defined(__OPTIMIZE__) - /* - Disable lazy relocations to make usage of external libraries - more deterministic for our RT threads. We abuse __OPTIMIZE__ as - a check whether we are a debug build or not. - */ - - if (!getenv("LD_BIND_NOW")) { - char *rp; - - /* We have to execute ourselves, because the libc caches the - * value of $LD_BIND_NOW on initialization. */ - - pa_set_env("LD_BIND_NOW", "1"); - - if ((rp = pa_readlink("/proc/self/exe"))) - pa_assert_se(execv(rp, argv) == 0); - else - pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?"); - } -#endif - if ((e = getenv("PULSE_PASSED_FD"))) { passed_fd = atoi(e); -- cgit From 673112b192a9494ea96f7daca061b080db5d3977 Mon Sep 17 00:00:00 2001 From: Diego Elio 'Flameeyes' Pettenò Date: Fri, 17 Jul 2009 14:18:07 +0200 Subject: Check for support of -z nodelete LD flag, don't use it unconditionally. On non-GNU, non-Sun linkers, the -z option is often not understood; make sure that the -z nodelete option is usable before making use of it. Unbreaks build on Mac OS X. --- configure.ac | 9 +++++++++ src/Makefile.am | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cc7f674a..112a1a8f 100644 --- a/configure.ac +++ b/configure.ac @@ -119,6 +119,15 @@ dnl other linkes might be added later CC_CHECK_LDFLAGS([-Wl,-z,now], [IMMEDIATE_LDFLAGS="-Wl,-z,now"]) AC_SUBST([IMMEDIATE_LDFLAGS]) +dnl On ELF systems we don't want the libraries to be unloaded since we +dnl don't clean them up properly, so we request the nodelete flag to be +dnl enabled. +dnl +dnl On other systems, we don't really know how to do that, but it's +dnl welcome if somebody can tell. +CC_CHECK_LDFLAGS([-Wl,-z,nodelete], [NODELETE_LDFLAGS="-Wl,-z,nodelete"]) +AC_SUBST([NODELETE_LDFLAGS]) + dnl Check for the proper way to build libraries that have no undefined dnl symbols; on some hosts this needs to be avoided but the macro dnl takes care of it. diff --git a/src/Makefile.am b/src/Makefile.am index ac627c84..c022fa7c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -87,7 +87,7 @@ AM_CFLAGS = \ AM_LIBADD = $(PTHREAD_LIBS) $(INTLLIBS) AM_LDADD = $(PTHREAD_LIBS) $(INTLLIBS) -AM_LDFLAGS = -Wl,-z,nodelete +AM_LDFLAGS = $(NODELETE_LDFLAGS) if STATIC_BINS BINLDFLAGS = -static -- cgit From a6d67187126ef37b69b0d8d94dfeebeb364a8444 Mon Sep 17 00:00:00 2001 From: Diego Elio 'Flameeyes' Pettenò Date: Fri, 17 Jul 2009 14:33:33 +0200 Subject: Request explicitly POSIX.1-2001 for clock_gettime. This might actually call for a rewrite of system extensions handling. --- configure.ac | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac index 112a1a8f..9b49f23e 100644 --- a/configure.ac +++ b/configure.ac @@ -74,6 +74,9 @@ case $host in AC_DEFINE(_XOPEN_SOURCE, 600, Needed to get declarations for msg_control and msg_controllen on Solaris) AC_DEFINE(__EXTENSIONS__, 1, Needed to get declarations for msg_control and msg_controllen on Solaris) ;; + *-*-darwin* ) + AC_DEFINE([_POSIX_C_SOURCE], [200112L], [Needed to get clock_gettime on Mac OS X]) + ;; esac AM_SILENT_RULES([yes]) -- cgit From 0a5257b520ae540775367eb20a4db3e76436cdf9 Mon Sep 17 00:00:00 2001 From: Diego Elio 'Flameeyes' Pettenò Date: Fri, 17 Jul 2009 20:41:58 +0200 Subject: Also request Darwin extensions, as they are needed for stuff like NSIG. Without this definition, non-POSIX interfaces (which are needed) are hidden by the _POSIX_C_SOURCE request (for clock_gettime). --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 9b49f23e..18007357 100644 --- a/configure.ac +++ b/configure.ac @@ -76,6 +76,7 @@ case $host in ;; *-*-darwin* ) AC_DEFINE([_POSIX_C_SOURCE], [200112L], [Needed to get clock_gettime on Mac OS X]) + AC_DEFINE([_DARWIN_C_SOURCE], [200112L], [Needed to get NSIG on Mac OS X]) ;; esac -- cgit From 191c57effe385c797d8f226accd9afceee972888 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 17 Jul 2009 13:45:37 +0200 Subject: make bootstrap.sh aware of Darwin environment Signed-off-by: Daniel Mack --- bootstrap.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index aa9755fa..a5bd9a78 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -40,10 +40,22 @@ run_versioned() { set -ex +case $(uname) in + *Darwin*) + CP_OPTS="-R" + CHMOD_OPTS="" + LIBTOOLIZE="glibtoolize" + ;; + *) + CP_OPTS="-av" + CHMOD_OPTS="-c" + ;; +esac + if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then echo "Activating pre-commit hook." - cp -av .git/hooks/pre-commit.sample .git/hooks/pre-commit - chmod -c +x .git/hooks/pre-commit + cp ${CP_OPTS} .git/hooks/pre-commit.sample .git/hooks/pre-commit + chmod ${CHMOD_OPTS} +x .git/hooks/pre-commit fi if [ -f .tarball-version ]; then -- cgit From 8c85c9999661a57e1bd10e79ad398b812ff4ea87 Mon Sep 17 00:00:00 2001 From: Diego Elio 'Flameeyes' Pettenò Date: Fri, 17 Jul 2009 20:48:44 +0200 Subject: Further simplify on Daniel's patch for bootstrap.sh. Instead of having further indirections, stick to POSIX command options for cp and chmod. This leaves just the LIBTOOL handling to be Darwin-specific. --- bootstrap.sh | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index a5bd9a78..79e0a7dc 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -42,20 +42,14 @@ set -ex case $(uname) in *Darwin*) - CP_OPTS="-R" - CHMOD_OPTS="" LIBTOOLIZE="glibtoolize" ;; - *) - CP_OPTS="-av" - CHMOD_OPTS="-c" - ;; esac if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then echo "Activating pre-commit hook." - cp ${CP_OPTS} .git/hooks/pre-commit.sample .git/hooks/pre-commit - chmod ${CHMOD_OPTS} +x .git/hooks/pre-commit + cp -pv .git/hooks/pre-commit.sample .git/hooks/pre-commit + chmod -v +x .git/hooks/pre-commit fi if [ -f .tarball-version ]; then -- cgit From 542607f4c602e632b32efe2b6fd21f81ff52bd8d Mon Sep 17 00:00:00 2001 From: Diego Elio 'Flameeyes' Pettenò Date: Fri, 17 Jul 2009 21:03:22 +0200 Subject: Make the rtstutter tests mostly pointless without CLOCK_REALTIME. On the other hand, this actually makes the test build, and test at least that it doesn't abort away, when the CLOCK_REALTIME interface is not present (or when clock_gettime is not found). --- src/tests/rtstutter.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tests/rtstutter.c b/src/tests/rtstutter.c index a4b5d596..c93fee93 100644 --- a/src/tests/rtstutter.c +++ b/src/tests/rtstutter.c @@ -67,7 +67,9 @@ static void* work(void *p) { pa_log_notice("CPU%i: Sleeping for 1s", PA_PTR_TO_UINT(p)); sleep(1); +#ifdef CLOCK_REALTIME pa_assert_se(clock_gettime(CLOCK_REALTIME, &end) == 0); +#endif nsec = (uint64_t) ((((double) rand())*(double)(msec_upper-msec_lower)*PA_NSEC_PER_MSEC)/RAND_MAX) + @@ -84,7 +86,9 @@ static void* work(void *p) { } do { +#ifdef CLOCK_REALTIME pa_assert_se(clock_gettime(CLOCK_REALTIME, &now) == 0); +#endif } while (now.tv_sec < end.tv_sec || (now.tv_sec == end.tv_sec && now.tv_nsec < end.tv_nsec)); } -- cgit From d18eb61bd2fe5940bccc2b5fcda4029159021d00 Mon Sep 17 00:00:00 2001 From: Diego Elio 'Flameeyes' Pettenò Date: Fri, 17 Jul 2009 21:05:49 +0200 Subject: Again make sure that the wait() definition is not shadowed. Rename the parameter in pa_asyncmsgq_get() to wait_op. --- src/pulsecore/asyncmsgq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c index e191b05f..083d9de2 100644 --- a/src/pulsecore/asyncmsgq.c +++ b/src/pulsecore/asyncmsgq.c @@ -172,11 +172,11 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi return i.ret; } -int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *chunk, pa_bool_t wait) { +int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *chunk, pa_bool_t wait_op) { pa_assert(PA_REFCNT_VALUE(a) > 0); pa_assert(!a->current); - if (!(a->current = pa_asyncq_pop(a->asyncq, wait))) { + if (!(a->current = pa_asyncq_pop(a->asyncq, wait_op))) { /* pa_log("failure"); */ return -1; } -- cgit From 7e2afffb81ab8b495d4f769858a855c2df2c0610 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Jul 2009 22:38:38 +0200 Subject: alsa: deal properly with IO functions asking us to write 0 bytes --- src/modules/alsa/alsa-sink.c | 6 +++++- src/modules/alsa/alsa-source.c | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 0cde694c..e7925902 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -494,6 +494,9 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle if (frames > pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size) frames = pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size; + if (frames == 0) + break; + /* Check these are multiples of 8 bit */ pa_assert((areas[0].first & 7) == 0); pa_assert((areas[0].step & 7)== 0); @@ -631,7 +634,8 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polle frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, (snd_pcm_uframes_t) frames); pa_memblock_release(u->memchunk.memblock); - pa_assert(frames != 0); + if (frames == 0) + break; if (PA_UNLIKELY(frames < 0)) { diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index a6760e1e..41bb768b 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -473,6 +473,9 @@ static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled if (frames > pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size) frames = pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size; + if (frames == 0) + break; + /* Check these are multiples of 8 bit */ pa_assert((areas[0].first & 7) == 0); pa_assert((areas[0].step & 7)== 0); @@ -599,7 +602,10 @@ static int unix_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, (snd_pcm_uframes_t) frames); pa_memblock_release(chunk.memblock); - pa_assert(frames != 0); + if (frames == 0) { + pa_memblock_unref(chunk.memblock); + break; + } if (PA_UNLIKELY(frames < 0)) { pa_memblock_unref(chunk.memblock); -- cgit From 2f54b5df183630bb284a16ed9be88279c8f0f0e4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Jul 2009 22:47:51 +0200 Subject: daemon: reset personality, to make the autospawn env cleaup complete --- src/daemon/main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/daemon/main.c b/src/daemon/main.c index eb378d24..c759df53 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -65,6 +65,10 @@ #include #endif +#ifdef __linux__ +#include +#endif + #include #include #include @@ -433,6 +437,12 @@ int main(int argc, char *argv[]) { /* We might be autospawned, in which case have no idea in which * context we have been started. Let's cleanup our execution * context as good as possible */ + +#ifdef __linux__ + if (personality(PER_LINUX) < 0) + pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno)); +#endif + pa_drop_root(); pa_close_all(passed_fd, -1); pa_reset_sigs(-1); -- cgit From e3b0ce57e0f44790bd75412778cce8129e3945eb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Jul 2009 22:48:54 +0200 Subject: udev: don't fail if /dev/snd is not available right-away --- src/modules/module-udev-detect.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c index 1ad6fa2d..c8ec2bf9 100644 --- a/src/modules/module-udev-detect.c +++ b/src/modules/module-udev-detect.c @@ -65,6 +65,8 @@ static const char* const valid_modargs[] = { NULL }; +static int setup_inotify(struct userdata *u); + static void device_free(struct device *d) { pa_assert(d); @@ -117,6 +119,9 @@ static void card_changed(struct userdata *u, struct udev_device *dev) { pa_assert(u); pa_assert(dev); + /* Maybe /dev/snd is now available? */ + setup_inotify(u); + path = udev_device_get_devpath(dev); if ((d = pa_hashmap_get(u->devices, path))) { @@ -262,7 +267,7 @@ static void inotify_cb( } buf; struct userdata *u = userdata; static int type = 0; - pa_bool_t verify = FALSE; + pa_bool_t verify = FALSE, deleted = FALSE; for (;;) { ssize_t r; @@ -279,6 +284,9 @@ static void inotify_cb( if ((buf.e.mask & IN_CLOSE_WRITE) && pa_startswith(buf.e.name, "pcmC")) verify = TRUE; + + if ((buf.e.mask & (IN_DELETE_SELF|IN_MOVE_SELF))) + deleted = TRUE; } if (verify) { @@ -291,11 +299,14 @@ static void inotify_cb( verify_access(u, d); } - return; + if (!deleted) + return; fail: - a->io_free(u->inotify_io); - u->inotify_io = NULL; + if (u->inotify_io) { + a->io_free(u->inotify_io); + u->inotify_io = NULL; + } if (u->inotify_fd >= 0) { pa_close(u->inotify_fd); @@ -307,17 +318,28 @@ static int setup_inotify(struct userdata *u) { char *dev_snd; int r; + if (u->inotify_fd >= 0) + return 0; + if ((u->inotify_fd = inotify_init1(IN_CLOEXEC|IN_NONBLOCK)) < 0) { pa_log("inotify_init1() failed: %s", pa_cstrerror(errno)); return -1; } dev_snd = pa_sprintf_malloc("%s/snd", udev_get_dev_path(u->udev)); - r = inotify_add_watch(u->inotify_fd, dev_snd, IN_CLOSE_WRITE); + r = inotify_add_watch(u->inotify_fd, dev_snd, IN_CLOSE_WRITE|IN_DELETE_SELF|IN_MOVE_SELF); pa_xfree(dev_snd); if (r < 0) { - pa_log("inotify_add_watch() failed: %s", pa_cstrerror(errno)); + int saved_errno = errno; + + pa_close(u->inotify_fd); + u->inotify_fd = -1; + + if (saved_errno == ENOENT) + return 0; + + pa_log("inotify_add_watch() failed: %s", pa_cstrerror(saved_errno)); return -1; } -- cgit From 3b01d3a53f3b9261b30c1f7e5fe28d269c28cdf0 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 23 Jul 2009 13:40:23 +0200 Subject: protocol-native: use the right samplerate The render_memblockq is expressed in the sample_spec of the sink, not of the particular stream before resampling. --- src/pulsecore/protocol-native.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 96184bd2..9a37c565 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2550,7 +2550,7 @@ static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uin reply = reply_new(tag); pa_tagstruct_put_usec(reply, s->current_sink_latency + - pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sample_spec)); + pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sink->sample_spec)); pa_tagstruct_put_usec(reply, 0); pa_tagstruct_put_boolean(reply, s->playing_for > 0 && -- cgit