Index: alsa-lib/include/control.h =================================================================== RCS file: /cvsroot/alsa/alsa-lib/include/control.h,v retrieving revision 1.101 diff -u -r1.101 control.h --- alsa-lib/include/control.h 9 Jun 2005 17:12:08 -0000 1.101 +++ alsa-lib/include/control.h 15 Dec 2005 18:17:27 -0000 @@ -53,6 +53,12 @@ /** CTL card info container */ typedef struct _snd_ctl_card_info snd_ctl_card_info_t; +/** CTL misc container */ +typedef struct _snd_ctl_misc snd_ctl_misc_t; + +/** CTL misc container */ +/* FIXME: Add */ + /** CTL element identifier container */ typedef struct _snd_ctl_elem_id snd_ctl_elem_id_t; @@ -212,6 +218,8 @@ int snd_ctl_poll_descriptors_revents(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents); int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe); int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info); +int snd_ctl_misc(snd_ctl_t *ctl, snd_ctl_misc_t *misc); +int snd_ctl_elem_get_db_scale(snd_ctl_t *ctl, unsigned int numid, long *db_scale); int snd_ctl_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t * list); int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info); int snd_ctl_elem_read(snd_ctl_t *ctl, snd_ctl_elem_value_t *value); @@ -485,6 +493,8 @@ int snd_hctl_elem_info(snd_hctl_elem_t *elem, snd_ctl_elem_info_t * info); int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value); int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value); +int snd_hctl_elem_misc(snd_hctl_elem_t *elem, snd_ctl_misc_t * misc); +int snd_hctl_elem_get_db_gain(snd_hctl_elem_t *elem, long volume, long *db_gain); snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem); Index: alsa-lib/include/local.h =================================================================== RCS file: /cvsroot/alsa/alsa-lib/include/local.h,v retrieving revision 1.44 diff -u -r1.44 local.h --- alsa-lib/include/local.h 29 Sep 2005 19:11:50 -0000 1.44 +++ alsa-lib/include/local.h 15 Dec 2005 18:17:27 -0000 @@ -46,6 +46,7 @@ #define _snd_pcm_status sndrv_pcm_status #define _snd_ctl_card_info sndrv_ctl_card_info +#define _snd_ctl_misc sndrv_ctl_misc #define _snd_ctl_elem_id sndrv_ctl_elem_id #define _snd_ctl_elem_list sndrv_ctl_elem_list #define _snd_ctl_elem_info sndrv_ctl_elem_info Index: alsa-lib/include/sound/asound.h =================================================================== RCS file: /cvsroot/alsa/alsa-lib/include/sound/asound.h,v retrieving revision 1.22 diff -u -r1.22 asound.h --- alsa-lib/include/sound/asound.h 16 Aug 2005 12:19:15 -0000 1.22 +++ alsa-lib/include/sound/asound.h 15 Dec 2005 18:17:27 -0000 @@ -847,6 +847,18 @@ unsigned char reserved[128-sizeof(struct timespec)]; }; +struct sndrv_ctl_misc { + unsigned int type; /* This should be uint32_t */ + unsigned int length; /* This should be uint32_t */ + unsigned char message[2040]; +}; + +#define SND_MISC_DB_SCALE 2 +/* Request */ +#define SND_MISC_ELEM_NUMID 2 +/* Response */ +#define SND_MISC_ELEM_DB_SCALE 2 + enum { SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int), SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct sndrv_ctl_card_info), @@ -862,6 +874,7 @@ SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct sndrv_ctl_elem_id), SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int), SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct sndrv_hwdep_info), + SNDRV_CTL_IOCTL_MISC = _IOR('U', 0x22, struct sndrv_ctl_misc), SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int), SNDRV_CTL_IOCTL_PCM_INFO = _IOWR('U', 0x31, struct sndrv_pcm_info), SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE = _IOW('U', 0x32, int), Index: alsa-lib/src/control/control.c =================================================================== RCS file: /cvsroot/alsa/alsa-lib/src/control/control.c,v retrieving revision 1.108 diff -u -r1.108 control.c --- alsa-lib/src/control/control.c 14 Nov 2005 10:18:22 -0000 1.108 +++ alsa-lib/src/control/control.c 15 Dec 2005 18:17:27 -0000 @@ -238,6 +238,138 @@ } /** + * \brief Get/Set misc related information + * \param ctl CTL handle + * \param misc pointer + * \return 0 on success otherwise a negative error code + */ +int snd_ctl_misc(snd_ctl_t *ctl, snd_ctl_misc_t *misc) +{ + int err; + assert(ctl && misc); + err = ctl->ops->misc(ctl, misc); + return err; +} + +static int uint32_to_message(snd_ctl_misc_t *misc, unsigned int value) +{ + unsigned int pointer = misc->length; + /* If unsigned int is a 64bit value, we will just ignore the high 32bits. */ + misc->message[pointer++] = value & 0xff; + misc->message[pointer++] = (value >> 8) & 0xff; + misc->message[pointer++] = (value >> 16) & 0xff; + misc->message[pointer++] = (value >> 24) & 0xff; + misc->length = pointer; + return 0; +} + +static int message_to_uint32(snd_ctl_misc_t *misc, unsigned int *value) +{ + unsigned int pointer = misc->length; + unsigned int val; + val = misc->message[pointer++] ; + val |= ((misc->message[pointer++]) << 8); + val |= ((misc->message[pointer++]) << 16); + val |= ((misc->message[pointer++]) << 24); + misc->length = pointer; + *value = val; + return 0; +} + +static int add_int32_tlv_to_container(snd_ctl_misc_t *misc, unsigned int type, unsigned int value) +{ + uint32_to_message(misc, type); + uint32_to_message(misc, 4); + uint32_to_message(misc, value); + /* FIXME: Check for overflows */ + return 0; +} + +static int container_open(snd_ctl_misc_t *misc, unsigned int type) +{ + uint32_to_message(misc, type); + uint32_to_message(misc, 0); /* This gets updated at container close */ + return 0; +} + +static int container_close(snd_ctl_misc_t *misc) +{ + unsigned int pointer = 4; + unsigned int value = misc->length; + misc->message[pointer++] = value & 0xff; + misc->message[pointer++] = (value >> 8) & 0xff; + misc->message[pointer++] = (value >> 16) & 0xff; + misc->message[pointer++] = (value >> 24) & 0xff; + return 0; +} + +/** + * \brief Get/Set misc related information + * \param ctl CTL handle + * \param misc pointer + * \return 0 on success otherwise a negative error code + * db_scale: index into volume to db gain function. + */ +int snd_ctl_elem_get_db_scale(snd_ctl_t *ctl, unsigned int numid, long *db_scale) +{ + snd_ctl_misc_t *misc; + int err=0; + unsigned int received_length; + unsigned int tlv_type; + unsigned int tlv_length; + unsigned int tlv_value; + unsigned int container_type; + unsigned int container_length; + + assert(ctl && db_scale); + misc=malloc(sizeof(*misc)); + if (misc == NULL) { + err = -ENOMEM; + return err; + } + misc->type=1; + misc->length=0; + container_open(misc, SND_MISC_DB_SCALE); + add_int32_tlv_to_container(misc, SND_MISC_ELEM_NUMID, numid); + container_close(misc); + + err = ctl->ops->misc(ctl, misc); + received_length = misc->length; + misc->length=0; + message_to_uint32(misc, &container_type); + switch (container_type) { + case SND_MISC_DB_SCALE: + message_to_uint32(misc, &container_length); + /* FIXME: Do more sanity checks here */ + message_to_uint32(misc, &tlv_type); + switch (tlv_type) { + case SND_MISC_ELEM_DB_SCALE: + message_to_uint32(misc, &tlv_length); + if (tlv_length != 4) { + err = -EINVAL; + goto _err; + } + message_to_uint32(misc, &tlv_value); + break; + default: + err = -EINVAL; + goto _err; + break; + } + break; + default: + err = -EINVAL; + goto _err; + } + *db_scale=tlv_value; + +_err: + free(misc); + return err; +} + + +/** * \brief Get a list of element identifiers * \param ctl CTL handle * \param list CTL element identifiers list pointer Index: alsa-lib/src/control/control_hw.c =================================================================== RCS file: /cvsroot/alsa/alsa-lib/src/control/control_hw.c,v retrieving revision 1.43 diff -u -r1.43 control_hw.c --- alsa-lib/src/control/control_hw.c 9 Jun 2005 17:14:22 -0000 1.43 +++ alsa-lib/src/control/control_hw.c 15 Dec 2005 18:17:27 -0000 @@ -128,6 +128,16 @@ return 0; } +static int snd_ctl_hw_misc(snd_ctl_t *handle, snd_ctl_misc_t *misc) +{ + snd_ctl_hw_t *hw = handle->private_data; + if (ioctl(hw->fd, SNDRV_CTL_IOCTL_MISC, misc) < 0) { + //SYSERR("SNDRV_CTL_IOCTL_MISC failed"); + return -errno; + } + return 0; +} + static int snd_ctl_hw_elem_list(snd_ctl_t *handle, snd_ctl_elem_list_t *list) { snd_ctl_hw_t *hw = handle->private_data; @@ -296,6 +306,7 @@ .async = snd_ctl_hw_async, .subscribe_events = snd_ctl_hw_subscribe_events, .card_info = snd_ctl_hw_card_info, + .misc = snd_ctl_hw_misc, .element_list = snd_ctl_hw_elem_list, .element_info = snd_ctl_hw_elem_info, .element_add = snd_ctl_hw_elem_add, Index: alsa-lib/src/control/control_local.h =================================================================== RCS file: /cvsroot/alsa/alsa-lib/src/control/control_local.h,v retrieving revision 1.31 diff -u -r1.31 control_local.h --- alsa-lib/src/control/control_local.h 9 Jun 2005 17:09:33 -0000 1.31 +++ alsa-lib/src/control/control_local.h 15 Dec 2005 18:17:27 -0000 @@ -27,6 +27,7 @@ int (*async)(snd_ctl_t *handle, int sig, pid_t pid); int (*subscribe_events)(snd_ctl_t *handle, int subscribe); int (*card_info)(snd_ctl_t *handle, snd_ctl_card_info_t *info); + int (*misc)(snd_ctl_t *handle, snd_ctl_misc_t *info); int (*element_list)(snd_ctl_t *handle, snd_ctl_elem_list_t *list); int (*element_info)(snd_ctl_t *handle, snd_ctl_elem_info_t *info); int (*element_add)(snd_ctl_t *handle, snd_ctl_elem_info_t *info); Index: alsa-lib/src/control/hcontrol.c =================================================================== RCS file: /cvsroot/alsa/alsa-lib/src/control/hcontrol.c,v retrieving revision 1.36 diff -u -r1.36 hcontrol.c --- alsa-lib/src/control/hcontrol.c 28 Jun 2005 10:24:44 -0000 1.36 +++ alsa-lib/src/control/hcontrol.c 15 Dec 2005 18:17:27 -0000 @@ -759,6 +759,42 @@ } /** + * \brief Get misc information for an HCTL element + * \param elem HCTL element + * \param info HCTL element information + * \return 0 otherwise a negative error code on failure + */ +int snd_hctl_elem_get_db_gain(snd_hctl_elem_t *elem, long volume, long *db_gain) +{ + int err; + long db_scale; + assert(elem); + assert(elem->hctl); + if ((err = snd_ctl_elem_get_db_scale(elem->hctl->ctl, elem->id.numid, &db_scale)) < 0) + return err; + switch (db_scale) { + case 1: /* Scale from -51.50 dB to +12.00 dB in steps of 0.75 dB. 256 steps. */ + if (volume == 0) { + *db_gain=-9999999; /* Muted */ + break; + } + *db_gain=(volume * 25) - 5175; /* For ca0106 controls */ + break; + case 2: /* Scale from -39.60 dB to 0.00 dB in steps of 0.4 dB. 100 steps. */ + if (volume == 0) { + *db_gain=-9999999; /* Muted */ + break; + } + *db_gain=(volume * 40) - 4000; /* For emu10k1 dsp controls */ + break; + default: + *db_gain=-9999999; /* Muted */ + return 1; + } + return 0; +} + +/** * \brief Get information for an HCTL element * \param elem HCTL element * \param info HCTL element information Index: alsa-lib/src/mixer/simple_none.c =================================================================== RCS file: /cvsroot/alsa/alsa-lib/src/mixer/simple_none.c,v retrieving revision 1.8 diff -u -r1.8 simple_none.c --- alsa-lib/src/mixer/simple_none.c 2 Dec 2005 13:39:24 -0000 1.8 +++ alsa-lib/src/mixer/simple_none.c 15 Dec 2005 18:17:27 -0000 @@ -971,12 +971,36 @@ return 0; } -static int get_dB_ops(snd_mixer_elem_t *elem ATTRIBUTE_UNUSED, - int dir ATTRIBUTE_UNUSED, - snd_mixer_selem_channel_id_t channel ATTRIBUTE_UNUSED, - long *value ATTRIBUTE_UNUSED) +static int get_dB_ops(snd_mixer_elem_t *elem, + int dir, + snd_mixer_selem_channel_id_t channel, + long *value) { - return -ENXIO; + selem_none_t *s = snd_mixer_elem_get_private(elem); + selem_ctl_t *c; + int err=0; + int n; + long volume, db_gain; + if (dir==SM_PLAY) { + c = &s->ctls[CTL_PLAYBACK_VOLUME]; + if (c->type==2) { + if (get_volume_ops(elem, dir, channel, &volume)) + return -EINVAL; + if ((err = snd_hctl_elem_get_db_gain(c->elem, volume, &db_gain)) < 0) + goto _err; + } + } + //for (n=0;n<=CTL_LAST;n++) { + // c = &s->ctls[n]; + // printf("%d:c->inactive=%d\n",n, c->inactive); + //} + //misc=malloc(2048); + //if ((err = snd_hctl_misc(elem->ctl, misc)) < 0) + // return err; + //printf("misc=%p, *misc=%d\n",misc, (int) *misc); + *value=db_gain; +_err: + return err; } static int get_switch_ops(snd_mixer_elem_t *elem, int dir,