~aleteoryx/muditaos

f7f4adc19f17944349eeae2bcde8e5c98235e4e3 — Maciej Gibowicz 2 years ago 6daeebd
[BH-1264] Add alarm sound fade in

Adding a fade in for the alarm sound (main and power nap) according to
the pattern (V): dt = 30[s] * V/10.
26 files changed, 243 insertions(+), 32 deletions(-)

M harmony_changelog.md
M image/system_a/data/lang/Deutsch.json
M image/system_a/data/lang/English.json
M image/system_a/data/lang/Espanol.json
M image/system_a/data/lang/Francais.json
M image/system_a/data/lang/Polski.json
M module-audio/Audio/Audio.cpp
M module-audio/Audio/Audio.hpp
M module-audio/Audio/AudioCommon.hpp
M products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp
M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp
M products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/AlarmSettingsListItemProvider.cpp
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/AlarmSettingsModel.cpp
M products/BellHybrid/apps/common/include/common/models/AbstractAlarmSettingsModel.hpp
M products/BellHybrid/apps/common/include/common/models/AbstractAudioModel.hpp
M products/BellHybrid/apps/common/include/common/models/AlarmSettingsModel.hpp
M products/BellHybrid/apps/common/include/common/models/AudioModel.hpp
M products/BellHybrid/apps/common/src/AudioModel.cpp
M products/BellHybrid/services/audio/CMakeLists.txt
M products/BellHybrid/services/audio/ServiceAudio.cpp
A products/BellHybrid/services/audio/VolumeFadeIn.cpp
M products/BellHybrid/services/audio/include/audio/AudioMessage.hpp
M products/BellHybrid/services/audio/include/audio/ServiceAudio.hpp
A products/BellHybrid/services/audio/include/audio/VolumeFadeIn.hpp
M products/BellHybrid/services/db/include/db/SystemSettings.hpp
M harmony_changelog.md => harmony_changelog.md +1 -0
@@ 11,6 11,7 @@
* Added labels to Relaxation
* Added date format setting
* Added colors of noise to Relaxation
* Added gradual alarm volume increase

### Changed / Improved
* Optimize the way Relaxation is loading music files

M image/system_a/data/lang/Deutsch.json => image/system_a/data/lang/Deutsch.json +1 -0
@@ 73,6 73,7 @@
    "app_bell_settings_alarm_settings": "Alarmeinstellungen",
    "app_bell_settings_alarm_settings_alarm_tone_and_light": "Hauptalarm",
    "app_bell_settings_alarm_settings_light": "Alarmleuchte",
    "app_bell_settings_alarm_settings_fade": "Erhöht allmählich Alarmlautstärke",
    "app_bell_settings_alarm_settings_prewake_up": "Sanftes Wecken",
    "app_bell_settings_alarm_settings_prewake_up_chime_bottom_description": "vor dem Alarm",
    "app_bell_settings_alarm_settings_prewake_up_chime_tone": "Klang",

M image/system_a/data/lang/English.json => image/system_a/data/lang/English.json +1 -0
@@ 107,6 107,7 @@
    "app_bell_settings_alarm_settings": "Alarm",
    "app_bell_settings_alarm_settings_alarm_tone_and_light": "Main alarm",
    "app_bell_settings_alarm_settings_light": "Main alarm light",
    "app_bell_settings_alarm_settings_fade": "Gradually raise the alarm volume",
    "app_bell_settings_alarm_settings_prewake_up": "Pre-wake up",
    "app_bell_settings_alarm_settings_prewake_up_chime_bottom_description": "before the alarm",
    "app_bell_settings_alarm_settings_prewake_up_chime_tone": "Pre-wake up chime tone",

M image/system_a/data/lang/Espanol.json => image/system_a/data/lang/Espanol.json +1 -0
@@ 72,6 72,7 @@
    "app_bell_settings_alarm_settings": "Ajustes de alarma",
    "app_bell_settings_alarm_settings_alarm_tone_and_light": "Alarma principal",
    "app_bell_settings_alarm_settings_light": "Luz de alarma",
    "app_bell_settings_alarm_settings_fade": "Aumentar vol. alarma gradualmente",
    "app_bell_settings_alarm_settings_prewake_up": "Despertar gradual",
    "app_bell_settings_alarm_settings_prewake_up_chime_bottom_description": "antes de la alarma",
    "app_bell_settings_alarm_settings_prewake_up_chime_tone": "Tono",

