1*4d7e907cSAndroid Build Coastguard Worker /* 2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project 3*4d7e907cSAndroid Build Coastguard Worker * 4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*4d7e907cSAndroid Build Coastguard Worker * 8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*4d7e907cSAndroid Build Coastguard Worker * 10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License. 15*4d7e907cSAndroid Build Coastguard Worker */ 16*4d7e907cSAndroid Build Coastguard Worker 17*4d7e907cSAndroid Build Coastguard Worker #pragma once 18*4d7e907cSAndroid Build Coastguard Worker 19*4d7e907cSAndroid Build Coastguard Worker #include <iostream> 20*4d7e907cSAndroid Build Coastguard Worker #include <map> 21*4d7e907cSAndroid Build Coastguard Worker #include <memory> 22*4d7e907cSAndroid Build Coastguard Worker #include <mutex> 23*4d7e907cSAndroid Build Coastguard Worker #include <string> 24*4d7e907cSAndroid Build Coastguard Worker #include <vector> 25*4d7e907cSAndroid Build Coastguard Worker 26*4d7e907cSAndroid Build Coastguard Worker #include <android-base/thread_annotations.h> 27*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_auto_utils.h> 28*4d7e907cSAndroid Build Coastguard Worker 29*4d7e907cSAndroid Build Coastguard Worker extern "C" { 30*4d7e907cSAndroid Build Coastguard Worker #include <tinyalsa/mixer.h> 31*4d7e907cSAndroid Build Coastguard Worker } 32*4d7e907cSAndroid Build Coastguard Worker 33*4d7e907cSAndroid Build Coastguard Worker namespace aidl::android::hardware::audio::core::alsa { 34*4d7e907cSAndroid Build Coastguard Worker 35*4d7e907cSAndroid Build Coastguard Worker class Mixer { 36*4d7e907cSAndroid Build Coastguard Worker public: 37*4d7e907cSAndroid Build Coastguard Worker explicit Mixer(int card); 38*4d7e907cSAndroid Build Coastguard Worker ~Mixer(); 39*4d7e907cSAndroid Build Coastguard Worker isValid()40*4d7e907cSAndroid Build Coastguard Worker bool isValid() const { return mMixer != nullptr; } 41*4d7e907cSAndroid Build Coastguard Worker 42*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus getMasterMute(bool* muted); 43*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus getMasterVolume(float* volume); 44*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus getMicGain(float* gain); 45*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus getMicMute(bool* muted); 46*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus getVolumes(std::vector<float>* volumes); 47*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus setMasterMute(bool muted); 48*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus setMasterVolume(float volume); 49*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus setMicGain(float gain); 50*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus setMicMute(bool muted); 51*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus setVolumes(const std::vector<float>& volumes); 52*4d7e907cSAndroid Build Coastguard Worker 53*4d7e907cSAndroid Build Coastguard Worker private: 54*4d7e907cSAndroid Build Coastguard Worker enum Control { 55*4d7e907cSAndroid Build Coastguard Worker MASTER_SWITCH, 56*4d7e907cSAndroid Build Coastguard Worker MASTER_VOLUME, 57*4d7e907cSAndroid Build Coastguard Worker HW_VOLUME, 58*4d7e907cSAndroid Build Coastguard Worker MIC_SWITCH, 59*4d7e907cSAndroid Build Coastguard Worker MIC_GAIN, 60*4d7e907cSAndroid Build Coastguard Worker }; 61*4d7e907cSAndroid Build Coastguard Worker using ControlNamesAndExpectedCtlType = std::pair<std::string, enum mixer_ctl_type>; 62*4d7e907cSAndroid Build Coastguard Worker using Controls = std::map<Control, struct mixer_ctl*>; 63*4d7e907cSAndroid Build Coastguard Worker 64*4d7e907cSAndroid Build Coastguard Worker friend std::ostream& operator<<(std::ostream&, Control); 65*4d7e907cSAndroid Build Coastguard Worker static const std::map<Control, std::vector<ControlNamesAndExpectedCtlType>> kPossibleControls; 66*4d7e907cSAndroid Build Coastguard Worker static Controls initializeMixerControls(struct mixer* mixer); 67*4d7e907cSAndroid Build Coastguard Worker 68*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus findControl(Control ctl, struct mixer_ctl** result); 69*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus getMixerControlMute(Control ctl, bool* muted); 70*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus getMixerControlVolume(Control ctl, float* volume); 71*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus setMixerControlMute(Control ctl, bool muted); 72*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus setMixerControlVolume(Control ctl, float volume); 73*4d7e907cSAndroid Build Coastguard Worker 74*4d7e907cSAndroid Build Coastguard Worker int getMixerControlPercent(struct mixer_ctl* ctl, std::vector<int>* percents) 75*4d7e907cSAndroid Build Coastguard Worker REQUIRES(mMixerAccess); 76*4d7e907cSAndroid Build Coastguard Worker int getMixerControlValues(struct mixer_ctl* ctl, std::vector<int>* values) 77*4d7e907cSAndroid Build Coastguard Worker REQUIRES(mMixerAccess); 78*4d7e907cSAndroid Build Coastguard Worker int setMixerControlPercent(struct mixer_ctl* ctl, int percent) REQUIRES(mMixerAccess); 79*4d7e907cSAndroid Build Coastguard Worker int setMixerControlPercent(struct mixer_ctl* ctl, const std::vector<int>& percents) 80*4d7e907cSAndroid Build Coastguard Worker REQUIRES(mMixerAccess); 81*4d7e907cSAndroid Build Coastguard Worker int setMixerControlValue(struct mixer_ctl* ctl, int value) REQUIRES(mMixerAccess); 82*4d7e907cSAndroid Build Coastguard Worker 83*4d7e907cSAndroid Build Coastguard Worker // Since ALSA functions do not use internal locking, enforce thread safety at our level. 84*4d7e907cSAndroid Build Coastguard Worker std::mutex mMixerAccess; 85*4d7e907cSAndroid Build Coastguard Worker // The mixer object is owned by ALSA and will be released when the mixer is closed. 86*4d7e907cSAndroid Build Coastguard Worker struct mixer* const mMixer; 87*4d7e907cSAndroid Build Coastguard Worker // `mMixerControls` will only be initialized in constructor. After that, it will only be 88*4d7e907cSAndroid Build Coastguard Worker // read but not be modified. Each mixer_ctl object is owned by ALSA, it's life span is 89*4d7e907cSAndroid Build Coastguard Worker // the same as of the mixer itself. 90*4d7e907cSAndroid Build Coastguard Worker const Controls mMixerControls; 91*4d7e907cSAndroid Build Coastguard Worker }; 92*4d7e907cSAndroid Build Coastguard Worker 93*4d7e907cSAndroid Build Coastguard Worker } // namespace aidl::android::hardware::audio::core::alsa 94