示例#1
0
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");
        }
    }
}
int list(int argc, char **argv) {
    int nMixer = -1;

    if (argc == 3)
        nMixer = atoi(argv[2]);

    if (argc != 3 || nMixer < 0 || nMixer > 7) {
        printf("Usage: ainfo list <card number>\n"
               "where <card number> is between 0 and 7\n");
        return 0;
    }

    mixer *m = mixer_open(nMixer);

    if (m == NULL) {
        printf("Unable to open card #%d\n", nMixer);
        return 0;
    }

    int count = mixer_get_num_ctls(m);
    printf("Found %d controls:\n", count);

    for (int i = 0; i < count; i++) {
        char name[64], type[64];
        mixer_ctl *ctl = mixer_get_ctl(m, i);
        mixer_ctl_get_name(ctl, name, sizeof(name));
        printf("%d: %s (0x%x)\n", i, name, mixer_ctl_get_type(ctl));
    }

    return 0;
}
示例#3
0
int mixer_cache_apply(struct audio_tool_mixer_cache *cache, struct mixer *mixer)
{
    struct audio_tool_mixer_control_info *cur;
    struct mixer_ctl *ctl;
    int n, k, ret=0;

    for (n = 0 ; n < cache->count ; ++n) {
        cur = &cache->ctrls[n];
        ctl = mixer_get_ctl(mixer, n);
        for (k = 0 ; k < cur->num_values ; ++k) {
            switch (cur->type) {
            case MIXER_CTL_TYPE_BOOL:
            case MIXER_CTL_TYPE_INT:
                mixer_ctl_set_value(ctl, k, cur->value.integer[k]);
                break;
            case MIXER_CTL_TYPE_ENUM:
                mixer_ctl_set_enum_by_string(ctl, cur->value.enumerated[k]);
                break;
            case MIXER_CTL_TYPE_BYTE:
                mixer_ctl_set_value(ctl, k, cur->value.byte[k]);
                break;
            case MIXER_CTL_TYPE_INT64:
                mixer_ctl_set_value(ctl, k, cur->value.integer64[k]);
                break;
            default:
                ret = 1;
            }
        }
    }

    return ret;
}
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");
        }
    }
}
示例#5
0
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");
    }
}
示例#6
0
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");
}
示例#8
0
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");
}
示例#9
0
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_enum(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 */
            type = mixer_ctl_get_type(ctl);
            if (type == MIXER_CTL_TYPE_ENUM) {
                if (mixer_ctl_set_enum_by_string(ctl, string)) {
                    ALOGE("Error: invalid enum value");
                    ret = -1;
                } else {
                    ALOGV("Setting %s to string %s", name, string);
                }
            } else {
                ALOGV("Error: only enum types can be set with strings");
                ret = -1;
            }
            break;
        }
    }

    mixer_close(control_mixer);
    return ret;
}
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 int alloc_mixer_state(struct audio_route *ar)
{
    unsigned int i;

    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);
        /* only get value 0, assume multiple ctl values are the same */
        ar->mixer_state[i].old_value = mixer_ctl_get_value(ar->mixer_state[i].ctl, 0);
        ar->mixer_state[i].new_value = ar->mixer_state[i].old_value;
    }

    return 0;
}
示例#13
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;
		}
	}
}
示例#14
0
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);
}
int write_percentage(int argc, char **argv) {
    int nMixer = -1, nControl = -1;
    int location = -1, value = -1;

    if (argc == 6) {
        nMixer = atoi(argv[2]);
        nControl = atoi(argv[3]);
        location = atoi(argv[4]);
        value = atoi(argv[5]);
    }

    if (argc != 6 || nMixer < 0 || nMixer > 7 || nControl < 0 || location < 0) {
        printf("Usage: ainfo write-percentage <card number> <control number> <location> <value>\n"
               "where <card number> is between 0 and 7\n"
               "<control number> is the control to be written\n"
               "<location> is the location to be written\n"
               "<value> is the value to be written\n");
        return 0;
    }

    mixer *m = mixer_open(nMixer);

    if (m == NULL) {
        printf("Unable to open card #%d\n", nMixer);
        return 0;
    }

    mixer_ctl *c = mixer_get_ctl(m, nControl);

    if (c == NULL) {
        printf("Unable to open control #%d\n", nControl);
        return 0;        
    }

    char name[64], type[64];
    mixer_ctl_get_name(c, name, sizeof(name));
    mixer_ctl_set_percent(c, location, value);
    printf("Control: %s\nPercent: %d\nValue: %d\n", name, 
        mixer_ctl_get_percent(c, location), mixer_ctl_get_value(c, location));

    return 0;
}
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;
}
示例#17
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);
    }
}
int read_range(int argc, char **argv) {
    int nMixer = -1, nControl = -1;
    int location = -1;

    if (argc == 4) {
        nMixer = atoi(argv[2]);
        nControl = atoi(argv[3]);
    }

    if (argc != 4 || nMixer < 0 || nMixer > 7 || nControl < 0) {
        printf("Usage: ainfo read-range <card number> <control number> <location>\n"
               "where <card number> is between 0 and 7\n"
               "<control number> is the control to be read\n");
        return 0;
    }

    mixer *m = mixer_open(nMixer);

    if (m == NULL) {
        printf("Unable to open card #%d\n", nMixer);
        return 0;
    }

    mixer_ctl *c = mixer_get_ctl(m, nControl);

    if (c == NULL) {
        printf("Unable to open control #%d\n", nControl);
        return 0;        
    }

    char name[64], type[64];
    mixer_ctl_get_name(c, name, sizeof(name));
    printf("Control: %s\nMin: %d\nMax: %d\n", name, 
        mixer_ctl_get_range_min(c),  mixer_ctl_get_range_max(c));

    return 0;
}
示例#19
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");
}
示例#20
0
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;
}
示例#21
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");
}
bool TinyAmixerControl::accessHW(bool receive, std::string &error)
{
    CAutoLog autoLog(getConfigurableElement(), "ALSA", isDebugEnabled());

    // Mixer handle
    struct mixer *mixer;
    // Mixer control handle
    struct mixer_ctl *mixerControl;
    uint32_t elementCount;
    std::string controlName = getControlName();

    // Debug conditionnaly enabled in XML
    logControlInfo(receive);

    // Check parameter type is ok (deferred error, no exceptions available :-()
    if (!isTypeSupported()) {

        error = "Parameter type not supported.";
        return false;
    }

    // Check card number
    int32_t cardIndex = getCardNumber();
    if (cardIndex < 0) {

        error = "Card " + getCardName() + " not found. Error: " + strerror(-cardIndex);
        return false;
    }

    // Open alsa mixer
    // getMixerHandle is non-const; we need to forcefully remove the constness
    // then, we need to cast the generic subsystem into a TinyAlsaSubsystem.
    mixer = static_cast<TinyAlsaSubsystem *>(
        const_cast<CSubsystem *>(getSubsystem()))->getMixerHandle(cardIndex);

    if (!mixer) {

        error = "Failed to open mixer for card: " + getCardName();
        return false;
    }

    // Get control handle
    if (isdigit(controlName[0])) {

        mixerControl = mixer_get_ctl(mixer, asInteger(controlName));
    } else {

        mixerControl = mixer_get_ctl_by_name(mixer, controlName.c_str());
    }

    // Check control has been found
    if (!mixerControl) {
        error = "Failed to open mixer control: " + controlName;

        return false;
    }

    // Get element count
    elementCount = getNumValues(mixerControl);

    uint32_t scalarSize = getScalarSize();

    // Check available size
    if (elementCount * scalarSize != getSize()) {

        error = "ALSA: Control element count (" + asString(elementCount) +
                ") and configurable scalar element count (" +
                asString(getSize() / scalarSize) + ") mismatch";

        return false;
    }

    // Read/Write element
    bool success;
    if (receive) {

        success = readControl(mixerControl, elementCount, error);

    } else {

        success = writeControl(mixerControl, elementCount, error);

    }

    return success;
}
示例#23
0
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);
}
示例#24
0
/* 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);
}