diff options
author | Mark Farrugia <mark.farrugia@fiberdyne.com.au> | 2019-02-01 12:11:58 +1100 |
---|---|---|
committer | Mark Farrugia <mark.farrugia@fiberdyne.com.au> | 2019-02-01 12:17:42 +1100 |
commit | e3d18ca279933147d0f2336fd3356958e18d133b (patch) | |
tree | 4116a03151ff4e93de79d2127c2350195a117681 | |
parent | c80e9f59a309f428c412c11bf207f186f89ce59e (diff) |
Add error checking macros, and initial support for volume control
Signed-off-by: Mark Farrugia <mark.farrugia@fiberdyne.com.au>
-rw-r--r-- | include/avirt/avirt.h | 17 | ||||
-rw-r--r-- | src/avirt-config.c | 101 |
2 files changed, 116 insertions, 2 deletions
diff --git a/include/avirt/avirt.h b/include/avirt/avirt.h index 92eb23c..f1c4060 100644 --- a/include/avirt/avirt.h +++ b/include/avirt/avirt.h @@ -71,4 +71,21 @@ int snd_avirt_pcm_info(const char *pcm_name, snd_pcm_info_t *pcm_info); * @return: The ALSA card index on success, negative ERRNO otherwise */ int snd_avirt_card_index_get(int avirt_idx); + +/** + * snd_avirt_ctl_set_volume - Set an ALSA mixer volume value + * @name: The ALSA volume control name to set + * @volume: The volume to set + * @return: 0 on success, negative ERRNO otherwise + */ +int snd_avirt_ctl_set_volume(const char *name, long volume); + +/** + * snd_avirt_ctl_set_volume - Get an ALSA mixer volume value + * @name: The ALSA volume control name to get + * @volume: Populate this with the gotten value + * @return: 0 on success, negative ERRNO otherwise + */ +int snd_avirt_ctl_get_volume(const char *name, long *volume); + #endif // _AVIRT_H_ diff --git a/src/avirt-config.c b/src/avirt-config.c index a4a8957..491249e 100644 --- a/src/avirt-config.c +++ b/src/avirt-config.c @@ -32,6 +32,9 @@ #define AVIRT_CONFIGFS_PATH_MAXLEN 64 #define AVIRT_DEVICE_PATH "/dev/snd/by-path/platform-snd_avirt" +/** + * Logging macros + */ #define AVIRT_ERROR(errmsg) \ fprintf(stderr, "AVIRT ERROR: %s\n", errmsg); #define AVIRT_ERROR_V(fmt, args...) \ @@ -46,6 +49,21 @@ #endif /** + * Error checking macros + */ +#define CHK_ERR(err, fmt, args...) \ + if (err < 0) { \ + AVIRT_ERROR_V("Returned error:%d, "fmt, err, ##args); \ + return err; \ + } +#define CHK_ERR_GOTO(err, goto_label, fmt, args...) \ + if (err < 0) { \ + AVIRT_ERROR_V("Returned error:%d, "fmt, err, ##args); \ + retval = err; \ + goto goto_label; \ + } + +/** * extracted IOCTLs from <alsa/asoundlib.h> */ #define _IOR_HACKED(type,nr,size) _IOC(_IOC_READ,(type),(nr),size) @@ -123,7 +141,44 @@ static int mount_configfs() return err; } -int snd_avirt_info_get_card(int idx) +static int find_mixer_selem(const char *name, snd_mixer_t **handle, + snd_mixer_elem_t **selem) +{ + int retval = 0; + snd_mixer_selem_id_t *sid; + char devpath[32]; + + if (card_index < 0) + card_index = snd_avirt_card_index_get(0); + sprintf(devpath, "hw:%d", card_index); + + CHK_ERR(snd_mixer_open(handle, 0), "Couldn't open ctl handle"); + CHK_ERR_GOTO(snd_mixer_attach(*handle, devpath), + close_handle, "Couldn't attach ctl card '%s'", devpath); + CHK_ERR_GOTO(snd_mixer_selem_register(*handle, NULL, NULL), + close_handle, "Couldn't register ctl handle"); + CHK_ERR_GOTO(snd_mixer_load(*handle), + close_handle, "Couldn't load ctl handle"); + + snd_mixer_selem_id_alloca(&sid); + snd_mixer_selem_id_set_index(sid, 0); + snd_mixer_selem_id_set_name(sid, name); + *selem = snd_mixer_find_selem(*handle, sid); + if (!(*selem)) + { + AVIRT_ERROR_V("Cannot open ctl '%s'", name); + retval = -1; + } + + return retval; + +close_handle: + retval = snd_mixer_close(*handle); + + return retval; +} + +int snd_avirt_card_index_get(int idx) { int open_dev, err = 0; snd_ctl_card_info_t *card_info; @@ -163,7 +218,7 @@ int snd_avirt_pcm_info(const char *pcm_name, snd_pcm_info_t *pcm_info) char name[32]; if (card_index < 0) - card_index = snd_avirt_info_get_card(0); /* TD MF: Dynamically get the AVIRT card number */ + card_index = snd_avirt_card_index_get(0); if (card_index < 0) return card_index; @@ -205,6 +260,48 @@ exit_ctl: return err; } +int snd_avirt_ctl_set_volume(const char *name, long volume) +{ + long min, max; + int retval = 0; + snd_mixer_t *handle; + snd_mixer_elem_t *selem; + + CHK_ERR(find_mixer_selem(name, &handle, &selem), ""); + + CHK_ERR_GOTO(snd_mixer_selem_get_playback_volume_range(selem, &min, &max), close_handle, ""); + CHK_ERR_GOTO(snd_mixer_selem_set_playback_volume(selem, 0, volume), + close_handle, "Couldn't set playback volume for ctl '%s'", name); + + AVIRT_DEBUG_V("CTLSET: ctl:%s volume:%ld", name, volume * max / 100); + +close_handle: + snd_mixer_close(handle); + + return retval; +} + +int snd_avirt_ctl_get_volume(const char *name, long *volume) +{ + long min, max; + int retval = 0; + snd_mixer_t *handle; + snd_mixer_elem_t *selem; + + CHK_ERR(find_mixer_selem(name, &handle, &selem), ""); + + CHK_ERR_GOTO(snd_mixer_selem_get_playback_volume_range(selem, &min, &max), close_handle, ""); + CHK_ERR_GOTO(snd_mixer_selem_get_playback_volume(selem, 0, volume), + close_handle, "Couldn't get playback volume for ctl '%s'", name); + + AVIRT_DEBUG_V("CTLGET: ctl:%s volume:%ld", name, *volume * max / 100); + +close_handle: + snd_mixer_close(handle); + + return retval; +} + int snd_avirt_stream_new(const char *name, unsigned int channels, int direction, const char *map) { |