diff options
author | Sean McNeil <sean.mcneil@windriver.com> | 2009-04-16 06:07:30 +0700 |
---|---|---|
committer | Sean McNeil <sean.mcneil@windriver.com> | 2009-04-16 06:07:30 +0700 |
commit | 0c6fdabac66a07a37a14d87022aff3dfb306218b (patch) | |
tree | 30d698a68ec33c5274a3aff6ea626dd5e4f625dc | |
parent | d9ca3222cff122312af6dd329063dd8fd6f40dcf (diff) | |
download | alsa_sound-0c6fdabac66a07a37a14d87022aff3dfb306218b.tar.gz |
Add new generic ALSA control interface
-rw-r--r-- | AudioHardwareALSA.cpp | 118 | ||||
-rw-r--r-- | AudioHardwareALSA.h | 13 |
2 files changed, 131 insertions, 0 deletions
diff --git a/AudioHardwareALSA.cpp b/AudioHardwareALSA.cpp index bce67ef..27ca979 100644 --- a/AudioHardwareALSA.cpp +++ b/AudioHardwareALSA.cpp @@ -1401,4 +1401,122 @@ status_t ALSAMixer::getPlaybackMuteState(uint32_t device, bool *state) // ---------------------------------------------------------------------------- +ALSAControl::ALSAControl(const char *device) +{ + snd_ctl_open(&mHandle, device, 0); +} + +ALSAControl::~ALSAControl() +{ + if (mHandle) snd_ctl_close(mHandle); +} + +status_t ALSAControl::get(const char *name, unsigned int &value, int index) +{ + if (!mHandle) return NO_INIT; + + snd_ctl_elem_id_t *id; + snd_ctl_elem_info_t *info; + snd_ctl_elem_value_t *control; + + snd_ctl_elem_id_alloca(&id); + snd_ctl_elem_info_alloca(&info); + snd_ctl_elem_value_alloca(&control); + + snd_ctl_elem_id_set_name(id, name); + snd_ctl_elem_info_set_id(info, id); + + int ret = snd_ctl_elem_info(mHandle, info); + if (ret < 0) return BAD_VALUE; + + snd_ctl_elem_info_get_id(info, id); + snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(info); + unsigned int count = snd_ctl_elem_info_get_count(info); + if ((unsigned int)index >= count) return BAD_VALUE; + + snd_ctl_elem_value_set_id(control, id); + + ret = snd_ctl_elem_read(mHandle, control); + if (ret < 0) return BAD_VALUE; + + switch (type) { + case SND_CTL_ELEM_TYPE_BOOLEAN: + value = snd_ctl_elem_value_get_boolean(control, index); + break; + case SND_CTL_ELEM_TYPE_INTEGER: + value = snd_ctl_elem_value_get_integer(control, index); + break; + case SND_CTL_ELEM_TYPE_INTEGER64: + value = snd_ctl_elem_value_get_integer64(control, index); + break; + case SND_CTL_ELEM_TYPE_ENUMERATED: + value = snd_ctl_elem_value_get_enumerated(control, index); + break; + case SND_CTL_ELEM_TYPE_BYTES: + value = snd_ctl_elem_value_get_byte(control, index); + break; + default: + return BAD_VALUE; + } + + return NO_ERROR; +} + +status_t ALSAControl::set(const char *name, unsigned int value, int index) +{ + if (!mHandle) return NO_INIT; + + snd_ctl_elem_id_t *id; + snd_ctl_elem_info_t *info; + snd_ctl_elem_value_t *control; + + snd_ctl_elem_id_alloca(&id); + snd_ctl_elem_info_alloca(&info); + snd_ctl_elem_value_alloca(&control); + + snd_ctl_elem_id_set_name(id, name); + snd_ctl_elem_info_set_id(info, id); + + int ret = snd_ctl_elem_info(mHandle, info); + if (ret < 0) return BAD_VALUE; + + snd_ctl_elem_info_get_id(info, id); + snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(info); + unsigned int count = snd_ctl_elem_info_get_count(info); + if ((unsigned int)index >= count) return BAD_VALUE; + + if (index == -1) + index = 0; // Range over all of them + else + count = index + 1; // Just do the one specified + + snd_ctl_elem_value_set_id(control, id); + + for (unsigned int i = index; i < count; i++) + switch (type) { + case SND_CTL_ELEM_TYPE_BOOLEAN: + snd_ctl_elem_value_set_boolean(control, i, value); + break; + case SND_CTL_ELEM_TYPE_INTEGER: + snd_ctl_elem_value_set_integer(control, i, value); + break; + case SND_CTL_ELEM_TYPE_INTEGER64: + snd_ctl_elem_value_set_integer64(control, i, value); + break; + case SND_CTL_ELEM_TYPE_ENUMERATED: + snd_ctl_elem_value_set_enumerated(control, i, value); + break; + case SND_CTL_ELEM_TYPE_BYTES: + snd_ctl_elem_value_set_byte(control, i, value); + break; + default: + break; + } + + ret = snd_ctl_elem_write(mHandle, control); + return (ret < 0) ? BAD_VALUE : NO_ERROR; +} + +// ---------------------------------------------------------------------------- + }; // namespace android diff --git a/AudioHardwareALSA.h b/AudioHardwareALSA.h index 56045ff..0568a1e 100644 --- a/AudioHardwareALSA.h +++ b/AudioHardwareALSA.h @@ -53,6 +53,19 @@ namespace android snd_mixer_t *mMixer[SND_PCM_STREAM_LAST+1]; }; + class ALSAControl + { + public: + ALSAControl(const char *device = "default"); + virtual ~ALSAControl(); + + status_t get(const char *name, unsigned int &value, int index = 0); + status_t set(const char *name, unsigned int value, int index = -1); + + private: + snd_ctl_t *mHandle; + }; + class ALSAStreamOps { public: |