1356 lines
51 KiB
Diff
1356 lines
51 KiB
Diff
diff -r 9e2f117f24b9 NOTES
|
|
--- a/NOTES Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/NOTES Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -27,11 +27,14 @@ When LIBASOUND_DEBUG=1 is set, the error
|
|
When LIBASOUND_DEBUG=1 is set, the errors in hw_params configuration
|
|
will be dumped to stderr. Note that this will show even the non-fatal
|
|
errors of plug layer (trial-and-error of parameters).
|
|
-When LIBASOUND_DEBUG=2 is set, the default error message handler calls
|
|
-assert() to catch with a debugger, in addition to parameter debugging.
|
|
|
|
This feature is disabled when --with-debug=no is passed to configure,
|
|
i.e. no strict checking is done in alsa-lib.
|
|
+
|
|
+In addition, when --enable-debug-assert configure option is given and
|
|
+when LIBASOUND_DEBUG_ASSERT=1 is set, the default error message
|
|
+handler can call assert() to catch with a debugger. This feature was
|
|
+formerly activated via LIBASOUND_DEBUG=2.
|
|
|
|
|
|
Blocking Open Mode
|
|
diff -r 9e2f117f24b9 configure.in
|
|
--- a/configure.in Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/configure.in Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -167,6 +167,20 @@ else
|
|
else
|
|
AC_DEFINE(NDEBUG,,[No assert debug])
|
|
AC_MSG_RESULT(no)
|
|
+fi
|
|
+
|
|
+if test "$debug" = "yes"; then
|
|
+ AC_MSG_CHECKING(for debug assert)
|
|
+ AC_ARG_ENABLE(debug-assert,
|
|
+ AS_HELP_STRING([--enable-debug],
|
|
+ [enable assert call at the default error message handler]),
|
|
+ debug_assert="$enableval", debug_assert="no")
|
|
+ if test "$debug_assert" = "yes"; then
|
|
+ AC_MSG_RESULT(yes)
|
|
+ AC_DEFINE(ALSA_DEBUG_ASSERT,,[Enable assert at error message handler])
|
|
+ else
|
|
+ AC_MSG_RESULT(no)
|
|
+ fi
|
|
fi
|
|
|
|
dnl Temporary directory
|
|
diff -r 9e2f117f24b9 include/asoundlib-head.h
|
|
--- a/include/asoundlib-head.h Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/include/asoundlib-head.h Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -33,7 +33,6 @@
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
-#include <assert.h>
|
|
#include <endian.h>
|
|
#include <sys/poll.h>
|
|
#include <errno.h>
|
|
diff -r 9e2f117f24b9 include/control.h
|
|
--- a/include/control.h Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/include/control.h Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -279,7 +279,7 @@ size_t snd_ctl_elem_id_sizeof(void);
|
|
* \brief allocate an invalid #snd_ctl_elem_id_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_ctl_elem_id_alloca(ptr) do { assert(ptr); *ptr = (snd_ctl_elem_id_t *) alloca(snd_ctl_elem_id_sizeof()); memset(*ptr, 0, snd_ctl_elem_id_sizeof()); } while (0)
|
|
+#define snd_ctl_elem_id_alloca(ptr) __snd_alloca(ptr, snd_ctl_elem_id)
|
|
int snd_ctl_elem_id_malloc(snd_ctl_elem_id_t **ptr);
|
|
void snd_ctl_elem_id_free(snd_ctl_elem_id_t *obj);
|
|
void snd_ctl_elem_id_clear(snd_ctl_elem_id_t *obj);
|
|
@@ -302,7 +302,7 @@ size_t snd_ctl_card_info_sizeof(void);
|
|
* \brief allocate an invalid #snd_ctl_card_info_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_ctl_card_info_alloca(ptr) do { assert(ptr); *ptr = (snd_ctl_card_info_t *) alloca(snd_ctl_card_info_sizeof()); memset(*ptr, 0, snd_ctl_card_info_sizeof()); } while (0)
|
|
+#define snd_ctl_card_info_alloca(ptr) __snd_alloca(ptr, snd_ctl_card_info)
|
|
int snd_ctl_card_info_malloc(snd_ctl_card_info_t **ptr);
|
|
void snd_ctl_card_info_free(snd_ctl_card_info_t *obj);
|
|
void snd_ctl_card_info_clear(snd_ctl_card_info_t *obj);
|
|
@@ -320,7 +320,7 @@ size_t snd_ctl_event_sizeof(void);
|
|
* \brief allocate an invalid #snd_ctl_event_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_ctl_event_alloca(ptr) do { assert(ptr); *ptr = (snd_ctl_event_t *) alloca(snd_ctl_event_sizeof()); memset(*ptr, 0, snd_ctl_event_sizeof()); } while (0)
|
|
+#define snd_ctl_event_alloca(ptr) __snd_alloca(ptr, snd_ctl_event)
|
|
int snd_ctl_event_malloc(snd_ctl_event_t **ptr);
|
|
void snd_ctl_event_free(snd_ctl_event_t *obj);
|
|
void snd_ctl_event_clear(snd_ctl_event_t *obj);
|
|
@@ -332,7 +332,7 @@ size_t snd_ctl_elem_list_sizeof(void);
|
|
* \brief allocate an invalid #snd_ctl_elem_list_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_ctl_elem_list_alloca(ptr) do { assert(ptr); *ptr = (snd_ctl_elem_list_t *) alloca(snd_ctl_elem_list_sizeof()); memset(*ptr, 0, snd_ctl_elem_list_sizeof()); } while (0)
|
|
+#define snd_ctl_elem_list_alloca(ptr) __snd_alloca(ptr, snd_ctl_elem_list)
|
|
int snd_ctl_elem_list_malloc(snd_ctl_elem_list_t **ptr);
|
|
void snd_ctl_elem_list_free(snd_ctl_elem_list_t *obj);
|
|
void snd_ctl_elem_list_clear(snd_ctl_elem_list_t *obj);
|
|
@@ -353,7 +353,7 @@ size_t snd_ctl_elem_info_sizeof(void);
|
|
* \brief allocate an invalid #snd_ctl_elem_info_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_ctl_elem_info_alloca(ptr) do { assert(ptr); *ptr = (snd_ctl_elem_info_t *) alloca(snd_ctl_elem_info_sizeof()); memset(*ptr, 0, snd_ctl_elem_info_sizeof()); } while (0)
|
|
+#define snd_ctl_elem_info_alloca(ptr) __snd_alloca(ptr, snd_ctl_elem_info)
|
|
int snd_ctl_elem_info_malloc(snd_ctl_elem_info_t **ptr);
|
|
void snd_ctl_elem_info_free(snd_ctl_elem_info_t *obj);
|
|
void snd_ctl_elem_info_clear(snd_ctl_elem_info_t *obj);
|
|
@@ -408,7 +408,7 @@ size_t snd_ctl_elem_value_sizeof(void);
|
|
* \brief allocate an invalid #snd_ctl_elem_value_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_ctl_elem_value_alloca(ptr) do { assert(ptr); *ptr = (snd_ctl_elem_value_t *) alloca(snd_ctl_elem_value_sizeof()); memset(*ptr, 0, snd_ctl_elem_value_sizeof()); } while (0)
|
|
+#define snd_ctl_elem_value_alloca(ptr) __snd_alloca(ptr, snd_ctl_elem_value)
|
|
int snd_ctl_elem_value_malloc(snd_ctl_elem_value_t **ptr);
|
|
void snd_ctl_elem_value_free(snd_ctl_elem_value_t *obj);
|
|
void snd_ctl_elem_value_clear(snd_ctl_elem_value_t *obj);
|
|
@@ -441,6 +441,21 @@ const void * snd_ctl_elem_value_get_byte
|
|
const void * snd_ctl_elem_value_get_bytes(const snd_ctl_elem_value_t *obj);
|
|
void snd_ctl_elem_value_get_iec958(const snd_ctl_elem_value_t *obj, snd_aes_iec958_t *ptr);
|
|
void snd_ctl_elem_value_set_iec958(snd_ctl_elem_value_t *obj, const snd_aes_iec958_t *ptr);
|
|
+
|
|
+int snd_tlv_parse_dB_info(unsigned int *tlv, unsigned int tlv_size,
|
|
+ unsigned int **db_tlvp);
|
|
+int snd_tlv_get_dB_range(unsigned int *tlv, long rangemin, long rangemax,
|
|
+ long *min, long *max);
|
|
+int snd_tlv_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax,
|
|
+ long volume, long *db_gain);
|
|
+int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax,
|
|
+ long db_gain, long *value, int xdir);
|
|
+int snd_ctl_get_dB_range(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
|
|
+ long *min, long *max);
|
|
+int snd_ctl_convert_to_dB(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
|
|
+ long volume, long *db_gain);
|
|
+int snd_ctl_convert_from_dB(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
|
|
+ long db_gain, long *value, int xdir);
|
|
|
|
/**
|
|
* \defgroup HControl High level Control Interface
|
|
diff -r 9e2f117f24b9 include/global.h
|
|
--- a/include/global.h Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/include/global.h Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -102,6 +102,9 @@ int snd_dlclose(void *handle);
|
|
int snd_dlclose(void *handle);
|
|
|
|
|
|
+/** \brief alloca helper macro. */
|
|
+#define __snd_alloca(ptr,type) do { *ptr = (type##_t *) alloca(type##_sizeof()); memset(*ptr, 0, type##_sizeof()); } while (0)
|
|
+
|
|
/**
|
|
* \brief Internal structure for an async notification client handler.
|
|
*
|
|
diff -r 9e2f117f24b9 include/hwdep.h
|
|
--- a/include/hwdep.h Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/include/hwdep.h Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -108,7 +108,7 @@ ssize_t snd_hwdep_read(snd_hwdep_t *hwde
|
|
|
|
size_t snd_hwdep_info_sizeof(void);
|
|
/** allocate #snd_hwdep_info_t container on stack */
|
|
-#define snd_hwdep_info_alloca(ptr) do { assert(ptr); *ptr = (snd_hwdep_info_t *) alloca(snd_hwdep_info_sizeof()); memset(*ptr, 0, snd_hwdep_info_sizeof()); } while (0)
|
|
+#define snd_hwdep_info_alloca(ptr) __snd_alloca(ptr, snd_hwdep_info)
|
|
int snd_hwdep_info_malloc(snd_hwdep_info_t **ptr);
|
|
void snd_hwdep_info_free(snd_hwdep_info_t *obj);
|
|
void snd_hwdep_info_copy(snd_hwdep_info_t *dst, const snd_hwdep_info_t *src);
|
|
@@ -122,7 +122,7 @@ void snd_hwdep_info_set_device(snd_hwdep
|
|
|
|
size_t snd_hwdep_dsp_status_sizeof(void);
|
|
/** allocate #snd_hwdep_dsp_status_t container on stack */
|
|
-#define snd_hwdep_dsp_status_alloca(ptr) do { assert(ptr); *ptr = (snd_hwdep_dsp_status_t *) alloca(snd_hwdep_dsp_status_sizeof()); memset(*ptr, 0, snd_hwdep_dsp_status_sizeof()); } while (0)
|
|
+#define snd_hwdep_dsp_status_alloca(ptr) __snd_alloca(ptr, snd_hwdep_dsp_status)
|
|
int snd_hwdep_dsp_status_malloc(snd_hwdep_dsp_status_t **ptr);
|
|
void snd_hwdep_dsp_status_free(snd_hwdep_dsp_status_t *obj);
|
|
void snd_hwdep_dsp_status_copy(snd_hwdep_dsp_status_t *dst, const snd_hwdep_dsp_status_t *src);
|
|
@@ -135,7 +135,7 @@ unsigned int snd_hwdep_dsp_status_get_ch
|
|
|
|
size_t snd_hwdep_dsp_image_sizeof(void);
|
|
/** allocate #snd_hwdep_dsp_image_t container on stack */
|
|
-#define snd_hwdep_dsp_image_alloca(ptr) do { assert(ptr); *ptr = (snd_hwdep_dsp_image_t *) alloca(snd_hwdep_dsp_image_sizeof()); memset(*ptr, 0, snd_hwdep_dsp_image_sizeof()); } while (0)
|
|
+#define snd_hwdep_dsp_image_alloca(ptr) __snd_alloca(ptr, snd_hwdep_dsp_image)
|
|
int snd_hwdep_dsp_image_malloc(snd_hwdep_dsp_image_t **ptr);
|
|
void snd_hwdep_dsp_image_free(snd_hwdep_dsp_image_t *obj);
|
|
void snd_hwdep_dsp_image_copy(snd_hwdep_dsp_image_t *dst, const snd_hwdep_dsp_image_t *src);
|
|
diff -r 9e2f117f24b9 include/instr.h
|
|
--- a/include/instr.h Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/include/instr.h Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -44,12 +44,8 @@ typedef struct _snd_instr_header snd_ins
|
|
typedef struct _snd_instr_header snd_instr_header_t;
|
|
|
|
size_t snd_instr_header_sizeof(void);
|
|
-#define snd_instr_header_alloca(ptr) \
|
|
-do {\
|
|
- assert(ptr);\
|
|
- *ptr = (snd_instr_header_t *)alloca(snd_instr_header_sizeof());\
|
|
- memset(*ptr, 0, snd_instr_header_sizeof());\
|
|
-} while (0) /**< allocate instrument header on stack */
|
|
+/** allocate instrument header on stack */
|
|
+#define snd_instr_header_alloca(ptr) __snd_alloca(ptr, snd_instr_header)
|
|
int snd_instr_header_malloc(snd_instr_header_t **ptr, size_t len);
|
|
void snd_instr_header_free(snd_instr_header_t *ptr);
|
|
void snd_instr_header_copy(snd_instr_header_t *dst, const snd_instr_header_t *src);
|
|
diff -r 9e2f117f24b9 include/mixer.h
|
|
--- a/include/mixer.h Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/include/mixer.h Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -146,7 +146,7 @@ size_t snd_mixer_class_sizeof(void);
|
|
* \brief allocate an invalid #snd_mixer_class_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_mixer_class_alloca(ptr) do { assert(ptr); *ptr = (snd_mixer_class_t *) alloca(snd_mixer_class_sizeof()); memset(*ptr, 0, snd_mixer_class_sizeof()); } while (0)
|
|
+#define snd_mixer_class_alloca(ptr) __snd_alloca(ptr, snd_mixer_class)
|
|
int snd_mixer_class_malloc(snd_mixer_class_t **ptr);
|
|
void snd_mixer_class_free(snd_mixer_class_t *obj);
|
|
void snd_mixer_class_copy(snd_mixer_class_t *dst, const snd_mixer_class_t *src);
|
|
@@ -294,7 +294,7 @@ size_t snd_mixer_selem_id_sizeof(void);
|
|
* \brief allocate an invalid #snd_mixer_selem_id_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_mixer_selem_id_alloca(ptr) do { assert(ptr); *ptr = (snd_mixer_selem_id_t *) alloca(snd_mixer_selem_id_sizeof()); memset(*ptr, 0, snd_mixer_selem_id_sizeof()); } while (0)
|
|
+#define snd_mixer_selem_id_alloca(ptr) __snd_alloca(ptr, snd_mixer_selem_id)
|
|
int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr);
|
|
void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj);
|
|
void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src);
|
|
diff -r 9e2f117f24b9 include/pcm.h
|
|
--- a/include/pcm.h Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/include/pcm.h Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -470,7 +470,7 @@ size_t snd_pcm_info_sizeof(void);
|
|
* \brief allocate an invalid #snd_pcm_info_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_pcm_info_alloca(ptr) do { assert(ptr); *ptr = (snd_pcm_info_t *) alloca(snd_pcm_info_sizeof()); memset(*ptr, 0, snd_pcm_info_sizeof()); } while (0)
|
|
+#define snd_pcm_info_alloca(ptr) __snd_alloca(ptr, snd_pcm_info)
|
|
int snd_pcm_info_malloc(snd_pcm_info_t **ptr);
|
|
void snd_pcm_info_free(snd_pcm_info_t *obj);
|
|
void snd_pcm_info_copy(snd_pcm_info_t *dst, const snd_pcm_info_t *src);
|
|
@@ -548,7 +548,7 @@ size_t snd_pcm_hw_params_sizeof(void);
|
|
* \brief allocate an invalid #snd_pcm_hw_params_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_pcm_hw_params_alloca(ptr) do { assert(ptr); *ptr = (snd_pcm_hw_params_t *) alloca(snd_pcm_hw_params_sizeof()); memset(*ptr, 0, snd_pcm_hw_params_sizeof()); } while (0)
|
|
+#define snd_pcm_hw_params_alloca(ptr) __snd_alloca(ptr, snd_pcm_hw_params)
|
|
int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t **ptr);
|
|
void snd_pcm_hw_params_free(snd_pcm_hw_params_t *obj);
|
|
void snd_pcm_hw_params_copy(snd_pcm_hw_params_t *dst, const snd_pcm_hw_params_t *src);
|
|
@@ -699,7 +699,7 @@ size_t snd_pcm_sw_params_sizeof(void);
|
|
* \brief allocate an invalid #snd_pcm_sw_params_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_pcm_sw_params_alloca(ptr) do { assert(ptr); *ptr = (snd_pcm_sw_params_t *) alloca(snd_pcm_sw_params_sizeof()); memset(*ptr, 0, snd_pcm_sw_params_sizeof()); } while (0)
|
|
+#define snd_pcm_sw_params_alloca(ptr) __snd_alloca(ptr, snd_pcm_sw_params)
|
|
int snd_pcm_sw_params_malloc(snd_pcm_sw_params_t **ptr);
|
|
void snd_pcm_sw_params_free(snd_pcm_sw_params_t *obj);
|
|
void snd_pcm_sw_params_copy(snd_pcm_sw_params_t *dst, const snd_pcm_sw_params_t *src);
|
|
@@ -747,7 +747,7 @@ size_t snd_pcm_access_mask_sizeof(void);
|
|
* \brief allocate an empty #snd_pcm_access_mask_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_pcm_access_mask_alloca(ptr) do { assert(ptr); *ptr = (snd_pcm_access_mask_t *) alloca(snd_pcm_access_mask_sizeof()); memset(*ptr, 0, snd_pcm_access_mask_sizeof()); } while (0)
|
|
+#define snd_pcm_access_mask_alloca(ptr) __snd_alloca(ptr, snd_pcm_access_mask)
|
|
int snd_pcm_access_mask_malloc(snd_pcm_access_mask_t **ptr);
|
|
void snd_pcm_access_mask_free(snd_pcm_access_mask_t *obj);
|
|
void snd_pcm_access_mask_copy(snd_pcm_access_mask_t *dst, const snd_pcm_access_mask_t *src);
|
|
@@ -772,7 +772,7 @@ size_t snd_pcm_format_mask_sizeof(void);
|
|
* \brief allocate an empty #snd_pcm_format_mask_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_pcm_format_mask_alloca(ptr) do { assert(ptr); *ptr = (snd_pcm_format_mask_t *) alloca(snd_pcm_format_mask_sizeof()); memset(*ptr, 0, snd_pcm_format_mask_sizeof()); } while (0)
|
|
+#define snd_pcm_format_mask_alloca(ptr) __snd_alloca(ptr, snd_pcm_format_mask)
|
|
int snd_pcm_format_mask_malloc(snd_pcm_format_mask_t **ptr);
|
|
void snd_pcm_format_mask_free(snd_pcm_format_mask_t *obj);
|
|
void snd_pcm_format_mask_copy(snd_pcm_format_mask_t *dst, const snd_pcm_format_mask_t *src);
|
|
@@ -797,7 +797,7 @@ size_t snd_pcm_subformat_mask_sizeof(voi
|
|
* \brief allocate an empty #snd_pcm_subformat_mask_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_pcm_subformat_mask_alloca(ptr) do { assert(ptr); *ptr = (snd_pcm_subformat_mask_t *) alloca(snd_pcm_subformat_mask_sizeof()); memset(*ptr, 0, snd_pcm_subformat_mask_sizeof()); } while (0)
|
|
+#define snd_pcm_subformat_mask_alloca(ptr) __snd_alloca(ptr, snd_pcm_subformat_mask)
|
|
int snd_pcm_subformat_mask_malloc(snd_pcm_subformat_mask_t **ptr);
|
|
void snd_pcm_subformat_mask_free(snd_pcm_subformat_mask_t *obj);
|
|
void snd_pcm_subformat_mask_copy(snd_pcm_subformat_mask_t *dst, const snd_pcm_subformat_mask_t *src);
|
|
@@ -822,7 +822,7 @@ size_t snd_pcm_status_sizeof(void);
|
|
* \brief allocate an invalid #snd_pcm_status_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_pcm_status_alloca(ptr) do { assert(ptr); *ptr = (snd_pcm_status_t *) alloca(snd_pcm_status_sizeof()); memset(*ptr, 0, snd_pcm_status_sizeof()); } while (0)
|
|
+#define snd_pcm_status_alloca(ptr) __snd_alloca(ptr, snd_pcm_status)
|
|
int snd_pcm_status_malloc(snd_pcm_status_t **ptr);
|
|
void snd_pcm_status_free(snd_pcm_status_t *obj);
|
|
void snd_pcm_status_copy(snd_pcm_status_t *dst, const snd_pcm_status_t *src);
|
|
diff -r 9e2f117f24b9 include/rawmidi.h
|
|
--- a/include/rawmidi.h Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/include/rawmidi.h Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -93,7 +93,7 @@ size_t snd_rawmidi_info_sizeof(void);
|
|
* \brief allocate an invalid #snd_rawmidi_info_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_rawmidi_info_alloca(ptr) do { assert(ptr); *ptr = (snd_rawmidi_info_t *) alloca(snd_rawmidi_info_sizeof()); memset(*ptr, 0, snd_rawmidi_info_sizeof()); } while (0)
|
|
+#define snd_rawmidi_info_alloca(ptr) __snd_alloca(ptr, snd_rawmidi_info)
|
|
int snd_rawmidi_info_malloc(snd_rawmidi_info_t **ptr);
|
|
void snd_rawmidi_info_free(snd_rawmidi_info_t *obj);
|
|
void snd_rawmidi_info_copy(snd_rawmidi_info_t *dst, const snd_rawmidi_info_t *src);
|
|
@@ -116,7 +116,7 @@ size_t snd_rawmidi_params_sizeof(void);
|
|
* \brief allocate an invalid #snd_rawmidi_params_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_rawmidi_params_alloca(ptr) do { assert(ptr); *ptr = (snd_rawmidi_params_t *) alloca(snd_rawmidi_params_sizeof()); memset(*ptr, 0, snd_rawmidi_params_sizeof()); } while (0)
|
|
+#define snd_rawmidi_params_alloca(ptr) __snd_alloca(ptr, snd_rawmidi_params)
|
|
int snd_rawmidi_params_malloc(snd_rawmidi_params_t **ptr);
|
|
void snd_rawmidi_params_free(snd_rawmidi_params_t *obj);
|
|
void snd_rawmidi_params_copy(snd_rawmidi_params_t *dst, const snd_rawmidi_params_t *src);
|
|
@@ -133,7 +133,7 @@ size_t snd_rawmidi_status_sizeof(void);
|
|
* \brief allocate an invalid #snd_rawmidi_status_t using standard alloca
|
|
* \param ptr returned pointer
|
|
*/
|
|
-#define snd_rawmidi_status_alloca(ptr) do { assert(ptr); *ptr = (snd_rawmidi_status_t *) alloca(snd_rawmidi_status_sizeof()); memset(*ptr, 0, snd_rawmidi_status_sizeof()); } while (0)
|
|
+#define snd_rawmidi_status_alloca(ptr) __snd_alloca(ptr, snd_rawmidi_status)
|
|
int snd_rawmidi_status_malloc(snd_rawmidi_status_t **ptr);
|
|
void snd_rawmidi_status_free(snd_rawmidi_status_t *obj);
|
|
void snd_rawmidi_status_copy(snd_rawmidi_status_t *dst, const snd_rawmidi_status_t *src);
|
|
diff -r 9e2f117f24b9 include/seq.h
|
|
--- a/include/seq.h Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/include/seq.h Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -45,15 +45,6 @@ extern "C" {
|
|
|
|
/** Sequencer handle */
|
|
typedef struct _snd_seq snd_seq_t;
|
|
-
|
|
-#ifndef DOC_HIDDEN
|
|
-#define SND_ALLOCA(type,ptr) \
|
|
-do {\
|
|
- assert(ptr);\
|
|
- *ptr = (type##_t *)alloca(type##_sizeof());\
|
|
- memset(*ptr, 0, type##_sizeof());\
|
|
-} while (0)
|
|
-#endif
|
|
|
|
/**
|
|
* sequencer opening stream types
|
|
@@ -106,7 +97,7 @@ size_t snd_seq_system_info_sizeof(void);
|
|
size_t snd_seq_system_info_sizeof(void);
|
|
/** allocate a #snd_seq_system_info_t container on stack */
|
|
#define snd_seq_system_info_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_system_info, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_system_info)
|
|
int snd_seq_system_info_malloc(snd_seq_system_info_t **ptr);
|
|
void snd_seq_system_info_free(snd_seq_system_info_t *ptr);
|
|
void snd_seq_system_info_copy(snd_seq_system_info_t *dst, const snd_seq_system_info_t *src);
|
|
@@ -142,7 +133,7 @@ size_t snd_seq_client_info_sizeof(void);
|
|
size_t snd_seq_client_info_sizeof(void);
|
|
/** allocate a #snd_seq_client_info_t container on stack */
|
|
#define snd_seq_client_info_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_client_info, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_client_info)
|
|
int snd_seq_client_info_malloc(snd_seq_client_info_t **ptr);
|
|
void snd_seq_client_info_free(snd_seq_client_info_t *ptr);
|
|
void snd_seq_client_info_copy(snd_seq_client_info_t *dst, const snd_seq_client_info_t *src);
|
|
@@ -176,7 +167,7 @@ size_t snd_seq_client_pool_sizeof(void);
|
|
size_t snd_seq_client_pool_sizeof(void);
|
|
/** allocate a #snd_seq_client_pool_t container on stack */
|
|
#define snd_seq_client_pool_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_client_pool, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_client_pool)
|
|
int snd_seq_client_pool_malloc(snd_seq_client_pool_t **ptr);
|
|
void snd_seq_client_pool_free(snd_seq_client_pool_t *ptr);
|
|
void snd_seq_client_pool_copy(snd_seq_client_pool_t *dst, const snd_seq_client_pool_t *src);
|
|
@@ -265,7 +256,7 @@ size_t snd_seq_port_info_sizeof(void);
|
|
size_t snd_seq_port_info_sizeof(void);
|
|
/** allocate a #snd_seq_port_info_t container on stack */
|
|
#define snd_seq_port_info_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_port_info, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_port_info)
|
|
int snd_seq_port_info_malloc(snd_seq_port_info_t **ptr);
|
|
void snd_seq_port_info_free(snd_seq_port_info_t *ptr);
|
|
void snd_seq_port_info_copy(snd_seq_port_info_t *dst, const snd_seq_port_info_t *src);
|
|
@@ -323,7 +314,7 @@ size_t snd_seq_port_subscribe_sizeof(voi
|
|
size_t snd_seq_port_subscribe_sizeof(void);
|
|
/** allocate a #snd_seq_port_subscribe_t container on stack */
|
|
#define snd_seq_port_subscribe_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_port_subscribe, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_port_subscribe)
|
|
int snd_seq_port_subscribe_malloc(snd_seq_port_subscribe_t **ptr);
|
|
void snd_seq_port_subscribe_free(snd_seq_port_subscribe_t *ptr);
|
|
void snd_seq_port_subscribe_copy(snd_seq_port_subscribe_t *dst, const snd_seq_port_subscribe_t *src);
|
|
@@ -361,7 +352,7 @@ size_t snd_seq_query_subscribe_sizeof(vo
|
|
size_t snd_seq_query_subscribe_sizeof(void);
|
|
/** allocate a #snd_seq_query_subscribe_t container on stack */
|
|
#define snd_seq_query_subscribe_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_query_subscribe, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_query_subscribe)
|
|
int snd_seq_query_subscribe_malloc(snd_seq_query_subscribe_t **ptr);
|
|
void snd_seq_query_subscribe_free(snd_seq_query_subscribe_t *ptr);
|
|
void snd_seq_query_subscribe_copy(snd_seq_query_subscribe_t *dst, const snd_seq_query_subscribe_t *src);
|
|
@@ -411,7 +402,7 @@ size_t snd_seq_queue_info_sizeof(void);
|
|
size_t snd_seq_queue_info_sizeof(void);
|
|
/** allocate a #snd_seq_queue_info_t container on stack */
|
|
#define snd_seq_queue_info_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_queue_info, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_queue_info)
|
|
int snd_seq_queue_info_malloc(snd_seq_queue_info_t **ptr);
|
|
void snd_seq_queue_info_free(snd_seq_queue_info_t *ptr);
|
|
void snd_seq_queue_info_copy(snd_seq_queue_info_t *dst, const snd_seq_queue_info_t *src);
|
|
@@ -443,7 +434,7 @@ size_t snd_seq_queue_status_sizeof(void)
|
|
size_t snd_seq_queue_status_sizeof(void);
|
|
/** allocate a #snd_seq_queue_status_t container on stack */
|
|
#define snd_seq_queue_status_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_queue_status, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_queue_status)
|
|
int snd_seq_queue_status_malloc(snd_seq_queue_status_t **ptr);
|
|
void snd_seq_queue_status_free(snd_seq_queue_status_t *ptr);
|
|
void snd_seq_queue_status_copy(snd_seq_queue_status_t *dst, const snd_seq_queue_status_t *src);
|
|
@@ -461,7 +452,7 @@ size_t snd_seq_queue_tempo_sizeof(void);
|
|
size_t snd_seq_queue_tempo_sizeof(void);
|
|
/** allocate a #snd_seq_queue_tempo_t container on stack */
|
|
#define snd_seq_queue_tempo_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_queue_tempo, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_queue_tempo)
|
|
int snd_seq_queue_tempo_malloc(snd_seq_queue_tempo_t **ptr);
|
|
void snd_seq_queue_tempo_free(snd_seq_queue_tempo_t *ptr);
|
|
void snd_seq_queue_tempo_copy(snd_seq_queue_tempo_t *dst, const snd_seq_queue_tempo_t *src);
|
|
@@ -492,7 +483,7 @@ size_t snd_seq_queue_timer_sizeof(void);
|
|
size_t snd_seq_queue_timer_sizeof(void);
|
|
/** allocate a #snd_seq_queue_timer_t container on stack */
|
|
#define snd_seq_queue_timer_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_queue_timer, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_queue_timer)
|
|
int snd_seq_queue_timer_malloc(snd_seq_queue_timer_t **ptr);
|
|
void snd_seq_queue_timer_free(snd_seq_queue_timer_t *ptr);
|
|
void snd_seq_queue_timer_copy(snd_seq_queue_timer_t *dst, const snd_seq_queue_timer_t *src);
|
|
@@ -551,7 +542,7 @@ size_t snd_seq_remove_events_sizeof(void
|
|
size_t snd_seq_remove_events_sizeof(void);
|
|
/** allocate a #snd_seq_remove_events_t container on stack */
|
|
#define snd_seq_remove_events_alloca(ptr) \
|
|
- SND_ALLOCA(snd_seq_remove_events, ptr)
|
|
+ __snd_alloca(ptr, snd_seq_remove_events)
|
|
int snd_seq_remove_events_malloc(snd_seq_remove_events_t **ptr);
|
|
void snd_seq_remove_events_free(snd_seq_remove_events_t *ptr);
|
|
void snd_seq_remove_events_copy(snd_seq_remove_events_t *dst, const snd_seq_remove_events_t *src);
|
|
diff -r 9e2f117f24b9 include/timer.h
|
|
--- a/include/timer.h Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/include/timer.h Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -164,7 +164,7 @@ ssize_t snd_timer_read(snd_timer_t *hand
|
|
|
|
size_t snd_timer_id_sizeof(void);
|
|
/** allocate #snd_timer_id_t container on stack */
|
|
-#define snd_timer_id_alloca(ptr) do { assert(ptr); *ptr = (snd_timer_id_t *) alloca(snd_timer_id_sizeof()); memset(*ptr, 0, snd_timer_id_sizeof()); } while (0)
|
|
+#define snd_timer_id_alloca(ptr) __snd_alloca(ptr, snd_timer_id)
|
|
int snd_timer_id_malloc(snd_timer_id_t **ptr);
|
|
void snd_timer_id_free(snd_timer_id_t *obj);
|
|
void snd_timer_id_copy(snd_timer_id_t *dst, const snd_timer_id_t *src);
|
|
@@ -182,7 +182,7 @@ int snd_timer_id_get_subdevice(snd_timer
|
|
|
|
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)
|
|
+#define snd_timer_ginfo_alloca(ptr) __snd_alloca(ptr, snd_timer_ginfo)
|
|
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);
|
|
@@ -200,7 +200,7 @@ unsigned int snd_timer_ginfo_get_clients
|
|
|
|
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)
|
|
+#define snd_timer_info_alloca(ptr) __snd_alloca(ptr, snd_timer_info)
|
|
int snd_timer_info_malloc(snd_timer_info_t **ptr);
|
|
void snd_timer_info_free(snd_timer_info_t *obj);
|
|
void snd_timer_info_copy(snd_timer_info_t *dst, const snd_timer_info_t *src);
|
|
@@ -213,7 +213,7 @@ long snd_timer_info_get_resolution(snd_t
|
|
|
|
size_t snd_timer_params_sizeof(void);
|
|
/** allocate #snd_timer_params_t container on stack */
|
|
-#define snd_timer_params_alloca(ptr) do { assert(ptr); *ptr = (snd_timer_params_t *) alloca(snd_timer_params_sizeof()); memset(*ptr, 0, snd_timer_params_sizeof()); } while (0)
|
|
+#define snd_timer_params_alloca(ptr) __snd_alloca(ptr, snd_timer_params)
|
|
int snd_timer_params_malloc(snd_timer_params_t **ptr);
|
|
void snd_timer_params_free(snd_timer_params_t *obj);
|
|
void snd_timer_params_copy(snd_timer_params_t *dst, const snd_timer_params_t *src);
|
|
@@ -233,7 +233,7 @@ unsigned int snd_timer_params_get_filter
|
|
|
|
size_t snd_timer_status_sizeof(void);
|
|
/** allocate #snd_timer_status_t container on stack */
|
|
-#define snd_timer_status_alloca(ptr) do { assert(ptr); *ptr = (snd_timer_status_t *) alloca(snd_timer_status_sizeof()); memset(*ptr, 0, snd_timer_status_sizeof()); } while (0)
|
|
+#define snd_timer_status_alloca(ptr) __snd_alloca(ptr, snd_timer_status)
|
|
int snd_timer_status_malloc(snd_timer_status_t **ptr);
|
|
void snd_timer_status_free(snd_timer_status_t *obj);
|
|
void snd_timer_status_copy(snd_timer_status_t *dst, const snd_timer_status_t *src);
|
|
diff -r 9e2f117f24b9 src/Versions.in
|
|
--- a/src/Versions.in Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/src/Versions.in Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -296,3 +296,14 @@ ALSA_1.0.14 {
|
|
@SYMBOL_PREFIX@snd_device_name_free_hint;
|
|
@SYMBOL_PREFIX@snd_device_name_get_hint;
|
|
} ALSA_1.0.12;
|
|
+
|
|
+ALSA_1.0.16 {
|
|
+ global:
|
|
+ @SYMBOL_PREFIX@snd_tlv_parse_dB_info;
|
|
+ @SYMBOL_PREFIX@snd_tlv_get_dB_range;
|
|
+ @SYMBOL_PREFIX@snd_tlv_convert_to_dB;
|
|
+ @SYMBOL_PREFIX@snd_tlv_convert_from_dB;
|
|
+ @SYMBOL_PREFIX@snd_ctl_get_dB_range;
|
|
+ @SYMBOL_PREFIX@snd_ctl_convert_to_dB;
|
|
+ @SYMBOL_PREFIX@snd_ctl_convert_from_dB;
|
|
+} ALSA_1.0.14;
|
|
diff -r 9e2f117f24b9 src/control/Makefile.am
|
|
--- a/src/control/Makefile.am Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/src/control/Makefile.am Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -1,6 +1,6 @@ EXTRA_LTLIBRARIES = libcontrol.la
|
|
EXTRA_LTLIBRARIES = libcontrol.la
|
|
|
|
-libcontrol_la_SOURCES = cards.c namehint.c hcontrol.c \
|
|
+libcontrol_la_SOURCES = cards.c tlv.c namehint.c hcontrol.c \
|
|
control.c control_hw.c setup.c control_symbols.c
|
|
if BUILD_CTL_PLUGIN_SHM
|
|
libcontrol_la_SOURCES += control_shm.c
|
|
diff -r 9e2f117f24b9 src/control/tlv.c
|
|
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
|
|
+++ b/src/control/tlv.c Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -0,0 +1,429 @@
|
|
+/**
|
|
+ * \file control/tlv.c
|
|
+ * \brief dB conversion functions from control TLV information
|
|
+ * \author Takashi Iwai <tiwai@suse.de>
|
|
+ * \date 2007
|
|
+ */
|
|
+/*
|
|
+ * Control Interface - dB conversion functions from control TLV information
|
|
+ *
|
|
+ * Copyright (c) 2007 Takashi Iwai <tiwai@suse.de>
|
|
+ *
|
|
+ *
|
|
+ * 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 <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <unistd.h>
|
|
+#include <string.h>
|
|
+#ifndef HAVE_SOFT_FLOAT
|
|
+#include <math.h>
|
|
+#endif
|
|
+#include "control_local.h"
|
|
+
|
|
+#ifndef DOC_HIDDEN
|
|
+/* convert to index of integer array */
|
|
+#define int_index(size) (((size) + sizeof(int) - 1) / sizeof(int))
|
|
+/* max size of a TLV entry for dB information (including compound one) */
|
|
+#define MAX_TLV_RANGE_SIZE 256
|
|
+#endif
|
|
+
|
|
+/**
|
|
+ * \brief Parse TLV stream and retrieve dB information
|
|
+ * \param tlv the TLV source
|
|
+ * \param tlv_size the byte size of TLV source
|
|
+ * \param db_tlvp the pointer stored the dB TLV information
|
|
+ * \return the byte size of dB TLV information if found in the given
|
|
+ * TLV source, or a negative error code.
|
|
+ *
|
|
+ * This function parses the given TLV source and stores the TLV start
|
|
+ * point if the TLV information regarding dB conversion is found.
|
|
+ * The stored TLV pointer can be passed to the convesion functions
|
|
+ * #snd_tlv_convert_to_dB(), #snd_tlv_convert_from_dB() and
|
|
+ * #snd_tlv_get_dB_range().
|
|
+ */
|
|
+int snd_tlv_parse_dB_info(unsigned int *tlv,
|
|
+ unsigned int tlv_size,
|
|
+ unsigned int **db_tlvp)
|
|
+{
|
|
+ unsigned int type;
|
|
+ unsigned int size;
|
|
+ int err;
|
|
+
|
|
+ *db_tlvp = NULL;
|
|
+ type = tlv[0];
|
|
+ size = tlv[1];
|
|
+ tlv_size -= 2 * sizeof(int);
|
|
+ if (size > tlv_size) {
|
|
+ SNDERR("TLV size error");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ switch (type) {
|
|
+ case SND_CTL_TLVT_CONTAINER:
|
|
+ size = int_index(size) * sizeof(int);
|
|
+ tlv += 2;
|
|
+ while (size > 0) {
|
|
+ unsigned int len;
|
|
+ err = snd_tlv_parse_dB_info(tlv, size, db_tlvp);
|
|
+ if (err < 0)
|
|
+ return err; /* error */
|
|
+ if (err > 0)
|
|
+ return err; /* found */
|
|
+ len = int_index(tlv[1]) + 2;
|
|
+ size -= len * sizeof(int);
|
|
+ tlv += len;
|
|
+ }
|
|
+ break;
|
|
+ case SND_CTL_TLVT_DB_SCALE:
|
|
+#ifndef HAVE_SOFT_FLOAT
|
|
+ case SND_CTL_TLVT_DB_LINEAR:
|
|
+#endif
|
|
+ case SND_CTL_TLVT_DB_RANGE: {
|
|
+ unsigned int minsize;
|
|
+ if (type == SND_CTL_TLVT_DB_RANGE)
|
|
+ minsize = 4 * sizeof(int);
|
|
+ else
|
|
+ minsize = 2 * sizeof(int);
|
|
+ if (size < minsize) {
|
|
+ SNDERR("Invalid dB_scale TLV size");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ if (size > MAX_TLV_RANGE_SIZE) {
|
|
+ SNDERR("Too big dB_scale TLV size: %d", size);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ *db_tlvp = tlv;
|
|
+ return size + sizeof(int) * 2;
|
|
+ }
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ return -EINVAL; /* not found */
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Get the dB min/max values
|
|
+ * \param tlv the TLV source returned by #snd_tlv_parse_dB_info()
|
|
+ * \param rangemin the minimum value of the raw volume
|
|
+ * \param rangemax the maximum value of the raw volume
|
|
+ * \param min the pointer to store the minimum dB value (in 0.01dB unit)
|
|
+ * \param max the pointer to store the maximum dB value (in 0.01dB unit)
|
|
+ * \return 0 if successful, or a negative error code
|
|
+ */
|
|
+int snd_tlv_get_dB_range(unsigned int *tlv, long rangemin, long rangemax,
|
|
+ long *min, long *max)
|
|
+{
|
|
+ int err;
|
|
+
|
|
+ switch (tlv[0]) {
|
|
+ case SND_CTL_TLVT_DB_RANGE: {
|
|
+ unsigned int pos, len;
|
|
+ len = int_index(tlv[1]);
|
|
+ if (len > MAX_TLV_RANGE_SIZE)
|
|
+ return -EINVAL;
|
|
+ pos = 2;
|
|
+ while (pos + 4 <= len) {
|
|
+ long rmin, rmax;
|
|
+ rangemin = (int)tlv[pos];
|
|
+ rangemax = (int)tlv[pos + 1];
|
|
+ err = snd_tlv_get_dB_range(tlv + pos + 2,
|
|
+ rangemin, rangemax,
|
|
+ &rmin, &rmax);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ if (pos > 2) {
|
|
+ if (rmin < *min)
|
|
+ *min = rmin;
|
|
+ if (rmax > *max)
|
|
+ *max = rmax;
|
|
+ } else {
|
|
+ *min = rmin;
|
|
+ *max = rmax;
|
|
+ }
|
|
+ pos += int_index(tlv[pos + 3]) + 4;
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+ case SND_CTL_TLVT_DB_SCALE: {
|
|
+ int step;
|
|
+ *min = (int)tlv[2];
|
|
+ step = (tlv[3] & 0xffff);
|
|
+ *max = *min + (long)(step * (rangemax - rangemin));
|
|
+ return 0;
|
|
+ }
|
|
+ case SND_CTL_TLVT_DB_LINEAR:
|
|
+ *min = (int)tlv[2];
|
|
+ *max = (int)tlv[3];
|
|
+ return 0;
|
|
+ }
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Convert the given raw volume value to a dB gain
|
|
+ * \param tlv the TLV source returned by #snd_tlv_parse_dB_info()
|
|
+ * \param rangemin the minimum value of the raw volume
|
|
+ * \param rangemax the maximum value of the raw volume
|
|
+ * \param volume the raw volume value to convert
|
|
+ * \param db_gain the dB gain (in 0.01dB unit)
|
|
+ * \return 0 if successful, or a negative error code
|
|
+ */
|
|
+int snd_tlv_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax,
|
|
+ long volume, long *db_gain)
|
|
+{
|
|
+ switch (tlv[0]) {
|
|
+ case SND_CTL_TLVT_DB_RANGE: {
|
|
+ unsigned int pos, len;
|
|
+ len = int_index(tlv[1]);
|
|
+ if (len > MAX_TLV_RANGE_SIZE)
|
|
+ return -EINVAL;
|
|
+ pos = 2;
|
|
+ while (pos + 4 <= len) {
|
|
+ rangemin = (int)tlv[pos];
|
|
+ rangemax = (int)tlv[pos + 1];
|
|
+ if (volume >= rangemin && volume <= rangemax)
|
|
+ return snd_tlv_convert_to_dB(tlv + pos + 2,
|
|
+ rangemin, rangemax,
|
|
+ volume, db_gain);
|
|
+ pos += int_index(tlv[pos + 3]) + 4;
|
|
+ }
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ case SND_CTL_TLVT_DB_SCALE: {
|
|
+ int min, step, mute;
|
|
+ min = tlv[2];
|
|
+ step = (tlv[3] & 0xffff);
|
|
+ mute = (tlv[3] >> 16) & 1;
|
|
+ if (mute && volume == rangemin)
|
|
+ *db_gain = SND_CTL_TLV_DB_GAIN_MUTE;
|
|
+ else
|
|
+ *db_gain = (volume - rangemin) * step + min;
|
|
+ return 0;
|
|
+ }
|
|
+#ifndef HAVE_SOFT_FLOAT
|
|
+ case SND_CTL_TLVT_DB_LINEAR: {
|
|
+ int mindb = tlv[2];
|
|
+ int maxdb = tlv[3];
|
|
+ if (volume <= rangemin || rangemax <= rangemin)
|
|
+ *db_gain = mindb;
|
|
+ else if (volume >= rangemax)
|
|
+ *db_gain = maxdb;
|
|
+ else {
|
|
+ double val = (double)(volume - rangemin) /
|
|
+ (double)(rangemax - rangemin);
|
|
+ if (mindb <= SND_CTL_TLV_DB_GAIN_MUTE)
|
|
+ *db_gain = (long)(100.0 * 20.0 * log10(val)) +
|
|
+ maxdb;
|
|
+ else {
|
|
+ /* FIXME: precalculate and cache these values */
|
|
+ double lmin = pow(10.0, mindb/2000.0);
|
|
+ double lmax = pow(10.0, maxdb/2000.0);
|
|
+ val = (lmax - lmin) * val + lmin;
|
|
+ *db_gain = (long)(100.0 * 20.0 * log10(val));
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+#endif
|
|
+ }
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Convert from dB gain to the corresponding raw value
|
|
+ * \param tlv the TLV source returned by #snd_tlv_parse_dB_info()
|
|
+ * \param rangemin the minimum value of the raw volume
|
|
+ * \param rangemax the maximum value of the raw volume
|
|
+ * \param db_gain the dB gain to convert (in 0.01dB unit)
|
|
+ * \param value the pointer to store the converted raw volume value
|
|
+ * \param xdir the direction for round-up. The value is round up
|
|
+ * when this is positive.
|
|
+ * \return 0 if successful, or a negative error code
|
|
+ */
|
|
+int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax,
|
|
+ long db_gain, long *value, int xdir)
|
|
+{
|
|
+ switch (tlv[0]) {
|
|
+ case SND_CTL_TLVT_DB_RANGE: {
|
|
+ unsigned int pos, len;
|
|
+ len = int_index(tlv[1]);
|
|
+ if (len > MAX_TLV_RANGE_SIZE)
|
|
+ return -EINVAL;
|
|
+ pos = 2;
|
|
+ while (pos + 4 <= len) {
|
|
+ long dbmin, dbmax;
|
|
+ rangemin = (int)tlv[pos];
|
|
+ rangemax = (int)tlv[pos + 1];
|
|
+ if (!snd_tlv_get_dB_range(tlv + pos + 2,
|
|
+ rangemin, rangemax,
|
|
+ &dbmin, &dbmax) &&
|
|
+ db_gain >= dbmin && db_gain <= dbmax)
|
|
+ return snd_tlv_convert_from_dB(tlv + pos + 2,
|
|
+ rangemin, rangemax,
|
|
+ db_gain, value, xdir);
|
|
+ pos += int_index(tlv[pos + 3]) + 4;
|
|
+ }
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ case SND_CTL_TLVT_DB_SCALE: {
|
|
+ int min, step, max;
|
|
+ min = tlv[2];
|
|
+ step = (tlv[3] & 0xffff);
|
|
+ max = min + (int)(step * (rangemax - rangemin));
|
|
+ if (db_gain <= min)
|
|
+ *value = rangemin;
|
|
+ else if (db_gain >= max)
|
|
+ *value = rangemax;
|
|
+ else {
|
|
+ long v = (db_gain - min) * (rangemax - rangemin);
|
|
+ if (xdir > 0)
|
|
+ v += (max - min) - 1;
|
|
+ v = v / (max - min) + rangemin;
|
|
+ *value = v;
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+#ifndef HAVE_SOFT_FLOAT
|
|
+ case SND_CTL_TLVT_DB_LINEAR: {
|
|
+ int min, max;
|
|
+ min = tlv[2];
|
|
+ max = tlv[3];
|
|
+ if (db_gain <= min)
|
|
+ *value = rangemin;
|
|
+ else if (db_gain >= max)
|
|
+ *value = rangemax;
|
|
+ else {
|
|
+ /* FIXME: precalculate and cache vmin and vmax */
|
|
+ double vmin, vmax, v;
|
|
+ vmin = (min <= SND_CTL_TLV_DB_GAIN_MUTE) ? 0.0 :
|
|
+ pow(10.0, (double)min / 2000.0);
|
|
+ vmax = !max ? 1.0 : pow(10.0, (double)max / 2000.0);
|
|
+ v = pow(10.0, (double)db_gain / 2000.0);
|
|
+ v = (v - vmin) * (rangemax - rangemin) / (vmax - vmin);
|
|
+ if (xdir > 0)
|
|
+ v = ceil(v);
|
|
+ *value = (long)v + rangemin;
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+#endif
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+#ifndef DOC_HIDDEN
|
|
+#define TEMP_TLV_SIZE 4096
|
|
+struct tlv_info {
|
|
+ long minval, maxval;
|
|
+ unsigned int *tlv;
|
|
+ unsigned int buf[TEMP_TLV_SIZE];
|
|
+};
|
|
+#endif
|
|
+
|
|
+static int get_tlv_info(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
|
|
+ struct tlv_info *rec)
|
|
+{
|
|
+ snd_ctl_elem_info_t *info;
|
|
+ int err;
|
|
+
|
|
+ snd_ctl_elem_info_alloca(&info);
|
|
+ snd_ctl_elem_info_set_id(info, id);
|
|
+ err = snd_ctl_elem_info(ctl, info);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ if (!snd_ctl_elem_info_is_tlv_readable(info))
|
|
+ return -EINVAL;
|
|
+ if (snd_ctl_elem_info_get_type(info) != SND_CTL_ELEM_TYPE_INTEGER)
|
|
+ return -EINVAL;
|
|
+ rec->minval = snd_ctl_elem_info_get_min(info);
|
|
+ rec->maxval = snd_ctl_elem_info_get_max(info);
|
|
+ err = snd_ctl_elem_tlv_read(ctl, id, rec->buf, sizeof(rec->buf));
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ err = snd_tlv_parse_dB_info(rec->buf, sizeof(rec->buf), &rec->tlv);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Get the dB min/max values on the given control element
|
|
+ * \param ctl the control handler
|
|
+ * \param id the element id
|
|
+ * \param volume the raw volume value to convert
|
|
+ * \param min the pointer to store the minimum dB value (in 0.01dB unit)
|
|
+ * \param max the pointer to store the maximum dB value (in 0.01dB unit)
|
|
+ * \return 0 if successful, or a negative error code
|
|
+ */
|
|
+int snd_ctl_get_dB_range(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
|
|
+ long *min, long *max)
|
|
+{
|
|
+ struct tlv_info info;
|
|
+ int err;
|
|
+
|
|
+ err = get_tlv_info(ctl, id, &info);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ return snd_tlv_get_dB_range(info.tlv, info.minval, info.maxval,
|
|
+ min, max);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Convert the volume value to dB on the given control element
|
|
+ * \param ctl the control handler
|
|
+ * \param id the element id
|
|
+ * \param volume the raw volume value to convert
|
|
+ * \param db_gain the dB gain (in 0.01dB unit)
|
|
+ * \return 0 if successful, or a negative error code
|
|
+ */
|
|
+int snd_ctl_convert_to_dB(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
|
|
+ long volume, long *db_gain)
|
|
+{
|
|
+ struct tlv_info info;
|
|
+ int err;
|
|
+
|
|
+ err = get_tlv_info(ctl, id, &info);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ return snd_tlv_convert_to_dB(info.tlv, info.minval, info.maxval,
|
|
+ volume, db_gain);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * \brief Convert from dB gain to the raw volume value on the given control element
|
|
+ * \param ctl the control handler
|
|
+ * \param id the element id
|
|
+ * \param db_gain the dB gain to convert (in 0.01dB unit)
|
|
+ * \param value the pointer to store the converted raw volume value
|
|
+ * \param xdir the direction for round-up. The value is round up
|
|
+ * when this is positive.
|
|
+ * \return 0 if successful, or a negative error code
|
|
+ */
|
|
+int snd_ctl_convert_from_dB(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
|
|
+ long db_gain, long *value, int xdir)
|
|
+{
|
|
+ struct tlv_info info;
|
|
+ int err;
|
|
+
|
|
+ err = get_tlv_info(ctl, id, &info);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ return snd_tlv_convert_from_dB(info.tlv, info.minval, info.maxval,
|
|
+ db_gain, value, xdir);
|
|
+}
|
|
diff -r 9e2f117f24b9 src/error.c
|
|
--- a/src/error.c Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/src/error.c Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -135,8 +135,11 @@ static void snd_err_msg_default(const ch
|
|
fprintf(stderr, ": %s", snd_strerror(err));
|
|
putc('\n', stderr);
|
|
va_end(arg);
|
|
- if (! strcmp(verbose, "assert") || atoi(verbose) > 1)
|
|
+#ifdef ALSA_DEBUG_ASSERT
|
|
+ verbose = getenv("LIBASOUND_DEBUG_ASSERT");
|
|
+ if (verbose && *verbose)
|
|
assert(0);
|
|
+#endif
|
|
}
|
|
|
|
/**
|
|
diff -r 9e2f117f24b9 src/mixer/simple_none.c
|
|
--- a/src/mixer/simple_none.c Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/src/mixer/simple_none.c Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -35,6 +35,7 @@
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
+#include <assert.h>
|
|
#include <math.h>
|
|
#include <alsa/asoundlib.h>
|
|
#include "mixer_simple.h"
|
|
@@ -1068,150 +1069,13 @@ static int get_volume_ops(snd_mixer_elem
|
|
|
|
static int init_db_range(snd_hctl_elem_t *ctl, struct selem_str *rec);
|
|
|
|
-/* convert to index of integer array */
|
|
-#ifndef DOC_HIDDEN
|
|
-#define int_index(size) (((size) + sizeof(int) - 1) / sizeof(int))
|
|
-#endif
|
|
-
|
|
-/* max size of a TLV entry for dB information (including compound one) */
|
|
-#ifndef DOC_HIDDEN
|
|
-#define MAX_TLV_RANGE_SIZE 256
|
|
-#endif
|
|
-
|
|
-/* parse TLV stream and retrieve dB information
|
|
- * return 0 if successly found and stored to rec,
|
|
- * return 1 if no information is found,
|
|
- * or return a negative error code
|
|
- */
|
|
-static int parse_db_range(struct selem_str *rec, unsigned int *tlv,
|
|
- unsigned int tlv_size)
|
|
-{
|
|
- unsigned int type;
|
|
- unsigned int size;
|
|
- int err;
|
|
-
|
|
- type = tlv[0];
|
|
- size = tlv[1];
|
|
- tlv_size -= 2 * sizeof(int);
|
|
- if (size > tlv_size) {
|
|
- SNDERR("TLV size error");
|
|
- return -EINVAL;
|
|
- }
|
|
- switch (type) {
|
|
- case SND_CTL_TLVT_CONTAINER:
|
|
- size = int_index(size) * sizeof(int);
|
|
- tlv += 2;
|
|
- while (size > 0) {
|
|
- unsigned int len;
|
|
- err = parse_db_range(rec, tlv, size);
|
|
- if (err <= 0)
|
|
- return err; /* error or found dB */
|
|
- len = int_index(tlv[1]) + 2;
|
|
- size -= len * sizeof(int);
|
|
- tlv += len;
|
|
- }
|
|
- break;
|
|
- case SND_CTL_TLVT_DB_SCALE:
|
|
-#ifndef HAVE_SOFT_FLOAT
|
|
- case SND_CTL_TLVT_DB_LINEAR:
|
|
-#endif
|
|
- case SND_CTL_TLVT_DB_RANGE: {
|
|
- unsigned int minsize;
|
|
- if (type == SND_CTL_TLVT_DB_RANGE)
|
|
- minsize = 4 * sizeof(int);
|
|
- else
|
|
- minsize = 2 * sizeof(int);
|
|
- if (size < minsize) {
|
|
- SNDERR("Invalid dB_scale TLV size");
|
|
- return -EINVAL;
|
|
- }
|
|
- if (size > MAX_TLV_RANGE_SIZE) {
|
|
- SNDERR("Too big dB_scale TLV size: %d", size);
|
|
- return -EINVAL;
|
|
- }
|
|
- rec->db_info = malloc(size + sizeof(int) * 2);
|
|
- if (! rec->db_info)
|
|
- return -ENOMEM;
|
|
- memcpy(rec->db_info, tlv, size + sizeof(int) * 2);
|
|
- return 0;
|
|
- }
|
|
- default:
|
|
- break;
|
|
- }
|
|
- return -EINVAL; /* not found */
|
|
-}
|
|
-
|
|
-/* convert the given raw volume value to a dB gain
|
|
- */
|
|
-
|
|
-static int do_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax,
|
|
- long volume, long *db_gain)
|
|
-{
|
|
- switch (tlv[0]) {
|
|
- case SND_CTL_TLVT_DB_RANGE: {
|
|
- unsigned int pos, len;
|
|
- len = int_index(tlv[1]);
|
|
- if (len > MAX_TLV_RANGE_SIZE)
|
|
- return -EINVAL;
|
|
- pos = 2;
|
|
- while (pos + 4 <= len) {
|
|
- rangemin = (int)tlv[pos];
|
|
- rangemax = (int)tlv[pos + 1];
|
|
- if (volume >= rangemin && volume <= rangemax)
|
|
- return do_convert_to_dB(tlv + pos + 2,
|
|
- rangemin, rangemax,
|
|
- volume, db_gain);
|
|
- pos += int_index(tlv[pos + 3]) + 4;
|
|
- }
|
|
- return -EINVAL;
|
|
- }
|
|
- case SND_CTL_TLVT_DB_SCALE: {
|
|
- int min, step, mute;
|
|
- min = tlv[2];
|
|
- step = (tlv[3] & 0xffff);
|
|
- mute = (tlv[3] >> 16) & 1;
|
|
- if (mute && volume == rangemin)
|
|
- *db_gain = SND_CTL_TLV_DB_GAIN_MUTE;
|
|
- else
|
|
- *db_gain = (volume - rangemin) * step + min;
|
|
- return 0;
|
|
- }
|
|
-#ifndef HAVE_SOFT_FLOAT
|
|
- case SND_CTL_TLVT_DB_LINEAR: {
|
|
- int mindb = tlv[2];
|
|
- int maxdb = tlv[3];
|
|
- if (volume <= rangemin || rangemax <= rangemin)
|
|
- *db_gain = mindb;
|
|
- else if (volume >= rangemax)
|
|
- *db_gain = maxdb;
|
|
- else {
|
|
- double val = (double)(volume - rangemin) /
|
|
- (double)(rangemax - rangemin);
|
|
- if (mindb <= SND_CTL_TLV_DB_GAIN_MUTE)
|
|
- *db_gain = (long)(100.0 * 20.0 * log10(val)) +
|
|
- maxdb;
|
|
- else {
|
|
- /* FIXME: precalculate and cache these values */
|
|
- double lmin = pow(10.0, mindb/2000.0);
|
|
- double lmax = pow(10.0, maxdb/2000.0);
|
|
- val = (lmax - lmin) * val + lmin;
|
|
- *db_gain = (long)(100.0 * 20.0 * log10(val));
|
|
- }
|
|
- }
|
|
- return 0;
|
|
- }
|
|
-#endif
|
|
- }
|
|
- return -EINVAL;
|
|
-}
|
|
-
|
|
static int convert_to_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
|
|
long volume, long *db_gain)
|
|
{
|
|
if (init_db_range(ctl, rec) < 0)
|
|
return -EINVAL;
|
|
- return do_convert_to_dB(rec->db_info, rec->min, rec->max,
|
|
- volume, db_gain);
|
|
+ return snd_tlv_convert_to_dB(rec->db_info, rec->min, rec->max,
|
|
+ volume, db_gain);
|
|
}
|
|
|
|
/* initialize dB range information, reading TLV via hcontrol
|
|
@@ -1221,6 +1085,8 @@ static int init_db_range(snd_hctl_elem_t
|
|
snd_ctl_elem_info_t *info;
|
|
unsigned int *tlv = NULL;
|
|
const unsigned int tlv_size = 4096;
|
|
+ unsigned int *dbrec;
|
|
+ int db_size;
|
|
|
|
if (rec->db_init_error)
|
|
return -EINVAL;
|
|
@@ -1237,8 +1103,13 @@ static int init_db_range(snd_hctl_elem_t
|
|
return -ENOMEM;
|
|
if (snd_hctl_elem_tlv_read(ctl, tlv, tlv_size) < 0)
|
|
goto error;
|
|
- if (parse_db_range(rec, tlv, tlv_size) < 0)
|
|
+ db_size = snd_tlv_parse_dB_info(tlv, tlv_size, &dbrec);
|
|
+ if (db_size < 0)
|
|
goto error;
|
|
+ rec->db_info = malloc(db_size);
|
|
+ if (!rec->db_info)
|
|
+ goto error;
|
|
+ memcpy(rec->db_info, dbrec, db_size);
|
|
free(tlv);
|
|
rec->db_initialized = 1;
|
|
return 0;
|
|
@@ -1269,59 +1140,13 @@ static selem_ctl_t *get_selem_ctl(selem_
|
|
return c;
|
|
}
|
|
|
|
-/* Get the dB min/max values
|
|
- */
|
|
-static int do_get_dB_range(unsigned int *tlv, long rangemin, long rangemax,
|
|
- long *min, long *max)
|
|
-{
|
|
- switch (tlv[0]) {
|
|
- case SND_CTL_TLVT_DB_RANGE: {
|
|
- unsigned int pos, len;
|
|
- len = int_index(tlv[1]);
|
|
- if (len > MAX_TLV_RANGE_SIZE)
|
|
- return -EINVAL;
|
|
- pos = 2;
|
|
- while (pos + 4 <= len) {
|
|
- long rmin, rmax;
|
|
- rangemin = (int)tlv[pos];
|
|
- rangemax = (int)tlv[pos + 1];
|
|
- do_get_dB_range(tlv + pos + 2, rangemin, rangemax,
|
|
- &rmin, &rmax);
|
|
- if (pos > 2) {
|
|
- if (rmin < *min)
|
|
- *min = rmin;
|
|
- if (rmax > *max)
|
|
- *max = rmax;
|
|
- } else {
|
|
- *min = rmin;
|
|
- *max = rmax;
|
|
- }
|
|
- pos += int_index(tlv[pos + 3]) + 4;
|
|
- }
|
|
- return 0;
|
|
- }
|
|
- case SND_CTL_TLVT_DB_SCALE: {
|
|
- int step;
|
|
- *min = (int)tlv[2];
|
|
- step = (tlv[3] & 0xffff);
|
|
- *max = *min + (long)(step * (rangemax - rangemin));
|
|
- return 0;
|
|
- }
|
|
- case SND_CTL_TLVT_DB_LINEAR:
|
|
- *min = (int)tlv[2];
|
|
- *max = (int)tlv[3];
|
|
- return 0;
|
|
- }
|
|
- return -EINVAL;
|
|
-}
|
|
-
|
|
static int get_dB_range(snd_hctl_elem_t *ctl, struct selem_str *rec,
|
|
long *min, long *max)
|
|
{
|
|
if (init_db_range(ctl, rec) < 0)
|
|
return -EINVAL;
|
|
|
|
- return do_get_dB_range(rec->db_info, rec->min, rec->max, min, max);
|
|
+ return snd_tlv_get_dB_range(rec->db_info, rec->min, rec->max, min, max);
|
|
}
|
|
|
|
static int get_dB_range_ops(snd_mixer_elem_t *elem, int dir,
|
|
@@ -1336,89 +1161,14 @@ static int get_dB_range_ops(snd_mixer_el
|
|
return get_dB_range(c->elem, &s->str[dir], min, max);
|
|
}
|
|
|
|
-/* Convert from dB gain to the corresponding raw value.
|
|
- * The value is round up when xdir > 0.
|
|
- */
|
|
-static int do_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax,
|
|
- long db_gain, long *value, int xdir)
|
|
-{
|
|
- switch (tlv[0]) {
|
|
- case SND_CTL_TLVT_DB_RANGE: {
|
|
- unsigned int pos, len;
|
|
- len = int_index(tlv[1]);
|
|
- if (len > MAX_TLV_RANGE_SIZE)
|
|
- return -EINVAL;
|
|
- pos = 2;
|
|
- while (pos + 4 <= len) {
|
|
- long dbmin, dbmax;
|
|
- rangemin = (int)tlv[pos];
|
|
- rangemax = (int)tlv[pos + 1];
|
|
- if (! do_get_dB_range(tlv + pos + 2, rangemin, rangemax,
|
|
- &dbmin, &dbmax) &&
|
|
- db_gain >= dbmin && db_gain <= dbmax)
|
|
- return do_convert_from_dB(tlv + pos + 2,
|
|
- rangemin, rangemax,
|
|
- db_gain, value, xdir);
|
|
- pos += int_index(tlv[pos + 3]) + 4;
|
|
- }
|
|
- return -EINVAL;
|
|
- }
|
|
- case SND_CTL_TLVT_DB_SCALE: {
|
|
- int min, step, max;
|
|
- min = tlv[2];
|
|
- step = (tlv[3] & 0xffff);
|
|
- max = min + (int)(step * (rangemax - rangemin));
|
|
- if (db_gain <= min)
|
|
- *value = rangemin;
|
|
- else if (db_gain >= max)
|
|
- *value = rangemax;
|
|
- else {
|
|
- long v = (db_gain - min) * (rangemax - rangemin);
|
|
- if (xdir > 0)
|
|
- v += (max - min) - 1;
|
|
- v = v / (max - min) + rangemin;
|
|
- *value = v;
|
|
- }
|
|
- return 0;
|
|
- }
|
|
-#ifndef HAVE_SOFT_FLOAT
|
|
- case SND_CTL_TLVT_DB_LINEAR: {
|
|
- int min, max;
|
|
- min = tlv[2];
|
|
- max = tlv[3];
|
|
- if (db_gain <= min)
|
|
- *value = rangemin;
|
|
- else if (db_gain >= max)
|
|
- *value = rangemax;
|
|
- else {
|
|
- /* FIXME: precalculate and cache vmin and vmax */
|
|
- double vmin, vmax, v;
|
|
- vmin = (min <= SND_CTL_TLV_DB_GAIN_MUTE) ? 0.0 :
|
|
- pow(10.0, (double)min / 2000.0);
|
|
- vmax = !max ? 1.0 : pow(10.0, (double)max / 2000.0);
|
|
- v = pow(10.0, (double)db_gain / 2000.0);
|
|
- v = (v - vmin) * (rangemax - rangemin) / (vmax - vmin);
|
|
- if (xdir > 0)
|
|
- v = ceil(v);
|
|
- *value = (long)v + rangemin;
|
|
- }
|
|
- return 0;
|
|
- }
|
|
-#endif
|
|
- default:
|
|
- break;
|
|
- }
|
|
- return -EINVAL;
|
|
-}
|
|
-
|
|
static int convert_from_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
|
|
long db_gain, long *value, int xdir)
|
|
{
|
|
if (init_db_range(ctl, rec) < 0)
|
|
return -EINVAL;
|
|
|
|
- return do_convert_from_dB(rec->db_info, rec->min, rec->max,
|
|
- db_gain, value, xdir);
|
|
+ return snd_tlv_convert_from_dB(rec->db_info, rec->min, rec->max,
|
|
+ db_gain, value, xdir);
|
|
}
|
|
|
|
static int get_dB_ops(snd_mixer_elem_t *elem,
|
|
diff -r 9e2f117f24b9 src/pcm/pcm_dmix.c
|
|
--- a/src/pcm/pcm_dmix.c Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/src/pcm/pcm_dmix.c Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -652,9 +652,10 @@ static int snd_pcm_dmix_close(snd_pcm_t
|
|
if (dmix->client)
|
|
snd_pcm_direct_client_discard(dmix);
|
|
shm_sum_discard(dmix);
|
|
- if (snd_pcm_direct_shm_discard(dmix))
|
|
- snd_pcm_direct_semaphore_discard(dmix);
|
|
- else
|
|
+ if (snd_pcm_direct_shm_discard(dmix)) {
|
|
+ if (snd_pcm_direct_semaphore_discard(dmix))
|
|
+ snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
|
|
+ } else
|
|
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
|
|
free(dmix->bindings);
|
|
pcm->private_data = NULL;
|
|
diff -r 9e2f117f24b9 src/pcm/pcm_params.c
|
|
--- a/src/pcm/pcm_params.c Mon Oct 15 10:36:46 2007 +0200
|
|
+++ b/src/pcm/pcm_params.c Fri Oct 26 02:01:39 2007 +0200
|
|
@@ -78,31 +78,14 @@ static inline int hw_is_interval(snd_pcm
|
|
var <= SND_PCM_HW_PARAM_LAST_INTERVAL;
|
|
}
|
|
|
|
-static inline snd_mask_t *hw_param_mask(snd_pcm_hw_params_t *params,
|
|
- snd_pcm_hw_param_t var)
|
|
-{
|
|
- assert(hw_is_mask(var));
|
|
- return (snd_mask_t*)¶ms->masks[var - SND_PCM_HW_PARAM_FIRST_MASK];
|
|
-}
|
|
+#define hw_param_mask(params,var) \
|
|
+ &((params)->masks[(var) - SND_PCM_HW_PARAM_FIRST_MASK])
|
|
|
|
-static inline snd_interval_t *hw_param_interval(snd_pcm_hw_params_t *params,
|
|
- snd_pcm_hw_param_t var)
|
|
-{
|
|
- assert(hw_is_interval(var));
|
|
- return ¶ms->intervals[var - SND_PCM_HW_PARAM_FIRST_INTERVAL];
|
|
-}
|
|
+#define hw_param_interval(params,var) \
|
|
+ &((params)->intervals[(var) - SND_PCM_HW_PARAM_FIRST_INTERVAL])
|
|
|
|
-static inline const snd_mask_t *hw_param_mask_c(const snd_pcm_hw_params_t *params,
|
|
- snd_pcm_hw_param_t var)
|
|
-{
|
|
- return (const snd_mask_t *)hw_param_mask((snd_pcm_hw_params_t*) params, var);
|
|
-}
|
|
-
|
|
-static inline const snd_interval_t *hw_param_interval_c(const snd_pcm_hw_params_t *params,
|
|
- snd_pcm_hw_param_t var)
|
|
-{
|
|
- return (const snd_interval_t *)hw_param_interval((snd_pcm_hw_params_t*) params, var);
|
|
-}
|
|
+#define hw_param_mask_c hw_param_mask
|
|
+#define hw_param_interval_c hw_param_interval
|
|
|
|
static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
|
|
{
|