From f6e1b0eae63dfd937213e0b0fdb01f106621421c Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 26 Oct 2012 15:47:01 +0200 Subject: Mixer: Avoid mode and use directions logic instead, introducing modem support Signed-off-by: Paul Kocialkowski --- audio_hw.c | 24 ++-- audio_in.c | 27 ++-- audio_out.c | 28 ++--- mixer.c | 410 +++++++++++++++++++++++++++++++++++++++++++----------------- mixer.h | 45 ++++--- 5 files changed, 361 insertions(+), 173 deletions(-) diff --git a/audio_hw.c b/audio_hw.c index 38acef4..7dee074 100644 --- a/audio_hw.c +++ b/audio_hw.c @@ -89,7 +89,7 @@ static int audio_hw_set_voice_volume(struct audio_hw_device *dev, float volume) if(device->mode == AUDIO_MODE_IN_CALL) { // FIXME: Select the device from ril interface tinyalsa_mixer_set_voice_volume(device->mixer, - AUDIO_DEVICE_IN_DEFAULT, device->mode, volume); + AUDIO_DEVICE_OUT_DEFAULT, volume); } return 0; @@ -126,16 +126,17 @@ static int audio_hw_set_mode(struct audio_hw_device *dev, int mode) device = (struct tinyalsa_audio_device *) dev; if(mode != device->mode) { - device->mode = mode; + if(mode == AUDIO_MODE_IN_CALL) { + tinyalsa_mixer_set_modem_state(device->mixer, 1); - if(device->stream_out != NULL) { - audio_out_set_route(device->stream_out, - device->stream_out->device_current); - // TODO: audio_input_set_route + if(device->stream_out != NULL) + tinyalsa_mixer_set_device(device->mixer, device->stream_out->device_current); + } else if(device->mode == AUDIO_MODE_IN_CALL) { + tinyalsa_mixer_set_modem_state(device->mixer, 0); } - } - device->mode = mode; + device->mode = mode; + } return 0; } @@ -160,7 +161,7 @@ static int audio_hw_set_mic_mute(struct audio_hw_device *dev, bool state) // FIXME: Select the device from input if mode isn't in-call, // select it from ril interface if mode is in-call tinyalsa_mixer_set_mic_mute(device->mixer, - AUDIO_DEVICE_IN_DEFAULT, device->mode, state); + AUDIO_DEVICE_IN_DEFAULT, state); } return 0; @@ -307,11 +308,6 @@ int audio_hw_open(const hw_module_t *module, const char *name, goto error_device; } - rc = tinyalsa_mixer_set_route(tinyalsa_mixer, AUDIO_DEVICE_OUT_DEFAULT, AUDIO_MODE_NORMAL); - if(rc < 0) { - LOGE("Failed to set default mixer route"); - } - tinyalsa_audio_device->mixer = tinyalsa_mixer; *device = &(dev->common); diff --git a/audio_in.c b/audio_in.c index 8e83478..29cda6e 100644 --- a/audio_in.c +++ b/audio_in.c @@ -95,22 +95,11 @@ int audio_in_set_route(struct tinyalsa_audio_stream_in *stream_in, stream_in->device_current = device; - if(device == 0) { - tinyalsa_mixer_set_route(stream_in->device->mixer, - AUDIO_DEVICE_IN_DEFAULT, stream_in->device->mode); + if(device == 0) + return stream_in->stream.common.standby((struct audio_stream *) stream_in); - rc = yamaha_mc1n2_audio_input_stop(stream_in->device->mc1n2_pdata); - if(rc < 0) { - LOGE("Failed to set Yamaha-MC1N2-Audio route"); - } - - stream_in->standby = 1; - - return 0; - } - tinyalsa_mixer_set_route(stream_in->device->mixer, - stream_in->device_current, stream_in->device->mode); + tinyalsa_mixer_set_device(stream_in->device->mixer, stream_in->device_current); #ifdef YAMAHA_MC1N2_AUDIO yamaha_mc1n2_audio_set_route(stream_in->device->mc1n2_pdata, device, @@ -308,7 +297,7 @@ static int audio_in_set_gain(struct audio_stream_in *stream, float gain) return -1; tinyalsa_mixer_set_input_gain(stream_in->device->mixer, - stream_in->device_current, stream_in->device->mode, gain); + stream_in->device_current, gain); return 0; } @@ -396,6 +385,8 @@ void audio_hw_close_input_stream(struct audio_hw_device *dev, tinyalsa_audio_device = (struct tinyalsa_audio_device *) dev; + tinyalsa_mixer_set_input_state(tinyalsa_audio_device->mixer, 0); + tinyalsa_audio_device->stream_in = NULL; } @@ -459,6 +450,12 @@ int audio_hw_open_input_stream(struct audio_hw_device *dev, *channels = (uint32_t) tinyalsa_audio_stream_in->channels; *format = (uint32_t) tinyalsa_audio_stream_in->format; + rc = tinyalsa_mixer_set_input_state(tinyalsa_audio_device->mixer, 1); + if(rc < 0) { + LOGE("Unable to set input state"); + goto error_stream; + } + audio_in_set_route(tinyalsa_audio_stream_in, devices); rc = audio_in_pcm_open(tinyalsa_audio_stream_in); diff --git a/audio_out.c b/audio_out.c index 4bfd9b3..a347eaa 100644 --- a/audio_out.c +++ b/audio_out.c @@ -99,22 +99,10 @@ int audio_out_set_route(struct tinyalsa_audio_stream_out *stream_out, stream_out->device_current = device; - if(device == 0) { - tinyalsa_mixer_set_route(stream_out->device->mixer, - AUDIO_DEVICE_OUT_DEFAULT, stream_out->device->mode); + if(device == 0) + return stream_out->stream.common.standby((struct audio_stream *) stream_out); - rc = yamaha_mc1n2_audio_output_stop(stream_out->device->mc1n2_pdata); - if(rc < 0) { - LOGE("Failed to set Yamaha-MC1N2-Audio route"); - } - - stream_out->standby = 1; - - return 0; - } - - tinyalsa_mixer_set_route(stream_out->device->mixer, - stream_out->device_current, stream_out->device->mode); + tinyalsa_mixer_set_device(stream_out->device->mixer, stream_out->device_current); #ifdef YAMAHA_MC1N2_AUDIO yamaha_mc1n2_audio_set_route(stream_out->device->mc1n2_pdata, device, @@ -322,7 +310,7 @@ static int audio_out_set_volume(struct audio_stream_out *stream, float left, volume = (left + right) / 2; tinyalsa_mixer_set_output_volume(stream_out->device->mixer, - stream_out->device_current, stream_out->device->mode, volume); + stream_out->device_current, volume); return 0; } @@ -418,6 +406,8 @@ void audio_hw_close_output_stream(struct audio_hw_device *dev, tinyalsa_audio_device = (struct tinyalsa_audio_device *) dev; + tinyalsa_mixer_set_output_state(tinyalsa_audio_device->mixer, 0); + tinyalsa_audio_device->stream_out = NULL; } @@ -482,6 +472,12 @@ int audio_hw_open_output_stream(struct audio_hw_device *dev, *channels = (uint32_t) tinyalsa_audio_stream_out->channels; *format = (uint32_t) tinyalsa_audio_stream_out->format; + rc = tinyalsa_mixer_set_output_state(tinyalsa_audio_device->mixer, 1); + if(rc < 0) { + LOGE("Unable to set output state"); + goto error_stream; + } + audio_out_set_route(tinyalsa_audio_stream_out, devices); rc = audio_out_pcm_open(tinyalsa_audio_stream_out); diff --git a/mixer.c b/mixer.c index 6848dc8..e18d1da 100644 --- a/mixer.c +++ b/mixer.c @@ -176,7 +176,7 @@ void tinyalsa_mixer_device_free(struct tinyalsa_mixer_device *mixer_device) } struct tinyalsa_mixer_device *tinyalsa_mixer_get_device(struct tinyalsa_mixer_io *mixer_io, - audio_devices_t device, audio_mode_t mode) + audio_devices_t device) { struct tinyalsa_mixer_device *mixer_device = NULL; struct list_head *list = NULL; @@ -188,8 +188,7 @@ struct tinyalsa_mixer_device *tinyalsa_mixer_get_device(struct tinyalsa_mixer_io while(list != NULL) { mixer_device = (struct tinyalsa_mixer_device *) list->data; - if(mixer_device != NULL && mixer_device->props.type == device && - mixer_device->props.mode == mode) { + if(mixer_device != NULL && mixer_device->props.type == device) { break; } else { mixer_device = NULL; @@ -254,7 +253,7 @@ void tinyalsa_mixer_config_start(void *data, const XML_Char *elem, } } } else if(strcmp(elem, "output") == 0) { - config_data->direction = AUDIO_DEVICE_OUT_ALL; + config_data->direction = TINYALSA_MIXER_DIRECTION_OUTPUT; for(i=0 ; attr[i] != NULL && attr[i+1] ; i++) { if(strcmp(attr[i], "card") == 0) { @@ -312,7 +311,7 @@ void tinyalsa_mixer_config_start(void *data, const XML_Char *elem, } } } else if(strcmp(elem, "input") == 0) { - config_data->direction = AUDIO_DEVICE_IN_ALL; + config_data->direction = TINYALSA_MIXER_DIRECTION_INPUT; for(i=0 ; attr[i] != NULL && attr[i+1] ; i++) { if(strcmp(attr[i], "card") == 0) { @@ -360,28 +359,26 @@ void tinyalsa_mixer_config_start(void *data, const XML_Char *elem, LOGE("Unknown input attr: %s", attr[i]); } } - } else if(strcmp(elem, "mode") == 0) { - for(i=0 ; attr[i] != NULL && attr[i+1] != NULL ; i++) { - if(strcmp(attr[i], "type") == 0) { + } else if(strcmp(elem, "modem") == 0) { + config_data->direction = TINYALSA_MIXER_DIRECTION_MODEM; + + for(i=0 ; attr[i] != NULL && attr[i+1] ; i++) { + if(strcmp(attr[i], "card") == 0) { i++; - if(strcmp(attr[i], "normal") == 0) { - config_data->device_props.mode = AUDIO_MODE_NORMAL; - } else if(strcmp(attr[i], "ringtone") == 0) { - config_data->device_props.mode = AUDIO_MODE_RINGTONE; - } else if(strcmp(attr[i], "in-call") == 0) { - config_data->device_props.mode = AUDIO_MODE_IN_CALL; - } else if(strcmp(attr[i], "in-communication") == 0) { - config_data->device_props.mode = AUDIO_MODE_IN_COMMUNICATION; - } else { - LOGE("Unknown mode attr: %s", attr[i]); - } + config_data->io_props.card = atoi(attr[i]); + } else if(strcmp(attr[i], "device") == 0) { + i++; + config_data->io_props.device = atoi(attr[i]); + } else { + LOGE("Unknown modem attr: %s", attr[i]); } } } else if(strcmp(elem, "device") == 0) { for(i=0 ; attr[i] != NULL && attr[i+1] != NULL ; i++) { if(strcmp(attr[i], "type") == 0) { i++; - if((config_data->direction & (~AUDIO_DEVICE_OUT_ALL)) == 0) { + if(config_data->direction == TINYALSA_MIXER_DIRECTION_OUTPUT || + config_data->direction == TINYALSA_MIXER_DIRECTION_MODEM) { if(strcmp(attr[i], "default") == 0) { config_data->device_props.type = AUDIO_DEVICE_OUT_DEFAULT; } else if(strcmp(attr[i], "earpiece") == 0) { @@ -415,8 +412,10 @@ void tinyalsa_mixer_config_start(void *data, const XML_Char *elem, } else { LOGE("Unknown device attr: %s", attr[i]); } - } else if((config_data->direction & (~AUDIO_DEVICE_IN_ALL)) == 0) { - if(strcmp(attr[i], "communication") == 0) { + } else if(config_data->direction == TINYALSA_MIXER_DIRECTION_INPUT) { + if(strcmp(attr[i], "default") == 0) { + config_data->device_props.type = AUDIO_DEVICE_IN_DEFAULT; + } else if(strcmp(attr[i], "communication") == 0) { config_data->device_props.type = AUDIO_DEVICE_IN_COMMUNICATION; } else if(strcmp(attr[i], "ambient") == 0) { config_data->device_props.type = AUDIO_DEVICE_IN_AMBIENT; @@ -436,19 +435,6 @@ void tinyalsa_mixer_config_start(void *data, const XML_Char *elem, LOGE("Unknown device attr: %s", attr[i]); } } - } else if(strcmp(attr[i], "mode") == 0) { - i++; - if(strcmp(attr[i], "normal") == 0) { - config_data->device_props.mode = AUDIO_MODE_NORMAL; - } else if(strcmp(attr[i], "ringtone") == 0) { - config_data->device_props.mode = AUDIO_MODE_RINGTONE; - } else if(strcmp(attr[i], "in-call") == 0) { - config_data->device_props.mode = AUDIO_MODE_IN_CALL; - } else if(strcmp(attr[i], "in-communication") == 0) { - config_data->device_props.mode = AUDIO_MODE_IN_COMMUNICATION; - } else { - LOGE("Unknown mode attr: %s", attr[i]); - } } else { LOGE("Unknown device attr: %s", attr[i]); } @@ -537,9 +523,13 @@ void tinyalsa_mixer_config_end(void *data, const XML_Char *elem) memcpy(&config_data->mixer->input.props, &config_data->io_props, sizeof(config_data->io_props)); memset(&config_data->io_props, 0, sizeof(config_data->io_props)); config_data->direction = 0; + } else if(strcmp(elem, "modem") == 0) { + memcpy(&config_data->mixer->modem.props, &config_data->io_props, sizeof(config_data->io_props)); + memset(&config_data->io_props, 0, sizeof(config_data->io_props)); + config_data->direction = 0; } else if(strcmp(elem, "device") == 0) { // direction == 0 will fallback to out - if((config_data->direction & (~AUDIO_DEVICE_OUT_ALL)) == 0) { + if(config_data->direction == TINYALSA_MIXER_DIRECTION_OUTPUT) { list = list_head_alloc(); list->data = (void *) config_data->device; @@ -554,7 +544,7 @@ void tinyalsa_mixer_config_end(void *data, const XML_Char *elem) list_prev->next = list; list->prev = list_prev; } - } else if((config_data->direction & (~AUDIO_DEVICE_IN_ALL)) == 0) { + } else if(config_data->direction == TINYALSA_MIXER_DIRECTION_INPUT) { list = list_head_alloc(); list->data = (void *) config_data->device; @@ -569,6 +559,21 @@ void tinyalsa_mixer_config_end(void *data, const XML_Char *elem) list_prev->next = list; list->prev = list_prev; } + } else if(config_data->direction == TINYALSA_MIXER_DIRECTION_MODEM) { + list = list_head_alloc(); + list->data = (void *) config_data->device; + + if(config_data->mixer->modem.devices == NULL) { + config_data->mixer->modem.devices = list; + } else { + list_prev = config_data->mixer->modem.devices; + + while(list_prev->next != NULL) + list_prev = list_prev->next; + + list_prev->next = list; + list->prev = list_prev; + } } config_data->device = NULL; @@ -642,7 +647,7 @@ error_file: } /* - * Route + * Route/Directions */ int tinyalsa_mixer_set_route_ctrl(struct tinyalsa_mixer *mixer, @@ -724,8 +729,60 @@ int tinyalsa_mixer_set_route_list(struct tinyalsa_mixer *mixer, struct list_head return 0; } +int tinyalsa_mixer_set_route(struct tinyalsa_mixer *mixer, + struct tinyalsa_mixer_io *mixer_io, audio_devices_t device) +{ + struct tinyalsa_mixer_device *mixer_device = NULL; + struct list_head *list = NULL; + int rc; + + if(mixer == NULL || mixer_io == NULL) + return -1; + + mixer->mixer = mixer_open(mixer_io->props.card); + if(mixer->mixer == NULL) { + LOGE("Unable to open mixer for card: %d", mixer_io->props.card); + return -1; + } + + + mixer_device = tinyalsa_mixer_get_device(mixer_io, device); + if(mixer_device == NULL) { + LOGE("Unable to find a matching device: 0x%x", device); + goto error_mixer; + } + + if(mixer_io->device_current != NULL) { + rc = tinyalsa_mixer_set_route_list(mixer, mixer_io->device_current->disable); + if(rc < 0) { + LOGE("Unable to disable current device controls"); + goto error_mixer; + } + } + + rc = tinyalsa_mixer_set_route_list(mixer, mixer_device->enable); + if(rc < 0) { + LOGE("Unable to enable device controls"); + goto error_mixer; + } + + mixer_io->device_current = mixer_device; + + mixer_close(mixer->mixer); + mixer->mixer = NULL; + + return 0; + +error_mixer: + mixer_close(mixer->mixer); + mixer->mixer = NULL; + + return -1; +} + int tinyalsa_mixer_set_device_volume_with_attr(struct tinyalsa_mixer *mixer, - audio_devices_t device, audio_mode_t mode, char *attr, float volume) + enum tinyalsa_mixer_direction direction, audio_devices_t device, + char *attr, float volume) { struct tinyalsa_mixer_io *mixer_io = NULL; struct tinyalsa_mixer_device *mixer_device = NULL; @@ -738,12 +795,23 @@ int tinyalsa_mixer_set_device_volume_with_attr(struct tinyalsa_mixer *mixer, if(mixer == NULL || attr == NULL) return -1; - if(audio_is_output_device(device)) { - mixer_io = &mixer->output; - } else if(audio_is_input_device(device)) { - mixer_io = &mixer->input; - } else { - LOGE("Invalid device: 0x%x", device); + switch(direction) { + case TINYALSA_MIXER_DIRECTION_OUTPUT: + mixer_io = &mixer->output; + break; + case TINYALSA_MIXER_DIRECTION_INPUT: + mixer_io = &mixer->input; + break; + case TINYALSA_MIXER_DIRECTION_MODEM: + mixer_io = &mixer->modem; + break; + default: + LOGE("Invalid diretion: 0x%x", direction); + return -1; + } + + if(!mixer_io->state) { + LOGE("Unable to set device for the asked direction: state is %d", mixer_io->state); return -1; } @@ -753,10 +821,9 @@ int tinyalsa_mixer_set_device_volume_with_attr(struct tinyalsa_mixer *mixer, return -1; } - mixer_device = tinyalsa_mixer_get_device(mixer_io, device, mode); + mixer_device = tinyalsa_mixer_get_device(mixer_io, device); if(mixer_device == NULL) { - LOGE("Unable to find a matching device: 0x%x with mode: 0x%x", - device, mode); + LOGE("Unable to find a matching device: 0x%x", device); goto error_mixer; } @@ -811,7 +878,8 @@ error_mixer: } int tinyalsa_mixer_set_device_state_with_attr(struct tinyalsa_mixer *mixer, - audio_devices_t device, audio_mode_t mode, char *attr, int state) + enum tinyalsa_mixer_direction direction, audio_devices_t device, + char *attr, int state) { struct tinyalsa_mixer_io *mixer_io = NULL; struct tinyalsa_mixer_device *mixer_device = NULL; @@ -822,12 +890,25 @@ int tinyalsa_mixer_set_device_state_with_attr(struct tinyalsa_mixer *mixer, if(mixer == NULL || attr == NULL) return -1; - if(audio_is_output_device(device)) { - mixer_io = &mixer->output; - } else if(audio_is_input_device(device)) { - mixer_io = &mixer->input; - } else { - LOGE("Invalid device: 0x%x", device); + state = state >= 1 ? 1 : 0; + + switch(direction) { + case TINYALSA_MIXER_DIRECTION_OUTPUT: + mixer_io = &mixer->output; + break; + case TINYALSA_MIXER_DIRECTION_INPUT: + mixer_io = &mixer->input; + break; + case TINYALSA_MIXER_DIRECTION_MODEM: + mixer_io = &mixer->modem; + break; + default: + LOGE("Invalid diretion: 0x%x", direction); + return -1; + } + + if(!mixer_io->state) { + LOGE("Unable to set device for the asked direction: state is %d", mixer_io->state); return -1; } @@ -837,10 +918,9 @@ int tinyalsa_mixer_set_device_state_with_attr(struct tinyalsa_mixer *mixer, return -1; } - mixer_device = tinyalsa_mixer_get_device(mixer_io, device, mode); + mixer_device = tinyalsa_mixer_get_device(mixer_io, device); if(mixer_device == NULL) { - LOGE("Unable to find a matching device: 0x%x with mode: 0x%x", - device, mode); + LOGE("Unable to find a matching device: 0x%x", device); goto error_mixer; } @@ -873,34 +953,41 @@ error_mixer: return -1; } -/* - * Interface - */ - -int tinyalsa_mixer_set_route(struct tinyalsa_mixer *mixer, audio_devices_t device, audio_mode_t mode) +int tinyalsa_mixer_set_state(struct tinyalsa_mixer *mixer, + enum tinyalsa_mixer_direction direction, int state) { struct tinyalsa_mixer_io *mixer_io = NULL; struct tinyalsa_mixer_device *mixer_device = NULL; - struct list_head *list = NULL; - int device_default = 0; + struct list_head *list; + audio_devices_t default_device; int rc; - LOGD("%s(%x, %x)", __func__, device, mode); - if(mixer == NULL) return -1; - if(audio_is_output_device(device)) { - mixer_io = &mixer->output; - if(device == AUDIO_DEVICE_OUT_DEFAULT) - device_default = 1; - } else if(audio_is_input_device(device)) { - mixer_io = &mixer->input; - if(device == AUDIO_DEVICE_IN_DEFAULT) - device_default = 1; - } else { - LOGE("Invalid device: 0x%x", device); - return -1; + state = state >= 1 ? 1 : 0; + + switch(direction) { + case TINYALSA_MIXER_DIRECTION_OUTPUT: + mixer_io = &mixer->output; + default_device = AUDIO_DEVICE_OUT_DEFAULT; + break; + case TINYALSA_MIXER_DIRECTION_INPUT: + mixer_io = &mixer->input; + default_device = AUDIO_DEVICE_IN_DEFAULT; + break; + case TINYALSA_MIXER_DIRECTION_MODEM: + mixer_io = &mixer->modem; + default_device = AUDIO_DEVICE_OUT_DEFAULT; + break; + default: + LOGE("Invalid diretion: 0x%x", direction); + return -1; + } + + if(mixer_io->state == state) { + LOGD("Current state is already: %d", state); + return 0; } mixer->mixer = mixer_open(mixer_io->props.card); @@ -909,40 +996,37 @@ int tinyalsa_mixer_set_route(struct tinyalsa_mixer *mixer, audio_devices_t devic return -1; } - if(device_default && mixer_io->device_current != NULL) { + if(!state && mixer_io->device_current != NULL && + mixer_io->device_current->disable != NULL) { rc = tinyalsa_mixer_set_route_list(mixer, mixer_io->device_current->disable); if(rc < 0) { LOGE("Unable to disable current device controls"); goto error_mixer; } - - mixer_io->device_current = NULL; - - goto exit_mixer; } - mixer_device = tinyalsa_mixer_get_device(mixer_io, device, mode); + mixer_device = tinyalsa_mixer_get_device(mixer_io, default_device); if(mixer_device == NULL) { - LOGE("Unable to find a matching device: 0x%x with mode: 0x%x", - device, mode); - goto error_mixer; + LOGD("Unable to find default device"); + // This is not really an issue } - if(mixer_io->device_current != NULL) { - rc = tinyalsa_mixer_set_route_list(mixer, mixer_io->device_current->disable); + if(state && mixer_device != NULL && mixer_device->enable != NULL) { + rc = tinyalsa_mixer_set_route_list(mixer, mixer_device->enable); if(rc < 0) { - LOGE("Unable to disable current device controls"); + LOGE("Unable to enable default device controls"); + goto error_mixer; + } + } else if(!state && mixer_device != NULL) { + rc = tinyalsa_mixer_set_route_list(mixer, mixer_device->disable); + if(rc < 0) { + LOGE("Unable to disable default device controls"); goto error_mixer; } } - rc = tinyalsa_mixer_set_route_list(mixer, mixer_device->enable); - if(rc < 0) { - LOGE("Unable to enable device controls"); - goto error_mixer; - } - - mixer_io->device_current = mixer_device; + mixer_io->device_current = NULL; + mixer_io->state = state; exit_mixer: mixer_close(mixer->mixer); @@ -957,12 +1041,80 @@ error_mixer: return -1; } +/* + * Interface + */ + +int tinyalsa_mixer_set_output_state(struct tinyalsa_mixer *mixer, int state) +{ + LOGD("%s(%d)", __func__, state); + + return tinyalsa_mixer_set_state(mixer, TINYALSA_MIXER_DIRECTION_OUTPUT, state); +} + +int tinyalsa_mixer_set_input_state(struct tinyalsa_mixer *mixer, int state) +{ + LOGD("%s(%d)", __func__, state); + + return tinyalsa_mixer_set_state(mixer, TINYALSA_MIXER_DIRECTION_INPUT, state); +} + +int tinyalsa_mixer_set_modem_state(struct tinyalsa_mixer *mixer, int state) +{ + LOGD("%s(%d)", __func__, state); + + return tinyalsa_mixer_set_state(mixer, TINYALSA_MIXER_DIRECTION_MODEM, state); +} + +int tinyalsa_mixer_set_device(struct tinyalsa_mixer *mixer, audio_devices_t device) +{ + int rc; + + LOGD("%s(%x)", __func__, device); + + if(mixer == NULL) + return -1; + + if(!audio_is_output_device(device) && !audio_is_input_device(device)) { + LOGE("Invalid device: 0x%x", device); + return -1; + } + + + if(audio_is_output_device(device) && mixer->output.state) { + rc = tinyalsa_mixer_set_route(mixer, &mixer->output, device); + if(rc < 0) { + LOGE("Unable to set route for device: %x", device); + return -1; + } + } + + if(audio_is_input_device(device) && mixer->input.state) { + rc = tinyalsa_mixer_set_route(mixer, &mixer->input, device); + if(rc < 0) { + LOGE("Unable to set route for device: %x", device); + return -1; + } + } + + if(audio_is_output_device(device) && mixer->modem.state) { + rc = tinyalsa_mixer_set_route(mixer, &mixer->modem, device); + if(rc < 0) { + LOGE("Unable to set route for device: %x", device); + return -1; + } + } + + return 0; +} + int tinyalsa_mixer_set_output_volume(struct tinyalsa_mixer *mixer, - audio_devices_t device, audio_mode_t mode, float volume) + audio_devices_t device, float volume) { - LOGD("%s(%p, %x, %x, %f)", __func__, mixer, device, mode, volume); + LOGD("%s(%p, %x, %f)", __func__, mixer, device, volume); - return tinyalsa_mixer_set_device_volume_with_attr(mixer, device, mode, + return tinyalsa_mixer_set_device_volume_with_attr(mixer, + TINYALSA_MIXER_DIRECTION_OUTPUT, device, "output-volume", volume); } @@ -971,34 +1123,46 @@ int tinyalsa_mixer_set_master_volume(struct tinyalsa_mixer *mixer, float volume) LOGD("%s(%p, %f)", __func__, mixer, volume); return tinyalsa_mixer_set_device_volume_with_attr(mixer, - AUDIO_DEVICE_OUT_DEFAULT, AUDIO_MODE_NORMAL, + TINYALSA_MIXER_DIRECTION_OUTPUT, AUDIO_DEVICE_OUT_DEFAULT, "master-volume", volume); } int tinyalsa_mixer_set_mic_mute(struct tinyalsa_mixer *mixer, - audio_devices_t device, audio_mode_t mode, int mute) + audio_devices_t device, int mute) { - LOGD("%s(%p, %x, %x, %d)", __func__, mixer, device, mode, mute); - - return tinyalsa_mixer_set_device_state_with_attr(mixer, device, mode, - "mic-mute", mute ? 0 : 1); + LOGD("%s(%p, %x, %d)", __func__, mixer, device, mute); + + // Mic mute can be set for both input and modem directions + if(audio_is_input_device(device)) { + return tinyalsa_mixer_set_device_state_with_attr(mixer, + TINYALSA_MIXER_DIRECTION_INPUT, device, + "mic-mute", mute); + } else if(audio_is_output_device(device)) { + return tinyalsa_mixer_set_device_state_with_attr(mixer, + TINYALSA_MIXER_DIRECTION_MODEM, device, + "mic-mute", mute); + } else { + return -1; + } } int tinyalsa_mixer_set_input_gain(struct tinyalsa_mixer *mixer, - audio_devices_t device, audio_mode_t mode, float gain) + audio_devices_t device, float gain) { - LOGD("%s(%p, %x, %x, %f)", __func__, mixer, device, mode, gain); + LOGD("%s(%p, %x, %f)", __func__, mixer, device, gain); - return tinyalsa_mixer_set_device_volume_with_attr(mixer, device, mode, + return tinyalsa_mixer_set_device_volume_with_attr(mixer, + TINYALSA_MIXER_DIRECTION_INPUT, device, "input-gain", gain); } int tinyalsa_mixer_set_voice_volume(struct tinyalsa_mixer *mixer, - audio_devices_t device, audio_mode_t mode, float volume) + audio_devices_t device, float volume) { - LOGD("%s(%p, %x, %x, %f)", __func__, mixer, device, mode, volume); + LOGD("%s(%p, %x, %f)", __func__, mixer, device, volume); - return tinyalsa_mixer_set_device_volume_with_attr(mixer, device, mode, + return tinyalsa_mixer_set_device_volume_with_attr(mixer, + TINYALSA_MIXER_DIRECTION_MODEM, device, "voice-volume", volume); } @@ -1033,6 +1197,16 @@ audio_devices_t tinyalsa_mixer_get_supported_devices(struct tinyalsa_mixer *mixe list = list->next; } + list = mixer->modem.devices; + while(list != NULL) { + if(list->data != NULL) { + mixer_device = (struct tinyalsa_mixer_device *) list->data; + devices |= mixer_device->props.type; + } + + list = list->next; + } + return devices; } @@ -1050,6 +1224,13 @@ struct tinyalsa_mixer_io_props *tinyalsa_mixer_get_input_props(struct tinyalsa_m return &(mixer->input.props); } +struct tinyalsa_mixer_io_props *tinyalsa_mixer_get_modem_props(struct tinyalsa_mixer *mixer) +{ + LOGD("%s(%p)", __func__, mixer); + + return &(mixer->modem.props); +} + void tinyalsa_mixer_close(struct tinyalsa_mixer *mixer) { LOGD("%s(%p)", __func__, mixer); @@ -1057,8 +1238,13 @@ void tinyalsa_mixer_close(struct tinyalsa_mixer *mixer) if(mixer == NULL) return; + tinyalsa_mixer_set_output_state(mixer, 0); + tinyalsa_mixer_set_input_state(mixer, 0); + tinyalsa_mixer_set_modem_state(mixer, 0); + tinyalsa_mixer_io_free_devices(&mixer->output); tinyalsa_mixer_io_free_devices(&mixer->input); + tinyalsa_mixer_io_free_devices(&mixer->modem); free(mixer); } diff --git a/mixer.h b/mixer.h index 3b1e19b..a6f7cca 100644 --- a/mixer.h +++ b/mixer.h @@ -47,7 +47,6 @@ struct tinyalsa_mixer_data { struct tinyalsa_mixer_device_props { audio_devices_t type; - audio_mode_t mode; }; struct tinyalsa_mixer_device { @@ -72,42 +71,56 @@ struct tinyalsa_mixer_io { struct tinyalsa_mixer_io_props props; struct tinyalsa_mixer_device *device_current; struct list_head *devices; + int state; }; struct tinyalsa_mixer { struct tinyalsa_mixer_io output; struct tinyalsa_mixer_io input; + struct tinyalsa_mixer_io modem; struct mixer *mixer; }; +enum tinyalsa_mixer_direction { + TINYALSA_MIXER_DIRECTION_OUTPUT, + TINYALSA_MIXER_DIRECTION_INPUT, + TINYALSA_MIXER_DIRECTION_MODEM, + TINYALSA_MIXER_DIRECTION_MAX +}; + struct tinyalsa_mixer_config_data { struct tinyalsa_mixer *mixer; struct tinyalsa_mixer_io_props io_props; struct tinyalsa_mixer_device_props device_props; - int direction; + enum tinyalsa_mixer_direction direction; struct tinyalsa_mixer_device *device; struct list_head **list_start; struct list_head *list; }; -int tinyalsa_mixer_open(struct tinyalsa_mixer **mixer_p, char *config_file); -void tinyalsa_mixer_close(struct tinyalsa_mixer *mixer); +int tinyalsa_mixer_set_output_state(struct tinyalsa_mixer *mixer, int state); +int tinyalsa_mixer_set_input_state(struct tinyalsa_mixer *mixer, int state); +int tinyalsa_mixer_set_modem_state(struct tinyalsa_mixer *mixer, int state); -struct tinyalsa_mixer_io_props *tinyalsa_mixer_get_input_props(struct tinyalsa_mixer *mixer); -struct tinyalsa_mixer_io_props *tinyalsa_mixer_get_output_props(struct tinyalsa_mixer *mixer); -audio_devices_t tinyalsa_mixer_get_supported_devices(struct tinyalsa_mixer *mixer); +int tinyalsa_mixer_set_device(struct tinyalsa_mixer *mixer, audio_devices_t device); -int tinyalsa_mixer_set_voice_volume(struct tinyalsa_mixer *mixer, - audio_devices_t device, audio_mode_t mode, float volume); -int tinyalsa_mixer_set_input_gain(struct tinyalsa_mixer *mixer, - audio_devices_t device, audio_mode_t mode, float gain); -int tinyalsa_mixer_set_mic_mute(struct tinyalsa_mixer *mixer, - audio_devices_t device, audio_mode_t mode, int mute); -int tinyalsa_mixer_set_master_volume(struct tinyalsa_mixer *mixer, float volume); int tinyalsa_mixer_set_output_volume(struct tinyalsa_mixer *mixer, - audio_devices_t device, audio_mode_t mode, float volume); + audio_devices_t device, float volume); +int tinyalsa_mixer_set_master_volume(struct tinyalsa_mixer *mixer, float volume); +int tinyalsa_mixer_set_mic_mute(struct tinyalsa_mixer *mixer, + audio_devices_t device, int mute); +int tinyalsa_mixer_set_input_gain(struct tinyalsa_mixer *mixer, + audio_devices_t device, float gain); +int tinyalsa_mixer_set_voice_volume(struct tinyalsa_mixer *mixer, + audio_devices_t device, float volume); + +audio_devices_t tinyalsa_mixer_get_supported_devices(struct tinyalsa_mixer *mixer); +struct tinyalsa_mixer_io_props *tinyalsa_mixer_get_output_props(struct tinyalsa_mixer *mixer); +struct tinyalsa_mixer_io_props *tinyalsa_mixer_get_input_props(struct tinyalsa_mixer *mixer); +struct tinyalsa_mixer_io_props *tinyalsa_mixer_get_modem_props(struct tinyalsa_mixer *mixer); -int tinyalsa_mixer_set_route(struct tinyalsa_mixer *mixer, audio_devices_t device, audio_mode_t mode); +void tinyalsa_mixer_close(struct tinyalsa_mixer *mixer); +int tinyalsa_mixer_open(struct tinyalsa_mixer **mixer_p, char *config_file); #endif -- cgit v1.1