~aleteoryx/muditaos

fd935f41796f521e65b206150eb11dde6549afb1 — Alek Rudnik 5 years ago 5dbd726
[EGD-6093] Audio settings API

Refactored Audio settings API.
Moved phone modes logic from serivce audio to service clients level.
Removed redundant API.
Seprated API for vibration and sound enable/disable.
Fixed issues with vibrations logic.
26 files changed, 496 insertions(+), 341 deletions(-)

M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/application-call/ApplicationCall.cpp
M module-apps/application-call/ApplicationCall.hpp
M module-apps/application-call/windows/CallWindow.cpp
M module-apps/application-settings-new/ApplicationSettings.cpp
M module-apps/application-settings-new/CMakeLists.txt
A module-apps/application-settings-new/models/AudioSettingsModel.cpp
A module-apps/application-settings-new/models/AudioSettingsModel.hpp
M module-apps/application-settings-new/windows/AlarmClockWindow.cpp
M module-apps/application-settings-new/windows/AlarmClockWindow.hpp
M module-apps/application-settings-new/windows/CalendarWindow.cpp
M module-apps/application-settings-new/windows/CalendarWindow.hpp
M module-apps/application-settings-new/windows/MessagesWindow.cpp
M module-apps/application-settings-new/windows/MessagesWindow.hpp
M module-apps/application-settings-new/windows/PhoneWindow.cpp
M module-apps/application-settings-new/windows/PhoneWindow.hpp
M module-audio/Audio/AudioCommon.cpp
M module-audio/Audio/AudioCommon.hpp
M module-audio/Audio/test/unittest_audio.cpp
M module-services/service-audio/AudioServiceAPI.cpp
M module-services/service-audio/ServiceAudio.cpp
M module-services/service-audio/service-audio/AudioMessage.hpp
M module-services/service-audio/service-audio/AudioServiceAPI.hpp
M module-services/service-audio/service-audio/ServiceAudio.hpp
M module-services/service-cellular/ServiceCellular.cpp
M module-apps/Application.cpp => module-apps/Application.cpp +0 -20
@@ 644,31 644,11 @@ namespace app
        pushWindow(windowName);
    }

    bool Application::setVolume(const audio::Volume &value,
                                const audio::Profile::Type &profileType,
                                const audio::PlaybackType &playbackType)
    {
        const auto ret = AudioServiceAPI::SetSetting(this, audio::Setting::Volume, value, playbackType, profileType);
        return ret == audio::RetCode::Success;
    }

    auto Application::getVolume(audio::Volume &volume,
                                const audio::Profile::Type &profileType,
                                const audio::PlaybackType &playbackType)
    {
        return AudioServiceAPI::GetSetting(this, audio::Setting::Volume, volume, playbackType, profileType);
    }

    bool Application::adjustCurrentVolume(const int step)
    {
        return AudioServiceAPI::KeyPressed(this, step);
    }

    audio::RetCode Application::getCurrentVolume(audio::Volume &volume)
    {
        return AudioServiceAPI::GetSetting(this, audio::Setting::Volume, volume);
    }

    void Application::toggleTorchOnOff()
    {
        auto msg = std::make_shared<sevm::ToggleTorchOnOffMessage>();

M module-apps/Application.hpp => module-apps/Application.hpp +0 -9
@@ 284,14 284,6 @@ namespace app
            systemCloseInProgress = true;
        }

        bool setVolume(const audio::Volume &value,
                       const audio::Profile::Type &profileType,
                       const audio::PlaybackType &playbackType);

        auto getVolume(audio::Volume &volume,
                       const audio::Profile::Type &profileType,
                       const audio::PlaybackType &playbackType);

        bool adjustCurrentVolume(const int step);
        bool increaseCurrentVolume(const audio::Volume step = audio::defaultVolumeStep)
        {


@@ 301,7 293,6 @@ namespace app
        {
            return adjustCurrentVolume(-step);
        }
        audio::RetCode getCurrentVolume(audio::Volume &volume);

        void toggleTorchOnOff();


M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +2 -1
@@ 301,7 301,8 @@ namespace app

    void ApplicationCall::startAudioRinging()
    {
        AudioServiceAPI::PlaybackStart(this, audio::PlaybackType::CallRingtone, ringtone_path);
        const auto filePath = AudioServiceAPI::GetSound(this, audio::PlaybackType::CallRingtone);
        AudioServiceAPI::PlaybackStart(this, audio::PlaybackType::CallRingtone, filePath);
    }

    void ApplicationCall::startAudioRouting()

M module-apps/application-call/ApplicationCall.hpp => module-apps/application-call/ApplicationCall.hpp +0 -3
@@ 26,9 26,6 @@ namespace app
        inline constexpr auto name_dialogConfirm     = "DialogConfirm";
        inline constexpr auto name_number            = "NumberWindow";
    } // namespace window

    inline constexpr auto ringtone_path = "assets/audio/rington_drum_2.mp3"; // Should bo moved to database

    class CallWindowInterface
    {
      public:

M module-apps/application-call/windows/CallWindow.cpp => module-apps/application-call/windows/CallWindow.cpp +0 -1
@@ 194,7 194,6 @@ namespace gui
            microphoneIcon->set(MicrophoneIconState::MUTE);
            setFocusItem(nullptr);
            connectTimerOnExit();
            LOG_FATAL("CALL_ENDED");
        } break;
        case State::CALL_IN_PROGRESS: {
            if (prevState == State::INCOMING_CALL) { // otherwise it is already started

M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +12 -5
@@ 420,25 420,33 @@ namespace app
            return std::make_unique<gui::ApnOptionsWindow>(app);
        });
        windowsFactory.attach(gui::window::name::phone, [](Application *app, const std::string &name) {
            return std::make_unique<gui::PhoneWindow>(app);
            auto audioModel =
                std::make_unique<audio_settings::AudioSettingsModel>(app, audio_settings::PlaybackType::CallRingtone);
            return std::make_unique<gui::PhoneWindow>(app, std::move(audioModel));
        });
        windowsFactory.attach(gui::window::name::call_ringtone, [](Application *app, const std::string &name) {
            return std::make_unique<gui::CallRingtoneWindow>(app);
        });
        windowsFactory.attach(gui::window::name::messages, [](Application *app, const std::string &name) {
            return std::make_unique<gui::MessagesWindow>(app);
            auto audioModel = std::make_unique<audio_settings::AudioSettingsModel>(
                app, audio_settings::PlaybackType::TextMessageRingtone);
            return std::make_unique<gui::MessagesWindow>(app, std::move(audioModel));
        });
        windowsFactory.attach(gui::window::name::message_sound, [](Application *app, const std::string &name) {
            return std::make_unique<gui::MessageSoundWindow>(app);
        });
        windowsFactory.attach(gui::window::name::calendar, [](Application *app, const std::string &name) {
            return std::make_unique<gui::CalendarWindow>(app);
            auto audioModel =
                std::make_unique<audio_settings::AudioSettingsModel>(app, audio_settings::PlaybackType::Notifications);
            return std::make_unique<gui::CalendarWindow>(app, std::move(audioModel));
        });
        windowsFactory.attach(gui::window::name::notification_sound, [](Application *app, const std::string &name) {
            return std::make_unique<gui::NotificationSoundWindow>(app);
        });
        windowsFactory.attach(gui::window::name::alarm_clock, [](Application *app, const std::string &name) {
            return std::make_unique<gui::AlarmClockWindow>(app);
            auto audioModel =
                std::make_unique<audio_settings::AudioSettingsModel>(app, audio_settings::PlaybackType::Alarm);
            return std::make_unique<gui::AlarmClockWindow>(app, std::move(audioModel));
        });
        windowsFactory.attach(gui::window::name::phone_name, [](Application *app, const std::string &name) {
            return std::make_unique<gui::PhoneNameWindow>(app);


@@ 731,5 739,4 @@ namespace app
        settings->setValue(
            ::settings::Offline::connectionFrequency, std::to_string(val), ::settings::SettingsScope::Global);
    }

} /* namespace app */

