OSDN Git Service

API for device name lists and timer enhancements
authorJaroslav Kysela <perex@perex.cz>
Tue, 10 May 2005 10:52:30 +0000 (10:52 +0000)
committerJaroslav Kysela <perex@perex.cz>
Tue, 10 May 2005 10:52:30 +0000 (10:52 +0000)
- new snd_names_list and snd_names_list_free functions
- added snd_timer_ginfo related functions to the timer API

include/conf.h
include/timer.h
src/Makefile.am
src/Versions
src/names.c [new file with mode: 0644]
src/timer/timer_query.c

index b8bb8c3..32d6da3 100644 (file)
@@ -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 */
-
index 86edd1e..105dee2 100644 (file)
@@ -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)
index 624caa2..4c1f9d0 100644 (file)
@@ -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 \
index 24ecb1e..2fe0241 100644 (file)
@@ -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 (file)
index 0000000..a3152c6
--- /dev/null
@@ -0,0 +1,187 @@
+/**
+ * \file names.c
+ * \ingroup Configuration
+ * \brief Configuration helper functions - device names
+ * \author Jaroslav Kysela <perex@suse.cz>
+ * \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 <perex@suse.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 <stdarg.h>
+#include <wordexp.h>
+#include <dlfcn.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <locale.h>
+#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;
+       }
+}
index 44dd13d..ec5f61e 100644 (file)
@@ -221,6 +221,157 @@ int snd_timer_query_next_device(snd_timer_query_t *timer, snd_timer_id_t *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
  * \param info timer information