summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Farrugia <mark.farrugia@fiberdyne.com.au>2019-02-01 12:11:58 +1100
committerMark Farrugia <mark.farrugia@fiberdyne.com.au>2019-02-01 12:17:42 +1100
commite3d18ca279933147d0f2336fd3356958e18d133b (patch)
tree4116a03151ff4e93de79d2127c2350195a117681
parentc80e9f59a309f428c412c11bf207f186f89ce59e (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.h17
-rw-r--r--src/avirt-config.c101
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)
{