Mixer: Added voice volume and mic mute
authorPaul Kocialkowski <contact@paulk.fr>
Tue, 28 Aug 2012 22:17:45 +0000 (00:17 +0200)
committerPaul Kocialkowski <contact@paulk.fr>
Tue, 28 Aug 2012 22:21:25 +0000 (00:21 +0200)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
AudioHardware.cpp
AudioHardware.h
AudioStreamIn.h
AudioStreamOut.cpp
AudioStreamOut.h
Mixer.cpp
Mixer.h

index a9bb430..28a8c95 100644 (file)
@@ -39,6 +39,7 @@ AudioHardware::AudioHardware() :
        mInDevices(0),
        mOutDevices(0),
        mMode(AudioSystem::MODE_NORMAL),
+       mVoiceVolume(0),
        mMicMute(false)
 {
        LOGD("AudioHardware()");
@@ -67,12 +68,27 @@ status_t AudioHardware::setVoiceVolume(float volume)
 {
        LOGD("setVoiceVolume(%f)", volume);
 
+       mVoiceVolume = volume;
+
+       if(mOutput && mOutput->mMixer)
+               mOutput->mMixer->setVoiceVolume(volume);
+
        if(mRILInterface)
                mRILInterface->setVoiceVolume(volume);
 
        return NO_ERROR;
 }
 
+status_t AudioHardware::getVoiceVolume(float *volume)
+{
+       LOGD("getVoiceVolume()");
+
+       if(volume != NULL)
+               *volume = mVoiceVolume;
+
+       return NO_ERROR;
+}
+
 status_t AudioHardware::setMasterVolume(float volume)
 {
        LOGD("setMasterVolume(%f)", volume);
@@ -86,6 +102,9 @@ status_t AudioHardware::setMode(int mode)
 
        mMode = mode;
 
+       if(mode == AudioSystem::MODE_IN_CALL || mode == AudioSystem::MODE_IN_COMMUNICATION)
+               setVoiceVolume(mVoiceVolume);
+
        if(mRILInterface)
                mRILInterface->setMode(mode);
 
@@ -108,8 +127,11 @@ status_t AudioHardware::setMicMute(bool state)
 
        mMicMute = state;
 
+       if(mOutput && mOutput->mMixer)
+               mOutput->mMixer->setMicMute(state);
+
        if(mRILInterface)
-+              mRILInterface->setMicMute(state);
+               mRILInterface->setMicMute(state);
 
        return NO_ERROR;
 }
index f780007..b38f315 100644 (file)
@@ -40,6 +40,7 @@ public:
        virtual status_t initCheck();
 
        virtual status_t setVoiceVolume(float volume);
+       virtual status_t getVoiceVolume(float *volume);
        virtual status_t setMasterVolume(float volume);
 
        virtual status_t setMode(int mode);
@@ -79,6 +80,7 @@ private:
        unsigned int mOutDevices;
        unsigned int mInDevices;
        int mMode;
+       float mVoiceVolume;
        bool mMicMute;
 };
 
index 5b4a8aa..9361120 100644 (file)
@@ -57,12 +57,13 @@ public:
        virtual status_t setGain(float gain);
        virtual status_t dump(int fd, const Vector<String16>& args);
 
-private:
-       Mutex mLock;
        AudioHardware *mAudioHardware;
        TinyALSAAudioResampler *mAudioResampler;
        TinyALSAMixer *mMixer;
 
+private:
+       Mutex mLock;
+
        struct pcm *mPcm;
        struct pcm_config mPcmConfig;
 
index 48ac7a4..f57783d 100644 (file)
@@ -192,6 +192,7 @@ status_t TinyALSAAudioStreamOut::setParameters(const String8& keyValuePairs)
        String8 key = String8(AudioParameter::keyRouting);
        int device;
        int mode = AudioSystem::MODE_NORMAL;
+       float volume = 1;
 
        LOGD("TinyALSAAudioStreamOut::setParameters(%s)",
                keyValuePairs.string());
