static void tinymix_set_value(struct mixer *mixer, char *name, char *value) { struct mixer_ctl *ctl; enum mixer_ctl_type type; unsigned int i, num_values; ctl = mixer_get_ctl_by_name(mixer, name); if(!ctl) { log_err("cannot find control \'%s\'", name); return; } type = mixer_ctl_get_type(ctl); num_values = mixer_ctl_get_num_values(ctl); if(isdigit(value[0])) { int val = atoi(value); for(i = 0; i < num_values; i++) { if(mixer_ctl_set_value(ctl, i, val)) { log_err("value %d not accepted for %s", val, name); return; } } } else if(type == MIXER_CTL_TYPE_ENUM) { if(mixer_ctl_set_enum_by_string(ctl, value)) log_err("value %s not accepted for %s", value, name); } else if(type == MIXER_CTL_TYPE_BOOL) { if(strcasecmp(value,"on") == 0) i = 1; else if(strcasecmp(value, "off") == 0) i = 0; else { log_err("cannot set %s to \'%s\', on/off or 1/0 expected", name, value); return; } if(mixer_ctl_set_value(ctl, 0, i)) log_err("value %d not accepted for %s", i, name); } else log_err("type mismatch for %s, ignored", name); }
static void tinymix_set_value(struct mixer *mixer, unsigned int id, char *string) { struct mixer_ctl *ctl; enum mixer_ctl_type type; unsigned int num_values; unsigned int i; ctl = mixer_get_ctl(mixer, id); type = mixer_ctl_get_type(ctl); num_values = mixer_ctl_get_num_values(ctl); if (isdigit(string[0])) { int value = atoi(string); for (i = 0; i < num_values; i++) { if (mixer_ctl_set_value(ctl, i, value)) { fprintf(stderr, "Error: invalid value\n"); return; } } } else { if (type == MIXER_CTL_TYPE_ENUM) { if (mixer_ctl_set_enum_by_string(ctl, string)) fprintf(stderr, "Error: invalid enum value\n"); } else { fprintf(stderr, "Error: only enum types can be set with strings\n"); } } }
static void tinymix_set_value(struct mixer *mixer, const char *control, char **values, unsigned int num_values) { struct mixer_ctl *ctl; enum mixer_ctl_type type; unsigned int num_ctl_values; unsigned int i; if (isdigit(control[0])) ctl = mixer_get_ctl(mixer, atoi(control)); else ctl = mixer_get_ctl_by_name(mixer, control); if (!ctl) { fprintf(stderr, "Invalid mixer control\n"); return; } type = mixer_ctl_get_type(ctl); num_ctl_values = mixer_ctl_get_num_values(ctl); if (isdigit(values[0][0])) { if (num_values == 1) { /* Set all values the same */ int value = atoi(values[0]); for (i = 0; i < num_ctl_values; i++) { if (mixer_ctl_set_value(ctl, i, value)) { fprintf(stderr, "Error: invalid value\n"); return; } } } else { /* Set multiple values */ if (num_values > num_ctl_values) { fprintf(stderr, "Error: %d values given, but control only takes %d\n", num_values, num_ctl_values); return; } for (i = 0; i < num_values; i++) { if (mixer_ctl_set_value(ctl, i, atoi(values[i]))) { fprintf(stderr, "Error: invalid value for index %d\n", i); return; } } } } else { if (type == MIXER_CTL_TYPE_ENUM) { if (num_values != 1) { fprintf(stderr, "Enclose strings in quotes and try again\n"); return; } if (mixer_ctl_set_enum_by_string(ctl, values[0])) fprintf(stderr, "Error: invalid enum value\n"); } else { fprintf(stderr, "Error: only enum types can be set with strings\n"); } } }
static void tinymix_list_controls(struct mixer *mixer, int print_all) { struct mixer_ctl *ctl; const char *name, *type; unsigned int num_ctls, num_values; unsigned int i; num_ctls = mixer_get_num_ctls(mixer); printf("Number of controls: %u\n", num_ctls); if (print_all) printf("ctl\ttype\tnum\t%-40svalue\n", "name"); else printf("ctl\ttype\tnum\t%-40s\n", "name"); for (i = 0; i < num_ctls; i++) { ctl = mixer_get_ctl(mixer, i); name = mixer_ctl_get_name(ctl); type = mixer_ctl_get_type_string(ctl); num_values = mixer_ctl_get_num_values(ctl); printf("%u\t%s\t%u\t%-40s", i, type, num_values, name); if (print_all) tinymix_detail_control(mixer, name); printf("\n"); } }
static int alloc_mixer_state(struct audio_route *ar) { unsigned int i; unsigned int j; if (!ar) { ALOGE("%s: invalid audio_route", __func__); return -1; } ar->num_mixer_ctls = mixer_get_num_ctls(ar->mixer); ar->mixer_state = malloc(ar->num_mixer_ctls * sizeof(struct mixer_state)); if (!ar->mixer_state) return -1; for (i = 0; i < ar->num_mixer_ctls; i++) { ar->mixer_state[i].ctl = mixer_get_ctl(ar->mixer, i); ar->mixer_state[i].ctl_vals = mixer_ctl_get_num_values(ar->mixer_state[i].ctl); ar->mixer_state[i].ignored = 0; if (ar->mixer_state[i].ctl_vals > MAX_CTL_VALS) { ar->mixer_state[i].ctl_vals = MAX_CTL_VALS; } for (j = 0; j < ar->mixer_state[i].ctl_vals; j++) { ar->mixer_state[i].old_value[j] = mixer_ctl_get_value(ar->mixer_state[i].ctl, j); ar->mixer_state[i].new_value[j] = ar->mixer_state[i].old_value[j]; } } return 0; }
static void tinymix_detail_control(struct mixer *mixer, const char *control, int print_all) { struct mixer_ctl *ctl; enum mixer_ctl_type type; unsigned int num_values; unsigned int i; int min, max; if (isdigit(control[0])) ctl = mixer_get_ctl(mixer, atoi(control)); else ctl = mixer_get_ctl_by_name(mixer, control); if (!ctl) { fprintf(stderr, "Invalid mixer control\n"); return; } type = mixer_ctl_get_type(ctl); num_values = mixer_ctl_get_num_values(ctl); if (print_all) printf("%s:", mixer_ctl_get_name(ctl)); for (i = 0; i < num_values; i++) { switch (type) { case MIXER_CTL_TYPE_INT: printf(" %d", mixer_ctl_get_value(ctl, i)); break; case MIXER_CTL_TYPE_BOOL: printf(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off"); break; case MIXER_CTL_TYPE_ENUM: tinymix_print_enum(ctl, print_all); break; case MIXER_CTL_TYPE_BYTE: printf(" 0x%02x", mixer_ctl_get_value(ctl, i)); break; default: printf(" unknown"); break; }; } if (print_all) { if (type == MIXER_CTL_TYPE_INT) { min = mixer_ctl_get_range_min(ctl); max = mixer_ctl_get_range_max(ctl); printf(" (range %d->%d)", min, max); } } printf("\n"); }
static void tinymix_detail_control(struct mixer *mixer, unsigned int id, int print_all) { struct mixer_ctl *ctl; enum mixer_ctl_type type; unsigned int num_values; char buffer[256]; unsigned int i; int min, max; if (id >= mixer_get_num_ctls(mixer)) { fprintf(stderr, "Invalid mixer control\n"); return; } ctl = mixer_get_ctl(mixer, id); mixer_ctl_get_name(ctl, buffer, sizeof(buffer)); type = mixer_ctl_get_type(ctl); num_values = mixer_ctl_get_num_values(ctl); if (print_all) printf("%s:", buffer); for (i = 0; i < num_values; i++) { switch (type) { case MIXER_CTL_TYPE_INT: printf(" %d", mixer_ctl_get_value(ctl, i)); break; case MIXER_CTL_TYPE_BOOL: printf(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off"); break; case MIXER_CTL_TYPE_ENUM: tinymix_print_enum(ctl, print_all); break; case MIXER_CTL_TYPE_BYTE: printf(" 0x%02x", mixer_ctl_get_value(ctl, i)); break; default: printf(" unknown"); break; }; } if (print_all) { if (type == MIXER_CTL_TYPE_INT) { min = mixer_ctl_get_range_min(ctl); max = mixer_ctl_get_range_max(ctl); printf(" (range %d->%d)", min, max); } } printf("\n"); }
static bool setMixerValue(struct mixer* mixer, const char* name, const char* values) { if (!mixer) { ALOGE("no mixer in setMixerValue"); return false; } struct mixer_ctl *ctl = mixer_get_ctl_by_name(mixer, name); if (!ctl) { ALOGE("mixer_get_ctl_by_name failed for %s", name); return false; } enum mixer_ctl_type type = mixer_ctl_get_type(ctl); int numValues = mixer_ctl_get_num_values(ctl); int intValue; char stringValue[MAX_LINE_LENGTH]; for (int i = 0; i < numValues && values; i++) { // strip leading space while (*values == ' ') values++; if (*values == 0) break; switch (type) { case MIXER_CTL_TYPE_BOOL: case MIXER_CTL_TYPE_INT: if (sscanf(values, "%d", &intValue) == 1) { if (mixer_ctl_set_value(ctl, i, intValue) != 0) { ALOGE("mixer_ctl_set_value failed for %s %d", name, intValue); } } else { ALOGE("Could not parse %s as int for %s", values, name); } break; case MIXER_CTL_TYPE_ENUM: if (sscanf(values, "%s", stringValue) == 1) { if (mixer_ctl_set_enum_by_string(ctl, stringValue) != 0) { ALOGE("mixer_ctl_set_enum_by_string failed for %s %s", name, stringValue); } } else { ALOGE("Could not parse %s as enum for %s", values, name); } break; default: ALOGE("unsupported mixer type %d for %s", type, name); break; } values = strchr(values, ' '); } return true; }
static int path_add_value(struct mixer_path *path, struct mixer_value *mixer_value) { unsigned int i; int path_index; unsigned int num_values; /* Check that mixer value index is within range */ num_values = mixer_ctl_get_num_values(mixer_value->ctl); if (mixer_value->index >= (int)num_values) { ALOGE("mixer index %d is out of range for '%s'", mixer_value->index, mixer_ctl_get_name(mixer_value->ctl)); return -1; } path_index = find_ctl_in_path(path, mixer_value->ctl); if (path_index < 0) { /* New path */ path_index = alloc_path_setting(path); if (path_index < 0) return -1; /* initialise the new path setting */ path->setting[path_index].ctl = mixer_value->ctl; path->setting[path_index].num_values = num_values; path->setting[path_index].value = malloc(num_values * sizeof(int)); path->setting[path_index].linked = true; path->setting[path_index].value[0] = mixer_value->value; } if (mixer_value->index == -1) { /* Linked, so only set the first value */ path->setting[path_index].linked = true; path->setting[path_index].value[0] = mixer_value->value; } else { if (path->setting[path_index].linked && (num_values > 1)) { /* Unlinking the values, so duplicate them across */ for (i = 1; i < num_values; i++) { path->setting[path_index].value[i] = path->setting[path_index].value[0]; } path->setting[path_index].linked = false; } path->setting[path_index].value[mixer_value->index] = mixer_value->value; } return 0; }
void update_mixer_state(struct audio_route *ar) { unsigned int i; unsigned int j; for (i = 0; i < ar->num_mixer_ctls; i++) { /* if the value has changed, update the mixer */ if (ar->mixer_state[i].old_value != ar->mixer_state[i].new_value) { /* set all ctl values the same */ for (j = 0; j < mixer_ctl_get_num_values(ar->mixer_state[i].ctl); j++) mixer_ctl_set_value(ar->mixer_state[i].ctl, j, ar->mixer_state[i].new_value); ar->mixer_state[i].old_value = ar->mixer_state[i].new_value; } } }
static int alloc_mixer_state(struct audio_route *ar) { unsigned int i; unsigned int j; unsigned int num_values; struct mixer_ctl *ctl; bool linked; ar->num_mixer_ctls = mixer_get_num_ctls(ar->mixer); ar->mixer_state = malloc(ar->num_mixer_ctls * sizeof(struct mixer_state)); if (!ar->mixer_state) return -1; for (i = 0; i < ar->num_mixer_ctls; i++) { ctl = mixer_get_ctl(ar->mixer, i); num_values = mixer_ctl_get_num_values(ctl); ar->mixer_state[i].old_value = malloc(num_values * sizeof(int)); ar->mixer_state[i].new_value = malloc(num_values * sizeof(int)); ar->mixer_state[i].reset_value = malloc(num_values * sizeof(int)); /* * Get all mixer values for controls with multiple values. If all * values are the same, set the linked flag. */ linked = true; for (j = 0; j < num_values; j++) { ar->mixer_state[i].old_value[j] = mixer_ctl_get_value(ctl, j); ar->mixer_state[i].new_value[j] = ar->mixer_state[i].old_value[j]; /* * If the next value is different from the last, set linked to * false. */ if ((j > 0) && (ar->mixer_state[i].old_value[j - 1] != ar->mixer_state[i].old_value[j])) { linked = false; } } ar->mixer_state[i].ctl = ctl; ar->mixer_state[i].old_linked = linked; ar->mixer_state[i].new_linked = linked; ar->mixer_state[i].num_values = num_values; } return 0; }
int audio_route_control_set_number(unsigned int card_slot, char *control_name, char *string) { struct mixer *control_mixer; struct mixer_ctl *ctl; const char *name; unsigned int num_ctls, num_values; unsigned int i, j; enum mixer_ctl_type type; int value; int ret, mixer_ret; control_mixer = mixer_open(card_slot); if (!control_mixer) { ALOGE("Unable to open the control mixer, aborting."); return -1; } ALOGV("Control mixer open successful."); num_ctls = mixer_get_num_ctls(control_mixer); ret = 0; for (i = 0; i < num_ctls; i++) { ctl = mixer_get_ctl(control_mixer, i); name = mixer_ctl_get_name(ctl); if (name && strcmp(name, control_name) == 0) { /* Found the control, update and exit */ value = atoi(string); num_values = mixer_ctl_get_num_values(ctl); for (j = 0; j < num_values; j++) { mixer_ret = mixer_ctl_set_value(ctl, j, value); if (mixer_ret) { ALOGE("Error: invalid value (%s to %d)", name, value); mixer_close(control_mixer); /* Add up the number of failed controller values */ ret += -1; } } if (ret == 0) ALOGV("Setting %s to int %d", name, value); break; } } return ret; }
static bool do_set_volume(struct mixer *mixer, const char *name, unsigned volume) { struct mixer_ctl *ctl; unsigned i; ctl = mixer_get_ctl_by_name(mixer, name); if (! ctl) { fprintf(stderr, "Failed to find control: %s\n", name); mixer_close(mixer); return false; } for (i = 0; i < mixer_ctl_get_num_values(ctl); i++) { mixer_ctl_set_percent(ctl, i, volume); } return true; }
static int path_add_value(struct audio_route *ar, struct mixer_path *path, struct mixer_value *mixer_value) { unsigned int i; int path_index; unsigned int num_values; struct mixer_ctl *ctl; /* Check that mixer value index is within range */ ctl = index_to_ctl(ar, mixer_value->ctl_index); num_values = mixer_ctl_get_num_values(ctl); if (mixer_value->index >= (int)num_values) { ALOGE("mixer index %d is out of range for '%s'", mixer_value->index, mixer_ctl_get_name(ctl)); return -1; } path_index = find_ctl_index_in_path(path, mixer_value->ctl_index); if (path_index < 0) { /* New path */ path_index = alloc_path_setting(path); if (path_index < 0) return -1; /* 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].value = malloc(num_values * sizeof(int)); path->setting[path_index].value[0] = mixer_value->value; } if (mixer_value->index == -1) { /* set all values the same */ for (i = 0; i < num_values; i++) path->setting[path_index].value[i] = mixer_value->value; } else { /* set only one value */ path->setting[path_index].value[mixer_value->index] = mixer_value->value; } return 0; }
static void tinymix_set_value(struct mixer *mixer, unsigned int id, unsigned int value) { struct mixer_ctl *ctl; enum mixer_ctl_type type; unsigned int num_values; unsigned int i; ctl = mixer_get_ctl(mixer, id); type = mixer_ctl_get_type(ctl); num_values = mixer_ctl_get_num_values(ctl); for (i = 0; i < num_values; i++) { if (mixer_ctl_set_value(ctl, i, value)) { fprintf(stderr, "Error: invalid value\n"); return; } } }
TEST_F(MixerTest, tryTinyAlsaTest) { int hwId = AudioHardware::detectAudioHw(); ASSERT_TRUE(hwId >= 0); struct mixer* mixerp = mixer_open(hwId); ASSERT_TRUE(mixerp != NULL); int num_ctls = mixer_get_num_ctls(mixerp); LOGI("Number of mixel control %d", num_ctls); for (int i = 0; i < num_ctls; i++) { struct mixer_ctl* control = mixer_get_ctl(mixerp, i); ASSERT_TRUE(control != NULL); LOGI("Mixer control %s type %s value %d", mixer_ctl_get_name(control), mixer_ctl_get_type_string(control), mixer_ctl_get_num_values(control)); free(control); } // no mixer control for MobilePre. If this assumption fails, // mixer control should be added. ASSERT_TRUE(num_ctls == 0); mixer_close(mixerp); }
static int alloc_mixer_state(struct audio_route *ar) { unsigned int i; unsigned int j; unsigned int num_values; 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)); if (!ar->mixer_state) return -1; for (i = 0; i < ar->num_mixer_ctls; i++) { ctl = mixer_get_ctl(ar->mixer, i); num_values = mixer_ctl_get_num_values(ctl); ar->mixer_state[i].ctl = ctl; ar->mixer_state[i].num_values = num_values; /* Skip unsupported types that are not supported yet in XML */ type = mixer_ctl_get_type(ctl); if ((type != MIXER_CTL_TYPE_BOOL) && (type != MIXER_CTL_TYPE_INT) && (type != MIXER_CTL_TYPE_ENUM)) continue; ar->mixer_state[i].old_value = malloc(num_values * sizeof(int)); ar->mixer_state[i].new_value = malloc(num_values * sizeof(int)); ar->mixer_state[i].reset_value = malloc(num_values * sizeof(int)); if (type == MIXER_CTL_TYPE_ENUM) ar->mixer_state[i].old_value[0] = mixer_ctl_get_value(ctl, 0); else mixer_ctl_get_array(ctl, ar->mixer_state[i].old_value, num_values); memcpy(ar->mixer_state[i].new_value, ar->mixer_state[i].old_value, num_values * sizeof(int)); } return 0; }
static void tinymix_list_controls(struct mixer *mixer) { struct mixer_ctl *ctl; const char *type; unsigned int num_ctls, num_values; char buffer[256]; unsigned int i; num_ctls = mixer_get_num_ctls(mixer); printf("Number of controls: %d\n", num_ctls); printf("ctl\ttype\tnum\t%-40s value\n", "name"); for (i = 0; i < num_ctls; i++) { ctl = mixer_get_ctl(mixer, i); mixer_ctl_get_name(ctl, buffer, sizeof(buffer)); type = mixer_ctl_get_type_string(ctl); num_values = mixer_ctl_get_num_values(ctl); printf("%d\t%s\t%d\t%-40s", i, type, num_values, buffer); tinymix_detail_control(mixer, i, 0); } }
static void tinymix_detail_control(struct mixer *mixer, const char *control, int print_all) { struct mixer_ctl *ctl; enum mixer_ctl_type type; unsigned int num_values; unsigned int i; int min, max; int ret; char buf[512] = { 0 }; size_t len; if (isdigit(control[0])) ctl = mixer_get_ctl(mixer, atoi(control)); else ctl = mixer_get_ctl_by_name(mixer, control); if (!ctl) { fprintf(stderr, "Invalid mixer control\n"); return; } type = mixer_ctl_get_type(ctl); num_values = mixer_ctl_get_num_values(ctl); if (type == MIXER_CTL_TYPE_BYTE) { len = num_values; if (len > sizeof(buf)) { fprintf(stderr, "Truncating get to %zu bytes\n", sizeof(buf)); len = sizeof(buf); } ret = mixer_ctl_get_array(ctl, buf, len); if (ret < 0) { fprintf(stderr, "Failed to mixer_ctl_get_array\n"); return; } } if (print_all) printf("%s:", mixer_ctl_get_name(ctl)); for (i = 0; i < num_values; i++) { switch (type) { case MIXER_CTL_TYPE_INT: printf(" %d", mixer_ctl_get_value(ctl, i)); break; case MIXER_CTL_TYPE_BOOL: printf(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off"); break; case MIXER_CTL_TYPE_ENUM: tinymix_print_enum(ctl, print_all); break; case MIXER_CTL_TYPE_BYTE: printf("%02x", buf[i]); break; default: printf(" unknown"); break; }; } if (print_all) { if (type == MIXER_CTL_TYPE_INT) { min = mixer_ctl_get_range_min(ctl); max = mixer_ctl_get_range_max(ctl); printf(" (range %d->%d)", min, max); } } printf("\n"); }
int mixer_cache_populate(struct audio_tool_mixer_cache *cache, struct mixer *mixer) { struct mixer_ctl *ctl; struct audio_tool_mixer_control_info *cur; const char* name; size_t count, n, v; int tmp; if (!cache) return EINVAL; if (!mixer) return EINVAL; if (cache->ctrls) free(cache->ctrls); count = mixer_get_num_ctls(mixer); cache->count = count; if (count) { cache->ctrls = calloc(count, sizeof(struct audio_tool_mixer_control_info)); if (! cache->ctrls) return -ENOMEM; } for (n = 0, cur = cache->ctrls ; n < count ; ++n, ++cur) { ctl = mixer_get_ctl(mixer, n); if (!ctl) return ENODEV; name = mixer_ctl_get_name(ctl); if (!name) return ENODEV; cur->id = n; cur->type = mixer_ctl_get_type(ctl); strcpy(cur->name, name); cur->num_values = mixer_ctl_get_num_values(ctl); if (cur->num_values > MAX_NUM_VALUES) cur->num_values = MAX_NUM_VALUES; for (v = 0 ; v < cur->num_values ; ++v) { switch (cur->type) { case MIXER_CTL_TYPE_BOOL: case MIXER_CTL_TYPE_INT: cur->value.integer[v] = mixer_ctl_get_value(ctl, v); break; case MIXER_CTL_TYPE_ENUM: tmp = mixer_ctl_get_value(ctl, v); name = mixer_ctl_get_enum_string(ctl, tmp); // null value names were causing seg fault here if (name) strcpy(cur->value.enumerated[v], name); else printf("Skipping ENUM due to null setting for %s\n", cur->name); break; case MIXER_CTL_TYPE_BYTE: cur->value.byte[v] = mixer_ctl_get_value(ctl, v); break; case MIXER_CTL_TYPE_INT64: cur->value.integer64[v] = mixer_ctl_get_value(ctl, v); break; default: (void)0; } } } return 0; }
static void tinymix_detail_control(struct mixer *mixer, const char *control, int print_all) { struct mixer_ctl *ctl; enum mixer_ctl_type type; unsigned int num_values; unsigned int i; int min, max; int ret; char *buf = NULL; if (isdigit(control[0])) ctl = mixer_get_ctl(mixer, atoi(control)); else ctl = mixer_get_ctl_by_name(mixer, control); if (!ctl) { fprintf(stderr, "Invalid mixer control\n"); return; } type = mixer_ctl_get_type(ctl); num_values = mixer_ctl_get_num_values(ctl); if ((type == MIXER_CTL_TYPE_BYTE) && (num_values > 0)) { buf = calloc(1, num_values); if (buf == NULL) { fprintf(stderr, "Failed to alloc mem for bytes %d\n", num_values); return; } ret = mixer_ctl_get_array(ctl, buf, num_values); if (ret < 0) { fprintf(stderr, "Failed to mixer_ctl_get_array\n"); free(buf); return; } } if (print_all) printf("%s:", mixer_ctl_get_name(ctl)); for (i = 0; i < num_values; i++) { switch (type) { case MIXER_CTL_TYPE_INT: printf(" %d", mixer_ctl_get_value(ctl, i)); break; case MIXER_CTL_TYPE_BOOL: printf(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off"); break; case MIXER_CTL_TYPE_ENUM: tinymix_print_enum(ctl, print_all); break; case MIXER_CTL_TYPE_BYTE: printf("%02x", buf[i]); break; default: printf(" unknown"); break; }; } if (print_all) { if (type == MIXER_CTL_TYPE_INT) { min = mixer_ctl_get_range_min(ctl); max = mixer_ctl_get_range_max(ctl); printf(" (range %d->%d)", min, max); } } free(buf); printf("\n"); }
uint32_t TinyAmixerControl::getNumValues(struct mixer_ctl *mixerControl) { return mixer_ctl_get_num_values(mixerControl); }
static void tinymix_detail_control(struct mixer *mixer, const char *control) { struct mixer_ctl *ctl; enum mixer_ctl_type type; unsigned int num_values; unsigned int i; int min, max; int ret; char *buf = NULL; unsigned int tlv_header_size = 0; if (isdigit(control[0])) ctl = mixer_get_ctl(mixer, atoi(control)); else ctl = mixer_get_ctl_by_name(mixer, control); if (!ctl) { fprintf(stderr, "Invalid mixer control\n"); return; } type = mixer_ctl_get_type(ctl); num_values = mixer_ctl_get_num_values(ctl); if ((type == MIXER_CTL_TYPE_BYTE) && (num_values > 0)) { if (mixer_ctl_is_access_tlv_rw(ctl) != 0) { tlv_header_size = TLV_HEADER_SIZE; } buf = calloc(1, num_values + tlv_header_size); if (buf == NULL) { fprintf(stderr, "Failed to alloc mem for bytes %u\n", num_values); return; } ret = mixer_ctl_get_array(ctl, buf, num_values + tlv_header_size); if (ret < 0) { fprintf(stderr, "Failed to mixer_ctl_get_array\n"); free(buf); return; } } for (i = 0; i < num_values; i++) { switch (type) { case MIXER_CTL_TYPE_INT: printf("%d", mixer_ctl_get_value(ctl, i)); break; case MIXER_CTL_TYPE_BOOL: printf("%s", mixer_ctl_get_value(ctl, i) ? "On" : "Off"); break; case MIXER_CTL_TYPE_ENUM: tinymix_print_enum(ctl); break; case MIXER_CTL_TYPE_BYTE: /* skip printing TLV header if exists */ printf(" %02x", buf[i + tlv_header_size]); break; default: printf("unknown"); break; }; if ((i + 1) < num_values) { printf(", "); } } if (type == MIXER_CTL_TYPE_INT) { min = mixer_ctl_get_range_min(ctl); max = mixer_ctl_get_range_max(ctl); printf(" (range %d->%d)", min, max); } free(buf); }
/* Notes: * - param 'line' is modified by this function * - param 'db' has mixer_cache_touch() called on it. */ static void process_line(char* line, struct audio_tool_mixer_cache *db, struct mixer *mixer) { size_t length = strlen(line); size_t pos = 0, sep; const char* sep_ptr; enum field_t { FNAME=0, FTYPE, FCOUNT, FVALS } field = FNAME; unsigned control_id, val, val_no; const char *ctl_type; unsigned file_count, ctl_count; struct mixer_ctl *ctl; if (!length) return; if (line[0] == '#') return; control_id = -1; val_no = 0; while (pos < length) { sep_ptr = strstr(&line[pos], "\t"); if (sep_ptr) sep = (size_t) (sep_ptr - line); else sep = length; if (sep < length) line[sep] = '\0'; switch(field) { case FNAME: control_id = mixer_cache_get_id_by_name(db, &line[pos]); if (control_id == -1) { printf("Error: could not find control %s\n", &line[pos]); pos = length; } ctl = mixer_get_ctl(mixer, control_id); break; case FTYPE: ctl_type = mixer_ctl_get_type_string(ctl); if (0 != strcmp(ctl_type, &line[pos])) { printf("Error: type mismatch for control #%d: file=%s card=%s\n", control_id, &line[pos], ctl_type); pos = length; } break; case FCOUNT: ctl_count = mixer_ctl_get_num_values(ctl); file_count = atoi(&line[pos]); if (ctl_count != file_count) { printf("Error: mismatch in the count of control #%d's values: " "file=%d card=%d\n", control_id, file_count, ctl_count); pos = length; } break; case FVALS: if (0 == strcmp("#N/A", &line[pos])) { pos = length; } else if (0 == strcmp("ENUM", ctl_type)) { mixer_ctl_set_enum_by_string(ctl, &line[pos]); } else { val = atoi(&line[pos]); mixer_ctl_set_value(ctl, val_no, val); } ++val_no; break; } if (field != FVALS) ++field; pos = sep + 1; } mixer_cache_touch(db, control_id); }