summaryrefslogtreecommitdiffstats
path: root/src/pulsecore
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulsecore')
-rw-r--r--src/pulsecore/cli-text.c8
-rw-r--r--src/pulsecore/core-scache.c22
-rw-r--r--src/pulsecore/core-scache.h2
-rw-r--r--src/pulsecore/core.c41
-rw-r--r--src/pulsecore/core.h9
-rw-r--r--src/pulsecore/envelope.c1
-rw-r--r--src/pulsecore/idxset.c42
-rw-r--r--src/pulsecore/log.c3
-rw-r--r--src/pulsecore/ltdl-helper.c6
-rw-r--r--src/pulsecore/macro.h16
-rw-r--r--src/pulsecore/module.c20
-rw-r--r--src/pulsecore/namereg.c17
-rw-r--r--src/pulsecore/namereg.h2
-rw-r--r--src/pulsecore/play-memblockq.c2
-rw-r--r--src/pulsecore/proplist-util.c53
-rw-r--r--src/pulsecore/protocol-esound.c4
-rw-r--r--src/pulsecore/protocol-native.c45
-rw-r--r--src/pulsecore/protocol-simple.c4
-rw-r--r--src/pulsecore/shared.c26
-rw-r--r--src/pulsecore/shared.h6
-rw-r--r--src/pulsecore/sink-input.c99
-rw-r--r--src/pulsecore/sink-input.h6
-rw-r--r--src/pulsecore/sink.c88
-rw-r--r--src/pulsecore/sound-file-stream.c2
-rw-r--r--src/pulsecore/source-output.c82
-rw-r--r--src/pulsecore/source-output.h6
-rw-r--r--src/pulsecore/source.c41
27 files changed, 371 insertions, 282 deletions
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 57129d0c..8ca8f2d9 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -421,7 +421,7 @@ char *pa_source_output_list_to_string(pa_core *c) {
s,
" index: %u\n"
"\tdriver: <%s>\n"
- "\tflags: %s%s%s%s%s%s%s%s\n"
+ "\tflags: %s%s%s%s%s%s%s%s%s%s\n"
"\tstate: %s\n"
"\tsource: %u <%s>\n"
"\tcurrent latency: %0.2f ms\n"
@@ -439,6 +439,8 @@ char *pa_source_output_list_to_string(pa_core *c) {
o->flags & PA_SOURCE_OUTPUT_FIX_FORMAT ? "FIX_FORMAT " : "",
o->flags & PA_SOURCE_OUTPUT_FIX_RATE ? "FIX_RATE " : "",
o->flags & PA_SOURCE_OUTPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "",
+ o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND ? "DONT_INHIBIT_AUTO_SUSPEND " : "",
+ o->flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND ? "FAIL_ON_SUSPEND " : "",
state_table[pa_source_output_get_state(o)],
o->source->index, o->source->name,
(double) pa_source_output_get_latency(o, NULL) / PA_USEC_PER_MSEC,
@@ -498,7 +500,7 @@ char *pa_sink_input_list_to_string(pa_core *c) {
s,
" index: %u\n"
"\tdriver: <%s>\n"
- "\tflags: %s%s%s%s%s%s%s%s\n"
+ "\tflags: %s%s%s%s%s%s%s%s%s%s\n"
"\tstate: %s\n"
"\tsink: %u <%s>\n"
"\tvolume: %s\n"
@@ -520,6 +522,8 @@ char *pa_sink_input_list_to_string(pa_core *c) {
i->flags & PA_SINK_INPUT_FIX_FORMAT ? "FIX_FORMAT " : "",
i->flags & PA_SINK_INPUT_FIX_RATE ? "FIX_RATE " : "",
i->flags & PA_SINK_INPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "",
+ i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND ? "DONT_INHIBIT_AUTO_SUSPEND " : "",
+ i->flags & PA_SINK_INPUT_FAIL_ON_SUSPEND ? "FAIL_ON_SUSPEND " : "",
state_table[pa_sink_input_get_state(i)],
i->sink->index, i->sink->name,
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)),
diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index 6d2ae932..e5489415 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -120,9 +120,6 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
e->core = c;
e->proplist = pa_proplist_new();
- if (!c->scache)
- c->scache = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
-
pa_idxset_put(c->scache, e, &e->index);
pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index);
@@ -287,23 +284,18 @@ int pa_scache_remove_item(pa_core *c, const char *name) {
return 0;
}
-static void free_cb(void *p, void *userdata) {
- pa_scache_entry *e = p;
- pa_assert(e);
-
- free_entry(e);
-}
+void pa_scache_free_all(pa_core *c) {
+ pa_scache_entry *e;
-void pa_scache_free(pa_core *c) {
pa_assert(c);
- if (c->scache) {
- pa_idxset_free(c->scache, free_cb, NULL);
- c->scache = NULL;
- }
+ while ((e = pa_idxset_steal_first(c->scache, NULL)))
+ free_entry(e);
- if (c->scache_auto_unload_event)
+ if (c->scache_auto_unload_event) {
c->mainloop->time_free(c->scache_auto_unload_event);
+ c->scache_auto_unload_event = NULL;
+ }
}
int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx) {
diff --git a/src/pulsecore/core-scache.h b/src/pulsecore/core-scache.h
index a75f8aca..1fe3c309 100644
--- a/src/pulsecore/core-scache.h
+++ b/src/pulsecore/core-scache.h
@@ -58,7 +58,7 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname);
int pa_scache_remove_item(pa_core *c, const char *name);
int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx);
int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_name, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx);
-void pa_scache_free(pa_core *c);
+void pa_scache_free_all(pa_core *c);
const char *pa_scache_get_name_by_id(pa_core *c, uint32_t id);
uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name);
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 689fc8f8..5fd2bdfb 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -92,21 +92,22 @@ pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) {
c->state = PA_CORE_STARTUP;
c->mainloop = m;
+
c->clients = pa_idxset_new(NULL, NULL);
+ c->cards = pa_idxset_new(NULL, NULL);
c->sinks = pa_idxset_new(NULL, NULL);
c->sources = pa_idxset_new(NULL, NULL);
- c->source_outputs = pa_idxset_new(NULL, NULL);
c->sink_inputs = pa_idxset_new(NULL, NULL);
- c->cards = pa_idxset_new(NULL, NULL);
+ c->source_outputs = pa_idxset_new(NULL, NULL);
+ c->modules = pa_idxset_new(NULL, NULL);
+ c->scache = pa_idxset_new(NULL, NULL);
+
+ c->namereg = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+ c->shared = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
c->default_source = NULL;
c->default_sink = NULL;
- c->modules = NULL;
- c->namereg = NULL;
- c->scache = NULL;
- c->running_as_daemon = FALSE;
-
c->default_sample_spec.format = PA_SAMPLE_S16NE;
c->default_sample_spec.rate = 44100;
c->default_sample_spec.channels = 2;
@@ -128,22 +129,20 @@ pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) {
c->exit_idle_time = -1;
c->scache_idle_time = 20;
- c->flat_volumes = TRUE;
-
- c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3;
+ c->flat_volumes = TRUE;
c->disallow_module_loading = FALSE;
c->disallow_exit = FALSE;
+ c->running_as_daemon = FALSE;
c->realtime_scheduling = FALSE;
c->realtime_priority = 5;
c->disable_remixing = FALSE;
c->disable_lfe_remixing = FALSE;
+ c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3;
for (j = 0; j < PA_CORE_HOOK_MAX; j++)
pa_hook_init(&c->hooks[j], c);
- pa_shared_init(c);
-
pa_random(&c->cookie, sizeof(c->cookie));
#ifdef SIGPIPE
@@ -165,7 +164,13 @@ static void core_free(pa_object *o) {
c->state = PA_CORE_SHUTDOWN;
pa_module_unload_all(c);
- pa_assert(!c->modules);
+ pa_scache_free_all(c);
+
+ pa_assert(pa_idxset_isempty(c->scache));
+ pa_idxset_free(c->scache, NULL, NULL);
+
+ pa_assert(pa_idxset_isempty(c->modules));
+ pa_idxset_free(c->modules, NULL, NULL);
pa_assert(pa_idxset_isempty(c->clients));
pa_idxset_free(c->clients, NULL, NULL);
@@ -185,8 +190,12 @@ static void core_free(pa_object *o) {
pa_assert(pa_idxset_isempty(c->sink_inputs));
pa_idxset_free(c->sink_inputs, NULL, NULL);
- pa_scache_free(c);
- pa_namereg_free(c);
+ pa_assert(pa_hashmap_isempty(c->namereg));
+ pa_hashmap_free(c->namereg, NULL, NULL);
+
+ pa_assert(pa_hashmap_isempty(c->shared));
+ pa_hashmap_free(c->shared, NULL, NULL);
+
pa_subscription_free_all(c);
if (c->exit_event)
@@ -198,8 +207,6 @@ static void core_free(pa_object *o) {
pa_silence_cache_done(&c->silence_cache);
pa_mempool_free(c->mempool);
- pa_shared_cleanup(c);
-
for (j = 0; j < PA_CORE_HOOK_MAX; j++)
pa_hook_done(&c->hooks[j]);
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index b349c6fc..2b8f819b 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -112,7 +112,7 @@ struct pa_core {
/* Some hashmaps for all sorts of entities */
pa_hashmap *namereg, *shared;
- /* The name of the default sink/source */
+ /* The default sink/source */
pa_source *default_source;
pa_sink *default_sink;
@@ -129,13 +129,12 @@ struct pa_core {
pa_mempool *mempool;
pa_silence_cache silence_cache;
- int exit_idle_time, scache_idle_time;
- pa_bool_t flat_volumes;
-
pa_time_event *exit_event;
-
pa_time_event *scache_auto_unload_event;
+ int exit_idle_time, scache_idle_time;
+
+ pa_bool_t flat_volumes:1;
pa_bool_t disallow_module_loading:1;
pa_bool_t disallow_exit:1;
pa_bool_t running_as_daemon:1;
diff --git a/src/pulsecore/envelope.c b/src/pulsecore/envelope.c
index f872d347..b57b6435 100644
--- a/src/pulsecore/envelope.c
+++ b/src/pulsecore/envelope.c
@@ -599,7 +599,6 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
switch (e->sample_spec.format) {
-
case PA_SAMPLE_U8: {
uint8_t *t;
diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c
index 24a28db7..352ac977 100644
--- a/src/pulsecore/idxset.c
+++ b/src/pulsecore/idxset.c
@@ -386,8 +386,11 @@ void* pa_idxset_steal_first(pa_idxset *s, uint32_t *idx) {
void* pa_idxset_first(pa_idxset *s, uint32_t *idx) {
pa_assert(s);
- if (!s->iterate_list_head)
+ if (!s->iterate_list_head) {
+ if (idx)
+ *idx = PA_IDXSET_INVALID;
return NULL;
+ }
if (idx)
*idx = s->iterate_list_head->idx;
@@ -402,20 +405,41 @@ void *pa_idxset_next(pa_idxset *s, uint32_t *idx) {
pa_assert(s);
pa_assert(idx);
+ if (*idx == PA_IDXSET_INVALID)
+ return NULL;
+
hash = *idx % NBUCKETS;
- if (!(e = index_scan(s, hash, *idx)))
- return NULL;
+ if ((e = index_scan(s, hash, *idx))) {
+
+ e = e->iterate_next;
+
+ if (e) {
+ *idx = e->idx;
+ return e->data;
+ } else {
+ *idx = PA_IDXSET_INVALID;
+ return NULL;
+ }
+
+ } else {
+
+ /* If the entry passed doesn't exist anymore we try to find
+ * the next following */
+
+ for ((*idx)++; *idx < s->current_index; (*idx)++) {
+
+ hash = *idx % NBUCKETS;
+
+ if ((e = index_scan(s, hash, *idx))) {
+ *idx = e->idx;
+ return e->data;
+ }
+ }
- if (!e->iterate_next) {
*idx = PA_IDXSET_INVALID;
return NULL;
}
-
- e = e->iterate_next;
-
- *idx = e->idx;
- return e->data;
}
unsigned pa_idxset_size(pa_idxset*s) {
diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index 9a7f7cac..1ae43839 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -278,7 +278,8 @@ void pa_log_levelv_meta(
n++;
}
- if (!*t)
+ /* We ignore strings only made out of whitespace */
+ if (t[strspn(t, "\t ")] == 0)
continue;
switch (log_target) {
diff --git a/src/pulsecore/ltdl-helper.c b/src/pulsecore/ltdl-helper.c
index 0d4c22f8..ed0b63af 100644
--- a/src/pulsecore/ltdl-helper.c
+++ b/src/pulsecore/ltdl-helper.c
@@ -42,7 +42,9 @@ pa_void_func_t pa_load_sym(lt_dlhandle handle, const char *module, const char *s
pa_assert(handle);
pa_assert(symbol);
- if ((f = ((pa_void_func_t) (size_t) lt_dlsym(handle, symbol))))
+ *(void**) &f = lt_dlsym(handle, symbol);
+
+ if (f)
return f;
if (!module)
@@ -57,7 +59,7 @@ pa_void_func_t pa_load_sym(lt_dlhandle handle, const char *module, const char *s
if (!isalnum(*c))
*c = '_';
- f = (pa_void_func_t) (size_t) lt_dlsym(handle, sn);
+ *(void**) &f = lt_dlsym(handle, sn);
pa_xfree(sn);
return f;
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index f9ce949a..59460012 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -187,17 +187,17 @@ typedef int pa_bool_t;
abort(); \
} while (FALSE)
-#define PA_PTR_TO_UINT(p) ((unsigned int) (unsigned long) (p))
-#define PA_UINT_TO_PTR(u) ((void*) (unsigned long) (u))
+#define PA_PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
+#define PA_UINT_TO_PTR(u) ((void*) ((uintptr_t) (u)))
-#define PA_PTR_TO_UINT32(p) ((uint32_t) PA_PTR_TO_UINT(p))
-#define PA_UINT32_TO_PTR(u) PA_UINT_TO_PTR((uint32_t) u)
+#define PA_PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
+#define PA_UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
-#define PA_PTR_TO_INT(p) ((int) PA_PTR_TO_UINT(p))
-#define PA_INT_TO_PTR(u) PA_UINT_TO_PTR((int) u)
+#define PA_PTR_TO_INT(p) ((int) ((intptr_t) (p)))
+#define PA_INT_TO_PTR(u) ((void*) ((intptr_t) (u)))
-#define PA_PTR_TO_INT32(p) ((int32_t) PA_PTR_TO_UINT(p))
-#define PA_INT32_TO_PTR(u) PA_UINT_TO_PTR((int32_t) u)
+#define PA_PTR_TO_INT32(p) ((int32_t) ((intptr_t) (p)))
+#define PA_INT32_TO_PTR(u) ((void*) ((intptr_t) (u)))
#ifdef OS_IS_WIN32
#define PA_PATH_SEP "\\"
diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c
index d470bb0b..1eb70c8e 100644
--- a/src/pulsecore/module.c
+++ b/src/pulsecore/module.c
@@ -75,7 +75,7 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
m->load_once = load_once();
- if (m->load_once && c->modules) {
+ if (m->load_once) {
pa_module *i;
uint32_t idx;
/* OK, the module only wants to be loaded once, let's make sure it is */
@@ -105,9 +105,6 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
goto fail;
}
- if (!c->modules)
- c->modules = pa_idxset_new(NULL, NULL);
-
pa_assert_se(pa_idxset_put(c->modules, m, &m->index) >= 0);
pa_assert(m->index != PA_IDXSET_INVALID);
@@ -200,17 +197,11 @@ void pa_module_unload_by_index(pa_core *c, uint32_t idx, pa_bool_t force) {
}
void pa_module_unload_all(pa_core *c) {
+ pa_module *m;
pa_assert(c);
- if (c->modules) {
- pa_module *m;
-
- while ((m = pa_idxset_steal_first(c->modules, NULL)))
- pa_module_free(m);
-
- pa_idxset_free(c->modules, NULL, NULL);
- c->modules = NULL;
- }
+ while ((m = pa_idxset_steal_first(c->modules, NULL)))
+ pa_module_free(m);
if (c->module_defer_unload_event) {
c->mainloop->defer_free(c->module_defer_unload_event);
@@ -226,9 +217,6 @@ static void defer_cb(pa_mainloop_api*api, pa_defer_event *e, void *userdata) {
pa_core_assert_ref(c);
api->defer_enable(e, 0);
- if (!c->modules)
- return;
-
while ((m = pa_idxset_iterate(c->modules, &state, NULL)))
if (m->unload_requested)
pa_module_unload(c, m, TRUE);
diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c
index f3d5a8f8..86bcef74 100644
--- a/src/pulsecore/namereg.c
+++ b/src/pulsecore/namereg.c
@@ -87,16 +87,6 @@ char* pa_namereg_make_valid_name(const char *name) {
return n;
}
-void pa_namereg_free(pa_core *c) {
- pa_assert(c);
-
- if (!c->namereg)
- return;
-
- pa_assert(pa_hashmap_size(c->namereg) == 0);
- pa_hashmap_free(c->namereg, NULL, NULL);
-}
-
const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, pa_bool_t fail) {
struct namereg_entry *e;
char *n = NULL;
@@ -118,9 +108,6 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t
return NULL;
}
- if (!c->namereg)
- c->namereg = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-
if ((e = pa_hashmap_get(c->namereg, name)) && fail) {
pa_xfree(n);
return NULL;
@@ -207,10 +194,10 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type) {
}
- if (*name == '@' || !name || !pa_namereg_is_valid_name(name))
+ if (!name || *name == '@' || !pa_namereg_is_valid_name(name))
return NULL;
- if (c->namereg && (e = pa_hashmap_get(c->namereg, name)))
+ if ((e = pa_hashmap_get(c->namereg, name)))
if (e->type == type)
return e->data;
diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h
index b91dd52d..ff99525e 100644
--- a/src/pulsecore/namereg.h
+++ b/src/pulsecore/namereg.h
@@ -34,8 +34,6 @@ typedef enum pa_namereg_type {
PA_NAMEREG_CARD
} pa_namereg_type_t;
-void pa_namereg_free(pa_core *c);
-
const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, pa_bool_t fail);
void pa_namereg_unregister(pa_core *c, const char *name);
void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type);
diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index eac21de5..d1631264 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -200,7 +200,7 @@ pa_sink_input* pa_memblockq_sink_input_new(
pa_sink_input_new_data_set_virtual_volume(&data, volume);
pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
- u->sink_input = pa_sink_input_new(sink->core, &data, 0);
+ pa_sink_input_new(&u->sink_input, sink->core, &data, 0);
pa_sink_input_new_data_done(&data);
if (!u->sink_input)
diff --git a/src/pulsecore/proplist-util.c b/src/pulsecore/proplist-util.c
index 35c9985a..4920c27e 100644
--- a/src/pulsecore/proplist-util.c
+++ b/src/pulsecore/proplist-util.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <locale.h>
+#include <dlfcn.h>
#include <pulse/proplist.h>
#include <pulse/utf8.h>
@@ -36,7 +37,6 @@
#include "proplist-util.h"
void pa_init_proplist(pa_proplist *p) {
- int a, b;
#if !HAVE_DECL_ENVIRON
extern char **environ;
#endif
@@ -99,22 +99,36 @@ void pa_init_proplist(pa_proplist *p) {
}
}
- a = pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY);
- b = pa_proplist_contains(p, PA_PROP_APPLICATION_NAME);
-
- if (!a || !b) {
+ if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY)) {
char t[PATH_MAX];
if (pa_get_binary_name(t, sizeof(t))) {
char *c = pa_utf8_filter(t);
+ pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_BINARY, c);
+ pa_xfree(c);
+ }
+ }
- if (!a)
- pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_BINARY, c);
- if (!b)
- pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, c);
+#ifdef RTLD_NOLOAD
+ if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME)) {
+ void *dl;
- pa_xfree(c);
+ if ((dl = dlopen("libglib-2.0", RTLD_NOLOAD))) {
+ const char *(*_g_get_application_name)(void);
+
+ if ((*(void**) &_g_get_application_name = dlsym(dl, "g_get_application_name")))
+ pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, _g_get_application_name());
+
+ dlclose(dl);
}
}
+#endif
+
+ if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME)) {
+ const char *t;
+
+ if ((t = pa_proplist_gets(p, PA_PROP_APPLICATION_PROCESS_BINARY)))
+ pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, t);
+ }
if (!pa_proplist_contains(p, PA_PROP_APPLICATION_LANGUAGE)) {
const char *l;
@@ -122,4 +136,23 @@ void pa_init_proplist(pa_proplist *p) {
if ((l = setlocale(LC_MESSAGES, NULL)))
pa_proplist_sets(p, PA_PROP_APPLICATION_LANGUAGE, l);
}
+
+ if (!pa_proplist_contains(p, PA_PROP_WINDOW_X11_DISPLAY)) {
+ const char *t;
+
+ if ((t = getenv("DISPLAY"))) {
+ char *c = pa_utf8_filter(t);
+ pa_proplist_sets(p, PA_PROP_WINDOW_X11_DISPLAY, c);
+ pa_xfree(c);
+ }
+ }
+
+ if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_MACHINE_ID)) {
+ char *m;
+
+ if ((m = pa_machine_id())) {
+ pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_MACHINE_ID, m);
+ pa_xfree(m);
+ }
+ }
}
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 1311e678..e1643cbb 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -424,7 +424,7 @@ static int esd_proto_stream_play(connection *c, esd_proto_t request, const void
sdata.sink = sink;
pa_sink_input_new_data_set_sample_spec(&sdata, &ss);
- c->sink_input = pa_sink_input_new(c->protocol->core, &sdata, 0);
+ pa_sink_input_new(&c->sink_input, c->protocol->core, &sdata, 0);
pa_sink_input_new_data_done(&sdata);
CHECK_VALIDITY(c->sink_input, "Failed to create sink input.");
@@ -526,7 +526,7 @@ static int esd_proto_stream_record(connection *c, esd_proto_t request, const voi
sdata.source = source;
pa_source_output_new_data_set_sample_spec(&sdata, &ss);
- c->source_output = pa_source_output_new(c->protocol->core, &sdata, 0);
+ pa_source_output_new(&c->source_output, c->protocol->core, &sdata, 0);
pa_source_output_new_data_done(&sdata);
CHECK_VALIDITY(c->source_output, "Failed to create source output.");
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index c9621652..21a2cfbc 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -591,7 +591,8 @@ static record_stream* record_stream_new(
pa_proplist *p,
pa_bool_t adjust_latency,
pa_sink_input *direct_on_input,
- pa_bool_t early_requests) {
+ pa_bool_t early_requests,
+ int *ret) {
record_stream *s;
pa_source_output *source_output;
@@ -602,6 +603,7 @@ static record_stream* record_stream_new(
pa_assert(ss);
pa_assert(maxlength);
pa_assert(p);
+ pa_assert(ret);
pa_source_output_new_data_init(&data);
@@ -616,7 +618,7 @@ static record_stream* record_stream_new(
if (peak_detect)
data.resample_method = PA_RESAMPLER_PEAKS;
- source_output = pa_source_output_new(c->protocol->core, &data, flags);
+ *ret = pa_source_output_new(&source_output, c->protocol->core, &data, flags);
pa_source_output_new_data_done(&data);
@@ -965,7 +967,8 @@ static playback_stream* playback_stream_new(
pa_sink_input_flags_t flags,
pa_proplist *p,
pa_bool_t adjust_latency,
- pa_bool_t early_requests) {
+ pa_bool_t early_requests,
+ int *ret) {
playback_stream *s, *ssync;
pa_sink_input *sink_input;
@@ -982,6 +985,7 @@ static playback_stream* playback_stream_new(
pa_assert(minreq);
pa_assert(missing);
pa_assert(p);
+ pa_assert(ret);
/* Find syncid group */
for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
@@ -998,8 +1002,10 @@ static playback_stream* playback_stream_new(
if (!sink)
sink = ssync->sink_input->sink;
- else if (sink != ssync->sink_input->sink)
+ else if (sink != ssync->sink_input->sink) {
+ *ret = PA_ERR_INVALID;
return NULL;
+ }
}
pa_sink_input_new_data_init(&data);
@@ -1017,7 +1023,7 @@ static playback_stream* playback_stream_new(
pa_sink_input_new_data_set_muted(&data, muted);
data.sync_base = ssync ? ssync->sink_input : NULL;
- sink_input = pa_sink_input_new(c->protocol->core, &data, flags);
+ *ret = pa_sink_input_new(&sink_input, c->protocol->core, &data, flags);
pa_sink_input_new_data_done(&data);
@@ -1691,11 +1697,12 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
adjust_latency = FALSE,
early_requests = FALSE,
dont_inhibit_auto_suspend = FALSE,
- muted_set = FALSE;
-
+ muted_set = FALSE,
+ fail_on_suspend = FALSE;
pa_sink_input_flags_t flags = 0;
pa_proplist *p;
pa_bool_t volume_set = TRUE;
+ int ret = PA_ERR_INVALID;
pa_native_connection_assert_ref(c);
pa_assert(t);
@@ -1775,7 +1782,8 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
if (c->version >= 15) {
if (pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
- pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0) {
+ pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
+ pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
protocol_error(c);
pa_proplist_free(p);
return;
@@ -1814,16 +1822,17 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
(fix_channels ? PA_SINK_INPUT_FIX_CHANNELS : 0) |
(no_move ? PA_SINK_INPUT_DONT_MOVE : 0) |
(variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0) |
- (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0);
+ (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
+ (fail_on_suspend ? PA_SINK_INPUT_FAIL_ON_SUSPEND : 0);
/* Only since protocol version 15 there's a seperate muted_set
* flag. For older versions we synthesize it here */
muted_set = muted_set || muted;
- s = playback_stream_new(c, sink, &ss, &map, &maxlength, &tlength, &prebuf, &minreq, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests);
+ s = playback_stream_new(c, sink, &ss, &map, &maxlength, &tlength, &prebuf, &minreq, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, &ret);
pa_proplist_free(p);
- CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
+ CHECK_VALIDITY(c->pstream, s, tag, ret);
reply = reply_new(tag);
pa_tagstruct_putu32(reply, s->index);
@@ -1942,11 +1951,13 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
adjust_latency = FALSE,
peak_detect = FALSE,
early_requests = FALSE,
- dont_inhibit_auto_suspend = FALSE;
+ dont_inhibit_auto_suspend = FALSE,
+ fail_on_suspend = 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;
+ int ret = PA_ERR_INVALID;
pa_native_connection_assert_ref(c);
pa_assert(t);
@@ -2016,7 +2027,8 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
if (c->version >= 15) {
- if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0) {
+ if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
+ pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
protocol_error(c);
pa_proplist_free(p);
return;
@@ -2064,12 +2076,13 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
(fix_channels ? PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) |
(no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
(variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) |
- (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0);
+ (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
+ (fail_on_suspend ? PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND : 0);
- s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency, direct_on_input, early_requests);
+ s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency, direct_on_input, early_requests, &ret);
pa_proplist_free(p);
- CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
+ CHECK_VALIDITY(c->pstream, s, tag, ret);
reply = reply_new(tag);
pa_tagstruct_putu32(reply, s->index);
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index dd8002a3..e149c40d 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -539,7 +539,7 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp
pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
pa_sink_input_new_data_set_sample_spec(&data, &o->sample_spec);
- c->sink_input = pa_sink_input_new(p->core, &data, 0);
+ pa_sink_input_new(&c->sink_input, p->core, &data, 0);
pa_sink_input_new_data_done(&data);
if (!c->sink_input) {
@@ -591,7 +591,7 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp
pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
pa_source_output_new_data_set_sample_spec(&data, &o->sample_spec);
- c->source_output = pa_source_output_new(p->core, &data, 0);
+ pa_source_output_new(&c->source_output, p->core, &data, 0);
pa_source_output_new_data_done(&data);
if (!c->source_output) {
diff --git a/src/pulsecore/shared.c b/src/pulsecore/shared.c
index d6e42dd8..9485dc33 100644
--- a/src/pulsecore/shared.c
+++ b/src/pulsecore/shared.c
@@ -99,32 +99,6 @@ int pa_shared_remove(pa_core *c, const char *name) {
return 0;
}
-void pa_shared_init(pa_core *c) {
- pa_assert(c);
-
- c->shared = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-}
-
-void pa_shared_cleanup(pa_core *c) {
- pa_assert(c);
-
- if (!c->shared)
- return;
-
- if (!pa_hashmap_isempty(c->shared)) {
- pa_strbuf *s = pa_strbuf_new();
-
- pa_shared_dump(c, s);
- pa_log_debug("%s", pa_strbuf_tostring(s));
- pa_strbuf_free(s);
- pa_assert(pa_hashmap_isempty(c->shared));
- }
-
- pa_hashmap_free(c->shared, NULL, NULL);
- c->shared = NULL;
-
-}
-
void pa_shared_dump(pa_core *c, pa_strbuf *s) {
void *state = NULL;
pa_shared *p;
diff --git a/src/pulsecore/shared.h b/src/pulsecore/shared.h
index dd3f94e2..f6f8d3cf 100644
--- a/src/pulsecore/shared.h
+++ b/src/pulsecore/shared.h
@@ -49,12 +49,6 @@ int pa_shared_remove(pa_core *c, const char *name);
/* A combination of pa_shared_remove() and pa_shared_set() */
int pa_shared_replace(pa_core *c, const char *name, void *data);
-/* Free all memory used by the shared property system */
-void pa_shared_cleanup(pa_core *c);
-
-/* Initialize the shared property system */
-void pa_shared_init(pa_core *c);
-
/* Dump the current set of shared properties */
void pa_shared_dump(pa_core *c, pa_strbuf *s);
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index d4d11194..a3a29e9b 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -120,7 +120,8 @@ static void reset_callbacks(pa_sink_input *i) {
}
/* Called from main context */
-pa_sink_input* pa_sink_input_new(
+int pa_sink_input_new(
+ pa_sink_input **_i,
pa_core *core,
pa_sink_input_new_data *data,
pa_sink_input_flags_t flags) {
@@ -129,28 +130,31 @@ pa_sink_input* pa_sink_input_new(
pa_resampler *resampler = NULL;
char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
pa_channel_map original_cm;
+ int r;
+ pa_assert(_i);
pa_assert(core);
pa_assert(data);
- if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data) < 0)
- return NULL;
+ if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0)
+ return r;
- pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
+ pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
if (!data->sink) {
data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK);
data->save_sink = FALSE;
}
- pa_return_null_if_fail(data->sink);
- pa_return_null_if_fail(pa_sink_get_state(data->sink) != PA_SINK_UNLINKED);
- pa_return_null_if_fail(!data->sync_base || (data->sync_base->sink == data->sink && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED));
+ pa_return_val_if_fail(data->sink, -PA_ERR_NOENTITY);
+ pa_return_val_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)), -PA_ERR_BADSTATE);
+ pa_return_val_if_fail(!data->sync_base || (data->sync_base->sink == data->sink && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED), -PA_ERR_INVALID);
+ pa_return_val_if_fail(!(flags & PA_SINK_INPUT_FAIL_ON_SUSPEND) || pa_sink_get_state(data->sink) != PA_SINK_SUSPENDED, -PA_ERR_BADSTATE);
if (!data->sample_spec_is_set)
data->sample_spec = data->sink->sample_spec;
- pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec));
+ pa_return_val_if_fail(pa_sample_spec_valid(&data->sample_spec), -PA_ERR_INVALID);
if (!data->channel_map_is_set) {
if (pa_channel_map_compatible(&data->sink->channel_map, &data->sample_spec))
@@ -159,8 +163,8 @@ pa_sink_input* pa_sink_input_new(
pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
}
- pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
- pa_return_null_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec));
+ pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID);
+ pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
if (!data->virtual_volume_is_set) {
@@ -183,14 +187,14 @@ pa_sink_input* pa_sink_input_new(
}
}
- pa_return_null_if_fail(pa_cvolume_valid(&data->virtual_volume));
- pa_return_null_if_fail(pa_cvolume_compatible(&data->virtual_volume, &data->sample_spec));
+ pa_return_val_if_fail(pa_cvolume_valid(&data->virtual_volume), -PA_ERR_INVALID);
+ pa_return_val_if_fail(pa_cvolume_compatible(&data->virtual_volume, &data->sample_spec), -PA_ERR_INVALID);
if (!data->soft_volume_is_set)
data->soft_volume = data->virtual_volume;
- pa_return_null_if_fail(pa_cvolume_valid(&data->soft_volume));
- pa_return_null_if_fail(pa_cvolume_compatible(&data->soft_volume, &data->sample_spec));
+ pa_return_val_if_fail(pa_cvolume_valid(&data->soft_volume), -PA_ERR_INVALID);
+ pa_return_val_if_fail(pa_cvolume_compatible(&data->soft_volume, &data->sample_spec), -PA_ERR_INVALID);
if (!data->muted_is_set)
data->muted = FALSE;
@@ -218,17 +222,17 @@ pa_sink_input* pa_sink_input_new(
if (data->resample_method == PA_RESAMPLER_INVALID)
data->resample_method = core->resample_method;
- pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX);
+ pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
if (data->client)
pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
- if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data) < 0)
- return NULL;
+ if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
+ return r;
if (pa_idxset_size(data->sink->inputs) >= PA_MAX_INPUTS_PER_SINK) {
pa_log_warn("Failed to create sink input: too many inputs per sink.");
- return NULL;
+ return -PA_ERR_TOOLARGE;
}
if ((flags & PA_SINK_INPUT_VARIABLE_RATE) ||
@@ -245,7 +249,7 @@ pa_sink_input* pa_sink_input_new(
(core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
(core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
pa_log_warn("Unsupported resampling operation.");
- return NULL;
+ return -PA_ERR_NOTSUPPORTED;
}
}
@@ -330,7 +334,8 @@ pa_sink_input* pa_sink_input_new(
/* Don't forget to call pa_sink_input_put! */
- return i;
+ *_i = i;
+ return 0;
}
/* Called from main context */
@@ -347,7 +352,7 @@ static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
}
/* Called from main context */
-static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
+static void sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
pa_sink_input *ssync;
pa_assert(i);
@@ -355,7 +360,7 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
state = PA_SINK_INPUT_RUNNING;
if (i->state == state)
- return 0;
+ return;
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);
@@ -382,8 +387,6 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
}
pa_sink_update_status(i->sink);
-
- return 0;
}
/* Called from main context */
@@ -549,7 +552,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {
}
/* Called from thread context */
-int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
+void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
pa_bool_t do_volume_adj_here;
pa_bool_t volume_is_norm;
size_t block_size_max_sink, block_size_max_sink_input;
@@ -563,9 +566,6 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
/* pa_log_debug("peek"); */
- if (!i->pop)
- return -1;
-
pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING ||
i->thread_info.state == PA_SINK_INPUT_CORKED ||
i->thread_info.state == PA_SINK_INPUT_DRAINED);
@@ -692,8 +692,6 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
pa_cvolume_mute(volume, i->sink->sample_spec.channels);
else
*volume = i->thread_info.soft_volume;
-
- return 0;
}
/* Called from thread context */
@@ -960,7 +958,7 @@ void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b) {
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));
- pa_return_val_if_fail(i->thread_info.resampler, -1);
+ pa_return_val_if_fail(i->thread_info.resampler, -PA_ERR_BADSTATE);
if (i->sample_spec.rate == rate)
return 0;
@@ -1048,16 +1046,17 @@ pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) {
int pa_sink_input_start_move(pa_sink_input *i) {
pa_source_output *o, *p = NULL;
pa_sink *origin;
+ int r;
pa_sink_input_assert_ref(i);
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
pa_assert(i->sink);
if (!pa_sink_input_may_move(i))
- return -1;
+ return -PA_ERR_NOTSUPPORTED;
- if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i) < 0)
- return -1;
+ if ((r = pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], i)) < 0)
+ return r;
origin = i->sink;
@@ -1099,14 +1098,7 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
pa_sink_assert_ref(dest);
if (!pa_sink_input_may_move_to(i, dest))
- return -1;
-
- i->sink = dest;
- i->save_sink = save;
- pa_idxset_put(dest->inputs, i, NULL);
-
- if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
- i->sink->n_corked++;
+ return -PA_ERR_NOTSUPPORTED;
if (i->thread_info.resampler &&
pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &dest->sample_spec) &&
@@ -1130,11 +1122,18 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
(i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
pa_log_warn("Unsupported resampling operation.");
- return -1;
+ return -PA_ERR_NOTSUPPORTED;
}
} else
new_resampler = NULL;
+ i->sink = dest;
+ i->save_sink = save;
+ pa_idxset_put(dest->inputs, i, NULL);
+
+ if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
+ i->sink->n_corked++;
+
/* Replace resampler and render queue */
if (new_resampler != i->thread_info.resampler) {
@@ -1180,6 +1179,8 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
/* Called from main context */
int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
+ int r;
+
pa_sink_input_assert_ref(i);
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
pa_assert(i->sink);
@@ -1189,13 +1190,13 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
return 0;
if (!pa_sink_input_may_move_to(i, dest))
- return -1;
+ return -PA_ERR_NOTSUPPORTED;
- if (pa_sink_input_start_move(i) < 0)
- return -1;
+ if ((r = pa_sink_input_start_move(i)) < 0)
+ return r;
- if (pa_sink_input_finish_move(i, dest, save) < 0)
- return -1;
+ if ((r = pa_sink_input_finish_move(i, dest, save)) < 0)
+ return r;
return 0;
}
@@ -1310,7 +1311,7 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
}
}
- return -1;
+ return -PA_ERR_NOTIMPLEMENTED;
}
/* Called from main thread */
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 893d8690..d82a3a62 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -58,6 +58,7 @@ typedef enum pa_sink_input_flags {
PA_SINK_INPUT_FIX_RATE = 64,
PA_SINK_INPUT_FIX_CHANNELS = 128,
PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND = 256,
+ PA_SINK_INPUT_FAIL_ON_SUSPEND = 512
} pa_sink_input_flags_t;
struct pa_sink_input {
@@ -256,7 +257,8 @@ void pa_sink_input_new_data_done(pa_sink_input_new_data *data);
/* To be called by the implementing module only */
-pa_sink_input* pa_sink_input_new(
+int pa_sink_input_new(
+ pa_sink_input **i,
pa_core *core,
pa_sink_input_new_data *data,
pa_sink_input_flags_t flags);
@@ -312,7 +314,7 @@ pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i);
/* To be used exclusively by the sink driver IO thread */
-int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_cvolume *volume);
+void pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_cvolume *volume);
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 */);
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 3afeadb0..0c297ec3 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -128,6 +128,7 @@ pa_sink* pa_sink_new(
char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
pa_source_new_data source_data;
const char *dn;
+ char *pt;
pa_assert(core);
pa_assert(data);
@@ -233,11 +234,14 @@ pa_sink* pa_sink_new(
if (s->card)
pa_assert_se(pa_idxset_put(s->card->sinks, s, NULL) >= 0);
- pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s",
+ pt = pa_proplist_to_string_sep(s->proplist, "\n ");
+ pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s\n %s",
s->index,
s->name,
pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
- pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map));
+ pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
+ pt);
+ pa_xfree(pt);
pa_source_new_data_init(&source_data);
pa_source_new_data_set_sample_spec(&source_data, &s->sample_spec);
@@ -301,6 +305,11 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
s->state = state;
+ if (state != PA_SINK_UNLINKED) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
+ pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ }
+
if (suspend_change) {
pa_sink_input *i;
uint32_t idx;
@@ -308,15 +317,13 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
/* We're suspending or resuming, tell everyone about it */
for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx)))
- if (i->suspend)
+ if (s->state == PA_SINK_SUSPENDED &&
+ (i->flags & PA_SINK_INPUT_FAIL_ON_SUSPEND))
+ pa_sink_input_kill(i);
+ else if (i->suspend)
i->suspend(i, state == PA_SINK_SUSPENDED);
}
- if (state != PA_SINK_UNLINKED) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
- pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
- pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
- }
-
return 0;
}
@@ -540,9 +547,17 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
+ /* If nobody requested this and this is actually no real rewind
+ * then we can short cut this */
+ if (!s->thread_info.rewind_requested && nbytes <= 0)
+ return;
+
s->thread_info.rewind_nbytes = 0;
s->thread_info.rewind_requested = FALSE;
+ if (s->thread_info.state == PA_SINK_SUSPENDED)
+ return;
+
if (nbytes > 0)
pa_log_debug("Processing rewind...");
@@ -552,7 +567,7 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
}
if (nbytes > 0)
- if (s->monitor_source && PA_SOURCE_IS_OPENED(s->monitor_source->thread_info.state))
+ if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
pa_source_process_rewind(s->monitor_source, nbytes);
}
@@ -569,8 +584,7 @@ static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, uns
while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
pa_sink_input_assert_ref(i);
- if (pa_sink_input_peek(i, *length, &info->chunk, &info->volume) < 0)
- continue;
+ pa_sink_input_peek(i, *length, &info->chunk, &info->volume);
if (mixlength == 0 || info->chunk.length < mixlength)
mixlength = info->chunk.length;
@@ -632,7 +646,7 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *
/* Drop read data */
pa_sink_input_drop(i, result->length);
- if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source))) {
+ if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state)) {
if (pa_hashmap_size(i->thread_info.direct_outputs) > 0) {
void *ostate = NULL;
@@ -688,7 +702,7 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, pa_memchunk *
}
}
- if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
+ if (s->monitor_source && PA_SOURCE_IS_LINKED(s->monitor_source->thread_info.state))
pa_source_post(s->monitor_source, result);
}
@@ -699,7 +713,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
size_t block_size_max;
pa_sink_assert_ref(s);
- pa_assert(PA_SINK_IS_OPENED(s->thread_info.state));
+ pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
pa_assert(pa_frame_aligned(length, &s->sample_spec));
pa_assert(result);
@@ -708,6 +722,13 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
pa_assert(!s->thread_info.rewind_requested);
pa_assert(s->thread_info.rewind_nbytes == 0);
+ if (s->thread_info.state == PA_SINK_SUSPENDED) {
+ result->memblock = pa_memblock_ref(s->silence.memblock);
+ result->index = s->silence.index;
+ result->length = PA_MIN(s->silence.length, length);
+ return;
+ }
+
if (length <= 0)
length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
@@ -772,7 +793,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
size_t length, block_size_max;
pa_sink_assert_ref(s);
- pa_assert(PA_SINK_IS_OPENED(s->thread_info.state));
+ pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
pa_assert(target);
pa_assert(target->memblock);
pa_assert(target->length > 0);
@@ -783,6 +804,11 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
pa_assert(!s->thread_info.rewind_requested);
pa_assert(s->thread_info.rewind_nbytes == 0);
+ if (s->thread_info.state == PA_SINK_SUSPENDED) {
+ pa_silence_memchunk(target, &s->sample_spec);
+ return;
+ }
+
length = target->length;
block_size_max = pa_mempool_block_size_max(s->core->mempool);
if (length > block_size_max)
@@ -850,7 +876,7 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
size_t l, d;
pa_sink_assert_ref(s);
- pa_assert(PA_SINK_IS_OPENED(s->thread_info.state));
+ pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
pa_assert(target);
pa_assert(target->memblock);
pa_assert(target->length > 0);
@@ -880,7 +906,7 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
/* 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));
+ pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
pa_assert(length > 0);
pa_assert(pa_frame_aligned(length, &s->sample_spec));
pa_assert(result);
@@ -906,7 +932,7 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
/* The returned value is supposed to be in the time domain of the sound card! */
- if (!PA_SINK_IS_OPENED(s->state))
+ if (s->state == PA_SINK_SUSPENDED)
return 0;
if (!(s->flags & PA_SINK_LATENCY))
@@ -922,12 +948,24 @@ void pa_sink_update_flat_volume(pa_sink *s, pa_cvolume *new_volume) {
pa_sink_input *i;
uint32_t idx;
+ pa_sink_assert_ref(s);
+ pa_assert(new_volume);
+ pa_assert(PA_SINK_IS_LINKED(s->state));
+ pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
+
/* This is called whenever a sink input volume changes and we
* might need to fix up the sink volume accordingly. Please note
* that we don't actually update the sinks volume here, we only
* return how it needs to be updated. The caller should then call
* pa_sink_set_flat_volume().*/
+ if (pa_idxset_isempty(s->inputs)) {
+ /* In the special case that we have no sink input we leave the
+ * volume unmodified. */
+ *new_volume = s->virtual_volume;
+ return;
+ }
+
pa_cvolume_mute(new_volume, s->channel_map.channels);
/* First let's determine the new maximum volume of all inputs
@@ -969,8 +1007,8 @@ void pa_sink_propagate_flat_volume(pa_sink *s, const pa_cvolume *old_volume) {
uint32_t idx;
pa_sink_assert_ref(s);
- pa_assert(PA_SINK_IS_LINKED(s->state));
pa_assert(old_volume);
+ pa_assert(PA_SINK_IS_LINKED(s->state));
pa_assert(s->flags & PA_SINK_FLAT_VOLUME);
/* This is called whenever the sink volume changes that is not
@@ -1129,6 +1167,7 @@ pa_bool_t pa_sink_get_mute(pa_sink *s, pa_bool_t force_refresh) {
pa_bool_t pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p) {
pa_sink_assert_ref(s);
+ pa_assert(p);
pa_proplist_update(s->proplist, mode, p);
@@ -1469,7 +1508,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
case PA_SINK_MESSAGE_SET_MUTE:
- if (!s->thread_info.soft_muted != s->muted) {
+ if (s->thread_info.soft_muted != s->muted) {
s->thread_info.soft_muted = s->muted;
pa_sink_request_rewind(s, (size_t) -1);
}
@@ -1482,6 +1521,10 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
case PA_SINK_MESSAGE_SET_STATE:
s->thread_info.state = PA_PTR_TO_UINT(userdata);
+
+ if (s->thread_info.state == PA_SINK_SUSPENDED)
+ s->thread_info.rewind_requested = FALSE;
+
return 0;
case PA_SINK_MESSAGE_DETACH:
@@ -1609,6 +1652,9 @@ 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));
+ if (s->thread_info.state == PA_SINK_SUSPENDED)
+ return;
+
if (nbytes == (size_t) -1)
nbytes = s->thread_info.max_rewind;
@@ -1670,7 +1716,7 @@ pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
pa_sink_assert_ref(s);
pa_assert(PA_SINK_IS_LINKED(s->state));
- if (!PA_SINK_IS_OPENED(s->state))
+ if (s->state == PA_SINK_SUSPENDED)
return 0;
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 1be421f1..67b072b6 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -326,7 +326,7 @@ int pa_play_file(
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);
+ pa_sink_input_new(&u->sink_input, sink->core, &data, 0);
pa_sink_input_new_data_done(&data);
if (!u->sink_input)
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 1e1ac4e1..c5cb16d8 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -95,7 +95,8 @@ static void reset_callbacks(pa_source_output *o) {
}
/* Called from main context */
-pa_source_output* pa_source_output_new(
+int pa_source_output_new(
+ pa_source_output**_o,
pa_core *core,
pa_source_output_new_data *data,
pa_source_output_flags_t flags) {
@@ -103,29 +104,31 @@ pa_source_output* pa_source_output_new(
pa_source_output *o;
pa_resampler *resampler = NULL;
char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+ int r;
+ pa_assert(_o);
pa_assert(core);
pa_assert(data);
- if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], data) < 0)
- return NULL;
+ if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], data)) < 0)
+ return r;
- pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
+ pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID);
if (!data->source) {
data->source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE);
data->save_source = FALSE;
}
- 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);
+ pa_return_val_if_fail(data->source, -PA_ERR_NOENTITY);
+ pa_return_val_if_fail(PA_SOURCE_IS_LINKED(pa_source_get_state(data->source)), -PA_ERR_BADSTATE);
+ pa_return_val_if_fail(!data->direct_on_input || data->direct_on_input->sink == data->source->monitor_of, -PA_ERR_INVALID);
+ pa_return_val_if_fail(!(flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND) || pa_source_get_state(data->source) != PA_SOURCE_SUSPENDED, -PA_ERR_BADSTATE);
if (!data->sample_spec_is_set)
data->sample_spec = data->source->sample_spec;
- pa_return_null_if_fail(pa_sample_spec_valid(&data->sample_spec));
+ pa_return_val_if_fail(pa_sample_spec_valid(&data->sample_spec), -PA_ERR_INVALID);
if (!data->channel_map_is_set) {
if (pa_channel_map_compatible(&data->source->channel_map, &data->sample_spec))
@@ -134,8 +137,8 @@ pa_source_output* pa_source_output_new(
pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
}
- pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
- pa_return_null_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec));
+ pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID);
+ pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
if (flags & PA_SOURCE_OUTPUT_FIX_FORMAT)
data->sample_spec.format = data->source->sample_spec.format;
@@ -154,17 +157,17 @@ pa_source_output* pa_source_output_new(
if (data->resample_method == PA_RESAMPLER_INVALID)
data->resample_method = core->resample_method;
- pa_return_null_if_fail(data->resample_method < PA_RESAMPLER_MAX);
+ pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID);
if (data->client)
pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist);
- if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], data) < 0)
- return NULL;
+ if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], data)) < 0)
+ return r;
if (pa_idxset_size(data->source->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
pa_log("Failed to create source output: too many outputs per source.");
- return NULL;
+ return -PA_ERR_TOOLARGE;
}
if ((flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ||
@@ -181,7 +184,7 @@ pa_source_output* pa_source_output_new(
(core->disable_remixing || (flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
(core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
pa_log_warn("Unsupported resampling operation.");
- return NULL;
+ return -PA_ERR_NOTSUPPORTED;
}
}
@@ -245,7 +248,8 @@ pa_source_output* pa_source_output_new(
/* Don't forget to call pa_source_output_put! */
- return o;
+ *_o = o;
+ return 0;
}
/* Called from main context */
@@ -262,11 +266,11 @@ static void update_n_corked(pa_source_output *o, pa_source_output_state_t state)
}
/* Called from main context */
-static int source_output_set_state(pa_source_output *o, pa_source_output_state_t state) {
+static void source_output_set_state(pa_source_output *o, pa_source_output_state_t state) {
pa_assert(o);
if (o->state == state)
- return 0;
+ return;
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);
@@ -277,8 +281,6 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED], o);
pa_source_update_status(o->source);
-
- return 0;
}
/* Called from main context */
@@ -575,7 +577,7 @@ void pa_source_output_cork(pa_source_output *o, pa_bool_t b) {
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));
- pa_return_val_if_fail(o->thread_info.resampler, -1);
+ pa_return_val_if_fail(o->thread_info.resampler, -PA_ERR_BADSTATE);
if (o->sample_spec.rate == rate)
return 0;
@@ -675,16 +677,17 @@ pa_bool_t pa_source_output_may_move_to(pa_source_output *o, pa_source *dest) {
/* Called from main context */
int pa_source_output_start_move(pa_source_output *o) {
pa_source *origin;
+ int r;
pa_source_output_assert_ref(o);
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
pa_assert(o->source);
if (!pa_source_output_may_move(o))
- return -1;
+ return -PA_ERR_NOTSUPPORTED;
- if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_START], o) < 0)
- return -1;
+ if ((r = pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_START], o)) < 0)
+ return r;
origin = o->source;
@@ -713,13 +716,6 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t
if (!pa_source_output_may_move_to(o, dest))
return -1;
- o->source = dest;
- o->save_source = save;
- pa_idxset_put(o->source->outputs, o, NULL);
-
- if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED)
- o->source->n_corked++;
-
if (o->thread_info.resampler &&
pa_sample_spec_equal(pa_resampler_input_sample_spec(o->thread_info.resampler), &dest->sample_spec) &&
pa_channel_map_equal(pa_resampler_input_channel_map(o->thread_info.resampler), &dest->channel_map))
@@ -742,11 +738,18 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t
((o->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
(o->core->disable_remixing || (o->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
pa_log_warn("Unsupported resampling operation.");
- return -1;
+ return -PA_ERR_NOTSUPPORTED;
}
} else
new_resampler = NULL;
+ o->source = dest;
+ o->save_source = save;
+ pa_idxset_put(o->source->outputs, o, NULL);
+
+ if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED)
+ o->source->n_corked++;
+
/* Replace resampler */
if (new_resampler != o->thread_info.resampler) {
if (o->thread_info.resampler)
@@ -783,6 +786,7 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t
/* Called from main context */
int pa_source_output_move_to(pa_source_output *o, pa_source *dest, pa_bool_t save) {
+ int r;
pa_source_output_assert_ref(o);
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
@@ -793,13 +797,13 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest, pa_bool_t sav
return 0;
if (!pa_source_output_may_move_to(o, dest))
- return -1;
+ return -PA_ERR_NOTSUPPORTED;
- if (pa_source_output_start_move(o) < 0)
- return -1;
+ if ((r = pa_source_output_start_move(o)) < 0)
+ return r;
- if (pa_source_output_finish_move(o, dest, save) < 0)
- return -1;
+ if ((r = pa_source_output_finish_move(o, dest, save)) < 0)
+ return r;
return 0;
}
@@ -863,5 +867,5 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int
}
}
- return -1;
+ return -PA_ERR_NOTIMPLEMENTED;
}
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 79b4926b..91f28f94 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -54,7 +54,8 @@ typedef enum pa_source_output_flags {
PA_SOURCE_OUTPUT_FIX_FORMAT = 32,
PA_SOURCE_OUTPUT_FIX_RATE = 64,
PA_SOURCE_OUTPUT_FIX_CHANNELS = 128,
- PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND = 256
+ PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND = 256,
+ PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND = 512
} pa_source_output_flags_t;
struct pa_source_output {
@@ -204,7 +205,8 @@ void pa_source_output_new_data_done(pa_source_output_new_data *data);
/* To be called by the implementing module only */
-pa_source_output* pa_source_output_new(
+int pa_source_output_new(
+ pa_source_output**o,
pa_core *core,
pa_source_output_new_data *data,
pa_source_output_flags_t flags);
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 0152b082..04c7f8b7 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -119,6 +119,7 @@ pa_source* pa_source_new(
pa_source *s;
const char *name;
char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+ char *pt;
pa_assert(core);
pa_assert(data);
@@ -222,11 +223,14 @@ pa_source* pa_source_new(
if (s->card)
pa_assert_se(pa_idxset_put(s->card->sources, s, NULL) >= 0);
- pa_log_info("Created source %u \"%s\" with sample spec %s and channel map %s",
+ pt = pa_proplist_to_string_sep(s->proplist, "\n ");
+ pa_log_info("Created source %u \"%s\" with sample spec %s and channel map %s\n %s",
s->index,
s->name,
pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
- pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map));
+ pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
+ pt);
+ pa_xfree(pt);
return s;
}
@@ -263,6 +267,11 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
s->state = state;
+ if (state != PA_SOURCE_UNLINKED) { /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
+ pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ }
+
if (suspend_change) {
pa_source_output *o;
uint32_t idx;
@@ -270,12 +279,13 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
/* We're suspending or resuming, tell everyone about it */
for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx)))
- if (o->suspend)
+ if (s->state == PA_SOURCE_SUSPENDED &&
+ (o->flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND))
+ pa_source_output_kill(o);
+ else if (o->suspend)
o->suspend(o, state == PA_SOURCE_SUSPENDED);
}
- if (state != PA_SOURCE_UNLINKED) /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
- pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
return 0;
}
@@ -475,7 +485,10 @@ void pa_source_process_rewind(pa_source *s, size_t nbytes) {
void *state = NULL;
pa_source_assert_ref(s);
- pa_assert(PA_SOURCE_IS_OPENED(s->thread_info.state));
+ pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
+
+ if (s->thread_info.state == PA_SOURCE_SUSPENDED)
+ return;
if (nbytes <= 0)
return;
@@ -494,9 +507,12 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
void *state = NULL;
pa_source_assert_ref(s);
- pa_assert(PA_SOURCE_IS_OPENED(s->thread_info.state));
+ pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
pa_assert(chunk);
+ if (s->thread_info.state == PA_SOURCE_SUSPENDED)
+ return;
+
if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
pa_memchunk vchunk = *chunk;
@@ -530,11 +546,14 @@ void pa_source_post(pa_source*s, const pa_memchunk *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_assert(PA_SOURCE_IS_LINKED(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_SUSPENDED)
+ return;
+
if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
pa_memchunk vchunk = *chunk;
@@ -560,7 +579,7 @@ pa_usec_t pa_source_get_latency(pa_source *s) {
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
- if (!PA_SOURCE_IS_OPENED(s->state))
+ if (s->state == PA_SOURCE_SUSPENDED)
return 0;
if (!(s->flags & PA_SOURCE_LATENCY))
@@ -671,8 +690,8 @@ pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
/* Called from main thread */
pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p) {
-
pa_source_assert_ref(s);
+ pa_assert(p);
pa_proplist_update(s->proplist, mode, p);
@@ -996,7 +1015,7 @@ pa_usec_t pa_source_get_requested_latency(pa_source *s) {
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
- if (!PA_SOURCE_IS_OPENED(s->state))
+ if (s->state == PA_SOURCE_SUSPENDED)
return 0;
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);