From a022bc1fbc6fa287bbdc969cdf969c10c39fe2a1 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 10 May 2005 10:52:30 +0000 Subject: [PATCH] API for device name lists and timer enhancements - new snd_names_list and snd_names_list_free functions - added snd_timer_ginfo related functions to the timer API --- include/conf.h | 14 ++- include/timer.h | 18 ++++ src/Makefile.am | 2 +- src/Versions | 18 ++++ src/names.c | 187 ++++++++++++++++++++++++++++++++++++++++ src/timer/timer_query.c | 151 ++++++++++++++++++++++++++++++++ 6 files changed, 388 insertions(+), 2 deletions(-) create mode 100644 src/names.c diff --git a/include/conf.h b/include/conf.h index b8bb8c32..32d6da36 100644 --- a/include/conf.h +++ b/include/conf.h @@ -170,6 +170,19 @@ int snd_config_get_bool(const snd_config_t *conf); int snd_config_get_ctl_iface_ascii(const char *ascii); int snd_config_get_ctl_iface(const snd_config_t *conf); +/* Names functions */ + +typedef struct snd_devname snd_devname_t; + +struct snd_devname { + char *name; + char *comment; + snd_devname_t *next; +}; + +int snd_names_list(const char *interface, snd_devname_t **list); +void snd_names_list_free(snd_devname_t *list); + /** \} */ #ifdef __cplusplus @@ -177,4 +190,3 @@ int snd_config_get_ctl_iface(const snd_config_t *conf); #endif #endif /* __ALSA_CONF_H */ - diff --git a/include/timer.h b/include/timer.h index 86edd1e4..105dee20 100644 --- a/include/timer.h +++ b/include/timer.h @@ -173,6 +173,24 @@ int snd_timer_id_get_device(snd_timer_id_t *id); void snd_timer_id_set_subdevice(snd_timer_id_t *id, int subdevice); int snd_timer_id_get_subdevice(snd_timer_id_t *id); +size_t snd_timer_ginfo_sizeof(void); +/** allocate #snd_timer_ginfo_t container on stack */ +#define snd_timer_ginfo_alloca(ptr) do { assert(ptr); *ptr = (snd_timer_ginfo_t *) alloca(snd_timer_ginfo_sizeof()); memset(*ptr, 0, snd_timer_ginfo_sizeof()); } while (0) +int snd_timer_ginfo_malloc(snd_timer_ginfo_t **ptr); +void snd_timer_ginfo_free(snd_timer_ginfo_t *obj); +void snd_timer_ginfo_copy(snd_timer_ginfo_t *dst, const snd_timer_ginfo_t *src); + +int snd_timer_ginfo_set_tid(snd_timer_ginfo_t *obj, snd_timer_id_t *tid); +snd_timer_id_t *snd_timer_ginfo_get_tid(snd_timer_ginfo_t *obj); +unsigned int snd_timer_ginfo_get_flags(snd_timer_ginfo_t *obj); +int snd_timer_ginfo_get_card(snd_timer_ginfo_t *obj); +char *snd_timer_ginfo_get_id(snd_timer_ginfo_t *obj); +char *snd_timer_ginfo_get_name(snd_timer_ginfo_t *obj); +unsigned long snd_timer_ginfo_get_resolution(snd_timer_ginfo_t *obj); +unsigned long snd_timer_ginfo_get_resolution_min(snd_timer_ginfo_t *obj); +unsigned long snd_timer_ginfo_get_resolution_max(snd_timer_ginfo_t *obj); +unsigned int snd_timer_ginfo_get_clients(snd_timer_ginfo_t *obj); + size_t snd_timer_info_sizeof(void); /** allocate #snd_timer_info_t container on stack */ #define snd_timer_info_alloca(ptr) do { assert(ptr); *ptr = (snd_timer_info_t *) alloca(snd_timer_info_sizeof()); memset(*ptr, 0, snd_timer_info_sizeof()); } while (0) diff --git a/src/Makefile.am b/src/Makefile.am index 624caa23..4c1f9d0a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,7 +9,7 @@ VSYMS = endif lib_LTLIBRARIES = libasound.la -libasound_la_SOURCES = conf.c confmisc.c input.c output.c async.c error.c dlmisc.c socket.c shmarea.c userfile.c +libasound_la_SOURCES = conf.c confmisc.c input.c output.c async.c error.c dlmisc.c socket.c shmarea.c userfile.c names.c libasound_la_LIBADD = control/libcontrol.la \ mixer/libmixer.la ordinary_mixer/libordinarymixer.la \ pcm/libpcm.la ordinary_pcm/libordinarypcm.la \ diff --git a/src/Versions b/src/Versions index 24ecb1ed..2fe0241a 100644 --- a/src/Versions +++ b/src/Versions @@ -174,6 +174,9 @@ ALSA_1.0.8 { ALSA_1.0.9 { global: + snd_names_list; + snd_names_list_free; + snd_pcm_hw_params_set_rate_resample; snd_pcm_hw_params_get_rate_resample; @@ -194,4 +197,19 @@ ALSA_1.0.9 { snd_pcm_parse_control_id; + snd_timer_ginfo_sizeof; + snd_timer_ginfo_malloc; + snd_timer_ginfo_free; + snd_timer_ginfo_copy; + snd_timer_ginfo_set_tid; + snd_timer_ginfo_get_tid; + snd_timer_ginfo_get_flags; + snd_timer_ginfo_get_card; + snd_timer_ginfo_get_id; + snd_timer_ginfo_get_name; + snd_timer_ginfo_get_resolution; + snd_timer_ginfo_get_resolution_min; + snd_timer_ginfo_get_resolution_max; + snd_timer_ginfo_get_clients; + } ALSA_1.0.5; diff --git a/src/names.c b/src/names.c new file mode 100644 index 00000000..a3152c69 --- /dev/null +++ b/src/names.c @@ -0,0 +1,187 @@ +/** + * \file names.c + * \ingroup Configuration + * \brief Configuration helper functions - device names + * \author Jaroslav Kysela + * \date 2005 + * + * Provide a list of device names for applications. + * + * See the \ref conf page for more details. + */ +/* + * Configuration helper functions - device names + * Copyright (c) 2005 by Jaroslav Kysela + * + * + * 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 +#include +#include +#include +#include +#include +#include +#include "local.h" + +#define ALSA_NAMES_ENV "ALSA_NAMES_FILE" +#define ALSA_NAMES_PATH1 "/etc/asound.names" +#define ALSA_NAMES_PATH2 "~/.asoundnm" + +static int names_parse(snd_config_t *top, const char *interface, snd_devname_t **list) +{ + snd_config_iterator_t i, next; + snd_config_iterator_t j, jnext; + char *name, *comment; + const char *id; + snd_devname_t *dn, *last = NULL; + int err; + + err = snd_config_search(top, interface, &top); + if (err < 0) + return err; + snd_config_for_each(i, next, top) { + snd_config_t *n = snd_config_iterator_entry(i); + if (snd_config_get_id(n, &id) < 0) + continue; + name = comment = NULL; + snd_config_for_each(j, jnext, n) { + snd_config_t *m = snd_config_iterator_entry(j); + if (snd_config_get_id(m, &id) < 0) + continue; + if (strcmp(id, "name") == 0) { + err = snd_config_get_string(m, (const char **)&name); + if (err < 0) + continue; + name = strdup(name); + if (name == NULL) { + err = -ENOMEM; + goto _err; + } + } + if (strcmp(id, "comment") == 0) { + err = snd_config_get_string(m, (const char **)&comment); + if (err < 0) + continue; + comment = strdup(comment); + if (name == NULL) { + err = -ENOMEM; + goto _err; + } + } + } + if (name != NULL) { + dn = malloc(sizeof(*dn)); + if (dn == NULL) { + err = -ENOMEM; + goto _err; + } + dn->name = name; + dn->comment = comment; + dn->next = NULL; + if (last == NULL) { + *list = dn; + } else { + last->next = dn; + } + last = dn; + } else { + if (comment != NULL) + free(comment); + } + } + return 0; + + _err: + if (name) + free(name); + if (comment) + free(comment); + return err; +} + +/** + * \brief Give a list of device names and associated comments for selected interface + * \param interface a string identifying interface ("pcm", "ctl", "seq", "rawmidi") + * \param list result - a pointer to list + * \return A non-negative value if successful, otherwise a negative error code. + * + * The global configuration files are specified in the environment variable + * \c ALSA_NAMES_FILE. + */ +int snd_names_list(const char *interface, snd_devname_t **list) +{ + char *file; + snd_config_t *top; + snd_input_t *in; + int err; + + assert(interface); + assert(list); + *list = NULL; + file = getenv(ALSA_NAMES_ENV); + if (file) { + file = strdup(file); + if (file == NULL) + return -ENOMEM; + } else { + err = snd_user_file(ALSA_NAMES_PATH2, &file); + if (err < 0) + return err; + if (access(file, R_OK)) { + file = strdup(ALSA_NAMES_PATH1); + if (file == NULL) + return -ENOMEM; + } + } + err = snd_config_top(&top); + if (err >= 0) + err = snd_input_stdio_open(&in, file, "r"); + if (err >= 0) { + err = snd_config_load(top, in); + snd_input_close(in); + if (err < 0) { + SNDERR("%s may be old or corrupted: consider to remove or fix it", file); + } else { + err = names_parse(top, interface, list); + if (err < 0) { + snd_names_list_free(*list); + *list = NULL; + } + } + } else { + SNDERR("cannot access file %s", file); + } + snd_config_delete(top); + return err >= 0 ? 0 : err; +} + +void snd_names_list_free(snd_devname_t *list) +{ + snd_devname_t *next; + + while (list != NULL) { + next = list->next; + if (list->name) + free(list->name); + if (list->comment) + free(list->comment); + free(list); + list = next; + } +} diff --git a/src/timer/timer_query.c b/src/timer/timer_query.c index 44dd13df..ec5f61e1 100644 --- a/src/timer/timer_query.c +++ b/src/timer/timer_query.c @@ -220,6 +220,157 @@ int snd_timer_query_next_device(snd_timer_query_t *timer, snd_timer_id_t *tid) return timer->ops->next_device(timer, tid); } +/** + * \brief get size of the snd_timer_ginfo_t structure in bytes + * \return size of the snd_timer_ginfo_t structure in bytes + */ +size_t snd_timer_ginfo_sizeof(void) +{ + return sizeof(snd_timer_ginfo_t); +} + +/** + * \brief allocate a new snd_timer_ginfo_t structure + * \param ptr returned pointer + * \return 0 on success otherwise a negative error code if fails + * + * Allocates a new snd_timer_info_t structure using the standard + * malloc C library function. + */ +int snd_timer_ginfo_malloc(snd_timer_ginfo_t **info) +{ + assert(info); + *info = calloc(1, sizeof(snd_timer_ginfo_t)); + if (!*info) + return -ENOMEM; + return 0; +} + +/** + * \brief frees the snd_timer_ginfo_t structure + * \param info pointer to the snd_timer_ginfo_t structure to free + * + * Frees the given snd_timer_info_t structure using the standard + * free C library function. + */ +void snd_timer_ginfo_free(snd_timer_ginfo_t *info) +{ + assert(info); + free(info); +} + +/** + * \brief copy one snd_timer_info_t structure to another + * \param dst destination snd_timer_info_t structure + * \param src source snd_timer_info_t structure + */ +void snd_timer_ginfo_copy(snd_timer_ginfo_t *dst, const snd_timer_ginfo_t *src) +{ + assert(dst && src); + *dst = *src; +} + +/** + * \brief set timer identification + * \param obj pointer to #snd_timer_ginfo_t structure + * \return zero on success otherwise a negative error number + */ +int snd_timer_ginfo_set_tid(snd_timer_ginfo_t *obj, snd_timer_id_t *tid) +{ + obj->tid = *((snd_timer_id_t *)tid); + return 0; +} + +/** + * \brief get timer identification + * \param obj pointer to #snd_timer_ginfo_t structure + * \return pointer to snd_timer_id_t + */ +snd_timer_id_t *snd_timer_ginfo_get_tid(snd_timer_ginfo_t *obj) +{ + return (snd_timer_id_t *)&obj->tid; +} + +/** + * \brief get timer flags + * \param obj pointer to #snd_timer_ginfo_t structure + * \return timer flags + */ +unsigned int snd_timer_ginfo_get_flags(snd_timer_ginfo_t *obj) +{ + return obj->flags; +} + +/** + * \brief get associated card with timer + * \param obj pointer to #snd_timer_ginfo_t structure + * \return associated card + */ +int snd_timer_ginfo_get_card(snd_timer_ginfo_t *obj) +{ + return obj->card; +} + +/** + * \brief get timer identification + * \param obj pointer to #snd_timer_ginfo_t structure + * \return timer identification + */ +char *snd_timer_ginfo_get_id(snd_timer_ginfo_t *obj) +{ + return obj->id; +} + +/** + * \brief get timer name + * \param obj pointer to #snd_timer_ginfo_t structure + * \return timer name + */ +char *snd_timer_ginfo_get_name(snd_timer_ginfo_t *obj) +{ + return obj->name; +} + +/** + * \brief get timer resolution in ns + * \param obj pointer to #snd_timer_ginfo_t structure + * \return timer resolution in ns + */ +unsigned long snd_timer_ginfo_get_resolution(snd_timer_ginfo_t *obj) +{ + return obj->resolution; +} + +/** + * \brief get timer minimal resolution in ns + * \param obj pointer to #snd_timer_ginfo_t structure + * \return timer minimal resolution in ns + */ +unsigned long snd_timer_ginfo_get_resolution_min(snd_timer_ginfo_t *obj) +{ + return obj->resolution_min; +} + +/** + * \brief get timer maximal resolution in ns + * \param obj pointer to #snd_timer_ginfo_t structure + * \return timer maximal resolution in ns + */ +unsigned long snd_timer_ginfo_get_resolution_max(snd_timer_ginfo_t *obj) +{ + return obj->resolution_max; +} + +/** + * \brief get current timer clients + * \param obj pointer to #snd_timer_ginfo_t structure + * \return current timer clients + */ +unsigned int snd_timer_ginfo_get_clients(snd_timer_ginfo_t *obj) +{ + return obj->clients; +} + /** * \brief obtain the timer global information * \param timer timer handle -- 2.47.1