M image/system_a/data/lang/Francais.json => image/system_a/data/lang/Francais.json +1 -0
@@ 74,6 74,7 @@
    "app_bell_settings_alarm_settings": "Alarme",
    "app_bell_settings_alarm_settings_alarm_tone_and_light": "Alarme principale",
    "app_bell_settings_alarm_settings_light": "Lumi\u00e8re de r\u00e9veil",
    "app_bell_settings_alarm_settings_fade": "Augmentation graduelle du volume",
    "app_bell_settings_alarm_settings_prewake_up": "Pr\u00e9-r\u00e9veil",
    "app_bell_settings_alarm_settings_prewake_up_chime_bottom_description": "avant l'alarme",
    "app_bell_settings_alarm_settings_prewake_up_chime_tone": "M\u00e9lodie de pr\u00e9-r\u00e9veil",

M image/system_a/data/lang/Polski.json => image/system_a/data/lang/Polski.json +1 -0
@@ 73,6 73,7 @@
    "app_bell_settings_alarm_settings": "Alarm",
    "app_bell_settings_alarm_settings_alarm_tone_and_light": "G\u0142\u00f3wny alarm",
    "app_bell_settings_alarm_settings_light": "\u015awiat\u0142o alarmu",
    "app_bell_settings_alarm_settings_fade": "Stopniowo podnoś głośność alarmu",
    "app_bell_settings_alarm_settings_prewake_up": "Wst\u0119pne budzenie",
    "app_bell_settings_alarm_settings_prewake_up_chime_bottom_description": "przed alarmem",
    "app_bell_settings_alarm_settings_prewake_up_chime_tone": "D\u017awi\u0119k wst\u0119pnego budzenia",

M module-audio/Audio/Audio.cpp => module-audio/Audio/Audio.cpp +3 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Audio.hpp"


@@ 32,7 32,7 @@ namespace audio
        return currentOperation->SendEvent(std::move(evt));
    }

    audio::RetCode Audio::SetOutputVolume(Volume vol)
    audio::RetCode Audio::SetOutputVolume(float vol)
    {
        auto volToSet = vol;
        if (vol > maxVolume) {


@@ 145,7 145,7 @@ namespace audio
    audio::RetCode Audio::Mute()
    {
        muted = Muted::True;
        return SetOutputVolume(0);
        return SetOutputVolume(0.0f);
    }

    void Audio::SendUpdateEventsToCurrentOperation()

M module-audio/Audio/Audio.hpp => module-audio/Audio/Audio.hpp +2 -2
@@ 47,8 47,8 @@ namespace audio
            return currentState;
        }

        // Range 0-1
        audio::RetCode SetOutputVolume(Volume vol);
        // Range 0.0-10.0
        audio::RetCode SetOutputVolume(float vol);

        // Range 0-10
        audio::RetCode SetInputGain(Gain gain);

M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +6 -0
@@ 81,6 81,12 @@ namespace audio
        Other
    };

    enum class FadeIn
    {
        Disable,
        Enable
    };

    /// Used to describe audio operations
    using Context = std::pair<Profile::Type, PlaybackType>;


M products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp => products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp +9 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PlayAudioActions.hpp"


@@ 24,8 24,14 @@ namespace alarms
        if (duration) {
            spawnTimer(*duration);
        }
        return service.bus.sendUnicast(std::make_shared<service::AudioStartPlaybackRequest>(path, playbackType),
                                       service::audioServiceName);
        const auto fadeInSettings = utils::getNumericValue<bool>(
            settings.getValue(bell::settings::Alarm::fadeActive, settings::SettingsScope::Global));
        const auto fadeInEnabled = (fadeInSettings && (playbackType == audio::PlaybackType::Alarm))
                                       ? audio::FadeIn::Enable
                                       : audio::FadeIn::Disable;
        return service.bus.sendUnicast(
            std::make_shared<service::AudioStartPlaybackRequest>(path, playbackType, fadeInEnabled),
            service::audioServiceName);
    }

    bool PlayAudioAction::turnOff()

