From 8aed9f23e589576d5bcc156f1f7d7544825fe5c2 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Sat, 13 Oct 2012 11:52:21 +0200 Subject: Mixer: Proper device attr functions, clean split of alloc/free functions Signed-off-by: Paul Kocialkowski --- mixer.c | 437 +++++++++++++++++++++++++++++++++++++++++++--------------------- mixer.h | 15 ++- 2 files changed, 306 insertions(+), 146 deletions(-) diff --git a/mixer.c b/mixer.c index 508fea8..1781215 100644 --- a/mixer.c +++ b/mixer.c @@ -93,6 +93,142 @@ void tinyalsa_mixer_data_free(struct tinyalsa_mixer_data *mixer_data) free(mixer_data); } +struct tinyalsa_mixer_data *tinyalsa_mixer_get_data_with_attr( + struct list_head *list_data, char *attr) +{ + struct tinyalsa_mixer_data *mixer_data = NULL; + + while(list_data != NULL) { + mixer_data = (struct tinyalsa_mixer_data *) list_data->data; + + if(mixer_data->type == MIXER_DATA_TYPE_CTRL) { + if(mixer_data->attr != NULL && + strcmp(mixer_data->attr, attr) == 0) { + break; + } else { + mixer_data = NULL; + } + + } + + if(list_data->next != NULL) + list_data = list_data->next; + else + break; + } + + return mixer_data; +} + +/* + * Mixer device + */ + +struct tinyalsa_mixer_device *tinyalsa_mixer_device_alloc(void) +{ + struct tinyalsa_mixer_device *mixer_device = (struct tinyalsa_mixer_device *) + calloc(1, sizeof(struct tinyalsa_mixer_device)); + + return mixer_device; +} + +void tinyalsa_mixer_device_free(struct tinyalsa_mixer_device *mixer_device) +{ + struct tinyalsa_mixer_data *mixer_data; + struct list_head *list_data; + struct list_head *list_prev; + + if(mixer_device == NULL) + return; + + list_data = mixer_device->enable; + + while(list_data != NULL) { + mixer_data = (struct tinyalsa_mixer_data *) list_data->data; + + tinyalsa_mixer_data_free(mixer_data); + list_data->data = NULL; + + list_prev = list_data; + list_data = list_data->next; + + list_head_free(list_prev); + } + + list_data = mixer_device->disable; + + while(list_data != NULL) { + mixer_data = (struct tinyalsa_mixer_data *) list_data->data; + + tinyalsa_mixer_data_free(mixer_data); + list_data->data = NULL; + + list_prev = list_data; + list_data = list_data->next; + + list_head_free(list_prev); + } + + mixer_device->enable = NULL; + mixer_device->disable = NULL; + + free(mixer_device); +} + +struct tinyalsa_mixer_device *tinyalsa_mixer_get_device(struct tinyalsa_mixer_io *mixer_io, + audio_devices_t device, audio_mode_t mode) +{ + struct tinyalsa_mixer_device *mixer_device = NULL; + struct list_head *list = NULL; + + if(mixer_io == NULL) + return NULL; + + list = mixer_io->devices; + + 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) { + break; + } else { + mixer_device = NULL; + } + + list = list->next; + } + + return mixer_device; +} + +/* + * Mixer I/O + */ + +void tinyalsa_mixer_io_free_devices(struct tinyalsa_mixer_io *mixer_io) +{ + struct tinyalsa_mixer_device *mixer_device; + struct list_head *list_device; + struct list_head *list_prev; + + if(mixer_io == NULL) + return; + + list_device = mixer_io->devices; + + while(list_device != NULL) { + mixer_device = (struct tinyalsa_mixer_device *) list_device->data; + + tinyalsa_mixer_device_free(mixer_device); + list_device->data = NULL; + + list_prev = list_device; + list_device = list_device->next; + + list_head_free(list_prev); + } +} + /* * Mixer config */ @@ -318,7 +454,7 @@ void tinyalsa_mixer_config_start(void *data, const XML_Char *elem, } if(config_data->device_props.type != 0) { - config_data->device = calloc(1, sizeof(struct tinyalsa_mixer_device)); + config_data->device = tinyalsa_mixer_device_alloc(); memcpy(&config_data->device->props, &config_data->device_props, sizeof(config_data->device_props)); } else { LOGE("Missing attrs for elem: %s", elem); @@ -506,7 +642,7 @@ error_file: } /* - * Interface + * Route */ int tinyalsa_mixer_set_route_ctrl(struct tinyalsa_mixer *mixer, @@ -588,16 +724,18 @@ int tinyalsa_mixer_set_route_list(struct tinyalsa_mixer *mixer, struct list_head return 0; } -int tinyalsa_mixer_set_route(struct tinyalsa_mixer *mixer, audio_devices_t device, audio_mode_t mode) +int tinyalsa_mixer_set_device_volume_with_attr(struct tinyalsa_mixer *mixer, + audio_devices_t device, audio_mode_t mode, char *attr, float volume) { struct tinyalsa_mixer_io *mixer_io = NULL; struct tinyalsa_mixer_device *mixer_device = NULL; + struct tinyalsa_mixer_data *mixer_data = NULL; struct list_head *list = NULL; + int value, value_min, value_max, values_count; + char *value_string = NULL; int rc; - LOGD("%s(%x, %x)", __func__, device, mode); - - if(mixer == NULL) + if(mixer == NULL || attr == NULL) return -1; if(audio_is_output_device(device)) { @@ -615,46 +753,56 @@ int tinyalsa_mixer_set_route(struct tinyalsa_mixer *mixer, audio_devices_t devic return -1; } - list = mixer_io->devices; + mixer_device = tinyalsa_mixer_get_device(mixer_io, device, mode); + if(mixer_device == NULL) { + LOGE("Unable to find a matching device: 0x%x with mode: 0x%x", + device, mode); + goto error_mixer; + } - 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) { - break; - } else { - mixer_device = NULL; - } + list = mixer_device->enable; - list = list->next; + mixer_data = tinyalsa_mixer_get_data_with_attr(list, attr); + if(mixer_data == NULL) { + LOGE("Unable to find a matching ctrl with attr: %s", attr); + goto error_mixer; } - if(mixer_device == NULL) { - LOGE("Unable to find a matching device: 0x%x with mode: 0x%x", - device, mode); + if(mixer_data->value == NULL) { + LOGE("Missing mixer data value!"); 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; - } + values_count = sscanf(mixer_data->value, "%d-%d", &value_min, &value_max); + if(values_count != 2) { + LOGE("Failed to get mixer data value!"); + goto error_mixer; } - rc = tinyalsa_mixer_set_route_list(mixer, mixer_device->enable); + value = (value_max - value_min) * volume + value_min; + + // Ugly workaround because a string value is needed + value_string = mixer_data->value; + asprintf(&mixer_data->value, "%d", value); + + rc = tinyalsa_mixer_set_route_ctrl(mixer, mixer_data); if(rc < 0) { - LOGE("Unable to enable device controls"); - goto error_mixer; + LOGE("Unable to set ctrl!"); + goto error_data; } - mixer_io->device_current = mixer_device; + free(mixer_data->value); + mixer_data->value = value_string; + mixer_close(mixer->mixer); mixer->mixer = NULL; return 0; +error_data: + free(mixer_data->value); + mixer_data->value = value_string; + error_mixer: mixer_close(mixer->mixer); mixer->mixer = NULL; @@ -662,19 +810,26 @@ error_mixer: return -1; } -int tinyalsa_mixer_set_device_attr(struct tinyalsa_mixer *mixer, - audio_devices_t device, int enable, struct tinyalsa_mixer_io *mixer_io, - char *attr) +int tinyalsa_mixer_set_device_state_with_attr(struct tinyalsa_mixer *mixer, + audio_devices_t device, audio_mode_t mode, char *attr, int state) { + struct tinyalsa_mixer_io *mixer_io = NULL; struct tinyalsa_mixer_device *mixer_device = NULL; struct tinyalsa_mixer_data *mixer_data = NULL; struct list_head *list = NULL; int rc; - if(attr == NULL || mixer_io == NULL) + if(mixer == NULL || attr == NULL) return -1; - list = mixer_io->devices; + 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); + return -1; + } mixer->mixer = mixer_open(mixer_io->props.card); if(mixer->mixer == NULL) { @@ -682,49 +837,101 @@ int tinyalsa_mixer_set_device_attr(struct tinyalsa_mixer *mixer, return -1; } - while(list != NULL) { - mixer_device = (struct tinyalsa_mixer_device *) list->data; - if(mixer_device != NULL && mixer_device->props.type == device) { - break; - } else { - mixer_device = NULL; - } - - list = list->next; - } - + mixer_device = tinyalsa_mixer_get_device(mixer_io, device, mode); if(mixer_device == NULL) { - LOGE("Unable to find a matching device: 0x%x", device); + LOGE("Unable to find a matching device: 0x%x with mode: 0x%x", + device, mode); goto error_mixer; } - if(enable) + if(state) list = mixer_device->enable; else list = mixer_device->disable; - while(list != NULL) { - mixer_data = (struct tinyalsa_mixer_data *) list->data; + mixer_data = tinyalsa_mixer_get_data_with_attr(list, attr); + if(mixer_data == NULL) { + LOGE("Unable to find a matching ctrl with attr: %s", attr); + goto error_mixer; + } - if(mixer_data->type == MIXER_DATA_TYPE_CTRL) { - if(mixer_data->attr != NULL && - strcmp(mixer_data->attr, attr) == 0) { - rc = tinyalsa_mixer_set_route_ctrl(mixer, mixer_data); - if(rc < 0) { - LOGE("Unable to set control!"); - goto error_mixer; - } + rc = tinyalsa_mixer_set_route_ctrl(mixer, mixer_data); + if(rc < 0) { + LOGE("Unable to set ctrl!"); + goto error_mixer; + } - break; - } + mixer_close(mixer->mixer); + mixer->mixer = NULL; + + return 0; + +error_mixer: + mixer_close(mixer->mixer); + mixer->mixer = NULL; + + return -1; +} + +/* + * Interface + */ + +int tinyalsa_mixer_set_route(struct tinyalsa_mixer *mixer, audio_devices_t device, audio_mode_t mode) +{ + struct tinyalsa_mixer_io *mixer_io = NULL; + struct tinyalsa_mixer_device *mixer_device = NULL; + struct list_head *list = NULL; + int rc; + + LOGD("%s(%x, %x)", __func__, device, mode); + + if(mixer == 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); + 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, mode); + if(mixer_device == NULL) { + LOGE("Unable to find a matching device: 0x%x with mode: 0x%x", + device, mode); + goto error_mixer; + } + + if(mixer_device == NULL) { + LOGE("Unable to find a matching device: 0x%x with mode: 0x%x", + device, mode); + 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; } + } - if(list->next != NULL) - list = list->next; - else - break; - } + 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; @@ -737,44 +944,49 @@ error_mixer: return -1; } -int tinyalsa_mixer_set_output_volume(struct tinyalsa_mixer *mixer, audio_devices_t device) +int tinyalsa_mixer_set_output_volume(struct tinyalsa_mixer *mixer, + audio_devices_t device, audio_mode_t mode, float volume) { - LOGD("%s(%p, %x)", __func__, mixer, device); + LOGD("%s(%p, %x, %x, %f)", __func__, mixer, device, mode, volume); - return tinyalsa_mixer_set_device_attr(mixer, device, 1, - &mixer->output, "output-volume"); + return tinyalsa_mixer_set_device_volume_with_attr(mixer, device, mode, + "output-volume", volume); } -int tinyalsa_mixer_set_master_volume(struct tinyalsa_mixer *mixer, audio_devices_t device) +int tinyalsa_mixer_set_master_volume(struct tinyalsa_mixer *mixer, + audio_devices_t device, audio_mode_t mode, float volume) { - LOGD("%s(%p, %x)", __func__, mixer, device); + LOGD("%s(%p, %x, %x, %f)", __func__, mixer, device, mode, volume); - return tinyalsa_mixer_set_device_attr(mixer, device, 1, - &mixer->output, "master-volume"); + return tinyalsa_mixer_set_device_volume_with_attr(mixer, device, mode, + "master-volume", volume); } -int tinyalsa_mixer_set_mic_mute(struct tinyalsa_mixer *mixer, audio_devices_t device, int mute) +int tinyalsa_mixer_set_mic_mute(struct tinyalsa_mixer *mixer, + audio_devices_t device, audio_mode_t mode, int mute) { - LOGD("%s(%p, %x, %d)", __func__, mixer, device, mute); + LOGD("%s(%p, %x, %x, %d)", __func__, mixer, device, mode, mute); - return tinyalsa_mixer_set_device_attr(mixer, device, mute ? 0 : 1, - &mixer->input, "mic-mute"); + return tinyalsa_mixer_set_device_state_with_attr(mixer, device, mode, + "mic-mute", mute ? 0 : 1); } -int tinyalsa_mixer_set_input_gain(struct tinyalsa_mixer *mixer, audio_devices_t device) +int tinyalsa_mixer_set_input_gain(struct tinyalsa_mixer *mixer, + audio_devices_t device, audio_mode_t mode, float gain) { - LOGD("%s(%p, %x)", __func__, mixer, device); + LOGD("%s(%p, %x, %x, %f)", __func__, mixer, device, mode, gain); - return tinyalsa_mixer_set_device_attr(mixer, device, 1, - &mixer->input, "input-gain"); + return tinyalsa_mixer_set_device_volume_with_attr(mixer, device, mode, + "input-gain", gain); } -int tinyalsa_mixer_set_voice_volume(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) { - LOGD("%s(%p, %x)", __func__, mixer, device); + LOGD("%s(%p, %x, %x, %f)", __func__, mixer, device, mode, volume); - return tinyalsa_mixer_set_device_attr(mixer, device, 1, - &mixer->input, "voice-volume"); + return tinyalsa_mixer_set_device_volume_with_attr(mixer, device, mode, + "voice-volume", volume); } audio_devices_t tinyalsa_mixer_get_supported_devices(struct tinyalsa_mixer *mixer) @@ -825,63 +1037,6 @@ struct tinyalsa_mixer_io_props *tinyalsa_mixer_get_input_props(struct tinyalsa_m return &(mixer->input.props); } -void tinyalsa_mixer_io_free_devices(struct tinyalsa_mixer_io *mixer_io) -{ - struct tinyalsa_mixer_device *mixer_device; - struct tinyalsa_mixer_data *mixer_data; - struct list_head *list_device; - struct list_head *list_data; - struct list_head *list_prev; - - if(mixer_io == NULL) - return; - - list_device = mixer_io->devices; - - while(list_device != NULL) { - mixer_device = (struct tinyalsa_mixer_device *) list_device->data; - - list_data = mixer_device->enable; - - while(list_data != NULL) { - mixer_data = (struct tinyalsa_mixer_data *) list_data->data; - - tinyalsa_mixer_data_free(mixer_data); - list_data->data = NULL; - - list_prev = list_data; - list_data = list_data->next; - - list_head_free(list_prev); - } - - list_data = mixer_device->disable; - - while(list_data != NULL) { - mixer_data = (struct tinyalsa_mixer_data *) list_data->data; - - tinyalsa_mixer_data_free(mixer_data); - list_data->data = NULL; - - list_prev = list_data; - list_data = list_data->next; - - list_head_free(list_prev); - } - - mixer_device->enable = NULL; - mixer_device->disable = NULL; - - free(mixer_device); - list_device->data = NULL; - - list_prev = list_device; - list_device = list_device->next; - - list_head_free(list_prev); - } -} - void tinyalsa_mixer_close(struct tinyalsa_mixer *mixer) { LOGD("%s(%p)", __func__, mixer); diff --git a/mixer.h b/mixer.h index fd1d67d..669136c 100644 --- a/mixer.h +++ b/mixer.h @@ -98,11 +98,16 @@ struct tinyalsa_mixer_io_props *tinyalsa_mixer_get_input_props(struct tinyalsa_m 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_voice_volume(struct tinyalsa_mixer *mixer, audio_devices_t device); -int tinyalsa_mixer_set_input_gain(struct tinyalsa_mixer *mixer, audio_devices_t device); -int tinyalsa_mixer_set_mic_mute(struct tinyalsa_mixer *mixer, audio_devices_t device, int mute); -int tinyalsa_mixer_set_master_volume(struct tinyalsa_mixer *mixer, audio_devices_t device); -int tinyalsa_mixer_set_output_volume(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, + audio_devices_t device, audio_mode_t mode, float volume); +int tinyalsa_mixer_set_output_volume(struct tinyalsa_mixer *mixer, + audio_devices_t device, audio_mode_t mode, float volume); int tinyalsa_mixer_set_route(struct tinyalsa_mixer *mixer, audio_devices_t device, audio_mode_t mode); -- cgit v1.1