@@ -202,6 +203,10 @@ status_t TinyALSAAudioStreamOut::setParameters(const String8& keyValuePairs)
 
                mMixer->route(mDevice, mode);
 
+               mAudioHardware->getVoiceVolume(&volume);
+               if(mode == AudioSystem::MODE_IN_CALL || mode == AudioSystem::MODE_IN_COMMUNICATION)
+                       mAudioHardware->setVoiceVolume(volume);
+
                if(mAudioHardware->mRILInterface)
                        mAudioHardware->mRILInterface->setRouting(device);
 
index ab550c5..976ca45 100644 (file)
@@ -56,11 +56,12 @@ public:
        virtual status_t setVolume(float left, float right);
        virtual status_t dump(int fd, const Vector<String16>& args);
 
-private:
-       Mutex mLock;
        AudioHardware *mAudioHardware;
        TinyALSAMixer *mMixer;
 
+private:
+       Mutex mLock;
+
        struct pcm *mPcm;
        struct pcm_config mPcmConfig;
 
index ce6912b..04fd72d 100644 (file)
--- a/Mixer.cpp
+++ b/Mixer.cpp
@@ -206,6 +206,8 @@ void tinyalsa_mixer_device_list_free(struct list_head *list)
                mixer_data = (struct tinyalsa_mixer_data *) list->data;
                if(mixer_data->name)
                        free(mixer_data->name);
+               if(mixer_data->attr)
+                       free(mixer_data->attr);
                if(mixer_data->value)
                        free(mixer_data->value);
 
@@ -333,6 +335,32 @@ struct tinyalsa_mixer_device *tinyalsa_mixer_device_get_from_strings(
        }
 }
 