M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp +5 -2
@@ 89,8 89,11 @@ namespace app::powernap

        const auto &filePath = soundsRepository->titleToPath(
            settings->getValue(bell::settings::Alarm::tone, settings::SettingsScope::Global));

        audioModel.play(filePath.value_or(""), AbstractAudioModel::PlaybackType::Alarm, {});
        const auto fadeInActive = utils::getNumericValue<bool>(settings->getValue(bell::settings::Alarm::fadeActive,
                                                                                  settings::SettingsScope::Global))
                                      ? audio::FadeIn::Enable
                                      : audio::FadeIn::Disable;
        audioModel.play(filePath.value_or(""), AbstractAudioModel::PlaybackType::Alarm, {}, fadeInActive);
        napAlarmTimer.start();
        napFinished = true;
    }

M products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp => products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp +2 -0
@@ 216,11 216,13 @@ namespace app
            gui::BellSettingsAlarmSettingsWindow::name, [this](ApplicationCommon *app, const std::string &) {
                auto alarmToneModel       = std::make_unique<bell_settings::AlarmToneModel>(this);
                auto alarmVolumeModel     = std::make_unique<bell_settings::AlarmVolumeModel>(*audioModel);
                auto alarmFadeOnOffModel  = std::make_unique<bell_settings::AlarmFadeOnOffModel>(this);
                auto alarmLightOnOffModel = std::make_unique<bell_settings::AlarmLightOnOffModel>(this);
                auto alarmFrontlightModel = std::make_unique<bell_settings::AlarmFrontlightModel>(this);
                auto alarmSettingsModel =
                    std::make_unique<bell_settings::AlarmSettingsModel>(std::move(alarmToneModel),
                                                                        std::move(alarmVolumeModel),
                                                                        std::move(alarmFadeOnOffModel),
                                                                        std::move(alarmLightOnOffModel),
                                                                        std::move(alarmFrontlightModel));
                auto soundsRepository = std::make_unique<SoundsRepository>(paths::audio::proprietary() / paths::audio::alarm());

M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/AlarmSettingsListItemProvider.cpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/AlarmSettingsListItemProvider.cpp +6 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BellSettingsStyle.hpp"


@@ 73,6 73,11 @@ namespace app::bell_settings

        internalData.emplace_back(alarmVolume);

        auto onOffFade = new OnOffListItem(settingsModel.getAlarmFadeOnOff(),
                                           utils::translate("app_bell_settings_alarm_settings_fade"));

        internalData.emplace_back(onOffFade);

        auto onOffLight = new OnOffListItem(settingsModel.getAlarmLightOnOff(),
                                            utils::translate("app_bell_settings_alarm_settings_light"));


M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/AlarmSettingsModel.cpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/AlarmSettingsModel.cpp +12 -0
@@ 48,6 48,18 @@ namespace app::bell_settings
        defaultValue = audioModel.getVolume(AbstractAudioModel::PlaybackType::Alarm).value_or(0);
    }

    void AlarmFadeOnOffModel::setValue(bool value)
    {
        const auto valStr = std::to_string(static_cast<int>(value));
        settings.setValue(bell::settings::Alarm::fadeActive, valStr, settings::SettingsScope::Global);
    }

    bool AlarmFadeOnOffModel::getValue() const
    {
        const auto str = settings.getValue(bell::settings::Alarm::fadeActive, settings::SettingsScope::Global);
        return (utils::toNumeric(str) != 0);
    }

    void AlarmLightOnOffModel::setValue(bool value)
    {
        const auto valStr = std::to_string(static_cast<int>(value));

M products/BellHybrid/apps/common/include/common/models/AbstractAlarmSettingsModel.hpp => products/BellHybrid/apps/common/include/common/models/AbstractAlarmSettingsModel.hpp +10 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 17,10 17,12 @@ namespace app::bell_settings
        AbstractAlarmSettingsModel(
            std::unique_ptr<gui::AbstractSettingsModel<UTF8>> alarmTone,
            std::unique_ptr<gui::AbstractSettingsModel<std::uint8_t>> alarmVolume,
            std::unique_ptr<gui::AbstractSettingsModel<bool>> alarmFadeOnOff,
            std::unique_ptr<gui::AbstractSettingsModel<bool>> alarmLightOnOff,
            std::unique_ptr<gui::AbstractSettingsModel<frontlight_utils::Brightness>> alarmFrontlight)
            : alarmTone(std::move(alarmTone)), alarmVolume(std::move(alarmVolume)),
              alarmLightOnOff(std::move(alarmLightOnOff)), alarmFrontlight(std::move(alarmFrontlight))
              alarmFadeOnOff(std::move(alarmFadeOnOff)), alarmLightOnOff(std::move(alarmLightOnOff)),
              alarmFrontlight(std::move(alarmFrontlight))
        {}

        virtual ~AbstractAlarmSettingsModel() = default;


@@ 35,6 37,11 @@ namespace app::bell_settings
            return *alarmVolume;
        }

        gui::AbstractSettingsModel<bool> &getAlarmFadeOnOff()
        {
            return *alarmFadeOnOff;
        }

        gui::AbstractSettingsModel<bool> &getAlarmLightOnOff()
        {
            return *alarmLightOnOff;


@@ 48,6 55,7 @@ namespace app::bell_settings
      private:
        std::unique_ptr<gui::AbstractSettingsModel<UTF8>> alarmTone;
        std::unique_ptr<gui::AbstractSettingsModel<std::uint8_t>> alarmVolume;
        std::unique_ptr<gui::AbstractSettingsModel<bool>> alarmFadeOnOff;
        std::unique_ptr<gui::AbstractSettingsModel<bool>> alarmLightOnOff;
        std::unique_ptr<gui::AbstractSettingsModel<frontlight_utils::Brightness>> alarmFrontlight;
    };

