@@ -82,6 +82,9 @@
/* Section defining custom global configuration variables. */
#define GLOBAL_CONFIG_EXT_TAG "custom_properties"
+static const char * const droid_combined_auto_outputs[3] = { "primary", "low_latency", NULL };
+static const char * const droid_combined_auto_inputs[2] = { "primary", NULL };
+
static void droid_port_free(pa_droid_port *p);
static bool string_convert_num_to_str(const struct string_conversion *list, const uint32_t value, const char **to_str) {
@@ -829,12 +832,15 @@
return false;
}
-/* outputs or inputs string lists can be NULL, which means include all outputs and inputs
- * from module. */
+/* If outputs or inputs string list contain string *all* it means all
+ * outputs or inputs are added to the combined profile.
+ * If outputs or inputs string list contain string *auto* it means
+ * all devices that are in module and listed in droid_combined_auto_*
+ * are added to the combined profile. */
static pa_droid_profile *add_combined_profile(pa_droid_profile_set *ps,
const pa_droid_config_hw_module *module,
- pa_strlist *outputs,
- pa_strlist *inputs) {
+ const pa_strlist *outputs,
+ const pa_strlist *inputs) {
pa_droid_profile *p;
char *description;
char *o_str;
@@ -846,27 +852,65 @@
pa_assert(ps);
pa_assert(module);
- for (unsigned i = 0; i < module->outputs_size; i++) {
- if (outputs && !str_in_strlist(module->outputs[i].name, outputs))
- continue;
+ if (outputs) {
+ if (str_in_strlist(PA_DROID_COMBINED_AUTO, outputs)) {
+ for (unsigned i = 0; droid_combined_auto_outputs[i]; i++) {
+ for (unsigned j = 0; j < module->outputs_size; j++) {
+ if (pa_streq(droid_combined_auto_outputs[i], module->outputs[j].name)) {
+ pa_log_debug("Auto add to combined profile output %s", module->outputs[j].name);
+ to_outputs = pa_strlist_prepend(to_outputs, module->outputs[j].name);
+ }
+ }
+ }
+ } else {
+ for (unsigned i = 0; i < module->outputs_size; i++) {
+ if (!str_in_strlist(PA_DROID_COMBINED_ALL, outputs) &&
+ !str_in_strlist(module->outputs[i].name, outputs))
+ continue;
- to_outputs = pa_strlist_prepend(to_outputs, module->outputs[i].name);
+ to_outputs = pa_strlist_prepend(to_outputs, module->outputs[i].name);
+ }
+ }
+
+ to_outputs = pa_strlist_reverse(to_outputs);
}
- to_outputs = pa_strlist_reverse(to_outputs);
- for (unsigned i = 0; i < module->inputs_size; i++) {
- if (inputs && !str_in_strlist(module->inputs[i].name, inputs))
- continue;
+ if (inputs) {
+ if (str_in_strlist(PA_DROID_COMBINED_AUTO, inputs)) {
+ for (unsigned i = 0; droid_combined_auto_inputs[i]; i++) {
+ for (unsigned j = 0; j < module->inputs_size; j++) {
+ if (pa_streq(droid_combined_auto_inputs[i], module->inputs[j].name)) {
+ pa_log_debug("Auto add to combined profile input %s", module->inputs[j].name);
+ to_inputs = pa_strlist_prepend(to_inputs, module->inputs[j].name);
+ }
+ }
+ }
+ } else {
+ for (unsigned i = 0; i < module->inputs_size; i++) {
+ if (!str_in_strlist(PA_DROID_COMBINED_ALL, inputs) &&
+ !str_in_strlist(module->inputs[i].name, inputs))
+ continue;
+
+ to_inputs = pa_strlist_prepend(to_inputs, module->inputs[i].name);
+ }
+ }
- to_inputs = pa_strlist_prepend(to_inputs, module->inputs[i].name);
+ to_inputs = pa_strlist_reverse(to_inputs);
}
- to_inputs = pa_strlist_reverse(to_inputs);
+#if (PULSEAUDIO_VERSION >= 8)
+ o_str = pa_strlist_to_string(to_outputs);
+ i_str = pa_strlist_to_string(to_inputs);
+#else
o_str = pa_strlist_tostring(to_outputs);
i_str = pa_strlist_tostring(to_inputs);
+#endif
pa_log_debug("New combined profile: %s (outputs: %s, inputs: %s)", module->name, o_str, i_str);
+ if (!to_outputs && !to_inputs)
+ pa_log("Combined profile doesn't have any outputs or inputs!");
+
description = pa_sprintf_malloc("Combined outputs (%s) and inputs (%s) of %s.", o_str,
i_str,
module->name);
@@ -875,26 +919,30 @@
pa_xfree(o_str);
pa_xfree(i_str);
- for (unsigned i = 0; i < module->outputs_size; i++) {
- if (!str_in_strlist(module->outputs[i].name, to_outputs))
- continue;
+ if (to_outputs) {
+ for (unsigned i = 0; i < module->outputs_size; i++) {
+ if (!str_in_strlist(module->outputs[i].name, to_outputs))
+ continue;
- am = pa_droid_mapping_get(ps, PA_DIRECTION_OUTPUT, &module->outputs[i]);
- pa_droid_profile_add_mapping(p, am);
+ am = pa_droid_mapping_get(ps, PA_DIRECTION_OUTPUT, &module->outputs[i]);
+ pa_droid_profile_add_mapping(p, am);
- if (pa_streq(module->outputs[i].name, "primary"))
- p->priority += DEFAULT_PRIORITY;
+ if (pa_streq(module->outputs[i].name, "primary"))
+ p->priority += DEFAULT_PRIORITY;
+ }
}
- for (unsigned i = 0; i < module->inputs_size; i++) {
- if (!str_in_strlist(module->inputs[i].name, to_inputs))
- continue;
+ if (to_inputs) {
+ for (unsigned i = 0; i < module->inputs_size; i++) {
+ if (!str_in_strlist(module->inputs[i].name, to_inputs))
+ continue;
- am = pa_droid_mapping_get(ps, PA_DIRECTION_INPUT, &module->inputs[i]);
- pa_droid_profile_add_mapping(p, am);
+ am = pa_droid_mapping_get(ps, PA_DIRECTION_INPUT, &module->inputs[i]);
+ pa_droid_profile_add_mapping(p, am);
- if (pa_streq(module->inputs[i].name, "primary"))
- p->priority += DEFAULT_PRIORITY;
+ if (pa_streq(module->inputs[i].name, "primary"))
+ p->priority += DEFAULT_PRIORITY;
+ }
}
pa_strlist_free(to_outputs);
@@ -922,10 +970,9 @@
return ps;
}
-pa_droid_profile_set *pa_droid_profile_set_new(const pa_droid_config_hw_module *module) {
- pa_droid_profile_set *ps;
-
- ps = profile_set_new(module);
+static void add_all_profiles(pa_droid_profile_set *ps, const pa_droid_config_hw_module *module) {
+ pa_assert(ps);
+ pa_assert(module);
/* Each distinct hw module output matches one profile. If there are multiple inputs
* combinations are made so that all possible outputs and inputs can be selected.
@@ -941,15 +988,25 @@
} else
add_profile(ps, &module->outputs[o], NULL);
}
+}
+
+pa_droid_profile_set *pa_droid_profile_set_new(const pa_droid_config_hw_module *module) {
+ pa_droid_profile_set *ps;
+
+ ps = profile_set_new(module);
+ add_all_profiles(ps, module);
return ps;
}
-pa_droid_profile_set *pa_droid_profile_set_combined_new(const pa_droid_config_hw_module *module, pa_strlist *inputs, pa_strlist *outputs) {
+pa_droid_profile_set *pa_droid_profile_set_combined_new(const pa_droid_config_hw_module *module,
+ const pa_strlist *outputs,
+ const pa_strlist *inputs) {
pa_droid_profile_set *ps;
ps = profile_set_new(module);
- add_combined_profile(ps, module, inputs, outputs);
+ add_combined_profile(ps, module, outputs, inputs);
+ add_all_profiles(ps, module);
return ps;
}
@@ -1565,10 +1622,19 @@
hal_channel_mask |= c;
}
+ memset(&config_out, 0, sizeof(struct audio_config));
config_out.sample_rate = spec->rate;
config_out.channel_mask = hal_channel_mask;
config_out.format = hal_audio_format;
+ if (pa_idxset_size(module->outputs) == 0) {
+ pa_log_debug("Set initial output device to %#010x", devices);
+ module->output_device = devices;
+ } else {
+ pa_log_debug("Output with device %#010x already open, using as initial device.", module->output_device);
+ devices = module->output_device;
+ }
+
pa_droid_hw_module_lock(module);
ret = module->device->open_output_stream(module->device,
module->stream_out_id++,
@@ -1664,13 +1730,18 @@
pa_channel_map_init_mono(&channel_map);
sample_spec.channels = 1;
/* Only allow recording both downlink and uplink. */
-#ifdef QCOM_HARDWARE
+#if defined(QCOM_HARDWARE)
+ #if ANDROID_VERSION_MAJOR == 5 && ANDROID_VERSION_MINOR == 1
+ hal_channel_mask = AUDIO_CHANNEL_IN_MONO;
+ #else
hal_channel_mask = AUDIO_CHANNEL_IN_VOICE_CALL_MONO;
+ #endif
#else
hal_channel_mask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK;
#endif
}
+ memset(&config_in, 0, sizeof(struct audio_config));
config_in.sample_rate = sample_spec.rate;
config_in.channel_mask = hal_channel_mask;
config_in.format = hal_audio_format;
@@ -1690,7 +1761,15 @@
pa_droid_hw_module_unlock(module);
if (ret < 0 || !stream) {
- pa_log("Failed to open input stream: %d", ret);
+ pa_log("Failed to open input stream: %d with device: %u flags: %u sample rate: %u channels: %u (%u) format: %u (%u)",
+ ret,
+ devices,
+ 0, /* AUDIO_INPUT_FLAG_NONE on v3. v1 and v2 don't have input flags. */
+ config_in.sample_rate,
+ sample_spec.channels,
+ config_in.channel_mask,
+ sample_spec.format,
+ config_in.format);
goto fail;
}
@@ -1707,6 +1786,10 @@
buffer_size = s->in->common.get_buffer_size(&s->in->common);
+ /* As audio_source_t may not have any effect when opening the input stream
+ * set input parameters immediately after opening the stream. */
+ pa_droid_stream_set_input_route(s, devices, NULL);
+
pa_log_info("Opened droid input stream %p with device: %u flags: %u sample rate: %u channels: %u (%u) format: %u (%u) buffer size: %u (%llu usec)",
(void *) s,
devices,
@@ -1798,6 +1881,9 @@
pa_log_warn("output set_parameters(%s) not allowed while stream is active", parameters);
else
pa_log_warn("output set_parameters(%s) failed", parameters);
+ } else {
+ /* Store last set output device. */
+ s->module->output_device = device;
}
}
|
@@ -470,7 +470,8 @@
return true;
}
-#if DROID_HAL == 1
+#if (DROID_HAL == 1) || \
+ (defined(QCOM_HARDWARE) && ANDROID_VERSION_MAJOR == 5 && ANDROID_VERSION_MINOR == 1)
static bool voicecall_record_profile_event_cb(struct userdata *u, pa_droid_profile *p, bool enabling) {
pa_queue *source_outputs = NULL;
pa_droid_mapping *am;
@@ -505,15 +506,13 @@
}
} else {
- /* don't do anything if voicecall source has already been destroyed. */
- if (!u->voicecall_source)
- return true;
-
pa_log_info("Disabling voice call record.");
- source_outputs = pa_source_move_all_start(u->voicecall_source, source_outputs);
- pa_droid_source_free(u->voicecall_source);
- u->voicecall_source = NULL;
+ if (u->voicecall_source) {
+ source_outputs = pa_source_move_all_start(u->voicecall_source, source_outputs);
+ pa_droid_source_free(u->voicecall_source);
+ u->voicecall_source = NULL;
+ }
am = pa_droid_idxset_get_primary(u->old_profile->input_mappings);
@@ -818,16 +817,38 @@
u->card_data.userdata = u;
if (combine) {
- char *tmp;
pa_strlist *o = NULL;
+ pa_strlist *i = NULL;
+
+ if (pa_streq(combine, PA_DROID_COMBINED_AUTO)) {
+ o = pa_strlist_parse(PA_DROID_COMBINED_AUTO);
+ i = pa_strlist_parse(PA_DROID_COMBINED_AUTO);
+ } else {
+ char *tmp, *d;
+ const char *inputs = NULL;
+ const char *outputs = NULL;
+
+ tmp = pa_replace(combine, ",", " ");
+
+ outputs = tmp;
+ if ((d = strstr(tmp, ":"))) {
+ d[0] = '\0';
+ inputs = d + 1;
+ }
+
+ if (outputs)
+ o = pa_strlist_parse(outputs);
+
+ if (inputs)
+ i = pa_strlist_parse(inputs);
+
+ pa_xfree(tmp);
+ }
- tmp = pa_replace(combine, ",", " ");
- o = pa_strlist_parse(tmp);
+ u->profile_set = pa_droid_profile_set_combined_new(u->hw_module->enabled_module, o, i);
- u->profile_set = pa_droid_profile_set_combined_new(u->hw_module->enabled_module,
- o, NULL);
pa_strlist_free(o);
- pa_xfree(tmp);
+ pa_strlist_free(i);
} else
u->profile_set = pa_droid_profile_set_new(u->hw_module->enabled_module);
|