card: Update card with new common.

This commit is contained in:
Juho Hämäläinen 2022-02-23 11:41:13 +02:00
parent 2d1a50d450
commit e0d66cf4ad

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013-2018 Jolla Ltd. * Copyright (C) 2013-2022 Jolla Ltd.
* *
* Contact: Juho Hämäläinen <juho.hamalainen@jolla.com> * Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
* *
@ -61,6 +61,7 @@
#include <droid/droid-util.h> #include <droid/droid-util.h>
#include <droid/sllist.h> #include <droid/sllist.h>
#include <droid/utils.h>
#include "droid-sink.h" #include "droid-sink.h"
#include "droid-source.h" #include "droid-source.h"
@ -73,16 +74,13 @@ PA_MODULE_USAGE(
"source_name=<name for the source> " "source_name=<name for the source> "
"namereg_fail=<when false attempt to synthesise new names if they are already taken> " "namereg_fail=<when false attempt to synthesise new names if they are already taken> "
"rate=<sample rate> " "rate=<sample rate> "
"output_flags=<flags for sink> "
"module_id=<which droid hw module to load, default primary> " "module_id=<which droid hw module to load, default primary> "
"voice_source_routing=<always true, parameter left for compatibility> " "voice_source_routing=<always true, parameter left for compatibility> "
"deferred_volume=<synchronize software and hardware volume changes to avoid momentary jumps?> " "deferred_volume=<synchronize software and hardware volume changes to avoid momentary jumps?> "
"config=<location for droid audio configuration> " "config=<location for droid audio configuration> "
"voice_property_key=<proplist key searched for sink-input that should control voice call volume> " "voice_property_key=<proplist key searched for sink-input that should control voice call volume> "
"voice_property_value=<proplist value for the key for voice control sink-input> " "voice_property_value=<proplist value for the key for voice control sink-input> "
"default_profile=<boolean. create default profile for primary module or not. defaults to true> " "options=<comma separated list of options to enable/disable>"
"merge_inputs=<unused, always true> "
"quirks=<comma separated list of quirks to enable/disable>"
); );
static const char* const valid_modargs[] = { static const char* const valid_modargs[] = {
@ -97,26 +95,18 @@ static const char* const valid_modargs[] = {
"sink_rate", "sink_rate",
"sink_format", "sink_format",
"sink_channel_map", "sink_channel_map",
"sink_mix_route",
"source_rate", "source_rate",
"source_format", "source_format",
"source_channel_map", "source_channel_map",
"output_flags",
"module_id", "module_id",
"voice_source_routing", "voice_source_routing",
"sink_buffer", "sink_buffer",
"source_buffer", "source_buffer",
"deferred_volume", "deferred_volume",
"mute_routing_before",
"mute_routing_after",
"prewrite_on_resume",
"config", "config",
"voice_property_key", "voice_property_key",
"voice_property_value", "voice_property_value",
"default_profile", /* DM_OPTIONS */
"combine",
"merge_inputs",
"quirks",
NULL, NULL,
}; };
@ -289,16 +279,57 @@ static void set_card_name(pa_modargs *ma, pa_card_new_data *data, const char *mo
} }
static bool output_enabled(struct userdata *u, pa_droid_mapping *am) { static bool output_enabled(struct userdata *u, pa_droid_mapping *am) {
bool enabled = false;
pa_assert(u); pa_assert(u);
pa_assert(am); pa_assert(am);
if (!pa_droid_quirk(u->hw_module, QUIRK_OUTPUT_FAST) && am->output->flags & AUDIO_OUTPUT_FLAG_FAST)
return false;
if (!pa_droid_quirk(u->hw_module, QUIRK_OUTPUT_DEEP_BUFFER) && am->output->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) if (am->mix_port->flags & AUDIO_OUTPUT_FLAG_PRIMARY)
return false; enabled = true;
return true; else if (am->mix_port->flags & AUDIO_OUTPUT_FLAG_RAW)
enabled = false;
else if (pa_droid_option(u->hw_module, DM_OPTION_OUTPUT_FAST) && am->mix_port->flags & AUDIO_OUTPUT_FLAG_FAST)
enabled = true;
else if (pa_droid_option(u->hw_module, DM_OPTION_OUTPUT_DEEP_BUFFER) && am->mix_port->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER)
enabled = true;
pa_log_debug("Output mix port \"%s\" %s", am->name, enabled ? "enabled" : "disabled");
return enabled;
}
static bool input_enabled(struct userdata *u, pa_droid_mapping *am) {
bool enabled = false;
pa_assert(u);
pa_assert(am);
/* Look for primary mix port as the one used for creating droid-source. */
if (dm_strcasestr(am->name, "primary"))
enabled = true;
pa_log_debug("Input mix port \"%s\" %s", am->name, enabled ? "enabled" : "disabled");
return enabled;
}
static uint32_t max_channels_for_mix_port(dm_config_port *mix_port, uint32_t previous_max_channels) {
uint32_t max_channels = 0;
dm_config_profile *profile;
void *state;
DM_LIST_FOREACH_DATA(profile, mix_port->profiles, state) {
for (int i = 0; profile->channel_masks[i]; i++) {
max_channels = audio_channel_count_from_out_mask(profile->channel_masks[i]) > max_channels
? audio_channel_count_from_out_mask(profile->channel_masks[i]) : max_channels;
}
}
return max_channels > previous_max_channels ? max_channels : previous_max_channels;
} }
static void add_profile(struct userdata *u, pa_hashmap *h, pa_hashmap *ports, pa_droid_profile *ap) { static void add_profile(struct userdata *u, pa_hashmap *h, pa_hashmap *ports, pa_droid_profile *ap) {
@ -319,26 +350,23 @@ static void add_profile(struct userdata *u, pa_hashmap *h, pa_hashmap *ports, pa
cp->available = PA_AVAILABLE_YES; cp->available = PA_AVAILABLE_YES;
cp->priority = ap->priority; cp->priority = ap->priority;
/* Output mappings */
max_channels = 0; max_channels = 0;
PA_IDXSET_FOREACH(am, ap->output_mappings, idx) { PA_IDXSET_FOREACH(am, ap->output_mappings, idx) {
if (!output_enabled(u, am))
continue;
cp->n_sinks++; cp->n_sinks++;
pa_droid_add_card_ports(cp, ports, am, u->core); pa_droid_add_card_ports(cp, ports, am, u->core);
max_channels = popcount(am->output->channel_masks) > max_channels max_channels = max_channels_for_mix_port(am->mix_port, max_channels);
? popcount(am->output->channel_masks) : max_channels;
} }
cp->max_sink_channels = max_channels; cp->max_sink_channels = max_channels;
/* Input mappings */
max_channels = 0; max_channels = 0;
if ((am = ap->input_mapping)) { PA_IDXSET_FOREACH(am, ap->input_mappings, idx) {
const pa_droid_config_device *input;
cp->n_sources++; cp->n_sources++;
pa_droid_add_card_ports(cp, ports, am, u->core); pa_droid_add_card_ports(cp, ports, am, u->core);
SLLIST_FOREACH(input, am->inputs) max_channels = max_channels_for_mix_port(am->mix_port, max_channels);
max_channels = popcount(input->channel_masks) > max_channels
? popcount(input->channel_masks) : max_channels;
} }
cp->max_source_channels = max_channels; cp->max_source_channels = max_channels;
@ -384,8 +412,13 @@ static void init_profile(struct userdata *u) {
} }
} }
if (d->droid_profile && (am = d->droid_profile->input_mapping)) { if (d->droid_profile && pa_idxset_size(d->droid_profile->input_mappings) > 0) {
am->source = pa_droid_source_new(u->module, u->modargs, __FILE__, (audio_devices_t) 0, &u->card_data, am, u->card); PA_IDXSET_FOREACH(am, d->droid_profile->input_mappings, idx) {
if (!input_enabled(u, am))
continue;
am->source = pa_droid_source_new(u->module, u->modargs, __FILE__, &u->card_data, am, u->card);
}
} }
} }
@ -437,12 +470,12 @@ static bool voicecall_profile_event_cb(struct userdata *u, pa_droid_profile *p,
if (enabling) { if (enabling) {
pa_droid_sink_set_voice_control(am_output->sink, true); pa_droid_sink_set_voice_control(am_output->sink, true);
if (pa_droid_quirk(u->hw_module, QUIRK_REALCALL)) if (pa_droid_option(u->hw_module, DM_OPTION_REALCALL))
pa_droid_set_parameters(u->hw_module, VENDOR_EXT_REALCALL_ON); pa_droid_set_parameters(u->hw_module, VENDOR_EXT_REALCALL_ON);
} else { } else {
pa_droid_sink_set_voice_control(am_output->sink, false); pa_droid_sink_set_voice_control(am_output->sink, false);
if (pa_droid_quirk(u->hw_module, QUIRK_REALCALL)) if (pa_droid_option(u->hw_module, DM_OPTION_REALCALL))
pa_droid_set_parameters(u->hw_module, VENDOR_EXT_REALCALL_OFF); pa_droid_set_parameters(u->hw_module, VENDOR_EXT_REALCALL_OFF);
} }
@ -681,15 +714,20 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
} }
} }
if (next->droid_profile && (am = next->droid_profile->input_mapping)) { if (next->droid_profile && pa_idxset_size(next->droid_profile->input_mappings) > 0) {
PA_IDXSET_FOREACH(am, next->droid_profile->input_mappings, idx) {
if (!input_enabled(u, am))
continue;
if (!am->source) if (!am->source)
am->source = pa_droid_source_new(u->module, u->modargs, __FILE__, (audio_devices_t) 0, &u->card_data, am, u->card); am->source = pa_droid_source_new(u->module, u->modargs, __FILE__, &u->card_data, am, u->card);
if (source_outputs && am->source) { if (source_outputs && am->source) {
pa_source_move_all_finish(am->source, source_outputs, false); pa_source_move_all_finish(am->source, source_outputs, false);
source_outputs = NULL; source_outputs = NULL;
} }
} }
}
/* if only primary sink is left after profile change and we have detached sink-inputs attach /* if only primary sink is left after profile change and we have detached sink-inputs attach
* them to primary sink. */ * them to primary sink. */
@ -714,23 +752,17 @@ int pa__init(pa_module *m) {
pa_card_new_data data; pa_card_new_data data;
const char *module_id; const char *module_id;
bool namereg_fail = false; bool namereg_fail = false;
bool default_profile = true;
pa_card_profile *voicecall = NULL; pa_card_profile *voicecall = NULL;
pa_assert(m); pa_assert(m);
pa_log_info("Create new droid-card"); pa_log_info("Create new droid-card");
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { if (!(ma = pa_droid_modargs_new(m->argument, valid_modargs))) {
pa_log("Failed to parse module arguments."); pa_log("Failed to parse module arguments.");
goto fail; goto fail;
} }
if (pa_modargs_get_value_boolean(ma, "default_profile", &default_profile) < 0) {
pa_log("Failed to parse default_profile argument. Expects boolean value");
goto fail;
}
u = pa_xnew0(struct userdata, 1); u = pa_xnew0(struct userdata, 1);
u->core = m->core; u->core = m->core;
m->userdata = u; m->userdata = u;
@ -740,15 +772,12 @@ int pa__init(pa_module *m) {
if (!(u->hw_module = pa_droid_hw_module_get2(u->core, ma, module_id))) if (!(u->hw_module = pa_droid_hw_module_get2(u->core, ma, module_id)))
goto fail; goto fail;
pa_droid_quirk_log(u->hw_module); pa_droid_options_log(u->hw_module);
u->card_data.module_id = pa_xstrdup(module_id); u->card_data.module_id = pa_xstrdup(module_id);
u->card_data.userdata = u; u->card_data.userdata = u;
if (default_profile)
u->profile_set = pa_droid_profile_set_default_new(u->hw_module->enabled_module); u->profile_set = pa_droid_profile_set_default_new(u->hw_module->enabled_module);
else
u->profile_set = pa_droid_profile_set_new(u->hw_module->enabled_module);
pa_card_new_data_init(&data); pa_card_new_data_init(&data);
data.driver = __FILE__; data.driver = __FILE__;
@ -859,7 +888,6 @@ void pa__done(pa_module *m) {
if (u->card && u->card->sources) if (u->card && u->card->sources)
pa_idxset_remove_all(u->card->sources, (pa_free_cb_t) pa_droid_source_free); pa_idxset_remove_all(u->card->sources, (pa_free_cb_t) pa_droid_source_free);
if (u->card) if (u->card)
pa_card_free(u->card); pa_card_free(u->card);