Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/next/external/cache/sources/tinyalsa/tinymix.c
Views: 3959
/* tinymix.c1**2** Copyright 2011, The Android Open Source Project3**4** Redistribution and use in source and binary forms, with or without5** modification, are permitted provided that the following conditions are met:6** * Redistributions of source code must retain the above copyright7** notice, this list of conditions and the following disclaimer.8** * Redistributions in binary form must reproduce the above copyright9** notice, this list of conditions and the following disclaimer in the10** documentation and/or other materials provided with the distribution.11** * Neither the name of The Android Open Source Project nor the names of12** its contributors may be used to endorse or promote products derived13** from this software without specific prior written permission.14**15** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND16** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE19** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER22** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH25** DAMAGE.26*/2728#include <tinyalsa/asoundlib.h>29#include <errno.h>30#include <stdio.h>31#include <stdlib.h>32#include <ctype.h>33#include <string.h>34#include <limits.h>35#include <errno.h>3637static void tinymix_list_controls(struct mixer *mixer);38static void tinymix_detail_control(struct mixer *mixer, const char *control,39int print_all);40static void tinymix_set_value(struct mixer *mixer, const char *control,41char **values, unsigned int num_values);42static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all);4344int main(int argc, char **argv)45{46struct mixer *mixer;47int card = 0;4849if ((argc > 2) && (strcmp(argv[1], "-D") == 0)) {50argv++;51if (argv[1]) {52card = atoi(argv[1]);53argv++;54argc -= 2;55} else {56argc -= 1;57}58}5960mixer = mixer_open(card);61if (!mixer) {62fprintf(stderr, "Failed to open mixer\n");63return EXIT_FAILURE;64}656667if (argc == 1) {68printf("Mixer name: '%s'\n", mixer_get_name(mixer));69tinymix_list_controls(mixer);70} else if (argc == 2) {71tinymix_detail_control(mixer, argv[1], 1);72} else if (argc >= 3) {73tinymix_set_value(mixer, argv[1], &argv[2], argc - 2);74} else {75printf("Usage: tinymix [-D card] [control id] [value to set]\n");76}7778mixer_close(mixer);7980return 0;81}8283static void tinymix_list_controls(struct mixer *mixer)84{85struct mixer_ctl *ctl;86const char *name, *type;87unsigned int num_ctls, num_values;88unsigned int i;8990num_ctls = mixer_get_num_ctls(mixer);9192printf("Number of controls: %d\n", num_ctls);9394printf("ctl\ttype\tnum\t%-40s value\n", "name");95for (i = 0; i < num_ctls; i++) {96ctl = mixer_get_ctl(mixer, i);9798name = mixer_ctl_get_name(ctl);99type = mixer_ctl_get_type_string(ctl);100num_values = mixer_ctl_get_num_values(ctl);101printf("%d\t%s\t%d\t%-40s", i, type, num_values, name);102tinymix_detail_control(mixer, name, 0);103}104}105106static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all)107{108unsigned int num_enums;109unsigned int i;110const char *string;111112num_enums = mixer_ctl_get_num_enums(ctl);113114for (i = 0; i < num_enums; i++) {115string = mixer_ctl_get_enum_string(ctl, i);116if (print_all)117printf("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "",118string);119else if (mixer_ctl_get_value(ctl, 0) == (int)i)120printf(" %-s", string);121}122}123124static void tinymix_detail_control(struct mixer *mixer, const char *control,125int print_all)126{127struct mixer_ctl *ctl;128enum mixer_ctl_type type;129unsigned int num_values;130unsigned int i;131int min, max;132int ret;133char buf[512] = { 0 };134size_t len;135136if (isdigit(control[0]))137ctl = mixer_get_ctl(mixer, atoi(control));138else139ctl = mixer_get_ctl_by_name(mixer, control);140141if (!ctl) {142fprintf(stderr, "Invalid mixer control\n");143return;144}145146type = mixer_ctl_get_type(ctl);147num_values = mixer_ctl_get_num_values(ctl);148149if (type == MIXER_CTL_TYPE_BYTE) {150len = num_values;151if (len > sizeof(buf)) {152fprintf(stderr, "Truncating get to %zu bytes\n", sizeof(buf));153len = sizeof(buf);154}155ret = mixer_ctl_get_array(ctl, buf, len);156if (ret < 0) {157fprintf(stderr, "Failed to mixer_ctl_get_array\n");158return;159}160}161162if (print_all)163printf("%s:", mixer_ctl_get_name(ctl));164165for (i = 0; i < num_values; i++) {166switch (type)167{168case MIXER_CTL_TYPE_INT:169printf(" %d", mixer_ctl_get_value(ctl, i));170break;171case MIXER_CTL_TYPE_BOOL:172printf(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");173break;174case MIXER_CTL_TYPE_ENUM:175tinymix_print_enum(ctl, print_all);176break;177case MIXER_CTL_TYPE_BYTE:178printf("%02x", buf[i]);179break;180default:181printf(" unknown");182break;183};184}185186if (print_all) {187if (type == MIXER_CTL_TYPE_INT) {188min = mixer_ctl_get_range_min(ctl);189max = mixer_ctl_get_range_max(ctl);190printf(" (range %d->%d)", min, max);191}192}193printf("\n");194}195196static void tinymix_set_byte_ctl(struct mixer_ctl *ctl, const char *control,197char **values, unsigned int num_values)198{199int ret;200char buf[512] = { 0 };201char *end;202int i;203long n;204205if (num_values > sizeof(buf)) {206fprintf(stderr, "Truncating set to %zu bytes\n", sizeof(buf));207num_values = sizeof(buf);208}209210for (i = 0; i < num_values; i++) {211errno = 0;212n = strtol(values[i], &end, 0);213if (*end) {214fprintf(stderr, "%s not an integer\n", values[i]);215exit(EXIT_FAILURE);216}217if (errno) {218fprintf(stderr, "strtol: %s: %s\n", values[i],219strerror(errno));220exit(EXIT_FAILURE);221}222if (n < 0 || n > 0xff) {223fprintf(stderr, "%s should be between [0, 0xff]\n",224values[i]);225exit(EXIT_FAILURE);226}227buf[i] = n;228}229230ret = mixer_ctl_set_array(ctl, buf, num_values);231if (ret < 0) {232fprintf(stderr, "Failed to set binary control\n");233exit(EXIT_FAILURE);234}235}236237static int is_int(char *value)238{239char* end;240long int result;241242errno = 0;243result = strtol(value, &end, 10);244245if (result == LONG_MIN || result == LONG_MAX)246return 0;247248return errno == 0 && *end == '\0';249}250251static void tinymix_set_value(struct mixer *mixer, const char *control,252char **values, unsigned int num_values)253{254struct mixer_ctl *ctl;255enum mixer_ctl_type type;256unsigned int num_ctl_values;257unsigned int i;258259if (isdigit(control[0]))260ctl = mixer_get_ctl(mixer, atoi(control));261else262ctl = mixer_get_ctl_by_name(mixer, control);263264if (!ctl) {265fprintf(stderr, "Invalid mixer control\n");266return;267}268269type = mixer_ctl_get_type(ctl);270num_ctl_values = mixer_ctl_get_num_values(ctl);271272if (type == MIXER_CTL_TYPE_BYTE) {273tinymix_set_byte_ctl(ctl, control, values, num_values);274return;275}276277if (is_int(values[0])) {278if (num_values == 1) {279/* Set all values the same */280int value = atoi(values[0]);281282for (i = 0; i < num_ctl_values; i++) {283if (mixer_ctl_set_value(ctl, i, value)) {284fprintf(stderr, "Error: invalid value\n");285return;286}287}288} else {289/* Set multiple values */290if (num_values > num_ctl_values) {291fprintf(stderr,292"Error: %d values given, but control only takes %d\n",293num_values, num_ctl_values);294return;295}296for (i = 0; i < num_values; i++) {297if (mixer_ctl_set_value(ctl, i, atoi(values[i]))) {298fprintf(stderr, "Error: invalid value for index %d\n", i);299return;300}301}302}303} else {304if (type == MIXER_CTL_TYPE_ENUM) {305if (num_values != 1) {306fprintf(stderr, "Enclose strings in quotes and try again\n");307return;308}309if (mixer_ctl_set_enum_by_string(ctl, values[0]))310fprintf(stderr, "Error: invalid enum value\n");311} else {312fprintf(stderr, "Error: only enum types can be set with strings\n");313}314}315}316317318319