~aleteoryx/muditaos

78f075712cd31836335d925ef094ab90873c5095 — Hubert Chrzaniuk 5 years ago 74e6051
[EGD-4023] Vibration - get values from DB (#807)

M module-audio/Audio/AudioCommon.cpp => module-audio/Audio/AudioCommon.cpp +11 -47
@@ 33,59 33,23 @@ namespace audio
        return utils::enumToString(setting);
    }

    const std::string str(const Setting &setting, const PlaybackType &playbackType, const Profile::Type &profileType)
    const std::string dbPath(const Setting &setting, const PlaybackType &playbackType, const Profile::Type &profileType)
    {
        std::stringstream ss;
        const auto typeStr = str(profileType);
        if (typeStr.empty()) {
            return "";
        }
        const auto op = str(playbackType);
        if (op.empty()) {
            ss << "audio/" << str(profileType) << "/" << str(setting);
        if (profileType == Profile::Type::Idle && playbackType == PlaybackType::None) {
            return std::string();
        }
        else {
            ss << "audio/" << str(profileType) << "/" << str(playbackType) << "/" << str(setting);
        }
        return ss.str();
    }

    const std::string str(const Setting &setting, const PlaybackType &playbackType, const bool headphonesInserted)
    {
        const auto playbackCall = (headphonesInserted) ? str(setting, playbackType, Profile::Type::PlaybackHeadphones)
                                                       : str(setting, playbackType, Profile::Type::PlaybackLoudspeaker);
        switch (playbackType) {
        case PlaybackType::None: {
            return "";
        }
        case PlaybackType::Multimedia: {
            return playbackCall;
        }
        case PlaybackType::Notifications: {
            return playbackCall;
        std::string path(audioDbPrefix);
        if (auto s = str(profileType); !s.empty()) {
            path.append(s + "/");
        }
        case PlaybackType::KeypadSound: {
            return playbackCall;
        if (auto s = str(playbackType); !s.empty()) {
            path.append(s + "/");
        }
        case PlaybackType::CallRingtone: {
            return playbackCall;
        }
        case PlaybackType::TextMessageRingtone: {
            return playbackCall;
        }
        }
        return "";
    }

    const std::string str(const Setting &setting, const PlaybackType &playbackType)
    {
        std::stringstream ss;
        const auto txtPlaybackType = str(playbackType);
        if (txtPlaybackType.empty()) {
            return "";
        if (auto s = str(setting); !s.empty()) {
            path.append(s);
        }
        ss << "audio/" << txtPlaybackType << "/" << str(setting);
        return ss.str();
        return path;
    }

    auto GetVolumeText(const audio::Volume &volume) -> const std::string

M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +5 -9
@@ 25,6 25,8 @@ namespace audio

    constexpr uint32_t audioOperationTimeout = 1000;

    static const std::string audioDbPrefix = "audio/";

    enum class Setting
    {
        Volume,


@@ 57,15 59,9 @@ namespace audio

    [[nodiscard]] const std::string str(const Setting &setting) noexcept;

    [[nodiscard]] const std::string str(const Setting &setting,
                                        const PlaybackType &playbackType,
                                        const Profile::Type &profileType);

    [[nodiscard]] const std::string str(const Setting &setting,
                                        const PlaybackType &playbackType,
                                        const bool headphonesInserted);

    [[nodiscard]] const std::string str(const Setting &setting, const PlaybackType &playbackType);
    [[nodiscard]] const std::string dbPath(const Setting &setting,
                                           const PlaybackType &playbackType,
                                           const Profile::Type &profileType);

    enum class EventType
    {

M module-audio/Audio/AudioMux.cpp => module-audio/Audio/AudioMux.cpp +5 -2
@@ 65,9 65,12 @@ namespace audio

    std::optional<AudioMux::Input *> AudioMux::GetActiveInput()
    {
        // first return active routing inputs
        if (auto routingInput = GetInput({Audio::State::Routing}); routingInput) {
            return routingInput;
        }
        for (auto &audioInput : audioInputs) {
            if (audioInput.audio->GetCurrentState() != Audio::State::Idle &&
                audioInput.audio->GetCurrentOperationState() == audio::Operation::State::Active) {
            if (audioInput.audio->GetCurrentState() != Audio::State::Idle) {
                return &audioInput;
            }
        }

M module-audio/Audio/AudioMux.hpp => module-audio/Audio/AudioMux.hpp +1 -1
@@ 78,7 78,7 @@ namespace audio
         */
        auto GetIdleInput() -> std::optional<Input *>;
        /**
         * Gets first Active input
         * Gets input, if possible routing one, otherwise first playback
         * @return nullopt if input not found
         */
        auto GetActiveInput() -> std::optional<Input *>;

M module-audio/Audio/Operation/PlaybackOperation.cpp => module-audio/Audio/Operation/PlaybackOperation.cpp +2 -2
@@ 45,11 45,11 @@ namespace audio
        constexpr audio::Volume defaultHeadphonesVolume  = 2;

        const auto dbLoudspeakerVolumePath =
            audio::str(audio::Setting::Volume, playbackType, audio::Profile::Type::PlaybackLoudspeaker);
            audio::dbPath(audio::Setting::Volume, playbackType, audio::Profile::Type::PlaybackLoudspeaker);
        const auto loudspeakerVolume = dbCallback(dbLoudspeakerVolumePath, defaultLoudspeakerVolume);

        const auto dbHeadphonesVolumePath =
            audio::str(audio::Setting::Volume, playbackType, audio::Profile::Type::PlaybackHeadphones);
            audio::dbPath(audio::Setting::Volume, playbackType, audio::Profile::Type::PlaybackHeadphones);
        const auto headphonesVolume = dbCallback(dbHeadphonesVolumePath, defaultHeadphonesVolume);

        availableProfiles.push_back(Profile::Create(Profile::Type::PlaybackLoudspeaker, nullptr, loudspeakerVolume));

M module-audio/Audio/Operation/RecorderOperation.cpp => module-audio/Audio/Operation/RecorderOperation.cpp +2 -2
@@ 52,11 52,11 @@ namespace audio
        constexpr audio::Gain defaultRecordingHeadsetGain    = 100;

        const auto dbRecordingOnBoardMicGainPath =
            audio::str(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RecordingBuiltInMic);
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RecordingBuiltInMic);
        const auto recordingOnBoardMicGain = dbCallback(dbRecordingOnBoardMicGainPath, defaultRecordingOnBoardMicGain);

        const auto dbRecordingHeadsetGainPath =
            audio::str(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RecordingHeadset);
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RecordingHeadset);
        const auto recordingHeadsetGain = dbCallback(dbRecordingHeadsetGainPath, defaultRecordingHeadsetGain);

        availableProfiles.push_back(

M module-audio/Audio/Operation/RouterOperation.cpp => module-audio/Audio/Operation/RouterOperation.cpp +6 -6
@@ 73,23 73,23 @@ namespace audio
        constexpr audio::Volume defaultRoutingHeadsetVolume      = 10;

        const auto dbRoutingEarspeakerGainPath =
            audio::str(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingEarspeaker);
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingEarspeaker);
        const auto routingEarspeakerGain = dbCallback(dbRoutingEarspeakerGainPath, defaultRoutingEarspeakerGain);
        const auto dbRoutingEarspeakerVolumePath =
            audio::str(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingEarspeaker);
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingEarspeaker);
        const auto routingEarspeakerVolume = dbCallback(dbRoutingEarspeakerVolumePath, defaultRoutingEarspeakerVolume);
        const auto dbRoutingSpeakerphoneGainPath =
            audio::str(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingSpeakerphone);
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingSpeakerphone);
        const auto routingSpeakerphoneGain = dbCallback(dbRoutingSpeakerphoneGainPath, defaultRoutingSpeakerphoneGain);
        const auto dbRoutingSpeakerphoneVolumePath =
            audio::str(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingSpeakerphone);
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingSpeakerphone);
        const auto routingSpeakerphoneVolume =
            dbCallback(dbRoutingSpeakerphoneVolumePath, defaultRoutingSpeakerphoneVolume);
        const auto dbRoutingHeadsetGainPath =
            audio::str(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingHeadset);
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingHeadset);
        const auto routingHeadsetGain = dbCallback(dbRoutingHeadsetGainPath, defaultRoutingHeadsetGain);
        const auto dbRoutingHeadsetVolumePath =
            audio::str(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingHeadset);
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingHeadset);
        const auto routingHeadsetVolume = dbCallback(dbRoutingHeadsetVolumePath, defaultRoutingHeadsetVolume);

        availableProfiles.push_back(

M module-audio/Audio/test/unittest_audio.cpp => module-audio/Audio/test/unittest_audio.cpp +4 -4
@@ 42,7 42,7 @@ TEST_CASE("Audio settings string creation")
{
    SECTION("Create volume string for playback loudspeaker, multimedia")
    {
        const auto str = audio::str(
        const auto str = audio::dbPath(
            audio::Setting::Volume, audio::PlaybackType::Multimedia, audio::Profile::Type::PlaybackLoudspeaker);
        REQUIRE_FALSE(str.empty());
        REQUIRE(str == "audio/PlaybackLoudspeaker/Multimedia/Volume");


@@ 51,7 51,7 @@ TEST_CASE("Audio settings string creation")
    SECTION("Create volume string for routing speakerphone")
    {
        const auto str =
            audio::str(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingSpeakerphone);
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingSpeakerphone);
        REQUIRE_FALSE(str.empty());
        REQUIRE(str == "audio/RoutingSpeakerphone/Volume");
    }


@@ 59,14 59,14 @@ TEST_CASE("Audio settings string creation")
    SECTION("Create gain string for recording built-in microphone")
    {
        const auto str =
            audio::str(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RecordingBuiltInMic);
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RecordingBuiltInMic);
        REQUIRE_FALSE(str.empty());
        REQUIRE(str == "audio/RecordingBuiltInMic/Gain");
    }

    SECTION("Create empty volume string when Idle")
    {
        const auto str = audio::str(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::Idle);
        const auto str = audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::Idle);
        REQUIRE(str.empty());
    }
}

M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +146 -103
@@ 23,8 23,8 @@ ServiceAudio::ServiceAudio()
      audioMux([this](auto... params) { return this->AsyncCallback(params...); },
               [this](auto... params) { return this->DbCallback(params...); })
{
    busChannels.push_back(sys::BusChannels::ServiceAudioNotifications);
    LOG_INFO("[ServiceAudio] Initializing");
    busChannels.push_back(sys::BusChannels::ServiceAudioNotifications);
}

ServiceAudio::~ServiceAudio()


@@ 34,6 34,70 @@ ServiceAudio::~ServiceAudio()

sys::ReturnCodes ServiceAudio::InitHandler()
{
    static const std::string defaultVolumeHigh = "10";
    static const std::string defaultVolumeLow  = "2";
    static const std::string defaultTrue       = "1";
    static const std::string defaultFalse      = "0";

    static const int IdxPath  = 0;
    static const int IdxValue = 1;

    const static std::vector<std::vector<std::string>> defaultSettings = {

        // PLAYBACK
        {dbPath(Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackBTA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackBTA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackBTA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackBTA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackBTA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        // ROUTING
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingBTHeadset), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingEarspeaker), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingSpeakerphone), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadset), "50"},

        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingBTHeadset), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingEarspeaker), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadphones), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingSpeakerphone), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadset), defaultVolumeHigh},

        // MISC
        {dbPath(Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle), defaultFalse},
        {dbPath(Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle), defaultFalse},
        {dbPath(Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle), defaultTrue},

        {dbPath(Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle), defaultTrue},
        {dbPath(Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle), defaultTrue},
    };

    for (const auto &defaultSet : defaultSettings) {
        addOrIgnoreEntry(defaultSet[IdxPath], defaultSet[IdxValue]);
    }

    return sys::ReturnCodes::Success;
}



