X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=audio_route%2Faudio_route.c;h=379695801b9ee17fc2feeaa9e2aef1eebe82a055;hb=c464b075738cbd007f6e82db3b619f79f6b90b05;hp=af1abca9045b8e64a8fe57537c0515304a83d182;hpb=41038a402a9f4a206cbb73674f6a8d9987c158ad;p=android-x86%2Fsystem-media.git diff --git a/audio_route/audio_route.c b/audio_route/audio_route.c index af1abca9..37969580 100644 --- a/audio_route/audio_route.c +++ b/audio_route/audio_route.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include @@ -33,7 +33,8 @@ #define INITIAL_MIXER_PATH_SIZE 8 union ctl_values { - int *integer; + int *enumerated; + long *integer; void *ptr; unsigned char *bytes; }; @@ -56,7 +57,7 @@ struct mixer_setting { struct mixer_value { unsigned int ctl_index; int index; - int value; + long value; }; struct mixer_path { @@ -97,12 +98,32 @@ static bool is_supported_ctl_type(enum mixer_ctl_type type) } } +/* as they match in alsa */ +static size_t sizeof_ctl_type(enum mixer_ctl_type type) { + switch (type) { + case MIXER_CTL_TYPE_BOOL: + case MIXER_CTL_TYPE_INT: + return sizeof(long); + case MIXER_CTL_TYPE_ENUM: + return sizeof(int); + case MIXER_CTL_TYPE_BYTE: + return sizeof(unsigned char); + case MIXER_CTL_TYPE_INT64: + case MIXER_CTL_TYPE_IEC958: + case MIXER_CTL_TYPE_UNKNOWN: + default: + LOG_ALWAYS_FATAL("Unsupported mixer ctl type: %d, check type before calling", (int)type); + return 0; + } +} + static inline struct mixer_ctl *index_to_ctl(struct audio_route *ar, unsigned int ctl_index) { return ar->mixer_state[ctl_index].ctl; } +#if 0 static void path_print(struct audio_route *ar, struct mixer_path *path) { unsigned int i; @@ -116,12 +137,16 @@ static void path_print(struct audio_route *ar, struct mixer_path *path) if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_BYTE) { for (j = 0; j < path->setting[i].num_values; j++) ALOGE(" id=%d value=0x%02x", j, path->setting[i].value.bytes[j]); + } else if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_ENUM) { + for (j = 0; j < path->setting[i].num_values; j++) + ALOGE(" id=%d value=%d", j, path->setting[i].value.enumerated[j]); } else { for (j = 0; j < path->setting[i].num_values; j++) - ALOGE(" id=%d value=%d", j, path->setting[i].value.integer[j]); + ALOGE(" id=%d value=%ld", j, path->setting[i].value.integer[j]); } } } +#endif static void path_free(struct audio_route *ar) { @@ -137,6 +162,8 @@ static void path_free(struct audio_route *ar) } } free(ar->mixer_path); + ar->mixer_path = NULL; + ar->mixer_path_size = 0; } static struct mixer_path *path_get_by_name(struct audio_route *ar, @@ -231,7 +258,6 @@ static int path_add_setting(struct audio_route *ar, struct mixer_path *path, struct mixer_setting *setting) { int path_index; - unsigned int value_sz = sizeof(int); if (find_ctl_index_in_path(path, setting->ctl_index) != -1) { struct mixer_ctl *ctl = index_to_ctl(ar, setting->ctl_index); @@ -241,6 +267,11 @@ static int path_add_setting(struct audio_route *ar, struct mixer_path *path, return -1; } + if (!is_supported_ctl_type(setting->type)) { + ALOGE("unsupported type %d", (int)setting->type); + return -1; + } + path_index = alloc_path_setting(path); if (path_index < 0) return -1; @@ -249,10 +280,9 @@ static int path_add_setting(struct audio_route *ar, struct mixer_path *path, path->setting[path_index].type = setting->type; path->setting[path_index].num_values = setting->num_values; - if (setting->type == MIXER_CTL_TYPE_BYTE) - value_sz = sizeof(unsigned char); + size_t value_sz = sizeof_ctl_type(setting->type); - path->setting[path_index].value.ptr = malloc(setting->num_values * value_sz); + path->setting[path_index].value.ptr = calloc(setting->num_values, value_sz); /* copy all values */ memcpy(path->setting[path_index].value.ptr, setting->value.ptr, setting->num_values * value_sz); @@ -266,7 +296,6 @@ static int path_add_value(struct audio_route *ar, struct mixer_path *path, unsigned int i; int path_index; unsigned int num_values; - unsigned int value_sz = sizeof(int); struct mixer_ctl *ctl; /* Check that mixer value index is within range */ @@ -282,6 +311,11 @@ static int path_add_value(struct audio_route *ar, struct mixer_path *path, if (path_index < 0) { /* New path */ + enum mixer_ctl_type type = mixer_ctl_get_type(ctl); + if (!is_supported_ctl_type(type)) { + ALOGE("unsupported type %d", (int)type); + return -1; + } path_index = alloc_path_setting(path); if (path_index < 0) return -1; @@ -289,14 +323,14 @@ static int path_add_value(struct audio_route *ar, struct mixer_path *path, /* initialise the new path setting */ path->setting[path_index].ctl_index = mixer_value->ctl_index; path->setting[path_index].num_values = num_values; - path->setting[path_index].type = mixer_ctl_get_type(ctl); + path->setting[path_index].type = type; - if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) - value_sz = sizeof(unsigned char); - - path->setting[path_index].value.ptr = malloc(num_values * value_sz); + size_t value_sz = sizeof_ctl_type(type); + path->setting[path_index].value.ptr = calloc(num_values, value_sz); if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) path->setting[path_index].value.bytes[0] = mixer_value->value; + else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM) + path->setting[path_index].value.enumerated[0] = mixer_value->value; else path->setting[path_index].value.integer[0] = mixer_value->value; } @@ -306,6 +340,9 @@ static int path_add_value(struct audio_route *ar, struct mixer_path *path, if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) { for (i = 0; i < num_values; i++) path->setting[path_index].value.bytes[i] = mixer_value->value; + } else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM) { + for (i = 0; i < num_values; i++) + path->setting[path_index].value.enumerated[i] = mixer_value->value; } else { for (i = 0; i < num_values; i++) path->setting[path_index].value.integer[i] = mixer_value->value; @@ -314,6 +351,8 @@ static int path_add_value(struct audio_route *ar, struct mixer_path *path, /* set only one value */ if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) path->setting[path_index].value.bytes[mixer_value->index] = mixer_value->value; + else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM) + path->setting[path_index].value.enumerated[mixer_value->index] = mixer_value->value; else path->setting[path_index].value.integer[mixer_value->index] = mixer_value->value; } @@ -336,7 +375,6 @@ static int path_add_path(struct audio_route *ar, struct mixer_path *path, static int path_apply(struct audio_route *ar, struct mixer_path *path) { unsigned int i; - unsigned int value_sz; unsigned int ctl_index; struct mixer_ctl *ctl; enum mixer_ctl_type type; @@ -347,12 +385,7 @@ static int path_apply(struct audio_route *ar, struct mixer_path *path) type = mixer_ctl_get_type(ctl); if (!is_supported_ctl_type(type)) continue; - - if (type == MIXER_CTL_TYPE_BYTE) - value_sz = sizeof(unsigned char); - else - value_sz = sizeof(int); - + size_t value_sz = sizeof_ctl_type(type); memcpy(ar->mixer_state[ctl_index].new_value.ptr, path->setting[i].value.ptr, path->setting[i].num_values * value_sz); } @@ -363,8 +396,6 @@ static int path_apply(struct audio_route *ar, struct mixer_path *path) static int path_reset(struct audio_route *ar, struct mixer_path *path) { unsigned int i; - unsigned int j; - unsigned int value_sz; unsigned int ctl_index; struct mixer_ctl *ctl; enum mixer_ctl_type type; @@ -375,12 +406,7 @@ static int path_reset(struct audio_route *ar, struct mixer_path *path) type = mixer_ctl_get_type(ctl); if (!is_supported_ctl_type(type)) continue; - - if (type == MIXER_CTL_TYPE_BYTE) - value_sz = sizeof(unsigned char); - else - value_sz = sizeof(int); - + size_t value_sz = sizeof_ctl_type(type); /* reset the value(s) */ memcpy(ar->mixer_state[ctl_index].new_value.ptr, ar->mixer_state[ctl_index].reset_value.ptr, @@ -394,13 +420,24 @@ static int path_reset(struct audio_route *ar, struct mixer_path *path) static int mixer_enum_string_to_value(struct mixer_ctl *ctl, const char *string) { unsigned int i; + unsigned int num_values = mixer_ctl_get_num_enums(ctl); + + if (string == NULL) { + ALOGE("NULL enum value string passed to mixer_enum_string_to_value() for ctl %s", + mixer_ctl_get_name(ctl)); + return 0; + } /* Search the enum strings for a particular one */ - for (i = 0; i < mixer_ctl_get_num_enums(ctl); i++) { + for (i = 0; i < num_values; i++) { if (strcmp(mixer_ctl_get_enum_string(ctl, i), string) == 0) break; } - + if (i == num_values) { + ALOGE("unknown enum value string %s for ctl %s", + string, mixer_ctl_get_name(ctl)); + return 0; + } return i; } @@ -415,7 +452,7 @@ static void start_tag(void *data, const XML_Char *tag_name, unsigned int i; unsigned int ctl_index; struct mixer_ctl *ctl; - int value; + long value; unsigned int id; struct mixer_value mixer_value; enum mixer_ctl_type type; @@ -457,7 +494,7 @@ static void start_tag(void *data, const XML_Char *tag_name, switch (mixer_ctl_get_type(ctl)) { case MIXER_CTL_TYPE_BOOL: case MIXER_CTL_TYPE_INT: - value = (int) strtol((char *)attr_value, NULL, 0); + value = strtol((char *)attr_value, NULL, 0); break; case MIXER_CTL_TYPE_BYTE: value = (unsigned char) strtol((char *)attr_value, NULL, 16); @@ -488,6 +525,8 @@ static void start_tag(void *data, const XML_Char *tag_name, if (id < ar->mixer_state[ctl_index].num_values) if (type == MIXER_CTL_TYPE_BYTE) ar->mixer_state[ctl_index].new_value.bytes[id] = value; + else if (type == MIXER_CTL_TYPE_ENUM) + ar->mixer_state[ctl_index].new_value.enumerated[id] = value; else ar->mixer_state[ctl_index].new_value.integer[id] = value; else @@ -498,6 +537,8 @@ static void start_tag(void *data, const XML_Char *tag_name, for (i = 0; i < ar->mixer_state[ctl_index].num_values; i++) if (type == MIXER_CTL_TYPE_BYTE) ar->mixer_state[ctl_index].new_value.bytes[i] = value; + else if (type == MIXER_CTL_TYPE_ENUM) + ar->mixer_state[ctl_index].new_value.enumerated[i] = value; else ar->mixer_state[ctl_index].new_value.integer[i] = value; } @@ -529,14 +570,12 @@ static void end_tag(void *data, const XML_Char *tag_name) static int alloc_mixer_state(struct audio_route *ar) { unsigned int i; - unsigned int j; unsigned int num_values; - unsigned int value_sz; struct mixer_ctl *ctl; enum mixer_ctl_type type; ar->num_mixer_ctls = mixer_get_num_ctls(ar->mixer); - ar->mixer_state = malloc(ar->num_mixer_ctls * sizeof(struct mixer_state)); + ar->mixer_state = calloc(ar->num_mixer_ctls, sizeof(struct mixer_state)); if (!ar->mixer_state) return -1; @@ -553,17 +592,13 @@ static int alloc_mixer_state(struct audio_route *ar) if (!is_supported_ctl_type(type)) continue; - if (type == MIXER_CTL_TYPE_BYTE) - value_sz = sizeof(unsigned char); - else - value_sz = sizeof(int); - - ar->mixer_state[i].old_value.ptr = malloc(num_values * value_sz); - ar->mixer_state[i].new_value.ptr = malloc(num_values * value_sz); - ar->mixer_state[i].reset_value.ptr = malloc(num_values * value_sz); + size_t value_sz = sizeof_ctl_type(type); + ar->mixer_state[i].old_value.ptr = calloc(num_values, value_sz); + ar->mixer_state[i].new_value.ptr = calloc(num_values, value_sz); + ar->mixer_state[i].reset_value.ptr = calloc(num_values, value_sz); if (type == MIXER_CTL_TYPE_ENUM) - ar->mixer_state[i].old_value.integer[0] = mixer_ctl_get_value(ctl, 0); + ar->mixer_state[i].old_value.enumerated[0] = mixer_ctl_get_value(ctl, 0); else mixer_ctl_get_array(ctl, ar->mixer_state[i].old_value.ptr, num_values); @@ -620,6 +655,14 @@ int audio_route_update_mixer(struct audio_route *ar) break; } } + } else if (type == MIXER_CTL_TYPE_ENUM) { + for (j = 0; j < num_values; j++) { + if (ar->mixer_state[i].old_value.enumerated[j] + != ar->mixer_state[i].new_value.enumerated[j]) { + changed = true; + break; + } + } } else { for (j = 0; j < num_values; j++) { if (ar->mixer_state[i].old_value.integer[j] != ar->mixer_state[i].new_value.integer[j]) { @@ -629,16 +672,12 @@ int audio_route_update_mixer(struct audio_route *ar) } } if (changed) { - unsigned int value_sz = sizeof(int); - - if (type == MIXER_CTL_TYPE_BYTE) - value_sz = sizeof(unsigned char); - if (type == MIXER_CTL_TYPE_ENUM) - mixer_ctl_set_value(ctl, 0, ar->mixer_state[i].new_value.integer[0]); + mixer_ctl_set_value(ctl, 0, ar->mixer_state[i].new_value.enumerated[0]); else mixer_ctl_set_array(ctl, ar->mixer_state[i].new_value.ptr, num_values); + size_t value_sz = sizeof_ctl_type(type); memcpy(ar->mixer_state[i].old_value.ptr, ar->mixer_state[i].new_value.ptr, num_values * value_sz); } @@ -651,7 +690,6 @@ int audio_route_update_mixer(struct audio_route *ar) static void save_mixer_state(struct audio_route *ar) { unsigned int i; - unsigned int value_sz; enum mixer_ctl_type type; for (i = 0; i < ar->num_mixer_ctls; i++) { @@ -659,11 +697,7 @@ static void save_mixer_state(struct audio_route *ar) if (!is_supported_ctl_type(type)) continue; - if (type == MIXER_CTL_TYPE_BYTE) - value_sz = sizeof(unsigned char); - else - value_sz = sizeof(int); - + size_t value_sz = sizeof_ctl_type(type); memcpy(ar->mixer_state[i].reset_value.ptr, ar->mixer_state[i].new_value.ptr, ar->mixer_state[i].num_values * value_sz); } @@ -673,7 +707,6 @@ static void save_mixer_state(struct audio_route *ar) void audio_route_reset(struct audio_route *ar) { unsigned int i; - unsigned int value_sz; enum mixer_ctl_type type; /* load all of the saved values */ @@ -682,11 +715,7 @@ void audio_route_reset(struct audio_route *ar) if (!is_supported_ctl_type(type)) continue; - if (type == MIXER_CTL_TYPE_BYTE) - value_sz = sizeof(unsigned char); - else - value_sz = sizeof(int); - + size_t value_sz = sizeof_ctl_type(type); memcpy(ar->mixer_state[i].new_value.ptr, ar->mixer_state[i].reset_value.ptr, ar->mixer_state[i].num_values * value_sz); } @@ -771,21 +800,25 @@ static int audio_route_update_path(struct audio_route *ar, const char *name, boo continue; } + size_t value_sz = sizeof_ctl_type(type); /* if any value has changed, update the mixer */ for (j = 0; j < ms->num_values; j++) { if (type == MIXER_CTL_TYPE_BYTE) { if (ms->old_value.bytes[j] != ms->new_value.bytes[j]) { mixer_ctl_set_array(ms->ctl, ms->new_value.bytes, ms->num_values); - memcpy(ms->old_value.bytes, ms->new_value.bytes, ms->num_values); + memcpy(ms->old_value.bytes, ms->new_value.bytes, ms->num_values * value_sz); break; } - } - else if (ms->old_value.integer[j] != ms->new_value.integer[j]) { - if (type == MIXER_CTL_TYPE_ENUM) - mixer_ctl_set_value(ms->ctl, 0, ms->new_value.integer[0]); - else - mixer_ctl_set_array(ms->ctl, ms->new_value.integer, ms->num_values); - memcpy(ms->old_value.integer, ms->new_value.integer, ms->num_values * sizeof(int)); + } else if (type == MIXER_CTL_TYPE_ENUM) { + if (ms->old_value.enumerated[j] != ms->new_value.enumerated[j]) { + mixer_ctl_set_value(ms->ctl, 0, ms->new_value.enumerated[0]); + memcpy(ms->old_value.enumerated, ms->new_value.enumerated, + ms->num_values * value_sz); + break; + } + } else if (ms->old_value.integer[j] != ms->new_value.integer[j]) { + mixer_ctl_set_array(ms->ctl, ms->new_value.integer, ms->num_values); + memcpy(ms->old_value.integer, ms->new_value.integer, ms->num_values * value_sz); break; } } @@ -818,7 +851,6 @@ struct audio_route *audio_route_init(unsigned int card, const char *xml_path) FILE *file; int bytes_read; void *buf; - int i; struct audio_route *ar; ar = calloc(1, sizeof(struct audio_route)); @@ -890,6 +922,7 @@ struct audio_route *audio_route_init(unsigned int card, const char *xml_path) return ar; err_parse: + path_free(ar); XML_ParserFree(parser); err_parser_create: fclose(file); @@ -908,5 +941,6 @@ void audio_route_free(struct audio_route *ar) { free_mixer_state(ar); mixer_close(ar->mixer); + path_free(ar); free(ar); }