/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include extern "C" { #include } namespace aidl::android::hardware::audio::core::alsa { class Mixer { public: explicit Mixer(int card); ~Mixer(); bool isValid() const { return mMixer != nullptr; } ndk::ScopedAStatus getMasterMute(bool* muted); ndk::ScopedAStatus getMasterVolume(float* volume); ndk::ScopedAStatus getMicGain(float* gain); ndk::ScopedAStatus getMicMute(bool* muted); ndk::ScopedAStatus getVolumes(std::vector* volumes); ndk::ScopedAStatus setMasterMute(bool muted); ndk::ScopedAStatus setMasterVolume(float volume); ndk::ScopedAStatus setMicGain(float gain); ndk::ScopedAStatus setMicMute(bool muted); ndk::ScopedAStatus setVolumes(const std::vector& volumes); private: enum Control { MASTER_SWITCH, MASTER_VOLUME, HW_VOLUME, MIC_SWITCH, MIC_GAIN, }; using ControlNamesAndExpectedCtlType = std::pair; using Controls = std::map; friend std::ostream& operator<<(std::ostream&, Control); static const std::map> kPossibleControls; static Controls initializeMixerControls(struct mixer* mixer); ndk::ScopedAStatus findControl(Control ctl, struct mixer_ctl** result); ndk::ScopedAStatus getMixerControlMute(Control ctl, bool* muted); ndk::ScopedAStatus getMixerControlVolume(Control ctl, float* volume); ndk::ScopedAStatus setMixerControlMute(Control ctl, bool muted); ndk::ScopedAStatus setMixerControlVolume(Control ctl, float volume); int getMixerControlPercent(struct mixer_ctl* ctl, std::vector* percents) REQUIRES(mMixerAccess); int getMixerControlValues(struct mixer_ctl* ctl, std::vector* values) REQUIRES(mMixerAccess); int setMixerControlPercent(struct mixer_ctl* ctl, int percent) REQUIRES(mMixerAccess); int setMixerControlPercent(struct mixer_ctl* ctl, const std::vector& percents) REQUIRES(mMixerAccess); int setMixerControlValue(struct mixer_ctl* ctl, int value) REQUIRES(mMixerAccess); // Since ALSA functions do not use internal locking, enforce thread safety at our level. std::mutex mMixerAccess; // The mixer object is owned by ALSA and will be released when the mixer is closed. struct mixer* const mMixer; // `mMixerControls` will only be initialized in constructor. After that, it will only be // read but not be modified. Each mixer_ctl object is owned by ALSA, it's life span is // the same as of the mixer itself. const Controls mMixerControls; }; } // namespace aidl::android::hardware::audio::core::alsa