M module-apps/application-settings-new/CMakeLists.txt => module-apps/application-settings-new/CMakeLists.txt +1 -0
@@ 23,6 23,7 @@ target_sources( ${PROJECT_NAME}
        models/QuotesModel.cpp
        models/CategoriesModel.cpp
        models/SARInfoRepository.cpp
        models/AudioSettingsModel.cpp
        presenter/SARInfoWindowPresenter.cpp
        widgets/ChangePasscodeLockHandler.cpp
        widgets/QuoteWidget.cpp

A module-apps/application-settings-new/models/AudioSettingsModel.cpp => module-apps/application-settings-new/models/AudioSettingsModel.cpp +93 -0
@@ 0,0 1,93 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "AudioSettingsModel.hpp"

#include <service-audio/AudioServiceAPI.hpp>
#include <log/log.hpp>

namespace audio_settings
{

    constexpr audio::PlaybackType playbackTypeToAudioPlaybackType(PlaybackType type)
    {
        switch (type) {
        case PlaybackType::Notifications:
            return audio::PlaybackType::Notifications;
        case PlaybackType::KeypadSound:
            return audio::PlaybackType::KeypadSound;
        case PlaybackType::CallRingtone:
            return audio::PlaybackType::CallRingtone;
        case PlaybackType::TextMessageRingtone:
            return audio::PlaybackType::TextMessageRingtone;
        case PlaybackType::Alarm:
            return audio::PlaybackType::Alarm;
        }
        return audio::PlaybackType::None;
    }

    AudioSettingsModel::AudioSettingsModel(app::Application *application, PlaybackType playbackType)
        : application(application), playbackType(playbackTypeToAudioPlaybackType(playbackType))
    {}

    bool AudioSettingsModel::isVibrationEnabled()
    {
        auto settingState = AudioServiceAPI::GetVibrationSetting(application, playbackType);
        if (!settingState) {
            LOG_ERROR("Cannot read vibration setting for %s", audio::str(playbackType).c_str());
        }
        return (settingState.value_or(audio::SettingState::Disabled) == audio::SettingState::Enabled) ? true : false;
    }

    void AudioSettingsModel::setVibrationEnabled()
    {
        AudioServiceAPI::SetVibrationSetting(application, audio::SettingState::Enabled, playbackType);
    }

    void AudioSettingsModel::setVibrationDisabled()
    {
        AudioServiceAPI::SetVibrationSetting(application, audio::SettingState::Disabled, playbackType);
    }

    bool AudioSettingsModel::isSoundEnabled()
    {
        auto settingState = AudioServiceAPI::GetSoundSetting(application, playbackType);
        if (!settingState) {
            LOG_ERROR("Cannot read sound enabled setting for %s", audio::str(playbackType).c_str());
        }
        return (settingState.value_or(audio::SettingState::Disabled) == audio::SettingState::Enabled) ? true : false;
    }

    void AudioSettingsModel::setSoundEnabled()
    {
        AudioServiceAPI::SetSoundSetting(application, audio::SettingState::Enabled, playbackType);
    }

    void AudioSettingsModel::setSoundDisabled()
    {
        AudioServiceAPI::SetSoundSetting(application, audio::SettingState::Disabled, playbackType);
    }
    std::string AudioSettingsModel::getSound()
    {
        return AudioServiceAPI::GetSound(application, playbackType);
    }

    void AudioSettingsModel::setSound(std::string filePath)
    {
        AudioServiceAPI::SetSound(application, filePath, playbackType);
    }

    audio::Volume AudioSettingsModel::getVolume()
    {
        auto volume = AudioServiceAPI::GetVolume(application, playbackType);
        if (!volume) {
            LOG_ERROR("Cannot read volume level for %s", audio::str(playbackType).c_str());
        }
        return volume.value_or(0);
    }

    void AudioSettingsModel::setVolume(audio::Volume volume)
    {
        AudioServiceAPI::SetVolume(application, volume, playbackType);
    }
} // namespace audio_settings

A module-apps/application-settings-new/models/AudioSettingsModel.hpp => module-apps/application-settings-new/models/AudioSettingsModel.hpp +66 -0
@@ 0,0 1,66 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <Application.hpp>

namespace audio
{
    enum class PlaybackType;
}

namespace audio_settings
{
    enum class PlaybackType
    {
        Notifications,
        KeypadSound,
        CallRingtone,
        TextMessageRingtone,
        Alarm
    };

    /// @brief Abstract audio settings model interface class
    class AbstractAudioSettingsModel
    {
      public:
        virtual ~AbstractAudioSettingsModel() noexcept = default;

        [[nodiscard]] virtual bool isVibrationEnabled() = 0;
        virtual void setVibrationEnabled()              = 0;
        virtual void setVibrationDisabled()             = 0;
        [[nodiscard]] virtual bool isSoundEnabled()     = 0;
        virtual void setSoundEnabled()                  = 0;
        virtual void setSoundDisabled()                 = 0;
        /// @return sound file path, returns empty string if not found
        [[nodiscard]] virtual std::string getSound() = 0;
        /// @param sound file path
        virtual void setSound(std::string filePath)     = 0;
        [[nodiscard]] virtual audio::Volume getVolume() = 0;
        virtual void setVolume(audio::Volume vol)       = 0;
    };

    class AudioSettingsModel : public AbstractAudioSettingsModel
    {
      public:
        /// @param application application pointer
        /// @param playbackType playback type
        AudioSettingsModel(app::Application *application, PlaybackType playbackType);

        bool isVibrationEnabled() override;
        void setVibrationEnabled() override;
        void setVibrationDisabled() override;
        bool isSoundEnabled() override;
        void setSoundEnabled() override;
        void setSoundDisabled() override;
        std::string getSound() override;
        void setSound(std::string) override;
        audio::Volume getVolume() override;
        void setVolume(audio::Volume vol) override;

      private:
        app::Application *application = nullptr;
        audio::PlaybackType playbackType;
    };
} // namespace audio_settings

M module-apps/application-settings-new/windows/AlarmClockWindow.cpp => module-apps/application-settings-new/windows/AlarmClockWindow.cpp +11 -9
@@ 2,24 2,26 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "AlarmClockWindow.hpp"
#include "application-settings-new/ApplicationSettings.hpp"
#include "application-settings-new/widgets/SpinBoxOptionSettings.hpp"
#include "BaseSettingsWindow.hpp"

#include <application-settings-new/ApplicationSettings.hpp>
#include <i18n/i18n.hpp>
#include "BaseSettingsWindow.hpp"
#include "application-settings-new/widgets/SpinBoxOptionSettings.hpp"

namespace gui
{
    AlarmClockWindow::AlarmClockWindow(app::Application *app)
        : BaseSettingsWindow(app, gui::window::name::alarm_clock), mWidgetMaker(this)
    AlarmClockWindow::AlarmClockWindow(app::Application *app,
                                       std::unique_ptr<audio_settings::AbstractAudioSettingsModel> &&audioModel)
        : BaseSettingsWindow(app, gui::window::name::alarm_clock), mWidgetMaker(this),
          mAudioModel(std::move(audioModel))
    {
        mVibrationsEnabled = true;
        setTitle(utils::localize.get("app_settings_apps_alarm_clock"));
    }

    std::list<Option> AlarmClockWindow::buildOptionsList()
    {
        std::list<gui::Option> optionList;
        mVibrationsEnabled = mAudioModel->isVibrationEnabled();
        mWidgetMaker.addSwitchOption(optionList,
                                     utils::translateI18("app_settings_vibration"),
                                     mVibrationsEnabled,


@@ 34,7 36,7 @@ namespace gui

        optionList.emplace_back(std::make_unique<gui::SpinBoxOptionSettings>(
            utils::translateI18("app_settings_volume"),
            std::ceil(1.2),
            mAudioModel->getVolume(),
            std::ceil(10.0),
            [&](uint8_t value) {
                setVolume(value);


@@ 47,14 49,14 @@ namespace gui

    void AlarmClockWindow::switchVibrationState()
    {
        mVibrationsEnabled = !mVibrationsEnabled;
        LOG_INFO("switchVibrationState %d", static_cast<int>(mVibrationsEnabled));
        (mVibrationsEnabled) ? mAudioModel->setVibrationDisabled() : mAudioModel->setVibrationEnabled();
        refreshOptionsList();
    }

    void AlarmClockWindow::setVolume(uint8_t vol)
    {
        LOG_INFO("setVolume %d", static_cast<int>(vol));
        mAudioModel->setVolume(vol);
    }

} // namespace gui

M module-apps/application-settings-new/windows/AlarmClockWindow.hpp => module-apps/application-settings-new/windows/AlarmClockWindow.hpp +7 -1
@@ 5,6 5,7 @@

#include "BaseSettingsWindow.hpp"
#include "OptionsWidgetMaker.hpp"
#include <application-settings-new/models/AudioSettingsModel.hpp>

namespace gui
{


@@ 15,7 16,9 @@ namespace gui
      public:
        ///  Constructor
        ///  @app parent application pointer
        explicit AlarmClockWindow(app::Application *app);
        /// @audioModel audio settings model
        explicit AlarmClockWindow(app::Application *app,
                                  std::unique_ptr<audio_settings::AbstractAudioSettingsModel> &&audioModel);

      private:
        ///  Switches alarm vibration state


@@ 34,5 37,8 @@ namespace gui

        ///  Flag describing if phone vibration is enabled
        bool mVibrationsEnabled = false;

        /// Audio settings model
        std::unique_ptr<audio_settings::AbstractAudioSettingsModel> mAudioModel;
    };
} // namespace gui

M module-apps/application-settings-new/windows/CalendarWindow.cpp => module-apps/application-settings-new/windows/CalendarWindow.cpp +8 -8
@@ 10,17 10,19 @@

namespace gui
{
    CalendarWindow::CalendarWindow(app::Application *app)
        : BaseSettingsWindow(app, gui::window::name::calendar), mWidgetMaker(this)
    CalendarWindow::CalendarWindow(app::Application *app,
                                   std::unique_ptr<audio_settings::AbstractAudioSettingsModel> &&audioModel)
        : BaseSettingsWindow(app, gui::window::name::calendar), mWidgetMaker(this), mAudioModel(std::move(audioModel))
    {
        mVibrationsEnabled = true;
        mSoundEnabled      = true;
        setTitle(utils::localize.get("app_settings_apps_calendar"));
    }

    std::list<Option> CalendarWindow::buildOptionsList()
    {
        std::list<gui::Option> optionList;
        mVibrationsEnabled = mAudioModel->isVibrationEnabled();
        mSoundEnabled      = mAudioModel->isSoundEnabled();

        mWidgetMaker.addSwitchOption(optionList,
                                     utils::translateI18("app_settings_vibration"),
                                     mVibrationsEnabled,


@@ 42,15 44,13 @@ namespace gui

    void CalendarWindow::switchVibrationState()
    {
        mVibrationsEnabled = !mVibrationsEnabled;
        LOG_INFO("switchVibrationState %d", static_cast<int>(mVibrationsEnabled));
        (mVibrationsEnabled) ? mAudioModel->setVibrationDisabled() : mAudioModel->setVibrationEnabled();
        refreshOptionsList();
    }

    void CalendarWindow::switchSoundState()
    {
        mSoundEnabled = !mSoundEnabled;
        LOG_INFO("switchSoundState %d", static_cast<int>(mSoundEnabled));
        mSoundEnabled ? mAudioModel->setSoundDisabled() : mAudioModel->setSoundEnabled();
        refreshOptionsList();
    }


M module-apps/application-settings-new/windows/CalendarWindow.hpp => module-apps/application-settings-new/windows/CalendarWindow.hpp +7 -1
@@ 5,6 5,7 @@

#include "BaseSettingsWindow.hpp"
#include "OptionsWidgetMaker.hpp"
#include <application-settings-new/models/AudioSettingsModel.hpp>

namespace gui
{


@@ 15,7 16,9 @@ namespace gui
      public:
        ///  Constructor
        ///  @app parent application pointer
        explicit CalendarWindow(app::Application *app);
        ///  @audioModel audio settings model
        explicit CalendarWindow(app::Application *app,
                                std::unique_ptr<audio_settings::AbstractAudioSettingsModel> &&audioModel);

      private:
        ///  Switches calendar vibration state


@@ 39,5 42,8 @@ namespace gui

        ///  Flag describing if calendar sound is enabled
        bool mSoundEnabled = true;

        /// Audio settings model
        std::unique_ptr<audio_settings::AbstractAudioSettingsModel> mAudioModel;
    };
} // namespace gui

M module-apps/application-settings-new/windows/MessagesWindow.cpp => module-apps/application-settings-new/windows/MessagesWindow.cpp +8 -9
@@ 10,18 10,19 @@

namespace gui
{
    MessagesWindow::MessagesWindow(app::Application *app)
        : BaseSettingsWindow(app, gui::window::name::messages), mWidgetMaker(this)
    MessagesWindow::MessagesWindow(app::Application *app,
                                   std::unique_ptr<audio_settings::AbstractAudioSettingsModel> &&audioModel)
        : BaseSettingsWindow(app, gui::window::name::messages), mWidgetMaker(this), mAudioModel(std::move(audioModel))
    {
        mVibrationsEnabled       = false;
        mSoundEnabled            = true;
        mShowUnreadMessagesFirst = true;
        mShowUnreadMessagesFirst = false;
        setTitle(utils::localize.get("app_settings_apps_messages"));
    }

    std::list<Option> MessagesWindow::buildOptionsList()
    {
        std::list<gui::Option> optionList;
        mVibrationsEnabled = mAudioModel->isVibrationEnabled();
        mSoundEnabled      = mAudioModel->isSoundEnabled();

        mWidgetMaker.addSwitchOption(optionList,
                                     utils::translateI18("app_settings_vibration"),


@@ 51,15 52,13 @@ namespace gui

    void MessagesWindow::switchVibrationState()
    {
        mVibrationsEnabled = !mVibrationsEnabled;
        LOG_INFO("switchVibrationState %d", static_cast<int>(mVibrationsEnabled));
        (mVibrationsEnabled) ? mAudioModel->setVibrationDisabled() : mAudioModel->setVibrationEnabled();
        refreshOptionsList();
    }

    void MessagesWindow::switchSoundState()
    {
        mSoundEnabled = !mSoundEnabled;
        LOG_INFO("switchSoundState %d", static_cast<int>(mSoundEnabled));
        mSoundEnabled ? mAudioModel->setSoundDisabled() : mAudioModel->setSoundEnabled();
        refreshOptionsList();
    }


M module-apps/application-settings-new/windows/MessagesWindow.hpp => module-apps/application-settings-new/windows/MessagesWindow.hpp +7 -2
@@ 5,6 5,7 @@

#include "BaseSettingsWindow.hpp"
#include "OptionsWidgetMaker.hpp"
#include <application-settings-new/models/AudioSettingsModel.hpp>

namespace gui
{


@@ 15,11 16,12 @@ namespace gui
      public:
        ///  Constructor
        ///  @app parent application pointer
        explicit MessagesWindow(app::Application *app);
        ///  @audioModel audio settings model
        explicit MessagesWindow(app::Application *app,
                                std::unique_ptr<audio_settings::AbstractAudioSettingsModel> &&audioModel);

      private:
        ///  Switches messages vibration state
        ///  @return new state
        void switchVibrationState();

        ///  Switches messages sound state


@@ 49,5 51,8 @@ namespace gui

        ///  Flag describing if unread messages are shown first
        bool mShowUnreadMessagesFirst = true;

        /// Audio settings model
        std::unique_ptr<audio_settings::AbstractAudioSettingsModel> mAudioModel;
    };
} // namespace gui

M module-apps/application-settings-new/windows/PhoneWindow.cpp => module-apps/application-settings-new/windows/PhoneWindow.cpp +8 -9
@@ 10,17 10,19 @@

namespace gui
{
    PhoneWindow::PhoneWindow(app::Application *app)
        : BaseSettingsWindow(app, gui::window::name::phone), mWidgetMaker(this)
    PhoneWindow::PhoneWindow(app::Application *app,
                             std::unique_ptr<audio_settings::AbstractAudioSettingsModel> &&audioModel)
        : BaseSettingsWindow(app, gui::window::name::phone), mWidgetMaker(this), mAudioModel(std::move(audioModel))
    {
        mVibrationsEnabled = true;
        mSoundEnabled      = true;
        setTitle(utils::localize.get("app_settings_apps_phone"));
    }

    std::list<Option> PhoneWindow::buildOptionsList()
    {
        std::list<gui::Option> optionList;
        mVibrationsEnabled = mAudioModel->isVibrationEnabled();
        mSoundEnabled      = mAudioModel->isSoundEnabled();

        mWidgetMaker.addSwitchOption(optionList,
                                     utils::translateI18("app_settings_vibration"),
                                     mVibrationsEnabled,


@@ 39,16 41,13 @@ namespace gui

    void PhoneWindow::switchVibrationState()
    {
        LOG_INFO("switchVibrationState before %d", static_cast<int>(mVibrationsEnabled));
        mVibrationsEnabled = !mVibrationsEnabled;
        LOG_INFO("switchVibrationState after %d", static_cast<int>(mVibrationsEnabled));
        (mVibrationsEnabled) ? mAudioModel->setVibrationDisabled() : mAudioModel->setVibrationEnabled();
        refreshOptionsList();
    }

    void PhoneWindow::switchSoundState()
    {
        mSoundEnabled = !mSoundEnabled;
        LOG_INFO("switchSoundState %d", static_cast<int>(mSoundEnabled));
        mSoundEnabled ? mAudioModel->setSoundDisabled() : mAudioModel->setSoundEnabled();
        refreshOptionsList();
    }


M module-apps/application-settings-new/windows/PhoneWindow.hpp => module-apps/application-settings-new/windows/PhoneWindow.hpp +7 -2
@@ 5,7 5,7 @@

#include "BaseSettingsWindow.hpp"
#include "OptionsWidgetMaker.hpp"

#include <application-settings-new/models/AudioSettingsModel.hpp>
namespace gui
{
    ///  @brief Phone (call) vibration and sound settings window


@@ 14,7 14,9 @@ namespace gui
      public:
        ///  Constructor
        ///  @app parent application pointer
        explicit PhoneWindow(app::Application *app);
        ///  @audioModel audio settings model
        explicit PhoneWindow(app::Application *app,
                             std::unique_ptr<audio_settings::AbstractAudioSettingsModel> &&audioModel);

      private:
        ///  Switches phone vibration state


@@ 38,5 40,8 @@ namespace gui

        ///  Flag describing if phone sound is enabled
        bool mSoundEnabled = true;

        /// Audio settings model
        std::unique_ptr<audio_settings::AbstractAudioSettingsModel> mAudioModel;
    };
} // namespace gui

M module-audio/Audio/AudioCommon.cpp => module-audio/Audio/AudioCommon.cpp +2 -8
@@ 63,13 63,10 @@ namespace audio

    const std::string dbPath(const DbPathElement &element)
    {
        return dbPath(element.setting, element.playbackType, element.profileType, element.phoneMode);
        return dbPath(element.setting, element.playbackType, element.profileType);
    }

    const std::string dbPath(const Setting &setting,
                             const PlaybackType &playbackType,
                             const Profile::Type &profileType,
                             const std::optional<sys::phone_modes::PhoneMode> phoneMode)
    const std::string dbPath(const Setting &setting, const PlaybackType &playbackType, const Profile::Type &profileType)
    {
        if (profileType == Profile::Type::Idle && playbackType == PlaybackType::None) {
            return std::string();


@@ 79,9 76,6 @@ namespace audio
        std::string path;

        pathElements.emplace_back(audioDbPrefix);
        if ((setting == Setting::EnableSound || setting == Setting::EnableVibration) && phoneMode.has_value()) {
            pathElements.emplace_back(utils::enumToString(phoneMode.value()));
        }

        if (auto s = str(profileType); !s.empty()) {
            pathElements.emplace_back(s);

M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +9 -6
@@ 7,9 7,7 @@
#include "Profiles/Profile.hpp"

#include <Service/Message.hpp>
#include <PhoneModes/Common.hpp>
#include <Utils.hpp>
#include <PhoneModes/Common.hpp>

#include <bitset>
#include <map>


@@ 45,7 43,14 @@ namespace audio
        Volume,
        Gain,
        EnableVibration,
        EnableSound
        EnableSound,
        Sound
    };

    enum class SettingState : bool
    {
        Enabled,
        Disabled
    };

    enum class PlaybackType


@@ 67,7 72,6 @@ namespace audio
        Setting setting;
        PlaybackType playbackType;
        Profile::Type profileType;
        std::optional<sys::phone_modes::PhoneMode> phoneMode = std::nullopt;
    };

    [[nodiscard]] const std::string str(const PlaybackType &playbackType) noexcept;


@@ 78,8 82,7 @@ namespace audio

    [[nodiscard]] const std::string dbPath(const Setting &setting,
                                           const PlaybackType &playbackType,
                                           const Profile::Type &profileType,
                                           const std::optional<sys::phone_modes::PhoneMode> phoneMode = std::nullopt);
                                           const Profile::Type &profileType);

    [[nodiscard]] bool isSystemSound(const PlaybackType &playbackType) noexcept;


M module-audio/Audio/test/unittest_audio.cpp => module-audio/Audio/test/unittest_audio.cpp +18 -39
@@ 41,40 41,31 @@ TEST_CASE("Audio settings string creation")
{
    SECTION("Create volume string for playback loudspeaker, multimedia")
    {
        const auto str = audio::dbPath(audio::Setting::Volume,
                                       audio::PlaybackType::Multimedia,
                                       audio::Profile::Type::PlaybackLoudspeaker,
                                       sys::phone_modes::PhoneMode::Connected);
        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");
    }

    SECTION("Create volume string for routing speakerphone")
    {
        const auto str = audio::dbPath(audio::Setting::Volume,
                                       audio::PlaybackType::None,
                                       audio::Profile::Type::RoutingLoudspeaker,
                                       sys::phone_modes::PhoneMode::Offline);
        const auto str =
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingLoudspeaker);
        REQUIRE_FALSE(str.empty());
        REQUIRE(str == "audio/RoutingLoudspeaker/Volume");
    }

    SECTION("Create gain string for recording built-in microphone")
    {
        const auto str = audio::dbPath(audio::Setting::Gain,
                                       audio::PlaybackType::None,
                                       audio::Profile::Type::RecordingBuiltInMic,
                                       sys::phone_modes::PhoneMode::DoNotDisturb);
        const auto str =
            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::dbPath(audio::Setting::Volume,
                                       audio::PlaybackType::None,
                                       audio::Profile::Type::Idle,
                                       sys::phone_modes::PhoneMode::Offline);
        const auto str = audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::Idle);
        REQUIRE(str.empty());
    }



@@ 101,34 92,22 @@ TEST_CASE("Audio settings string creation")
            {PlaybackType::None, Setting::Volume, "audio/RecordingBuiltInMic/Volume"},

            // EnableSound
            {PlaybackType::System, Setting::EnableSound, "audio/Offline/RecordingBuiltInMic/Notifications/EnableSound"},
            {PlaybackType::Meditation,
             Setting::EnableSound,
             "audio/Offline/RecordingBuiltInMic/Meditation/EnableSound"},
            {PlaybackType::CallRingtone,
             Setting::EnableSound,
             "audio/Offline/RecordingBuiltInMic/CallRingtone/EnableSound"},
            {PlaybackType::KeypadSound,
             Setting::EnableSound,
             "audio/Offline/RecordingBuiltInMic/KeypadSound/EnableSound"},
            {PlaybackType::System, Setting::EnableSound, "audio/RecordingBuiltInMic/Notifications/EnableSound"},
            {PlaybackType::Meditation, Setting::EnableSound, "audio/RecordingBuiltInMic/Meditation/EnableSound"},
            {PlaybackType::CallRingtone, Setting::EnableSound, "audio/RecordingBuiltInMic/CallRingtone/EnableSound"},
            {PlaybackType::KeypadSound, Setting::EnableSound, "audio/RecordingBuiltInMic/KeypadSound/EnableSound"},
            {PlaybackType::TextMessageRingtone,
             Setting::EnableSound,
             "audio/Offline/RecordingBuiltInMic/TextMessageRingtone/EnableSound"},
            {PlaybackType::Notifications,
             Setting::EnableSound,
             "audio/Offline/RecordingBuiltInMic/Notifications/EnableSound"},
            {PlaybackType::Alarm, Setting::EnableSound, "audio/Offline/RecordingBuiltInMic/Alarm/EnableSound"},
            {PlaybackType::Multimedia,
             Setting::EnableSound,
             "audio/Offline/RecordingBuiltInMic/Multimedia/EnableSound"},
            {PlaybackType::None, Setting::EnableSound, "audio/Offline/RecordingBuiltInMic/EnableSound"},
             "audio/RecordingBuiltInMic/TextMessageRingtone/EnableSound"},
            {PlaybackType::Notifications, Setting::EnableSound, "audio/RecordingBuiltInMic/Notifications/EnableSound"},
            {PlaybackType::Alarm, Setting::EnableSound, "audio/RecordingBuiltInMic/Alarm/EnableSound"},
            {PlaybackType::Multimedia, Setting::EnableSound, "audio/RecordingBuiltInMic/Multimedia/EnableSound"},
            {PlaybackType::None, Setting::EnableSound, "audio/RecordingBuiltInMic/EnableSound"},
        };

        for (auto &testCase : testCases) {
            const auto str = audio::dbPath(testCase.setting,
                                           testCase.playbackType,
                                           audio::Profile::Type::RecordingBuiltInMic,
                                           sys::phone_modes::PhoneMode::Offline);
            const auto str =
                audio::dbPath(testCase.setting, testCase.playbackType, audio::Profile::Type::RecordingBuiltInMic);
            REQUIRE_FALSE(str.empty());
            REQUIRE(str == testCase.path);
        }

M module-services/service-audio/AudioServiceAPI.cpp => module-services/service-audio/AudioServiceAPI.cpp +79 -27
@@ 102,51 102,103 @@ namespace AudioServiceAPI
        return serv->bus.sendUnicast(msg, service::name::audio);
    }

    template <typename T>
    audio::RetCode GetSetting(sys::Service *serv,
                              const audio::Setting &setting,
                              T &value,
                              const audio::PlaybackType &playbackType,
                              const audio::Profile::Type &profileType)
    std::string GetSetting(sys::Service *serv, audio::Setting setting, audio::PlaybackType playbackType)
    {
        auto msg  = std::make_shared<AudioGetSetting>(profileType, playbackType, setting);
        auto msg  = std::make_shared<AudioGetSetting>(playbackType, setting);
        auto resp = SendAudioRequest(serv, msg);
        if (resp->retCode == RetCode::Success) {
            value = resp->val;
            return resp->val;
        }

        return resp->retCode;
        return "";
    }

    template audio::RetCode GetSetting<uint32_t>(sys::Service *serv,
                                                 const audio::Setting &setting,
                                                 uint32_t &value,
                                                 const audio::PlaybackType &playbackType,
                                                 const audio::Profile::Type &profileType);
    std::optional<audio::SettingState> GetSettingState(sys::Service *serv,
                                                       audio::Setting setting,
                                                       audio::PlaybackType playbackType)
    {
        auto settingValue = GetSetting(serv, setting, playbackType);
        if (!settingValue.empty()) {
            return settingValue != "0" ? audio::SettingState::Enabled : audio::SettingState::Disabled;
        }

    template audio::RetCode GetSetting<bool>(sys::Service *serv,
                                             const audio::Setting &setting,
                                             bool &value,
                                             const audio::PlaybackType &playbackType,
                                             const audio::Profile::Type &profileType);
        return std::nullopt;
    }

    template <typename T>
    audio::RetCode SetSetting(sys::Service *serv,
                              const audio::Setting &setting,
                              audio::Setting setting,
                              const T value,
                              const audio::PlaybackType &playbackType,
                              const audio::Profile::Type &profileType)
                              audio::PlaybackType playbackType)
    {
        auto msg = std::make_shared<AudioSetSetting>(playbackType, setting, std::to_string(value));

        return SendAudioRequest(serv, msg)->retCode;
    }

    template <>
    audio::RetCode SetSetting<std::string>(sys::Service *serv,
                                           audio::Setting setting,
                                           const std::string str,
                                           audio::PlaybackType playbackType)
    {
        auto msg = std::make_shared<AudioSetSetting>(profileType, playbackType, setting, std::to_string(value));
        auto msg = std::make_shared<AudioSetSetting>(playbackType, setting, str);

        return SendAudioRequest(serv, msg)->retCode;
    }

    template audio::RetCode SetSetting<uint32_t>(
        sys::Service *, const Setting &, const uint32_t, const PlaybackType &, const Profile::Type &);
    audio::RetCode SetVibrationSetting(sys::Service *serv,
                                       audio::SettingState settingState,
                                       audio::PlaybackType playbackType)
    {
        return SetSetting(
            serv, audio::Setting::EnableVibration, settingState == audio::SettingState::Enabled, playbackType);
    }

    audio::RetCode SetSoundSetting(sys::Service *serv,
                                   audio::SettingState settingState,
                                   audio::PlaybackType playbackType)
    {
        return SetSetting(
            serv, audio::Setting::EnableSound, settingState == audio::SettingState::Enabled, playbackType);
    }

    std::optional<audio::SettingState> GetVibrationSetting(sys::Service *serv, audio::PlaybackType playbackType)
    {
        return GetSettingState(serv, audio::Setting::EnableVibration, playbackType);
    }

    std::optional<audio::SettingState> GetSoundSetting(sys::Service *serv, audio::PlaybackType playbackType)
    {
        return GetSettingState(serv, audio::Setting::EnableSound, playbackType);
    }

    audio::RetCode SetSound(sys::Service *serv, const std::string &filePath, audio::PlaybackType playbackType)
    {
        return SetSetting(serv, audio::Setting::Sound, filePath, playbackType);
    }

    std::string GetSound(sys::Service *serv, audio::PlaybackType playbackType)
    {
        return GetSetting(serv, audio::Setting::Sound, playbackType);
    }

    template audio::RetCode SetSetting<bool>(
        sys::Service *, const Setting &, const bool, const PlaybackType &, const Profile::Type &);
    audio::RetCode SetVolume(sys::Service *serv, const audio::Volume vol, audio::PlaybackType playbackType)
    {
        return SetSetting(serv, audio::Setting::Volume, std::to_string(vol), playbackType);
    }

    std::optional<audio::Volume> GetVolume(sys::Service *serv, audio::PlaybackType playbackType)
    {
        std::optional<audio::Volume> volume;
        try {
            return static_cast<audio::Volume>(std::stoi(GetSetting(serv, audio::Setting::Volume, playbackType)));
        }
        catch (const std::exception &e) {
            LOG_ERROR("exception %s", e.what());
            return std::nullopt;
        }
    }

    std::optional<Tags> GetFileTags(sys::Service *serv, const std::string &fileName)
    {

M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +60 -132
@@ 20,7 20,6 @@
#include <utility>

using namespace audio;
using namespace sys::phone_modes;

inline constexpr auto audioServiceStackSize = 1024 * 4;



@@ 29,6 28,10 @@ static constexpr auto defaultVolumeLow   = "2";
static constexpr auto defaultVolumeMuted = "0";
static constexpr auto defaultTrue        = "1";
static constexpr auto defaultFalse       = "0";
static constexpr auto defaultCallRingtonePath        = "assets/audio/Ringtone-drum2.mp3";
static constexpr auto defaultTextMessageRingtonePath = "assets/audio/SMS-drum2.mp3";
static constexpr auto defaultNotificationsPath       = "assets/audio/SMS-drum2.mp3";
static constexpr auto defaultKeypadSoundPath         = "assets/audio/SMS-drum2.mp3";

static constexpr std::initializer_list<std::pair<audio::DbPathElement, const char *>> cacheInitializer{



@@ 41,9 44,7 @@ static constexpr std::initializer_list<std::pair<audio::DbPathElement, const cha
    {DbPathElement{Setting::Volume, PlaybackType::System, Profile::Type::PlaybackBluetoothA2DP}, defaultVolumeLow},
    {DbPathElement{Setting::Volume, PlaybackType::System, Profile::Type::PlaybackLoudspeaker}, defaultVolumeHigh},

    {DbPathElement{Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackHeadphones}, defaultVolumeLow},
    {DbPathElement{Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackBluetoothA2DP}, defaultVolumeLow},
    {DbPathElement{Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackLoudspeaker}, defaultVolumeHigh},
    {DbPathElement{Setting::Volume, PlaybackType::Alarm, Profile::Type::Idle}, defaultVolumeLow},

    // ROUTING
    {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHSP}, "20"},


@@ 62,110 63,36 @@ static constexpr std::initializer_list<std::pair<audio::DbPathElement, const cha
    {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RecordingBluetoothHSP}, "100"},

    // MISC
    {DbPathElement{Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle, PhoneMode::Connected},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle, PhoneMode::Connected},
     defaultTrue},
    {DbPathElement{Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle, PhoneMode::Connected},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle, PhoneMode::Connected},
     defaultTrue},
    {DbPathElement{
         Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle, PhoneMode::Connected},
     defaultTrue},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Meditation, Profile::Type::Idle, PhoneMode::Connected},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle}, defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle}, defaultTrue},
    {DbPathElement{Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultTrue},
    {DbPathElement{Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle}, defaultTrue},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Meditation, Profile::Type::Idle}, defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Alarm, Profile::Type::Idle}, defaultTrue},

    {DbPathElement{Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultFalse},
    {DbPathElement{
         Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Meditation, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Alarm, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultTrue},

    {DbPathElement{Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle, PhoneMode::Offline},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle, PhoneMode::Offline},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle, PhoneMode::Offline},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle, PhoneMode::Offline},
     defaultFalse},
    {DbPathElement{
         Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle, PhoneMode::Offline},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Meditation, Profile::Type::Idle, PhoneMode::Offline},
     defaultFalse},
    {DbPathElement{Setting::EnableVibration, PlaybackType::Alarm, Profile::Type::Idle, PhoneMode::Offline},
     defaultTrue},

    {DbPathElement{Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle, PhoneMode::Connected},
     defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle, PhoneMode::Connected},
     defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle, PhoneMode::Connected},
     defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle, PhoneMode::Connected},
     defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle, PhoneMode::Connected},
     defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Meditation, Profile::Type::Idle, PhoneMode::Connected},
     defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Alarm, Profile::Type::Idle, PhoneMode::Connected}, defaultTrue},

    {DbPathElement{Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultFalse},
    {DbPathElement{Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultFalse},
    {DbPathElement{Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultFalse},
    {DbPathElement{
         Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultFalse},
    {DbPathElement{Setting::EnableSound, PlaybackType::Meditation, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Alarm, Profile::Type::Idle, PhoneMode::DoNotDisturb},
     defaultTrue},

    {DbPathElement{Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle, PhoneMode::Offline},
     defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle, PhoneMode::Offline},
     defaultFalse},
    {DbPathElement{Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle, PhoneMode::Offline},
     defaultFalse},
    {DbPathElement{Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle, PhoneMode::Offline},
     defaultFalse},
    {DbPathElement{Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle, PhoneMode::Offline},
     defaultFalse},
    {DbPathElement{Setting::EnableSound, PlaybackType::Meditation, Profile::Type::Idle, PhoneMode::Offline},
     defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Alarm, Profile::Type::Idle, PhoneMode::Offline}, defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle}, defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle}, defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle}, defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Meditation, Profile::Type::Idle}, defaultTrue},
    {DbPathElement{Setting::EnableSound, PlaybackType::Alarm, Profile::Type::Idle}, defaultTrue},

    {DbPathElement{Setting::Sound, PlaybackType::Notifications, Profile::Type::Idle}, defaultNotificationsPath},
    {DbPathElement{Setting::Sound, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultKeypadSoundPath},
    {DbPathElement{Setting::Sound, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultCallRingtonePath},
    {DbPathElement{Setting::Sound, PlaybackType::TextMessageRingtone, Profile::Type::Idle},
     defaultTextMessageRingtonePath},
};

ServiceAudio::ServiceAudio()
    : sys::Service(service::name::audio, "", audioServiceStackSize, sys::ServicePriority::Idle),
      audioMux([this](auto... params) { return this->AudioServicesCallback(params...); }),
      settingsProvider(std::make_unique<settings::Settings>(this)),
      phoneModeObserver(std::make_unique<sys::phone_modes::Observer>())
      settingsProvider(std::make_unique<settings::Settings>(this))
{
    LOG_INFO("[ServiceAudio] Initializing");
    bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
    bus.channels.push_back(sys::BusChannel::PhoneModeChanges);

    phoneModeObserver->connect(this);
    phoneModeObserver->subscribe([&](sys::phone_modes::PhoneMode phoneMode) { HandlePhoneModeChange(phoneMode); });

    connect(typeid(BluetoothDeviceVolumeChanged),
            [this](sys::Message *msg) -> sys::MessagePointer { return handleVolumeChangedOnBluetoothDevice(msg); });


@@ 209,8 136,7 @@ std::optional<std::string> ServiceAudio::AudioServicesCallback(const sys::Messag
        bus.sendMulticast(std::move(newMsg), sys::BusChannel::ServiceAudioNotifications);
    }
    else if (const auto *dbReq = dynamic_cast<const AudioServiceMessage::DbRequest *>(msg); dbReq) {
        std::string path =
            dbPath(dbReq->setting, dbReq->playback, dbReq->profile, phoneModeObserver->getCurrentPhoneMode());
        std::string path = dbPath(dbReq->setting, dbReq->playback, dbReq->profile);
        LOG_DEBUG("ServiceAudio::DBbCallback(%s)", path.c_str());
        auto settings_it = settingsCache.find(path);
        if (settingsCache.end() == settings_it) {


@@ 246,7 172,6 @@ constexpr bool ServiceAudio::IsResumable(const audio::PlaybackType &type) const

constexpr bool ServiceAudio::ShouldLoop(const std::optional<audio::PlaybackType> &type) const
{

    return type.value_or(audio::PlaybackType::None) == audio::PlaybackType::CallRingtone;
}



@@ 256,6 181,7 @@ bool ServiceAudio::IsVibrationEnabled(const audio::PlaybackType &type)
        utils::getNumericValue<audio::Vibrate>(getSetting(Setting::EnableVibration, Profile::Type::Idle, type));
    return isEnabled;
}

bool ServiceAudio::IsOperationEnabled(const audio::PlaybackType &plType, const Operation::Type &opType)
{
    if (opType == Operation::Type::Router || opType == Operation::Type::Recorder) {


@@ 266,6 192,11 @@ bool ServiceAudio::IsOperationEnabled(const audio::PlaybackType &plType, const O
    return isEnabled;
}

std::string ServiceAudio::GetSound(const audio::PlaybackType &plType)
{
    return getSetting(Setting::Sound, Profile::Type::Idle, plType);
}

ServiceAudio::VibrationType ServiceAudio::GetVibrationType(const audio::PlaybackType &type)
{
    if (!IsVibrationEnabled(type)) {


@@ 299,7 230,7 @@ void ServiceAudio::VibrationUpdate(const audio::PlaybackType &type, std::optiona
        EventManagerServiceAPI::vibraPulseRepeatUntilStop(this);
        vibrationMotorStatus = AudioMux::VibrationStatus::On;
    }
    else if (!anyOfInputsOn && IsVibrationMotorOn()) {
    else if ((!anyOfInputsOn && IsVibrationMotorOn()) || (anyOfInputsOn && IsVibrationMotorOn())) {
        EventManagerServiceAPI::vibraStop(this);
        vibrationMotorStatus = AudioMux::VibrationStatus::Off;
    }


@@ 544,25 475,6 @@ auto ServiceAudio::HandleKeyPressed(const int step) -> std::unique_ptr<AudioKeyP
        audio::RetCode::Success, newVolume, AudioKeyPressedResponse::ShowPopup::True, context);
}

void ServiceAudio::HandlePhoneModeChange(sys::phone_modes::PhoneMode phoneMode)
{
    LOG_INFO("Phone mode changed to %s", utils::enumToString(phoneMode).c_str());
    for (auto &input : audioMux.GetAllInputs()) {
        if (input.audio->GetCurrentState() != Audio::State::Idle) {
            std::string path = dbPath(Setting::Volume,
                                      input.audio->GetCurrentOperationPlaybackType(),
                                      input.audio->GetPriorityPlaybackProfile(),
                                      phoneMode);
            if (const auto it = settingsCache.find(path); settingsCache.end() != it) {
                input.audio->SetOutputVolume(utils::getNumericValue<audio::Volume>(it->second));
            }
            else {
                LOG_ERROR("Requested uninitialized DB value %s", path.c_str());
            }
        }
    }
}

void ServiceAudio::MuteCurrentOperation()
{
    for (auto &input : audioMux.GetAllInputs()) {


@@ 583,7 495,7 @@ bool ServiceAudio::IsBusy()
sys::MessagePointer ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
{
    sys::MessagePointer responseMsg;
    bool isBusy = IsBusy();
    const auto isBusy = IsBusy();
    auto &msgType = typeid(*msgl);

    if (msgType == typeid(AudioNotificationMessage)) {


@@ 592,12 504,12 @@ sys::MessagePointer ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sy
    }
    else if (msgType == typeid(AudioGetSetting)) {
        auto *msg   = static_cast<AudioGetSetting *>(msgl);
        auto value  = getSetting(msg->setting, msg->profileType, msg->playbackType);
        responseMsg = std::make_shared<AudioResponseMessage>(RetCode::Success, utils::getNumericValue<float>(value));
        auto value  = getSetting(msg->setting, Profile::Type::Idle, msg->playbackType);
        responseMsg = std::make_shared<AudioResponseMessage>(RetCode::Success, value);
    }
    else if (msgType == typeid(AudioSetSetting)) {
        auto *msg = static_cast<AudioSetSetting *>(msgl);
        setSetting(msg->setting, msg->val, msg->profileType, msg->playbackType);
        setSetting(msg->setting, msg->val, Profile::Type::Idle, msg->playbackType);
        responseMsg = std::make_shared<AudioResponseMessage>(RetCode::Success);
    }
    else if (msgType == typeid(AudioStopRequest)) {


@@ 679,10 591,22 @@ std::string ServiceAudio::getSetting(const Setting &setting,
        }
    }

    if (setting == Setting::EnableVibration || setting == Setting::EnableSound) {
    switch (setting) {
    case Setting::EnableVibration:
    case Setting::EnableSound:
    case Setting::Sound:
        targetProfile = Profile::Type::Idle;
        break;
    case Setting::Volume:
        if (targetPlayback == PlaybackType::Alarm) {
            targetProfile = Profile::Type::Idle;
        }
        break;
    case Setting::Gain:
        break;
    }
    std::string path = dbPath(setting, targetPlayback, targetProfile, phoneModeObserver->getCurrentPhoneMode());

    const auto path = dbPath(setting, targetPlayback, targetProfile);

    if (const auto set_it = settingsCache.find(path); settingsCache.end() != set_it) {
        LOG_INFO("Get audio setting %s = %s", path.c_str(), set_it->second.c_str());


@@ 724,7 648,12 @@ void ServiceAudio::setSetting(const Setting &setting,
        valueToSet              = std::to_string(clampedValue);
        if (activeInput) {
            retCode = activeInput.value()->audio->SetOutputVolume(clampedValue);
            break;
        }
        if (updatedPlayback == PlaybackType::Alarm) {
            updatedProfile = Profile::Type::Idle;
        }
        break;
    } break;
    case Setting::Gain: {
        const auto clampedValue = std::clamp(utils::getNumericValue<audio::Gain>(value), minGain, maxGain);


@@ 734,17 663,16 @@ void ServiceAudio::setSetting(const Setting &setting,
        }
    } break;
    case Setting::EnableVibration:
    case Setting::EnableSound: {
    case Setting::EnableSound:
    case Setting::Sound: {
        updatedProfile = audio::Profile::Type::Idle;
        valueToSet     = value;
    } break;
    }

    if (retCode == RetCode::Success) {
        settingsProvider->setValue(
            dbPath(setting, updatedPlayback, updatedProfile, phoneModeObserver->getCurrentPhoneMode()), valueToSet);
        settingsCache[dbPath(setting, updatedPlayback, updatedProfile, phoneModeObserver->getCurrentPhoneMode())] =
            valueToSet;
        settingsProvider->setValue(dbPath(setting, updatedPlayback, updatedProfile), valueToSet);
        settingsCache[dbPath(setting, updatedPlayback, updatedProfile)] = valueToSet;
    }
}


M module-services/service-audio/service-audio/AudioMessage.hpp => module-services/service-audio/service-audio/AudioMessage.hpp +12 -20
@@ 23,21 23,20 @@ class AudioMessage : public sys::DataMessage
class AudioResponseMessage : public sys::ResponseMessage
{
  public:
    AudioResponseMessage(audio::RetCode retCode  = audio::RetCode::Success,
                         const audio::Tags &tags = {},
                         const float val         = 0.0)
    explicit AudioResponseMessage(audio::RetCode retCode  = audio::RetCode::Success,
                                  const audio::Tags &tags = {},
                                  const std::string &val  = {})
        : sys::ResponseMessage(), retCode(retCode), tags(tags), val(val)
    {}

    AudioResponseMessage(audio::RetCode retCode, const float val) : AudioResponseMessage(retCode, {}, val)
    AudioResponseMessage(audio::RetCode retCode, const std::string &val) : AudioResponseMessage(retCode, {}, val)
    {}

    virtual ~AudioResponseMessage()
    {}
    virtual ~AudioResponseMessage() = default;

    const audio::RetCode retCode = audio::RetCode::Success;
    audio::Tags tags             = {};
    float val                    = 0.0;
    std::string val;
};

class AudioNotificationMessage : public AudioMessage


@@ 62,16 61,14 @@ class AudioNotificationMessage : public AudioMessage
class AudioSettingsMessage : public AudioMessage
{
  public:
    AudioSettingsMessage(const audio::Profile::Type &profileType,
                         const audio::PlaybackType &playbackType,
    AudioSettingsMessage(const audio::PlaybackType &playbackType,
                         const audio::Setting &setting,
                         const std::string &val = {})
        : AudioMessage{}, profileType{profileType}, playbackType{playbackType}, setting{setting}, val{val}
        : AudioMessage{}, playbackType{playbackType}, setting{setting}, val{val}
    {}

    ~AudioSettingsMessage() override = default;

    audio::Profile::Type profileType = audio::Profile::Type::Idle;
    audio::PlaybackType playbackType = audio::PlaybackType::None;
    const audio::Setting setting;
    std::string val{};


@@ 80,10 77,8 @@ class AudioSettingsMessage : public AudioMessage
class AudioGetSetting : public AudioSettingsMessage
{
  public:
    AudioGetSetting(const audio::Profile::Type &profileType,
                    const audio::PlaybackType &playbackType,
                    const audio::Setting &setting)
        : AudioSettingsMessage{profileType, playbackType, setting}
    AudioGetSetting(const audio::PlaybackType &playbackType, const audio::Setting &setting)
        : AudioSettingsMessage{playbackType, setting}
    {}

    ~AudioGetSetting() override = default;


@@ 92,11 87,8 @@ class AudioGetSetting : public AudioSettingsMessage
class AudioSetSetting : public AudioSettingsMessage
{
  public:
    AudioSetSetting(const audio::Profile::Type &profileType,
                    const audio::PlaybackType &playbackType,
                    const audio::Setting &setting,
                    const std::string &val)
        : AudioSettingsMessage{profileType, playbackType, setting, val}
    AudioSetSetting(const audio::PlaybackType &playbackType, const audio::Setting &setting, const std::string &val)
        : AudioSettingsMessage{playbackType, setting, val}
    {}

    ~AudioSetSetting() override = default;

M module-services/service-audio/service-audio/AudioServiceAPI.hpp => module-services/service-audio/service-audio/AudioServiceAPI.hpp +72 -23
@@ 34,7 34,7 @@ namespace AudioServiceAPI
     *
     * @param serv Requesting service.
     * @param playbackType Type of playback.
     * @param fileName Name of the file.
     * @param fileName Name of the file
     * @return True if request has been sent successfully, false otherwise
     *  Response will come as message AudioStartPlaybackResponse
     */


@@ 130,44 130,93 @@ namespace AudioServiceAPI
     * @return audio::Tags on success, std::nullopt on failure
     */
    std::optional<audio::Tags> GetFileTags(sys::Service *serv, const std::string &fileName);
    /** @brief Gets settings. Current profile is taken by default.

    /** @brief Sets vibrations setting state
     *
     * @param serv - requesting service.
     * @param setting - setting to be set eg. Gain, volume etc.
     * @param value - requested value.
     * @param profileType - selected profile type.
     * @param playbackType -  type of playback. Not used when profileType is different than playback.
     * @param settingState - state to be set.
     * @param playbackType -  type of playback.
     * @return Standard service-api return code. Success if suitable.
     */
    template <typename T>
    audio::RetCode GetSetting(sys::Service *serv,
                              const audio::Setting &setting,
                              T &value,
                              const audio::PlaybackType &playbackType = audio::PlaybackType::None,
                              const audio::Profile::Type &profileType = audio::Profile::Type::Idle);
    /** @brief Sets settings. Current profile is taken by default.
    audio::RetCode SetVibrationSetting(sys::Service *serv,
                                       audio::SettingState settingState,
                                       audio::PlaybackType playbackType);

    /** @brief Gets vibrations setting state
     *
     * @param serv - requesting service.
     * @param playbackType -  type of playback.
     * @return Requested setting state on success. std::nullopt on failure
     */
    std::optional<audio::SettingState> GetVibrationSetting(sys::Service *serv, audio::PlaybackType playbackType);

    /** @brief Sets sound setting state
     *
     * @param serv - requesting service.
     * @param settingState - state to be set.
     * @param playbackType -  type of playback.
     * @return Standard service-api return code. Success if suitable.
     */
    audio::RetCode SetSoundSetting(sys::Service *serv,
                                   audio::SettingState settingState,
                                   audio::PlaybackType playbackType);

    /** @brief Gets sound setting state
     *
     * @param serv - requesting service.
     * @param setting - setting to be set eg. Gain, volume etc.
     * @param value - value to be set.
     * @param profileType - selected profile type.
     * @param playbackType -  type of playback. Not used when profileType is different than playback.
     * @return Requested setting state on success. std::nullopt on failure
     */
    std::optional<audio::SettingState> GetSoundSetting(sys::Service *serv, audio::PlaybackType playbackType);

    /** @brief Sets sound for chosen playback type
     *
     * @param serv - requesting service.
     * @param settingState - path to the file
     * @param playbackType -  type of playback.
     * @return Standard service-api return code. Success if suitable.
     */
    audio::RetCode SetSound(sys::Service *serv, const std::string &filePath, audio::PlaybackType playbackType);

    /** @brief Gets sound for chosen playback type
     *
     * @param serv - requesting service.
     * @param playbackType -  type of playback.
     * @return requested path to the file. Empty string on failure
     */
    std::string GetSound(sys::Service *serv, audio::PlaybackType playbackType);

    /** @brief Sets volume level for chosen playback type
     *
     * @param serv - requesting service.
     * @param vol - volume level
     * @param playbackType -  type of playback.
     * @return Standard service-api return code. Success if suitable.
     */
    template <typename T>
    audio::RetCode SetSetting(sys::Service *serv,
                              const audio::Setting &setting,
                              const T value,
                              const audio::PlaybackType &playbackType = audio::PlaybackType::None,
                              const audio::Profile::Type &profileType = audio::Profile::Type::Idle);
    audio::RetCode SetVolume(sys::Service *serv, const audio::Volume vol, audio::PlaybackType playbackType);

    /** @brief Gets volume level for chosen playback type
     *
     * @param serv - requesting service.
     * @param playbackType -  type of playback.
     * @return requested volume level. std::nullopt on failure
     */
    std::optional<audio::Volume> GetVolume(sys::Service *serv, audio::PlaybackType playbackType);

    /** @brief Key pressed handler.
     *
     * @param serv - requesting service.
     * @param step - step that will be added to current volume.
     * @return True if request has been sent successfully, false otherwise
     *  Response will come as message AudioKeyPressedResponse
     * @note Response will come as message AudioKeyPressedResponse
     */
    bool KeyPressed(sys::Service *serv, const int step);

    /** @brief Bluetooth volume changed handler.
     *
     * @param serv - requesting service.
     * @param volume - volume level
     * @return True if request has been sent successfully, false otherwise
     */
    bool BluetoothVolumeChanged(sys::Service *serv, const uint8_t volume);
}; // namespace AudioServiceAPI

M module-services/service-audio/service-audio/ServiceAudio.hpp => module-services/service-audio/service-audio/ServiceAudio.hpp +2 -4
@@ 10,7 10,6 @@

#include <MessageType.hpp>
#include <Service/Service.hpp>
#include <PhoneModes/Observer.hpp>
#include <Utils.hpp>

#include <service-db/DBServiceAPI.hpp>


@@ 58,7 57,6 @@ class ServiceAudio : public sys::Service
    audio::AudioMux::VibrationStatus vibrationMotorStatus = audio::AudioMux::VibrationStatus::Off;
    std::unique_ptr<settings::Settings> settingsProvider;
    std::map<std::string, std::string> settingsCache;
    std::unique_ptr<sys::phone_modes::Observer> phoneModeObserver;
    bool bluetoothConnected = false;

    auto IsVibrationMotorOn()


@@ 81,7 79,6 @@ class ServiceAudio : public sys::Service
    auto HandleGetFileTags(const std::string &fileName) -> std::unique_ptr<AudioResponseMessage>;
    void HandleNotification(const AudioNotificationMessage::Type &type, const audio::Token &token);
    auto HandleKeyPressed(const int step) -> std::unique_ptr<AudioKeyPressedResponse>;
    void HandlePhoneModeChange(sys::phone_modes::PhoneMode phoneMode);
    void MuteCurrentOperation();
    void VibrationUpdate(const audio::PlaybackType &type               = audio::PlaybackType::None,
                         std::optional<audio::AudioMux::Input *> input = std::nullopt);


@@ 89,12 86,13 @@ class ServiceAudio : public sys::Service

    auto IsVibrationEnabled(const audio::PlaybackType &type) -> bool;
    auto IsOperationEnabled(const audio::PlaybackType &plType, const audio::Operation::Type &opType) -> bool;
    std::string GetSound(const audio::PlaybackType &plType);
    constexpr auto IsResumable(const audio::PlaybackType &type) const -> bool;
    constexpr auto ShouldLoop(const std::optional<audio::PlaybackType> &type) const -> bool;
    auto IsBusy() -> bool;

    //! Setter for settings
    //! \param setting Setting be controlled
    //! \param setting Setting to be controlled
    //! \param value New value of setting
    //! \param profileType Audio profile to be controlled
    //! \param playbackType Playback type to be controlled

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +5 -2
@@ 1850,8 1850,11 @@ void ServiceCellular::onSMSReceived()
    DBServiceAPI::GetQuery(this,
                           db::Interface::Name::Notifications,
                           std::make_unique<db::query::notifications::Increment>(NotificationsRecord::Key::Sms));
    const std::string ringtone_path = "assets/audio/sms_drum_2.mp3";
    AudioServiceAPI::PlaybackStart(this, audio::PlaybackType::TextMessageRingtone, ringtone_path);

    const auto guard = [&]() { return !phoneModeObserver->isInMode(sys::phone_modes::PhoneMode::DoNotDisturb); };
    auto filePath    = AudioServiceAPI::GetSound(this, audio::PlaybackType::TextMessageRingtone);
    utility::conditionally_invoke(
        guard, &AudioServiceAPI::PlaybackStart, this, audio::PlaybackType::TextMessageRingtone, filePath);
}

bool ServiceCellular::receiveAllMessages()