diff options
Diffstat (limited to 'src/pulsecore')
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); |