summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2012-10-13 11:52:21 +0200
committerPaul Kocialkowski <contact@paulk.fr>2012-10-13 11:52:21 +0200
commit8aed9f23e589576d5bcc156f1f7d7544825fe5c2 (patch)
tree0d111469fcf7faa85079bcd7c855821919371bec
parent5c413b14dd589b5d4f8e7f3ec088743988cc9e99 (diff)
downloadhardware_tinyalsa-audio-8aed9f23e589576d5bcc156f1f7d7544825fe5c2.zip
hardware_tinyalsa-audio-8aed9f23e589576d5bcc156f1f7d7544825fe5c2.tar.gz
hardware_tinyalsa-audio-8aed9f23e589576d5bcc156f1f7d7544825fe5c2.tar.bz2
Mixer: Proper device attr functions, clean split of alloc/free functions
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
-rw-r--r--mixer.c437
-rw-r--r--mixer.h15
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);