summaryrefslogtreecommitdiffstats
path: root/src/pulsecore
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulsecore')
-rw-r--r--src/pulsecore/asyncmsgq.c2
-rw-r--r--src/pulsecore/asyncmsgq.h2
-rw-r--r--src/pulsecore/asyncq.c2
-rw-r--r--src/pulsecore/asyncq.h2
-rw-r--r--src/pulsecore/atomic.h15
-rw-r--r--src/pulsecore/authkey-prop.c2
-rw-r--r--src/pulsecore/authkey-prop.h2
-rw-r--r--src/pulsecore/authkey.c2
-rw-r--r--src/pulsecore/authkey.h2
-rw-r--r--src/pulsecore/autoload.c2
-rw-r--r--src/pulsecore/autoload.h2
-rw-r--r--src/pulsecore/avahi-wrap.c2
-rw-r--r--src/pulsecore/avahi-wrap.h2
-rw-r--r--src/pulsecore/cli-command.c2
-rw-r--r--src/pulsecore/cli-command.h2
-rw-r--r--src/pulsecore/cli-text.c24
-rw-r--r--src/pulsecore/cli-text.h2
-rw-r--r--src/pulsecore/cli.c2
-rw-r--r--src/pulsecore/cli.h2
-rw-r--r--src/pulsecore/client.c9
-rw-r--r--src/pulsecore/client.h2
-rw-r--r--src/pulsecore/conf-parser.c2
-rw-r--r--src/pulsecore/conf-parser.h2
-rw-r--r--src/pulsecore/core-error.c2
-rw-r--r--src/pulsecore/core-error.h2
-rw-r--r--src/pulsecore/core-scache.c13
-rw-r--r--src/pulsecore/core-scache.h2
-rw-r--r--src/pulsecore/core-subscribe.c2
-rw-r--r--src/pulsecore/core-subscribe.h2
-rw-r--r--src/pulsecore/core-util.c109
-rw-r--r--src/pulsecore/core-util.h14
-rw-r--r--src/pulsecore/core.c10
-rw-r--r--src/pulsecore/core.h3
-rw-r--r--src/pulsecore/creds.h2
-rw-r--r--src/pulsecore/dllmain.c2
-rw-r--r--src/pulsecore/dynarray.c2
-rw-r--r--src/pulsecore/dynarray.h2
-rw-r--r--src/pulsecore/endianmacros.h2
-rw-r--r--src/pulsecore/envelope.c2
-rw-r--r--src/pulsecore/envelope.h2
-rw-r--r--src/pulsecore/esound.h2
-rw-r--r--src/pulsecore/fdsem.c2
-rw-r--r--src/pulsecore/fdsem.h2
-rw-r--r--src/pulsecore/flist.c2
-rw-r--r--src/pulsecore/flist.h2
-rw-r--r--src/pulsecore/hashmap.c34
-rw-r--r--src/pulsecore/hashmap.h9
-rw-r--r--src/pulsecore/hook-list.c39
-rw-r--r--src/pulsecore/hook-list.h16
-rw-r--r--src/pulsecore/idxset.c2
-rw-r--r--src/pulsecore/idxset.h2
-rw-r--r--src/pulsecore/inet_ntop.c2
-rw-r--r--src/pulsecore/inet_pton.c2
-rw-r--r--src/pulsecore/iochannel.c15
-rw-r--r--src/pulsecore/iochannel.h4
-rw-r--r--src/pulsecore/ioline.c2
-rw-r--r--src/pulsecore/ioline.h2
-rw-r--r--src/pulsecore/ipacl.c2
-rw-r--r--src/pulsecore/ipacl.h2
-rw-r--r--src/pulsecore/llist.h2
-rw-r--r--src/pulsecore/log.c2
-rw-r--r--src/pulsecore/log.h2
-rw-r--r--src/pulsecore/ltdl-helper.c2
-rw-r--r--src/pulsecore/ltdl-helper.h2
-rw-r--r--src/pulsecore/macro.h2
-rw-r--r--src/pulsecore/mcalign.c2
-rw-r--r--src/pulsecore/mcalign.h2
-rw-r--r--src/pulsecore/memblock.c2
-rw-r--r--src/pulsecore/memblock.h2
-rw-r--r--src/pulsecore/memblockq.c15
-rw-r--r--src/pulsecore/memblockq.h4
-rw-r--r--src/pulsecore/memchunk.c18
-rw-r--r--src/pulsecore/memchunk.h2
-rw-r--r--src/pulsecore/modargs.c20
-rw-r--r--src/pulsecore/modargs.h2
-rw-r--r--src/pulsecore/modinfo.c2
-rw-r--r--src/pulsecore/modinfo.h2
-rw-r--r--src/pulsecore/module.c4
-rw-r--r--src/pulsecore/module.h2
-rw-r--r--src/pulsecore/msgobject.c2
-rw-r--r--src/pulsecore/msgobject.h2
-rw-r--r--src/pulsecore/mutex-posix.c2
-rw-r--r--src/pulsecore/mutex-win32.c2
-rw-r--r--src/pulsecore/mutex.h2
-rw-r--r--src/pulsecore/namereg.c2
-rw-r--r--src/pulsecore/namereg.h2
-rw-r--r--src/pulsecore/native-common.h2
-rw-r--r--src/pulsecore/object.c2
-rw-r--r--src/pulsecore/object.h2
-rw-r--r--src/pulsecore/once.c2
-rw-r--r--src/pulsecore/once.h2
-rw-r--r--src/pulsecore/packet.c2
-rw-r--r--src/pulsecore/packet.h2
-rw-r--r--src/pulsecore/parseaddr.c2
-rw-r--r--src/pulsecore/parseaddr.h2
-rw-r--r--src/pulsecore/pdispatch.c2
-rw-r--r--src/pulsecore/pdispatch.h2
-rw-r--r--src/pulsecore/pid.c100
-rw-r--r--src/pulsecore/pid.h8
-rw-r--r--src/pulsecore/pipe.c2
-rw-r--r--src/pulsecore/pipe.h2
-rw-r--r--src/pulsecore/play-memblockq.c3
-rw-r--r--src/pulsecore/play-memblockq.h2
-rw-r--r--src/pulsecore/play-memchunk.c2
-rw-r--r--src/pulsecore/play-memchunk.h2
-rw-r--r--src/pulsecore/poll.c2
-rw-r--r--src/pulsecore/poll.h2
-rw-r--r--src/pulsecore/proplist-util.c118
-rw-r--r--src/pulsecore/proplist-util.h29
-rw-r--r--src/pulsecore/props.c2
-rw-r--r--src/pulsecore/props.h2
-rw-r--r--src/pulsecore/protocol-cli.c2
-rw-r--r--src/pulsecore/protocol-cli.h2
-rw-r--r--src/pulsecore/protocol-esound.c6
-rw-r--r--src/pulsecore/protocol-esound.h2
-rw-r--r--src/pulsecore/protocol-http.c2
-rw-r--r--src/pulsecore/protocol-http.h2
-rw-r--r--src/pulsecore/protocol-native.c127
-rw-r--r--src/pulsecore/protocol-native.h2
-rw-r--r--src/pulsecore/protocol-simple.c4
-rw-r--r--src/pulsecore/protocol-simple.h2
-rw-r--r--src/pulsecore/pstream-util.c2
-rw-r--r--src/pulsecore/pstream-util.h2
-rw-r--r--src/pulsecore/pstream.c2
-rw-r--r--src/pulsecore/pstream.h2
-rw-r--r--src/pulsecore/queue.c2
-rw-r--r--src/pulsecore/queue.h2
-rw-r--r--src/pulsecore/random.c8
-rw-r--r--src/pulsecore/random.h2
-rw-r--r--src/pulsecore/refcnt.h2
-rw-r--r--src/pulsecore/resampler.c16
-rw-r--r--src/pulsecore/resampler.h2
-rw-r--r--src/pulsecore/rtclock.c2
-rw-r--r--src/pulsecore/rtclock.h2
-rw-r--r--src/pulsecore/rtpoll.c5
-rw-r--r--src/pulsecore/rtpoll.h2
-rw-r--r--src/pulsecore/rtsig.c2
-rw-r--r--src/pulsecore/rtsig.h2
-rw-r--r--src/pulsecore/sample-util.c2
-rw-r--r--src/pulsecore/sample-util.h2
-rw-r--r--src/pulsecore/sconv-s16be.c2
-rw-r--r--src/pulsecore/sconv-s16be.h2
-rw-r--r--src/pulsecore/sconv-s16le.c2
-rw-r--r--src/pulsecore/sconv-s16le.h2
-rw-r--r--src/pulsecore/sconv.c2
-rw-r--r--src/pulsecore/sconv.h2
-rw-r--r--src/pulsecore/semaphore-posix.c2
-rw-r--r--src/pulsecore/semaphore-win32.c2
-rw-r--r--src/pulsecore/semaphore.h2
-rw-r--r--src/pulsecore/shm.c2
-rw-r--r--src/pulsecore/shm.h2
-rw-r--r--src/pulsecore/shmasyncq.c2
-rw-r--r--src/pulsecore/shmasyncq.h2
-rw-r--r--src/pulsecore/sink-input.c150
-rw-r--r--src/pulsecore/sink-input.h37
-rw-r--r--src/pulsecore/sink.c383
-rw-r--r--src/pulsecore/sink.h46
-rw-r--r--src/pulsecore/sioman.c2
-rw-r--r--src/pulsecore/sioman.h2
-rw-r--r--src/pulsecore/socket-client.c20
-rw-r--r--src/pulsecore/socket-client.h2
-rw-r--r--src/pulsecore/socket-server.c17
-rw-r--r--src/pulsecore/socket-server.h6
-rw-r--r--src/pulsecore/socket-util.c41
-rw-r--r--src/pulsecore/socket-util.h8
-rw-r--r--src/pulsecore/sound-file-stream.c14
-rw-r--r--src/pulsecore/sound-file-stream.h2
-rw-r--r--src/pulsecore/sound-file.c7
-rw-r--r--src/pulsecore/sound-file.h2
-rw-r--r--src/pulsecore/source-output.c113
-rw-r--r--src/pulsecore/source-output.h35
-rw-r--r--src/pulsecore/source.c304
-rw-r--r--src/pulsecore/source.h63
-rw-r--r--src/pulsecore/speexwrap.h2
-rw-r--r--src/pulsecore/start-child.c2
-rw-r--r--src/pulsecore/start-child.h2
-rw-r--r--src/pulsecore/strbuf.c2
-rw-r--r--src/pulsecore/strbuf.h2
-rw-r--r--src/pulsecore/strlist.c2
-rw-r--r--src/pulsecore/strlist.h2
-rw-r--r--src/pulsecore/tagstruct.c2
-rw-r--r--src/pulsecore/tagstruct.h2
-rw-r--r--src/pulsecore/thread-mq.c2
-rw-r--r--src/pulsecore/thread-mq.h2
-rw-r--r--src/pulsecore/thread-posix.c2
-rw-r--r--src/pulsecore/thread-win32.c2
-rw-r--r--src/pulsecore/thread.h2
-rw-r--r--src/pulsecore/time-smoother.c10
-rw-r--r--src/pulsecore/time-smoother.h4
-rw-r--r--src/pulsecore/tokenizer.c2
-rw-r--r--src/pulsecore/tokenizer.h2
-rw-r--r--src/pulsecore/x11prop.c2
-rw-r--r--src/pulsecore/x11prop.h2
-rw-r--r--src/pulsecore/x11wrap.c43
-rw-r--r--src/pulsecore/x11wrap.h12
195 files changed, 1565 insertions, 839 deletions
diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index eba1c2cb..5c7af2a8 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h
index 93f1ce86..1f38207a 100644
--- a/src/pulsecore/asyncmsgq.h
+++ b/src/pulsecore/asyncmsgq.h
@@ -1,8 +1,6 @@
#ifndef foopulseasyncmsgqhfoo
#define foopulseasyncmsgqhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c
index 8e0dfbc3..03e9f0df 100644
--- a/src/pulsecore/asyncq.c
+++ b/src/pulsecore/asyncq.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/asyncq.h b/src/pulsecore/asyncq.h
index 4cdf8cd0..e6847ab8 100644
--- a/src/pulsecore/asyncq.h
+++ b/src/pulsecore/asyncq.h
@@ -1,8 +1,6 @@
#ifndef foopulseasyncqhfoo
#define foopulseasyncqhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h
index ad3dca30..a91c4d56 100644
--- a/src/pulsecore/atomic.h
+++ b/src/pulsecore/atomic.h
@@ -1,12 +1,11 @@
#ifndef foopulseatomichfoo
#define foopulseatomichfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
- Copyright 2006 Lennart Poettering
+ Copyright 2006-2008 Lennart Poettering
+ Copyright 2008 Nokia Corporation
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
@@ -380,9 +379,9 @@ static inline int pa_atomic_dec(pa_atomic_t *a) {
/* Returns non-zero when the operation was successful. */
static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) {
- int failed = 1;
+ pa_bool_t failed;
do {
- failed = __kernel_cmpxchg(old_i, new_i, &a->value);
+ failed = !!__kernel_cmpxchg(old_i, new_i, &a->value);
} while(failed && a->value == old_i);
return !failed;
}
@@ -404,10 +403,10 @@ static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) {
}
static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) {
- int failed = 1;
+ pa_bool_t failed;
do {
- failed = __kernel_cmpxchg_u((unsigned long) old_p, (unsigned long) new_p, &a->value);
- } while(failed && a->value == old_p);
+ failed = !!__kernel_cmpxchg_u((unsigned long) old_p, (unsigned long) new_p, &a->value);
+ } while(failed && a->value == (unsigned long) old_p);
return !failed;
}
diff --git a/src/pulsecore/authkey-prop.c b/src/pulsecore/authkey-prop.c
index 54154500..a953bf7d 100644
--- a/src/pulsecore/authkey-prop.c
+++ b/src/pulsecore/authkey-prop.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/authkey-prop.h b/src/pulsecore/authkey-prop.h
index 247202f3..de02d2aa 100644
--- a/src/pulsecore/authkey-prop.h
+++ b/src/pulsecore/authkey-prop.h
@@ -1,8 +1,6 @@
#ifndef fooauthkeyprophfoo
#define fooauthkeyprophfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c
index 80bc8576..f3f40f80 100644
--- a/src/pulsecore/authkey.c
+++ b/src/pulsecore/authkey.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/authkey.h b/src/pulsecore/authkey.h
index 18e5157d..8301db1e 100644
--- a/src/pulsecore/authkey.h
+++ b/src/pulsecore/authkey.h
@@ -1,8 +1,6 @@
#ifndef fooauthkeyhfoo
#define fooauthkeyhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/autoload.c b/src/pulsecore/autoload.c
index a1d3e02d..26c294b2 100644
--- a/src/pulsecore/autoload.c
+++ b/src/pulsecore/autoload.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/autoload.h b/src/pulsecore/autoload.h
index 8a3522a7..3926351f 100644
--- a/src/pulsecore/autoload.h
+++ b/src/pulsecore/autoload.h
@@ -1,8 +1,6 @@
#ifndef fooautoloadhfoo
#define fooautoloadhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/avahi-wrap.c b/src/pulsecore/avahi-wrap.c
index fae54810..d5f40d83 100644
--- a/src/pulsecore/avahi-wrap.c
+++ b/src/pulsecore/avahi-wrap.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/avahi-wrap.h b/src/pulsecore/avahi-wrap.h
index 1e20ec38..7d8995bb 100644
--- a/src/pulsecore/avahi-wrap.h
+++ b/src/pulsecore/avahi-wrap.h
@@ -1,8 +1,6 @@
#ifndef fooavahiwrapperhfoo
#define fooavahiwrapperhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 925a2e8c..cbdb602a 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/cli-command.h b/src/pulsecore/cli-command.h
index 2a923443..9bf35dc3 100644
--- a/src/pulsecore/cli-command.h
+++ b/src/pulsecore/cli-command.h
@@ -1,8 +1,6 @@
#ifndef fooclicommandhfoo
#define fooclicommandhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 029a7089..c92fca20 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -118,6 +116,9 @@ char *pa_sink_list_to_string(pa_core *c) {
for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
+ pa_usec_t min_latency, max_latency;
+
+ pa_sink_get_latency_range(sink, &min_latency, &max_latency);
pa_strbuf_printf(
s,
@@ -130,6 +131,8 @@ char *pa_sink_list_to_string(pa_core *c) {
"\tmuted: %s\n"
"\tcurrent latency: %0.2f ms\n"
"\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n"
+ "\tmax request: %lu KiB\n"
+ "\tmax rewind: %lu KiB\n"
"\tmonitor source: %u\n"
"\tsample spec: %s\n"
"\tchannel map: %s\n"
@@ -149,7 +152,9 @@ char *pa_sink_list_to_string(pa_core *c) {
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)),
pa_yes_no(pa_sink_get_mute(sink)),
(double) pa_sink_get_latency(sink) / PA_USEC_PER_MSEC,
- (double) pa_sink_get_requested_latency(sink) / PA_USEC_PER_MSEC, (double) sink->min_latency / PA_USEC_PER_MSEC, (double) sink->max_latency / PA_USEC_PER_MSEC,
+ (double) pa_sink_get_requested_latency(sink) / PA_USEC_PER_MSEC, (double) min_latency / PA_USEC_PER_MSEC, (double) max_latency / PA_USEC_PER_MSEC,
+ (unsigned long) pa_sink_get_max_request(sink) / 1024,
+ (unsigned long) pa_sink_get_max_rewind(sink) / 1024,
sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &sink->channel_map),
@@ -186,6 +191,9 @@ char *pa_source_list_to_string(pa_core *c) {
for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], *t;
+ pa_usec_t min_latency, max_latency;
+
+ pa_source_get_latency_range(source, &min_latency, &max_latency);
pa_strbuf_printf(
s,
@@ -198,6 +206,7 @@ char *pa_source_list_to_string(pa_core *c) {
"\tmuted: %s\n"
"\tcurrent latency: %0.2f ms\n"
"\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n"
+ "\tmax rewind: %lu KiB\n"
"\tsample spec: %s\n"
"\tchannel map: %s\n"
"\tused by: %u\n"
@@ -216,7 +225,8 @@ char *pa_source_list_to_string(pa_core *c) {
pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)),
pa_yes_no(pa_source_get_mute(source)),
(double) pa_source_get_latency(source) / PA_USEC_PER_MSEC,
- (double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC, (double) source->min_latency / PA_USEC_PER_MSEC, (double) source->max_latency / PA_USEC_PER_MSEC,
+ (double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC, (double) min_latency / PA_USEC_PER_MSEC, (double) max_latency / PA_USEC_PER_MSEC,
+ (unsigned long) pa_source_get_max_rewind(source) / 1024,
pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map),
pa_source_used_by(source),
@@ -287,7 +297,7 @@ char *pa_source_output_list_to_string(pa_core *c) {
o->flags & PA_SOURCE_OUTPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "",
state_table[pa_source_output_get_state(o)],
o->source->index, o->source->name,
- (double) pa_source_output_get_latency(o) / PA_USEC_PER_MSEC,
+ (double) pa_source_output_get_latency(o, NULL) / PA_USEC_PER_MSEC,
clt,
pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map),
@@ -296,6 +306,8 @@ char *pa_source_output_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "\towner module: %u\n", o->module->index);
if (o->client)
pa_strbuf_printf(s, "\tclient: %u <%s>\n", o->client->index, pa_strnull(pa_proplist_gets(o->client->proplist, PA_PROP_APPLICATION_NAME)));
+ if (o->direct_on_input)
+ pa_strbuf_printf(s, "\tdirect on input: %u\n", o->direct_on_input->index);
t = pa_proplist_to_string(o->proplist);
pa_strbuf_printf(s, "\tproperties:\n%s", t);
@@ -361,7 +373,7 @@ char *pa_sink_input_list_to_string(pa_core *c) {
i->sink->index, i->sink->name,
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)),
pa_yes_no(pa_sink_input_get_mute(i)),
- (double) pa_sink_input_get_latency(i) / PA_USEC_PER_MSEC,
+ (double) pa_sink_input_get_latency(i, NULL) / PA_USEC_PER_MSEC,
clt,
pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
diff --git a/src/pulsecore/cli-text.h b/src/pulsecore/cli-text.h
index 9e5bf081..f4cb97a5 100644
--- a/src/pulsecore/cli-text.h
+++ b/src/pulsecore/cli-text.h
@@ -1,8 +1,6 @@
#ifndef fooclitexthfoo
#define fooclitexthfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c
index 47712d30..b3c639f8 100644
--- a/src/pulsecore/cli.c
+++ b/src/pulsecore/cli.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/cli.h b/src/pulsecore/cli.h
index 2b58d458..6077a8e8 100644
--- a/src/pulsecore/cli.h
+++ b/src/pulsecore/cli.h
@@ -1,8 +1,6 @@
#ifndef fooclihfoo
#define fooclihfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c
index 4eca4e2a..0ffd2330 100644
--- a/src/pulsecore/client.c
+++ b/src/pulsecore/client.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -66,18 +64,21 @@ pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) {
}
void pa_client_free(pa_client *c) {
+ pa_core *core;
+
pa_assert(c);
pa_assert(c->core);
+ core = c->core;
pa_idxset_remove_by_data(c->core->clients, c, NULL);
- pa_core_check_quit(c->core);
-
pa_log_info("Freed %u \"%s\"", c->index, pa_strnull(pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME)));
pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index);
pa_proplist_free(c->proplist);
pa_xfree(c->driver);
pa_xfree(c);
+
+ pa_core_check_quit(core);
}
void pa_client_kill(pa_client *c) {
diff --git a/src/pulsecore/client.h b/src/pulsecore/client.h
index bff057ed..28d1fe5f 100644
--- a/src/pulsecore/client.h
+++ b/src/pulsecore/client.h
@@ -1,8 +1,6 @@
#ifndef foopulseclienthfoo
#define foopulseclienthfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c
index 12ea49c2..4aec45d7 100644
--- a/src/pulsecore/conf-parser.c
+++ b/src/pulsecore/conf-parser.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/conf-parser.h b/src/pulsecore/conf-parser.h
index b56d979e..7eb1fae2 100644
--- a/src/pulsecore/conf-parser.h
+++ b/src/pulsecore/conf-parser.h
@@ -1,8 +1,6 @@
#ifndef fooconfparserhfoo
#define fooconfparserhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/core-error.c b/src/pulsecore/core-error.c
index 8a61e726..3d6c2c3b 100644
--- a/src/pulsecore/core-error.c
+++ b/src/pulsecore/core-error.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/core-error.h b/src/pulsecore/core-error.h
index 443c4883..b0c306c7 100644
--- a/src/pulsecore/core-error.h
+++ b/src/pulsecore/core-error.h
@@ -1,8 +1,6 @@
#ifndef foocoreerrorhfoo
#define foocoreerrorhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index e5546007..75fa2ff1 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -63,7 +61,7 @@
#include "core-scache.h"
-#define UNLOAD_POLL_TIME 5
+#define UNLOAD_POLL_TIME 60
static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
pa_core *c = userdata;
@@ -131,8 +129,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
}
e->last_used_time = 0;
- e->memchunk.memblock = NULL;
- e->memchunk.index = e->memchunk.length = 0;
+ pa_memchunk_reset(&e->memchunk);
e->filename = NULL;
e->lazy = FALSE;
e->last_used_time = 0;
@@ -165,8 +162,7 @@ int pa_scache_add_item(
pa_assert(!map || (pa_channel_map_valid(map) && ss && ss->channels == map->channels));
if (ss && !map)
- if (!(map = pa_channel_map_init_auto(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT)))
- return -1;
+ pa_channel_map_init_extend(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT);
if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX)
return -1;
@@ -277,8 +273,7 @@ int pa_scache_remove_item(pa_core *c, const char *name) {
if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0)))
return -1;
- if (pa_idxset_remove_by_data(c->scache, e, NULL) != e)
- pa_assert(0);
+ pa_assert_se(pa_idxset_remove_by_data(c->scache, e, NULL) == e);
pa_log_debug("Removed sample \"%s\"", name);
diff --git a/src/pulsecore/core-scache.h b/src/pulsecore/core-scache.h
index 31f3ff32..80e0fd04 100644
--- a/src/pulsecore/core-scache.h
+++ b/src/pulsecore/core-scache.h
@@ -1,8 +1,6 @@
#ifndef foocorescachehfoo
#define foocorescachehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/core-subscribe.c b/src/pulsecore/core-subscribe.c
index 06c5a4ad..6107002b 100644
--- a/src/pulsecore/core-subscribe.c
+++ b/src/pulsecore/core-subscribe.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/core-subscribe.h b/src/pulsecore/core-subscribe.h
index 2b6863f9..2f9730d9 100644
--- a/src/pulsecore/core-subscribe.h
+++ b/src/pulsecore/core-subscribe.h
@@ -1,8 +1,6 @@
#ifndef foocoresubscribehfoo
#define foocoresubscribehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index c8ea4f52..d259fb16 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -1144,12 +1142,13 @@ fail:
/* Unlock a temporary lcok file */
int pa_unlock_lockfile(const char *fn, int fd) {
int r = 0;
- pa_assert(fn);
pa_assert(fd >= 0);
- if (unlink(fn) < 0) {
- pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
- r = -1;
+ if (fn) {
+ if (unlink(fn) < 0) {
+ pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
+ r = -1;
+ }
}
if (pa_lock_fd(fd, 0) < 0) {
@@ -1165,24 +1164,35 @@ int pa_unlock_lockfile(const char *fn, int fd) {
return r;
}
-char *pa_get_runtime_dir(void) {
+static char *get_dir(mode_t m, const char *env_name) {
const char *e;
char *d;
- if ((e = getenv("PULSE_RUNTIME_PATH")))
+ if ((e = getenv(env_name)))
d = pa_xstrdup(e);
else {
char h[PATH_MAX];
+ struct stat st;
if (!pa_get_home_dir(h, sizeof(h))) {
pa_log_error("Failed to get home directory.");
return NULL;
}
+ if (stat(h, &st) < 0) {
+ pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
+ return NULL;
+ }
+
+ if (st.st_uid != getuid()) {
+ pa_log_error("Home directory %s not ours.", d);
+ return NULL;
+ }
+
d = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
}
- if (pa_make_secure_dir(d, 0700, (pid_t) -1, (pid_t) -1) < 0) {
+ if (pa_make_secure_dir(d, m, (pid_t) -1, (pid_t) -1) < 0) {
pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
return NULL;
}
@@ -1190,6 +1200,14 @@ char *pa_get_runtime_dir(void) {
return d;
}
+char *pa_get_runtime_dir(void) {
+ return get_dir(pa_in_system_mode() ? 0755 : 0700, "PULSE_RUNTIME_PATH");
+}
+
+char *pa_get_state_dir(void) {
+ return get_dir(0700, "PULSE_STATE_PATH");
+}
+
/* Try to open a configuration file. If "env" is specified, open the
* value of the specified environment variable. Otherwise look for a
* file "local" in the home directory or a file "global" in global
@@ -1418,7 +1436,7 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
}
/* Returns nonzero when *s starts with *pfx */
-int pa_startswith(const char *s, const char *pfx) {
+pa_bool_t pa_startswith(const char *s, const char *pfx) {
size_t l;
pa_assert(s);
@@ -1430,7 +1448,7 @@ int pa_startswith(const char *s, const char *pfx) {
}
/* Returns nonzero when *s ends with *sfx */
-int pa_endswith(const char *s, const char *sfx) {
+pa_bool_t pa_endswith(const char *s, const char *sfx) {
size_t l1, l2;
pa_assert(s);
@@ -1472,13 +1490,16 @@ char *pa_make_path_absolute(const char *p) {
/* if fn is null return the PulseAudio run time path in s (~/.pulse)
* if fn is non-null and starts with / return fn
* otherwise append fn to the run time path and return it */
-char *pa_runtime_path(const char *fn) {
+static char *get_path(const char *fn, pa_bool_t rt) {
char *rtp;
if (pa_is_path_absolute(fn))
return pa_xstrdup(fn);
- rtp = pa_get_runtime_dir();
+ rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
+
+ if (!rtp)
+ return NULL;
if (fn) {
char *r;
@@ -1489,6 +1510,14 @@ char *pa_runtime_path(const char *fn) {
return rtp;
}
+char *pa_runtime_path(const char *fn) {
+ return get_path(fn, 1);
+}
+
+char *pa_state_path(const char *fn) {
+ return get_path(fn, 0);
+}
+
/* Convert the string s to a signed integer in *ret_i */
int pa_atoi(const char *s, int32_t *ret_i) {
char *x = NULL;
@@ -1541,13 +1570,13 @@ static void c_locale_destroy(void) {
}
#endif
-int pa_atof(const char *s, float *ret_f) {
+int pa_atod(const char *s, double *ret_d) {
char *x = NULL;
- float f;
+ double f;
int r = 0;
pa_assert(s);
- pa_assert(ret_f);
+ pa_assert(ret_d);
/* This should be locale independent */
@@ -1562,22 +1591,18 @@ int pa_atof(const char *s, float *ret_f) {
if (c_locale) {
errno = 0;
- f = strtof_l(s, &x, c_locale);
+ f = strtod_l(s, &x, c_locale);
} else
#endif
{
errno = 0;
-#ifdef HAVE_STRTOF
- f = strtof(s, &x);
-#else
f = strtod(s, &x);
-#endif
}
if (!x || *x || errno != 0)
r = -1;
else
- *ret_f = f;
+ *ret_d = f;
return r;
}
@@ -1774,10 +1799,11 @@ int pa_close_all(int except_fd, ...) {
i = 0;
if (except_fd >= 0) {
+ int fd;
p[i++] = except_fd;
- while ((p[i++] = va_arg(ap, int)) >= 0)
- ;
+ while ((fd = va_arg(ap, int)) >= 0)
+ p[i++] = fd;
}
p[i] = -1;
@@ -1803,6 +1829,7 @@ int pa_close_allv(const int except_fds[]) {
struct dirent *de;
while ((de = readdir(d))) {
+ pa_bool_t found;
long l;
char *e = NULL;
int i;
@@ -1826,17 +1853,23 @@ int pa_close_allv(const int except_fds[]) {
return -1;
}
- if (fd <= 3)
+ if (fd < 3)
continue;
if (fd == dirfd(d))
continue;
+ found = FALSE;
for (i = 0; except_fds[i] >= 0; i++)
- if (except_fds[i] == fd)
- continue;
+ if (except_fds[i] == fd) {
+ found = TRUE;
+ break;
+ }
+
+ if (found)
+ continue;
- if (close(fd) < 0) {
+ if (pa_close(fd) < 0) {
saved_errno = errno;
closedir(d);
errno = saved_errno;
@@ -1890,10 +1923,11 @@ int pa_unblock_sigs(int except, ...) {
i = 0;
if (except >= 1) {
+ int sig;
p[i++] = except;
- while ((p[i++] = va_arg(ap, int)) >= 0)
- ;
+ while ((sig = va_arg(ap, int)) >= 0)
+ p[i++] = sig;
}
p[i] = -1;
@@ -1957,12 +1991,12 @@ int pa_reset_sigsv(const int except[]) {
int sig;
for (sig = 1; sig < _NSIG; sig++) {
- int reset = 1;
+ pa_bool_t reset = TRUE;
switch (sig) {
case SIGKILL:
case SIGSTOP:
- reset = 0;
+ reset = FALSE;
break;
default: {
@@ -1970,7 +2004,7 @@ int pa_reset_sigsv(const int except[]) {
for (i = 0; except[i] > 0; i++) {
if (sig == except[i]) {
- reset = 0;
+ reset = FALSE;
break;
}
}
@@ -2000,3 +2034,12 @@ void pa_set_env(const char *key, const char *value) {
putenv(pa_sprintf_malloc("%s=%s", key, value));
}
+
+pa_bool_t pa_in_system_mode(void) {
+ const char *e;
+
+ if (!(e = getenv("PULSE_SYSTEM")))
+ return FALSE;
+
+ return !!atoi(e);
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index ec4cdc43..2ed81fc5 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -1,8 +1,6 @@
#ifndef foocoreutilhfoo
#define foocoreutilhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -114,18 +112,20 @@ int pa_unlock_lockfile(const char *fn, int fd);
char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength);
size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength);
-int pa_startswith(const char *s, const char *pfx) PA_GCC_PURE;
-int pa_endswith(const char *s, const char *sfx) PA_GCC_PURE;
+pa_bool_t pa_startswith(const char *s, const char *pfx) PA_GCC_PURE;
+pa_bool_t pa_endswith(const char *s, const char *sfx) PA_GCC_PURE;
FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result);
char* pa_find_config_file(const char *global, const char *local, const char *env);
char *pa_get_runtime_dir(void);
+char *pa_get_state_dir(void);
char *pa_runtime_path(const char *fn);
+char *pa_state_path(const char *fn);
int pa_atoi(const char *s, int32_t *ret_i);
int pa_atou(const char *s, uint32_t *ret_u);
-int pa_atof(const char *s, float *ret_f);
+int pa_atod(const char *s, double *ret_d);
int pa_snprintf(char *str, size_t size, const char *format, ...);
int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap);
@@ -180,4 +180,8 @@ int pa_reset_sigsv(const int except[]);
void pa_set_env(const char *key, const char *value);
+pa_bool_t pa_in_system_mode(void);
+
+#define pa_streq(a,b) (!strcmp((a),(b)))
+
#endif
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 3b758a38..b2638b10 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -135,7 +133,6 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3;
- c->is_system_instance = FALSE;
c->disallow_module_loading = FALSE;
c->realtime_scheduling = FALSE;
c->realtime_priority = 5;
@@ -210,11 +207,16 @@ static void quit_callback(pa_mainloop_api*m, pa_time_event *e, PA_GCC_UNUSED con
void pa_core_check_quit(pa_core *c) {
pa_assert(c);
- if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_size(c->clients) == 0) {
+ if (!c->quit_event &&
+ c->exit_idle_time >= 0 &&
+ pa_idxset_size(c->clients) == 0) {
+
struct timeval tv;
pa_gettimeofday(&tv);
tv.tv_sec+= c->exit_idle_time;
+
c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c);
+
} else if (c->quit_event && pa_idxset_size(c->clients) > 0) {
c->mainloop->time_free(c->quit_event);
c->quit_event = NULL;
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 50c05b4c..d9ed46f6 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -1,8 +1,6 @@
#ifndef foocorehfoo
#define foocorehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -123,7 +121,6 @@ struct pa_core {
pa_bool_t disallow_module_loading, running_as_daemon;
pa_resample_method_t resample_method;
- pa_bool_t is_system_instance;
pa_bool_t realtime_scheduling;
int realtime_priority;
pa_bool_t disable_remixing;
diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h
index 51dfc33d..c15c469b 100644
--- a/src/pulsecore/creds.h
+++ b/src/pulsecore/creds.h
@@ -1,8 +1,6 @@
#ifndef foocredshfoo
#define foocredshfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/dllmain.c b/src/pulsecore/dllmain.c
index 52cbf9e2..269de604 100644
--- a/src/pulsecore/dllmain.c
+++ b/src/pulsecore/dllmain.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/dynarray.c b/src/pulsecore/dynarray.c
index 8bdb46fa..a1fcd8a3 100644
--- a/src/pulsecore/dynarray.c
+++ b/src/pulsecore/dynarray.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/dynarray.h b/src/pulsecore/dynarray.h
index 0f222e10..82b42082 100644
--- a/src/pulsecore/dynarray.h
+++ b/src/pulsecore/dynarray.h
@@ -1,8 +1,6 @@
#ifndef foodynarrayhfoo
#define foodynarrayhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h
index 6b80246b..26336918 100644
--- a/src/pulsecore/endianmacros.h
+++ b/src/pulsecore/endianmacros.h
@@ -1,8 +1,6 @@
#ifndef fooendianmacroshfoo
#define fooendianmacroshfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/envelope.c b/src/pulsecore/envelope.c
index 2f5da5a0..e2691611 100644
--- a/src/pulsecore/envelope.c
+++ b/src/pulsecore/envelope.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/envelope.h b/src/pulsecore/envelope.h
index c54c137a..5296415a 100644
--- a/src/pulsecore/envelope.h
+++ b/src/pulsecore/envelope.h
@@ -1,8 +1,6 @@
#ifndef foopulseenvelopehfoo
#define foopulseenvelopehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/esound.h b/src/pulsecore/esound.h
index ea6a5665..79322ae4 100644
--- a/src/pulsecore/esound.h
+++ b/src/pulsecore/esound.h
@@ -1,8 +1,6 @@
#ifndef fooesoundhfoo
#define fooesoundhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index 22d2a850..1531e3db 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/fdsem.h b/src/pulsecore/fdsem.h
index f4f7b99a..48a77c49 100644
--- a/src/pulsecore/fdsem.h
+++ b/src/pulsecore/fdsem.h
@@ -1,8 +1,6 @@
#ifndef foopulsefdsemhfoo
#define foopulsefdsemhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c
index d9740777..f166ee33 100644
--- a/src/pulsecore/flist.c
+++ b/src/pulsecore/flist.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h
index 3d9a89a2..c040667d 100644
--- a/src/pulsecore/flist.h
+++ b/src/pulsecore/flist.h
@@ -1,8 +1,6 @@
#ifndef foopulseflisthfoo
#define foopulseflisthfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c
index c9d5632c..b7f4109b 100644
--- a/src/pulsecore/hashmap.c
+++ b/src/pulsecore/hashmap.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -191,24 +189,36 @@ unsigned pa_hashmap_size(pa_hashmap *h) {
}
void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void **key) {
+ struct hashmap_entry *e;
+
pa_assert(h);
pa_assert(state);
- if (!*state)
- *state = h->first_entry;
+ if (*state == (void*) -1)
+ goto at_end;
+
+ if ((!*state && !h->first_entry))
+ goto at_end;
+
+ e = *state ? *state : h->first_entry;
+
+ if (e->next)
+ *state = e->next;
else
- *state = ((struct hashmap_entry*) *state)->next;
+ *state = (void*) -1;
- if (!*state) {
- if (key)
- *key = NULL;
- return NULL;
- }
+ if (key)
+ *key = e->key;
+
+ return e->value;
+
+at_end:
+ *state = (void *) -1;
if (key)
- *key = ((struct hashmap_entry*) *state)->key;
+ *key = NULL;
- return ((struct hashmap_entry*) *state)->value;
+ return NULL;
}
void* pa_hashmap_steal_first(pa_hashmap *h) {
diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h
index 98df4502..a4505c4c 100644
--- a/src/pulsecore/hashmap.h
+++ b/src/pulsecore/hashmap.h
@@ -1,8 +1,6 @@
#ifndef foohashmaphfoo
#define foohashmaphfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -51,9 +49,10 @@ unsigned pa_hashmap_size(pa_hashmap *h);
/* May be used to iterate through the hashmap. Initially the opaque
pointer *state has to be set to NULL. The hashmap may not be
- modified during iteration. The key of the entry is returned in
- *key, if key is non-NULL. After the last entry in the hashmap NULL
- is returned. */
+ modified during iteration -- except for deleting the current entry
+ via pa_hashmap_remove(). The key of the entry is returned in *key,
+ if key is non-NULL. After the last entry in the hashmap NULL is
+ returned. */
void *pa_hashmap_iterate(pa_hashmap *h, void **state, const void**key);
void *pa_hashmap_steal_first(pa_hashmap *h);
diff --git a/src/pulsecore/hook-list.c b/src/pulsecore/hook-list.c
index 3a6874c4..0aac4759 100644
--- a/src/pulsecore/hook-list.c
+++ b/src/pulsecore/hook-list.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -33,8 +31,7 @@ void pa_hook_init(pa_hook *hook, void *data) {
pa_assert(hook);
PA_LLIST_HEAD_INIT(pa_hook_slot, hook->slots);
- hook->last = NULL;
- hook->n_dead = hook->firing = 0;
+ hook->n_dead = hook->n_firing = 0;
hook->data = data;
}
@@ -42,9 +39,6 @@ static void slot_free(pa_hook *hook, pa_hook_slot *slot) {
pa_assert(hook);
pa_assert(slot);
- if (hook->last == slot)
- hook->last = slot->prev;
-
PA_LLIST_REMOVE(pa_hook_slot, hook->slots, slot);
pa_xfree(slot);
@@ -52,7 +46,7 @@ static void slot_free(pa_hook *hook, pa_hook_slot *slot) {
void pa_hook_free(pa_hook *hook) {
pa_assert(hook);
- pa_assert(!hook->firing);
+ pa_assert(hook->n_firing == 0);
while (hook->slots)
slot_free(hook, hook->slots);
@@ -60,19 +54,26 @@ void pa_hook_free(pa_hook *hook) {
pa_hook_init(hook, NULL);
}
-pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *data) {
- pa_hook_slot *slot;
+pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_priority_t prio, pa_hook_cb_t cb, void *data) {
+ pa_hook_slot *slot, *where, *prev;
pa_assert(cb);
slot = pa_xnew(pa_hook_slot, 1);
slot->hook = hook;
- slot->dead = 0;
+ slot->dead = FALSE;
slot->callback = cb;
slot->data = data;
+ slot->priority = prio;
- PA_LLIST_INSERT_AFTER(pa_hook_slot, hook->slots, hook->last, slot);
- hook->last = slot;
+ prev = NULL;
+ for (where = hook->slots; where; where = where->next) {
+ if (prio < where->priority)
+ break;
+ prev = where;
+ }
+
+ PA_LLIST_INSERT_AFTER(pa_hook_slot, hook->slots, prev, slot);
return slot;
}
@@ -81,8 +82,8 @@ void pa_hook_slot_free(pa_hook_slot *slot) {
pa_assert(slot);
pa_assert(!slot->dead);
- if (slot->hook->firing > 0) {
- slot->dead = 1;
+ if (slot->hook->n_firing > 0) {
+ slot->dead = TRUE;
slot->hook->n_dead++;
} else
slot_free(slot->hook, slot);
@@ -94,7 +95,7 @@ pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) {
pa_assert(hook);
- hook->firing ++;
+ hook->n_firing ++;
for (slot = hook->slots; slot; slot = slot->next) {
if (slot->dead)
@@ -104,7 +105,8 @@ pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) {
break;
}
- hook->firing --;
+ hook->n_firing --;
+ pa_assert(hook->n_firing >= 0);
for (slot = hook->slots; hook->n_dead > 0 && slot; slot = next) {
next = slot->next;
@@ -115,6 +117,7 @@ pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) {
}
}
+ pa_assert(hook->n_dead == 0);
+
return result;
}
-
diff --git a/src/pulsecore/hook-list.h b/src/pulsecore/hook-list.h
index c288980d..cf85aca5 100644
--- a/src/pulsecore/hook-list.h
+++ b/src/pulsecore/hook-list.h
@@ -1,8 +1,6 @@
#ifndef foohooklistfoo
#define foohooklistfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -38,14 +36,21 @@ typedef enum pa_hook_result {
PA_HOOK_CANCEL = -1
} pa_hook_result_t;
+typedef enum pa_hook_priority {
+ PA_HOOK_EARLY = -100,
+ PA_HOOK_NORMAL = 0,
+ PA_HOOK_LATE = 100
+} pa_hook_priority_t;
+
typedef pa_hook_result_t (*pa_hook_cb_t)(
void *hook_data,
void *call_data,
void *slot_data);
struct pa_hook_slot {
- int dead;
+ pa_bool_t dead;
pa_hook *hook;
+ pa_hook_priority_t priority;
pa_hook_cb_t callback;
void *data;
PA_LLIST_FIELDS(pa_hook_slot);
@@ -53,8 +58,7 @@ struct pa_hook_slot {
struct pa_hook {
PA_LLIST_HEAD(pa_hook_slot, slots);
- pa_hook_slot *last;
- int firing, n_dead;
+ int n_firing, n_dead;
void *data;
};
@@ -62,7 +66,7 @@ struct pa_hook {
void pa_hook_init(pa_hook *hook, void *data);
void pa_hook_free(pa_hook *hook);
-pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t, void *data);
+pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_priority_t prio, pa_hook_cb_t cb, void *data);
void pa_hook_slot_free(pa_hook_slot *slot);
pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data);
diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c
index 8a88471f..7c9520a4 100644
--- a/src/pulsecore/idxset.c
+++ b/src/pulsecore/idxset.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h
index 5b55cec2..0a4e528e 100644
--- a/src/pulsecore/idxset.h
+++ b/src/pulsecore/idxset.h
@@ -1,8 +1,6 @@
#ifndef fooidxsethfoo
#define fooidxsethfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/inet_ntop.c b/src/pulsecore/inet_ntop.c
index 4a4f7aac..87551232 100644
--- a/src/pulsecore/inet_ntop.c
+++ b/src/pulsecore/inet_ntop.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/inet_pton.c b/src/pulsecore/inet_pton.c
index 84d0c0ea..d191e550 100644
--- a/src/pulsecore/inet_pton.c
+++ b/src/pulsecore/inet_pton.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c
index 63ab2ad7..b40c9815 100644
--- a/src/pulsecore/iochannel.c
+++ b/src/pulsecore/iochannel.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -424,3 +422,16 @@ int pa_iochannel_get_send_fd(pa_iochannel *io) {
return io->ofd;
}
+
+pa_bool_t pa_iochannel_socket_is_local(pa_iochannel *io) {
+ pa_assert(io);
+
+ if (pa_socket_is_local(io->ifd))
+ return TRUE;
+
+ if (io->ifd != io->ofd)
+ if (pa_socket_is_local(io->ofd))
+ return TRUE;
+
+ return FALSE;
+}
diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h
index c9794d99..9050df90 100644
--- a/src/pulsecore/iochannel.h
+++ b/src/pulsecore/iochannel.h
@@ -1,8 +1,6 @@
#ifndef fooiochannelhfoo
#define fooiochannelhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -85,6 +83,8 @@ void pa_iochannel_socket_peer_to_string(pa_iochannel*io, char*s, size_t l);
int pa_iochannel_socket_set_rcvbuf(pa_iochannel*io, size_t l);
int pa_iochannel_socket_set_sndbuf(pa_iochannel*io, size_t l);
+pa_bool_t pa_iochannel_socket_is_local(pa_iochannel *io);
+
pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io);
int pa_iochannel_get_recv_fd(pa_iochannel *io);
diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c
index 85bbadc4..90afaafd 100644
--- a/src/pulsecore/ioline.c
+++ b/src/pulsecore/ioline.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/ioline.h b/src/pulsecore/ioline.h
index f4edc7b4..b9a3d9f4 100644
--- a/src/pulsecore/ioline.h
+++ b/src/pulsecore/ioline.h
@@ -1,8 +1,6 @@
#ifndef fooiolinehfoo
#define fooiolinehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c
index 9b22e8f5..7b5f865b 100644
--- a/src/pulsecore/ipacl.c
+++ b/src/pulsecore/ipacl.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/ipacl.h b/src/pulsecore/ipacl.h
index 175f54e0..7b7ffa61 100644
--- a/src/pulsecore/ipacl.h
+++ b/src/pulsecore/ipacl.h
@@ -1,8 +1,6 @@
#ifndef fooparseaddrhfoo
#define fooparseaddrhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/llist.h b/src/pulsecore/llist.h
index e62f15b4..46b54eb3 100644
--- a/src/pulsecore/llist.h
+++ b/src/pulsecore/llist.h
@@ -1,8 +1,6 @@
#ifndef foollistfoo
#define foollistfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index b5929ec4..5eda4f65 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/log.h b/src/pulsecore/log.h
index 765dd2e5..2047696e 100644
--- a/src/pulsecore/log.h
+++ b/src/pulsecore/log.h
@@ -1,8 +1,6 @@
#ifndef foologhfoo
#define foologhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/ltdl-helper.c b/src/pulsecore/ltdl-helper.c
index b83897a6..0d4c22f8 100644
--- a/src/pulsecore/ltdl-helper.c
+++ b/src/pulsecore/ltdl-helper.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/ltdl-helper.h b/src/pulsecore/ltdl-helper.h
index 5c7388a1..ea73de54 100644
--- a/src/pulsecore/ltdl-helper.h
+++ b/src/pulsecore/ltdl-helper.h
@@ -1,8 +1,6 @@
#ifndef foopulsecoreltdlhelperhfoo
#define foopulsecoreltdlhelperhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index 1d9eafd5..fd33b7bb 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -1,8 +1,6 @@
#ifndef foopulsemacrohfoo
#define foopulsemacrohfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/mcalign.c b/src/pulsecore/mcalign.c
index e12f84f8..a03d5ae7 100644
--- a/src/pulsecore/mcalign.c
+++ b/src/pulsecore/mcalign.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/mcalign.h b/src/pulsecore/mcalign.h
index 6c8b8d5f..e82eb007 100644
--- a/src/pulsecore/mcalign.h
+++ b/src/pulsecore/mcalign.h
@@ -1,8 +1,6 @@
#ifndef foomcalignhfoo
#define foomcalignhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 7005b441..c2ee1360 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h
index 8dc3f5a3..efe55b02 100644
--- a/src/pulsecore/memblock.h
+++ b/src/pulsecore/memblock.h
@@ -1,8 +1,6 @@
#ifndef foopulsememblockhfoo
#define foopulsememblockhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index c047e56f..a9f28a07 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -786,6 +784,9 @@ void pa_memblockq_set_tlength(pa_memblockq *bq, size_t tlength) {
if (bq->tlength > bq->maxlength)
bq->tlength = bq->maxlength;
+ if (bq->prebuf > bq->tlength)
+ pa_memblockq_set_prebuf(bq, bq->tlength);
+
if (bq->minreq > bq->tlength)
pa_memblockq_set_minreq(bq, bq->tlength);
@@ -803,8 +804,8 @@ void pa_memblockq_set_prebuf(pa_memblockq *bq, size_t prebuf) {
if (prebuf > 0 && bq->prebuf < bq->base)
bq->prebuf = bq->base;
- if (bq->prebuf > bq->maxlength)
- bq->prebuf = bq->maxlength;
+ if (bq->prebuf > bq->tlength)
+ bq->prebuf = bq->tlength;
if (bq->prebuf <= 0 || pa_memblockq_get_length(bq) >= bq->prebuf)
bq->in_prebuf = FALSE;
@@ -908,3 +909,9 @@ unsigned pa_memblockq_get_nblocks(pa_memblockq *bq) {
return bq->n_blocks;
}
+
+size_t pa_memblockq_get_base(pa_memblockq *bq) {
+ pa_assert(bq);
+
+ return bq->base;
+}
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index 7c38757f..81f7cbb8 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -1,8 +1,6 @@
#ifndef foomemblockqhfoo
#define foomemblockqhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -169,4 +167,6 @@ pa_bool_t pa_memblockq_prebuf_active(pa_memblockq *bq);
unsigned pa_memblockq_get_nblocks(pa_memblockq *bq);
+size_t pa_memblockq_get_base(pa_memblockq *bq);
+
#endif
diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c
index 16a9c140..0bbf8590 100644
--- a/src/pulsecore/memchunk.c
+++ b/src/pulsecore/memchunk.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -49,17 +47,20 @@ pa_memchunk* pa_memchunk_make_writable(pa_memchunk *c, size_t min) {
pa_memblock_get_length(c->memblock) >= c->index+min)
return c;
- l = c->length;
- if (l < min)
- l = min;
+ l = PA_MAX(c->length, min);
n = pa_memblock_new(pa_memblock_get_pool(c->memblock), l);
- tdata = pa_memblock_acquire(n);
+
sdata = pa_memblock_acquire(c->memblock);
+ tdata = pa_memblock_acquire(n);
+
memcpy(tdata, (uint8_t*) sdata + c->index, c->length);
- pa_memblock_release(n);
+
pa_memblock_release(c->memblock);
+ pa_memblock_release(n);
+
pa_memblock_unref(c->memblock);
+
c->memblock = n;
c->index = 0;
@@ -69,8 +70,7 @@ pa_memchunk* pa_memchunk_make_writable(pa_memchunk *c, size_t min) {
pa_memchunk* pa_memchunk_reset(pa_memchunk *c) {
pa_assert(c);
- c->memblock = NULL;
- c->length = c->index = 0;
+ memset(c, 0, sizeof(*c));
return c;
}
diff --git a/src/pulsecore/memchunk.h b/src/pulsecore/memchunk.h
index 46a82406..9458f4ff 100644
--- a/src/pulsecore/memchunk.h
+++ b/src/pulsecore/memchunk.h
@@ -1,8 +1,6 @@
#ifndef foomemchunkhfoo
#define foomemchunkhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c
index 0dab254b..5f5902c9 100644
--- a/src/pulsecore/modargs.c
+++ b/src/pulsecore/modargs.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -53,6 +51,12 @@ static int add_key_value(pa_hashmap *map, char *key, char *value, const char* co
pa_assert(key);
pa_assert(value);
+ if (pa_hashmap_get(map, key)) {
+ pa_xfree(key);
+ pa_xfree(value);
+ return -1;
+ }
+
if (valid_keys) {
const char*const* v;
for (v = valid_keys; *v; v++)
@@ -80,7 +84,15 @@ pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) {
map = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
if (args) {
- enum { WHITESPACE, KEY, VALUE_START, VALUE_SIMPLE, VALUE_DOUBLE_QUOTES, VALUE_TICKS } state;
+ enum {
+ WHITESPACE,
+ KEY,
+ VALUE_START,
+ VALUE_SIMPLE,
+ VALUE_DOUBLE_QUOTES,
+ VALUE_TICKS
+ } state;
+
const char *p, *key, *value;
size_t key_len = 0, value_len = 0;
@@ -100,6 +112,8 @@ pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) {
case KEY:
if (*p == '=')
state = VALUE_START;
+ else if (isspace(*p))
+ goto fail;
else
key_len++;
break;
diff --git a/src/pulsecore/modargs.h b/src/pulsecore/modargs.h
index 504b9cd7..23766cfc 100644
--- a/src/pulsecore/modargs.h
+++ b/src/pulsecore/modargs.h
@@ -1,8 +1,6 @@
#ifndef foomodargshfoo
#define foomodargshfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/modinfo.c b/src/pulsecore/modinfo.c
index d1a78fbb..ac4ca88a 100644
--- a/src/pulsecore/modinfo.c
+++ b/src/pulsecore/modinfo.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/modinfo.h b/src/pulsecore/modinfo.h
index da6d5428..605637c4 100644
--- a/src/pulsecore/modinfo.h
+++ b/src/pulsecore/modinfo.h
@@ -1,8 +1,6 @@
#ifndef foomodinfohfoo
#define foomodinfohfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c
index 8e5bd2d1..f1eeb762 100644
--- a/src/pulsecore/module.c
+++ b/src/pulsecore/module.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -120,7 +118,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
if (!c->modules)
c->modules = pa_idxset_new(NULL, NULL);
- if (!c->module_auto_unload_event) {
+ if (m->auto_unload && !c->module_auto_unload_event) {
struct timeval ntv;
pa_gettimeofday(&ntv);
pa_timeval_add(&ntv, UNLOAD_POLL_TIME*1000000);
diff --git a/src/pulsecore/module.h b/src/pulsecore/module.h
index 68c7238d..ec582f25 100644
--- a/src/pulsecore/module.h
+++ b/src/pulsecore/module.h
@@ -1,8 +1,6 @@
#ifndef foomodulehfoo
#define foomodulehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/msgobject.c b/src/pulsecore/msgobject.c
index f54e69f2..81417ea4 100644
--- a/src/pulsecore/msgobject.c
+++ b/src/pulsecore/msgobject.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/msgobject.h b/src/pulsecore/msgobject.h
index 8221cc33..1a43fa35 100644
--- a/src/pulsecore/msgobject.h
+++ b/src/pulsecore/msgobject.h
@@ -1,8 +1,6 @@
#ifndef foopulsemsgobjecthfoo
#define foopulsemsgobjecthfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c
index 6ac98484..35465b7b 100644
--- a/src/pulsecore/mutex-posix.c
+++ b/src/pulsecore/mutex-posix.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/mutex-win32.c b/src/pulsecore/mutex-win32.c
index 77d63d15..5e884e7f 100644
--- a/src/pulsecore/mutex-win32.c
+++ b/src/pulsecore/mutex-win32.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/mutex.h b/src/pulsecore/mutex.h
index 9ca8fae5..36e1d635 100644
--- a/src/pulsecore/mutex.h
+++ b/src/pulsecore/mutex.h
@@ -1,8 +1,6 @@
#ifndef foopulsemutexhfoo
#define foopulsemutexhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c
index 1b0977d7..cc18adab 100644
--- a/src/pulsecore/namereg.c
+++ b/src/pulsecore/namereg.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h
index 0f5b4d4d..af0153ec 100644
--- a/src/pulsecore/namereg.h
+++ b/src/pulsecore/namereg.h
@@ -1,8 +1,6 @@
#ifndef foonamereghfoo
#define foonamereghfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h
index 56f9037e..809d6c75 100644
--- a/src/pulsecore/native-common.h
+++ b/src/pulsecore/native-common.h
@@ -1,8 +1,6 @@
#ifndef foonativecommonhfoo
#define foonativecommonhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/object.c b/src/pulsecore/object.c
index 6c36242b..9a2f28f3 100644
--- a/src/pulsecore/object.c
+++ b/src/pulsecore/object.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/object.h b/src/pulsecore/object.h
index 562fd113..7dcfa2eb 100644
--- a/src/pulsecore/object.h
+++ b/src/pulsecore/object.h
@@ -1,8 +1,6 @@
#ifndef foopulseobjecthfoo
#define foopulseobjecthfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/once.c b/src/pulsecore/once.c
index a358cf65..989741dc 100644
--- a/src/pulsecore/once.c
+++ b/src/pulsecore/once.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/once.h b/src/pulsecore/once.h
index c9fe6d0a..576d40fa 100644
--- a/src/pulsecore/once.h
+++ b/src/pulsecore/once.h
@@ -1,8 +1,6 @@
#ifndef foopulseoncehfoo
#define foopulseoncehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/packet.c b/src/pulsecore/packet.c
index 2706efea..cee468bd 100644
--- a/src/pulsecore/packet.c
+++ b/src/pulsecore/packet.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/packet.h b/src/pulsecore/packet.h
index bcac4a7f..5989b1fa 100644
--- a/src/pulsecore/packet.h
+++ b/src/pulsecore/packet.h
@@ -1,8 +1,6 @@
#ifndef foopackethfoo
#define foopackethfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/parseaddr.c b/src/pulsecore/parseaddr.c
index 149c9e00..f2b6b2cf 100644
--- a/src/pulsecore/parseaddr.c
+++ b/src/pulsecore/parseaddr.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/parseaddr.h b/src/pulsecore/parseaddr.h
index fd7cad3b..5fbcb9a7 100644
--- a/src/pulsecore/parseaddr.h
+++ b/src/pulsecore/parseaddr.h
@@ -1,8 +1,6 @@
#ifndef fooparseaddrhfoo
#define fooparseaddrhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c
index bdd7cde1..e6a6ae4d 100644
--- a/src/pulsecore/pdispatch.c
+++ b/src/pulsecore/pdispatch.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h
index de0aa3ec..5c31d80e 100644
--- a/src/pulsecore/pdispatch.h
+++ b/src/pulsecore/pdispatch.h
@@ -1,8 +1,6 @@
#ifndef foopdispatchhfoo
#define foopdispatchhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c
index 2ff132bb..addb17cc 100644
--- a/src/pulsecore/pid.c
+++ b/src/pulsecore/pid.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -140,8 +138,51 @@ fail:
return -1;
}
+static int proc_name_ours(pid_t pid, const char *procname) {
+#ifdef __linux__
+ char bn[PATH_MAX];
+ FILE *f;
+
+ pa_snprintf(bn, sizeof(bn), "/proc/%lu/stat", (unsigned long) pid);
+
+ if (!(f = fopen(bn, "r"))) {
+ pa_log_info("Failed to open %s: %s", bn, pa_cstrerror(errno));
+ return -1;
+ } else {
+ char *expected;
+ pa_bool_t good;
+ char stored[64];
+
+ if (!(fgets(stored, sizeof(stored), f))) {
+ pa_log_info("Failed to read from %s: %s", bn, feof(f) ? "EOF" : pa_cstrerror(errno));
+ fclose(f);
+ return -1;
+ }
+
+ fclose(f);
+
+ expected = pa_sprintf_malloc("%lu (%s)", (unsigned long) pid, procname);
+ good = pa_startswith(stored, expected);
+ pa_xfree(expected);
+
+#if !defined(__OPTIMIZE__)
+ if (!good) {
+ /* libtool likes to rename our binary names ... */
+ expected = pa_sprintf_malloc("%lu (lt-%s)", (unsigned long) pid, procname);
+ good = pa_startswith(stored, expected);
+ pa_xfree(expected);
+ }
+#endif
+
+ return !!good;
+ }
+#endif
+
+ return 1;
+}
+
/* Create a new PID file for the current process. */
-int pa_pid_file_create(void) {
+int pa_pid_file_create(const char *procname) {
int fd = -1;
int ret = -1;
char t[20];
@@ -153,7 +194,8 @@ int pa_pid_file_create(void) {
HANDLE process;
#endif
- fn = pa_runtime_path("pid");
+ if (!(fn = pa_runtime_path("pid")))
+ goto fail;
if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
goto fail;
@@ -161,14 +203,24 @@ int pa_pid_file_create(void) {
if ((pid = read_pid(fn, fd)) == (pid_t) -1)
pa_log_warn("Corrupt PID file, overwriting.");
else if (pid > 0) {
+
#ifdef OS_IS_WIN32
if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
CloseHandle(process);
#else
if (kill(pid, 0) >= 0 || errno != ESRCH) {
#endif
- pa_log("Daemon already running.");
- goto fail;
+ int ours = 1;
+
+ if (procname)
+ if ((ours = proc_name_ours(pid, procname)) < 0)
+ goto fail;
+
+ if (ours) {
+ pa_log("Daemon already running.");
+ ret = 1;
+ goto fail;
+ }
}
pa_log_warn("Stale PID file, overwriting.");
@@ -212,7 +264,8 @@ int pa_pid_file_remove(void) {
int ret = -1;
pid_t pid;
- fn = pa_runtime_path("pid");
+ if (!(fn = pa_runtime_path("pid")))
+ goto fail;
if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
@@ -234,7 +287,7 @@ int pa_pid_file_remove(void) {
#ifdef OS_IS_WIN32
pa_lock_fd(fd, 0);
- close(fd);
+ pa_close(fd);
fd = -1;
#endif
@@ -265,8 +318,8 @@ fail:
* exists and the PID therein too. Returns 0 on succcess, -1
* otherwise. If pid is non-NULL and a running daemon was found,
* return its PID therein */
-int pa_pid_file_check_running(pid_t *pid, const char *binary_name) {
- return pa_pid_file_kill(0, pid, binary_name);
+int pa_pid_file_check_running(pid_t *pid, const char *procname) {
+ return pa_pid_file_kill(0, pid, procname);
}
#ifndef OS_IS_WIN32
@@ -274,7 +327,7 @@ int pa_pid_file_check_running(pid_t *pid, const char *binary_name) {
/* Kill a current running daemon. Return non-zero on success, -1
* otherwise. If successful *pid contains the PID of the daemon
* process. */
-int pa_pid_file_kill(int sig, pid_t *pid, const char *binary_name) {
+int pa_pid_file_kill(int sig, pid_t *pid, const char *procname) {
int fd = -1;
char *fn;
int ret = -1;
@@ -282,10 +335,12 @@ int pa_pid_file_kill(int sig, pid_t *pid, const char *binary_name) {
#ifdef __linux__
char *e = NULL;
#endif
+
if (!pid)
pid = &_pid;
- fn = pa_runtime_path("pid");
+ if (!(fn = pa_runtime_path("pid")))
+ goto fail;
if ((fd = open_pid_file(fn, O_RDONLY)) < 0)
goto fail;
@@ -293,22 +348,15 @@ int pa_pid_file_kill(int sig, pid_t *pid, const char *binary_name) {
if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
goto fail;
-#ifdef __linux__
- if (binary_name) {
- pa_snprintf(fn, sizeof(fn), "/proc/%lu/exe", (unsigned long) pid);
+ if (procname) {
+ int ours;
- if ((e = pa_readlink(fn))) {
- char *f = pa_path_get_filename(e);
- if (strcmp(f, binary_name)
-#if !defined(__OPTIMIZE__)
- /* libtool likes to rename our binary names ... */
- && !(pa_startswith(f, "lt-") && strcmp(f+3, binary_name) == 0)
-#endif
- )
- goto fail;
- }
+ if ((ours = proc_name_ours(*pid, procname)) < 0)
+ goto fail;
+
+ if (!ours)
+ goto fail;
}
-#endif
ret = kill(*pid, sig);
diff --git a/src/pulsecore/pid.h b/src/pulsecore/pid.h
index 1d6de7b5..3c8a9de3 100644
--- a/src/pulsecore/pid.h
+++ b/src/pulsecore/pid.h
@@ -1,8 +1,6 @@
#ifndef foopidhfoo
#define foopidhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -24,9 +22,9 @@
USA.
***/
-int pa_pid_file_create(void);
+int pa_pid_file_create(const char *procname);
int pa_pid_file_remove(void);
-int pa_pid_file_check_running(pid_t *pid, const char *binary_name);
-int pa_pid_file_kill(int sig, pid_t *pid, const char *binary_name);
+int pa_pid_file_check_running(pid_t *pid, const char *procname);
+int pa_pid_file_kill(int sig, pid_t *pid, const char *procname);
#endif
diff --git a/src/pulsecore/pipe.c b/src/pulsecore/pipe.c
index e614c9c6..93d78a22 100644
--- a/src/pulsecore/pipe.c
+++ b/src/pulsecore/pipe.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/pipe.h b/src/pulsecore/pipe.h
index e013a2e7..9a7e62c8 100644
--- a/src/pulsecore/pipe.h
+++ b/src/pulsecore/pipe.h
@@ -1,8 +1,6 @@
#ifndef foopipehfoo
#define foopipehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 2688f923..8b3e79b9 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -138,6 +136,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
return -1;
}
+ chunk->length = PA_MIN(chunk->length, nbytes);
pa_memblockq_drop(u->memblockq, chunk->length);
return 0;
diff --git a/src/pulsecore/play-memblockq.h b/src/pulsecore/play-memblockq.h
index 9ecf7700..1a42867b 100644
--- a/src/pulsecore/play-memblockq.h
+++ b/src/pulsecore/play-memblockq.h
@@ -1,8 +1,6 @@
#ifndef fooplaymemblockqhfoo
#define fooplaymemblockqhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index 67a92138..0dd48251 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/play-memchunk.h b/src/pulsecore/play-memchunk.h
index f7c9d178..c312ae82 100644
--- a/src/pulsecore/play-memchunk.h
+++ b/src/pulsecore/play-memchunk.h
@@ -1,8 +1,6 @@
#ifndef fooplaychunkhfoo
#define fooplaychunkhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/poll.c b/src/pulsecore/poll.c
index 288f7dfb..88ac21e4 100644
--- a/src/pulsecore/poll.c
+++ b/src/pulsecore/poll.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/poll.h b/src/pulsecore/poll.h
index 6be6069b..86c37a08 100644
--- a/src/pulsecore/poll.h
+++ b/src/pulsecore/poll.h
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/proplist-util.c b/src/pulsecore/proplist-util.c
new file mode 100644
index 00000000..6005775e
--- /dev/null
+++ b/src/pulsecore/proplist-util.c
@@ -0,0 +1,118 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2008 Lennart Poettering
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <locale.h>
+
+#include <pulse/proplist.h>
+#include <pulse/utf8.h>
+#include <pulse/xmalloc.h>
+#include <pulse/util.h>
+
+#include <pulsecore/core-util.h>
+
+#include "proplist-util.h"
+
+void pa_init_proplist(pa_proplist *p) {
+ int a, b;
+#ifndef HAVE_DECL_ENVIRON
+ extern char **environ;
+#endif
+ char **e;
+
+ pa_assert(p);
+
+ for (e = environ; *e; e++) {
+
+ if (pa_startswith(*e, "PULSE_PROP_")) {
+ size_t kl = strcspn(*e+11, "=");
+ char *k;
+
+ if ((*e)[11+kl] != '=')
+ continue;
+
+ if (!pa_utf8_valid(*e+11+kl+1))
+ continue;
+
+ k = pa_xstrndup(*e+11, kl);
+
+ if (pa_proplist_contains(p, k)) {
+ pa_xfree(k);
+ continue;
+ }
+
+ pa_proplist_sets(p, k, *e+11+kl+1);
+ pa_xfree(k);
+ }
+ }
+
+ if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_ID)) {
+ char t[32];
+ pa_snprintf(t, sizeof(t), "%lu", (unsigned long) getpid());
+ pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_ID, t);
+ }
+
+ if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_USER)) {
+ char t[64];
+ if (pa_get_user_name(t, sizeof(t))) {
+ char *c = pa_utf8_filter(t);
+ pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_USER, c);
+ pa_xfree(c);
+ }
+ }
+
+ if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_HOST)) {
+ char t[64];
+ if (pa_get_host_name(t, sizeof(t))) {
+ char *c = pa_utf8_filter(t);
+ pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_HOST, c);
+ pa_xfree(c);
+ }
+ }
+
+ a = pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY);
+ b = pa_proplist_contains(p, PA_PROP_APPLICATION_NAME);
+
+ if (!a || !b) {
+ char t[PATH_MAX];
+ if (pa_get_binary_name(t, sizeof(t))) {
+ char *c = pa_utf8_filter(t);
+
+ if (!a)
+ pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_BINARY, c);
+ if (!b)
+ pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, c);
+
+ pa_xfree(c);
+ }
+ }
+
+ if (!pa_proplist_contains(p, PA_PROP_APPLICATION_LANGUAGE)) {
+ const char *l;
+
+ if ((l = setlocale(LC_MESSAGES, NULL)))
+ pa_proplist_sets(p, PA_PROP_APPLICATION_LANGUAGE, l);
+ }
+}
diff --git a/src/pulsecore/proplist-util.h b/src/pulsecore/proplist-util.h
new file mode 100644
index 00000000..c6bdc103
--- /dev/null
+++ b/src/pulsecore/proplist-util.h
@@ -0,0 +1,29 @@
+#ifndef fooproplistutilutilhfoo
+#define fooproplistutilutilhfoo
+
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2008 Lennart Poettering
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <pulse/proplist.h>
+
+void pa_init_proplist(pa_proplist *p);
+
+#endif
diff --git a/src/pulsecore/props.c b/src/pulsecore/props.c
index cbf748df..23d432ec 100644
--- a/src/pulsecore/props.c
+++ b/src/pulsecore/props.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/props.h b/src/pulsecore/props.h
index 880325f6..95db229b 100644
--- a/src/pulsecore/props.h
+++ b/src/pulsecore/props.h
@@ -1,8 +1,6 @@
#ifndef foopropshfoo
#define foopropshfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/protocol-cli.c b/src/pulsecore/protocol-cli.c
index 2f797a14..30cb475d 100644
--- a/src/pulsecore/protocol-cli.c
+++ b/src/pulsecore/protocol-cli.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/protocol-cli.h b/src/pulsecore/protocol-cli.h
index 3870def3..8922ac62 100644
--- a/src/pulsecore/protocol-cli.h
+++ b/src/pulsecore/protocol-cli.h
@@ -1,8 +1,6 @@
#ifndef fooprotocolclihfoo
#define fooprotocolclihfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 492dc9fa..db1b4305 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -1042,7 +1040,7 @@ static int do_read(connection *c) {
}
if (!c->playback.current_memblock) {
- pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, 0));
+ pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, (size_t) -1));
c->playback.memblock_index = 0;
space = pa_memblock_get_length(c->playback.current_memblock);
@@ -1275,6 +1273,8 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
} else {
size_t m;
+ chunk->length = PA_MIN(length, chunk->length);
+
c->playback.underrun = FALSE;
pa_memblockq_drop(c->input_memblockq, chunk->length);
diff --git a/src/pulsecore/protocol-esound.h b/src/pulsecore/protocol-esound.h
index 868ef5d2..0c9447d3 100644
--- a/src/pulsecore/protocol-esound.h
+++ b/src/pulsecore/protocol-esound.h
@@ -1,8 +1,6 @@
#ifndef fooprotocolesoundhfoo
#define fooprotocolesoundhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c
index bc2e9af6..03990435 100644
--- a/src/pulsecore/protocol-http.c
+++ b/src/pulsecore/protocol-http.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/protocol-http.h b/src/pulsecore/protocol-http.h
index cf952476..e3372335 100644
--- a/src/pulsecore/protocol-http.h
+++ b/src/pulsecore/protocol-http.h
@@ -1,8 +1,6 @@
#ifndef fooprotocolhttphfoo
#define fooprotocolhttphfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 2adcdfc7..923a5665 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -132,7 +130,8 @@ typedef struct upload_stream {
struct connection {
pa_msgobject parent;
- pa_bool_t authorized;
+ pa_bool_t authorized:1;
+ pa_bool_t is_local:1;
uint32_t version;
pa_protocol_native *protocol;
pa_client *client;
@@ -485,7 +484,7 @@ static void fix_record_buffer_attr_pre(record_stream *s, pa_bool_t adjust_latenc
pa_usec_t fragsize_usec;
/* So, the user asked us to adjust the latency according to
- * the what the source can provide. Half the latency will be
+ * 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. */
@@ -499,7 +498,8 @@ static void fix_record_buffer_attr_pre(record_stream *s, pa_bool_t adjust_latenc
fragsize_usec = s->source_latency;
*fragsize = pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
- }
+ } else
+ s->source_latency = 0;
}
static void fix_record_buffer_attr_post(record_stream *s, uint32_t *maxlength, uint32_t *fragsize) {
@@ -533,7 +533,8 @@ static record_stream* record_stream_new(
uint32_t *fragsize,
pa_source_output_flags_t flags,
pa_proplist *p,
- pa_bool_t adjust_latency) {
+ pa_bool_t adjust_latency,
+ pa_sink_input *direct_on_input) {
record_stream *s;
pa_source_output *source_output;
@@ -553,6 +554,7 @@ static record_stream* record_stream_new(
data.module = c->protocol->module;
data.client = c->client;
data.source = source;
+ data.direct_on_input = direct_on_input;
pa_source_output_new_data_set_sample_spec(&data, ss);
pa_source_output_new_data_set_channel_map(&data, map);
if (peak_detect)
@@ -597,6 +599,11 @@ static record_stream* record_stream_new(
pa_idxset_put(c->record_streams, s, &s->index);
+ pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
+ ((double) pa_bytes_to_usec(s->fragment_size, &source_output->sample_spec) + (double) s->source_latency) / PA_USEC_PER_MSEC,
+ (double) pa_bytes_to_usec(s->fragment_size, &source_output->sample_spec) / PA_USEC_PER_MSEC,
+ (double) s->source_latency / PA_USEC_PER_MSEC);
+
pa_source_output_put(s->source_output);
return s;
}
@@ -803,7 +810,7 @@ static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_la
if (*tlength <= *minreq)
*tlength = *minreq*2 + frame_size;
- if (*prebuf <= 0)
+ if (*prebuf <= 0 || *prebuf > *tlength)
*prebuf = *tlength;
}
@@ -1281,7 +1288,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
if (pa_memblockq_peek(s->memblockq, chunk) < 0) {
-/* pa_log("UNDERRUN: %lu", pa_memblockq_get_length(s->memblockq)); */
+/* pa_log("UNDERRUN: %lu", (unsigned long) pa_memblockq_get_length(s->memblockq)); */
if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
s->drain_request = FALSE;
@@ -1298,6 +1305,8 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
/* pa_log("NOTUNDERRUN %lu", (unsigned long) chunk->length); */
+ chunk->length = PA_MIN(nbytes, chunk->length);
+
if (i->thread_info.underrun_for > 0)
pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_STARTED, NULL, 0, NULL, NULL);
@@ -1750,7 +1759,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
record_stream *s;
uint32_t maxlength, fragment_size;
uint32_t source_index;
- const char *name, *source_name;
+ const char *name = NULL, *source_name;
pa_sample_spec ss;
pa_channel_map map;
pa_tagstruct *reply;
@@ -1768,6 +1777,8 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
peak_detect = FALSE;
pa_source_output_flags_t flags = 0;
pa_proplist *p;
+ uint32_t direct_on_input_idx = PA_INVALID_INDEX;
+ pa_sink_input *direct_on_input = NULL;
connection_assert_ref(c);
pa_assert(t);
@@ -1816,7 +1827,8 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
if (pa_tagstruct_get_boolean(t, &peak_detect) < 0 ||
pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
- pa_tagstruct_get_proplist(t, p) < 0) {
+ pa_tagstruct_get_proplist(t, p) < 0 ||
+ pa_tagstruct_getu32(t, &direct_on_input_idx) < 0) {
protocol_error(c);
pa_proplist_free(p);
return;
@@ -1846,6 +1858,15 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
}
}
+ if (direct_on_input_idx != PA_INVALID_INDEX) {
+
+ if (!(direct_on_input = pa_idxset_get_by_index(c->protocol->core->sink_inputs, direct_on_input_idx))) {
+ pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
+ pa_proplist_free(p);
+ return;
+ }
+ }
+
flags =
(corked ? PA_SOURCE_OUTPUT_START_CORKED : 0) |
(no_remap ? PA_SOURCE_OUTPUT_NO_REMAP : 0) |
@@ -1856,7 +1877,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
(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);
+ s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency, direct_on_input);
pa_proplist_free(p);
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
@@ -1914,7 +1935,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
connection *c = CONNECTION(userdata);
const void*cookie;
pa_tagstruct *reply;
- char tmp[16];
+ pa_bool_t shm_on_remote, do_shm;
connection_assert_ref(c);
pa_assert(t);
@@ -1932,8 +1953,17 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
return;
}
- pa_snprintf(tmp, sizeof(tmp), "%u", c->version);
- pa_proplist_sets(c->client->proplist, "native-protocol.version", tmp);
+ /* Starting with protocol version 13 the MSB of the version tag
+ reflects if shm is available for this connection or
+ not. */
+ if (c->version >= 13) {
+ shm_on_remote = !!(c->version & 0x80000000U);
+ c->version &= 0x7FFFFFFFU;
+ }
+
+ pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
+
+ pa_proplist_setf(c->client->proplist, "native-protocol.version", "%u", c->version);
if (!c->authorized) {
pa_bool_t success = FALSE;
@@ -1964,16 +1994,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
(unsigned long) creds->uid,
(unsigned long) creds->gid,
- success);
-
- if (c->version >= 10 &&
- pa_mempool_is_shared(c->protocol->core->mempool) &&
- creds->uid == getuid()) {
-
- pa_pstream_enable_shm(c->pstream, TRUE);
- pa_log_info("Enabled SHM for new connection");
- }
-
+ (int) success);
}
#endif
@@ -1993,8 +2014,32 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
}
}
+ /* Enable shared memory support if possible */
+ do_shm =
+ pa_mempool_is_shared(c->protocol->core->mempool) &&
+ c->is_local;
+
+ pa_log_debug("SHM possible: %s", pa_yes_no(do_shm));
+
+ if (do_shm)
+ if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
+ do_shm = FALSE;
+
+ if (do_shm) {
+ /* Only enable SHM if both sides are owned by the same
+ * user. This is a security measure because otherwise data
+ * private to the user might leak. */
+
+ const pa_creds *creds;
+ if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
+ do_shm = FALSE;
+ }
+
+ pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
+ pa_pstream_enable_shm(c->pstream, do_shm);
+
reply = reply_new(tag);
- pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION);
+ pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0));
#ifdef HAVE_CREDS
{
@@ -2229,7 +2274,7 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
connection_assert_ref(c);
pa_assert(t);
- if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
+ if (pa_tagstruct_gets(t, &name) < 0 ||
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
pa_tagstruct_get_channel_map(t, &map) < 0 ||
pa_tagstruct_getu32(t, &length) < 0) {
@@ -2244,9 +2289,6 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
- if (c->version < 13)
- CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
-
p = pa_proplist_new();
if (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) {
@@ -2257,6 +2299,11 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
if (c->version < 13)
pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
+ else if (!name)
+ if (!(name = pa_proplist_gets(p, PA_PROP_EVENT_ID)))
+ name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME);
+
+ CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
s = upload_stream_new(c, &ss, &map, name, length, p);
pa_proplist_free(p);
@@ -2488,6 +2535,7 @@ static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_input *s) {
pa_sample_spec fixed_ss;
+ pa_usec_t sink_latency;
pa_assert(t);
pa_sink_input_assert_ref(s);
@@ -2502,8 +2550,8 @@ static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_in
pa_tagstruct_put_sample_spec(t, &fixed_ss);
pa_tagstruct_put_channel_map(t, &s->channel_map);
pa_tagstruct_put_cvolume(t, &s->volume);
- pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s));
- pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink));
+ pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency));
+ pa_tagstruct_put_usec(t, sink_latency);
pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
pa_tagstruct_puts(t, s->driver);
if (c->version >= 11)
@@ -2514,6 +2562,7 @@ static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_in
static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source_output *s) {
pa_sample_spec fixed_ss;
+ pa_usec_t source_latency;
pa_assert(t);
pa_source_output_assert_ref(s);
@@ -2527,8 +2576,8 @@ static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sour
pa_tagstruct_putu32(t, s->source->index);
pa_tagstruct_put_sample_spec(t, &fixed_ss);
pa_tagstruct_put_channel_map(t, &s->channel_map);
- pa_tagstruct_put_usec(t, pa_source_output_get_latency(s));
- pa_tagstruct_put_usec(t, pa_source_get_latency(s->source));
+ pa_tagstruct_put_usec(t, pa_source_output_get_latency(s, &source_latency));
+ pa_tagstruct_put_usec(t, source_latency);
pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
pa_tagstruct_puts(t, s->driver);
@@ -2542,12 +2591,15 @@ static void scache_fill_tagstruct(connection *c, pa_tagstruct *t, pa_scache_entr
pa_assert(t);
pa_assert(e);
- fixup_sample_spec(c, &fixed_ss, &e->sample_spec);
+ if (e->memchunk.memblock)
+ fixup_sample_spec(c, &fixed_ss, &e->sample_spec);
+ else
+ memset(&fixed_ss, 0, sizeof(fixed_ss));
pa_tagstruct_putu32(t, e->index);
pa_tagstruct_puts(t, e->name);
pa_tagstruct_put_cvolume(t, &e->volume);
- pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec));
+ pa_tagstruct_put_usec(t, e->memchunk.memblock ? pa_bytes_to_usec(e->memchunk.length, &e->sample_spec) : 0);
pa_tagstruct_put_sample_spec(t, &fixed_ss);
pa_tagstruct_put_channel_map(t, &e->channel_map);
pa_tagstruct_putu32(t, e->memchunk.length);
@@ -3885,7 +3937,6 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
connection *c;
char cname[256], pname[128];
- pa_assert(s);
pa_assert(io);
pa_assert(p);
@@ -3914,6 +3965,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
} else
c->auth_timeout_event = NULL;
+ c->is_local = pa_iochannel_socket_is_local(io);
c->version = 8;
c->protocol = p;
pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
@@ -3946,7 +3998,6 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
#ifdef HAVE_CREDS
if (pa_iochannel_creds_supported(io))
pa_iochannel_creds_enable(io);
-
#endif
}
@@ -4005,7 +4056,7 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo
pa_log("auth-group-enabled= expects a boolean argument.");
return NULL;
}
- p->auth_group = a ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", c->is_system_instance ? PA_ACCESS_GROUP : NULL)) : NULL;
+ p->auth_group = a ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP : NULL)) : NULL;
if (p->auth_group)
pa_log_info("Allowing access to group '%s'.", p->auth_group);
diff --git a/src/pulsecore/protocol-native.h b/src/pulsecore/protocol-native.h
index bf05f937..a52fa8cf 100644
--- a/src/pulsecore/protocol-native.h
+++ b/src/pulsecore/protocol-native.h
@@ -1,8 +1,6 @@
#ifndef fooprotocolnativehfoo
#define fooprotocolnativehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index cbe48440..020a281d 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -374,6 +372,8 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
} else {
size_t m;
+ chunk->length = PA_MIN(length, chunk->length);
+
c->playback.underrun = FALSE;
pa_memblockq_drop(c->input_memblockq, chunk->length);
diff --git a/src/pulsecore/protocol-simple.h b/src/pulsecore/protocol-simple.h
index 3b02c88e..e1b3143b 100644
--- a/src/pulsecore/protocol-simple.h
+++ b/src/pulsecore/protocol-simple.h
@@ -1,8 +1,6 @@
#ifndef fooprotocolsimplehfoo
#define fooprotocolsimplehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c
index a6932158..f84f486a 100644
--- a/src/pulsecore/pstream-util.c
+++ b/src/pulsecore/pstream-util.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/pstream-util.h b/src/pulsecore/pstream-util.h
index 67759f2a..ae0d79c3 100644
--- a/src/pulsecore/pstream-util.h
+++ b/src/pulsecore/pstream-util.h
@@ -1,8 +1,6 @@
#ifndef foopstreamutilhfoo
#define foopstreamutilhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index 5004d67f..e26ca473 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h
index 00b37b71..a528b25c 100644
--- a/src/pulsecore/pstream.h
+++ b/src/pulsecore/pstream.h
@@ -1,8 +1,6 @@
#ifndef foopstreamhfoo
#define foopstreamhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/queue.c b/src/pulsecore/queue.c
index 9b6a37f0..08fd1426 100644
--- a/src/pulsecore/queue.c
+++ b/src/pulsecore/queue.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/queue.h b/src/pulsecore/queue.h
index cd767364..b09216cf 100644
--- a/src/pulsecore/queue.h
+++ b/src/pulsecore/queue.h
@@ -1,8 +1,6 @@
#ifndef fooqueuehfoo
#define fooqueuehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/random.c b/src/pulsecore/random.c
index 87afebfa..5deac37b 100644
--- a/src/pulsecore/random.c
+++ b/src/pulsecore/random.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -64,7 +62,11 @@ static int random_proper(void *ret_data, size_t length) {
while (*device) {
ret = 0;
- if ((fd = open(*device, O_RDONLY)) >= 0) {
+ if ((fd = open(*device, O_RDONLY
+#ifdef O_NOCTTY
+ | O_NOCTTY
+#endif
+ )) >= 0) {
if ((r = pa_loop_read(fd, ret_data, length, NULL)) < 0 || (size_t) r != length)
ret = -1;
diff --git a/src/pulsecore/random.h b/src/pulsecore/random.h
index 01b7d746..36d7f9df 100644
--- a/src/pulsecore/random.h
+++ b/src/pulsecore/random.h
@@ -1,8 +1,6 @@
#ifndef foorandomhfoo
#define foorandomhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h
index f0885fb4..291f4504 100644
--- a/src/pulsecore/refcnt.h
+++ b/src/pulsecore/refcnt.h
@@ -1,8 +1,6 @@
#ifndef foopulserefcnthfoo
#define foopulserefcnthfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index d645639c..00dc794c 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -1457,10 +1455,10 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
r->peaks.max_i[c] = n;
}
- for (c = 0; c < r->o_ss.channels; c++, d++)
+ for (c = 0; c < r->o_ss.channels; c++, d++) {
*d = r->peaks.max_i[c];
-
- memset(r->peaks.max_i, 0, sizeof(r->peaks.max_i));
+ r->peaks.max_i[c] = 0;
+ }
} else {
unsigned i, c;
float *s = (float*) ((uint8_t*) src + fz * j);
@@ -1476,11 +1474,13 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
r->peaks.max_f[c] = n;
}
- for (c = 0; c < r->o_ss.channels; c++, d++)
+ for (c = 0; c < r->o_ss.channels; c++, d++) {
*d = r->peaks.max_f[c];
-
- memset(r->peaks.max_f, 0, sizeof(r->peaks.max_f));
+ r->peaks.max_f[c] = 0;
+ }
}
+
+ start = j+1;
}
pa_memblock_release(input->memblock);
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index 8534f5b5..5e302a9b 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -1,8 +1,6 @@
#ifndef fooresamplerhfoo
#define fooresamplerhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
index e74e5243..f33de830 100644
--- a/src/pulsecore/rtclock.c
+++ b/src/pulsecore/rtclock.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h
index f68ad761..705de48f 100644
--- a/src/pulsecore/rtclock.h
+++ b/src/pulsecore/rtclock.h
@@ -1,8 +1,6 @@
#ifndef foopulsertclockhfoo
#define foopulsertclockhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 64fa42ad..a67a5516 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -514,6 +512,9 @@ void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, pa_usec_t usec) {
void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
pa_assert(p);
+ /* Scheduling a timeout for more than an hour is very very suspicious */
+ pa_assert(usec <= PA_USEC_PER_SEC*60ULL*60ULL);
+
pa_rtclock_get(&p->next_elapse);
pa_timeval_add(&p->next_elapse, usec);
p->timer_enabled = TRUE;
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index 16dadbc3..08776ef0 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -1,8 +1,6 @@
#ifndef foopulsertpollhfoo
#define foopulsertpollhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c
index bfc49c88..4df217c3 100644
--- a/src/pulsecore/rtsig.c
+++ b/src/pulsecore/rtsig.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/rtsig.h b/src/pulsecore/rtsig.h
index 7830d272..e414122d 100644
--- a/src/pulsecore/rtsig.h
+++ b/src/pulsecore/rtsig.h
@@ -1,8 +1,6 @@
#ifndef foopulsertsighfoo
#define foopulsertsighfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index a8028296..b42b79d1 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 59b4c632..cef70750 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -1,8 +1,6 @@
#ifndef foosampleutilhfoo
#define foosampleutilhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sconv-s16be.c b/src/pulsecore/sconv-s16be.c
index 638beb2e..e7e1449a 100644
--- a/src/pulsecore/sconv-s16be.c
+++ b/src/pulsecore/sconv-s16be.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sconv-s16be.h b/src/pulsecore/sconv-s16be.h
index 454c9508..60580815 100644
--- a/src/pulsecore/sconv-s16be.h
+++ b/src/pulsecore/sconv-s16be.h
@@ -1,8 +1,6 @@
#ifndef foosconv_s16befoo
#define foosconv_s16befoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c
index 90e9b6d2..41670f27 100644
--- a/src/pulsecore/sconv-s16le.c
+++ b/src/pulsecore/sconv-s16le.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sconv-s16le.h b/src/pulsecore/sconv-s16le.h
index 4165f8a2..8d4c87c3 100644
--- a/src/pulsecore/sconv-s16le.h
+++ b/src/pulsecore/sconv-s16le.h
@@ -1,8 +1,6 @@
#ifndef foosconv_s16lefoo
#define foosconv_s16lefoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c
index ebd74586..581e4681 100644
--- a/src/pulsecore/sconv.c
+++ b/src/pulsecore/sconv.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sconv.h b/src/pulsecore/sconv.h
index 901f50a3..59710369 100644
--- a/src/pulsecore/sconv.h
+++ b/src/pulsecore/sconv.h
@@ -1,8 +1,6 @@
#ifndef foosconvhfoo
#define foosconvhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/semaphore-posix.c b/src/pulsecore/semaphore-posix.c
index 750c2afc..7c9f859d 100644
--- a/src/pulsecore/semaphore-posix.c
+++ b/src/pulsecore/semaphore-posix.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/semaphore-win32.c b/src/pulsecore/semaphore-win32.c
index f6576348..41e0b8d4 100644
--- a/src/pulsecore/semaphore-win32.c
+++ b/src/pulsecore/semaphore-win32.c
@@ -1,5 +1,3 @@
-/* $Id: mutex-win32.c 1426 2007-02-13 15:35:19Z ossman $ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/semaphore.h b/src/pulsecore/semaphore.h
index c394e0f2..850ae817 100644
--- a/src/pulsecore/semaphore.h
+++ b/src/pulsecore/semaphore.h
@@ -1,8 +1,6 @@
#ifndef foopulsesemaphorehfoo
#define foopulsesemaphorehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index a6843819..298bf716 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/shm.h b/src/pulsecore/shm.h
index 60bc355f..c2adbd07 100644
--- a/src/pulsecore/shm.h
+++ b/src/pulsecore/shm.h
@@ -1,8 +1,6 @@
#ifndef foopulseshmhfoo
#define foopulseshmhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/shmasyncq.c b/src/pulsecore/shmasyncq.c
index 7af2985c..eac56adb 100644
--- a/src/pulsecore/shmasyncq.c
+++ b/src/pulsecore/shmasyncq.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/shmasyncq.h b/src/pulsecore/shmasyncq.h
index ca35ffd2..9845c391 100644
--- a/src/pulsecore/shmasyncq.h
+++ b/src/pulsecore/shmasyncq.h
@@ -1,8 +1,6 @@
#ifndef foopulseshmasyncqhfoo
#define foopulseshmasyncqhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index d51ff810..43e7bb21 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -44,7 +42,6 @@
#define MEMBLOCKQ_MAXLENGTH (32*1024*1024)
#define CONVERT_BUFFER_LENGTH (PA_PAGE_SIZE)
-#define MOVE_BUFFER_LENGTH (PA_PAGE_SIZE*256)
static PA_DEFINE_CHECK_TYPE(pa_sink_input, pa_msgobject);
@@ -94,12 +91,16 @@ void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
pa_proplist_free(data->proplist);
}
+/* Called from main context */
static void reset_callbacks(pa_sink_input *i) {
pa_assert(i);
i->pop = NULL;
i->process_rewind = NULL;
i->update_max_rewind = NULL;
+ i->update_max_request = NULL;
+ i->update_sink_requested_latency = NULL;
+ i->update_sink_latency_range = NULL;
i->attach = NULL;
i->detach = NULL;
i->suspend = NULL;
@@ -109,6 +110,7 @@ static void reset_callbacks(pa_sink_input *i) {
i->state_change = NULL;
}
+/* Called from main context */
pa_sink_input* pa_sink_input_new(
pa_core *core,
pa_sink_input_new_data *data,
@@ -127,7 +129,7 @@ pa_sink_input* pa_sink_input_new(
pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
if (!data->sink)
- data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK, 1);
+ data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK, TRUE);
pa_return_null_if_fail(data->sink);
pa_return_null_if_fail(pa_sink_get_state(data->sink) != PA_SINK_UNLINKED);
@@ -237,6 +239,8 @@ pa_sink_input* pa_sink_input_new(
} else
i->sync_next = i->sync_prev = NULL;
+ i->direct_outputs = pa_idxset_new(NULL, NULL);
+
reset_callbacks(i);
i->userdata = NULL;
@@ -252,6 +256,7 @@ pa_sink_input* pa_sink_input_new(
i->thread_info.rewrite_flush = FALSE;
i->thread_info.underrun_for = (uint64_t) -1;
i->thread_info.playing_for = 0;
+ i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
i->thread_info.render_memblockq = pa_memblockq_new(
0,
@@ -278,6 +283,7 @@ pa_sink_input* pa_sink_input_new(
return i;
}
+/* Called from main context */
static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
pa_assert(i);
@@ -289,6 +295,7 @@ static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
pa_sink_update_status(i->sink);
}
+/* Called from main context */
static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
pa_sink_input *ssync;
pa_assert(i);
@@ -299,8 +306,7 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
if (i->state == state)
return 0;
- if (pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0)
- return -1;
+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) == 0);
update_n_corked(i, state);
i->state = state;
@@ -314,14 +320,23 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
ssync->state = state;
}
- if (state != PA_SINK_INPUT_UNLINKED)
+ if (state != PA_SINK_INPUT_UNLINKED) {
pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], i);
+ for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev)
+ pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
+
+ for (ssync = i->sync_next; ssync; ssync = ssync->sync_next)
+ pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], ssync);
+ }
+
return 0;
}
+/* Called from main context */
void pa_sink_input_unlink(pa_sink_input *i) {
pa_bool_t linked;
+ pa_source_output *o, *p = NULL;
pa_assert(i);
/* See pa_sink_unlink() for a couple of comments how this function
@@ -345,12 +360,18 @@ void pa_sink_input_unlink(pa_sink_input *i) {
if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
pa_sink_input_unref(i);
+ while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
+ pa_assert(o != p);
+ pa_source_output_kill(o);
+ p = o;
+ }
+
update_n_corked(i, PA_SINK_INPUT_UNLINKED);
i->state = PA_SINK_INPUT_UNLINKED;
if (linked)
if (i->sink->asyncmsgq)
- pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL) == 0);
reset_callbacks(i);
@@ -363,6 +384,7 @@ void pa_sink_input_unlink(pa_sink_input *i) {
pa_sink_input_unref(i);
}
+/* Called from main context */
static void sink_input_free(pa_object *o) {
pa_sink_input* i = PA_SINK_INPUT(o);
@@ -385,17 +407,27 @@ static void sink_input_free(pa_object *o) {
if (i->proplist)
pa_proplist_free(i->proplist);
+ if (i->direct_outputs)
+ pa_idxset_free(i->direct_outputs, NULL, NULL);
+
+ if (i->thread_info.direct_outputs)
+ pa_hashmap_free(i->thread_info.direct_outputs, NULL, NULL);
+
pa_xfree(i->driver);
pa_xfree(i);
}
+/* Called from main context */
void pa_sink_input_put(pa_sink_input *i) {
pa_sink_input_state_t state;
pa_sink_input_assert_ref(i);
pa_assert(i->state == PA_SINK_INPUT_INIT);
+
+ /* The following fields must be initialized properly */
pa_assert(i->pop);
pa_assert(i->process_rewind);
+ pa_assert(i->kill);
i->thread_info.volume = i->volume;
i->thread_info.muted = i->muted;
@@ -405,33 +437,36 @@ void pa_sink_input_put(pa_sink_input *i) {
update_n_corked(i, state);
i->state = state;
- pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL) == 0);
pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
}
+/* Called from main context */
void pa_sink_input_kill(pa_sink_input*i) {
pa_sink_input_assert_ref(i);
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
- if (i->kill)
- i->kill(i);
+ i->kill(i);
}
-pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
- pa_usec_t r = 0;
+/* Called from main context */
+pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
+ pa_usec_t r[2] = { 0, 0 };
pa_sink_input_assert_ref(i);
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
- if (pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, &r, 0, NULL) < 0)
- r = 0;
+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, r, 0, NULL) == 0);
if (i->get_latency)
- r += i->get_latency(i);
+ r[0] += i->get_latency(i);
+
+ if (sink_latency)
+ *sink_latency = r[1];
- return r;
+ return r[0];
}
/* Called from thread context */
@@ -684,42 +719,54 @@ void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes /* in the
i->update_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
}
+/* Called from thread context */
+void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */) {
+ pa_sink_input_assert_ref(i);
+ pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
+ pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
+
+ if (i->update_max_request)
+ i->update_max_request(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
+}
+
+/* Called from thread context */
static pa_usec_t fixup_latency(pa_sink *s, pa_usec_t usec) {
pa_sink_assert_ref(s);
if (usec == (pa_usec_t) -1)
return usec;
- if (s->max_latency > 0 && usec > s->max_latency)
- usec = s->max_latency;
+ if (s->thread_info.max_latency > 0 && usec > s->thread_info.max_latency)
+ usec = s->thread_info.max_latency;
- if (s->min_latency > 0 && usec < s->min_latency)
- usec = s->min_latency;
+ if (s->thread_info.min_latency > 0 && usec < s->thread_info.min_latency)
+ usec = s->thread_info.min_latency;
return usec;
}
+/* Called from thread context */
pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
pa_sink_input_assert_ref(i);
usec = fixup_latency(i->sink, usec);
-
i->thread_info.requested_sink_latency = usec;
pa_sink_invalidate_requested_latency(i->sink);
return usec;
}
+/* Called from main context */
pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
pa_sink_input_assert_ref(i);
- usec = fixup_latency(i->sink, usec);
-
if (PA_SINK_INPUT_IS_LINKED(i->state))
- pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
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;
}
@@ -727,13 +774,14 @@ pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec)
return usec;
}
+/* Called from main context */
pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
pa_usec_t usec = 0;
pa_sink_input_assert_ref(i);
if (PA_SINK_INPUT_IS_LINKED(i->state))
- pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
else
/* If this sink input is not realized yet, we have to touch
* the thread info data directly */
@@ -742,19 +790,22 @@ pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
return usec;
}
+/* Called from main context */
void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
pa_sink_input_assert_ref(i);
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
+ pa_assert(volume);
if (pa_cvolume_equal(&i->volume, volume))
return;
i->volume = *volume;
- pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree);
+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, &i->volume, 0, NULL) == 0);
pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
}
+/* Called from main context */
const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) {
pa_sink_input_assert_ref(i);
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
@@ -762,6 +813,7 @@ const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) {
return &i->volume;
}
+/* Called from main context */
void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute) {
pa_assert(i);
pa_sink_input_assert_ref(i);
@@ -776,13 +828,15 @@ void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute) {
pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
}
-int pa_sink_input_get_mute(pa_sink_input *i) {
+/* Called from main context */
+pa_bool_t pa_sink_input_get_mute(pa_sink_input *i) {
pa_sink_input_assert_ref(i);
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
- return !!i->muted;
+ return i->muted;
}
+/* Called from main context */
void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) {
pa_sink_input_assert_ref(i);
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
@@ -790,6 +844,7 @@ void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) {
sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
}
+/* Called from main context */
int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
pa_sink_input_assert_ref(i);
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
@@ -806,6 +861,7 @@ int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
return 0;
}
+/* Called from main context */
void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
const char *old;
pa_sink_input_assert_ref(i);
@@ -829,16 +885,19 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
}
}
+/* Called from main context */
pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
pa_sink_input_assert_ref(i);
return i->resample_method;
}
+/* Called from main context */
int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) {
pa_resampler *new_resampler;
pa_sink *origin;
pa_sink_input_move_hook_data hook_data;
+ pa_source_output *o, *p = NULL;
pa_sink_input_assert_ref(i);
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
@@ -862,6 +921,13 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) {
return -1;
}
+ /* Kill directly connected outputs */
+ while ((o = pa_idxset_first(i->direct_outputs, NULL))) {
+ pa_assert(o != p);
+ pa_source_output_kill(o);
+ p = o;
+ }
+
if (i->thread_info.resampler &&
pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) &&
pa_channel_map_equal(&origin->channel_map, &dest->channel_map))
@@ -893,7 +959,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) {
hook_data.destination = dest;
pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], &hook_data);
- pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
pa_idxset_remove_by_data(origin->inputs, i, NULL);
pa_idxset_put(dest->inputs, i, NULL);
@@ -927,7 +993,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) {
pa_sink_update_status(origin);
pa_sink_update_status(dest);
- pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);
if (i->moved)
i->moved(i);
@@ -942,6 +1008,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) {
return 0;
}
+/* Called from IO thread context */
void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
pa_sink_input_assert_ref(i);
@@ -971,14 +1038,13 @@ void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state
i->thread_info.state = state;
}
-/* Called from thread context */
+/* Called from thread context, except when it is not. */
int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
pa_sink_input *i = PA_SINK_INPUT(o);
-
pa_sink_input_assert_ref(i);
- pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
switch (code) {
+
case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
i->thread_info.volume = *((pa_cvolume*) userdata);
pa_sink_input_request_rewind(i, 0, TRUE, FALSE);
@@ -991,8 +1057,13 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
pa_usec_t *r = userdata;
+ pa_usec_t sink_usec = 0;
+
+ r[0] += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
+
+ if (i->sink->parent.process_msg(PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_GET_LATENCY, &sink_usec, 0, NULL) >= 0)
+ r[1] += sink_usec;
- *r += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
return 0;
}
@@ -1017,10 +1088,12 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
return 0;
}
- case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY:
+ case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY: {
+ pa_usec_t *usec = userdata;
- pa_sink_input_set_requested_latency_within_thread(i, (pa_usec_t) offset);
+ *usec = pa_sink_input_set_requested_latency_within_thread(i, *usec);
return 0;
+ }
case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
pa_usec_t *r = userdata;
@@ -1033,6 +1106,7 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
return -1;
}
+/* Called from main thread */
pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
pa_sink_input_assert_ref(i);
@@ -1052,6 +1126,7 @@ pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
return TRUE;
}
+/* Called from IO context */
void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sample spec */, pa_bool_t rewrite, pa_bool_t flush) {
size_t lbq;
@@ -1111,6 +1186,7 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam
pa_sink_request_rewind(i->sink, nbytes - lbq);
}
+/* Called from main context */
pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
pa_sink_input_assert_ref(i);
pa_assert(ret);
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 5f146122..c07a7404 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -1,8 +1,6 @@
#ifndef foopulsesinkinputhfoo
#define foopulsesinkinputhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -73,13 +71,19 @@ struct pa_sink_input {
pa_sink_input_state_t state;
pa_sink_input_flags_t flags;
- pa_proplist *proplist;
char *driver; /* may be NULL */
+ pa_proplist *proplist;
+
pa_module *module; /* may be NULL */
pa_client *client; /* may be NULL */
pa_sink *sink;
+ /* A sink input may be connected to multiple source outputs
+ * directly, so that they don't get mixed data of the entire
+ * source. */
+ pa_idxset *direct_outputs;
+
pa_sample_spec sample_spec;
pa_channel_map channel_map;
@@ -109,6 +113,18 @@ struct pa_sink_input {
* changes. Called from IO context. */
void (*update_max_rewind) (pa_sink_input *i, size_t nbytes); /* may be NULL */
+ /* Called whenever the maxiumum request size of the sink
+ * changes. Called from IO context. */
+ void (*update_max_request) (pa_sink_input *i, size_t nbytes); /* may be NULL */
+
+ /* Called whenever the configured latency of the sink
+ * changes. Called from IO context. */
+ void (*update_sink_requested_latency) (pa_sink_input *i); /* may be NULL */
+
+ /* Called whenver the latency range of the sink changes. Called
+ * from IO context. */
+ void (*update_sink_latency_range) (pa_sink_input *i); /* may be NULL */
+
/* If non-NULL this function is called when the input is first
* connected to a sink or when the rtpoll/asyncmsgq fields
* change. You usually don't need to implement this function
@@ -130,12 +146,12 @@ struct pa_sink_input {
/* Supposed to unlink and destroy this stream. Called from main
* context. */
- void (*kill) (pa_sink_input *i); /* may be NULL */
+ void (*kill) (pa_sink_input *i); /* may NOT be NULL */
/* Return the current latency (i.e. length of bufferd audio) of
- this stream. Called from main context. If NULL a
- PA_SINK_INPUT_MESSAGE_GET_LATENCY message is sent to the IO thread
- instead. */
+ this stream. Called from main context. This is added to what the
+ PA_SINK_INPUT_MESSAGE_GET_LATENCY message sent to the IO thread
+ returns */
pa_usec_t (*get_latency) (pa_sink_input *i); /* may be NULL */
/* If non_NULL this function is called from thread context if the
@@ -166,6 +182,8 @@ struct pa_sink_input {
/* The requested latency for the sink */
pa_usec_t requested_sink_latency;
+
+ pa_hashmap *direct_outputs;
} thread_info;
void *userdata;
@@ -253,12 +271,12 @@ int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate);
/* External code may request disconnection with this function */
void pa_sink_input_kill(pa_sink_input*i);
-pa_usec_t pa_sink_input_get_latency(pa_sink_input *i);
+pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency);
void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume);
const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i);
void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute);
-int pa_sink_input_get_mute(pa_sink_input *i);
+pa_bool_t pa_sink_input_get_mute(pa_sink_input *i);
pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i);
@@ -274,6 +292,7 @@ int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_c
void pa_sink_input_drop(pa_sink_input *i, size_t length);
void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */);
void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */);
+void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */);
void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state);
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 31c3cfc8..edb023b2 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -105,6 +103,7 @@ void pa_sink_new_data_done(pa_sink_new_data *data) {
pa_proplist_free(data->proplist);
}
+/* Called from main context */
static void reset_callbacks(pa_sink *s) {
pa_assert(s);
@@ -117,6 +116,7 @@ static void reset_callbacks(pa_sink *s) {
s->update_requested_latency = NULL;
}
+/* Called from main context */
pa_sink* pa_sink_new(
pa_core *core,
pa_sink_new_data *data,
@@ -192,7 +192,7 @@ pa_sink* pa_sink_new(
s->volume = data->volume;
s->muted = data->muted;
- s->refresh_volume = s->refresh_mute = FALSE;
+ s->refresh_volume = s->refresh_muted = FALSE;
reset_callbacks(s);
s->userdata = NULL;
@@ -207,17 +207,17 @@ pa_sink* pa_sink_new(
&s->sample_spec,
0);
- s->min_latency = DEFAULT_MIN_LATENCY;
- s->max_latency = s->min_latency;
-
s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
- s->thread_info.soft_volume = s->volume;
- s->thread_info.soft_muted = s->muted;
+ pa_cvolume_reset(&s->thread_info.soft_volume, s->sample_spec.channels);
+ s->thread_info.soft_muted = FALSE;
s->thread_info.state = s->state;
s->thread_info.rewind_nbytes = 0;
s->thread_info.max_rewind = 0;
+ s->thread_info.max_request = 0;
s->thread_info.requested_latency_valid = FALSE;
s->thread_info.requested_latency = 0;
+ s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
+ s->thread_info.max_latency = 0;
pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
@@ -249,11 +249,14 @@ pa_sink* pa_sink_new(
}
s->monitor_source->monitor_of = s;
+
+ pa_source_set_latency_range(s->monitor_source, s->thread_info.min_latency, s->thread_info.max_latency);
pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
return s;
}
+/* Called from main context */
static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
int ret;
pa_bool_t suspend_change;
@@ -272,8 +275,7 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
return -1;
if (s->asyncmsgq)
- if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0)
- return -1;
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) == 0);
s->state = state;
@@ -294,18 +296,25 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
return 0;
}
+/* Called from main context */
void pa_sink_put(pa_sink* s) {
pa_sink_assert_ref(s);
pa_assert(s->state == PA_SINK_INIT);
+
+ /* The following fields must be initialized properly when calling _put() */
pa_assert(s->asyncmsgq);
pa_assert(s->rtpoll);
+ pa_assert(!s->thread_info.min_latency || !s->thread_info.max_latency ||
+ s->thread_info.min_latency <= s->thread_info.max_latency);
- pa_assert(!s->min_latency || !s->max_latency || s->min_latency <= s->max_latency);
-
- if (!(s->flags & PA_SINK_HW_VOLUME_CTRL))
+ if (!(s->flags & PA_SINK_HW_VOLUME_CTRL)) {
s->flags |= PA_SINK_DECIBEL_VOLUME;
+ s->thread_info.soft_volume = s->volume;
+ s->thread_info.soft_muted = s->muted;
+ }
+
pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
pa_source_put(s->monitor_source);
@@ -314,6 +323,7 @@ void pa_sink_put(pa_sink* s) {
pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s);
}
+/* Called from main context */
void pa_sink_unlink(pa_sink* s) {
pa_bool_t linked;
pa_sink_input *i, *j = NULL;
@@ -359,6 +369,7 @@ void pa_sink_unlink(pa_sink* s) {
}
}
+/* Called from main context */
static void sink_free(pa_object *o) {
pa_sink *s = PA_SINK(o);
pa_sink_input *i;
@@ -395,6 +406,7 @@ static void sink_free(pa_object *o) {
pa_xfree(s);
}
+/* Called from main context */
void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
pa_sink_assert_ref(s);
@@ -404,6 +416,7 @@ void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
pa_source_set_asyncmsgq(s->monitor_source, q);
}
+/* Called from main context */
void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
pa_sink_assert_ref(s);
@@ -412,6 +425,7 @@ void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
pa_source_set_rtpoll(s->monitor_source, p);
}
+/* Called from main context */
int pa_sink_update_status(pa_sink*s) {
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->state));
@@ -422,6 +436,7 @@ int pa_sink_update_status(pa_sink*s) {
return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
}
+/* Called from main context */
int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->state));
@@ -432,11 +447,12 @@ int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
}
+/* Called from IO thread context */
void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
pa_sink_input *i;
void *state = NULL;
pa_sink_assert_ref(s);
- pa_assert(PA_SINK_IS_LINKED(s->state));
+ pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
/* Make sure the sink code already reset the counter! */
pa_assert(s->thread_info.rewind_nbytes <= 0);
@@ -451,11 +467,11 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
pa_sink_input_process_rewind(i, nbytes);
}
- if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
+ if (s->monitor_source && PA_SOURCE_IS_OPENED(s->monitor_source->thread_info.state))
pa_source_process_rewind(s->monitor_source, nbytes);
-
}
+/* Called from IO thread context */
static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxinfo) {
pa_sink_input *i;
unsigned n = 0;
@@ -495,24 +511,26 @@ static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, uns
return n;
}
-static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length) {
+/* Called from IO thread context */
+static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *result) {
pa_sink_input *i;
void *state = NULL;
unsigned p = 0;
unsigned n_unreffed = 0;
pa_sink_assert_ref(s);
+ pa_assert(result);
+ pa_assert(result->memblock);
+ pa_assert(result->length > 0);
/* We optimize for the case where the order of the inputs has not changed */
while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
unsigned j;
- pa_mix_info* m;
+ pa_mix_info* m = NULL;
pa_sink_input_assert_ref(i);
- m = NULL;
-
/* Let's try to find the matching entry info the pa_mix_info array */
for (j = 0; j < n; j ++) {
@@ -527,14 +545,47 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length
}
/* Drop read data */
- pa_sink_input_drop(i, length);
+ pa_sink_input_drop(i, result->length);
+
+ if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source))) {
+
+ if (pa_hashmap_size(i->thread_info.direct_outputs) > 0) {
+ void *ostate = NULL;
+ pa_source_output *o;
+ pa_memchunk c;
+
+ if (m && m->chunk.memblock) {
+ c = m->chunk;
+ pa_memblock_ref(c.memblock);
+ pa_assert(result->length <= c.length);
+ c.length = result->length;
+
+ pa_memchunk_make_writable(&c, 0);
+ pa_volume_memchunk(&c, &s->sample_spec, &m->volume);
+ } else {
+ c = s->silence;
+ pa_memblock_ref(c.memblock);
+ pa_assert(result->length <= c.length);
+ c.length = result->length;
+ }
+
+ while ((o = pa_hashmap_iterate(i->thread_info.direct_outputs, &ostate, NULL))) {
+ pa_source_output_assert_ref(o);
+ pa_assert(o->direct_on_input == i);
+ pa_source_post_direct(s->monitor_source, o, &c);
+ }
+
+ pa_memblock_unref(c.memblock);
+ }
+ }
if (m) {
- pa_sink_input_unref(m->userdata);
- m->userdata = NULL;
if (m->chunk.memblock)
pa_memblock_unref(m->chunk.memblock);
- pa_memchunk_reset(&m->chunk);
+ pa_memchunk_reset(&m->chunk);
+
+ pa_sink_input_unref(m->userdata);
+ m->userdata = NULL;
n_unreffed += 1;
}
@@ -551,8 +602,12 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length
pa_memblock_unref(info->chunk.memblock);
}
}
+
+ if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
+ pa_source_post(s->monitor_source, result);
}
+/* Called from IO thread context */
void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
pa_mix_info info[MAX_MIX_CHANNELS];
unsigned n;
@@ -621,14 +676,12 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
}
if (s->thread_info.state == PA_SINK_RUNNING)
- inputs_drop(s, info, n, result->length);
-
- if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
- pa_source_post(s->monitor_source, result);
+ inputs_drop(s, info, n, result);
pa_sink_unref(s);
}
+/* Called from IO thread context */
void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
pa_mix_info info[MAX_MIX_CHANNELS];
unsigned n;
@@ -650,6 +703,8 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
if (length > block_size_max)
length = pa_frame_align(block_size_max, &s->sample_spec);
+ pa_assert(length > 0);
+
n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, &length, info, MAX_MIX_CHANNELS) : 0;
if (n == 0) {
@@ -673,8 +728,8 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
vchunk = info[0].chunk;
pa_memblock_ref(vchunk.memblock);
- if (vchunk.length > target->length)
- vchunk.length = target->length;
+ if (vchunk.length > length)
+ vchunk.length = length;
if (!pa_cvolume_is_norm(&volume)) {
pa_memchunk_make_writable(&vchunk, 0);
@@ -700,14 +755,12 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
}
if (s->thread_info.state == PA_SINK_RUNNING)
- inputs_drop(s, info, n, target->length);
-
- if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
- pa_source_post(s->monitor_source, target);
+ inputs_drop(s, info, n, target);
pa_sink_unref(s);
}
+/* Called from IO thread context */
void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
pa_memchunk chunk;
size_t l, d;
@@ -739,6 +792,7 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
pa_sink_unref(s);
}
+/* Called from IO thread context */
void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_OPENED(s->thread_info.state));
@@ -757,6 +811,7 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
pa_sink_render_into_full(s, result);
}
+/* Called from main thread */
pa_usec_t pa_sink_get_latency(pa_sink *s) {
pa_usec_t usec = 0;
@@ -768,14 +823,14 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
if (!PA_SINK_IS_OPENED(s->state))
return 0;
- if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
- return 0;
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
return usec;
}
+/* Called from main thread */
void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) {
- int changed;
+ pa_bool_t changed;
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->state));
@@ -788,34 +843,36 @@ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) {
s->set_volume = NULL;
if (!s->set_volume)
- pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree);
+ pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, volume, 0, NULL);
if (changed)
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
+/* Called from main thread */
const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
- struct pa_cvolume old_volume;
-
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->state));
- old_volume = s->volume;
+ if (s->refresh_volume) {
+ struct pa_cvolume old_volume = s->volume;
- if (s->get_volume && s->get_volume(s) < 0)
- s->get_volume = NULL;
+ if (s->get_volume && s->get_volume(s) < 0)
+ s->get_volume = NULL;
- if (!s->get_volume && s->refresh_volume)
- pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, &s->volume, 0, NULL);
+ if (!s->get_volume)
+ pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, &s->volume, 0, NULL);
- if (!pa_cvolume_equal(&old_volume, &s->volume))
- pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ if (!pa_cvolume_equal(&old_volume, &s->volume))
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ }
return &s->volume;
}
+/* Called from main thread */
void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) {
- int changed;
+ pa_bool_t changed;
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->state));
@@ -833,26 +890,29 @@ void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) {
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
+/* Called from main thread */
pa_bool_t pa_sink_get_mute(pa_sink *s) {
- pa_bool_t old_muted;
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->state));
- old_muted = s->muted;
+ if (s->refresh_muted) {
+ pa_bool_t old_muted = s->muted;
- if (s->get_mute && s->get_mute(s) < 0)
- s->get_mute = NULL;
+ if (s->get_mute && s->get_mute(s) < 0)
+ s->get_mute = NULL;
- if (!s->get_mute && s->refresh_mute)
- pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &s->muted, 0, NULL);
+ if (!s->get_mute)
+ pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &s->muted, 0, NULL);
- if (old_muted != s->muted)
- pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ if (old_muted != s->muted)
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ }
return s->muted;
}
+/* Called from main thread */
void pa_sink_set_description(pa_sink *s, const char *description) {
const char *old;
pa_sink_assert_ref(s);
@@ -884,6 +944,7 @@ void pa_sink_set_description(pa_sink *s, const char *description) {
}
}
+/* Called from main thread */
unsigned pa_sink_linked_by(pa_sink *s) {
unsigned ret;
@@ -901,6 +962,7 @@ unsigned pa_sink_linked_by(pa_sink *s) {
return ret;
}
+/* Called from main thread */
unsigned pa_sink_used_by(pa_sink *s) {
unsigned ret;
@@ -916,10 +978,10 @@ unsigned pa_sink_used_by(pa_sink *s) {
return ret - s->n_corked;
}
+/* Called from IO thread, except when it is not */
int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
pa_sink *s = PA_SINK(o);
pa_sink_assert_ref(s);
- pa_assert(s->thread_info.state != PA_SINK_UNLINKED);
switch ((pa_sink_message_t) code) {
@@ -957,6 +1019,7 @@ 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);
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);
@@ -975,11 +1038,11 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
* sink input handling a few lines down at
* PA_SINK_MESSAGE_PREPAPRE_MOVE, too. */
- pa_sink_input_set_state_within_thread(i, i->state);
-
if (i->detach)
i->detach(i);
+ pa_sink_input_set_state_within_thread(i, i->state);
+
pa_assert(i->thread_info.attached);
i->thread_info.attached = FALSE;
@@ -1072,6 +1135,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
i->attach(i);
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);
@@ -1122,9 +1186,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
case PA_SINK_MESSAGE_DETACH:
- /* We're detaching all our input streams so that the
- * asyncmsgq and rtpoll fields can be changed without
- * problems */
+ /* Detach all streams */
pa_sink_detach_within_thread(s);
return 0;
@@ -1138,9 +1200,40 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
pa_usec_t *usec = userdata;
*usec = pa_sink_get_requested_latency_within_thread(s);
+
+ if (*usec == (pa_usec_t) -1)
+ *usec = s->thread_info.max_latency;
+
+ return 0;
+ }
+
+ case PA_SINK_MESSAGE_SET_LATENCY_RANGE: {
+ pa_usec_t *r = userdata;
+
+ pa_sink_update_latency_range(s, r[0], r[1]);
+
+ return 0;
+ }
+
+ case PA_SINK_MESSAGE_GET_LATENCY_RANGE: {
+ pa_usec_t *r = userdata;
+
+ r[0] = s->thread_info.min_latency;
+ r[1] = s->thread_info.max_latency;
+
return 0;
}
+ case PA_SINK_MESSAGE_GET_MAX_REWIND:
+
+ *((size_t*) userdata) = s->thread_info.max_rewind;
+ return 0;
+
+ case PA_SINK_MESSAGE_GET_MAX_REQUEST:
+
+ *((size_t*) userdata) = s->thread_info.max_request;
+ return 0;
+
case PA_SINK_MESSAGE_GET_LATENCY:
case PA_SINK_MESSAGE_MAX:
;
@@ -1149,6 +1242,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
return -1;
}
+/* Called from main thread */
int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) {
pa_sink *sink;
uint32_t idx;
@@ -1162,20 +1256,23 @@ int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) {
return ret;
}
+/* Called from main thread */
void pa_sink_detach(pa_sink *s) {
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->state));
- pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL) == 0);
}
+/* Called from main thread */
void pa_sink_attach(pa_sink *s) {
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->state));
- pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
}
+/* Called from IO thread */
void pa_sink_detach_within_thread(pa_sink *s) {
pa_sink_input *i;
void *state = NULL;
@@ -1191,6 +1288,7 @@ void pa_sink_detach_within_thread(pa_sink *s) {
pa_source_detach_within_thread(s->monitor_source);
}
+/* Called from IO thread */
void pa_sink_attach_within_thread(pa_sink *s) {
pa_sink_input *i;
void *state = NULL;
@@ -1206,6 +1304,7 @@ void pa_sink_attach_within_thread(pa_sink *s) {
pa_source_attach_within_thread(s->monitor_source);
}
+/* Called from IO thread */
void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
@@ -1224,10 +1323,12 @@ void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
s->request_rewind(s);
}
+/* Called from IO thread */
pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
pa_usec_t result = (pa_usec_t) -1;
pa_sink_input *i;
void *state = NULL;
+ pa_usec_t monitor_latency;
pa_sink_assert_ref(s);
@@ -1240,12 +1341,18 @@ pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
(result == (pa_usec_t) -1 || result > i->thread_info.requested_sink_latency))
result = i->thread_info.requested_sink_latency;
+ monitor_latency = pa_source_get_requested_latency_within_thread(s->monitor_source);
+
+ if (monitor_latency != (pa_usec_t) -1 &&
+ (result == (pa_usec_t) -1 || result > monitor_latency))
+ result = monitor_latency;
+
if (result != (pa_usec_t) -1) {
- if (s->max_latency > 0 && result > s->max_latency)
- result = s->max_latency;
+ if (s->thread_info.max_latency > 0 && result > s->thread_info.max_latency)
+ result = s->thread_info.max_latency;
- if (s->min_latency > 0 && result < s->min_latency)
- result = s->min_latency;
+ if (s->thread_info.min_latency > 0 && result < s->thread_info.min_latency)
+ result = s->thread_info.min_latency;
}
s->thread_info.requested_latency = result;
@@ -1254,6 +1361,7 @@ pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
return result;
}
+/* Called from main thread */
pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
pa_usec_t usec = 0;
@@ -1263,15 +1371,11 @@ pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
if (!PA_SINK_IS_OPENED(s->state))
return 0;
- if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) < 0)
- return 0;
-
- if (usec == (pa_usec_t) -1)
- usec = s->max_latency;
-
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
return usec;
}
+/* Called from IO thread */
void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
pa_sink_input *i;
void *state = NULL;
@@ -1283,20 +1387,145 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
s->thread_info.max_rewind = max_rewind;
- while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
- pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
+ if (PA_SINK_IS_LINKED(s->thread_info.state)) {
+ while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
+ pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
+ }
if (s->monitor_source)
pa_source_set_max_rewind(s->monitor_source, s->thread_info.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);
+
+ if (max_request == s->thread_info.max_request)
+ return;
+
+ s->thread_info.max_request = max_request;
+
+ if (PA_SINK_IS_LINKED(s->thread_info.state)) {
+ while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
+ pa_sink_input_update_max_request(i, s->thread_info.max_request);
+ }
+}
+
+/* Called from IO thread */
void pa_sink_invalidate_requested_latency(pa_sink *s) {
+ pa_sink_input *i;
+ void *state = NULL;
pa_sink_assert_ref(s);
- pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
s->thread_info.requested_latency_valid = FALSE;
if (s->update_requested_latency)
s->update_requested_latency(s);
+
+ while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
+ if (i->update_sink_requested_latency)
+ i->update_sink_requested_latency(i);
+}
+
+/* Called from main thread */
+void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
+ pa_sink_assert_ref(s);
+
+ /* min_latency == 0: no limit
+ * min_latency == (size_t) -1: default limit
+ * min_latency anything else: specified limit
+ *
+ * Similar for max_latency */
+
+ if (min_latency == (pa_usec_t) -1)
+ min_latency = DEFAULT_MIN_LATENCY;
+
+ if (max_latency == (pa_usec_t) -1)
+ max_latency = min_latency;
+
+ pa_assert(!min_latency || !max_latency ||
+ min_latency <= max_latency);
+
+ if (PA_SINK_IS_LINKED(s->state)) {
+ pa_usec_t r[2];
+
+ r[0] = min_latency;
+ r[1] = max_latency;
+
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
+ } else {
+ s->thread_info.min_latency = min_latency;
+ s->thread_info.max_latency = max_latency;
+
+ s->monitor_source->thread_info.min_latency = min_latency;
+ s->monitor_source->thread_info.max_latency = max_latency;
+
+ s->thread_info.requested_latency_valid = s->monitor_source->thread_info.requested_latency_valid = FALSE;
+ }
+}
+
+/* Called from main thread */
+void pa_sink_get_latency_range(pa_sink *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
+ pa_sink_assert_ref(s);
+ pa_assert(min_latency);
+ pa_assert(max_latency);
+
+ if (PA_SINK_IS_LINKED(s->state)) {
+ pa_usec_t r[2] = { 0, 0 };
+
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
+
+ *min_latency = r[0];
+ *max_latency = r[1];
+ } else {
+ *min_latency = s->thread_info.min_latency;
+ *max_latency = s->thread_info.max_latency;
+ }
+}
+
+/* Called from IO thread */
+void pa_sink_update_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
+ pa_sink_input *i;
+ void *state = NULL;
+
+ pa_sink_assert_ref(s);
+
+ s->thread_info.min_latency = min_latency;
+ s->thread_info.max_latency = max_latency;
+
+ while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
+ if (i->update_sink_latency_range)
+ i->update_sink_latency_range(i);
+
+ pa_sink_invalidate_requested_latency(s);
+
+ pa_source_update_latency_range(s->monitor_source, min_latency, max_latency);
+}
+
+size_t pa_sink_get_max_rewind(pa_sink *s) {
+ size_t r;
+ pa_sink_assert_ref(s);
+
+ if (!PA_SINK_IS_LINKED(s->state))
+ return s->thread_info.max_rewind;
+
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
+
+ return r;
+}
+
+size_t pa_sink_get_max_request(pa_sink *s) {
+ size_t r;
+ pa_sink_assert_ref(s);
+
+ if (!PA_SINK_IS_LINKED(s->state))
+ return s->thread_info.max_request;
+
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MAX_REQUEST, &r, 0, NULL) == 0);
+
+ return r;
}
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index f297c8f1..b73944e8 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -1,8 +1,6 @@
#ifndef foopulsesinkhfoo
#define foopulsesinkhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -82,17 +80,15 @@ struct pa_sink {
pa_cvolume volume;
pa_bool_t muted;
- pa_bool_t refresh_volume;
- pa_bool_t refresh_mute;
+
+ pa_bool_t refresh_volume:1;
+ pa_bool_t refresh_muted:1;
pa_asyncmsgq *asyncmsgq;
pa_rtpoll *rtpoll;
pa_memchunk silence;
- pa_usec_t min_latency; /* we won't go below this latency */
- pa_usec_t max_latency; /* An upper limit for the latencies */
-
/* Called when the main loop requests a state change. Called from
* main loop context. If returns -1 the state change will be
* inhibited */
@@ -100,8 +96,9 @@ struct pa_sink {
/* Callled when the volume is queried. Called from main loop
* context. If this is NULL a PA_SINK_MESSAGE_GET_VOLUME message
- * will be sent to the IO thread instead. */
- int (*get_volume)(pa_sink *s); /* may be null */
+ * will be sent to the IO thread instead. If refresh_volume is
+ * FALSE neither this function is called nor a message is sent. */
+ int (*get_volume)(pa_sink *s); /* may be NULL */
/* Called when the volume shall be changed. Called from main loop
* context. If this is NULL a PA_SINK_MESSAGE_SET_VOLUME message
@@ -110,7 +107,8 @@ struct pa_sink {
/* Called when the mute setting is queried. Called from main loop
* context. If this is NULL a PA_SINK_MESSAGE_GET_MUTE message
- * will be sent to the IO thread instead. */
+ * will be sent to the IO thread instead. If refresh_mute is
+ * FALSE neither this function is called nor a message is sent.*/
int (*get_mute)(pa_sink *s); /* dito */
/* Called when the mute setting shall be changed. Called from main
@@ -132,17 +130,24 @@ struct pa_sink {
pa_sink_state_t state;
pa_hashmap *inputs;
pa_cvolume soft_volume;
- pa_bool_t soft_muted;
+ pa_bool_t soft_muted:1;
- pa_bool_t requested_latency_valid;
+ pa_bool_t requested_latency_valid:1;
pa_usec_t requested_latency;
- /* The number of bytes we need keep around to be able to satisfy
- * every DMA buffer rewrite */
+ /* The number of bytes streams need to keep around as history to
+ * be able to satisfy every DMA buffer rewrite */
size_t max_rewind;
+ /* The number of bytes streams need to keep around to satisfy
+ * every DMA write request */
+ size_t max_request;
+
/* Maximum of what clients requested to rewind in this cycle */
size_t rewind_nbytes;
+
+ pa_usec_t min_latency; /* we won't go below this latency */
+ pa_usec_t max_latency; /* An upper limit for the latencies */
} thread_info;
void *userdata;
@@ -165,6 +170,10 @@ typedef enum pa_sink_message {
PA_SINK_MESSAGE_FINISH_MOVE,
PA_SINK_MESSAGE_ATTACH,
PA_SINK_MESSAGE_DETACH,
+ PA_SINK_MESSAGE_SET_LATENCY_RANGE,
+ PA_SINK_MESSAGE_GET_LATENCY_RANGE,
+ PA_SINK_MESSAGE_GET_MAX_REWIND,
+ PA_SINK_MESSAGE_GET_MAX_REQUEST,
PA_SINK_MESSAGE_MAX
} pa_sink_message_t;
@@ -209,6 +218,8 @@ void pa_sink_set_description(pa_sink *s, const char *description);
void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q);
void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p);
+void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency);
+
void pa_sink_detach(pa_sink *s);
void pa_sink_attach(pa_sink *s);
@@ -217,6 +228,10 @@ void pa_sink_attach(pa_sink *s);
/* The returned value is supposed to be in the time domain of the sound card! */
pa_usec_t pa_sink_get_latency(pa_sink *s);
pa_usec_t pa_sink_get_requested_latency(pa_sink *s);
+void pa_sink_get_latency_range(pa_sink *s, pa_usec_t *min_latency, pa_usec_t *max_latency);
+
+size_t pa_sink_get_max_rewind(pa_sink *s);
+size_t pa_sink_get_max_request(pa_sink *s);
int pa_sink_update_status(pa_sink*s);
int pa_sink_suspend(pa_sink *s, pa_bool_t suspend);
@@ -248,6 +263,9 @@ void pa_sink_detach_within_thread(pa_sink *s);
pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s);
void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind);
+void pa_sink_set_max_request(pa_sink *s, size_t max_request);
+
+void pa_sink_update_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency);
/* To be called exclusively by sink input drivers, from IO context */
diff --git a/src/pulsecore/sioman.c b/src/pulsecore/sioman.c
index 8d4c6fa7..7e5b186c 100644
--- a/src/pulsecore/sioman.c
+++ b/src/pulsecore/sioman.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sioman.h b/src/pulsecore/sioman.h
index 49fffb34..d0cacc9b 100644
--- a/src/pulsecore/sioman.h
+++ b/src/pulsecore/sioman.h
@@ -1,8 +1,6 @@
#ifndef foosiomanhfoo
#define foosiomanhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c
index a99193b7..e69a63da 100644
--- a/src/pulsecore/socket-client.c
+++ b/src/pulsecore/socket-client.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -61,6 +59,7 @@
#include <pulsecore/core-error.h>
#include <pulsecore/socket-util.h>
#include <pulsecore/core-util.h>
+#include <pulsecore/socket-util.h>
#include <pulsecore/log.h>
#include <pulsecore/parseaddr.h>
#include <pulsecore/macro.h>
@@ -270,22 +269,7 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size
pa_assert(sa);
pa_assert(salen);
- switch (sa->sa_family) {
- case AF_UNIX:
- c->local = TRUE;
- break;
-
- case AF_INET:
- c->local = ((const struct sockaddr_in*) sa)->sin_addr.s_addr == INADDR_LOOPBACK;
- break;
-
- case AF_INET6:
- c->local = memcmp(&((const struct sockaddr_in6*) sa)->sin6_addr, &in6addr_loopback, sizeof(struct in6_addr)) == 0;
- break;
-
- default:
- c->local = FALSE;
- }
+ c->local = pa_socket_address_is_local(sa);
if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) {
pa_log("socket(): %s", pa_cstrerror(errno));
diff --git a/src/pulsecore/socket-client.h b/src/pulsecore/socket-client.h
index 41e8c3bd..9ceeaddc 100644
--- a/src/pulsecore/socket-client.h
+++ b/src/pulsecore/socket-client.h
@@ -1,8 +1,6 @@
#ifndef foosocketclienthfoo
#define foosocketclienthfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c
index 162a1aac..9885a02b 100644
--- a/src/pulsecore/socket-server.c
+++ b/src/pulsecore/socket-server.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -83,7 +81,7 @@ struct pa_socket_server {
char *filename;
char *tcpwrap_service;
- void (*on_connection)(pa_socket_server*s, pa_iochannel *io, void *userdata);
+ pa_socket_server_on_connection_cb_t on_connection;
void *userdata;
pa_io_event *io_event;
@@ -91,7 +89,7 @@ struct pa_socket_server {
enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX, SOCKET_SERVER_IPV6 } type;
};
-static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
+static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
pa_socket_server *s = userdata;
pa_iochannel *io;
int nfd;
@@ -195,9 +193,9 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file
pa_make_fd_cloexec(fd);
+ memset(&sa, 0, sizeof(sa));
sa.sun_family = AF_UNIX;
- strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1);
- sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
+ pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
pa_make_socket_low_delay(fd);
@@ -295,7 +293,7 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad
pa_socket_server *ss;
int fd = -1;
struct sockaddr_in6 sa;
- int on = 1;
+ int on;
pa_assert(m);
pa_assert(port > 0);
@@ -308,11 +306,13 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad
pa_make_fd_cloexec(fd);
#ifdef IPV6_V6ONLY
+ on = 1;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
pa_log("setsockopt(IPPROTO_IPV6, IPV6_V6ONLY): %s", pa_cstrerror(errno));
#endif
#ifdef SO_REUSEADDR
+ on = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
pa_log("setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", pa_cstrerror(errno));
#endif
@@ -426,7 +426,7 @@ void pa_socket_server_unref(pa_socket_server *s) {
socket_server_free(s);
}
-void pa_socket_server_set_callback(pa_socket_server*s, void (*on_connection)(pa_socket_server*s, pa_iochannel *io, void *userdata), void *userdata) {
+void pa_socket_server_set_callback(pa_socket_server*s, pa_socket_server_on_connection_cb_t on_connection, void *userdata) {
pa_assert(s);
pa_assert(PA_REFCNT_VALUE(s) >= 1);
@@ -507,7 +507,6 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
}
pa_snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port));
-
}
return c;
diff --git a/src/pulsecore/socket-server.h b/src/pulsecore/socket-server.h
index 777599e5..1edfb432 100644
--- a/src/pulsecore/socket-server.h
+++ b/src/pulsecore/socket-server.h
@@ -1,8 +1,6 @@
#ifndef foosocketserverhfoo
#define foosocketserverhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -47,7 +45,9 @@ pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const cha
void pa_socket_server_unref(pa_socket_server*s);
pa_socket_server* pa_socket_server_ref(pa_socket_server *s);
-void pa_socket_server_set_callback(pa_socket_server*s, void (*on_connection)(pa_socket_server*s, pa_iochannel *io, void *userdata), void *userdata);
+typedef void (*pa_socket_server_on_connection_cb_t)(pa_socket_server*s, pa_iochannel *io, void *userdata);
+
+void pa_socket_server_set_callback(pa_socket_server*s, pa_socket_server_on_connection_cb_t connection_cb, void *userdata);
char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l);
diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c
index 456accb8..f721f699 100644
--- a/src/pulsecore/socket-util.c
+++ b/src/pulsecore/socket-util.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -129,8 +127,8 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
return;
#endif
}
-
}
+
#ifndef OS_IS_WIN32
pa_snprintf(c, l, "Unknown network client");
return;
@@ -284,3 +282,40 @@ int pa_unix_socket_remove_stale(const char *fn) {
}
#endif /* HAVE_SYS_UN_H */
+
+
+pa_bool_t pa_socket_address_is_local(const struct sockaddr *sa) {
+ pa_assert(sa);
+
+ switch (sa->sa_family) {
+ case AF_UNIX:
+ return TRUE;
+
+ case AF_INET:
+ return ((const struct sockaddr_in*) sa)->sin_addr.s_addr == INADDR_LOOPBACK;
+
+ case AF_INET6:
+ return memcmp(&((const struct sockaddr_in6*) sa)->sin6_addr, &in6addr_loopback, sizeof(struct in6_addr)) == 0;
+
+ default:
+ return FALSE;
+ }
+}
+
+pa_bool_t pa_socket_is_local(int fd) {
+
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+#ifdef HAVE_SYS_UN_H
+ struct sockaddr_un un;
+#endif
+ } sa;
+ socklen_t sa_len = sizeof(sa);
+
+ if (getpeername(fd, &sa.sa, &sa_len) < 0)
+ return FALSE;
+
+ return pa_socket_address_is_local(&sa.sa);
+}
diff --git a/src/pulsecore/socket-util.h b/src/pulsecore/socket-util.h
index a0344c68..7a40285a 100644
--- a/src/pulsecore/socket-util.h
+++ b/src/pulsecore/socket-util.h
@@ -1,8 +1,6 @@
#ifndef foosocketutilhfoo
#define foosocketutilhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -26,6 +24,9 @@
***/
#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <pulsecore/macro.h>
void pa_socket_peer_to_string(int fd, char *c, size_t l);
@@ -39,4 +40,7 @@ int pa_socket_set_rcvbuf(int fd, size_t l);
int pa_unix_socket_is_stale(const char *fn);
int pa_unix_socket_remove_stale(const char *fn);
+pa_bool_t pa_socket_address_is_local(const struct sockaddr *sa);
+pa_bool_t pa_socket_is_local(int fd);
+
#endif
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index e209676f..8eedf830 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -35,6 +33,7 @@
#include <sndfile.h>
#include <pulse/xmalloc.h>
+#include <pulse/util.h>
#include <pulsecore/core-error.h>
#include <pulsecore/sink-input.h>
@@ -149,8 +148,6 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
if (!u->memblockq)
return -1;
- pa_log_debug("pop: %lu", (unsigned long) length);
-
for (;;) {
pa_memchunk tchunk;
size_t fs;
@@ -158,6 +155,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
sf_count_t n;
if (pa_memblockq_peek(u->memblockq, chunk) >= 0) {
+ chunk->length = PA_MIN(chunk->length, length);
pa_memblockq_drop(u->memblockq, chunk->length);
return 0;
}
@@ -194,11 +192,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
pa_memblock_unref(tchunk.memblock);
}
- pa_log_debug("peek fail");
-
if (pa_sink_input_safe_to_remove(i)) {
- pa_log_debug("completed to play");
-
pa_memblockq_free(u->memblockq);
u->memblockq = NULL;
@@ -216,6 +210,8 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
u = FILE_STREAM(i->userdata);
file_stream_assert_ref(u);
+ pa_log("backwards %lu", (unsigned long) nbytes);
+
if (!u->memblockq)
return;
@@ -330,7 +326,7 @@ int pa_play_file(
data.driver = __FILE__;
pa_sink_input_new_data_set_sample_spec(&data, &ss);
pa_sink_input_new_data_set_volume(&data, volume);
- pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, fname);
+ pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, pa_path_get_filename(fname));
pa_proplist_sets(data.proplist, PA_PROP_MEDIA_FILENAME, fname);
u->sink_input = pa_sink_input_new(sink->core, &data, 0);
diff --git a/src/pulsecore/sound-file-stream.h b/src/pulsecore/sound-file-stream.h
index 189e242d..4cc69146 100644
--- a/src/pulsecore/sound-file-stream.h
+++ b/src/pulsecore/sound-file-stream.h
@@ -1,8 +1,6 @@
#ifndef foosoundfilestreamhfoo
#define foosoundfilestreamhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c
index 3e6f683d..3183ede6 100644
--- a/src/pulsecore/sound-file.c
+++ b/src/pulsecore/sound-file.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -119,10 +117,7 @@ int pa_sound_file_load(
}
if (map)
- if (!pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT)) {
- pa_log("Unsupported channel map in file %s", fname);
- goto finish;
- }
+ pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
if ((l = pa_frame_size(ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
pa_log("File too large");
diff --git a/src/pulsecore/sound-file.h b/src/pulsecore/sound-file.h
index 46763bd8..e4d703d3 100644
--- a/src/pulsecore/sound-file.h
+++ b/src/pulsecore/sound-file.h
@@ -1,8 +1,6 @@
#ifndef soundfilehfoo
#define soundfilehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 5c36937a..3d1abe30 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -76,12 +74,15 @@ void pa_source_output_new_data_done(pa_source_output_new_data *data) {
pa_proplist_free(data->proplist);
}
+/* Called from main context */
static void reset_callbacks(pa_source_output *o) {
pa_assert(o);
o->push = NULL;
o->process_rewind = NULL;
o->update_max_rewind = NULL;
+ o->update_source_requested_latency = NULL;
+ o->update_source_latency_range = NULL;
o->attach = NULL;
o->detach = NULL;
o->suspend = NULL;
@@ -91,6 +92,7 @@ static void reset_callbacks(pa_source_output *o) {
o->state_change = NULL;
}
+/* Called from main context */
pa_source_output* pa_source_output_new(
pa_core *core,
pa_source_output_new_data *data,
@@ -109,11 +111,13 @@ pa_source_output* pa_source_output_new(
pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
if (!data->source)
- data->source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE, 1);
+ data->source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE, TRUE);
pa_return_null_if_fail(data->source);
pa_return_null_if_fail(pa_source_get_state(data->source) != PA_SOURCE_UNLINKED);
+ pa_return_null_if_fail(!data->direct_on_input || data->direct_on_input->sink == data->source->monitor_of);
+
if (!data->sample_spec_is_set)
data->sample_spec = data->source->sample_spec;
@@ -192,6 +196,8 @@ pa_source_output* pa_source_output_new(
o->sample_spec = data->sample_spec;
o->channel_map = data->channel_map;
+ o->direct_on_input = data->direct_on_input;
+
reset_callbacks(o);
o->userdata = NULL;
@@ -200,6 +206,7 @@ pa_source_output* pa_source_output_new(
o->thread_info.sample_spec = o->sample_spec;
o->thread_info.resampler = resampler;
o->thread_info.requested_source_latency = (pa_usec_t) -1;
+ o->thread_info.direct_on_input = o->direct_on_input;
o->thread_info.delay_memblockq = pa_memblockq_new(
0,
@@ -214,6 +221,9 @@ pa_source_output* pa_source_output_new(
pa_assert_se(pa_idxset_put(core->source_outputs, o, &o->index) == 0);
pa_assert_se(pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL) == 0);
+ if (o->direct_on_input)
+ pa_assert_se(pa_idxset_put(o->direct_on_input->direct_outputs, o, NULL) == 0);
+
pa_log_info("Created output %u \"%s\" on %s with sample spec %s and channel map %s",
o->index,
pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME)),
@@ -226,6 +236,7 @@ pa_source_output* pa_source_output_new(
return o;
}
+/* Called from main context */
static void update_n_corked(pa_source_output *o, pa_source_output_state_t state) {
pa_assert(o);
@@ -237,14 +248,14 @@ static void update_n_corked(pa_source_output *o, pa_source_output_state_t state)
pa_source_update_status(o->source);
}
+/* Called from main context */
static int source_output_set_state(pa_source_output *o, pa_source_output_state_t state) {
pa_assert(o);
if (o->state == state)
return 0;
- if (pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0)
- return -1;
+ pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) == 0);
update_n_corked(o, state);
o->state = state;
@@ -255,6 +266,7 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
return 0;
}
+/* Called from main context */
void pa_source_output_unlink(pa_source_output*o) {
pa_bool_t linked;
pa_assert(o);
@@ -269,6 +281,8 @@ void pa_source_output_unlink(pa_source_output*o) {
if (linked)
pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o);
+ if (o->direct_on_input)
+ pa_idxset_remove_by_data(o->direct_on_input->direct_outputs, o, NULL);
pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
if (pa_idxset_remove_by_data(o->source->outputs, o, NULL))
pa_source_output_unref(o);
@@ -278,7 +292,7 @@ void pa_source_output_unlink(pa_source_output*o) {
if (linked)
if (o->source->asyncmsgq)
- pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL) == 0);
reset_callbacks(o);
@@ -291,6 +305,7 @@ void pa_source_output_unlink(pa_source_output*o) {
pa_source_output_unref(o);
}
+/* Called from main context */
static void source_output_free(pa_object* mo) {
pa_source_output *o = PA_SOURCE_OUTPUT(mo);
@@ -317,45 +332,52 @@ static void source_output_free(pa_object* mo) {
pa_xfree(o);
}
+/* Called from main context */
void pa_source_output_put(pa_source_output *o) {
pa_source_output_state_t state;
pa_source_output_assert_ref(o);
pa_assert(o->state == PA_SOURCE_OUTPUT_INIT);
+
+ /* The following fields must be initialized properly */
pa_assert(o->push);
+ pa_assert(o->kill);
state = o->flags & PA_SOURCE_OUTPUT_START_CORKED ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
update_n_corked(o, state);
o->state = state;
- pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL) == 0);
pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], o);
}
+/* Called from main context */
void pa_source_output_kill(pa_source_output*o) {
pa_source_output_assert_ref(o);
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
- if (o->kill)
- o->kill(o);
+ o->kill(o);
}
-pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
- pa_usec_t r = 0;
+/* Called from main context */
+pa_usec_t pa_source_output_get_latency(pa_source_output *o, pa_usec_t *source_latency) {
+ pa_usec_t r[2] = { 0, 0 };
pa_source_output_assert_ref(o);
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
- if (pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY, &r, 0, NULL) < 0)
- r = 0;
+ pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY, r, 0, NULL) == 0);
if (o->get_latency)
- r += o->get_latency(o);
+ r[0] += o->get_latency(o);
- return r;
+ if (source_latency)
+ *source_latency = r[1];
+
+ return r[0];
}
/* Called from thread context */
@@ -368,10 +390,10 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
pa_assert(chunk);
pa_assert(pa_frame_aligned(chunk->length, &o->source->sample_spec));
- if (!o->push || o->state == PA_SOURCE_OUTPUT_CORKED)
+ if (!o->push || o->thread_info.state == PA_SOURCE_OUTPUT_CORKED)
return;
- pa_assert(o->state == PA_SOURCE_OUTPUT_RUNNING);
+ pa_assert(o->thread_info.state == PA_SOURCE_OUTPUT_RUNNING);
if (pa_memblockq_push(o->thread_info.delay_memblockq, chunk) < 0) {
pa_log_debug("Delay queue overflow!");
@@ -409,7 +431,8 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
if (rchunk.length > 0)
o->push(o, &rchunk);
- pa_memblock_unref(rchunk.memblock);
+ if (rchunk.memblock)
+ pa_memblock_unref(rchunk.memblock);
}
pa_memblock_unref(qchunk.memblock);
@@ -421,7 +444,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes /* in sink sample spec */) {
pa_source_output_assert_ref(o);
- pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
+ pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->thread_info.state));
pa_assert(pa_frame_aligned(nbytes, &o->source->sample_spec));
if (nbytes <= 0)
@@ -455,42 +478,44 @@ void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes /* i
o->update_max_rewind(o, o->thread_info.resampler ? pa_resampler_result(o->thread_info.resampler, nbytes) : nbytes);
}
+/* Called from thread context */
static pa_usec_t fixup_latency(pa_source *s, pa_usec_t usec) {
pa_source_assert_ref(s);
if (usec == (pa_usec_t) -1)
return usec;
- if (s->max_latency > 0 && usec > s->max_latency)
- usec = s->max_latency;
+ if (s->thread_info.max_latency > 0 && usec > s->thread_info.max_latency)
+ usec = s->thread_info.max_latency;
- if (s->min_latency > 0 && usec < s->min_latency)
- usec = s->min_latency;
+ if (s->thread_info.min_latency > 0 && usec < s->thread_info.min_latency)
+ usec = s->thread_info.min_latency;
return usec;
}
+/* Called from thread context */
pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output *o, pa_usec_t usec) {
pa_source_output_assert_ref(o);
usec = fixup_latency(o->source, usec);
-
o->thread_info.requested_source_latency = usec;
pa_source_invalidate_requested_latency(o->source);
return usec;
}
+/* Called from main context */
pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
pa_source_output_assert_ref(o);
- usec = fixup_latency(o->source, usec);
-
if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
- pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
+ pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
else {
/* If this sink input 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;
}
@@ -498,13 +523,14 @@ pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t
return usec;
}
+/* Called from main context */
pa_usec_t pa_source_output_get_requested_latency(pa_source_output *o) {
pa_usec_t usec = 0;
pa_source_output_assert_ref(o);
if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
- pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
else
/* If this sink input is not realized yet, we have to touch
* the thread info data directly */
@@ -513,6 +539,7 @@ pa_usec_t pa_source_output_get_requested_latency(pa_source_output *o) {
return usec;
}
+/* Called from main context */
void pa_source_output_cork(pa_source_output *o, pa_bool_t b) {
pa_source_output_assert_ref(o);
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
@@ -520,6 +547,7 @@ void pa_source_output_cork(pa_source_output *o, pa_bool_t b) {
source_output_set_state(o, b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING);
}
+/* Called from main context */
int pa_source_output_set_rate(pa_source_output *o, uint32_t rate) {
pa_source_output_assert_ref(o);
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
@@ -536,6 +564,7 @@ int pa_source_output_set_rate(pa_source_output *o, uint32_t rate) {
return 0;
}
+/* Called from main context */
void pa_source_output_set_name(pa_source_output *o, const char *name) {
const char *old;
pa_source_output_assert_ref(o);
@@ -559,12 +588,14 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) {
}
}
+/* Called from main context */
pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) {
pa_source_output_assert_ref(o);
return o->resample_method;
}
+/* Called from main context */
int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
pa_source *origin;
pa_resampler *new_resampler;
@@ -582,6 +613,9 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
if (o->flags & PA_SOURCE_OUTPUT_DONT_MOVE)
return -1;
+ if (o->direct_on_input)
+ return -1;
+
if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
pa_log_warn("Failed to move source output: too many outputs per source.");
return -1;
@@ -619,7 +653,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], &hook_data);
/* Okey, let's move it */
- pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL) == 0);
pa_idxset_remove_by_data(origin->outputs, o, NULL);
pa_idxset_put(dest->outputs, o, NULL);
@@ -652,7 +686,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
pa_source_update_status(origin);
pa_source_update_status(dest);
- pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL) == 0);
if (o->moved)
o->moved(o);
@@ -667,6 +701,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
return 0;
}
+/* Called from IO thread context */
void pa_source_output_set_state_within_thread(pa_source_output *o, pa_source_output_state_t state) {
pa_source_output_assert_ref(o);
@@ -679,19 +714,22 @@ void pa_source_output_set_state_within_thread(pa_source_output *o, pa_source_out
o->thread_info.state = state;
}
-/* Called from thread context */
+/* Called from IO thread context, except when it is not */
int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk* chunk) {
pa_source_output *o = PA_SOURCE_OUTPUT(mo);
-
pa_source_output_assert_ref(o);
- pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->thread_info.state));
switch (code) {
case PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY: {
pa_usec_t *r = userdata;
+ pa_usec_t source_usec = 0;
+
+ r[0] += pa_bytes_to_usec(pa_memblockq_get_length(o->thread_info.delay_memblockq), &o->source->sample_spec);
+
+ if (o->source->parent.process_msg(PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_GET_LATENCY, &source_usec, 0, NULL) >= 0)
+ r[1] += source_usec;
- *r += pa_bytes_to_usec(pa_memblockq_get_length(o->thread_info.delay_memblockq), &o->source->sample_spec);
return 0;
}
@@ -706,10 +744,13 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int
pa_source_output_set_state_within_thread(o, PA_PTR_TO_UINT(userdata));
return 0;
- case PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY:
+ case PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY: {
+ pa_usec_t *usec = userdata;
+
+ *usec = pa_source_output_set_requested_latency_within_thread(o, *usec);
- pa_source_output_set_requested_latency_within_thread(o, (pa_usec_t) offset);
return 0;
+ }
case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
pa_usec_t *r = userdata;
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 2dadb5c4..61825b22 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -1,8 +1,6 @@
#ifndef foopulsesourceoutputhfoo
#define foopulsesourceoutputhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -66,13 +64,17 @@ struct pa_source_output {
pa_source_output_state_t state;
pa_source_output_flags_t flags;
- pa_proplist *proplist;
char *driver; /* may be NULL */
+ pa_proplist *proplist;
+
pa_module *module; /* may be NULL */
pa_client *client; /* may be NULL */
pa_source *source;
+ /* A source output can monitor just a single input of a sink, in which case we find it here */
+ pa_sink_input *direct_on_input; /* may be NULL */
+
pa_sample_spec sample_spec;
pa_channel_map channel_map;
@@ -80,16 +82,24 @@ struct pa_source_output {
/* Pushes a new memchunk into the output. Called from IO thread
* context. */
- void (*push)(pa_source_output *o, const pa_memchunk *chunk);
+ void (*push)(pa_source_output *o, const pa_memchunk *chunk); /* may NOT be NULL */
/* Only relevant for monitor sources right now: called when the
- * recorded stream is rewound. Called from IO context*/
- void (*process_rewind)(pa_source_output *o, size_t nbytes);
+ * recorded stream is rewound. Called from IO context */
+ void (*process_rewind)(pa_source_output *o, size_t nbytes); /* may be NULL */
/* Called whenever the maximum rewindable size of the source
* changes. Called from IO thread context. */
void (*update_max_rewind) (pa_source_output *o, size_t nbytes); /* may be NULL */
+ /* Called whenever the configured latency of the source
+ * changes. Called from IO context. */
+ void (*update_source_requested_latency) (pa_source_output *o); /* may be NULL */
+
+ /* Called whenver the latency range of the source changes. Called
+ * from IO context. */
+ void (*update_source_latency_range) (pa_source_output *o); /* may be NULL */
+
/* If non-NULL this function is called when the output is first
* connected to a source. Called from IO thread context */
void (*attach) (pa_source_output *o); /* may be NULL */
@@ -108,12 +118,12 @@ struct pa_source_output {
/* Supposed to unlink and destroy this stream. Called from main
* context. */
- void (*kill)(pa_source_output* o); /* may be NULL */
+ void (*kill)(pa_source_output* o); /* may NOT be NULL */
/* Return the current latency (i.e. length of bufferd audio) of
- this stream. Called from main context. If NULL a
- PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY message is sent to the IO
- thread instead. */
+ this stream. Called from main context. This is added to what the
+ PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY message sent to the IO thread
+ returns */
pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */
/* If non_NULL this function is called from thread context if the
@@ -135,6 +145,8 @@ struct pa_source_output {
/* The requested latency for the source */
pa_usec_t requested_source_latency;
+
+ pa_sink_input *direct_on_input; /* may be NULL */
} thread_info;
void *userdata;
@@ -154,6 +166,7 @@ enum {
typedef struct pa_source_output_new_data {
pa_proplist *proplist;
+ pa_sink_input *direct_on_input;
const char *driver;
pa_module *module;
@@ -202,7 +215,7 @@ int pa_source_output_set_rate(pa_source_output *o, uint32_t rate);
/* External code may request disconnection with this funcion */
void pa_source_output_kill(pa_source_output*o);
-pa_usec_t pa_source_output_get_latency(pa_source_output *i);
+pa_usec_t pa_source_output_get_latency(pa_source_output *i, pa_usec_t *source_latency);
pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o);
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index c767abcf..8256a988 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -99,6 +97,7 @@ void pa_source_new_data_done(pa_source_new_data *data) {
pa_proplist_free(data->proplist);
}
+/* Called from main context */
static void reset_callbacks(pa_source *s) {
pa_assert(s);
@@ -110,6 +109,7 @@ static void reset_callbacks(pa_source *s) {
s->update_requested_latency = NULL;
}
+/* Called from main context */
pa_source* pa_source_new(
pa_core *core,
pa_source_new_data *data,
@@ -120,6 +120,8 @@ pa_source* pa_source_new(
char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
pa_assert(core);
+ pa_assert(data);
+ pa_assert(data->name);
s = pa_msgobject_new(pa_source);
@@ -128,6 +130,8 @@ pa_source* pa_source_new(
return NULL;
}
+ pa_source_new_data_set_name(data, name);
+
if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0) {
pa_xfree(s);
pa_namereg_unregister(core, name);
@@ -195,16 +199,15 @@ pa_source* pa_source_new(
&s->sample_spec,
0);
- s->min_latency = DEFAULT_MIN_LATENCY;
- s->max_latency = s->min_latency;
-
s->thread_info.outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
- s->thread_info.soft_volume = s->volume;
- s->thread_info.soft_muted = s->muted;
+ pa_cvolume_reset(&s->thread_info.soft_volume, s->sample_spec.channels);
+ s->thread_info.soft_muted = FALSE;
s->thread_info.state = s->state;
s->thread_info.max_rewind = 0;
s->thread_info.requested_latency_valid = FALSE;
s->thread_info.requested_latency = 0;
+ s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
+ s->thread_info.max_latency = 0;
pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
@@ -217,6 +220,7 @@ pa_source* pa_source_new(
return s;
}
+/* Called from main context */
static int source_set_state(pa_source *s, pa_source_state_t state) {
int ret;
pa_bool_t suspend_change;
@@ -235,8 +239,7 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
return -1;
if (s->asyncmsgq)
- if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) < 0)
- return -1;
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL) == 0);
s->state = state;
@@ -257,24 +260,32 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
return 0;
}
+/* Called from main context */
void pa_source_put(pa_source *s) {
pa_source_assert_ref(s);
pa_assert(s->state == PA_SINK_INIT);
+
+ /* The following fields must be initialized properly when calling _put() */
pa_assert(s->asyncmsgq);
pa_assert(s->rtpoll);
+ pa_assert(!s->thread_info.min_latency || !s->thread_info.max_latency ||
+ s->thread_info.min_latency <= s->thread_info.max_latency);
- pa_assert(!s->min_latency || !s->max_latency || s->min_latency <= s->max_latency);
-
- if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL))
+ if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL)) {
s->flags |= PA_SOURCE_DECIBEL_VOLUME;
+ s->thread_info.soft_volume = s->volume;
+ s->thread_info.soft_muted = s->muted;
+ }
+
pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s);
}
+/* Called from main context */
void pa_source_unlink(pa_source *s) {
pa_bool_t linked;
pa_source_output *o, *j = NULL;
@@ -312,6 +323,7 @@ void pa_source_unlink(pa_source *s) {
}
}
+/* Called from main context */
static void source_free(pa_object *o) {
pa_source_output *so;
pa_source *s = PA_SOURCE(o);
@@ -343,18 +355,21 @@ static void source_free(pa_object *o) {
pa_xfree(s);
}
+/* Called from main context */
void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) {
pa_source_assert_ref(s);
s->asyncmsgq = q;
}
+/* Called from main context */
void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) {
pa_source_assert_ref(s);
s->rtpoll = p;
}
+/* Called from main context */
int pa_source_update_status(pa_source*s) {
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
@@ -365,6 +380,7 @@ int pa_source_update_status(pa_source*s) {
return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
}
+/* Called from main context */
int pa_source_suspend(pa_source *s, pa_bool_t suspend) {
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
@@ -375,6 +391,7 @@ int pa_source_suspend(pa_source *s, pa_bool_t suspend) {
return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
}
+/* Called from IO thread context */
void pa_source_process_rewind(pa_source *s, size_t nbytes) {
pa_source_output *o;
void *state = NULL;
@@ -393,6 +410,7 @@ void pa_source_process_rewind(pa_source *s, size_t nbytes) {
}
}
+/* Called from IO thread context */
void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
pa_source_output *o;
void *state = NULL;
@@ -417,7 +435,9 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
pa_source_output_assert_ref(o);
- pa_source_output_push(o, &vchunk);
+
+ if (!o->thread_info.direct_on_input)
+ pa_source_output_push(o, &vchunk);
}
pa_memblock_unref(vchunk.memblock);
@@ -425,11 +445,43 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
pa_source_output_assert_ref(o);
- pa_source_output_push(o, chunk);
+
+ if (!o->thread_info.direct_on_input)
+ pa_source_output_push(o, chunk);
}
}
}
+/* Called from IO thread context */
+void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk *chunk) {
+ pa_source_assert_ref(s);
+ pa_assert(PA_SOURCE_IS_OPENED(s->thread_info.state));
+ pa_source_output_assert_ref(o);
+ pa_assert(o->thread_info.direct_on_input);
+ pa_assert(chunk);
+
+ if (s->thread_info.state != PA_SOURCE_RUNNING)
+ return;
+
+ if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
+ pa_memchunk vchunk = *chunk;
+
+ pa_memblock_ref(vchunk.memblock);
+ pa_memchunk_make_writable(&vchunk, 0);
+
+ if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
+ pa_silence_memchunk(&vchunk, &s->sample_spec);
+ else
+ pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
+
+ pa_source_output_push(o, &vchunk);
+
+ pa_memblock_unref(vchunk.memblock);
+ } else
+ pa_source_output_push(o, chunk);
+}
+
+/* Called from main thread */
pa_usec_t pa_source_get_latency(pa_source *s) {
pa_usec_t usec;
@@ -439,14 +491,14 @@ pa_usec_t pa_source_get_latency(pa_source *s) {
if (!PA_SOURCE_IS_OPENED(s->state))
return 0;
- if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
- return 0;
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
return usec;
}
+/* Called from main thread */
void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
- int changed;
+ pa_bool_t changed;
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
@@ -459,34 +511,36 @@ void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
s->set_volume = NULL;
if (!s->set_volume)
- pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), 0, NULL, pa_xfree);
+ pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, volume, 0, NULL);
if (changed)
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
+/* Called from main thread */
const pa_cvolume *pa_source_get_volume(pa_source *s) {
- pa_cvolume old_volume;
-
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
- old_volume = s->volume;
+ if (s->refresh_volume) {
+ pa_cvolume old_volume = s->volume;
- if (s->get_volume && s->get_volume(s) < 0)
- s->get_volume = NULL;
+ if (s->get_volume && s->get_volume(s) < 0)
+ s->get_volume = NULL;
- if (!s->get_volume && s->refresh_volume)
- pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, &s->volume, 0, NULL);
+ if (!s->get_volume)
+ pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, &s->volume, 0, NULL);
- if (!pa_cvolume_equal(&old_volume, &s->volume))
- pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ if (!pa_cvolume_equal(&old_volume, &s->volume))
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ }
return &s->volume;
}
+/* Called from main thread */
void pa_source_set_mute(pa_source *s, pa_bool_t mute) {
- int changed;
+ pa_bool_t changed;
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
@@ -504,26 +558,29 @@ void pa_source_set_mute(pa_source *s, pa_bool_t mute) {
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
+/* Called from main thread */
pa_bool_t pa_source_get_mute(pa_source *s) {
- pa_bool_t old_muted;
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
- old_muted = s->muted;
+ if (s->refresh_muted) {
+ pa_bool_t old_muted = s->muted;
- if (s->get_mute && s->get_mute(s) < 0)
- s->get_mute = NULL;
+ if (s->get_mute && s->get_mute(s) < 0)
+ s->get_mute = NULL;
- if (!s->get_mute && s->refresh_muted)
- pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, &s->muted, 0, NULL);
+ if (!s->get_mute)
+ pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, &s->muted, 0, NULL);
- if (old_muted != s->muted)
- pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ if (old_muted != s->muted)
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ }
return s->muted;
}
+/* Called from main thread */
void pa_source_set_description(pa_source *s, const char *description) {
const char *old;
pa_source_assert_ref(s);
@@ -547,6 +604,7 @@ void pa_source_set_description(pa_source *s, const char *description) {
}
}
+/* Called from main thread */
unsigned pa_source_linked_by(pa_source *s) {
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
@@ -554,6 +612,7 @@ unsigned pa_source_linked_by(pa_source *s) {
return pa_idxset_size(s->outputs);
}
+/* Called from main thread */
unsigned pa_source_used_by(pa_source *s) {
unsigned ret;
@@ -566,17 +625,23 @@ unsigned pa_source_used_by(pa_source *s) {
return ret - s->n_corked;
}
+/* Called from IO thread, except when it is not */
int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
pa_source *s = PA_SOURCE(object);
pa_source_assert_ref(s);
- pa_assert(s->thread_info.state != PA_SOURCE_UNLINKED);
switch ((pa_source_message_t) code) {
+
case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
+ if (o->direct_on_input) {
+ o->thread_info.direct_on_input = o->direct_on_input;
+ pa_hashmap_put(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index), o);
+ }
+
pa_assert(!o->thread_info.attached);
o->thread_info.attached = TRUE;
@@ -606,6 +671,11 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
pa_assert(o->thread_info.attached);
o->thread_info.attached = FALSE;
+ if (o->thread_info.direct_on_input) {
+ pa_hashmap_remove(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index));
+ o->thread_info.direct_on_input = NULL;
+ }
+
if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
pa_source_output_unref(o);
@@ -636,9 +706,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
case PA_SOURCE_MESSAGE_DETACH:
- /* We're detaching all our output streams so that the
- * asyncmsgq and rtpoll fields can be changed without
- * problems */
+ /* Detach all streams */
pa_source_detach_within_thread(s);
return 0;
@@ -652,10 +720,45 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
pa_usec_t *usec = userdata;
*usec = pa_source_get_requested_latency_within_thread(s);
+
+ if (*usec == (pa_usec_t) -1)
+ *usec = s->thread_info.max_latency;
+
+ return 0;
+ }
+
+ case PA_SOURCE_MESSAGE_SET_LATENCY_RANGE: {
+ pa_usec_t *r = userdata;
+
+ pa_source_update_latency_range(s, r[0], r[1]);
+
+ return 0;
+ }
+
+ case PA_SOURCE_MESSAGE_GET_LATENCY_RANGE: {
+ pa_usec_t *r = userdata;
+
+ r[0] = s->thread_info.min_latency;
+ r[1] = s->thread_info.max_latency;
+
return 0;
}
+ case PA_SOURCE_MESSAGE_GET_MAX_REWIND:
+
+ *((size_t*) userdata) = s->thread_info.max_rewind;
+ return 0;
+
case PA_SOURCE_MESSAGE_GET_LATENCY:
+
+ if (s->monitor_of) {
+ *((pa_usec_t*) userdata) = 0;
+ return 0;
+ }
+
+ /* Implementors need to overwrite this implementation! */
+ return -1;
+
case PA_SOURCE_MESSAGE_MAX:
;
}
@@ -663,6 +766,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
return -1;
}
+/* Called from main thread */
int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) {
uint32_t idx;
pa_source *source;
@@ -676,20 +780,23 @@ int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) {
return ret;
}
+/* Called from main thread */
void pa_source_detach(pa_source *s) {
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
- pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL) == 0);
}
+/* Called from main thread */
void pa_source_attach(pa_source *s) {
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
- pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL);
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
}
+/* Called from IO thread */
void pa_source_detach_within_thread(pa_source *s) {
pa_source_output *o;
void *state = NULL;
@@ -702,6 +809,7 @@ void pa_source_detach_within_thread(pa_source *s) {
o->detach(o);
}
+/* Called from IO thread */
void pa_source_attach_within_thread(pa_source *s) {
pa_source_output *o;
void *state = NULL;
@@ -714,6 +822,7 @@ void pa_source_attach_within_thread(pa_source *s) {
o->attach(o);
}
+/* Called from IO thread */
pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
pa_usec_t result = (pa_usec_t) -1;
pa_source_output *o;
@@ -731,11 +840,11 @@ pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
result = o->thread_info.requested_source_latency;
if (result != (pa_usec_t) -1) {
- if (s->max_latency > 0 && result > s->max_latency)
- result = s->max_latency;
+ if (s->thread_info.max_latency > 0 && result > s->thread_info.max_latency)
+ result = s->thread_info.max_latency;
- if (s->min_latency > 0 && result < s->min_latency)
- result = s->min_latency;
+ if (s->thread_info.min_latency > 0 && result < s->thread_info.min_latency)
+ result = s->thread_info.min_latency;
}
s->thread_info.requested_latency = result;
@@ -744,6 +853,7 @@ pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
return result;
}
+/* Called from main thread */
pa_usec_t pa_source_get_requested_latency(pa_source *s) {
pa_usec_t usec;
@@ -753,15 +863,12 @@ pa_usec_t pa_source_get_requested_latency(pa_source *s) {
if (!PA_SOURCE_IS_OPENED(s->state))
return 0;
- if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) < 0)
- return 0;
-
- if (usec == (pa_usec_t) -1)
- usec = s->max_latency;
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
return usec;
}
+/* Called from IO thread */
void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
pa_source_output *o;
void *state = NULL;
@@ -773,17 +880,106 @@ void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
s->thread_info.max_rewind = max_rewind;
- while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
- pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
+ if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
+ while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+ pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
+ }
}
void pa_source_invalidate_requested_latency(pa_source *s) {
+ pa_source_output *o;
+ void *state = NULL;
pa_source_assert_ref(s);
- pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
s->thread_info.requested_latency_valid = FALSE;
if (s->update_requested_latency)
s->update_requested_latency(s);
+
+ while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+ o->update_source_requested_latency(o);
+
+ if (s->monitor_of)
+ pa_sink_invalidate_requested_latency(s->monitor_of);
+}
+
+void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
+ pa_source_assert_ref(s);
+
+ /* min_latency == 0: no limit
+ * min_latency == (size_t) -1: default limit
+ * min_latency anything else: specified limit
+ *
+ * Similar for max_latency */
+
+ if (min_latency == (pa_usec_t) -1)
+ min_latency = DEFAULT_MIN_LATENCY;
+
+ if (max_latency == (pa_usec_t) -1)
+ max_latency = min_latency;
+
+ pa_assert(!min_latency || !max_latency ||
+ min_latency <= max_latency);
+
+ if (PA_SINK_IS_LINKED(s->state)) {
+ pa_usec_t r[2];
+
+ r[0] = min_latency;
+ r[1] = max_latency;
+
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
+ } else {
+ s->thread_info.min_latency = min_latency;
+ s->thread_info.max_latency = max_latency;
+
+ s->thread_info.requested_latency_valid = FALSE;
+ }
+}
+
+void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
+ pa_source_assert_ref(s);
+ pa_assert(min_latency);
+ pa_assert(max_latency);
+
+ if (PA_SOURCE_IS_LINKED(s->state)) {
+ pa_usec_t r[2] = { 0, 0 };
+
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
+
+ *min_latency = r[0];
+ *max_latency = r[1];
+ } else {
+ *min_latency = s->thread_info.min_latency;
+ *max_latency = s->thread_info.max_latency;
+ }
+}
+
+/* Called from IO thread */
+void pa_source_update_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
+ pa_source_output *o;
+ void *state = NULL;
+
+ pa_source_assert_ref(s);
+
+ s->thread_info.min_latency = min_latency;
+ s->thread_info.max_latency = max_latency;
+
+ while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+ if (o->update_source_latency_range)
+ o->update_source_latency_range(o);
+
+ pa_source_invalidate_requested_latency(s);
+}
+
+size_t pa_source_get_max_rewind(pa_source *s) {
+ size_t r;
+ pa_source_assert_ref(s);
+
+ if (!PA_SOURCE_IS_LINKED(s->state))
+ return s->thread_info.max_rewind;
+
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
+
+ return r;
}
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index f9c9cbf9..f4a17e8d 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -1,8 +1,6 @@
#ifndef foopulsesourcehfoo
#define foopulsesourcehfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -42,6 +40,7 @@ typedef struct pa_source pa_source;
#include <pulsecore/asyncmsgq.h>
#include <pulsecore/msgobject.h>
#include <pulsecore/rtpoll.h>
+#include <pulsecore/source-output.h>
#define PA_MAX_OUTPUTS_PER_SOURCE 32
@@ -84,22 +83,44 @@ struct pa_source {
pa_cvolume volume;
pa_bool_t muted;
- pa_bool_t refresh_volume;
- pa_bool_t refresh_muted;
+
+ pa_bool_t refresh_volume:1;
+ pa_bool_t refresh_muted:1;
pa_asyncmsgq *asyncmsgq;
pa_rtpoll *rtpoll;
pa_memchunk silence;
- pa_usec_t min_latency; /* we won't go below this latency setting */
- pa_usec_t max_latency; /* An upper limit for the latencies */
-
+ /* Called when the main loop requests a state change. Called from
+ * main loop context. If returns -1 the state change will be
+ * inhibited */
int (*set_state)(pa_source*source, pa_source_state_t state); /* may be NULL */
- int (*set_volume)(pa_source *s); /* dito */
+
+ /* Callled when the volume is queried. Called from main loop
+ * context. If this is NULL a PA_SOURCE_MESSAGE_GET_VOLUME message
+ * will be sent to the IO thread instead. If refresh_volume is
+ * FALSE neither this function is called nor a message is sent. */
int (*get_volume)(pa_source *s); /* dito */
- int (*set_mute)(pa_source *s); /* dito */
+
+ /* Called when the volume shall be changed. Called from main loop
+ * context. If this is NULL a PA_SOURCE_MESSAGE_SET_VOLUME message
+ * will be sent to the IO thread instead. */
+ int (*set_volume)(pa_source *s); /* dito */
+
+ /* Called when the mute setting is queried. Called from main loop
+ * context. If this is NULL a PA_SOURCE_MESSAGE_GET_MUTE message
+ * will be sent to the IO thread instead. If refresh_mute is
+ * FALSE neither this function is called nor a message is sent.*/
int (*get_mute)(pa_source *s); /* dito */
+
+ /* Called when the mute setting shall be changed. Called from main
+ * loop context. If this is NULL a PA_SOURCE_MESSAGE_SET_MUTE
+ * message will be sent to the IO thread instead. */
+ int (*set_mute)(pa_source *s); /* dito */
+
+ /* Called when a the requested latency is changed. Called from IO
+ * thread context. */
void (*update_requested_latency)(pa_source *s); /* dito */
/* Contains copies of the above data so that the real-time worker
@@ -108,14 +129,17 @@ struct pa_source {
pa_source_state_t state;
pa_hashmap *outputs;
pa_cvolume soft_volume;
- pa_bool_t soft_muted;
+ pa_bool_t soft_muted:1;
- pa_bool_t requested_latency_valid;
- size_t requested_latency;
+ pa_bool_t requested_latency_valid:1;
+ pa_usec_t requested_latency;
/* Then number of bytes this source will be rewound for at
- * max */
+ * max. (Only used on monitor sources) */
size_t max_rewind;
+
+ pa_usec_t min_latency; /* we won't go below this latency */
+ pa_usec_t max_latency; /* An upper limit for the latencies */
} thread_info;
void *userdata;
@@ -136,6 +160,9 @@ typedef enum pa_source_message {
PA_SOURCE_MESSAGE_SET_STATE,
PA_SOURCE_MESSAGE_ATTACH,
PA_SOURCE_MESSAGE_DETACH,
+ PA_SOURCE_MESSAGE_SET_LATENCY_RANGE,
+ PA_SOURCE_MESSAGE_GET_LATENCY_RANGE,
+ PA_SOURCE_MESSAGE_GET_MAX_REWIND,
PA_SOURCE_MESSAGE_MAX
} pa_source_message_t;
@@ -180,13 +207,19 @@ void pa_source_set_description(pa_source *s, const char *description);
void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q);
void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p);
+void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency);
+
void pa_source_detach(pa_source *s);
void pa_source_attach(pa_source *s);
/* May be called by everyone, from main context */
+/* The returned value is supposed to be in the time domain of the sound card! */
pa_usec_t pa_source_get_latency(pa_source *s);
pa_usec_t pa_source_get_requested_latency(pa_source *s);
+void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t *max_latency);
+
+size_t pa_source_get_max_rewind(pa_source *s);
int pa_source_update_status(pa_source*s);
int pa_source_suspend(pa_source *s, pa_bool_t suspend);
@@ -203,7 +236,8 @@ unsigned pa_source_used_by(pa_source *s); /* Number of connected streams that ar
/* To be called exclusively by the source driver, from IO context */
-void pa_source_post(pa_source*s, const pa_memchunk *b);
+void pa_source_post(pa_source*s, const pa_memchunk *chunk);
+void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk *chunk);
void pa_source_process_rewind(pa_source *s, size_t nbytes);
int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, int64_t, pa_memchunk *chunk);
@@ -214,6 +248,7 @@ void pa_source_detach_within_thread(pa_source *s);
pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s);
void pa_source_set_max_rewind(pa_source *s, size_t max_rewind);
+void pa_source_update_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency);
/* To be called exclusively by source output drivers, from IO context */
diff --git a/src/pulsecore/speexwrap.h b/src/pulsecore/speexwrap.h
index df73edf0..617e4afb 100644
--- a/src/pulsecore/speexwrap.h
+++ b/src/pulsecore/speexwrap.h
@@ -1,8 +1,6 @@
#ifndef foopulsespeexwraphfoo
#define foopulsespeexwraphfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/start-child.c b/src/pulsecore/start-child.c
index e01011d6..1661383d 100644
--- a/src/pulsecore/start-child.c
+++ b/src/pulsecore/start-child.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/start-child.h b/src/pulsecore/start-child.h
index 359b5044..0b5ff660 100644
--- a/src/pulsecore/start-child.h
+++ b/src/pulsecore/start-child.h
@@ -1,8 +1,6 @@
#ifndef foopulsestartchildhfoo
#define foopulsestartchildhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/strbuf.c b/src/pulsecore/strbuf.c
index 7c576c67..b59b6f49 100644
--- a/src/pulsecore/strbuf.c
+++ b/src/pulsecore/strbuf.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/strbuf.h b/src/pulsecore/strbuf.h
index d3555a2c..24c876d5 100644
--- a/src/pulsecore/strbuf.h
+++ b/src/pulsecore/strbuf.h
@@ -1,8 +1,6 @@
#ifndef foostrbufhfoo
#define foostrbufhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/strlist.c b/src/pulsecore/strlist.c
index ac83f6b1..f587a2f8 100644
--- a/src/pulsecore/strlist.c
+++ b/src/pulsecore/strlist.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/strlist.h b/src/pulsecore/strlist.h
index 6e6e2d4a..1cb7537a 100644
--- a/src/pulsecore/strlist.h
+++ b/src/pulsecore/strlist.h
@@ -1,8 +1,6 @@
#ifndef foostrlisthfoo
#define foostrlisthfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c
index 7616cd16..b0ed59ef 100644
--- a/src/pulsecore/tagstruct.c
+++ b/src/pulsecore/tagstruct.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/tagstruct.h b/src/pulsecore/tagstruct.h
index 8699e6c8..e7d07054 100644
--- a/src/pulsecore/tagstruct.h
+++ b/src/pulsecore/tagstruct.h
@@ -1,8 +1,6 @@
#ifndef footagstructhfoo
#define footagstructhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c
index 7e39c577..34f92a7e 100644
--- a/src/pulsecore/thread-mq.c
+++ b/src/pulsecore/thread-mq.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/thread-mq.h b/src/pulsecore/thread-mq.h
index 0ae49f8c..3b5e0e78 100644
--- a/src/pulsecore/thread-mq.h
+++ b/src/pulsecore/thread-mq.h
@@ -1,8 +1,6 @@
#ifndef foopulsethreadmqhfoo
#define foopulsethreadmqhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c
index 7f43f43e..20ed16d9 100644
--- a/src/pulsecore/thread-posix.c
+++ b/src/pulsecore/thread-posix.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/thread-win32.c b/src/pulsecore/thread-win32.c
index cad1420a..c40d3342 100644
--- a/src/pulsecore/thread-win32.c
+++ b/src/pulsecore/thread-win32.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h
index 54ef320e..f3aca13e 100644
--- a/src/pulsecore/thread.h
+++ b/src/pulsecore/thread.h
@@ -1,8 +1,6 @@
#ifndef foopulsethreadhfoo
#define foopulsethreadhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index 9b4be29f..fe5a4f18 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -451,3 +449,11 @@ pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay)
return (pa_usec_t) ((double) y_delay / nde);
}
+
+void pa_smoother_reset(pa_smoother *s) {
+ pa_assert(s);
+
+ s->n_history = 0;
+ s->abc_valid = FALSE;
+
+}
diff --git a/src/pulsecore/time-smoother.h b/src/pulsecore/time-smoother.h
index b301b48c..2051e640 100644
--- a/src/pulsecore/time-smoother.h
+++ b/src/pulsecore/time-smoother.h
@@ -1,8 +1,6 @@
#ifndef foopulsetimesmootherhfoo
#define foopulsetimesmootherhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -46,4 +44,6 @@ void pa_smoother_set_time_offset(pa_smoother *s, pa_usec_t x_offset);
void pa_smoother_pause(pa_smoother *s, pa_usec_t x);
void pa_smoother_resume(pa_smoother *s, pa_usec_t x);
+void pa_smoother_reset(pa_smoother *s);
+
#endif
diff --git a/src/pulsecore/tokenizer.c b/src/pulsecore/tokenizer.c
index cf5da648..d1e0836b 100644
--- a/src/pulsecore/tokenizer.c
+++ b/src/pulsecore/tokenizer.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/tokenizer.h b/src/pulsecore/tokenizer.h
index 68a8db49..d51cd73e 100644
--- a/src/pulsecore/tokenizer.h
+++ b/src/pulsecore/tokenizer.h
@@ -1,8 +1,6 @@
#ifndef footokenizerhfoo
#define footokenizerhfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/x11prop.c b/src/pulsecore/x11prop.c
index a740e39b..9e75f63a 100644
--- a/src/pulsecore/x11prop.c
+++ b/src/pulsecore/x11prop.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/x11prop.h b/src/pulsecore/x11prop.h
index 388c5a34..c5998d3e 100644
--- a/src/pulsecore/x11prop.h
+++ b/src/pulsecore/x11prop.h
@@ -1,8 +1,6 @@
#ifndef foox11prophfoo
#define foox11prophfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c
index 800a9458..00b6a157 100644
--- a/src/pulsecore/x11wrap.c
+++ b/src/pulsecore/x11wrap.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -63,7 +61,8 @@ struct pa_x11_wrapper {
struct pa_x11_client {
PA_LLIST_FIELDS(pa_x11_client);
pa_x11_wrapper *wrapper;
- int (*callback)(pa_x11_wrapper *w, XEvent *e, void *userdata);
+ pa_x11_event_cb_t event_cb;
+ pa_x11_kill_cb_t kill_cb;
void *userdata;
};
@@ -72,17 +71,23 @@ static void work(pa_x11_wrapper *w) {
pa_assert(w);
pa_assert(PA_REFCNT_VALUE(w) >= 1);
+ pa_x11_wrapper_ref(w);
+
while (XPending(w->display)) {
- pa_x11_client *c;
+ pa_x11_client *c, *n;
XEvent e;
XNextEvent(w->display, &e);
- for (c = w->clients; c; c = c->next) {
- pa_assert(c->callback);
- if (c->callback(w, &e, c->userdata) != 0)
- break;
+ for (c = w->clients; c; c = n) {
+ n = c->next;
+
+ if (c->event_cb)
+ if (c->event_cb(w, &e, c->userdata) != 0)
+ break;
}
}
+
+ pa_x11_wrapper_unref(w);
}
/* IO notification event for the X11 display connection */
@@ -251,7 +256,24 @@ Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w) {
return w->display;
}
-pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata) {
+void pa_x11_wrapper_kill(pa_x11_wrapper *w) {
+ pa_x11_client *c, *n;
+
+ pa_assert(w);
+
+ pa_x11_wrapper_ref(w);
+
+ for (c = w->clients; c; c = n) {
+ n = c->next;
+
+ if (c->kill_cb)
+ c->kill_cb(w, c->userdata);
+ }
+
+ pa_x11_wrapper_unref(w);
+}
+
+pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, pa_x11_event_cb_t event_cb, pa_x11_kill_cb_t kill_cb, void *userdata) {
pa_x11_client *c;
pa_assert(w);
@@ -259,7 +281,8 @@ pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w,
c = pa_xnew(pa_x11_client, 1);
c->wrapper = w;
- c->callback = cb;
+ c->event_cb = event_cb;
+ c->kill_cb = kill_cb;
c->userdata = userdata;
PA_LLIST_PREPEND(pa_x11_client, w->clients, c);
diff --git a/src/pulsecore/x11wrap.h b/src/pulsecore/x11wrap.h
index 9bed2fce..badc3a1f 100644
--- a/src/pulsecore/x11wrap.h
+++ b/src/pulsecore/x11wrap.h
@@ -1,8 +1,6 @@
#ifndef foox11wraphfoo
#define foox11wraphfoo
-/* $Id$ */
-
/***
This file is part of PulseAudio.
@@ -30,6 +28,11 @@
typedef struct pa_x11_wrapper pa_x11_wrapper;
+typedef struct pa_x11_client pa_x11_client;
+
+typedef int (*pa_x11_event_cb_t)(pa_x11_wrapper *w, XEvent *e, void *userdata);
+typedef void (*pa_x11_kill_cb_t)(pa_x11_wrapper *w, void *userdata);
+
/* Return the X11 wrapper for this core. In case no wrapper was
existant before, allocate a new one */
pa_x11_wrapper* pa_x11_wrapper_get(pa_core *c, const char *name);
@@ -43,10 +46,11 @@ void pa_x11_wrapper_unref(pa_x11_wrapper* w);
/* Return the X11 display object for this connection */
Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w);
-typedef struct pa_x11_client pa_x11_client;
+/* Kill the connection to the X11 display */
+void pa_x11_wrapper_kill(pa_x11_wrapper *w);
/* Register an X11 client, that is called for each X11 event */
-pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata);
+pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, pa_x11_event_cb_t event_cb, pa_x11_kill_cb_t kill_cb, void *userdata);
/* Free an X11 client object */
void pa_x11_client_free(pa_x11_client *c);