@@ 92,14 156,18 @@ static void ExtVibrationStop()
{
    LOG_ERROR("[Vibration] - Unimplemented - vibration stop");
}
// below static members will be replaced by accessors to DB entries
static bool IsVibrationEnabled(const audio::PlaybackType &type)

bool ServiceAudio::IsVibrationEnabled(const audio::PlaybackType &type)
{
    return true;
    auto isEnabled = utils::getValue<audio::Vibrate>(
        getSetting(Setting::EnableVibration, Profile::Type::Idle, PlaybackType::Multimedia));
    return isEnabled;
}
static bool IsPlaybackEnabled(const audio::PlaybackType &type)
bool ServiceAudio::IsPlaybackEnabled(const audio::PlaybackType &type)
{
    return true;
    auto isEnabled = utils::getValue<audio::EnableSound>(
        getSetting(Setting::EnableSound, Profile::Type::Idle, PlaybackType::Multimedia));
    return isEnabled;
}

ServiceAudio::VibrationType ServiceAudio::GetVibrationType(const audio::PlaybackType &type)


@@ 269,6 337,13 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleSendEvent(std::shared_
        return std::make_unique<AudioResponseMessage>(RetCode::OperationNotSet);
    }

    if (evt->getType() == EventType::HeadphonesPlugin) {
        headphonesInserted = true;
    }
    else if (evt->getType() == EventType::HeadphonesUnplug) {
        headphonesInserted = false;
    }

    auto retVal = input.value()->audio->SendEvent(evt);
    return std::make_unique<AudioEventResponse>(retVal);
}


