diff --git a/src/Makefile.am b/src/Makefile.am index 9d96a9bbd..4efd4c4b0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -882,6 +882,7 @@ libpulsecore_@PA_MAJORMINOR@_la_SOURCES = \ pulsecore/module.c pulsecore/module.h \ pulsecore/msgobject.c pulsecore/msgobject.h \ pulsecore/namereg.c pulsecore/namereg.h \ + pulsecore/node.c pulsecore/node.h \ pulsecore/object.c pulsecore/object.h \ pulsecore/play-memblockq.c pulsecore/play-memblockq.h \ pulsecore/play-memchunk.c pulsecore/play-memchunk.h \ diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c index e6f2dfcba..cc8915c48 100644 --- a/src/pulsecore/core.c +++ b/src/pulsecore/core.c @@ -99,6 +99,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, bool shared, size_t shm_size) { c->source_outputs = pa_idxset_new(NULL, NULL); c->modules = pa_idxset_new(NULL, NULL); c->scache = pa_idxset_new(NULL, NULL); + c->nodes = 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); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index f268e4249..b2df5b522 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -139,7 +139,7 @@ struct pa_core { pa_mainloop_api *mainloop; /* idxset of all kinds of entities */ - pa_idxset *clients, *cards, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache; + pa_idxset *clients, *cards, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache, *nodes; /* Some hashmaps for all sorts of entities */ pa_hashmap *namereg, *shared; diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index 7704abe49..0b7bc898b 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -119,7 +119,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 || type == PA_NAMEREG_CARD) && + if ((type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE || type == PA_NAMEREG_CARD || type == PA_NAMEREG_NODE) && !pa_namereg_is_valid_name(name)) { if (fail) diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index afb3532a8..0fd0b4223 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -31,7 +31,8 @@ typedef enum pa_namereg_type { PA_NAMEREG_SINK, PA_NAMEREG_SOURCE, PA_NAMEREG_SAMPLE, - PA_NAMEREG_CARD + PA_NAMEREG_CARD, + PA_NAMEREG_NODE } pa_namereg_type_t; const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, bool fail); diff --git a/src/pulsecore/node.c b/src/pulsecore/node.c new file mode 100644 index 000000000..3f1ca7ccc --- /dev/null +++ b/src/pulsecore/node.c @@ -0,0 +1,164 @@ +/*** + This file is part of PulseAudio. + + Copyright (c) 2012 Intel Corporation + Janos Kovacs + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "node.h" + +pa_node_new_data *pa_node_new_data_init(pa_node_new_data *data) { + pa_assert(data); + + pa_zero(*data); + data->direction = PA_DIRECTION_OUTPUT; + + return data; +} + +void pa_node_new_data_set_fallback_name_prefix(pa_node_new_data *data, const char* prefix) { + pa_assert(data); + + pa_xfree(data->fallback_name_prefix); + data->fallback_name_prefix = pa_xstrdup(prefix); +} + +void pa_node_new_data_set_description(pa_node_new_data *data, const char *description) { + pa_assert(data); + + pa_xfree(data->description); + data->description = pa_xstrdup(description); +} + +void pa_node_new_data_set_type(pa_node_new_data *data, pa_node_type_t type) { + pa_assert(data); + + data->type = type; +} + +void pa_node_new_data_set_direction(pa_node_new_data *data, pa_direction_t direction) { + pa_assert(data); + + data->direction = direction; +} + +void pa_node_new_data_done(pa_node_new_data *data) { + pa_assert(data); + + pa_xfree(data->description); + pa_xfree(data->fallback_name_prefix); +} + +pa_node *pa_node_new(pa_core *core, pa_node_new_data *data) { + bool use_fallback_name_prefix; + pa_strbuf *name_buf; + char *name = NULL; + pa_node *n = NULL; + const char *registered_name = NULL; + + pa_assert(core); + pa_assert(data); + pa_assert(data->description); + + use_fallback_name_prefix = !!data->fallback_name_prefix; + + name_buf = pa_strbuf_new(); + + /* Automatic name generation code will appear here... */ + + if (use_fallback_name_prefix) + pa_strbuf_printf(name_buf, "%s-", data->fallback_name_prefix); + + pa_strbuf_puts(name_buf, data->direction == PA_DIRECTION_OUTPUT ? "output" : "input"); + + name = pa_strbuf_tostring_free(name_buf); + + n = pa_xnew0(pa_node, 1); + n->core = core; + n->state = PA_NODE_STATE_INIT; + + if (!(registered_name = pa_namereg_register(core, name, PA_NAMEREG_NODE, n, false))) { + pa_log("Failed to register name %s.", name); + goto fail; + } + + pa_xfree(name); + + n->name = pa_xstrdup(registered_name); + n->description = pa_xstrdup(data->description); + n->type = data->type; + n->direction = data->direction; + + return n; + +fail: + pa_xfree(name); + pa_node_free(n); + + return NULL; +} + +void pa_node_free(pa_node *node) { + pa_assert(node); + + if (node->state == PA_NODE_STATE_LINKED) + pa_node_unlink(node); + + pa_xfree(node->description); + + if (node->name) { + pa_namereg_unregister(node->core, node->name); + pa_xfree(node->name); + } + + pa_xfree(node); +} + +void pa_node_put(pa_node *node) { + pa_assert(node); + pa_assert(node->state == PA_NODE_STATE_INIT); + pa_assert(node->owner); + + pa_assert_se(pa_idxset_put(node->core->nodes, node, &node->index) >= 0); + + node->state = PA_NODE_STATE_LINKED; + + pa_log_debug("Created node %s.", node->name); +} + +void pa_node_unlink(pa_node *node) { + pa_assert(node); + pa_assert(node->state != PA_NODE_STATE_INIT); + + if (node->state == PA_NODE_STATE_UNLINKED) + return; + + pa_log_debug("Unlinking node %s.", node->name); + + pa_assert_se(pa_idxset_remove_by_index(node->core->nodes, node->index)); + + node->state = PA_NODE_STATE_UNLINKED; +} diff --git a/src/pulsecore/node.h b/src/pulsecore/node.h new file mode 100644 index 000000000..305853fac --- /dev/null +++ b/src/pulsecore/node.h @@ -0,0 +1,89 @@ +#ifndef foonodehfoo +#define foonodehfoo + +/*** + This file is part of PulseAudio. + + Copyright (c) 2012 Intel Corporation + Janos Kovacs + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +typedef struct pa_node_new_data pa_node_new_data; +typedef struct pa_node pa_node; + +#include + +/* The node type determines what the owner pointer of pa_node points to. */ +typedef enum { + PA_NODE_TYPE_PORT, /* owner: pa_port */ + PA_NODE_TYPE_SINK, /* owner: pa_sink */ + PA_NODE_TYPE_SOURCE, /* owner: pa_source */ + PA_NODE_TYPE_SINK_INPUT, /* owner: pa_sink_input */ + PA_NODE_TYPE_SOURCE_OUTPUT /* owner: pa_source_output */ +} pa_node_type_t; + +typedef enum { + PA_NODE_STATE_INIT, + PA_NODE_STATE_LINKED, + PA_NODE_STATE_UNLINKED +} pa_node_state_t; + +struct pa_node_new_data { + /* Node names are generated automatically as much as possible, but + * sometimes the available information for automatic generation isn't + * sufficient, in which case the generated node names would be just "input" + * or "output". In such cases the fallback name prefix, if set, is used to + * generate slightly more informative names, such as "jack-output" for JACK + * output nodes (in this example the fallback prefix would be "jack"). */ + char *fallback_name_prefix; + + char *description; + + pa_node_type_t type; + pa_direction_t direction; +}; + +struct pa_node { + pa_core *core; + + uint32_t index; + char *name; + char *description; + + pa_node_type_t type; + pa_direction_t direction; + + pa_node_state_t state; + + void *owner; +}; + +pa_node_new_data *pa_node_new_data_init(pa_node_new_data *data); +void pa_node_new_data_set_fallback_name_prefix(pa_node_new_data *data, const char *prefix); +void pa_node_new_data_set_description(pa_node_new_data *data, const char *description); +void pa_node_new_data_set_type(pa_node_new_data *data, pa_node_type_t type); +void pa_node_new_data_set_direction(pa_node_new_data *data, pa_direction_t direction); +void pa_node_new_data_done(pa_node_new_data *data); + +pa_node *pa_node_new(pa_core *core, pa_node_new_data *data); +void pa_node_free(pa_node *node); + +void pa_node_put(pa_node *node); +void pa_node_unlink(pa_node *node); + +#endif