summaryrefslogtreecommitdiffstats
path: root/alsa-lib/src/control/namehint.c
diff options
context:
space:
mode:
Diffstat (limited to 'alsa-lib/src/control/namehint.c')
-rw-r--r--alsa-lib/src/control/namehint.c650
1 files changed, 0 insertions, 650 deletions
diff --git a/alsa-lib/src/control/namehint.c b/alsa-lib/src/control/namehint.c
deleted file mode 100644
index e878f83..0000000
--- a/alsa-lib/src/control/namehint.c
+++ /dev/null
@@ -1,650 +0,0 @@
-/**
- * \file control/namehint.c
- * \brief Give device name hints
- * \author Jaroslav Kysela <perex@perex.cz>
- * \date 2006
- */
-/*
- * Give device name hints - main file
- * Copyright (c) 2006 by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "local.h"
-
-#ifndef DOC_HIDDEN
-struct hint_list {
- char **list;
- unsigned int count;
- unsigned int allocated;
- const char *siface;
- snd_ctl_elem_iface_t iface;
- snd_ctl_t *ctl;
- snd_ctl_card_info_t *info;
- int card;
- int device;
- long device_input;
- long device_output;
- int stream;
- int show_all;
- char *cardname;
-};
-#endif
-
-static int hint_list_add(struct hint_list *list,
- const char *name,
- const char *description)
-{
- char *x;
-
- if (list->count == list->allocated) {
- char **n = realloc(list->list, (list->allocated + 10) * sizeof(char *));
- if (n == NULL)
- return -ENOMEM;
- list->allocated += 10;
- list->list = n;
- }
- if (name == NULL) {
- x = NULL;
- } else {
- x = malloc(4 + strlen(name) + (description != NULL ? (4 + strlen(description) + 1) : 0) + 1);
- if (x == NULL)
- return -ENOMEM;
- memcpy(x, "NAME", 4);
- strcpy(x + 4, name);
- if (description != NULL) {
- strcat(x, "|DESC");
- strcat(x, description);
- }
- }
- list->list[list->count++] = x;
- return 0;
-}
-
-static void zero_handler(const char *file ATTRIBUTE_UNUSED,
- int line ATTRIBUTE_UNUSED,
- const char *function ATTRIBUTE_UNUSED,
- int err ATTRIBUTE_UNUSED,
- const char *fmt ATTRIBUTE_UNUSED, ...)
-{
-}
-
-static int get_dev_name1(struct hint_list *list, char **res, int device,
- int stream)
-{
- *res = NULL;
- if (device < 0)
- return 0;
- switch (list->iface) {
-#ifdef BUILD_HWDEP
- case SND_CTL_ELEM_IFACE_HWDEP:
- {
- snd_hwdep_info_t *info;
- snd_hwdep_info_alloca(&info);
- snd_hwdep_info_set_device(info, device);
- if (snd_ctl_hwdep_info(list->ctl, info) < 0)
- return 0;
- *res = strdup(snd_hwdep_info_get_name(info));
- return 0;
- }
-#endif
-#ifdef BUILD_PCM
- case SND_CTL_ELEM_IFACE_PCM:
- {
- snd_pcm_info_t *info;
- snd_pcm_info_alloca(&info);
- snd_pcm_info_set_device(info, device);
- snd_pcm_info_set_stream(info, stream ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK);
- if (snd_ctl_pcm_info(list->ctl, info) < 0)
- return 0;
- switch (snd_pcm_info_get_class(info)) {
- case SND_PCM_CLASS_MODEM:
- case SND_PCM_CLASS_DIGITIZER:
- return -ENODEV;
- default:
- break;
- }
- *res = strdup(snd_pcm_info_get_name(info));
- return 0;
- }
-#endif
-#ifdef BUILD_RAWMIDI
- case SND_CTL_ELEM_IFACE_RAWMIDI:
- {
- snd_rawmidi_info_t *info;
- snd_rawmidi_info_alloca(&info);
- snd_rawmidi_info_set_device(info, device);
- snd_rawmidi_info_set_stream(info, stream ? SND_RAWMIDI_STREAM_INPUT : SND_RAWMIDI_STREAM_OUTPUT);
- if (snd_ctl_rawmidi_info(list->ctl, info) < 0)
- return 0;
- *res = strdup(snd_rawmidi_info_get_name(info));
- return 0;
- }
-#endif
- default:
- return 0;
- }
-}
-
-static char *get_dev_name(struct hint_list *list)
-{
- char *str1, *str2, *res;
- int device;
-
- device = list->device_input >= 0 ? list->device_input : list->device;
- if (get_dev_name1(list, &str1, device, 1) < 0)
- return NULL;
- device = list->device_output >= 0 ? list->device_output : list->device;
- if (get_dev_name1(list, &str2, device, 0) < 0) {
- if (str1)
- free(str1);
- return NULL;
- }
- if (str1 != NULL || str2 != NULL) {
- if (str1 != NULL && str2 != NULL) {
- if (strcmp(str1, str2) == 0) {
- res = malloc(strlen(list->cardname) + strlen(str2) + 3);
- if (res != NULL) {
- strcpy(res, list->cardname);
- strcat(res, ", ");
- strcat(res, str2);
- }
- } else {
- res = malloc(strlen(list->cardname) + strlen(str2) + strlen(str1) + 6);
- if (res != NULL) {
- strcpy(res, list->cardname);
- strcat(res, ", ");
- strcat(res, str2);
- strcat(res, " / ");
- strcat(res, str1);
- }
- }
- free(str2);
- free(str1);
- return res;
- } else {
- if (str1 != NULL) {
- str2 = "Input";
- } else {
- str1 = str2;
- str2 = "Output";
- }
- res = malloc(strlen(list->cardname) + strlen(str1) + 19);
- if (res == NULL) {
- free(str1);
- return NULL;
- }
- strcpy(res, list->cardname);
- strcat(res, ", ");
- strcat(res, str1);
- strcat(res, "|IOID");
- strcat(res, str2);
- free(str1);
- return res;
- }
- }
- /* if the specified device doesn't exist, skip this entry */
- if (list->device >= 0 || list->device_input >= 0 || list->device_output >= 0)
- return NULL;
- return strdup(list->cardname);
-}
-
-#ifndef DOC_HIDDEN
-#define BUF_SIZE 128
-#endif
-
-static int try_config(struct hint_list *list,
- const char *base,
- const char *name)
-{
- snd_lib_error_handler_t eh;
- snd_config_t *res = NULL, *cfg, *cfg1, *n;
- snd_config_iterator_t i, next;
- char *buf, *buf1 = NULL, *buf2;
- const char *str;
- int err = 0, level;
- long dev = list->device;
-
- list->device_input = -1;
- list->device_output = -1;
- buf = malloc(BUF_SIZE);
- if (buf == NULL)
- return -ENOMEM;
- sprintf(buf, "%s.%s", base, name);
- /* look for redirection */
- if (snd_config_search(snd_config, buf, &cfg) >= 0 &&
- snd_config_get_string(cfg, &str) >= 0 &&
- ((strncmp(base, str, strlen(base)) == 0 &&
- str[strlen(base)] == '.') || strchr(str, '.') == NULL))
- goto __skip_add;
- if (list->card >= 0 && list->device >= 0)
- sprintf(buf, "%s:CARD=%s,DEV=%i", name, snd_ctl_card_info_get_id(list->info), list->device);
- else if (list->card >= 0)
- sprintf(buf, "%s:CARD=%s", name, snd_ctl_card_info_get_id(list->info));
- else
- strcpy(buf, name);
- eh = snd_lib_error;
- snd_lib_error_set_handler(&zero_handler);
- err = snd_config_search_definition(snd_config, base, buf, &res);
- snd_lib_error_set_handler(eh);
- if (err < 0)
- goto __skip_add;
- err = -EINVAL;
- if (snd_config_get_type(res) != SND_CONFIG_TYPE_COMPOUND)
- goto __cleanup;
- if (snd_config_search(res, "type", NULL) < 0)
- goto __cleanup;
-
-#if 0 /* for debug purposes */
- {
- snd_output_t *out;
- fprintf(stderr, "********* PCM '%s':\n", buf);
- snd_output_stdio_attach(&out, stderr, 0);
- snd_config_save(res, out);
- snd_output_close(out);
- fprintf(stderr, "\n");
- }
-#endif
-
- cfg1 = res;
- level = 0;
- __hint:
- level++;
- if (snd_config_search(cfg1, "type", &cfg) >= 0 &&
- snd_config_get_string(cfg, &str) >= 0 &&
- strcmp(str, "hw") == 0) {
- dev = 0;
- list->device_input = -1;
- list->device_output = -1;
- if (snd_config_search(cfg1, "device", &cfg) >= 0) {
- if (snd_config_get_integer(cfg, &dev) < 0) {
- SNDERR("(%s) device must be an integer", buf);
- err = -EINVAL;
- goto __cleanup;
- }
- }
- }
-
- if (snd_config_search(cfg1, "hint", &cfg) >= 0) {
- if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("hint (%s) must be a compound", buf);
- err = -EINVAL;
- goto __cleanup;
- }
- if (level == 1 &&
- snd_config_search(cfg, "show", &n) >= 0 &&
- snd_config_get_bool(n) <= 0)
- goto __skip_add;
- if (buf1 == NULL &&
- snd_config_search(cfg, "description", &n) >= 0 &&
- snd_config_get_string(n, &str) >= 0) {
- buf1 = strdup(str);
- if (buf1 == NULL) {
- err = -ENOMEM;
- goto __cleanup;
- }
- }
- if (snd_config_search(cfg, "device", &n) >= 0) {
- if (snd_config_get_integer(n, &dev) < 0) {
- SNDERR("(%s) device must be an integer", buf);
- err = -EINVAL;
- goto __cleanup;
- }
- list->device_input = dev;
- list->device_output = dev;
- }
- if (snd_config_search(cfg, "device_input", &n) >= 0) {
- if (snd_config_get_integer(n, &list->device_input) < 0) {
- SNDERR("(%s) device_input must be an integer", buf);
- err = -EINVAL;
- goto __cleanup;
- }
- list->device_output = -1;
- }
- if (snd_config_search(cfg, "device_output", &n) >= 0) {
- if (snd_config_get_integer(n, &list->device_output) < 0) {
- SNDERR("(%s) device_output must be an integer", buf);
- err = -EINVAL;
- goto __cleanup;
- }
- }
- } else if (level == 1 && !list->show_all)
- goto __skip_add;
- if (snd_config_search(cfg1, "slave", &cfg) >= 0 &&
- snd_config_search(cfg, base, &cfg1) >= 0)
- goto __hint;
- snd_config_delete(res);
- res = NULL;
- if (strchr(buf, ':') != NULL)
- goto __ok;
- /* find, if all parameters have a default, */
- /* otherwise filter this definition */
- eh = snd_lib_error;
- snd_lib_error_set_handler(&zero_handler);
- err = snd_config_search_alias_hooks(snd_config, base, buf, &res);
- snd_lib_error_set_handler(eh);
- if (err < 0)
- goto __cleanup;
- if (snd_config_search(res, "@args", &cfg) >= 0) {
- snd_config_for_each(i, next, cfg) {
- if (snd_config_search(snd_config_iterator_entry(i),
- "default", NULL) < 0) {
- err = -EINVAL;
- goto __cleanup;
- }
- }
- }
- __ok:
- err = 0;
- __cleanup:
- if (err >= 0) {
- list->device = dev;
- str = list->card >= 0 ? get_dev_name(list) : NULL;
- if (str != NULL) {
- level = (buf1 == NULL ? 0 : strlen(buf1)) + 1 + strlen(str);
- buf2 = realloc((char *)str, level + 1);
- if (buf2 != NULL) {
- if (buf1 != NULL) {
- str = strchr(buf2, '|');
- if (str != NULL)
- memmove(buf2 + (level - strlen(str)), str, strlen(str));
- else
- str = buf2 + strlen(buf2);
- *(char *)str++ = '\n';
- memcpy((char *)str, buf1, strlen(buf1));
- buf2[level] = '\0';
- free(buf1);
- }
- buf1 = buf2;
- } else {
- free((char *)str);
- }
- } else if (list->device >= 0)
- goto __skip_add;
- err = hint_list_add(list, buf, buf1);
- }
- __skip_add:
- if (res)
- snd_config_delete(res);
- if (buf1)
- free(buf1);
- free(buf);
- return err;
-}
-
-#ifndef DOC_HIDDEN
-#define IFACE(v, fcn) [SND_CTL_ELEM_IFACE_##v] = (next_devices_t)fcn
-
-typedef int (*next_devices_t)(snd_ctl_t *, int *);
-
-static const next_devices_t next_devices[] = {
- IFACE(CARD, NULL),
- IFACE(HWDEP, snd_ctl_hwdep_next_device),
- IFACE(MIXER, NULL),
- IFACE(PCM, snd_ctl_pcm_next_device),
- IFACE(RAWMIDI, snd_ctl_rawmidi_next_device),
- IFACE(TIMER, NULL),
- IFACE(SEQUENCER, NULL)
-};
-#endif
-
-static int add_card(struct hint_list *list, int card)
-{
- int err, ok;
- snd_config_t *conf, *n;
- snd_config_iterator_t i, next;
- const char *str;
- char ctl_name[16];
- snd_ctl_card_info_t *info;
-
- snd_ctl_card_info_alloca(&info);
- list->info = info;
- err = snd_config_search(snd_config, list->siface, &conf);
- if (err < 0)
- return err;
- sprintf(ctl_name, "hw:%i", card);
- err = snd_ctl_open(&list->ctl, ctl_name, 0);
- if (err < 0)
- return err;
- err = snd_ctl_card_info(list->ctl, info);
- if (err < 0)
- goto __error;
- snd_config_for_each(i, next, conf) {
- n = snd_config_iterator_entry(i);
- if (snd_config_get_id(n, &str) < 0)
- continue;
- if (next_devices[list->iface] != NULL) {
- list->card = card;
- list->device = -1;
- err = next_devices[list->iface](list->ctl, &list->device);
- if (list->device < 0)
- err = -EINVAL;
- ok = 0;
- while (err >= 0 && list->device >= 0) {
- err = try_config(list, list->siface, str);
- if (err < 0)
- break;
- err = next_devices[list->iface](list->ctl, &list->device);
- ok++;
- }
- if (ok)
- continue;
- } else {
- err = -EINVAL;
- }
- if (err == -EXDEV)
- continue;
- if (err < 0) {
- list->device = -1;
- err = try_config(list, list->siface, str);
- }
- if (err < 0) {
- list->card = -1;
- err = try_config(list, list->siface, str);
- }
- if (err == -ENOMEM)
- goto __error;
- }
- err = 0;
- __error:
- snd_ctl_close(list->ctl);
- return err;
-}
-
-static int get_card_name(struct hint_list *list, int card)
-{
- char scard[16], *s;
- int err;
-
- err = snd_card_get_name(card, &list->cardname);
- if (err <= 0)
- return 0;
- sprintf(scard, " #%i", card);
- s = realloc(list->cardname, strlen(list->cardname) + strlen(scard) + 1);
- if (s == NULL)
- return -ENOMEM;
- list->cardname = s;
- return 0;
-}
-
-/**
- * \brief Return string list with device name hints.
- * \param card Card number or -1 (means all cards)
- * \param iface Interface identification (like "pcm", "rawmidi", "timer", "seq")
- * \param hints Result - array of string with device name hints
- * \result zero if success, otherwise a negative error code
- *
- * Note: The device description is separated with '|' char.
- *
- * User defined hints are gathered from namehint.IFACE tree like:
- *
- * <code>
- * namehint.pcm {<br>
- * myfile "file:FILE=/tmp/soundwave.raw|Save sound output to /tmp/soundwave.raw"<br>
- * myplug "plug:front:Do all conversions for front speakers"<br>
- * }
- * </code>
- *
- * Special variables: defaults.namehint.showall specifies if all device
- * definitions are accepted (boolean type).
- */
-int snd_device_name_hint(int card, const char *iface, void ***hints)
-{
- struct hint_list list;
- char ehints[24];
- const char *str;
- snd_config_t *conf;
- snd_config_iterator_t i, next;
- int err;
-
- if (hints == NULL)
- return -EINVAL;
- err = snd_config_update();
- if (err < 0)
- return err;
- list.list = NULL;
- list.count = list.allocated = 0;
- list.siface = iface;
- if (strcmp(iface, "card") == 0)
- list.iface = SND_CTL_ELEM_IFACE_CARD;
- else if (strcmp(iface, "pcm") == 0)
- list.iface = SND_CTL_ELEM_IFACE_PCM;
- else if (strcmp(iface, "rawmidi") == 0)
- list.iface = SND_CTL_ELEM_IFACE_RAWMIDI;
- else if (strcmp(iface, "timer") == 0)
- list.iface = SND_CTL_ELEM_IFACE_TIMER;
- else if (strcmp(iface, "seq") == 0)
- list.iface = SND_CTL_ELEM_IFACE_SEQUENCER;
- else if (strcmp(iface, "hwdep") == 0)
- list.iface = SND_CTL_ELEM_IFACE_HWDEP;
- else
- return -EINVAL;
- list.show_all = 0;
- list.cardname = NULL;
- if (snd_config_search(snd_config, "defaults.namehint.showall", &conf) >= 0)
- list.show_all = snd_config_get_bool(conf) > 0;
- if (card >= 0) {
- err = get_card_name(&list, card);
- if (err >= 0)
- err = add_card(&list, card);
- } else {
- err = snd_card_next(&card);
- if (err < 0)
- goto __error;
- while (card >= 0) {
- err = get_card_name(&list, card);
- if (err < 0)
- goto __error;
- err = add_card(&list, card);
- if (err < 0)
- goto __error;
- err = snd_card_next(&card);
- if (err < 0)
- goto __error;
- }
- }
- sprintf(ehints, "namehint.%s", list.siface);
- err = snd_config_search(snd_config, ehints, &conf);
- if (err >= 0) {
- snd_config_for_each(i, next, conf) {
- if (snd_config_get_string(snd_config_iterator_entry(i),
- &str) < 0)
- continue;
- err = hint_list_add(&list, str, NULL);
- if (err < 0)
- goto __error;
- }
- }
- err = 0;
- __error:
- if (err < 0) {
- snd_device_name_free_hint((void **)list.list);
- if (list.cardname)
- free(list.cardname);
- return err;
- } else {
- err = hint_list_add(&list, NULL, NULL);
- if (err < 0)
- goto __error;
- *hints = (void **)list.list;
- if (list.cardname)
- free(list.cardname);
- }
- return 0;
-}
-
-/**
- * \brief Free a string list with device name hints.
- * \param hints A string list to free
- * \result zero if success, otherwise a negative error code
- */
-int snd_device_name_free_hint(void **hints)
-{
- char **h;
-
- if (hints == NULL)
- return 0;
- h = (char **)hints;
- while (*h) {
- free(*h);
- h++;
- }
- free(hints);
- return 0;
-}
-
-/**
- * \brief Get a hint Free a string list with device name hints.
- * \param hint A pointer to hint
- * \param id Hint ID (see bellow)
- * \result an allocated ASCII string if success, otherwise NULL
- *
- * List of valid IDs:
- * NAME - name of device
- * DESC - description of device
- * IOID - input / output identification (Input or Output strings),
- * not present (NULL) means both
- */
-char *snd_device_name_get_hint(const void *hint, const char *id)
-{
- const char *hint1 = (const char *)hint, *delim;
- char *res;
- unsigned size;
-
- if (strlen(id) != 4)
- return NULL;
- while (*hint1 != '\0') {
- delim = strchr(hint1, '|');
- if (memcmp(id, hint1, 4) != 0) {
- if (delim == NULL)
- return NULL;
- hint1 = delim + 1;
- continue;
- }
- if (delim == NULL)
- return strdup(hint1 + 4);
- size = delim - hint1 - 4;
- res = malloc(size + 1);
- if (res != NULL) {
- memcpy(res, hint1 + 4, size);
- res[size] = '\0';
- }
- return res;
- }
- return NULL;
-}