@@ 377,7 452,7 @@ sys::Message_t ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sys::Re
    sys::Message_t responseMsg;

    auto &msgType = typeid(*msgl);
    LOG_DEBUG("msgType %d", static_cast<int>(msgl->messageType));
    LOG_DEBUG("msgType %d %s", static_cast<int>(msgl->messageType), msgType.name());

    if (msgType == typeid(AudioNotificationMessage)) {
        auto *msg = static_cast<AudioNotificationMessage *>(msgl);


@@ 441,7 516,7 @@ sys::Message_t ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sys::Re
    }
}

void ServiceAudio::updateDbValue(const std::string &path, const audio::Setting &setting, const std::string &value)
void ServiceAudio::updateDbValue(const std::string &path, const std::string &value)
{
    if (path.empty()) {
        return;


@@ 453,126 528,94 @@ void ServiceAudio::updateDbValue(const std::string &path, const audio::Setting &
    DBServiceAPI::GetQuery(this, db::Interface::Name::Settings_v2, std::move(query));
}

void ServiceAudio::updateDbValue(const audio::Operation &currentOperation,
                                 const audio::Setting &setting,
                                 const uint32_t &value)
std::string ServiceAudio::getSetting(const Setting &setting,
                                     const Profile::Type &profileType,
                                     const PlaybackType &playbackType)
{
    const auto currentProfile = currentOperation.GetProfile();
    const std::string defaultValue = {};
    auto targetProfile             = profileType;
    auto targetPlayback            = playbackType;

    auto dbPath = audio::str(setting, currentOperation.GetPlaybackType(), currentProfile->GetType());
    updateDbValue(dbPath, setting, std::to_string(value));
}
    if (profileType == Profile::Type::Idle && playbackType == PlaybackType::None) {
        if (const auto activeInput = audioMux.GetActiveInput(); activeInput.has_value()) {
            const auto &currentOperation    = (*activeInput)->audio->GetCurrentOperation();
            const auto &currentProfile      = currentOperation.GetProfile()->GetType();
            const auto &currentPlaybackType = (*activeInput)->audio->GetCurrentOperationPlaybackType();

void ServiceAudio::updateDbValue(const audio::Operation &currentOperation,
                                 const audio::Setting &setting,
                                 const bool &value)
{
    auto dbPath = audio::str(setting, currentOperation.GetPlaybackType());
    updateDbValue(dbPath, setting, std::to_string(value));
}

void ServiceAudio::setSetting(const audio::Setting &setting,
                              const std::string &value,
                              const audio::Profile::Type &profileType,
                              const audio::PlaybackType &playbackType)
{
    if (setting == audio::Setting::EnableVibration || setting == audio::Setting::EnableSound) {
        const auto path = audio::str(setting, playbackType);
        addOrIgnoreEntry(path, value);
        updateDbValue(path, setting, value);
    }
    else {
        if (profileType == Profile::Type::Idle) {
            setCurrentSetting(setting, value);
            return;
            targetProfile  = currentProfile;
            targetPlayback = currentPlaybackType;
        }
        else if (setting == Setting::Volume) {
            targetProfile = headphonesInserted ? Profile::Type::PlaybackHeadphones : Profile::Type::PlaybackLoudspeaker;
            targetPlayback = PlaybackType::CallRingtone;
        }
        else {
            return defaultValue;
        }
        const auto path = audio::str(setting, playbackType, profileType);
        updateDbValue(path, setting, value);
    }
}

std::string ServiceAudio::getSetting(const audio::Setting &setting,
                                     const audio::Profile::Type &profileType,
                                     const audio::PlaybackType &playbackType)
{
    const std::string defaultValue = "";
    if (profileType == audio::Profile::Type::Idle) {
        if (const auto optSetting = getCurrentSetting(setting); optSetting.has_value()) {
            return optSetting.value();
        }
        return defaultValue;
    if (setting == Setting::EnableVibration || setting == Setting::EnableSound) {
        targetProfile = Profile::Type::Idle;
    }
    const auto path = audio::str(setting, playbackType, profileType);

    std::string path = dbPath(setting, targetPlayback, targetProfile);
    return fetchAudioSettingFromDb(path, defaultValue);
}

std::optional<std::string> ServiceAudio::getCurrentSetting(const audio::Setting &setting)
void ServiceAudio::setSetting(const Setting &setting,
                              const std::string &value,
                              const Profile::Type &profileType,
                              const PlaybackType &playbackType)
{
    const auto activeInput = audioMux.GetActiveInput();
    std::string valueToSet, path;
    auto retCode         = audio::RetCode::Success;
    auto updatedProfile  = profileType;
    auto updatedPlayback = playbackType;

    if (!activeInput.has_value()) {
        const auto idleInput = audioMux.GetIdleInput();
        if (idleInput.has_value() && setting == audio::Setting::Volume) {
            const auto path = audio::str(audio::Setting::Volume,
                                         audio::PlaybackType::CallRingtone,
                                         (*idleInput)->audio->GetHeadphonesInserted());
            return fetchAudioSettingFromDb<std::string>(path, "");
        }
        return {};
    }
    std::optional<AudioMux::Input *> activeInput;

    const auto &currentOperation = (*activeInput)->audio->GetCurrentOperation();
    const auto path             = [&setting, &currentOperation]() -> std::string {
        if (setting == audio::Setting::EnableVibration || setting == audio::Setting::EnableSound) {
            return audio::str(setting, currentOperation.GetPlaybackType());
    if (profileType == Profile::Type::Idle && playbackType == PlaybackType::None) {
        if (activeInput = audioMux.GetActiveInput(); activeInput.has_value()) {
            const auto &currentOperation = (*activeInput)->audio->GetCurrentOperation();
            updatedProfile               = currentOperation.GetProfile()->GetType();
            updatedPlayback              = (*activeInput)->audio->GetCurrentOperationPlaybackType();
        }
        else {
            return audio::str(setting, currentOperation.GetPlaybackType(), currentOperation.GetProfile()->GetType());
        else if (setting == audio::Setting::Volume) {
            updatedProfile =
                headphonesInserted ? Profile::Type::PlaybackHeadphones : Profile::Type::PlaybackLoudspeaker;
            updatedPlayback = PlaybackType::CallRingtone;
            valueToSet      = std::clamp(utils::getValue<audio::Volume>(value), minVolume, maxVolume);
        }
    }();
    return fetchAudioSettingFromDb<std::string>(path, "");
}

void ServiceAudio::setCurrentSetting(const audio::Setting &setting, const std::string &value)
{
    const auto activeInput = audioMux.GetActiveInput();

    if (!activeInput.has_value()) {
        const auto idleInput = audioMux.GetIdleInput();
        if (idleInput.has_value() && setting == audio::Setting::Volume) {
            const auto path = audio::str(audio::Setting::Volume,
                                         audio::PlaybackType::CallRingtone,
                                         (*idleInput)->audio->GetHeadphonesInserted());
            addOrIgnoreEntry(path, std::to_string(audio::playbackDefaults::defaultLoudspeakerVolume));
            const auto valueToSet = std::clamp(utils::getValue<audio::Volume>(value), minVolume, maxVolume);
            updateDbValue(path, Setting::Volume, std::to_string(valueToSet));
        else {
            return;
        }
        return;
    }

    auto &audio                 = (*activeInput)->audio;
    const auto &currentOperation = audio->GetCurrentOperation();
    switch (setting) {
    case audio::Setting::Volume: {
        const auto valueToSet = std::clamp(utils::getValue<audio::Volume>(value), minVolume, maxVolume);
        if (audio->SetOutputVolume(valueToSet) == audio::RetCode::Success) {
            updateDbValue(currentOperation, setting, valueToSet);
    case Setting::Volume: {
        const auto clampedValue = std::clamp(utils::getValue<audio::Volume>(value), minVolume, maxVolume);
        valueToSet              = std::to_string(clampedValue);
        if (activeInput) {
            retCode = activeInput.value()->audio->SetOutputVolume(clampedValue);
        }
    } break;
    case audio::Setting::Gain: {
        const auto valueToSet = std::clamp(utils::getValue<audio::Gain>(value), minGain, maxGain);
        if (audio->SetInputGain(valueToSet) == audio::RetCode::Success) {
            updateDbValue(currentOperation, setting, valueToSet);
    case Setting::Gain: {
        const auto clampedValue = std::clamp(utils::getValue<audio::Gain>(value), minGain, maxGain);
        valueToSet              = std::to_string(clampedValue);
        if (activeInput) {
            retCode = activeInput.value()->audio->SetInputGain(clampedValue);
        }
    } break;
    case audio::Setting::EnableVibration: {
        const auto valueToSet = utils::getValue<audio::Vibrate>(value);
        updateDbValue(currentOperation, setting, valueToSet);
    case Setting::EnableVibration:
    case Setting::EnableSound: {
        updatedProfile = audio::Profile::Type::Idle;
        valueToSet     = value;
    } break;
    case audio::Setting::EnableSound: {
        const auto valueToSet = utils::getValue<audio::EnableSound>(value);
        updateDbValue(currentOperation, setting, valueToSet);
    }

    if (retCode == RetCode::Success) {
        path = dbPath(setting, updatedPlayback, updatedProfile);
        updateDbValue(path, valueToSet);
    }
}


M module-services/service-audio/ServiceAudio.hpp => module-services/service-audio/ServiceAudio.hpp +7 -7
@@ 42,6 42,8 @@ class ServiceAudio : public sys::Service
    audio::AudioMux audioMux;
    audio::AudioMux::VibrationStatus vibrationMotorStatus = audio::AudioMux::VibrationStatus::Off;

    bool headphonesInserted = false;

    auto IsVibrationMotorOn()
    {
        return vibrationMotorStatus == audio::AudioMux::VibrationStatus::On;


@@ 69,6 71,8 @@ class ServiceAudio : public sys::Service
                         std::optional<audio::AudioMux::Input *> input = std::nullopt);
    auto GetVibrationType(const audio::PlaybackType &type) -> VibrationType;

    auto IsVibrationEnabled(const audio::PlaybackType &type) -> bool;
    auto IsPlaybackEnabled(const audio::PlaybackType &type) -> bool;
    constexpr auto IsResumable(const audio::PlaybackType &type) const -> bool;
    constexpr auto ShouldLoop(const std::optional<audio::PlaybackType> &type) const -> bool;



@@ 94,9 98,8 @@ class ServiceAudio : public sys::Service
        }
        return defaultValue;
    }
    void updateDbValue(const std::string &path, const std::string &value);

    void setCurrentSetting(const audio::Setting &setting, const std::string &value);
    void setCurrentVolume(const uint32_t &value);
    void setSetting(const audio::Setting &setting,
                    const std::string &value,
                    const audio::Profile::Type &profileType,


@@ 104,9 107,6 @@ class ServiceAudio : public sys::Service
    [[nodiscard]] std::string getSetting(const audio::Setting &setting,
                                         const audio::Profile::Type &profileType,
                                         const audio::PlaybackType &playbackType);
    std::optional<std::string> getCurrentSetting(const audio::Setting &setting);
    void updateDbValue(const std::string &path, const audio::Setting &setting, const std::string &value);
    void updateDbValue(const audio::Operation &currentOperation, const audio::Setting &setting, const uint32_t &value);
    void updateDbValue(const audio::Operation &currentOperation, const audio::Setting &setting, const bool &value);
    [[nodiscard]] const std::pair<audio::Profile::Type, audio::PlaybackType> getCurrentContext();

    const std::pair<audio::Profile::Type, audio::PlaybackType> getCurrentContext();
};