OSDN Git Service

Add new generic ALSA control interface
authorSean McNeil <sean.mcneil@windriver.com>
Wed, 15 Apr 2009 23:07:30 +0000 (06:07 +0700)
committerSean McNeil <sean.mcneil@windriver.com>
Wed, 15 Apr 2009 23:07:30 +0000 (06:07 +0700)
AudioHardwareALSA.cpp
AudioHardwareALSA.h

index bce67ef..27ca979 100644 (file)
@@ -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
index 56045ff..0568a1e 100644 (file)
@@ -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: