diff options
| author | Lennart Poettering <lennart@poettering.net> | 2009-01-15 18:29:16 +0100 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2009-01-15 18:29:16 +0100 | 
| commit | b6deb0cc4c169b5ef9450586fc66b0b823ef249c (patch) | |
| tree | aae25bfd17edabd2ded8bacfeb05034ad2602501 | |
| parent | aeb0707f1287c481d407d8e8f4a43f86661fdb23 (diff) | |
add new pa_card object as a way to logically combine multiple sinks and sources
| -rw-r--r-- | src/Makefile.am | 1 | ||||
| -rw-r--r-- | src/pulse/def.h | 8 | ||||
| -rw-r--r-- | src/pulsecore/card.c | 196 | ||||
| -rw-r--r-- | src/pulsecore/card.h | 91 | ||||
| -rw-r--r-- | src/pulsecore/core.c | 4 | ||||
| -rw-r--r-- | src/pulsecore/core.h | 5 | ||||
| -rw-r--r-- | src/pulsecore/namereg.c | 2 | ||||
| -rw-r--r-- | src/pulsecore/namereg.h | 3 | ||||
| -rw-r--r-- | src/pulsecore/sink.c | 8 | ||||
| -rw-r--r-- | src/pulsecore/sink.h | 3 | ||||
| -rw-r--r-- | src/pulsecore/source.c | 7 | ||||
| -rw-r--r-- | src/pulsecore/source.h | 3 | 
12 files changed, 327 insertions, 4 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index dd9035b5..e570a6d2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -716,6 +716,7 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES = \  		pulsecore/cli-command.c pulsecore/cli-command.h \  		pulsecore/cli-text.c pulsecore/cli-text.h \  		pulsecore/client.c pulsecore/client.h \ +		pulsecore/card.c pulsecore/card.h \  		pulsecore/core-scache.c pulsecore/core-scache.h \  		pulsecore/core-subscribe.c pulsecore/core-subscribe.h \  		pulsecore/core.c pulsecore/core.h \ diff --git a/src/pulse/def.h b/src/pulse/def.h index a2e29143..03e8416e 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -391,7 +391,10 @@ typedef enum pa_subscription_mask {      PA_SUBSCRIPTION_MASK_AUTOLOAD = 0x0100U,      /**< Autoload table events. */ -    PA_SUBSCRIPTION_MASK_ALL = 0x01ffU +    PA_SUBSCRIPTION_MASK_CARD = 0x0200U, +    /**< Card events. \since 0.9.15 */ + +    PA_SUBSCRIPTION_MASK_ALL = 0x03ffU      /**< Catch all events */  } pa_subscription_mask_t; @@ -424,6 +427,9 @@ typedef enum pa_subscription_event_type {      PA_SUBSCRIPTION_EVENT_AUTOLOAD = 0x0008U,      /**< Event type: Autoload table changes. */ +    PA_SUBSCRIPTION_EVENT_CARD = 0x0009U, +    /**< Event type: Card \since 0.9.15 */ +      PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 0x000FU,      /**< A mask to extract the event type from an event value */ diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c new file mode 100644 index 00000000..4f3548b4 --- /dev/null +++ b/src/pulsecore/card.c @@ -0,0 +1,196 @@ +/*** +  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(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); +    c->sources = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + +    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_idxset_free(c->sinks, NULL, NULL); +    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/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 f1f38ef1..87ea4ab6 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -79,6 +79,9 @@ typedef enum pa_core_hook {      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; @@ -96,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/sink.c b/src/pulsecore/sink.c index 3a662383..dbc72fb4 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; @@ -223,6 +224,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, @@ -235,6 +239,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); @@ -358,6 +363,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); diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 092e30f2..2bd83b63 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; @@ -186,6 +188,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/source.c b/src/pulsecore/source.c index dee6f3d5..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); 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;  | 