M products/BellHybrid/apps/common/include/common/models/AbstractAudioModel.hpp => products/BellHybrid/apps/common/include/common/models/AbstractAudioModel.hpp +5 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 36,7 36,10 @@ namespace app
        virtual void setVolume(Volume volume, PlaybackType playbackType, OnStateChangeCallback &&callback)  = 0;
        virtual std::optional<Volume> getVolume(PlaybackType playbackType)                                  = 0;
        virtual void getVolume(PlaybackType playbackType, OnGetValueCallback &&callback)                    = 0;
        virtual void play(const std::string &filePath, PlaybackType type, OnStateChangeCallback &&callback) = 0;
        virtual void play(const std::string &filePath,
                          PlaybackType type,
                          OnStateChangeCallback &&callback,
                          audio::FadeIn fadeIn = audio::FadeIn::Disable)                                    = 0;
        virtual void stopAny(OnStateChangeCallback &&callback)                                              = 0;
        virtual void stopPlayedByThis(OnStateChangeCallback &&callback)                                     = 0;
        virtual void pause(OnStateChangeCallback &&callback)                                                = 0;

M products/BellHybrid/apps/common/include/common/models/AlarmSettingsModel.hpp => products/BellHybrid/apps/common/include/common/models/AlarmSettingsModel.hpp +12 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 32,6 32,15 @@ namespace app::bell_settings
        std::uint8_t defaultValue;
    };

    class AlarmFadeOnOffModel : public gui::SettingsModel<bool>
    {
      public:
        using SettingsModel::SettingsModel;

        void setValue(bool value) override;
        bool getValue() const override;
    };

    class AlarmLightOnOffModel : public gui::SettingsModel<bool>
    {
      public:


@@ 55,10 64,12 @@ namespace app::bell_settings
      public:
        AlarmSettingsModel(std::unique_ptr<AlarmToneModel> alarmToneModel,
                           std::unique_ptr<AlarmVolumeModel> alarmVolumeModel,
                           std::unique_ptr<AlarmFadeOnOffModel> alarmFadeOnOffModel,
                           std::unique_ptr<AlarmLightOnOffModel> alarmLightOnOffModel,
                           std::unique_ptr<AlarmFrontlightModel> alarmFrontlightModel)
            : AbstractAlarmSettingsModel(std::move(alarmToneModel),
                                         std::move(alarmVolumeModel),
                                         std::move(alarmFadeOnOffModel),
                                         std::move(alarmLightOnOffModel),
                                         std::move(alarmFrontlightModel))
        {}

M products/BellHybrid/apps/common/include/common/models/AudioModel.hpp => products/BellHybrid/apps/common/include/common/models/AudioModel.hpp +5 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 17,7 17,10 @@ namespace app
        void setVolume(Volume volume, PlaybackType playbackType, OnStateChangeCallback &&callback) override;
        std::optional<Volume> getVolume(PlaybackType playbackType) override;
        void getVolume(PlaybackType playbackType, OnGetValueCallback &&callback) override;
        void play(const std::string &filePath, PlaybackType type, OnStateChangeCallback &&callback) override;
        void play(const std::string &filePath,
                  PlaybackType type,
                  OnStateChangeCallback &&callback,
                  audio::FadeIn fadeIn = audio::FadeIn::Disable) override;
        void stopAny(OnStateChangeCallback &&callback) override;
        void stopPlayedByThis(OnStateChangeCallback &&callback) override;
        void pause(OnStateChangeCallback &&callback) override;

M products/BellHybrid/apps/common/src/AudioModel.cpp => products/BellHybrid/apps/common/src/AudioModel.cpp +5 -2
@@ 73,10 73,13 @@ namespace app
        app->disconnect(typeid(service::AudioEOFNotification));
    }

    void AudioModel::play(const std::string &filePath, PlaybackType type, OnStateChangeCallback &&callback)
    void AudioModel::play(const std::string &filePath,
                          PlaybackType type,
                          OnStateChangeCallback &&callback,
                          audio::FadeIn fadeIn)
    {
        playbackFinishedFlag = false;
        auto msg  = std::make_unique<service::AudioStartPlaybackRequest>(filePath, convertPlaybackType(type));
        auto msg  = std::make_unique<service::AudioStartPlaybackRequest>(filePath, convertPlaybackType(type), fadeIn);
        auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::audioServiceName);

        auto cb = [_callback = callback, this](auto response) {

M products/BellHybrid/services/audio/CMakeLists.txt => products/BellHybrid/services/audio/CMakeLists.txt +2 -0
@@ 13,10 13,12 @@ target_include_directories(bell-audio
target_sources(bell-audio
        PRIVATE
        ServiceAudio.cpp
        VolumeFadeIn.cpp

        PUBLIC
        include/audio/AudioMessage.hpp
        include/audio/ServiceAudio.hpp
        include/audio/VolumeFadeIn.hpp

        )


M products/BellHybrid/services/audio/ServiceAudio.cpp => products/BellHybrid/services/audio/ServiceAudio.cpp +35 -8
@@ 16,9 16,11 @@ namespace
    constexpr auto defaultVolume        = "5";
    constexpr auto defaultSnoozeVolume  = "4";
    constexpr auto defaultBedtimeVolume = "6";
    constexpr audio::Volume maxInVolume = 10;
    constexpr audio::Volume minVolume   = 0;
    constexpr auto maxVolumeToSet       = 10.0f;
    constexpr auto minVolumeToSet       = 0.0f;
    constexpr auto profileType          = audio::Profile::Type::PlaybackLoudspeaker;
    constexpr auto volumeSetting        = audio::Setting::Volume;

    namespace initializer
    {
        using namespace audio;


@@ 69,9 71,19 @@ namespace service
        auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
        bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);

        auto callback = [this](float volumeToSet) {
            const auto clampedValue = std::clamp(volumeToSet, minVolumeToSet, maxVolumeToSet);
            if (const auto activeInput = audioMux.GetActiveInput(); activeInput) {
                if (activeInput.value()) {
                    activeInput.value()->audio->SetOutputVolume(clampedValue);
                }
            }
        };
        volumeFadeIn = std::make_unique<audio::VolumeFadeIn>(this, std::move(callback));

        connect(typeid(AudioStartPlaybackRequest), [this](sys::Message *msg) -> sys::MessagePointer {
            auto *msgl = static_cast<AudioStartPlaybackRequest *>(msg);
            return handleStart(audio::Operation::Type::Playback, msgl->fileName, msgl->playbackType);
            return handleStart(audio::Operation::Type::Playback, msgl->fadeIn, msgl->fileName, msgl->playbackType);
        });

        connect(typeid(AudioInternalEOFNotificationMessage), [this](sys::Message *msg) -> sys::MessagePointer {


@@ 81,6 93,7 @@ namespace service
        });

        connect(typeid(AudioStopRequest), [this](sys::Message *msg) -> sys::MessagePointer {
            volumeFadeIn->Stop();
            auto *msgl = static_cast<AudioStopRequest *>(msg);
            return handleStop(msgl->stopVec, msgl->token);
        });


@@ 134,7 147,8 @@ namespace service
        }
    }

    auto Audio::handleStart(const audio::Operation::Type opType,
    auto Audio::handleStart(audio::Operation::Type opType,
                            audio::FadeIn fadeIn,
                            const std::string &fileName,
                            const audio::PlaybackType &playbackType) -> std::unique_ptr<AudioResponseMessage>
    {


@@ 159,6 173,9 @@ namespace service
        auto input = audioMux.GetPlaybackInput(playbackType);
        AudioStart(input);
        manageCpuSentinel();
        if (fadeIn == audio::FadeIn::Enable) {
            volumeFadeIn->Start(getVolume(playbackType), minVolumeToSet, maxVolumeToSet);
        }

        return std::make_unique<AudioStartPlaybackResponse>(retCode, retToken);
    }


@@ 226,6 243,10 @@ namespace service
        if (const auto input = audioMux.GetInput(token); input) {
            if (shouldLoop((*input)->audio->GetCurrentOperationPlaybackType())) {
                (*input)->audio->Start();
                if (volumeFadeIn->IsActive()) {
                    volumeFadeIn->Restart();
                }

                if ((*input)->audio->IsMuted()) {
                    (*input)->audio->Mute();
                }


@@ 263,7 284,7 @@ namespace service
    {
        constexpr auto setting  = audio::Setting::Volume;
        auto retCode            = audio::RetCode::Success;
        const auto clampedValue = std::clamp(utils::getNumericValue<audio::Volume>(value), minVolume, maxInVolume);
        const auto clampedValue = std::clamp(utils::getNumericValue<float>(value), minVolumeToSet, maxVolumeToSet);

        if (const auto activeInput = audioMux.GetActiveInput(); activeInput) {
            if (activeInput.value()) {


@@ 279,9 300,7 @@ namespace service

    auto Audio::handleGetVolume(const audio::PlaybackType &playbackType) -> std::unique_ptr<AudioResponseMessage>
    {
        constexpr auto setting = audio::Setting::Volume;

        const auto path = dbPath(setting, playbackType, profileType);
        const auto path = dbPath(volumeSetting, playbackType, profileType);
        if (const auto value = settingsProvider->getValue(path); not value.empty()) {
            return std::make_unique<AudioResponseMessage>(audio::RetCode::Success, value);
        }


@@ 289,6 308,14 @@ namespace service
        return std::make_unique<AudioResponseMessage>(audio::RetCode::Failed);
    }

    auto Audio::getVolume(const audio::PlaybackType &playbackType) -> audio::Volume
    {
        const auto path  = dbPath(volumeSetting, playbackType, profileType);
        const auto value = settingsProvider->getValue(path);
        return value.empty() ? utils::getNumericValue<audio::Volume>(defaultVolume)
                             : utils::getNumericValue<audio::Volume>(value);
    }

    sys::ReturnCodes Audio::SwitchPowerModeHandler([[maybe_unused]] const sys::ServicePowerMode mode)
    {
        return sys::ReturnCodes::Success;

A products/BellHybrid/services/audio/VolumeFadeIn.cpp => products/BellHybrid/services/audio/VolumeFadeIn.cpp +71 -0
@@ 0,0 1,71 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "VolumeFadeIn.hpp"
#include <log/log.hpp>

namespace audio
{
    namespace
    {
        constexpr auto timerName{"volumeFadeTimer"};
        constexpr std::chrono::milliseconds fadeInterval{300};
        constexpr auto fadeStep{0.1f};
    } // namespace

    VolumeFadeIn::VolumeFadeIn(sys::Service *parent, SetCallback callback) : setVolumeCallback(callback)
    {
        timerHandle = sys::TimerFactory::createPeriodicTimer(
            parent, timerName, fadeInterval, [this]([[maybe_unused]] sys::Timer &timer) { PerformNextFadeStep(); });
    }

    VolumeFadeIn::~VolumeFadeIn()
    {
        Stop();
    }

    void VolumeFadeIn::Start(float targetVolume, float minVolume, float maxVolume)
    {
        if (targetVolume > maxVolume || minVolume > maxVolume) {
            LOG_ERROR("Incorrect parameters for audio fade in!");
            return;
        }
        this->targetVolume = targetVolume;
        this->minVolume    = minVolume;
        this->maxVolume    = maxVolume;
        currentVolume      = minVolume + fadeStep;
        Restart();
        timerHandle.start();
    }

    void VolumeFadeIn::Restart()
    {
        if (setVolumeCallback != nullptr) {
            setVolumeCallback(currentVolume);
        }
    }

    void VolumeFadeIn::Stop()
    {
        timerHandle.stop();
    }

    bool VolumeFadeIn::IsActive()
    {
        return timerHandle.isActive();
    }

    void VolumeFadeIn::PerformNextFadeStep()
    {
        if (currentVolume < targetVolume) {
            currentVolume = std::clamp(std::min(currentVolume + fadeStep, targetVolume), minVolume, maxVolume);
            if (setVolumeCallback != nullptr) {
                setVolumeCallback(currentVolume);
            }
        }
        else {
            Stop();
        }
    }

} // namespace audio

M products/BellHybrid/services/audio/include/audio/AudioMessage.hpp => products/BellHybrid/services/audio/include/audio/AudioMessage.hpp +6 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 107,12 107,15 @@ namespace service
    class AudioStartPlaybackRequest : public AudioMessage
    {
      public:
        AudioStartPlaybackRequest(const std::string &fileName, const audio::PlaybackType &playbackType)
            : AudioMessage(), fileName(fileName), playbackType(playbackType)
        AudioStartPlaybackRequest(const std::string &fileName,
                                  const audio::PlaybackType &playbackType,
                                  const audio::FadeIn fadeIn = audio::FadeIn::Disable)
            : AudioMessage(), fileName(fileName), playbackType(playbackType), fadeIn(fadeIn)
        {}

        const std::string fileName;
        const audio::PlaybackType playbackType;
        const audio::FadeIn fadeIn;
    };

    class AudioStartPlaybackResponse : public AudioResponseMessage

M products/BellHybrid/services/audio/include/audio/ServiceAudio.hpp => products/BellHybrid/services/audio/include/audio/ServiceAudio.hpp +4 -0
@@ 4,6 4,7 @@
#pragma once

#include "AudioMessage.hpp"
#include "VolumeFadeIn.hpp"
#include <Audio/Audio.hpp>
#include <Audio/AudioMux.hpp>
#include <MessageType.hpp>


@@ 40,6 41,7 @@ namespace service
        };

        auto handleStart(audio::Operation::Type opType,
                         audio::FadeIn fadeIn,
                         const std::string &fileName             = {},
                         const audio::PlaybackType &playbackType = audio::PlaybackType::None)
            -> std::unique_ptr<AudioResponseMessage>;


@@ 49,6 51,7 @@ namespace service
        auto handleSetVolume(const audio::PlaybackType &playbackType, const std::string &value)
            -> std::unique_ptr<AudioResponseMessage>;
        auto handleGetVolume(const audio::PlaybackType &playbackType) -> std::unique_ptr<AudioResponseMessage>;
        auto getVolume(const audio::PlaybackType &playbackType) -> audio::Volume;

        auto handlePause() -> std::unique_ptr<AudioResponseMessage>;
        auto handleResume() -> std::unique_ptr<AudioResponseMessage>;


@@ 69,6 72,7 @@ namespace service
        mutable audio::AudioMux audioMux;
        std::shared_ptr<sys::CpuSentinel> cpuSentinel;
        std::unique_ptr<settings::Settings> settingsProvider;
        std::unique_ptr<audio::VolumeFadeIn> volumeFadeIn;
    };

} // namespace service

A products/BellHybrid/services/audio/include/audio/VolumeFadeIn.hpp => products/BellHybrid/services/audio/include/audio/VolumeFadeIn.hpp +35 -0
@@ 0,0 1,35 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <Timers/TimerFactory.hpp>
#include <Audio/AudioCommon.hpp>

namespace audio
{
    class VolumeFadeIn
    {
      public:
        using SetCallback = std::function<void(float)>;

        VolumeFadeIn(sys::Service *parent, SetCallback callback);
        ~VolumeFadeIn();

        void Start(float targetVolume, float minVolume, float maxVolume);
        void Restart();
        void Stop();
        bool IsActive();

      private:
        sys::TimerHandle timerHandle;
        float targetVolume;
        float minVolume;
        float maxVolume;
        float currentVolume;
        SetCallback setVolumeCallback;

        void PerformNextFadeStep();
    };

} // namespace audio

M products/BellHybrid/services/db/include/db/SystemSettings.hpp => products/BellHybrid/services/db/include/db/SystemSettings.hpp +2 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 26,6 26,7 @@ namespace bell::settings
    namespace Alarm
    {
        constexpr inline auto tone        = "alarm_tone";
        constexpr inline auto fadeActive  = "alarm_fade_active";
        constexpr inline auto lightActive = "alarm_light_active";
        constexpr inline auto duration    = "alarm_duration";
        constexpr inline auto brightness  = "alarm_brightness";