diff options
Diffstat (limited to 'src/pulsecore')
-rw-r--r-- | src/pulsecore/card.c | 198 | ||||
-rw-r--r-- | src/pulsecore/card.h | 91 | ||||
-rw-r--r-- | src/pulsecore/cli-command.c | 17 | ||||
-rw-r--r-- | src/pulsecore/cli-text.c | 45 | ||||
-rw-r--r-- | src/pulsecore/cli-text.h | 2 | ||||
-rw-r--r-- | src/pulsecore/cli.c | 19 | ||||
-rw-r--r-- | src/pulsecore/client.c | 47 | ||||
-rw-r--r-- | src/pulsecore/client.h | 17 | ||||
-rw-r--r-- | src/pulsecore/core.c | 4 | ||||
-rw-r--r-- | src/pulsecore/core.h | 8 | ||||
-rw-r--r-- | src/pulsecore/namereg.c | 2 | ||||
-rw-r--r-- | src/pulsecore/namereg.h | 3 | ||||
-rw-r--r-- | src/pulsecore/play-memblockq.c | 2 | ||||
-rw-r--r-- | src/pulsecore/protocol-esound.c | 24 | ||||
-rw-r--r-- | src/pulsecore/protocol-native.c | 26 | ||||
-rw-r--r-- | src/pulsecore/protocol-simple.c | 20 | ||||
-rw-r--r-- | src/pulsecore/shared.c | 2 | ||||
-rw-r--r-- | src/pulsecore/sink-input.c | 29 | ||||
-rw-r--r-- | src/pulsecore/sink-input.h | 5 | ||||
-rw-r--r-- | src/pulsecore/sink.c | 18 | ||||
-rw-r--r-- | src/pulsecore/sink.h | 3 | ||||
-rw-r--r-- | src/pulsecore/sound-file-stream.c | 2 | ||||
-rw-r--r-- | src/pulsecore/source-output.c | 6 | ||||
-rw-r--r-- | src/pulsecore/source.c | 13 | ||||
-rw-r--r-- | src/pulsecore/source.h | 3 |
25 files changed, 541 insertions, 65 deletions
diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c new file mode 100644 index 00000000..03b9ebd7 --- /dev/null +++ b/src/pulsecore/card.c @@ -0,0 +1,198 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <pulse/xmalloc.h> + +#include <pulsecore/log.h> +#include <pulsecore/macro.h> +#include <pulsecore/core-util.h> +#include <pulsecore/namereg.h> + +#include "card.h" + +pa_card_config *pa_card_config_new(const char *name) { + pa_card_config *c; + + pa_assert(name); + + c = pa_xnew0(pa_card_config, 1); + c->name = pa_xstrdup(name); + + return c; +} + +void pa_card_config_free(pa_card_config *c) { + pa_assert(c); + + pa_xfree(c->name); + pa_xfree(c); +} + +pa_card_new_data* pa_card_new_data_init(pa_card_new_data *data) { + pa_assert(data); + + memset(data, 0, sizeof(*data)); + data->proplist = pa_proplist_new(); + + return data; +} + +void pa_card_new_data_set_name(pa_card_new_data *data, const char *name) { + pa_assert(data); + + pa_xfree(data->name); + data->name = pa_xstrdup(name); +} + +void pa_card_new_data_done(pa_card_new_data *data) { + + pa_assert(data); + + pa_proplist_free(data->proplist); + + if (data->configs) { + pa_card_config *c; + + while ((c = pa_hashmap_steal_first(data->configs))) + pa_card_config_free(c); + + pa_hashmap_free(data->configs, NULL, NULL); + } + + pa_xfree(data->name); +} + +pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) { + pa_card *c; + const char *name; + + pa_core_assert_ref(core); + pa_assert(data); + pa_assert(data->name); + + c = pa_xnew(pa_card, 1); + + if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_CARD, c, data->namereg_fail))) { + pa_xfree(c); + return NULL; + } + + pa_card_new_data_set_name(data, name); + + if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_NEW], data) < 0) { + pa_xfree(c); + pa_namereg_unregister(core, name); + return NULL; + } + + c->core = core; + c->name = pa_xstrdup(data->name); + c->proplist = pa_proplist_copy(data->proplist); + c->driver = pa_xstrdup(data->driver); + c->module = data->module; + + c->sinks = pa_idxset_new(NULL, NULL); + c->sources = pa_idxset_new(NULL, NULL); + + c->configs = data->configs; + data->configs = NULL; + c->active_config = data->active_config; + data->active_config = NULL; + + c->userdata = NULL; + c->set_config = NULL; + + pa_assert_se(pa_idxset_put(core->cards, c, &c->index) >= 0); + + pa_log_info("Created %u \"%s\"", c->index, c->name); + pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_NEW, c->index); + + pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_PUT], c); + return c; +} + +void pa_card_free(pa_card *c) { + pa_core *core; + pa_card_config *config; + + pa_assert(c); + pa_assert(c->core); + + core = c->core; + + pa_hook_fire(&core->hooks[PA_CORE_HOOK_CARD_UNLINK], c); + + pa_namereg_unregister(core, c->name); + + pa_idxset_remove_by_data(c->core->cards, c, NULL); + + pa_log_info("Freed %u \"%s\"", c->index, c->name); + + pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); + + pa_assert(pa_idxset_isempty(c->sinks)); + pa_idxset_free(c->sinks, NULL, NULL); + pa_assert(pa_idxset_isempty(c->sources)); + pa_idxset_free(c->sources, NULL, NULL); + + while ((config = pa_hashmap_steal_first(c->configs))) + pa_card_config_free(config); + + pa_hashmap_free(c->configs, NULL, NULL); + + pa_proplist_free(c->proplist); + pa_xfree(c->driver); + pa_xfree(c->name); + pa_xfree(c); + + pa_core_check_idle(core); +} + +int pa_card_set_config(pa_card *c, const char *name) { + pa_card_config *config; + pa_assert(c); + + if (!c->set_config) { + pa_log_warn("set_config() operation not implemented for card %u", c->index); + return -1; + } + + if (!c->configs) + return -1; + + if (!(config = pa_hashmap_get(c->configs, name))) + return -1; + + if (c->set_config(c, config) < 0) + return -1; + + pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index); + + return 0; +} diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h new file mode 100644 index 00000000..40e4a3ee --- /dev/null +++ b/src/pulsecore/card.h @@ -0,0 +1,91 @@ +#ifndef foopulsecardhfoo +#define foopulsecardhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +typedef struct pa_card pa_card; + +#include <pulse/proplist.h> +#include <pulsecore/core.h> +#include <pulsecore/module.h> +#include <pulsecore/idxset.h> + +typedef struct pa_card_config { + char *name; + + pa_bool_t optical_sink:1; + pa_bool_t optical_source:1; + + unsigned n_sinks; + unsigned n_sources; + + unsigned max_sink_channels; + unsigned max_source_channels; +} pa_card_config; + +struct pa_card { + uint32_t index; + pa_core *core; + + char *name; + + pa_proplist *proplist; + pa_module *module; + char *driver; + + pa_idxset *sinks; + pa_idxset *sources; + + pa_hashmap *configs; + pa_card_config *active_config; + + void *userdata; + + int (*set_config)(pa_card *c, pa_card_config *config); +}; + +typedef struct pa_card_new_data { + char *name; + + pa_proplist *proplist; + const char *driver; + pa_module *module; + + pa_hashmap *configs; + pa_card_config *active_config; + + pa_bool_t namereg_fail:1; +} pa_card_new_data; + +pa_card_config *pa_card_config_new(const char *name); +void pa_card_config_free(pa_card_config *c); + +pa_card_new_data *pa_card_new_data_init(pa_card_new_data *data); +void pa_card_new_data_set_name(pa_card_new_data *data, const char *name); +void pa_card_new_data_done(pa_card_new_data *data); + +pa_card *pa_card_new(pa_core *c, pa_card_new_data *data); +void pa_card_free(pa_card *c); + +int pa_card_set_config(pa_card *c, const char *name); + +#endif diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 07d55d07..93d6bbe6 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -80,6 +80,7 @@ static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_cards(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); @@ -137,6 +138,7 @@ static const struct command commands[] = { { "list-clients", pa_cli_command_clients, "List loaded clients", 1 }, { "list-sink-inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 }, { "list-source-outputs", pa_cli_command_source_outputs, "List source outputs", 1 }, + { "list-cards", pa_cli_command_cards, "List cards", 1 }, { "stat", pa_cli_command_stat, "Show memory block statistics", 1 }, { "info", pa_cli_command_info, "Show comprehensive status", 1 }, { "ls", pa_cli_command_info, NULL, 1 }, @@ -254,6 +256,20 @@ static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, p return 0; } +static int pa_cli_command_cards(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { + char *s; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + pa_assert_se(s = pa_card_list_to_string(c)); + pa_strbuf_puts(buf, s); + pa_xfree(s); + return 0; +} + static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { char *s; @@ -382,6 +398,7 @@ static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b pa_cli_command_sinks(c, t, buf, fail); pa_cli_command_sources(c, t, buf, fail); pa_cli_command_clients(c, t, buf, fail); + pa_cli_command_cards(c, t, buf, fail); pa_cli_command_sink_inputs(c, t, buf, fail); pa_cli_command_source_outputs(c, t, buf, fail); pa_cli_command_scache_list(c, t, buf, fail); diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index 362a9791..5d78ce64 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -97,6 +97,38 @@ char *pa_client_list_to_string(pa_core *c) { return pa_strbuf_tostring_free(s); } +char *pa_card_list_to_string(pa_core *c) { + pa_strbuf *s; + pa_card *card; + uint32_t idx = PA_IDXSET_INVALID; + pa_assert(c); + + s = pa_strbuf_new(); + + pa_strbuf_printf(s, "%u card(s) available in.\n", pa_idxset_size(c->cards)); + + for (card = pa_idxset_first(c->cards, &idx); card; card = pa_idxset_next(c->cards, &idx)) { + char *t; + pa_strbuf_printf( + s, + " index: %u\n" + "\tname: <%s>\n" + "\tdriver: <%s>\n", + card->index, + card->name, + card->driver); + + if (card->module) + pa_strbuf_printf(s, "\towner module: %u\n", card->module->index); + + t = pa_proplist_to_string(card->proplist); + pa_strbuf_printf(s, "\tproperties:\n%s", t); + pa_xfree(t); + } + + return pa_strbuf_tostring_free(s); +} + char *pa_sink_list_to_string(pa_core *c) { pa_strbuf *s; pa_sink *sink; @@ -174,6 +206,8 @@ char *pa_sink_list_to_string(pa_core *c) { pa_sink_used_by(sink), pa_sink_linked_by(sink)); + if (sink->card) + pa_strbuf_printf(s, "\tcard: %u <%s>\n", sink->card->index, sink->card->name); if (sink->module) pa_strbuf_printf(s, "\tmodule: %u\n", sink->module->index); @@ -260,6 +294,8 @@ char *pa_source_list_to_string(pa_core *c) { if (source->monitor_of) pa_strbuf_printf(s, "\tmonitor_of: %u\n", source->monitor_of->index); + if (source->card) + pa_strbuf_printf(s, "\tcard: %u <%s>\n", source->card->index, source->card->name); if (source->module) pa_strbuf_printf(s, "\tmodule: %u\n", source->module->index); @@ -508,7 +544,7 @@ char *pa_full_status_string(pa_core *c) { s = pa_strbuf_new(); - for (i = 0; i < 8; i++) { + for (i = 0; i < 9; i++) { char *t = NULL; switch (i) { @@ -528,12 +564,15 @@ char *pa_full_status_string(pa_core *c) { t = pa_client_list_to_string(c); break; case 5: - t = pa_module_list_to_string(c); + t = pa_card_list_to_string(c); break; case 6: - t = pa_scache_list_to_string(c); + t = pa_module_list_to_string(c); break; case 7: + t = pa_scache_list_to_string(c); + break; + case 8: t = pa_autoload_list_to_string(c); break; } diff --git a/src/pulsecore/cli-text.h b/src/pulsecore/cli-text.h index f4cb97a5..167565e5 100644 --- a/src/pulsecore/cli-text.h +++ b/src/pulsecore/cli-text.h @@ -31,6 +31,7 @@ char *pa_sink_input_list_to_string(pa_core *c); char *pa_source_output_list_to_string(pa_core *c); char *pa_sink_list_to_string(pa_core *core); char *pa_source_list_to_string(pa_core *c); +char *pa_card_list_to_string(pa_core *c); char *pa_client_list_to_string(pa_core *c); char *pa_module_list_to_string(pa_core *c); char *pa_scache_list_to_string(pa_core *c); @@ -39,4 +40,3 @@ char *pa_autoload_list_to_string(pa_core *c); char *pa_full_status_string(pa_core *c); #endif - diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c index 67bf1e73..25a4f748 100644 --- a/src/pulsecore/cli.c +++ b/src/pulsecore/cli.c @@ -67,20 +67,33 @@ static void client_kill(pa_client *c); pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) { char cname[256]; pa_cli *c; + pa_client_new_data data; + pa_client *client; + pa_assert(io); + pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); + + pa_client_new_data_init(&data); + data.driver = __FILE__; + data.module = m; + pa_proplist_sets(data.proplist, PA_PROP_APPLICATION_NAME, cname); + client = pa_client_new(core, &data); + pa_client_new_data_done(&data); + + if (!client) + return NULL; + c = pa_xnew(pa_cli, 1); c->core = core; + c->client = client; pa_assert_se(c->line = pa_ioline_new(io)); c->userdata = NULL; c->eof_callback = NULL; - pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname)); - pa_assert_se(c->client = pa_client_new(core, __FILE__, cname)); c->client->kill = client_kill; c->client->userdata = c; - c->client->module = m; pa_ioline_set_callback(c->line, line_callback, c); pa_ioline_puts(c->line, "Welcome to PulseAudio! Use \"help\" for usage information.\n"PROMPT); diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c index ab6e5df4..1e65fcd9 100644 --- a/src/pulsecore/client.c +++ b/src/pulsecore/client.c @@ -37,27 +37,49 @@ #include "client.h" -pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) { +pa_client_new_data* pa_client_new_data_init(pa_client_new_data *data) { + pa_assert(data); + + memset(data, 0, sizeof(*data)); + data->proplist = pa_proplist_new(); + + return data; +} + +void pa_client_new_data_done(pa_client_new_data *data) { + pa_assert(data); + + pa_proplist_free(data->proplist); +} + +pa_client *pa_client_new(pa_core *core, pa_client_new_data *data) { pa_client *c; pa_core_assert_ref(core); + pa_assert(data); + + if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_CLIENT_NEW], data) < 0) + return NULL; c = pa_xnew(pa_client, 1); c->core = core; - c->proplist = pa_proplist_new(); - if (name) - pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name); - c->driver = pa_xstrdup(driver); - c->module = NULL; + c->proplist = pa_proplist_copy(data->proplist); + c->driver = pa_xstrdup(data->driver); + c->module = data->module; + + c->sink_inputs = pa_idxset_new(NULL, NULL); + c->source_outputs = pa_idxset_new(NULL, NULL); - c->kill = NULL; c->userdata = NULL; + c->kill = NULL; pa_assert_se(pa_idxset_put(core->clients, c, &c->index) >= 0); - pa_log_info("Created %u \"%s\"", c->index, pa_strnull(name)); + pa_log_info("Created %u \"%s\"", c->index, pa_strnull(pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME))); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); + pa_hook_fire(&core->hooks[PA_CORE_HOOK_CLIENT_PUT], c); + pa_core_check_idle(core); return c; @@ -70,10 +92,19 @@ void pa_client_free(pa_client *c) { pa_assert(c->core); core = c->core; + + pa_hook_fire(&core->hooks[PA_CORE_HOOK_CLIENT_UNLINK], c); + pa_idxset_remove_by_data(c->core->clients, c, NULL); pa_log_info("Freed %u \"%s\"", c->index, pa_strnull(pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME))); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); + + pa_assert(pa_idxset_isempty(c->sink_inputs)); + pa_idxset_free(c->sink_inputs, NULL, NULL); + pa_assert(pa_idxset_isempty(c->source_outputs)); + pa_idxset_free(c->source_outputs, NULL, NULL); + pa_proplist_free(c->proplist); pa_xfree(c->driver); pa_xfree(c); diff --git a/src/pulsecore/client.h b/src/pulsecore/client.h index 28d1fe5f..48e9bc7a 100644 --- a/src/pulsecore/client.h +++ b/src/pulsecore/client.h @@ -42,11 +42,24 @@ struct pa_client { pa_module *module; char *driver; - void (*kill)(pa_client *c); + pa_idxset *sink_inputs; + pa_idxset *source_outputs; + void *userdata; + + void (*kill)(pa_client *c); }; -pa_client *pa_client_new(pa_core *c, const char *driver, const char *name); +typedef struct pa_client_new_data { + pa_proplist *proplist; + const char *driver; + pa_module *module; +} pa_client_new_data; + +pa_client_new_data *pa_client_new_data_init(pa_client_new_data *data); +void pa_client_new_data_done(pa_client_new_data *data); + +pa_client *pa_client_new(pa_core *c, pa_client_new_data *data); /* This function should be called only by the code that created the client */ void pa_client_free(pa_client *c); diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index 5761bbc7..20764325 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -97,6 +97,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) { 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->default_source_name = c->default_sink_name = NULL; @@ -167,6 +168,9 @@ static void core_free(pa_object *o) { pa_assert(pa_idxset_isempty(c->clients)); pa_idxset_free(c->clients, NULL, NULL); + pa_assert(pa_idxset_isempty(c->cards)); + pa_idxset_free(c->cards, NULL, NULL); + pa_assert(pa_idxset_isempty(c->sinks)); pa_idxset_free(c->sinks, NULL, NULL); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index f796fb93..87ea4ab6 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -76,6 +76,12 @@ typedef enum pa_core_hook { PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST, PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED, PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED, + PA_CORE_HOOK_CLIENT_NEW, + PA_CORE_HOOK_CLIENT_PUT, + PA_CORE_HOOK_CLIENT_UNLINK, + PA_CORE_HOOK_CARD_NEW, + PA_CORE_HOOK_CARD_PUT, + PA_CORE_HOOK_CARD_UNLINK, PA_CORE_HOOK_MAX } pa_core_hook_t; @@ -93,7 +99,7 @@ struct pa_core { pa_mainloop_api *mainloop; /* idxset of all kinds of entities */ - pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache, *autoload_idxset; + pa_idxset *clients, *cards, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache, *autoload_idxset; /* Some hashmaps for all sorts of entities */ pa_hashmap *namereg, *autoload_hashmap, *shared; diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index ecd8def8..c1a434ae 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -109,7 +109,7 @@ const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t if (!*name) return NULL; - if ((type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE) && + if ((type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE || type == PA_NAMEREG_CARD) && !pa_namereg_is_valid_name(name)) { if (fail) diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index f4581006..8ce548a7 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -30,7 +30,8 @@ typedef enum pa_namereg_type { PA_NAMEREG_SINK, PA_NAMEREG_SOURCE, - PA_NAMEREG_SAMPLE + PA_NAMEREG_SAMPLE, + PA_NAMEREG_CARD } pa_namereg_type_t; void pa_namereg_free(pa_core *c); diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c index 86edfe98..758c0dee 100644 --- a/src/pulsecore/play-memblockq.c +++ b/src/pulsecore/play-memblockq.c @@ -109,7 +109,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s * we are heard right-away. */ if (PA_SINK_INPUT_IS_LINKED(state) && i->thread_info.state == PA_SINK_INPUT_INIT) - pa_sink_input_request_rewind(i, 0, FALSE, TRUE); + pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE); } static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) { diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index 460119a9..6524b684 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -1238,7 +1238,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) { pa_log_debug("Requesting rewind due to end of underrun."); - pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE); + pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE, FALSE); } /* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */ @@ -1377,7 +1377,9 @@ static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timev void pa_esound_protocol_connect(pa_esound_protocol *p, pa_iochannel *io, pa_esound_options *o) { connection *c; - char cname[256], pname[128]; + char pname[128]; + pa_client_new_data data; + pa_client *client; pa_assert(p); pa_assert(io); @@ -1389,6 +1391,18 @@ void pa_esound_protocol_connect(pa_esound_protocol *p, pa_iochannel *io, pa_esou return; } + pa_client_new_data_init(&data); + data.module = o->module; + data.driver = __FILE__; + pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname)); + pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "EsounD client (%s)", pname); + pa_proplist_sets(data.proplist, "esound-protocol.peer", pname); + client = pa_client_new(p->core, &data); + pa_client_new_data_done(&data); + + if (!client) + return; + c = pa_msgobject_new(connection); c->parent.parent.free = connection_free; c->parent.process_msg = connection_process_msg; @@ -1396,11 +1410,7 @@ void pa_esound_protocol_connect(pa_esound_protocol *p, pa_iochannel *io, pa_esou c->io = io; pa_iochannel_set_callback(c->io, io_callback, c); - pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname)); - pa_snprintf(cname, sizeof(cname), "EsounD client (%s)", pname); - c->client = pa_client_new(p->core, __FILE__, cname); - pa_proplist_sets(c->client->proplist, "esound-protocol.peer", pname); - c->client->module = o->module; + c->client = client; c->client->kill = client_kill_cb; c->client->userdata = c; diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 3c1e5761..d99e212f 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1240,7 +1240,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) { pa_log_debug("Requesting rewind due to end of underrun."); pa_sink_input_request_rewind(s->sink_input, (size_t) (s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for), - FALSE, TRUE); + FALSE, TRUE, FALSE); } } else { @@ -1253,7 +1253,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) { * let's have it usk us again */ pa_log_debug("Requesting rewind due to rewrite."); - pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), TRUE, FALSE); + pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), TRUE, FALSE, FALSE); } } @@ -4214,7 +4214,9 @@ static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timev void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o) { pa_native_connection *c; - char cname[256], pname[128]; + char pname[128]; + pa_client *client; + pa_client_new_data data; pa_assert(p); pa_assert(io); @@ -4226,6 +4228,18 @@ void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_nati return; } + pa_client_new_data_init(&data); + data.module = o->module; + data.driver = __FILE__; + pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname)); + pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "Native client (%s)", pname); + pa_proplist_sets(data.proplist, "native-protocol.peer", pname); + client = pa_client_new(p->core, &data); + pa_client_new_data_done(&data); + + if (!client) + return; + c = pa_msgobject_new(pa_native_connection); c->parent.parent.free = native_connection_free; c->parent.process_msg = native_connection_process_msg; @@ -4257,13 +4271,9 @@ void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_nati c->is_local = pa_iochannel_socket_is_local(io); c->version = 8; - pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname)); - pa_snprintf(cname, sizeof(cname), "Native client (%s)", pname); - c->client = pa_client_new(p->core, __FILE__, cname); - pa_proplist_sets(c->client->proplist, "native-protocol.peer", pname); + c->client = client; c->client->kill = client_kill_cb; c->client->userdata = c; - c->client->module = o->module; c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 743bf2ee..a754669c 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -323,7 +323,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) { pa_log_debug("Requesting rewind due to end of underrun."); - pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE); + pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE, FALSE); } /* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */ @@ -476,7 +476,8 @@ static void io_callback(pa_iochannel*io, void *userdata) { void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simple_options *o) { connection *c = NULL; - char cname[256], pname[128]; + char pname[128]; + pa_client_new_data client_data; pa_assert(p); pa_assert(io); @@ -505,11 +506,18 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp c->playback.underrun = TRUE; pa_atomic_store(&c->playback.missing, 0); + pa_client_new_data_init(&client_data); + client_data.module = o->module; + client_data.driver = __FILE__; pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname)); - pa_snprintf(cname, sizeof(cname), "Simple client (%s)", pname); - pa_assert_se(c->client = pa_client_new(p->core, __FILE__, cname)); - pa_proplist_sets(c->client->proplist, "simple-protocol.peer", pname); - c->client->module = o->module; + pa_proplist_setf(client_data.proplist, PA_PROP_APPLICATION_NAME, "Simple client (%s)", pname); + pa_proplist_sets(client_data.proplist, "simple-protocol.peer", pname); + c->client = pa_client_new(p->core, &client_data); + pa_client_new_data_done(&client_data); + + if (!c->client) + goto fail; + c->client->kill = client_kill_cb; c->client->userdata = c; diff --git a/src/pulsecore/shared.c b/src/pulsecore/shared.c index 4c1ad80a..d6e42dd8 100644 --- a/src/pulsecore/shared.c +++ b/src/pulsecore/shared.c @@ -115,7 +115,7 @@ void pa_shared_cleanup(pa_core *c) { pa_strbuf *s = pa_strbuf_new(); pa_shared_dump(c, s); - pa_log_debug(pa_strbuf_tostring(s)); + pa_log_debug("%s", pa_strbuf_tostring(s)); pa_strbuf_free(s); pa_assert(pa_hashmap_isempty(c->shared)); } diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 33490cc6..185350fa 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -265,6 +265,7 @@ pa_sink_input* pa_sink_input_new( i->thread_info.requested_sink_latency = (pa_usec_t) -1; i->thread_info.rewrite_nbytes = 0; i->thread_info.rewrite_flush = FALSE; + i->thread_info.dont_rewind_render = FALSE; i->thread_info.underrun_for = (uint64_t) -1; i->thread_info.playing_for = 0; i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); @@ -282,6 +283,9 @@ pa_sink_input* pa_sink_input_new( pa_assert_se(pa_idxset_put(core->sink_inputs, pa_sink_input_ref(i), &i->index) == 0); pa_assert_se(pa_idxset_put(i->sink->inputs, i, NULL) == 0); + if (i->client) + pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0); + pa_log_info("Created input %u \"%s\" on %s with sample spec %s and channel map %s", i->index, pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)), @@ -371,6 +375,9 @@ void pa_sink_input_unlink(pa_sink_input *i) { if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL)) pa_sink_input_unref(i); + if (i->client) + pa_idxset_remove_by_data(i->client->sink_inputs, i, NULL); + while ((o = pa_idxset_first(i->direct_outputs, NULL))) { pa_assert(o != p); pa_source_output_kill(o); @@ -658,7 +665,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam lbq = pa_memblockq_get_length(i->thread_info.render_memblockq); - if (nbytes > 0) { + if (nbytes > 0 && !i->thread_info.dont_rewind_render) { pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes); pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes); } @@ -714,6 +721,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam i->thread_info.rewrite_nbytes = 0; i->thread_info.rewrite_flush = FALSE; + i->thread_info.dont_rewind_render = FALSE; } /* Called from thread context */ @@ -1091,7 +1099,7 @@ void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state /* This will tell the implementing sink input driver to rewind * so that the unplayed already mixed data is not lost */ - pa_sink_input_request_rewind(i, 0, TRUE, TRUE); + pa_sink_input_request_rewind(i, 0, TRUE, TRUE, FALSE); } else if (uncorking) { @@ -1102,7 +1110,7 @@ void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state /* OK, we're being uncorked. Make sure we're not rewound when * the hw buffer is remixed and request a remix. */ - pa_sink_input_request_rewind(i, 0, FALSE, TRUE); + pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE); } } @@ -1115,12 +1123,12 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t case PA_SINK_INPUT_MESSAGE_SET_VOLUME: i->thread_info.volume = *((pa_cvolume*) userdata); - pa_sink_input_request_rewind(i, 0, TRUE, FALSE); + pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE); return 0; case PA_SINK_INPUT_MESSAGE_SET_MUTE: i->thread_info.muted = PA_PTR_TO_UINT(userdata); - pa_sink_input_request_rewind(i, 0, TRUE, FALSE); + pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE); return 0; case PA_SINK_INPUT_MESSAGE_GET_LATENCY: { @@ -1195,7 +1203,7 @@ pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) { } /* Called from IO context */ -void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sample spec */, pa_bool_t rewrite, pa_bool_t flush) { +void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sample spec */, pa_bool_t rewrite, pa_bool_t flush, pa_bool_t dont_rewind_render) { size_t lbq; /* If 'rewrite' is TRUE the sink is rewound as far as requested @@ -1206,7 +1214,9 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam * If 'rewrite' is FALSE the sink is rewound as far as requested * and possible and the already rendered data is dropped so that * in the next iteration we read new data from the - * implementor. This implies 'flush' is TRUE. */ + * implementor. This implies 'flush' is TRUE. If + * dont_rewind_render is TRUE then the render memblockq is not + * rewound. */ pa_sink_input_assert_ref(i); @@ -1219,6 +1229,7 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam return; pa_assert(rewrite || flush); + pa_assert(!dont_rewind_render || !rewrite); /* Calculate how much we can rewind locally without having to * touch the sink */ @@ -1253,6 +1264,10 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam i->thread_info.rewrite_flush || (flush && i->thread_info.rewrite_nbytes != 0); + i->thread_info.dont_rewind_render = + i->thread_info.dont_rewind_render || + dont_rewind_render; + if (nbytes != (size_t) -1) { /* Transform to sink domain */ diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 8cfe32bc..3d2a8c0d 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -179,8 +179,9 @@ struct pa_sink_input { /* We maintain a history of resampled audio data here. */ pa_memblockq *render_memblockq; + /* 0: rewrite nothing, (size_t) -1: rewrite everything, otherwise how many bytes to rewrite */ size_t rewrite_nbytes; - pa_bool_t rewrite_flush; + pa_bool_t rewrite_flush, dont_rewind_render; uint64_t underrun_for, playing_for; pa_sink_input *sync_prev, *sync_next; @@ -277,7 +278,7 @@ fully -- or at all. If the request for a rewrite was successful, the sink driver will call ->rewind() and pass the number of bytes that could be rewound in the HW device. This functionality is required for implementing the "zero latency" write-through functionality. */ -void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t rewrite, pa_bool_t flush); +void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t rewrite, pa_bool_t flush, pa_bool_t dont_rewind_render); void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 809e8273..d1d68cdd 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -183,6 +183,7 @@ pa_sink* pa_sink_new( s->proplist = pa_proplist_copy(data->proplist); s->driver = pa_xstrdup(data->driver); s->module = data->module; + s->card = data->card; s->sample_spec = data->sample_spec; s->channel_map = data->channel_map; @@ -225,6 +226,9 @@ pa_sink* pa_sink_new( pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0); + 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", s->index, s->name, @@ -237,6 +241,7 @@ pa_sink* pa_sink_new( source_data.name = pa_sprintf_malloc("%s.monitor", name); source_data.driver = data->driver; source_data.module = data->module; + source_data.card = data->card; dn = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION); pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name); @@ -360,6 +365,9 @@ void pa_sink_unlink(pa_sink* s) { pa_namereg_unregister(s->core, s->name); pa_idxset_remove_by_data(s->core->sinks, s, NULL); + if (s->card) + pa_idxset_remove_by_data(s->card->sinks, s, NULL); + while ((i = pa_idxset_first(s->inputs, NULL))) { pa_assert(i != j); pa_sink_input_kill(i); @@ -644,7 +652,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_assert(length > 0); - n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, &length, info, MAX_MIX_CHANNELS) : 0; + n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS); if (n == 0) { @@ -687,8 +695,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { result->index = 0; } - if (s->thread_info.state == PA_SINK_RUNNING) - inputs_drop(s, info, n, result); + inputs_drop(s, info, n, result); pa_sink_unref(s); } @@ -718,7 +725,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_assert(length > 0); - n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, &length, info, MAX_MIX_CHANNELS) : 0; + n = fill_mix_info(s, &length, info, MAX_MIX_CHANNELS); if (n == 0) { if (target->length > length) @@ -767,8 +774,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_memblock_release(target->memblock); } - if (s->thread_info.state == PA_SINK_RUNNING) - inputs_drop(s, info, n, target); + inputs_drop(s, info, n, target); pa_sink_unref(s); } diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index fb5e1e89..507c1603 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -38,6 +38,7 @@ typedef struct pa_sink pa_sink; #include <pulsecore/refcnt.h> #include <pulsecore/msgobject.h> #include <pulsecore/rtpoll.h> +#include <pulsecore/card.h> #define PA_MAX_INPUTS_PER_SINK 32 @@ -70,6 +71,7 @@ struct pa_sink { pa_proplist *proplist; pa_module *module; /* may be NULL */ + pa_card *card; /* may be NULL */ pa_sample_spec sample_spec; pa_channel_map channel_map; @@ -187,6 +189,7 @@ typedef struct pa_sink_new_data { const char *driver; pa_module *module; + pa_card *card; pa_sample_spec sample_spec; pa_channel_map channel_map; diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index c30c16eb..b78afca8 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -133,7 +133,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s * we are heard right-away. */ if (PA_SINK_INPUT_IS_LINKED(state) && i->thread_info.state == PA_SINK_INPUT_INIT) - pa_sink_input_request_rewind(i, 0, FALSE, TRUE); + pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE); } /* Called from IO thread context */ diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index e3d0d8b2..b1c65d1c 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -223,6 +223,9 @@ pa_source_output* pa_source_output_new( pa_assert_se(pa_idxset_put(core->source_outputs, o, &o->index) == 0); pa_assert_se(pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL) == 0); + if (o->client) + pa_assert_se(pa_idxset_put(o->client->source_outputs, o, NULL) >= 0); + if (o->direct_on_input) pa_assert_se(pa_idxset_put(o->direct_on_input->direct_outputs, o, NULL) == 0); @@ -290,6 +293,9 @@ void pa_source_output_unlink(pa_source_output*o) { if (pa_idxset_remove_by_data(o->source->outputs, o, NULL)) pa_source_output_unref(o); + if (o->client) + pa_idxset_remove_by_data(o->client->source_outputs, o, NULL); + update_n_corked(o, PA_SOURCE_OUTPUT_UNLINKED); o->state = PA_SOURCE_OUTPUT_UNLINKED; diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index e65c5ce7..676a6b40 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -174,6 +174,7 @@ pa_source* pa_source_new( s->proplist = pa_proplist_copy(data->proplist); s->driver = pa_xstrdup(data->driver); s->module = data->module; + s->card = data->card; s->sample_spec = data->sample_spec; s->channel_map = data->channel_map; @@ -212,6 +213,9 @@ pa_source* pa_source_new( pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0); + 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", s->index, s->name, @@ -314,6 +318,9 @@ void pa_source_unlink(pa_source *s) { pa_namereg_unregister(s->core, s->name); pa_idxset_remove_by_data(s->core->sources, s, NULL); + if (s->card) + pa_idxset_remove_by_data(s->card->sinks, s, NULL); + while ((o = pa_idxset_first(s->outputs, NULL))) { pa_assert(o != j); pa_source_output_kill(o); @@ -429,9 +436,6 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) { pa_assert(PA_SOURCE_IS_OPENED(s->thread_info.state)); pa_assert(chunk); - if (s->thread_info.state != PA_SOURCE_RUNNING) - return; - if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) { pa_memchunk vchunk = *chunk; @@ -470,9 +474,6 @@ void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk * pa_assert(o->thread_info.direct_on_input); pa_assert(chunk); - if (s->thread_info.state != PA_SOURCE_RUNNING) - return; - if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) { pa_memchunk vchunk = *chunk; diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index fd8c4bd6..48240996 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -41,6 +41,7 @@ typedef struct pa_source pa_source; #include <pulsecore/msgobject.h> #include <pulsecore/rtpoll.h> #include <pulsecore/source-output.h> +#include <pulsecore/card.h> #define PA_MAX_OUTPUTS_PER_SOURCE 32 @@ -73,6 +74,7 @@ struct pa_source { pa_proplist *proplist; pa_module *module; /* may be NULL */ + pa_card *card; /* may be NULL */ pa_sample_spec sample_spec; pa_channel_map channel_map; @@ -174,6 +176,7 @@ typedef struct pa_source_new_data { const char *driver; pa_module *module; + pa_card *card; pa_sample_spec sample_spec; pa_channel_map channel_map; |