diff options
Diffstat (limited to 'src/modules/alsa/module-alsa-card.c')
| -rw-r--r-- | src/modules/alsa/module-alsa-card.c | 106 | 
1 files changed, 94 insertions, 12 deletions
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index 6c947c06..f2506024 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -28,6 +28,8 @@  #include <pulsecore/modargs.h>  #include "alsa-util.h" +#include "alsa-sink.h" +#include "alsa-source.h"  #include "module-alsa-card-symdef.h"  PA_MODULE_AUTHOR("Lennart Poettering"); @@ -48,19 +50,17 @@ PA_MODULE_USAGE(          "profile=<profile name>");  static const char* const valid_modargs[] = { -    "sink_name", -    "device", +    "name",      "device_id",      "format",      "rate", -    "channels", -    "channel_map",      "fragments",      "fragment_size",      "mmap",      "tsched",      "tsched_buffer_size",      "tsched_buffer_watermark", +    "profile",      NULL  }; @@ -73,10 +73,14 @@ struct userdata {      char *device_id;      pa_card *card; +    pa_sink *sink; +    pa_source *source; + +    pa_modargs *modargs;  };  struct profile_data { -    const pa_alsa_profile_info *sink, *source; +    const pa_alsa_profile_info *sink_profile, *source_profile;  };  static void enumerate_cb( @@ -119,8 +123,8 @@ static void enumerate_cb(      d = PA_CARD_PROFILE_DATA(p); -    d->sink = sink; -    d->source = source; +    d->sink_profile = sink; +    d->source_profile = source;      pa_hashmap_put(profiles, p->name, p);  } @@ -132,11 +136,59 @@ static void add_disabled_profile(pa_hashmap *profiles) {      p = pa_card_profile_new("off", "Off", sizeof(struct profile_data));      d = PA_CARD_PROFILE_DATA(p); -    d->sink = d->source = NULL; +    d->sink_profile = d->source_profile = NULL;      pa_hashmap_put(profiles, p->name, p);  } +static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { +    struct userdata *u; +    struct profile_data *nd, *od; + +    pa_assert(c); +    pa_assert(new_profile); +    pa_assert_se(u = c->userdata); + +    nd = PA_CARD_PROFILE_DATA(new_profile); +    od = PA_CARD_PROFILE_DATA(c->active_profile); + +    if (od->sink_profile != nd->sink_profile) { +        if (u->sink) { +            pa_alsa_sink_free(u->sink); +            u->sink = NULL; +        } + +        if (nd->sink_profile) +            u->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, nd->sink_profile); +    } + +    if (od->source_profile != nd->source_profile) { +        if (u->source) { +            pa_alsa_source_free(u->source); +            u->source = NULL; +        } + +        if (nd->source_profile) +            u->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, nd->source_profile); +    } + +    return 0; +} + +static void init_profile(struct userdata *u) { +    struct profile_data *d; + +    pa_assert(u); + +    d = PA_CARD_PROFILE_DATA(u->card->active_profile); + +    if (d->sink_profile) +        u->sink = pa_alsa_sink_new(u->module, u->modargs, __FILE__, u->card, d->sink_profile); + +    if (d->source_profile) +        u->source = pa_alsa_source_new(u->module, u->modargs, __FILE__, u->card, d->source_profile); +} +  int pa__init(pa_module*m) {      pa_card_new_data data;      pa_modargs *ma; @@ -144,6 +196,7 @@ int pa__init(pa_module*m) {      struct userdata *u;      pa_alsa_redirect_errors_inc(); +    snd_config_update_free_global();      pa_assert(m); @@ -152,10 +205,14 @@ int pa__init(pa_module*m) {          goto fail;      } -    m->userdata = u = pa_xnew0(struct userdata, 1); +    m->userdata = u = pa_xnew(struct userdata, 1);      u->core = m->core;      u->module = m;      u->device_id = pa_xstrdup(pa_modargs_get_value(ma, "device_id", DEFAULT_DEVICE_ID)); +    u->card = NULL; +    u->sink = NULL; +    u->source = NULL; +    u->modargs = ma;      if ((alsa_card_index = snd_card_get_index(u->device_id)) < 0) {          pa_log("Card '%s' doesn't exist: %s", u->device_id, snd_strerror(alsa_card_index)); @@ -186,17 +243,33 @@ int pa__init(pa_module*m) {      u->card = pa_card_new(m->core, &data);      pa_card_new_data_done(&data); +    if (!u->card) +        goto fail; + +    u->card->userdata = u; +    u->card->set_profile = card_set_profile; + +    init_profile(u); +      return 0;  fail: -    if (ma) -        pa_modargs_free(ma); -      pa__done(m);      return -1;  } +int pa__get_n_used(pa_module *m) { +    struct userdata *u; + +    pa_assert(m); +    pa_assert_se(u = m->userdata); + +    return +        (u->sink ? pa_sink_linked_by(u->sink) : 0) + +        (u->source ? pa_source_linked_by(u->source) : 0); +} +  void pa__done(pa_module*m) {      struct userdata *u; @@ -205,9 +278,18 @@ void pa__done(pa_module*m) {      if (!(u = m->userdata))          goto finish; +    if (u->sink) +        pa_alsa_sink_free(u->sink); + +    if (u->source) +        pa_alsa_source_free(u->source); +      if (u->card)          pa_card_free(u->card); +    if (u->modargs) +        pa_modargs_free(u->modargs); +      pa_xfree(u->device_id);      pa_xfree(u);  | 
