[pulseaudio-commits] 13 commits - po/POTFILES.in src/.gitignore src/Makefile.am src/modules src/pulse src/pulsecore src/tests src/utils
Arun Raghavan
arun at kemper.freedesktop.org
Wed Jun 22 08:39:06 UTC 2016
po/POTFILES.in | 1
src/.gitignore | 1
src/Makefile.am | 18 +
src/modules/alsa/alsa-sink.c | 9
src/modules/alsa/alsa-source.c | 9
src/modules/alsa/module-alsa-card.c | 8
src/modules/module-allow-passthrough.c | 312 +++++++++++++++++++++++++++++++++
src/modules/module-ladspa-sink.c | 5
src/pulse/context.c | 14 -
src/pulse/internal.h | 6
src/pulsecore/atomic.h | 2
src/pulsecore/core-util.c | 1
src/pulsecore/core-util.h | 4
src/pulsecore/protocol-native.c | 10 -
src/pulsecore/pstream.c | 4
src/pulsecore/sink-input.c | 6
src/pulsecore/sink.c | 6
src/pulsecore/source-output.c | 7
src/pulsecore/source.c | 6
src/tests/core-util-test.c | 282 +++++++++++++++++++++++++++++
src/utils/qpaeq | 8
21 files changed, 682 insertions(+), 37 deletions(-)
New commits:
commit d7ffbfd1dc210e716c8b744488af9666f36a0389
Author: John Paul Adrian Glaubitz <glaubitz at physik.fu-berlin.de>
Date: Mon May 16 20:53:13 2016 +0200
pulsecore: Fix incorrect architecture mapping on sparc64.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=95432
Signed-off-by: John Paul Adrian Glaubitz <glaubitz at physik.fu-berlin.de>
Signed-off-by: Arun Raghavan <arun at arunraghavan.net>
diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h
index 4758c84..7657144 100644
--- a/src/pulsecore/atomic.h
+++ b/src/pulsecore/atomic.h
@@ -201,7 +201,7 @@ static inline u_int atomic_fetchadd_int(volatile u_int *p, u_int v) {
return (v);
}
-#elif defined(__sparc64__)
+#elif defined(__sparc__) && defined(__arch64__)
#define atomic_load_acq_64 atomic_load_acq_long
#define atomic_fetchadd_int atomic_add_int
#elif defined(__ia64__)
commit a5f71d1c5453191d1a529633748cbdf69e16f665
Author: Juho Hämäläinen <jusa at hilvi.org>
Date: Fri May 13 17:39:41 2016 +0300
pulsecore: Don't allow unreferencing linked object.
Sink(-input) and source(-output) called unlink function when reference
count dropped to zero. This would result in unlink hooks being called
with an object having a reference count of zero, and this is not a
situation we want modules to have to deal with. It is better to just
remove the redundant unlinking code from sink(-input) and
source(-output) and assert on reference count in unlink functions as well.
It is expected that in well behaving code the owner of an object will
always unlink the object before unreferencing.
Signed-off-by: Arun Raghavan <arun at arunraghavan.net>
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index c7d99ef..a7f6d55 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -645,7 +645,7 @@ void pa_sink_input_unlink(pa_sink_input *i) {
bool linked;
pa_source_output *o, PA_UNUSED *p = NULL;
- pa_assert(i);
+ pa_sink_input_assert_ref(i);
pa_assert_ctl_context();
/* See pa_sink_unlink() for a couple of comments how this function
@@ -721,9 +721,7 @@ static void sink_input_free(pa_object *o) {
pa_assert(i);
pa_assert_ctl_context();
pa_assert(pa_sink_input_refcnt(i) == 0);
-
- if (PA_SINK_INPUT_IS_LINKED(i->state))
- pa_sink_input_unlink(i);
+ pa_assert(!PA_SINK_INPUT_IS_LINKED(i->state));
pa_log_info("Freeing input %u \"%s\"", i->index,
i->proplist ? pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)) : "");
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 3f1ef72..9bdf9be 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -669,7 +669,7 @@ void pa_sink_unlink(pa_sink* s) {
bool linked;
pa_sink_input *i, PA_UNUSED *j = NULL;
- pa_assert(s);
+ pa_sink_assert_ref(s);
pa_assert_ctl_context();
/* Please note that pa_sink_unlink() does more than simply
@@ -722,9 +722,7 @@ static void sink_free(pa_object *o) {
pa_assert(s);
pa_assert_ctl_context();
pa_assert(pa_sink_refcnt(s) == 0);
-
- if (PA_SINK_IS_LINKED(s->state))
- pa_sink_unlink(s);
+ pa_assert(!PA_SINK_IS_LINKED(s->state));
pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 6af1543..9e951ff 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -548,7 +548,8 @@ static void source_output_set_state(pa_source_output *o, pa_source_output_state_
/* Called from main context */
void pa_source_output_unlink(pa_source_output*o) {
bool linked;
- pa_assert(o);
+
+ pa_source_output_assert_ref(o);
pa_assert_ctl_context();
/* See pa_sink_unlink() for a couple of comments how this function
@@ -614,9 +615,7 @@ static void source_output_free(pa_object* mo) {
pa_assert(o);
pa_assert_ctl_context();
pa_assert(pa_source_output_refcnt(o) == 0);
-
- if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
- pa_source_output_unlink(o);
+ pa_assert(!PA_SOURCE_OUTPUT_IS_LINKED(o->state));
pa_log_info("Freeing output %u \"%s\"", o->index,
o->proplist ? pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME)) : "");
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 98374ae..8a527d8 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -612,7 +612,7 @@ void pa_source_unlink(pa_source *s) {
bool linked;
pa_source_output *o, PA_UNUSED *j = NULL;
- pa_assert(s);
+ pa_source_assert_ref(s);
pa_assert_ctl_context();
/* See pa_sink_unlink() for a couple of comments how this function
@@ -661,9 +661,7 @@ static void source_free(pa_object *o) {
pa_assert(s);
pa_assert_ctl_context();
pa_assert(pa_source_refcnt(s) == 0);
-
- if (PA_SOURCE_IS_LINKED(s->state))
- pa_source_unlink(s);
+ pa_assert(!PA_SOURCE_IS_LINKED(s->state));
pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
commit be4619e3f7b98a0595418bd7d13b7504ffb5136f
Author: Aidan Gauland <aidalgol at fastmail.net>
Date: Wed May 25 22:26:42 2016 +1200
qpaeq: Don't set font-size on widgets
Setting the font-size CSS property on a widget overrides the system
font-size, and since qpaeq provides no mechanism for setting the
application's font-size, we should not do this.
This commit also removes the font-size property from commented-out calls to
setStyleSheet() so that if these are ever reinstated, this behaviour is
not reintroduced.
Signed-off-by: Arun Raghavan <arun at arunraghavan.net>
diff --git a/src/utils/qpaeq b/src/utils/qpaeq
index 4b00e3a..ac4b9e4 100755
--- a/src/utils/qpaeq
+++ b/src/utils/qpaeq
@@ -299,7 +299,7 @@ class SliderArray(QtGui.QWidget):
def __init__(self,filter_state,parent=None):
super(SliderArray,self).__init__(parent)
#self.setStyleSheet('padding: 0px; border-width: 0px; margin: 0px;')
- #self.setStyleSheet('font-size: 7pt; font-family: monospace;'+outline%('blue'))
+ #self.setStyleSheet('font-family: monospace;'+outline%('blue'))
self.filter_state=filter_state
self.setLayout(QtGui.QHBoxLayout())
self.sub_array=None
@@ -367,7 +367,7 @@ class SliderArraySub(QtGui.QWidget):
self.slider=[None]*len(self.filter_state.frequencies)
self.label=[None]*len(self.slider)
#self.setStyleSheet('padding: 0px; border-width: 0px; margin: 0px;')
- #self.setStyleSheet('font-size: 7pt; font-family: monospace;'+outline%('blue'))
+ #self.setStyleSheet('font-family: monospace;'+outline%('blue'))
qt=QtCore.Qt
#self.layout().setHorizontalSpacing(1)
def add_slider(slider,label, c):
@@ -385,7 +385,7 @@ class SliderArraySub(QtGui.QWidget):
for i,hz in enumerate(self.filter_state.frequencies):
slider,label=create_slider(self.hz2label(hz))
self.slider[i]=slider
- #slider.setStyleSheet('font-size: 7pt; font-family: monospace;'+outline%('red',))
+ #slider.setStyleSheet('font-family: monospace;'+outline%('red',))
self.label[i]=label
c=i+1
add_slider(slider,label,i+1)
@@ -465,7 +465,7 @@ class SliderLabel(QtGui.QLabel):
clicked=QtCore.pyqtSignal()
def __init__(self,label_text,filter_state,parent=None):
super(SliderLabel,self).__init__(parent)
- self.setStyleSheet('font-size: 7pt; font-family: monospace;')
+ self.setStyleSheet('font-family: monospace;')
self.setText(label_text)
self.setMinimumSize(self.sizeHint())
def mouseDoubleClickEvent(self, event):
commit 81c8d380846ffb26d8529abb7a34db6428a2e8ef
Author: KimJeongYeon <jeongyeon.kim at samsung.com>
Date: Thu May 19 11:35:44 2016 +0900
ladspa-sink: avoid to configure invalid format
LADSPA allows float format only, but module-ladspa-sink possibly
could be loaded with ***any*** 'format' parameter. Therefore noisy
sound heard. This patch avoids to be configured as invalid format.
Signed-off-by: KimJeongYeon <jeongyeon.kim at samsung.com>
Signed-off-by: Arun Raghavan <arun at arunraghavan.net>
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 38b94e3..a6290b9 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -981,6 +981,11 @@ int pa__init(pa_module*m) {
goto fail;
}
+ if (ss.format != PA_SAMPLE_FLOAT32) {
+ pa_log("LADSPA accepts float format only");
+ goto fail;
+ }
+
if (!(plugin = pa_modargs_get_value(ma, "plugin", NULL))) {
pa_log("Missing LADSPA plugin name");
goto fail;
commit 111e332556ce98d52a73baad8f0b51e4885b8383
Author: Ulrich Eckhardt <ulrich.eckhardt at base-42.de>
Date: Mon May 16 19:51:05 2016 +0200
core-util: Improve pa_replace() behaviour
- Assert that the search string isn't empty.
- Add test.
- Improve documentation.
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index b6eb85a..f816da9 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -3194,6 +3194,7 @@ char *pa_replace(const char*s, const char*a, const char *b) {
pa_assert(s);
pa_assert(a);
+ pa_assert(*a);
pa_assert(b);
an = strlen(a);
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index d5a2d39..5725ca7 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -249,6 +249,10 @@ void pa_reduce(unsigned *num, unsigned *den);
unsigned pa_ncpus(void);
+/* Replaces all occurrences of `a' in `s' with `b'. The caller has to free the
+ * returned string. All parameters must be non-NULL and additionally `a' must
+ * not be a zero-length string.
+ */
char *pa_replace(const char*s, const char*a, const char *b);
/* Escapes p by inserting backslashes in front of backslashes. chars is a
diff --git a/src/tests/core-util-test.c b/src/tests/core-util-test.c
index d1470b4..c8e0fae 100644
--- a/src/tests/core-util-test.c
+++ b/src/tests/core-util-test.c
@@ -228,6 +228,11 @@ START_TEST (modargs_test_escape) {
}
END_TEST
+START_TEST (modargs_test_replace_fail_4) {
+ pa_replace("abe", "", "bab");
+}
+END_TEST
+
START_TEST (modargs_test_unescape) {
char* value;
@@ -264,6 +269,7 @@ int main(int argc, char *argv[]) {
tcase_add_test_raise_signal(tc, modargs_test_replace_fail_1, SIGABRT);
tcase_add_test_raise_signal(tc, modargs_test_replace_fail_2, SIGABRT);
tcase_add_test_raise_signal(tc, modargs_test_replace_fail_3, SIGABRT);
+ tcase_add_test_raise_signal(tc, modargs_test_replace_fail_4, SIGABRT);
tcase_add_test(tc, modargs_test_escape);
tcase_add_test(tc, modargs_test_unescape);
commit c9c8f4285f31fda5d3051832969983dfe0df1cab
Author: Ulrich Eckhardt <ulrich.eckhardt at base-42.de>
Date: Mon May 16 19:51:04 2016 +0200
core-util-test: Add tests
diff --git a/src/tests/core-util-test.c b/src/tests/core-util-test.c
index ae5457c..d1470b4 100644
--- a/src/tests/core-util-test.c
+++ b/src/tests/core-util-test.c
@@ -21,8 +21,226 @@
#include <check.h>
+#include <pulse/xmalloc.h>
#include <pulsecore/core-util.h>
+START_TEST (modargs_test_parse_boolean) {
+ ck_assert_int_eq(pa_parse_boolean("true"), true);
+ ck_assert_int_eq(pa_parse_boolean("yes"), true);
+ ck_assert_int_eq(pa_parse_boolean("1"), true);
+
+ ck_assert_int_eq(pa_parse_boolean("false"), false);
+ ck_assert_int_eq(pa_parse_boolean("no"), false);
+ ck_assert_int_eq(pa_parse_boolean("0"), false);
+
+ ck_assert_int_eq(pa_parse_boolean("maybe"), -1);
+ ck_assert_int_eq(pa_parse_boolean("42"), -1);
+}
+END_TEST
+
+START_TEST (modargs_test_parse_volume) {
+ pa_volume_t value;
+
+ // dB volumes
+ ck_assert_int_eq(pa_parse_volume("-20dB", &value), 0);
+ ck_assert_int_eq(value, 30419);
+ ck_assert_int_eq(pa_parse_volume("-10dB", &value), 0);
+ ck_assert_int_eq(value, 44649);
+ ck_assert_int_eq(pa_parse_volume("-1dB", &value), 0);
+ ck_assert_int_eq(value, 63069);
+ ck_assert_int_eq(pa_parse_volume("0dB", &value), 0);
+ ck_assert_int_eq(value, 65536);
+ ck_assert_int_eq(pa_parse_volume("1dB", &value), 0);
+ ck_assert_int_eq(value, 68100);
+ ck_assert_int_eq(pa_parse_volume("10dB", &value), 0);
+ ck_assert_int_eq(value, 96194);
+
+ // lowercase db
+ ck_assert_int_eq(pa_parse_volume("10db", &value), 0);
+ ck_assert_int_eq(value, 96194);
+
+ // percentage volumes
+ ck_assert_int_eq(pa_parse_volume("0%", &value), 0);
+ ck_assert_int_eq(value, 0);
+ ck_assert_int_eq(pa_parse_volume("50%", &value), 0);
+ ck_assert_int_eq(value, 32768);
+ ck_assert_int_eq(pa_parse_volume("100%", &value), 0);
+ ck_assert_int_eq(value, 65536);
+ ck_assert_int_eq(pa_parse_volume("150%", &value), 0);
+ ck_assert_int_eq(value, 98304);
+
+ // integer volumes`
+ ck_assert_int_eq(pa_parse_volume("0", &value), 0);
+ ck_assert_int_eq(value, 0);
+ ck_assert_int_eq(pa_parse_volume("100", &value), 0);
+ ck_assert_int_eq(value, 100);
+ ck_assert_int_eq(pa_parse_volume("1000", &value), 0);
+ ck_assert_int_eq(value, 1000);
+ ck_assert_int_eq(pa_parse_volume("65536", &value), 0);
+ ck_assert_int_eq(value, 65536);
+ ck_assert_int_eq(pa_parse_volume("100000", &value), 0);
+ ck_assert_int_eq(value, 100000);
+
+ // invalid volumes
+ ck_assert_int_lt(pa_parse_volume("", &value), 0);
+ ck_assert_int_lt(pa_parse_volume("-2", &value), 0);
+ ck_assert_int_lt(pa_parse_volume("on", &value), 0);
+ ck_assert_int_lt(pa_parse_volume("off", &value), 0);
+ ck_assert_int_lt(pa_parse_volume("none", &value), 0);
+}
+END_TEST
+
+START_TEST (modargs_test_atoi) {
+ int32_t value;
+
+ // decimal
+ ck_assert_int_eq(pa_atoi("100000", &value), 0);
+ ck_assert_int_eq(value, 100000);
+ ck_assert_int_eq(pa_atoi("-100000", &value), 0);
+ ck_assert_int_eq(value, -100000);
+
+ // hexadecimal
+ ck_assert_int_eq(pa_atoi("0x100000", &value), 0);
+ ck_assert_int_eq(value, 0x100000);
+ ck_assert_int_eq(pa_atoi("-0x100000", &value), 0);
+ ck_assert_int_eq(value, -0x100000);
+
+ // invalid values
+ ck_assert_int_lt(pa_atoi("3.14", &value), 0);
+ ck_assert_int_lt(pa_atoi("7*8", &value), 0);
+ ck_assert_int_lt(pa_atoi("false", &value), 0);
+}
+END_TEST
+
+START_TEST (modargs_test_atou) {
+ uint32_t value;
+
+ // decimal
+ ck_assert_int_eq(pa_atou("100000", &value), 0);
+ ck_assert_int_eq(value, 100000);
+
+ // hexadecimal
+ ck_assert_int_eq(pa_atou("0x100000", &value), 0);
+ ck_assert_int_eq(value, 0x100000);
+
+ // invalid values
+ ck_assert_int_lt(pa_atou("-100000", &value), 0);
+ ck_assert_int_lt(pa_atou("-0x100000", &value), 0);
+ ck_assert_int_lt(pa_atou("3.14", &value), 0);
+ ck_assert_int_lt(pa_atou("7*8", &value), 0);
+ ck_assert_int_lt(pa_atou("false", &value), 0);
+}
+END_TEST
+
+START_TEST (modargs_test_atol) {
+ long value;
+
+ // decimal
+ ck_assert_int_eq(pa_atol("100000", &value), 0);
+ ck_assert_int_eq(value, 100000l);
+ ck_assert_int_eq(pa_atol("-100000", &value), 0);
+ ck_assert_int_eq(value, -100000l);
+
+ // hexadecimal
+ ck_assert_int_eq(pa_atol("0x100000", &value), 0);
+ ck_assert_int_eq(value, 0x100000l);
+ ck_assert_int_eq(pa_atol("-0x100000", &value), 0);
+ ck_assert_int_eq(value, -0x100000l);
+
+ // invalid values
+ ck_assert_int_lt(pa_atol("3.14", &value), 0);
+ ck_assert_int_lt(pa_atol("7*8", &value), 0);
+ ck_assert_int_lt(pa_atol("false", &value), 0);
+}
+END_TEST
+
+START_TEST (modargs_test_atod) {
+ double value;
+ double epsilon = 0.001;
+
+ // decimal
+ ck_assert_int_eq(pa_atod("100000", &value), 0);
+ ck_assert(value > 100000 - epsilon);
+ ck_assert(value < 100000 + epsilon);
+ ck_assert_int_eq(pa_atod("-100000", &value), 0);
+ ck_assert(value > -100000 - epsilon);
+ ck_assert(value < -100000 + epsilon);
+ ck_assert_int_eq(pa_atod("3.14", &value), 0);
+ ck_assert(value > 3.14 - epsilon);
+ ck_assert(value < 3.14 + epsilon);
+
+ // invalid values
+ ck_assert_int_lt(pa_atod("7*8", &value), 0);
+ ck_assert_int_lt(pa_atod("false", &value), 0);
+}
+END_TEST
+
+START_TEST (modargs_test_replace) {
+ char* value;
+
+ value = pa_replace("abcde", "bcd", "XYZ");
+ ck_assert_str_eq(value, "aXYZe");
+ pa_xfree(value);
+
+ value = pa_replace("abe", "b", "bab");
+ ck_assert_str_eq(value, "ababe");
+ pa_xfree(value);
+
+ value = pa_replace("abe", "c", "bab");
+ ck_assert_str_eq(value, "abe");
+ pa_xfree(value);
+
+ value = pa_replace("abcde", "bcd", "");
+ ck_assert_str_eq(value, "ae");
+ pa_xfree(value);
+}
+END_TEST
+
+START_TEST (modargs_test_replace_fail_1) {
+ pa_replace(NULL, "b", "bab");
+}
+END_TEST
+
+START_TEST (modargs_test_replace_fail_2) {
+ pa_replace("abe", NULL, "bab");
+}
+END_TEST
+
+START_TEST (modargs_test_replace_fail_3) {
+ pa_replace("abcde", "b", NULL);
+}
+END_TEST
+
+START_TEST (modargs_test_escape) {
+ char* value;
+
+ value = pa_escape("abcde", "bcd");
+ ck_assert_str_eq(value, "a\\b\\c\\de");
+ pa_xfree(value);
+
+ value = pa_escape("\\", "bcd");
+ ck_assert_str_eq(value, "\\\\");
+ pa_xfree(value);
+
+ value = pa_escape("\\", NULL);
+ ck_assert_str_eq(value, "\\\\");
+ pa_xfree(value);
+}
+END_TEST
+
+START_TEST (modargs_test_unescape) {
+ char* value;
+
+ value = pa_unescape(pa_xstrdup("a\\b\\c\\de"));
+ ck_assert_str_eq(value, "abcde");
+ pa_xfree(value);
+
+ value = pa_unescape(pa_xstrdup("\\\\"));
+ ck_assert_str_eq(value, "\\");
+ pa_xfree(value);
+}
+END_TEST
+
int main(int argc, char *argv[]) {
int failed = 0;
Suite *s;
@@ -36,6 +254,18 @@ int main(int argc, char *argv[]) {
tc = tcase_create("core-util");
suite_add_tcase(s, tc);
+ tcase_add_test(tc, modargs_test_parse_boolean);
+ tcase_add_test(tc, modargs_test_parse_volume);
+ tcase_add_test(tc, modargs_test_atoi);
+ tcase_add_test(tc, modargs_test_atou);
+ tcase_add_test(tc, modargs_test_atol);
+ tcase_add_test(tc, modargs_test_atod);
+ tcase_add_test(tc, modargs_test_replace);
+ tcase_add_test_raise_signal(tc, modargs_test_replace_fail_1, SIGABRT);
+ tcase_add_test_raise_signal(tc, modargs_test_replace_fail_2, SIGABRT);
+ tcase_add_test_raise_signal(tc, modargs_test_replace_fail_3, SIGABRT);
+ tcase_add_test(tc, modargs_test_escape);
+ tcase_add_test(tc, modargs_test_unescape);
sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
commit e1bc4791104ce3814aa6963a539e98e6aec00b8a
Author: Ulrich Eckhardt <ulrich.eckhardt at base-42.de>
Date: Mon May 16 19:51:03 2016 +0200
core-util-test: Add boilerplate
diff --git a/src/.gitignore b/src/.gitignore
index 8a5dfb0..bfe74bd 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -35,6 +35,7 @@ asyncq-test
channelmap-test
close-test
connect-stress
+core-util-test
cpulimit-test
cpulimit-test2
cpu-sconv-test
diff --git a/src/Makefile.am b/src/Makefile.am
index adaa38b..a311575 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -240,6 +240,7 @@ endif
noinst_LTLIBRARIES =
TESTS_default = \
+ core-util-test \
mainloop-test \
strlist-test \
close-test \
@@ -355,6 +356,11 @@ check-daemon:
endif
+core_util_test_SOURCES = tests/core-util-test.c
+core_util_test_CFLAGS = $(AM_CFLAGS) $(LIBCHECK_CFLAGS)
+core_util_test_LDADD = $(AM_LDADD) libpulse.la libpulsecommon- at PA_MAJORMINOR@.la
+core_util_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBCHECK_LIBS)
+
mainloop_test_SOURCES = tests/mainloop-test.c
mainloop_test_CFLAGS = $(AM_CFLAGS) $(LIBCHECK_CFLAGS)
mainloop_test_LDADD = $(AM_LDADD) libpulse.la libpulsecommon- at PA_MAJORMINOR@.la
diff --git a/src/tests/core-util-test.c b/src/tests/core-util-test.c
new file mode 100644
index 0000000..ae5457c
--- /dev/null
+++ b/src/tests/core-util-test.c
@@ -0,0 +1,46 @@
+/***
+ This file is part of PulseAudio.
+
+ 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <check.h>
+
+#include <pulsecore/core-util.h>
+
+int main(int argc, char *argv[]) {
+ int failed = 0;
+ Suite *s;
+ TCase *tc;
+ SRunner *sr;
+
+ if (!getenv("MAKE_CHECK"))
+ pa_log_set_level(PA_LOG_DEBUG);
+
+ s = suite_create("Core-Util");
+
+ tc = tcase_create("core-util");
+ suite_add_tcase(s, tc);
+
+ sr = srunner_create(s);
+ srunner_run_all(sr, CK_NORMAL);
+ failed = srunner_ntests_failed(sr);
+ srunner_free(sr);
+
+ return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
commit 6f0e39d30f54d1f98802ea97d9cfbcfc64dd6076
Author: Tanu Kaskinen <tanuk at iki.fi>
Date: Wed May 25 14:13:42 2016 +0300
pstream: fix revoke callback setting
While investigating bug 95352, I noticed that
pa_pstream_set_revoke_callback() and pa_pstream_set_release_callback()
were identical - both set the release callback.
pa_pstream_set_revoke_callback() was obviously broken - it was setting
the wrong callback.
The only place where set_revoke_callback() is called is in
protocol-native.c. The code there looks like this:
pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
Since set_release_callback() is called last, the release callback gets
set correctly. The only problem is that the revoke callback stays
unset. What are the consequences of that? The code that calls the
revoke callback looks like this:
if (p->revoke_callback)
p->revoke_callback(p, block_id, p->revoke_callback_userdata);
else
pa_pstream_send_revoke(p, block_id);
So the intended callback is replaced with a pa_pstream_send_revoke()
call. What does the intended callback, that doesn't get called, do?
if (!(q = pa_thread_mq_get()))
pa_pstream_send_revoke(p, block_id);
else
pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
So the native protocol's revoke callback is anyway going to call
pa_pstream_send_revoke() when called from the main thread. If the
revoking is done from an IO thread, an asynchronous message is sent to
the main thread instead, and the message handler will then call
pa_pstream_send_revoke().
In conclusion, the only effect of this bug was that
pa_pstream_send_revoke() was sometimes being called from an IO thread
when it should have been called from the main thread. I don't know if
this caused the crash in bug 95352. Probably not.
diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index bbff2f6..2c9e452 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -1119,8 +1119,8 @@ void pa_pstream_set_revoke_callback(pa_pstream *p, pa_pstream_block_id_cb_t cb,
pa_assert(p);
pa_assert(PA_REFCNT_VALUE(p) > 0);
- p->release_callback = cb;
- p->release_callback_userdata = userdata;
+ p->revoke_callback = cb;
+ p->revoke_callback_userdata = userdata;
}
bool pa_pstream_is_pending(pa_pstream *p) {
commit 768c80f3c35da28f10a293ffa62c0e092db65db5
Author: Alexander E. Patrakov <patrakov at gmail.com>
Date: Sun May 22 02:03:21 2016 +0500
alsa: reread configuration when opening new devices
If a card has been hot-plugged after pulseaudio start, alsa-lib still has
old configuration in memory, which doesn't have PCM definitions for the
new card. Thus, this error appears, and the device doesn't work:
I: [pulseaudio] (alsa-lib)confmisc.c: Unable to find definition 'cards.USB-Audio.pcm.front.0:CARD=0'
I: [pulseaudio] (alsa-lib)conf.c: function snd_func_refer returned error: No such file or directory
I: [pulseaudio] (alsa-lib)conf.c: Evaluate error: No such file or directory
I: [pulseaudio] (alsa-lib)pcm.c: Unknown PCM front:0
I: [pulseaudio] alsa-util.c: Error opening PCM device front:0: No such file or directory
The snd_config_update_free_global() function makes alsa-lib forget any
cached configuration and reparse all PCM definitions from scratch next
time it is told to open anything.
The trick has been copied from Phonon.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=54029
Signed-off-by: Alexander E. Patrakov <patrakov at gmail.com>
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 2fdebe0..63674e2 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -2146,6 +2146,15 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
b = use_mmap;
d = use_tsched;
+ /* Force ALSA to reread its configuration if module-alsa-card didn't
+ * do it for us. This matters if our device was hot-plugged after ALSA
+ * has already read its configuration - see
+ * https://bugs.freedesktop.org/show_bug.cgi?id=54029
+ */
+
+ if (!card)
+ snd_config_update_free_global();
+
if (mapping) {
if (!(dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 4683dfe..0820b48 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1854,6 +1854,15 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
b = use_mmap;
d = use_tsched;
+ /* Force ALSA to reread its configuration if module-alsa-card didn't
+ * do it for us. This matters if our device was hot-plugged after ALSA
+ * has already read its configuration - see
+ * https://bugs.freedesktop.org/show_bug.cgi?id=54029
+ */
+
+ if (!card)
+ snd_config_update_free_global();
+
if (mapping) {
if (!(dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index e5cc4ae..adb942b 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -715,6 +715,14 @@ int pa__init(pa_module *m) {
}
pa_modargs_get_value_boolean(u->modargs, "use_ucm", &u->use_ucm);
+
+ /* Force ALSA to reread its configuration. This matters if our device
+ * was hot-plugged after ALSA has already read its configuration - see
+ * https://bugs.freedesktop.org/show_bug.cgi?id=54029
+ */
+
+ snd_config_update_free_global();
+
if (u->use_ucm && !pa_alsa_ucm_query_profiles(&u->ucm, u->alsa_card_index)) {
pa_log_info("Found UCM profiles");
commit 4c42b3ef7c3fca21d9decfe8a1ea283665796329
Author: Arun Raghavan <git at arunraghavan.net>
Date: Mon May 9 07:47:19 2016 +0530
i18n: Add module-allow-passthrough to POTFILES.in
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0903741..e2d6d11 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -22,6 +22,7 @@ src/modules/gconf/module-gconf.c
src/modules/jack/module-jack-sink.c
src/modules/jack/module-jack-source.c
src/modules/macosx/module-coreaudio-device.c
+src/modules/module-allow-passthrough.c
src/modules/module-always-sink.c
src/modules/module-cli.c
src/modules/module-combine.c
commit 0985a717f30faff74657eb292aac7f73e59eb162
Author: Arun Raghavan <git at arunraghavan.net>
Date: Sat May 7 13:42:34 2016 +0530
allow-passthrough: Use pa_module_hook_connect()
Signed-off-by: Arun Raghavan <git at arunraghavan.net>
diff --git a/src/modules/module-allow-passthrough.c b/src/modules/module-allow-passthrough.c
index 3b56c1f..4b801e4 100644
--- a/src/modules/module-allow-passthrough.c
+++ b/src/modules/module-allow-passthrough.c
@@ -51,12 +51,6 @@ struct userdata {
* its streams. */
pa_hashmap *null_sinks;
- pa_hook_slot
- *sink_input_new_slot,
- *sink_input_unlink_slot,
- *sink_input_move_start_slot,
- *sink_input_move_finish_slot;
-
bool moving;
};
@@ -281,10 +275,10 @@ int pa__init(pa_module*m) {
u->null_sinks = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
- u->sink_input_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_new_cb, u);
- u->sink_input_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_unlink_cb, u);
- u->sink_input_move_start_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_start_cb, u);
- u->sink_input_move_finish_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_finish_cb, u);
+ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_new_cb, u);
+ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_unlink_cb, u);
+ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_start_cb, u);
+ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_finish_cb, u);
u->moving = false;
@@ -308,15 +302,6 @@ void pa__done(pa_module*m) {
if (!(u = m->userdata))
return;
- if (u->sink_input_new_slot)
- pa_hook_slot_free(u->sink_input_new_slot);
- if (u->sink_input_unlink_slot)
- pa_hook_slot_free(u->sink_input_unlink_slot);
- if (u->sink_input_move_start_slot)
- pa_hook_slot_free(u->sink_input_move_start_slot);
- if (u->sink_input_move_finish_slot)
- pa_hook_slot_free(u->sink_input_move_finish_slot);
-
if (m->core->state != PA_CORE_SHUTDOWN)
unload_all_null_sink_modules(u, m->core);
commit 14804ba1ca4cfb58f2e8a9afa9ca87b309fa8d42
Author: Guillaume Desmottes <guillaume.desmottes at collabora.co.uk>
Date: Fri Mar 18 15:28:12 2016 +0100
allow-passthrough: Add module to allow passthrough streams always go through
For various use-cases a passthrough stream should have priority over all
other streams and get exclusive access to the sink regardless of whether
any other streams are playing.
An example use-case is ensuring Kodi can successfully start video
playback (with passthrough) even if an external notification sound
happened to be playing at the same time.
Signed-off-by: Arun Raghavan <git at arunraghavan.net>
diff --git a/src/Makefile.am b/src/Makefile.am
index b600dfb..adaa38b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1205,7 +1205,8 @@ modlibexec_LTLIBRARIES += \
module-switch-on-port-available.la \
module-filter-apply.la \
module-filter-heuristics.la \
- module-role-ducking.la
+ module-role-ducking.la \
+ module-allow-passthrough.la
if HAVE_ESOUND
modlibexec_LTLIBRARIES += \
@@ -1548,7 +1549,8 @@ SYMDEF_FILES = \
module-switch-on-connect-symdef.h \
module-switch-on-port-available-symdef.h \
module-filter-apply-symdef.h \
- module-filter-heuristics-symdef.h
+ module-filter-heuristics-symdef.h \
+ module-allow-passthrough-symdef.h
if HAVE_ESOUND
SYMDEF_FILES += \
@@ -2207,6 +2209,12 @@ module_rygel_media_server_la_LDFLAGS = $(MODULE_LDFLAGS)
module_rygel_media_server_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) libprotocol-http.la
module_rygel_media_server_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
+# Allow passthrough module
+module_allow_passthrough_la_SOURCES = modules/module-allow-passthrough.c
+module_allow_passthrough_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_allow_passthrough_la_LIBADD = $(MODULE_LIBADD)
+module_allow_passthrough_la_CFLAGS = $(AM_CFLAGS)
+
###################################
# Some minor stuff #
###################################
diff --git a/src/modules/module-allow-passthrough.c b/src/modules/module-allow-passthrough.c
new file mode 100644
index 0000000..3b56c1f
--- /dev/null
+++ b/src/modules/module-allow-passthrough.c
@@ -0,0 +1,327 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright (C) 2014 Collabora Ltd. <http://www.collabora.co.uk/>
+
+ 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulse/xmalloc.h>
+
+#include <pulsecore/core.h>
+#include <pulsecore/i18n.h>
+#include <pulsecore/sink-input.h>
+#include <pulsecore/source-output.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/log.h>
+#include <pulsecore/namereg.h>
+#include <pulsecore/core-util.h>
+
+#include "module-allow-passthrough-symdef.h"
+
+PA_MODULE_AUTHOR("Guillaume Desmottes");
+PA_MODULE_DESCRIPTION("When a passthrough stream is requested, route all the other streams to a dummy device");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(true);
+
+static const char* const valid_modargs[] = {
+ NULL,
+};
+
+struct userdata {
+ /* (pa_sink *) -> (pa_sink *)
+ * Map the 'real' muted sink to the null-sink currently being used to play
+ * its streams. */
+ pa_hashmap *null_sinks;
+
+ pa_hook_slot
+ *sink_input_new_slot,
+ *sink_input_unlink_slot,
+ *sink_input_move_start_slot,
+ *sink_input_move_finish_slot;
+
+ bool moving;
+};
+
+static pa_sink *ensure_null_sink_for_sink(struct userdata *u, pa_sink *s, pa_core *c) {
+ char *t;
+ pa_module *m;
+ pa_sink *sink;
+ uint32_t idx;
+ const char *name;
+
+ sink = pa_hashmap_get(u->null_sinks, s);
+ if (sink != NULL) {
+ /* We already have a null-sink for this sink */
+ return sink;
+ }
+
+ name = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME);
+
+ t = pa_sprintf_malloc("sink_name=allow_passthrough_null_%s sink_properties='device.description=\"%s\"'",
+ name ? name : "", _("Dummy Output"));
+ m = pa_module_load(c, "module-null-sink", t);
+ pa_xfree(t);
+
+ if (m == NULL)
+ return NULL;
+
+ PA_IDXSET_FOREACH(sink, c->sinks, idx) {
+ if (sink->module->index == m->index) {
+ pa_hashmap_put(u->null_sinks, s, sink);
+ return sink;
+ }
+ }
+
+ return NULL;
+}
+
+static void unload_null_sink_module_for_sink(struct userdata *u, pa_sink *s, pa_core *c) {
+ pa_sink *null_sink;
+
+ null_sink = pa_hashmap_get(u->null_sinks, s);
+ if (null_sink == NULL)
+ return;
+
+ pa_module_unload_request_by_index(c, null_sink->module->index, true);
+
+ pa_hashmap_remove(u->null_sinks, s);
+}
+
+static void move_stream(struct userdata *u, pa_sink_input *i, pa_sink *target) {
+ u->moving = true;
+ if (pa_sink_input_move_to(i, target, false) < 0)
+ pa_log_info("Failed to move sink input %u \"%s\" to %s.", i->index,
+ pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name);
+ else
+ pa_log_info("Successfully moved sink input %u \"%s\" to %s.", i->index,
+ pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name);
+ u->moving = false;
+}
+
+/* Check if @sink has any passthrough stream, ignoring @ignore */
+static bool sink_has_passthrough_stream(pa_sink *sink, pa_sink_input *ignore)
+{
+ pa_sink_input *stream;
+ uint32_t idx;
+
+ PA_IDXSET_FOREACH(stream, sink->inputs, idx) {
+ if (stream == ignore)
+ continue;
+
+ if (pa_sink_input_is_passthrough(stream))
+ return true;
+ }
+
+ return false;
+}
+
+static pa_hook_result_t new_passthrough_stream(struct userdata *u, pa_core *c, pa_sink *sink, pa_sink_input *i) {
+ uint32_t idx;
+ pa_sink_input *stream;
+ pa_sink *null_sink;
+
+ if (sink_has_passthrough_stream(sink, i)) {
+ pa_log_info("Dropping playing a passthrough stream; ignoring");
+ /* PulseAudio will reject the stream itself */
+ return PA_HOOK_OK;
+ }
+
+ pa_log_info("Just received a passthrough stream; pause all the others streams so it can play");
+
+ null_sink = ensure_null_sink_for_sink(u, sink, c);
+ if (null_sink == NULL)
+ return PA_HOOK_OK;
+
+ PA_IDXSET_FOREACH(stream, sink->inputs, idx) {
+ /* We don't want to move the stream which just moved to the sink and trigger this re-routing */
+ if (stream != i)
+ move_stream(u, stream, null_sink);
+ }
+
+ return PA_HOOK_OK;
+}
+
+/* return a null sink for the new stream if it needs to be re-routed */
+static pa_sink * new_normal_stream(struct userdata *u, pa_core *c, pa_sink *sink) {
+ if (!sink_has_passthrough_stream(sink, NULL))
+ return NULL;
+
+ /* A passthrough stream is already playing on this sink, re-route to a null sink */
+ return ensure_null_sink_for_sink(u, sink, c);
+}
+
+static pa_hook_result_t sink_input_new_cb(pa_core *core, pa_sink_input_new_data *new_data, struct userdata *u) {
+ pa_sink *null_sink;
+
+ pa_core_assert_ref(core);
+ /* This is a bit of a hack, to determine whether the input stream will use
+ * a passthrough stream, the sink should have been selected and a format
+ * renegotiated. This can either happen by an earlier module (e.g. one
+ * doing routing or other policies) and if not pulseaudio core will setup
+ * the defaults after all hooks for this event have been processed.
+ *
+ * Unfortunately if no other module decides on sink/format before this hook
+ * runs, pulse core doing it is too late, so if a sink and/or stream format
+ * haven't been setup & configured just yet do so now using the same code
+ * as pulsecore would use (default sink and higher priority negotiated
+ * format). */
+ if (!new_data->sink) {
+ pa_sink *sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK);
+ pa_return_val_if_fail(sink, -PA_ERR_NOENTITY);
+ pa_sink_input_new_data_set_sink(new_data, sink, false);
+ }
+
+ if (!new_data->format && new_data->nego_formats && !pa_idxset_isempty(new_data->nego_formats))
+ new_data->format = pa_format_info_copy(pa_idxset_first(new_data->nego_formats, NULL));
+
+ if (pa_sink_input_new_data_is_passthrough(new_data))
+ return new_passthrough_stream(u, core, new_data->sink, NULL);
+
+ null_sink = new_normal_stream(u, core, new_data->sink);
+
+ if (null_sink) {
+ pa_log_info("Already playing a passthrough stream; re-routing new stream to the null sink");
+ pa_sink_input_new_data_set_sink(new_data, null_sink, false);
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t passthrough_stream_removed(struct userdata *u, pa_core *c, pa_sink_input *i) {
+ uint32_t idx;
+ pa_sink_input *stream;
+ pa_sink *null_sink;
+
+ pa_assert(i->sink);
+
+ null_sink = pa_hashmap_get(u->null_sinks, i->sink);
+ if (null_sink == NULL)
+ return PA_HOOK_OK;
+
+ pa_log_info("Passthrough stream removed; restore all streams");
+
+ PA_IDXSET_FOREACH(stream, null_sink->inputs, idx) {
+ move_stream(u, stream, i->sink);
+ }
+
+ unload_null_sink_module_for_sink(u, i->sink, c);
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_input_removed(pa_core *core, pa_sink_input *i, struct userdata *u) {
+ pa_sink_input_assert_ref(i);
+
+ if (pa_sink_input_is_passthrough(i))
+ return passthrough_stream_removed(u, core, i);
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_input_unlink_cb(pa_core *core, pa_sink_input *i, struct userdata *u) {
+ return sink_input_removed(core, i, u);
+}
+
+static pa_hook_result_t sink_input_move_start_cb(pa_core *core, pa_sink_input *i, struct userdata *u) {
+ if (u->moving)
+ return PA_HOOK_OK;
+
+ return sink_input_removed(core, i, u);
+}
+
+static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input *i, struct userdata *u) {
+ pa_sink *null_sink;
+
+ if (u->moving)
+ return PA_HOOK_OK;
+
+ if (pa_sink_input_is_passthrough(i))
+ /* Passthrough stream has been moved to a new sink */
+ return new_passthrough_stream(u, core, i->sink, i);
+
+ null_sink = new_normal_stream(u, core, i->sink);
+ if (null_sink) {
+ pa_log_info("Already playing a passthrough stream; re-routing moved stream to the null sink");
+ move_stream(u, i, null_sink);
+ }
+
+ return PA_HOOK_OK;
+}
+
+int pa__init(pa_module*m) {
+ pa_modargs *ma;
+ struct userdata *u;
+
+ pa_assert(m);
+
+ if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+ pa_log("Failed to parse module arguments");
+ return -1;
+ }
+
+ m->userdata = u = pa_xnew(struct userdata, 1);
+
+ u->null_sinks = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+
+ u->sink_input_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_new_cb, u);
+ u->sink_input_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_unlink_cb, u);
+ u->sink_input_move_start_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_start_cb, u);
+ u->sink_input_move_finish_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_finish_cb, u);
+
+ u->moving = false;
+
+ pa_modargs_free(ma);
+ return 0;
+}
+
+static void unload_all_null_sink_modules(struct userdata *u, pa_core *c) {
+ void *state = NULL;
+ pa_sink *null_sink;
+
+ PA_HASHMAP_FOREACH(null_sink, u->null_sinks, state)
+ pa_module_unload_request_by_index(c, null_sink->module->index, true);
+}
+
+void pa__done(pa_module*m) {
+ struct userdata *u;
+
+ pa_assert(m);
+
+ if (!(u = m->userdata))
+ return;
+
+ if (u->sink_input_new_slot)
+ pa_hook_slot_free(u->sink_input_new_slot);
+ if (u->sink_input_unlink_slot)
+ pa_hook_slot_free(u->sink_input_unlink_slot);
+ if (u->sink_input_move_start_slot)
+ pa_hook_slot_free(u->sink_input_move_start_slot);
+ if (u->sink_input_move_finish_slot)
+ pa_hook_slot_free(u->sink_input_move_finish_slot);
+
+ if (m->core->state != PA_CORE_SHUTDOWN)
+ unload_all_null_sink_modules(u, m->core);
+
+ if (u->null_sinks)
+ pa_hashmap_free(u->null_sinks);
+
+ pa_xfree(u);
+}
commit 7ac5390042e0bc2c060bb29bceef0b0d8344f4b7
Author: Arun Raghavan <git at arunraghavan.net>
Date: Mon Apr 25 18:12:39 2016 +0530
client, protocol-native: Use macros for protocol version/flag access
This makes it easier to read and cleaner in general.
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 69be5f4..c39cbe7 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -504,17 +504,17 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
/* 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);
+ if ((c->version & PA_PROTOCOL_VERSION_MASK) >= 13) {
+ shm_on_remote = !!(c->version & PA_PROTOCOL_FLAG_SHM);
/* Starting with protocol version 31, the second MSB of the version
* tag reflects whether memfd is supported on the other PA end. */
- if (c->version >= 31)
- memfd_on_remote = !!(c->version & 0x40000000U);
+ if ((c->version & PA_PROTOCOL_VERSION_MASK) >= 31)
+ memfd_on_remote = !!(c->version & PA_PROTOCOL_FLAG_MEMFD);
/* Reserve the two most-significant _bytes_ of the version tag
* for flags. */
- c->version &= 0x0000FFFFU;
+ c->version &= PA_PROTOCOL_VERSION_MASK;
}
pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
@@ -629,8 +629,8 @@ static void setup_context(pa_context *c, pa_iochannel *io) {
/* Starting with protocol version 13 we use the MSB of the version
* tag for informing the other side if we could do SHM or not.
* Starting from version 31, second MSB is used to flag memfd support. */
- pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION | (c->do_shm ? 0x80000000U : 0) |
- (c->memfd_on_local ? 0x40000000 : 0));
+ pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION | (c->do_shm ? PA_PROTOCOL_FLAG_SHM : 0) |
+ (c->memfd_on_local ? PA_PROTOCOL_FLAG_MEMFD: 0));
pa_tagstruct_put_arbitrary(t, cookie, sizeof(cookie));
#ifdef HAVE_CREDS
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index 9bbb903..01d2b6e 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -49,6 +49,12 @@
#define DEFAULT_TIMEOUT (30)
+#define PA_PROTOCOL_FLAG_MASK 0xFFFF0000U
+#define PA_PROTOCOL_VERSION_MASK 0x0000FFFFU
+
+#define PA_PROTOCOL_FLAG_SHM 0x80000000U
+#define PA_PROTOCOL_FLAG_MEMFD 0x40000000U
+
struct pa_context {
PA_REFCNT_DECLARE;
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 5619b9c..594617e 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2718,17 +2718,17 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
/* Starting with protocol version 13 the MSB of the version tag
reflects if shm is available for this pa_native_connection or
not. */
- if (c->version >= 13) {
- shm_on_remote = !!(c->version & 0x80000000U);
+ if ((c->version & PA_PROTOCOL_VERSION_MASK) >= 13) {
+ shm_on_remote = !!(c->version & PA_PROTOCOL_FLAG_SHM);
/* Starting with protocol version 31, the second MSB of the version
* tag reflects whether memfd is supported on the other PA end. */
- if (c->version >= 31)
- memfd_on_remote = !!(c->version & 0x40000000U);
+ if ((c->version & PA_PROTOCOL_VERSION_MASK) >= 31)
+ memfd_on_remote = !!(c->version & PA_PROTOCOL_FLAG_MEMFD);
/* Reserve the two most-significant _bytes_ of the version tag
* for flags. */
- c->version &= 0x0000FFFFU;
+ c->version &= PA_PROTOCOL_VERSION_MASK;
}
pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
More information about the pulseaudio-commits
mailing list