+struct tinyalsa_mixer_data *tinyalsa_mixer_data_get_from_attr(
+       struct list_head *list, char *data_attr)
+{
+       struct tinyalsa_mixer_data *mixer_data = NULL;
+
+       if(list == NULL || data_attr == NULL)
+               return NULL;
+
+       while(list) {
+               mixer_data = (struct tinyalsa_mixer_data *) list->data;
+
+               if(mixer_data != NULL && mixer_data->attr != NULL) {
+                       if(strcmp(mixer_data->attr, data_attr) == 0) {
+                               return mixer_data;
+                       }
+               }
+
+               if(list->next != NULL)
+                       list = list->next;
+               else
+                       break;
+       }
+
+       return NULL;
+}
+
 status_t tinyalsa_mixer_route_set(struct mixer *mixer,
        struct tinyalsa_mixer_data *mixer_data)
 {
@@ -386,7 +414,11 @@ status_t tinyalsa_mixer_route_set_list(struct mixer *mixer, struct list_head *li
        while(list) {
                mixer_data = (struct tinyalsa_mixer_data *) list->data;
 
-               status = tinyalsa_mixer_route_set(mixer, mixer_data);
+               if(mixer_data->attr && strcmp(mixer_data->attr, "voice-volume") == 0) {
+                       LOGD("Skipping voice volume control");
+               } else {
+                       status = tinyalsa_mixer_route_set(mixer, mixer_data);
+               }
 
                if(list->next != NULL)
                        list = list->next;
@@ -496,6 +528,72 @@ error:
        return BAD_VALUE;
 }
 
+status_t tinyalsa_mixer_set_voice_volume(struct mixer *mixer, float volume)
+{
+       struct tinyalsa_mixer_data *mixer_data = NULL;
+       int value, value_min, value_max, values_count;
+       char *value_string;
+       status_t status;
+
+       if(mixer_current_output_device == NULL) {
+               LOGE("Failed to set voice volume: no output device!");
+               return BAD_VALUE;
+       }
+
+       mixer_data = tinyalsa_mixer_data_get_from_attr(
+               mixer_current_output_device->enable, "voice-volume");
+
+       if(mixer_data == NULL || mixer_data->value == NULL) {
+               LOGE("Failed to set voice volume: no valid data!");
+               return BAD_VALUE;
+       }
+
+       values_count = sscanf(mixer_data->value, "%d-%d", &value_min, &value_max);
+       if(values_count != 2) {
+               LOGE("Failed to set voice volume: wrong value!");
+               return BAD_VALUE;
+       }
+
+       value = (value_max - value_min) * volume + value_min;
+
+       // Ugly workaround because string value is needed
+       value_string = mixer_data->value;
+       asprintf(&mixer_data->value, "%d", value);
+
+       status = tinyalsa_mixer_route_set(mixer, mixer_data);
+
+       free(mixer_data->value);
+       mixer_data->value = value_string;
+
+       return status;
+}
+
+status_t tinyalsa_mixer_set_mic_mute(struct mixer *mixer, int state)
+{
+       struct tinyalsa_mixer_data *mixer_data = NULL;
+       status_t status;
+
+       if(mixer_current_output_device == NULL) {
+               LOGE("Failed to set mic mute: no output device!");
+               return BAD_VALUE;
+       }
+
+       if(state) {
+               mixer_data = tinyalsa_mixer_data_get_from_attr(
+                       mixer_current_output_device->enable, "mic");
+       } else {
+               mixer_data = tinyalsa_mixer_data_get_from_attr(
+                       mixer_current_output_device->disable, "mic");
+       }
+
+       if(mixer_data == NULL || mixer_data->value == NULL) {
+               LOGE("Failed to set mic mute: no valid data!");
+               return BAD_VALUE;
+       }
+
+       return tinyalsa_mixer_route_set(mixer, mixer_data);
+}
+
 void tinyalsa_mixer_config_free(void)
 {
        int devices_names_count, modes_names_count;
@@ -541,6 +639,7 @@ void tinyalsa_mixer_config_start(void *data, const XML_Char *elem,
        const XML_Char *device_type = NULL;
        const XML_Char *device_mode = NULL;
        const XML_Char *data_name = NULL;
+       const XML_Char *data_attr = NULL;
        const XML_Char *data_value = NULL;
        int i;
 
@@ -601,6 +700,9 @@ void tinyalsa_mixer_config_start(void *data, const XML_Char *elem,
                        if(strcmp(attr[i], "name") == 0) {
                                i++;
                                data_name = attr[i];
+                       } else if(strcmp(attr[i], "attr") == 0) {
+                               i++;
+                               data_attr = attr[i];
                        } else if(strcmp(attr[i], "value") == 0) {
                                i++;
                                data_value = attr[i];
@@ -625,6 +727,9 @@ void tinyalsa_mixer_config_start(void *data, const XML_Char *elem,
                        mixer_data->value = strdup((char *) data_value);
                        mixer_data->type = MIXER_DATA_TYPE_CTL;
 
+                       if(data_attr)
+                               mixer_data->attr = strdup((char *) data_attr);
+
                        config_data->list = list;
                }
        }
@@ -758,4 +863,14 @@ status_t TinyALSAMixer::route(int type, int mode)
        return tinyalsa_mixer_route(mMixer, type, mode);
 }
 
+status_t TinyALSAMixer::setVoiceVolume(float volume)
+{
+       return tinyalsa_mixer_set_voice_volume(mMixer, volume);
+}
+
+status_t TinyALSAMixer::setMicMute(bool state)
+{
+       return tinyalsa_mixer_set_mic_mute(mMixer, state ? 1 : 0);
+}
+
 }; // namespace android
diff --git a/Mixer.h b/Mixer.h
index 9d5d9c8..09b736e 100644 (file)
--- a/Mixer.h
+++ b/Mixer.h
@@ -48,6 +48,7 @@ struct list_head {
 struct tinyalsa_mixer_data {
        char *name;
        char *value;
+       char *attr;
 
        tinyalsa_mixer_data_type type;
 };
@@ -84,6 +85,8 @@ public:
        virtual ~TinyALSAMixer();
        virtual status_t route(int type);
        virtual status_t route(int type, int mode);
+       status_t setVoiceVolume(float volume);
+       status_t setMicMute(bool state);
 
 private:
        struct mixer *mMixer;