Add virtual_voice_stream

Adding option to create voice virtual stream when voicecall is active
This commit is contained in:
Ratchanan Srirattanamet 2019-10-17 02:49:41 +07:00 committed by NeKit
parent 0730b77e39
commit 81504b9ec4
3 changed files with 87 additions and 0 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (C) 2013-2018 Jolla Ltd.
* Copyright (C) 2010 Nokia Corporation.
*
* Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
@ -92,8 +93,10 @@ struct userdata {
bool use_hw_volume;
bool use_voice_volume;
bool voice_virtual_stream;
char *voice_property_key;
char *voice_property_value;
pa_sink_input *voice_virtual_sink_input;
pa_sink_input *voice_control_sink_input;
pa_hook_slot *sink_input_volume_changed_hook_slot;
@ -707,6 +710,74 @@ static pa_hook_result_t sink_input_volume_changed_hook_cb(pa_core *c, pa_sink_in
return PA_HOOK_OK;
}
/* For voice virtual stream, based on meego-mainvolume */
static void sink_input_kill_cb(pa_sink_input *i) {
struct userdata *u;
pa_sink_input_assert_ref(i);
pa_assert_se(u = i->userdata);
pa_sink_input_unlink(u->voice_virtual_sink_input);
pa_sink_input_unref(u->voice_virtual_sink_input);
u->voice_virtual_sink_input = NULL;
}
/* no-op */
static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
return 0;
}
/* no-op */
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
}
static void create_voice_virtual_stream(struct userdata *u) {
pa_sink_input_new_data data;
pa_assert(u);
if (!u->voice_virtual_stream || u->voice_virtual_sink_input)
return;
pa_sink_input_new_data_init(&data);
data.driver = __FILE__;
data.module = u->module;
pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, "Virtual Stream for Voice Volume Control (Droid)");
pa_proplist_sets(data.proplist, PA_PROP_MEDIA_ROLE, "phone");
pa_sink_input_new_data_set_sample_spec(&data, &u->core->default_sample_spec);
pa_sink_input_new_data_set_channel_map(&data, &u->core->default_channel_map);
data.flags = PA_SINK_INPUT_START_CORKED | PA_SINK_INPUT_NO_REMAP | PA_SINK_INPUT_NO_REMIX;
pa_sink_input_new(&u->voice_virtual_sink_input, u->module->core, &data);
pa_sink_input_new_data_done(&data);
if (!u->voice_virtual_sink_input) {
pa_log_warn("Failed to create virtual sink input.");
return;
}
u->voice_virtual_sink_input->userdata = u;
u->voice_virtual_sink_input->kill = sink_input_kill_cb;
u->voice_virtual_sink_input->pop = sink_input_pop_cb;
u->voice_virtual_sink_input->process_rewind = sink_input_process_rewind_cb;
pa_sink_input_put(u->voice_virtual_sink_input);
pa_log_debug("Created virtual sink input for voice call volume control.");
}
static void destroy_voice_virtual_stream(struct userdata *u) {
pa_assert(u);
if (!u->voice_virtual_sink_input)
return;
sink_input_kill_cb(u->voice_virtual_sink_input);
pa_log_debug("Removed virtual stream.");
}
/* Called from main thread */
void pa_droid_sink_set_voice_control(pa_sink* sink, bool enable) {
pa_sink_input *i;
@ -734,6 +805,9 @@ void pa_droid_sink_set_voice_control(pa_sink* sink, bool enable) {
pa_assert(!u->sink_input_volume_changed_hook_slot);
if (u->voice_virtual_stream)
create_voice_virtual_stream(u);
if (u->use_hw_volume)
pa_sink_set_set_volume_callback(u->sink, NULL);
@ -748,6 +822,9 @@ void pa_droid_sink_set_voice_control(pa_sink* sink, bool enable) {
} else {
pa_assert(u->sink_input_volume_changed_hook_slot);
if (u->voice_virtual_stream)
destroy_voice_virtual_stream(u);
u->voice_control_sink_input = NULL;
pa_hook_slot_free(u->sink_input_volume_changed_hook_slot);
u->sink_input_volume_changed_hook_slot = NULL;
@ -1048,6 +1125,7 @@ pa_sink *pa_droid_sink_new(pa_module *m,
struct userdata *u = NULL;
const pa_droid_config_device *output = NULL;
bool deferred_volume = false;
bool voice_virtual_stream = false;
char *thread_name = NULL;
pa_sink_new_data data;
const char *module_id = NULL;
@ -1135,6 +1213,11 @@ pa_sink *pa_droid_sink_new(pa_module *m,
goto fail;
}
if (pa_modargs_get_value_boolean(ma, "voice_virtual_stream", &voice_virtual_stream) < 0) {
pa_log("Failed to parse voice_virtual_stream. Needs to be a boolean argument.");
goto fail;
}
u = pa_xnew0(struct userdata, 1);
u->core = m->core;
u->module = m;
@ -1144,6 +1227,7 @@ pa_sink *pa_droid_sink_new(pa_module *m,
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
u->parameters = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
NULL, (pa_free_cb_t) parameter_free);
u->voice_virtual_stream = voice_virtual_stream;
u->voice_property_key = pa_xstrdup(pa_modargs_get_value(ma, "voice_property_key", DEFAULT_VOICE_CONTROL_PROPERTY_KEY));
u->voice_property_value = pa_xstrdup(pa_modargs_get_value(ma, "voice_property_value", DEFAULT_VOICE_CONTROL_PROPERTY_VALUE));
u->extra_devices_map = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);

View file

@ -83,6 +83,7 @@ PA_MODULE_USAGE(
"config=<location for droid audio configuration> "
"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_virtual_stream=<true/false> create virtual stream for voice call volume control (default false)"
"default_profile=<boolean. create default profile for primary module or not. defaults to true> "
"merge_inputs=<unused, always true> "
"quirks=<comma separated list of quirks to enable/disable>"
@ -116,6 +117,7 @@ static const char* const valid_modargs[] = {
"config",
"voice_property_key",
"voice_property_value",
"voice_virtual_stream",
"default_profile",
"combine",
"merge_inputs",

View file

@ -71,6 +71,7 @@ static const char* const valid_modargs[] = {
"deferred_volume",
"voice_property_key",
"voice_property_value",
"voice_virtual_stream",
NULL,
};