~aleteoryx/muditaos

264b84f5b25ba4f791b58b021302ac9241618dfd — Przemyslaw Brudny 4 years ago dfafd1f + afc3167
Merge remote-tracking branch 'origin/stable'
107 files changed, 963 insertions(+), 472 deletions(-)

A art/bell/bell_off_bottom.png
A art/bell/bell_very_big_mudita_logo.png
A image/assets/images/bell/bell_off_bottom_W_G.vpi
A image/assets/images/bell/bell_very_big_logo_W_G.vpi
M image/assets/lang/Deutsch.json
M image/assets/lang/English.json
M image/assets/lang/Espanol.json
M image/assets/lang/Francais.json
M image/assets/lang/Polski.json
M module-apps/apps-common/ApplicationCommon.cpp
M module-apps/apps-common/ApplicationCommon.hpp
M module-apps/apps-common/popups/WindowWithTimer.cpp
M module-apps/apps-common/popups/WindowWithTimer.hpp
M module-apps/apps-common/widgets/AlarmSetSpinner.cpp
M module-apps/apps-common/widgets/TimeSetFmtSpinner.cpp
M module-bsp/board/rt1051/bellpx/bsp/switches/switches.cpp
M module-bsp/board/rt1051/bellpx/bsp/switches/switches.hpp
M module-gui/gui/widgets/Window.hpp
M module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.cpp
M module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.hpp
M module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp
M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.cpp
M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp
M module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp
M module-services/service-time/AlarmOperations.cpp
M module-services/service-time/AlarmOperations.hpp
M products/BellHybrid/alarms/src/actions/FrontlightAction.cpp
M products/BellHybrid/alarms/src/actions/FrontlightAction.hpp
M products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp
M products/BellHybrid/alarms/src/actions/PlayAudioActions.hpp
M products/BellHybrid/apps/application-bell-background-sounds/ApplicationBellBackgroundSounds.cpp
M products/BellHybrid/apps/application-bell-background-sounds/data/BGSoundsStyle.hpp
M products/BellHybrid/apps/application-bell-background-sounds/include/application-bell-background-sounds/ApplicationBellBackgroundSounds.hpp
M products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsProgressPresenter.cpp
M products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsProgressPresenter.hpp
M products/BellHybrid/apps/application-bell-background-sounds/widgets/BGSoundsPlayer.cpp
M products/BellHybrid/apps/application-bell-background-sounds/widgets/BGSoundsPlayer.hpp
M products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsProgressWindow.cpp
M products/BellHybrid/apps/application-bell-bedtime/ApplicationBellBedtime.cpp
M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp
M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.hpp
M products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp
M products/BellHybrid/apps/application-bell-main/widgets/SnoozeTimer.cpp
M products/BellHybrid/apps/application-bell-main/widgets/SnoozeTimer.hpp
M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp
M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.hpp
M products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.cpp
M products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.hpp
M products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationRunningWindow.cpp
M products/BellHybrid/apps/application-bell-meditation-timer/windows/ReadyGoingWindow.cpp
M products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp
M products/BellHybrid/apps/application-bell-onboarding/CMakeLists.txt
M products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingFinalizeWindow.cpp
M products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingInstructionPromptWindow.cpp
A products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingWelcomeWindow.cpp
A products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingWelcomeWindow.hpp
M products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp
M products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp
M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp
M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp
M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp
M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.hpp
M products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp
M products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/ApplicationBellSettings.hpp
M products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/models/TimeUnitsModel.hpp
M products/BellHybrid/apps/application-bell-settings/models/advanced/FrontlightListItemProvider.cpp
M products/BellHybrid/apps/application-bell-settings/models/advanced/FrontlightModel.cpp
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/SnoozeListItemProvider.cpp
M products/BellHybrid/apps/application-bell-settings/presenter/BedtimeSettingsPresenter.cpp
M products/BellHybrid/apps/application-bell-settings/presenter/BedtimeSettingsPresenter.hpp
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/AlarmSettingsPresenter.cpp
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/AlarmSettingsPresenter.hpp
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.cpp
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.hpp
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/SnoozePresenter.cpp
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/SnoozePresenter.hpp
M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsBedtimeToneWindow.cpp
M products/BellHybrid/apps/application-bell-settings/windows/advanced/BellSettingsFrontlightWindow.cpp
M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsSnoozeWindow.cpp
M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsWindow.cpp
M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsPrewakeUpWindow.cpp
M products/BellHybrid/apps/common/include/common/data/BellFinishedWindowSwitchData.hpp
M products/BellHybrid/apps/common/include/common/models/AbstractAlarmModel.hpp
M products/BellHybrid/apps/common/include/common/models/AbstractAudioModel.hpp
M products/BellHybrid/apps/common/include/common/models/AlarmModel.hpp
M products/BellHybrid/apps/common/include/common/models/AudioModel.hpp
M products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp
M products/BellHybrid/apps/common/include/common/widgets/ListItems.hpp
M products/BellHybrid/apps/common/include/common/windows/BellWelcomeWindow.hpp
M products/BellHybrid/apps/common/src/AlarmModel.cpp
M products/BellHybrid/apps/common/src/AudioModel.cpp
M products/BellHybrid/apps/common/src/popups/BellRebootWindow.cpp
M products/BellHybrid/apps/common/src/windows/BellFinishedWindow.cpp
M products/BellHybrid/apps/common/src/windows/BellTurnOffWindow.cpp
M products/BellHybrid/apps/common/src/windows/BellWelcomeWindow.cpp
M products/BellHybrid/services/evtmgr/CMakeLists.txt
M products/BellHybrid/services/evtmgr/EventManager.cpp
M products/BellHybrid/services/evtmgr/backlight-handler/BacklightHandler.cpp
M products/BellHybrid/services/evtmgr/include/evtmgr/backlight-handler/BacklightHandler.hpp
M products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp
M products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.hpp
M products/BellHybrid/services/time/AlarmOperations.cpp
M products/BellHybrid/services/time/include/time/AlarmOperations.hpp
M products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.cpp
M products/PurePhone/services/evtmgr/include/evtmgr/BacklightHandler.hpp
M products/PurePhone/services/time/AlarmOperations.cpp
M products/PurePhone/services/time/include/time/AlarmOperations.hpp
A art/bell/bell_off_bottom.png => art/bell/bell_off_bottom.png +0 -0
A art/bell/bell_very_big_mudita_logo.png => art/bell/bell_very_big_mudita_logo.png +0 -0
A image/assets/images/bell/bell_off_bottom_W_G.vpi => image/assets/images/bell/bell_off_bottom_W_G.vpi +0 -0
A image/assets/images/bell/bell_very_big_logo_W_G.vpi => image/assets/images/bell/bell_very_big_logo_W_G.vpi +0 -0
M image/assets/lang/Deutsch.json => image/assets/lang/Deutsch.json +1 -0
@@ 607,6 607,7 @@
  "app_bell_settings_time_units_time_message": "Zeit",
  "app_bell_settings_advanced_temp_scale": "Temperaturskala",
  "app_bell_onboarding_finalize": "Gut gemacht!",
  "app_bell_onboarding_welcome": "Willkommen",
  "app_bellmain_home_screen_bottom_desc_dp": "Tief drücken, um zu aktivieren",
  "app_bellmain_home_screen_bottom_desc": "Der nächste Alarm klingelt",
  "app_bellmain_home_screen_bottom_desc_in": "in",

M image/assets/lang/English.json => image/assets/lang/English.json +2 -1
@@ 588,7 588,7 @@
  "app_bell_settings_time_units_time_message": "Time",
  "app_bellmain_alarm": "Alarm",
  "app_bellmain_bedtime": "Bedtime",
  "app_bell_bedtime_notification": "It is Your bedtime",
  "app_bell_bedtime_notification": "It is your bedtime",
  "app_bellmain_power_nap": "Power nap",
  "app_bellmain_meditation_timer": "Meditation",
  "app_bellmain_background_sounds": "Relaxation",


@@ 607,6 607,7 @@
  "app_bell_onboarding_info_deep_click_warning": "<text font='gt_pressura' weight='light' size='38'>You've </text><text font='gt_pressura' weight='regular' size='38'>deep pressed</text>",
  "app_bell_onboarding_info_deep_click_correction": "<text font='gt_pressura' weight='light' size='38'>Be more gentle,<br></br>try </text><text font='gt_pressura' weight='regular' size='38'>light click </text><text font='gt_pressura' weight='light' size='38'>this time</text>",
  "app_bell_onboarding_finalize": "Well done!",
  "app_bell_onboarding_welcome": "Welcome",
  "app_bell_settings_advanced": "Advanced",
  "app_bell_settings_time_units": "Time & units",
  "app_bell_settings_advanced_temp_scale": "Temperature scale",

M image/assets/lang/Espanol.json => image/assets/lang/Espanol.json +1 -0
@@ 615,6 615,7 @@
  "app_bell_onboarding_info_light_click": "<text font='gt_pressura' weight='regular' size='38'>Presiona ligeramente </text><text font='gt_pressura' weight='light' size='38'>para continuar</text>",
  "app_bell_onboarding_info_deep_click_warning": "<text font='gt_pressura' weight='light' size='38'>Has presionado </text><text font='gt_pressura' weight='regular' size='38'>a fondo</text>",
  "app_bell_onboarding_info_deep_click_correction": "<text font='gt_pressura' weight='light' size='38'>Sé más suave, <br></br>intenta </text><text font='gt_pressura' weight='regular' size='38'>presionar ligeramente </text><text font='gt_pressura' weight='light' size='38'>esta vez</text>",
  "app_bell_onboarding_welcome": "Bienvenido",
  "app_bellmain_home_screen_bottom_desc_dp": "Presionar a fondo para activar",
  "app_bellmain_alarm": "Alarma",
  "app_bellmain_power_nap": "Siesta",

M image/assets/lang/Francais.json => image/assets/lang/Francais.json +1 -0
@@ 589,6 589,7 @@
  "app_bell_onboarding_info_light_click": "<text font='gt_pressura' weight='regular' size='38'>Cliquer doucement </text><text font='gt_pressura' weight='light' size='38'>pour continuer</text>",
  "app_bell_onboarding_info_deep_click_warning": "<text font='gt_pressura' weight='light' size='38'>Vous avez </text><text font='gt_pressura' weight='regular' size='38'>appuyé fort</text>",
  "app_bell_onboarding_info_deep_click_correction": "<text font='gt_pressura' weight='light' size='38'>Soyez plus doux, <br></br>essayez </text><text font='gt_pressura' weight='regular' size='38'>de cliquer plus </text><text font='gt_pressura' weight='light' size='38'>légèrement cette fois</text>",
  "app_bell_onboarding_welcome": "Bienvenu",
  "app_bellmain_home_screen_bottom_desc_dp": "Appuyer fort pour activer",
  "app_bellmain_alarm": "Alarme",
  "app_bellmain_background_sounds": "Bruits de fond",

M image/assets/lang/Polski.json => image/assets/lang/Polski.json +2 -1
@@ 625,7 625,8 @@
  "app_bell_onboarding_info_rotate": "<text font='gt_pressura' weight='regular' size='38'>Obróć, </text><text font='gt_pressura' weight='light' size='38'>aby wybrać</text>",
  "app_bell_onboarding_info_light_click": "<text font='gt_pressura' weight='regular' size='38'>Kliknij lekko, </text><text font='gt_pressura' weight='light' size='38'>aby kontynuować</text>",
  "app_bell_onboarding_info_deep_click_warning": "<text font='gt_pressura' weight='light' size='38'>Głęboko </text><text font='gt_pressura' weight='regular' size='38'>wciśnięty</text>",
  "app_bell_onboarding_info_deep_click_correction": "<text font='gt_pressura' weight='light' size='38'>Bądź bardziej delikatny, <br></br>spróbuj </text><text font='gt_pressura' weight='regular' size='38'>tym razem </text><text font='gt_pressura' weight='light' size='38'>lekko kliknąć</text>",
  "app_bell_onboarding_info_deep_click_correction": "<text font='gt_pressura' weight='light' size='38'>Bądź bardziej delikatny,<br></br>spróbuj </text><text font='gt_pressura' weight='regular' size='38'>tym razem<br></br></text><text font='gt_pressura' weight='light' size='38'>lekko kliknąć</text>",
  "app_bell_onboarding_welcome": "Witamy",
  "app_bell_settings_advanced": "Zaawansowane",
  "app_bell_settings_time_units": "Czas i jednostki",
  "app_bell_settings_advanced_temp_scale": "Skala temperatury",

M module-apps/apps-common/ApplicationCommon.cpp => module-apps/apps-common/ApplicationCommon.cpp +12 -4
@@ 540,9 540,17 @@ namespace app
            }
            if (!isCurrentWindow(msg->getWindowName())) {
                if (!windowsStack.isEmpty()) {
                    const auto closeReason = msg->getReason() == SwitchReason::PhoneLock
                                                 ? gui::Window::CloseReason::PhoneLock
                                                 : gui::Window::CloseReason::WindowSwitch;
                    auto closeReason = gui::Window::CloseReason::WindowSwitch;
                    switch (msg->getReason()) {
                    case SwitchReason::PhoneLock:
                        closeReason = gui::Window::CloseReason::PhoneLock;
                        break;
                    case SwitchReason::Popup:
                        closeReason = gui::Window::CloseReason::Popup;
                        break;
                    default:
                        break;
                    }
                    getCurrentWindow()->onClose(closeReason);
                }
                setActiveWindow(msg->getWindowName());


@@ 919,7 927,7 @@ namespace app
                         std::make_unique<gui::AlarmPopupRequestParams>(popupParams));
        }
        else {
            switchWindow(gui::popup::resolveWindowName(id));
            switchWindow(gui::popup::resolveWindowName(id), gui::ShowMode::GUI_SHOW_INIT, nullptr, SwitchReason::Popup);
        }
    }


M module-apps/apps-common/ApplicationCommon.hpp => module-apps/apps-common/ApplicationCommon.hpp +2 -1
@@ 81,7 81,8 @@ namespace app
    enum class SwitchReason
    {
        SwitchRequest,
        PhoneLock
        PhoneLock,
        Popup
    };

    struct StartInBackground

M module-apps/apps-common/popups/WindowWithTimer.cpp => module-apps/apps-common/popups/WindowWithTimer.cpp +4 -4
@@ 25,13 25,13 @@ namespace gui
        };
    }

    void WindowWithTimer::resetTimer()
    void WindowWithTimer::resetTimer(const std::chrono::seconds newTimeout)
    {
        timeout = newTimeout;
        if (!popupTimer.isValid()) {
            popupTimer = app::GuiTimerFactory::createSingleShotTimer(application, this, popup::timerName, timeout);
            popupTimer = app::GuiTimerFactory::createSingleShotTimer(application, this, popup::timerName, newTimeout);
        }
        popupTimer.stop();
        popupTimer.start();
        popupTimer.restart(newTimeout);
    }

    void WindowWithTimer::detachTimerIfExists()

M module-apps/apps-common/popups/WindowWithTimer.hpp => module-apps/apps-common/popups/WindowWithTimer.hpp +2 -2
@@ 13,7 13,7 @@ namespace gui
    {
      private:
        sys::TimerHandle popupTimer;
        const std::chrono::milliseconds timeout;
        std::chrono::milliseconds timeout;

      public:
        explicit WindowWithTimer(app::ApplicationCommon *app,


@@ 27,6 27,6 @@ namespace gui

      protected:
        void detachTimerIfExists();
        void resetTimer();
        void resetTimer(const std::chrono::seconds newTimeout = defautTimeout);
    };
} // namespace gui

M module-apps/apps-common/widgets/AlarmSetSpinner.cpp => module-apps/apps-common/widgets/AlarmSetSpinner.cpp +5 -2
@@ 24,6 24,7 @@ namespace gui
        alarmImg->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        alarmImg->setMargins(Margins(style::alarm_set_spinner::margin, 0, style::alarm_set_spinner::margin, 0));
        alarmImg->setMinimumSizeToFitImage();
        alarmImg->activeItem = false;

        timeSpinner = new TimeSetFmtSpinner(this);
        timeSpinner->setFont(style::window::font::largelight);


@@ 92,7 93,6 @@ namespace gui
    auto AlarmSetSpinner::setAlarmStatus(Status status) noexcept -> void
    {
        alarmStatus = status;
        alarmImg->setMinimumSizeToFitImage();

        switch (alarmStatus) {
        case Status::ACTIVATED:


@@ 116,7 116,10 @@ namespace gui
            break;
        }

        resizeItems();
        alarmImg->setMinimumSizeToFitImage();
        alarmImg->setMaximumSize(alarmImg->widgetMinimumArea.w, alarmImg->widgetMinimumArea.h);

        alarmImg->informContentChanged();
    }

    auto AlarmSetSpinner::setAlarmTimeVisible(bool value) noexcept -> void

M module-apps/apps-common/widgets/TimeSetFmtSpinner.cpp => module-apps/apps-common/widgets/TimeSetFmtSpinner.cpp +5 -4
@@ 100,7 100,7 @@ namespace gui
        }

        timeFormat = newFormat;
        handleContentChanged();
        fmt->handleContentChanged();
    }

    auto TimeSetFmtSpinner::setMinute(int value) noexcept -> void


@@ 261,9 261,10 @@ namespace gui
        fmt->setMinimumWidthToFitText();
        fmt->setMargins(getFmtMargins(noFocusFontName));

        auto widthToSet = fmt->visible ? timeSetSpinner->widgetMinimumArea.w + fmt->widgetMinimumArea.w +
                                             fmt->margins.getSumInAxis(Axis::X)
                                       : timeSetSpinner->widgetMinimumArea.w;
        auto widthToSet =
            timeFormat == utils::time::Locale::TimeFormat::FormatTime12H
                ? timeSetSpinner->widgetMinimumArea.w + fmt->widgetMinimumArea.w + fmt->margins.getSumInAxis(Axis::X)
                : timeSetSpinner->widgetMinimumArea.w;

        setMinimumWidth(widthToSet);
        setMaximumWidth(widgetMinimumArea.w);

M module-bsp/board/rt1051/bellpx/bsp/switches/switches.cpp => module-bsp/board/rt1051/bellpx/bsp/switches/switches.cpp +103 -82
@@ 34,7 34,7 @@ namespace bsp::bell_switches
    constexpr std::chrono::milliseconds contactOscillationTimeout{30ms};
    constexpr std::chrono::milliseconds centerKeyPressValidationTimeout{30ms};

    enum class DebounceTimerId : unsigned int
    enum class KeyId : unsigned int
    {
        leftSideSwitch = 0,
        rightSideSwitch,


@@ 48,11 48,10 @@ namespace bsp::bell_switches

    struct DebounceTimerState
    {
        const DebounceTimerId id{DebounceTimerId::Invalid};
        const NotificationSource notificationSource{NotificationSource::Invalid};
        const KeyId id{KeyId::Invalid};
        const std::shared_ptr<drivers::DriverGPIO> gpio;
        const BoardDefinitions pin{-1};
        KeyEvents lastState{KeyEvents::Pressed};
        volatile KeyEvents lastState{KeyEvents::Pressed};
        TimerHandle_t timer{nullptr};

        void createTimer(TimerCallback callback, const std::chrono::milliseconds timeout)


@@ 71,18 70,19 @@ namespace bsp::bell_switches
        bool changeFlag = false;

      public:
        void setPressed()
        static constexpr bool NO_STATE_CHANGE_INDICATION{false};
        void setPressed(bool changed = true)
        {
            cpp_freertos::LockGuard lock(latchFlagMutex);
            pressed    = true;
            changeFlag = true;
            changeFlag = changed;
        }

        void setReleased()
        void setReleased(bool changed = true)
        {
            cpp_freertos::LockGuard lock(latchFlagMutex);
            pressed    = false;
            changeFlag = true;
            changeFlag = changed;
        }

        bool isPressed()


@@ 105,12 105,60 @@ namespace bsp::bell_switches

    } latchEventFlag;

    static std::map<DebounceTimerId, DebounceTimerState> debounceTimers;
    static std::map<KeyId, DebounceTimerState> debounceTimers;

    static xQueueHandle qHandleIrq{};
    std::shared_ptr<DriverGPIO> gpio_sw;
    std::shared_ptr<DriverGPIO> gpio_wakeup;

    NotificationSource getNotificationSource(KeyId keyId, KeyEvents state)
    {
        auto val = NotificationSource::Invalid;
        if (state == KeyEvents::Released) {
            switch (keyId) {
            case KeyId::leftSideSwitch:
                val = NotificationSource::leftSideKeyRelease;
                break;
            case KeyId::rightSideSwitch:
                val = NotificationSource::rightSideKeyRelease;
                break;
            case KeyId::lightCenterSwitch:
                val = NotificationSource::lightCenterKeyRelease;
                break;
            case KeyId::latchSwitch:
                val = NotificationSource::latchKeyRelease;
                break;
            case KeyId::wakeup:
                val = NotificationSource::wakeupEventRelease;
                break;
            default:
                break;
            }
        }
        else {
            switch (keyId) {
            case KeyId::leftSideSwitch:
                val = NotificationSource::leftSideKeyPress;
                break;
            case KeyId::rightSideSwitch:
                val = NotificationSource::rightSideKeyPress;
                break;
            case KeyId::lightCenterSwitch:
                val = NotificationSource::lightCenterKeyPress;
                break;
            case KeyId::latchSwitch:
                val = NotificationSource::latchKeyPress;
                break;
            case KeyId::wakeup:
                val = NotificationSource::wakeupEvent;
                break;
            default:
                break;
            }
        }
        return val;
    }

    void debounceTimerCallback(TimerHandle_t timerHandle)
    {
        auto timerState                     = static_cast<DebounceTimerState *>(pvTimerGetTimerID(timerHandle));


@@ 119,43 167,17 @@ namespace bsp::bell_switches

        auto currentState = timerState->gpio->ReadPin(static_cast<uint32_t>(timerState->pin)) ? KeyEvents::Released
                                                                                              : KeyEvents::Pressed;

        if (currentState == timerState->lastState && qHandleIrq != nullptr) {
            if (currentState == KeyEvents::Pressed) {
                if (timerState->notificationSource == NotificationSource::latchKeyPress) {
            if (timerState->id == KeyId::latchSwitch) {
                if (currentState == KeyEvents::Pressed) {
                    latchEventFlag.setPressed();
                }
                auto val = static_cast<std::uint16_t>(timerState->notificationSource);
                xQueueSend(qHandleIrq, &val, 0);
                timerState->lastState = KeyEvents::Released;
            }
            else {
                if (timerState->notificationSource == NotificationSource::latchKeyPress) {
                else {
                    latchEventFlag.setReleased();
                }
                auto val = NotificationSource::Invalid;
                switch (timerState->notificationSource) {
                case NotificationSource::leftSideKeyPress:
                    val = NotificationSource::leftSideKeyRelease;
                    break;
                case NotificationSource::rightSideKeyPress:
                    val = NotificationSource::rightSideKeyRelease;
                    break;
                case NotificationSource::lightCenterKeyPress:
                    val = NotificationSource::lightCenterKeyRelease;
                    break;
                case NotificationSource::latchKeyPress:
                    val = NotificationSource::latchKeyRelease;
                    break;
                case NotificationSource::wakeupEvent:
                    val = NotificationSource::wakeupEventRelease;
                    break;
                default:
                    break;
                }
                xQueueSend(qHandleIrq, &val, 0);
                timerState->lastState = KeyEvents::Pressed;
            }
            auto val = static_cast<std::uint16_t>(getNotificationSource(timerState->id, currentState));
            xQueueSend(qHandleIrq, &val, 0);
        }

        timerState->gpio->EnableInterrupt(1U << static_cast<uint32_t>(timerState->pin));


@@ 172,7 194,7 @@ namespace bsp::bell_switches
                latchEventFlag.clearChangedMark();
            }
            else {
                auto val = static_cast<std::uint16_t>(timerState->notificationSource);
                auto val = static_cast<std::uint16_t>(getNotificationSource(timerState->id, KeyEvents::Released));
                xQueueSend(qHandleIrq, &val, 0);
            }
        }


@@ 192,21 214,26 @@ namespace bsp::bell_switches
        debounceTimers.insert({timerState.id, timerState});
        DebounceTimerState &state = debounceTimers.find(timerState.id)->second;

        if (timerState.notificationSource == NotificationSource::lightCenterKeyPress) {
        if (timerState.id == KeyId::lightCenterSwitch) {
            state.createTimer(debounceTimerCenterClickCallback, centerKeyPressValidationTimeout);
        }
        else if (timerState.notificationSource == NotificationSource::latchKeyPress) {
        else {
            state.createTimer(debounceTimerCallback, contactOscillationTimeout);
            state.lastState = getLatchState();
            if (state.lastState == KeyEvents::Released) {
                latchEventFlag.setReleased();
            }
            else {
                latchEventFlag.setPressed();
            }
        }
    }

    void addLatchDebounceTimer(DebounceTimerState timerState)
    {
        debounceTimers.insert({timerState.id, timerState});
        DebounceTimerState &state = debounceTimers.find(timerState.id)->second;

        state.createTimer(debounceTimerCallback, contactOscillationTimeout);
        state.lastState = getLatchState();
        if (state.lastState == KeyEvents::Released) {
            latchEventFlag.setReleased(LatchEventFlag::NO_STATE_CHANGE_INDICATION);
        }
        else {
            state.createTimer(debounceTimerCallback, contactOscillationTimeout);
            latchEventFlag.setPressed(LatchEventFlag::NO_STATE_CHANGE_INDICATION);
        }
    }



@@ 240,33 267,20 @@ namespace bsp::bell_switches
        configureSwitch(BoardDefinitions::BELL_SWITCHES_CENTER, DriverGPIOPinParams::InterruptMode::IntRisingEdge);
        configureSwitch(BoardDefinitions::BELL_WAKEUP, DriverGPIOPinParams::InterruptMode::IntFallingEdge);

        addDebounceTimer(DebounceTimerState{DebounceTimerId::leftSideSwitch,
                                            NotificationSource::leftSideKeyPress,
                                            gpio_sw,
                                            BoardDefinitions::BELL_SWITCHES_LEFT});
        addDebounceTimer(DebounceTimerState{DebounceTimerId::rightSideSwitch,
                                            NotificationSource::rightSideKeyPress,
                                            gpio_sw,
                                            BoardDefinitions::BELL_SWITCHES_RIGHT});
        addDebounceTimer(DebounceTimerState{DebounceTimerId::lightCenterSwitch,
                                            NotificationSource::lightCenterKeyPress,
                                            gpio_sw,
                                            BoardDefinitions::BELL_SWITCHES_CENTER});
        addDebounceTimer(DebounceTimerState{DebounceTimerId::latchSwitch,
                                            NotificationSource::latchKeyPress,
                                            gpio_sw,
                                            BoardDefinitions::BELL_SWITCHES_LATCH,
                                            KeyEvents::Released});
        addDebounceTimer(DebounceTimerState{
            DebounceTimerId::wakeup, NotificationSource::wakeupEvent, gpio_wakeup, BoardDefinitions::BELL_WAKEUP});
        addDebounceTimer(DebounceTimerState{KeyId::leftSideSwitch, gpio_sw, BoardDefinitions::BELL_SWITCHES_LEFT});
        addDebounceTimer(DebounceTimerState{KeyId::rightSideSwitch, gpio_sw, BoardDefinitions::BELL_SWITCHES_RIGHT});
        addDebounceTimer(DebounceTimerState{KeyId::lightCenterSwitch, gpio_sw, BoardDefinitions::BELL_SWITCHES_CENTER});
        addLatchDebounceTimer(DebounceTimerState{
            KeyId::latchSwitch, gpio_sw, BoardDefinitions::BELL_SWITCHES_LATCH, KeyEvents::Released});
        addDebounceTimer(DebounceTimerState{KeyId::wakeup, gpio_wakeup, BoardDefinitions::BELL_WAKEUP});

        if (getLatchState() == KeyEvents::Pressed) {
            latchEventFlag.setPressed();
            auto timerState = static_cast<DebounceTimerState *>(
                pvTimerGetTimerID(debounceTimers[DebounceTimerId::latchSwitch].timer));
            latchEventFlag.setPressed(LatchEventFlag::NO_STATE_CHANGE_INDICATION);
            auto timerState =
                static_cast<DebounceTimerState *>(pvTimerGetTimerID(debounceTimers[KeyId::latchSwitch].timer));
            timerState->lastState = KeyEvents::Released;
        }

        clearStartupLatchInterrupt();
        enableIRQ();

        return kStatus_Success;


@@ 288,13 302,14 @@ namespace bsp::bell_switches
        return kStatus_Success;
    }

    void getDebounceTimer(BaseType_t xHigherPriorityTaskWoken, DebounceTimerId timerId)
    void getDebounceTimer(BaseType_t xHigherPriorityTaskWoken, KeyId timerId)
    {
        if (debounceTimers.find(timerId) == debounceTimers.end()) {
            LOG_ERROR("Could not find debouncer timer for: %s", magic_enum::enum_name(timerId).data());
            return;
        }
        auto debounceTimerState = debounceTimers.at(timerId);
        DebounceTimerState &debounceTimerState = debounceTimers.at(timerId);
        auto temp                              = &debounceTimerState;
        debounceTimerState.gpio->DisableInterrupt(1U << static_cast<uint32_t>(debounceTimerState.pin));
        debounceTimerState.lastState = debounceTimerState.gpio->ReadPin(static_cast<uint32_t>(debounceTimerState.pin))
                                           ? KeyEvents::Released


@@ 307,21 322,21 @@ namespace bsp::bell_switches
    BaseType_t IRQHandler(uint32_t mask)
    {
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        auto timerId                        = DebounceTimerId::Invalid;
        auto timerId                        = KeyId::Invalid;

        gpio_sw->ClearPortInterrupts(1U << mask);

        if (mask & (1 << magic_enum::enum_integer(BoardDefinitions::BELL_SWITCHES_LEFT))) {
            timerId = DebounceTimerId::leftSideSwitch;
            timerId = KeyId::leftSideSwitch;
        }
        else if (mask & (1 << magic_enum::enum_integer(BoardDefinitions::BELL_SWITCHES_RIGHT))) {
            timerId = DebounceTimerId::rightSideSwitch;
            timerId = KeyId::rightSideSwitch;
        }
        else if (mask & (1 << magic_enum::enum_integer(BoardDefinitions::BELL_SWITCHES_CENTER))) {
            timerId = DebounceTimerId::lightCenterSwitch;
            timerId = KeyId::lightCenterSwitch;
        }
        else if (mask & (1 << magic_enum::enum_integer(BoardDefinitions::BELL_SWITCHES_LATCH))) {
            timerId = DebounceTimerId::latchSwitch;
            timerId = KeyId::latchSwitch;
        }

        getDebounceTimer(xHigherPriorityTaskWoken, timerId);


@@ 334,7 349,7 @@ namespace bsp::bell_switches
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        gpio_wakeup->ClearPortInterrupts(1U << static_cast<uint32_t>(BoardDefinitions::BELL_WAKEUP));

        getDebounceTimer(xHigherPriorityTaskWoken, DebounceTimerId::wakeup);
        getDebounceTimer(xHigherPriorityTaskWoken, KeyId::wakeup);

        return xHigherPriorityTaskWoken;
    }


@@ 426,4 441,10 @@ namespace bsp::bell_switches
        return latchEventFlag.isPressed();
    }

    void clearStartupLatchInterrupt()
    {
        // Knob sets up interrupt on startup because of hw design
        gpio_sw->ClearPortInterrupts(1 << static_cast<uint32_t>(BoardDefinitions::BELL_SWITCHES_LATCH));
    }

} // namespace bsp::bell_switches

M module-bsp/board/rt1051/bellpx/bsp/switches/switches.hpp => module-bsp/board/rt1051/bellpx/bsp/switches/switches.hpp +3 -0
@@ 24,4 24,7 @@ namespace bsp::bell_switches
    BaseType_t IRQHandler(uint32_t mask);

    BaseType_t wakeupIRQHandler();

    void clearStartupLatchInterrupt();

} // namespace bsp::bell_switches

M module-gui/gui/widgets/Window.hpp => module-gui/gui/widgets/Window.hpp +2 -1
@@ 39,7 39,8 @@ namespace gui
        {
            ApplicationClose,
            WindowSwitch,
            PhoneLock
            PhoneLock,
            Popup
        };

        Window() = delete;

M module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.cpp => module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.cpp +7 -31
@@ 17,40 17,16 @@ namespace backlight

    HandlerCommon::HandlerCommon(std::shared_ptr<settings::Settings> settings,
                                 std::shared_ptr<screen_light_control::ScreenLightController> screenLightController,
                                 sys::Service *parent)
                                 sys::Service *parent,
                                 sys::timer::TimerCallback &&screenLightTimerCallback)
        : settings{std::move(settings)}, screenLightController{std::move(screenLightController)},
          screenLightTimer{std::make_shared<sys::TimerHandle>(sys::TimerFactory::createSingleShotTimer(
              parent, timers::screenLightTimerName, timers::screenLightTimerTimeout, [this](sys::Timer &t) {
                  if (getScreenAutoModeState() == screen_light_control::ScreenLightMode::Automatic &&
                      this->screenLightController->isLightOn()) {
                      this->screenLightController->processRequest(screen_light_control::Action::turnOff);
                  }
              }))}
          screenLightTimer{std::make_shared<sys::TimerHandle>(
              sys::TimerFactory::createSingleShotTimer(parent,
                                                       timers::screenLightTimerName,
                                                       timers::screenLightTimerTimeout,
                                                       std::move(screenLightTimerCallback)))}
    {}

    void HandlerCommon::init()
    {
        using namespace screen_light_control;
        settings->registerValueChange(settings::Brightness::brightnessLevel, [&](const std::string &value) {
            ManualModeParameters params{utils::getNumericValue<float>(value)};
            screenLightController->processRequest(Action::setManualModeBrightness, Parameters(params));
        });

        settings->registerValueChange(settings::Brightness::autoMode, [&]([[maybe_unused]] const std::string &value) {
            const auto action = getScreenAutoModeState() == ScreenLightMode::Automatic ? Action::enableAutomaticMode
                                                                                       : Action::disableAutomaticMode;
            screenLightController->processRequest(action);
        });

        settings->registerValueChange(settings::Brightness::state, [&]([[maybe_unused]] const std::string &value) {
            const auto action = getScreenLightState() ? Action::turnOn : Action::turnOff;
            if (action == Action::turnOn) {
                onScreenLightTurnedOn();
            }
            screenLightController->processRequest(action);
        });
    }

    auto HandlerCommon::getValue(const std::string &path) const -> std::string
    {
        return settings->getValue(path);

M module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.hpp => module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.hpp +6 -4
@@ 21,10 21,11 @@ namespace backlight
      public:
        HandlerCommon(std::shared_ptr<settings::Settings> settings,
                      std::shared_ptr<screen_light_control::ScreenLightController> screenLightController,
                      sys::Service *parent);
                      sys::Service *parent,
                      sys::timer::TimerCallback &&screenLightTimerCallback);

        /// initialise in InitHandler when Service is ready
        void init();
        virtual void init() = 0;

        /// Process request of the screen light control
        /// @screen_light_control::Action an action to perform


@@ 39,6 40,7 @@ namespace backlight
      private:
        virtual void onScreenLightTurnedOn() = 0;

      protected:
        std::shared_ptr<settings::Settings> settings;
        std::shared_ptr<screen_light_control::ScreenLightController> screenLightController;



@@ 51,8 53,8 @@ namespace backlight
        {
            return screenLightController;
        }
        void handleScreenLightSettings(screen_light_control::Action action,
                                       const screen_light_control::Parameters &params);
        virtual void handleScreenLightSettings(screen_light_control::Action action,
                                               const screen_light_control::Parameters &params);
        void handleScreenLightRefresh();

      protected:

M module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp => module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp +3 -0
@@ 60,6 60,9 @@ namespace screen_light_control::functions
                    rampTargetReached = true;
                }
            }
            else {
                rampTargetReached = true;
            }
        }

        return rampState;

M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.cpp => module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.cpp +6 -0
@@ 24,4 24,10 @@ namespace screen_light_control
        Expects(hasLinearProgressModeParams());
        return linearProgressModeParams.value();
    }

    auto Parameters::getConstLinearProgressModeParams() const noexcept -> const ConstLinearProgressModeParameters &
    {
        Expects(hasConstLinearProgressModeParams());
        return constLinearProgressModeParams.value();
    }
} // namespace screen_light_control

M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp +17 -0
@@ 60,11 60,17 @@ namespace screen_light_control
        float brightnessHysteresis = 0.0f;
    };

    struct ConstLinearProgressModeParameters
    {
        float targetBrightness = 0.0f;
    };

    class Parameters
    {
        std::optional<ManualModeParameters> manualModeParams;
        std::optional<AutomaticModeParameters> autoModeParams;
        std::optional<LinearProgressModeParameters> linearProgressModeParams;
        std::optional<ConstLinearProgressModeParameters> constLinearProgressModeParams;

      public:
        Parameters() = default;


@@ 77,6 83,9 @@ namespace screen_light_control
        explicit Parameters(const LinearProgressModeParameters &autoModeParams)
            : linearProgressModeParams{autoModeParams}
        {}
        explicit Parameters(const ConstLinearProgressModeParameters &autoModeParams)
            : constLinearProgressModeParams{autoModeParams}
        {}

        [[nodiscard]] bool hasManualModeParams() const noexcept
        {


@@ 98,5 107,13 @@ namespace screen_light_control
        }

        [[nodiscard]] auto getLinearProgressModeParams() const noexcept -> const LinearProgressModeParameters &;

        [[nodiscard]] bool hasConstLinearProgressModeParams() const noexcept
        {
            return constLinearProgressModeParams.has_value();
        }

        [[nodiscard]] auto getConstLinearProgressModeParams() const noexcept
            -> const ConstLinearProgressModeParameters &;
    };
} // namespace screen_light_control

M module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp => module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp +15 -0
@@ 80,6 80,21 @@ namespace sevm
        }
    };

    class ScreenLightSetConstLinearModeParams : public ScreenLightControlMessage
    {
        screen_light_control::ConstLinearProgressModeParameters params;

      public:
        explicit ScreenLightSetConstLinearModeParams(screen_light_control::ConstLinearProgressModeParameters params)
            : ScreenLightControlMessage(screen_light_control::Action::setAutomaticModeParameters), params{params}
        {}

        [[nodiscard]] auto getParams() const noexcept -> screen_light_control::ConstLinearProgressModeParameters
        {
            return params;
        }
    };

    class ScreenLightControlRequestParameters : public sys::DataMessage
    {
      public:

M module-services/service-time/AlarmOperations.cpp => module-services/service-time/AlarmOperations.cpp +5 -3
@@ 264,12 264,12 @@ namespace alarms
        }
    }

    auto AlarmOperationsCommon::minuteUpdated(TimePoint now) -> void
    auto AlarmOperationsCommon::minuteUpdated(TimePoint now) -> bool
    {
        processEvents(now);
        return processEvents(now);
    }

    void AlarmOperationsCommon::processEvents(TimePoint now)
    bool AlarmOperationsCommon::processEvents(TimePoint now)
    {
        const auto isHandlingInProgress = !ongoingSingleEvents.empty();
        if (!nextSingleEvents.empty()) {


@@ 284,7 284,9 @@ namespace alarms
            switchAlarmExecution(*(ongoingSingleEvents.front()), true);
            handleActiveAlarmsCountChange();
            handleSnoozedAlarmsCountChange();
            return true;
        }
        return false;
    }

    void AlarmOperationsCommon::addAlarmExecutionHandler(const alarms::AlarmType type,

M module-services/service-time/AlarmOperations.hpp => module-services/service-time/AlarmOperations.hpp +3 -3
@@ 56,7 56,7 @@ namespace alarms
        virtual void postponeSnooze(const std::uint32_t id,
                                    const TimePoint nextAlarmTime,
                                    OnSnoozeRingingAlarm callback)                                    = 0;
        virtual void minuteUpdated(TimePoint now)                                                     = 0;
        virtual bool minuteUpdated(TimePoint now)                                                            = 0;
        virtual void addAlarmExecutionHandler(const alarms::AlarmType type,
                                              const std::shared_ptr<alarms::AlarmHandler> handler)    = 0;
        virtual void stopAllSnoozedAlarms()                                                           = 0;


@@ 100,7 100,7 @@ namespace alarms
        void postponeSnooze(const std::uint32_t id,
                            const TimePoint nextAlarmTime,
                            OnSnoozeRingingAlarm callback) override;
        void minuteUpdated(TimePoint now) override;
        bool minuteUpdated(TimePoint now) override;
        void addAlarmExecutionHandler(const alarms::AlarmType type,
                                      const std::shared_ptr<alarms::AlarmHandler> handler) override;
        void stopAllSnoozedAlarms() override;


@@ 140,7 140,7 @@ namespace alarms
                                     OnGetAlarmsProcessed handledCallback);
        void checkAndUpdateCache(AlarmEventRecord record);
        void switchAlarmExecution(const SingleEventRecord &singleAlarmEvent, bool newStateOn);
        void processEvents(TimePoint now);
        bool processEvents(TimePoint now);
        void processNextEventsQueue(const TimePoint now);
        void processSnoozedEventsQueue(const TimePoint now);
        virtual void onAlarmTurnedOff(const std::shared_ptr<AlarmEventRecord> &event, alarms::AlarmType alarmType);

M products/BellHybrid/alarms/src/actions/FrontlightAction.cpp => products/BellHybrid/alarms/src/actions/FrontlightAction.cpp +7 -8
@@ 55,11 55,17 @@ namespace alarms
    } // namespace

    FrontlightAction::FrontlightAction(sys::Service &service, Mode mode)
        : pimpl{createFrontlightImplementation(service, mode)}
        : pimpl{createFrontlightImplementation(service, mode)}, settings{
                                                                    service::ServiceProxy{service.weak_from_this()}}
    {}

    bool FrontlightAction::execute()
    {
        const std::string flontlightEnabled =
            settings.getValue(bell::settings::Alarm::lightActive, settings::SettingsScope::Global);
        if (flontlightEnabled == std::string(frontlightOFF)) {
            return true;
        }
        return pimpl->execute();
    }



@@ 73,10 79,6 @@ namespace alarms

    bool ManualFrontlightAction::execute()
    {
        service.bus.sendUnicast(
            std::make_shared<sevm::ScreenLightControlMessage>(screen_light_control::Action::disableAutomaticMode),
            service::name::evt_manager);

        auto params = prepareParameters();
        service.bus.sendUnicast(std::make_shared<sevm::ScreenLightControlMessage>(
                                    screen_light_control::Action::turnOn, screen_light_control::Parameters{params}),


@@ 107,9 109,6 @@ namespace alarms
        const auto params = prepareParameters();
        service.bus.sendUnicast(std::make_shared<sevm::ScreenLightSetAutoProgressiveModeParams>(params),
                                service::name::evt_manager);
        service.bus.sendUnicast(
            std::make_shared<sevm::ScreenLightControlMessage>(screen_light_control::Action::enableAutomaticMode),
            service::name::evt_manager);
        service.bus.sendUnicast(std::make_shared<sevm::ScreenLightControlMessage>(screen_light_control::Action::turnOn),
                                service::name::evt_manager);
        return true;

M products/BellHybrid/alarms/src/actions/FrontlightAction.hpp => products/BellHybrid/alarms/src/actions/FrontlightAction.hpp +4 -0
@@ 4,6 4,7 @@
#pragma once

#include "AbstractAlarmAction.hpp"
#include <service-db/Settings.hpp>

#include <Service/Service.hpp>



@@ 23,6 24,9 @@ namespace alarms
        bool turnOff() override;

      private:
        static constexpr auto frontlightOFF = "0";

        std::unique_ptr<AbstractAlarmAction> pimpl;
        settings::Settings settings;
    };
} // namespace alarms

M products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp => products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp +2 -2
@@ 21,7 21,7 @@ namespace alarms

    bool PlayAudioAction::play(const std::filesystem::path &path, std::chrono::minutes duration)
    {
        if (duration != InfiniteDuration) {
        if (duration != InfiniteDuration && duration != NoDuration) {
            spawnTimer(duration);
        }
        return service.bus.sendUnicast(std::make_shared<service::AudioStartPlaybackRequest>(path, playbackType),


@@ 67,7 67,7 @@ namespace alarms
            return std::make_unique<PlayAudioAction>(service,
                                                     paths::getPreWakeUpChimesDir(),
                                                     bell::settings::PrewakeUp::tone,
                                                     bell::settings::PrewakeUp::duration,
                                                     NoPlaybackTimeout,
                                                     audio::PlaybackType::PreWakeUp);
        }


M products/BellHybrid/alarms/src/actions/PlayAudioActions.hpp => products/BellHybrid/alarms/src/actions/PlayAudioActions.hpp +3 -0
@@ 28,6 28,8 @@ namespace alarms

      private:
        static constexpr auto InfiniteDuration = std::chrono::minutes::max();
        static constexpr auto NoDuration       = std::chrono::minutes::zero();

        bool play(const std::filesystem::path &path, std::chrono::minutes duration = InfiniteDuration);
        void spawnTimer(std::chrono::minutes timeout);
        void detachTimer();


@@ 43,6 45,7 @@ namespace alarms

    namespace factory
    {
        static constexpr auto NoPlaybackTimeout = "0";
        std::unique_ptr<PlayAudioAction> createAlarmToneAction(sys::Service &service);
        std::unique_ptr<PlayAudioAction> createPreWakeUpChimeAction(sys::Service &service);
        std::unique_ptr<PlayAudioAction> createSnoozeChimeAction(sys::Service &service);

M products/BellHybrid/apps/application-bell-background-sounds/ApplicationBellBackgroundSounds.cpp => products/BellHybrid/apps/application-bell-background-sounds/ApplicationBellBackgroundSounds.cpp +2 -6
@@ 27,14 27,10 @@ namespace app
                                                                     StartInBackground startInBackground,
                                                                     uint32_t stackDepth)
        : Application(std::move(name), std::move(parent), statusIndicators, startInBackground, stackDepth),
          audioModel{std::make_unique<AudioModel>(this)}, player{
                                                              std::make_unique<bgSounds::BGSoundsPlayer>(*audioModel)}
          audioModel{std::make_unique<AudioModel>(this)}
    {
        player = std::make_unique<bgSounds::BGSoundsPlayer>(*audioModel);
        bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
        connect(typeid(service::AudioEOFNotification), [&](sys::Message *msg) -> sys::MessagePointer {
            auto notification = static_cast<service::AudioEOFNotification *>(msg);
            return player->handle(notification);
        });
    }
    ApplicationBellBackgroundSounds::~ApplicationBellBackgroundSounds() = default;


M products/BellHybrid/apps/application-bell-background-sounds/data/BGSoundsStyle.hpp => products/BellHybrid/apps/application-bell-background-sounds/data/BGSoundsStyle.hpp +1 -1
@@ 7,7 7,7 @@

namespace gui::bgSoundsStyle
{
    inline constexpr auto descriptionFont = style::window::font::verybig;
    inline constexpr auto descriptionFont = style::window::font::verybiglight;
    inline constexpr auto titleFont       = style::window::font::largelight;
    inline constexpr auto timerValueFont  = style::window::font::supersizemelight;
    inline constexpr auto valumeValueFont = style::window::font::supersizemelight;

M products/BellHybrid/apps/application-bell-background-sounds/include/application-bell-background-sounds/ApplicationBellBackgroundSounds.hpp => products/BellHybrid/apps/application-bell-background-sounds/include/application-bell-background-sounds/ApplicationBellBackgroundSounds.hpp +1 -0
@@ 22,6 22,7 @@ namespace app

    class ApplicationBellBackgroundSounds : public Application
    {
      private:
        std::unique_ptr<AbstractAudioModel> audioModel;
        std::unique_ptr<bgSounds::BGSoundsPlayer> player;


M products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsProgressPresenter.cpp => products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsProgressPresenter.cpp +4 -0
@@ 92,4 92,8 @@ namespace app::bgSounds
    {
        return player.isPaused();
    }
    void BGSoundsProgressPresenter::onBeforeShow()
    {
        getView()->setTimeFormat(timeModel->getTimeFormat());
    }
} // namespace app::bgSounds

M products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsProgressPresenter.hpp => products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsProgressPresenter.hpp +2 -0
@@ 47,6 47,7 @@ namespace app::bgSounds
            virtual void setTimer(std::unique_ptr<app::TimerWithCallbacks> &&timer) = 0;
            virtual void handleUpdateTimeEvent()                                    = 0;
            virtual bool isPaused()                                                 = 0;
            virtual void onBeforeShow()                                             = 0;
        };
    };



@@ 66,6 67,7 @@ namespace app::bgSounds
        void setTimer(std::unique_ptr<app::TimerWithCallbacks> &&_timer) override;
        void handleUpdateTimeEvent() override;
        bool isPaused() override;
        void onBeforeShow() override;

        void onFinished();


M products/BellHybrid/apps/application-bell-background-sounds/widgets/BGSoundsPlayer.cpp => products/BellHybrid/apps/application-bell-background-sounds/widgets/BGSoundsPlayer.cpp +5 -7
@@ 6,13 6,6 @@

namespace app::bgSounds
{
    auto BGSoundsPlayer::handle(service::AudioEOFNotification *msg) -> std::shared_ptr<sys::Message>
    {
        if (playbackMode == PlaybackMode::Looped) {
            audioModel.play(recentFilePath, AbstractAudioModel::PlaybackType::Multimedia, {});
        }
        return sys::msgHandled();
    }
    AbstractBGSoundsPlayer::PlaybackMode BGSoundsPlayer::getCurrentMode() const noexcept
    {
        return playbackMode;


@@ 26,6 19,11 @@ namespace app::bgSounds
        recentFilePath = filePath;
        playbackMode   = mode;
        audioModel.play(filePath, AbstractAudioModel::PlaybackType::Multimedia, std::move(callback));
        audioModel.setPlaybackFinishedCb([&]() {
            if (playbackMode == PlaybackMode::Looped) {
                audioModel.play(recentFilePath, AbstractAudioModel::PlaybackType::Multimedia, {});
            }
        });
    }
    void BGSoundsPlayer::stop(AbstractAudioModel::OnStateChangeCallback &&callback)
    {

M products/BellHybrid/apps/application-bell-background-sounds/widgets/BGSoundsPlayer.hpp => products/BellHybrid/apps/application-bell-background-sounds/widgets/BGSoundsPlayer.hpp +0 -2
@@ 41,8 41,6 @@ namespace app::bgSounds
      public:
        explicit BGSoundsPlayer(AbstractAudioModel &audioModel);

        auto handle(service::AudioEOFNotification *msg) -> std::shared_ptr<sys::Message>;

      private:
        void start(const std::string &filePath,
                   PlaybackMode mode,

M products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsProgressWindow.cpp => products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsProgressWindow.cpp +3 -0
@@ 75,6 75,8 @@ namespace gui

    void BGSoundsProgressWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        presenter->onBeforeShow();

        if (mode == ShowMode::GUI_SHOW_RETURN && presenter->isPaused()) {
            presenter->resume();
            return;


@@ 105,6 107,7 @@ namespace gui
        progressBar = createProgress(vBox);
        timerText   = createTimer(body->lastBox);
        time        = createClock(body->firstBox);
        updateTime();
        body->firstBox->resizeItems();
        vBox->resizeItems();


M products/BellHybrid/apps/application-bell-bedtime/ApplicationBellBedtime.cpp => products/BellHybrid/apps/application-bell-bedtime/ApplicationBellBedtime.cpp +1 -1
@@ 34,7 34,7 @@ namespace app
    {
        windowsFactory.attach(gui::name::window::main_window, [](ApplicationCommon *app, const std::string &) {
            auto audioModel   = std::make_unique<AudioModel>(app);
            auto bedtimeModel = std::make_unique<bell_bedtime::BedtimeModel>(app, std::move(audioModel));
            auto bedtimeModel = std::make_unique<bell_bedtime::BedtimeModel>(app, *audioModel);
            auto provider     = std::make_shared<bell_bedtime::BedtimeListItemProvider>(std::move(bedtimeModel));
            auto presenter    = std::make_unique<bell_bedtime::BellBedtimeWindowPresenter>(provider);
            return std::make_unique<gui::BellBedtimeWindow>(app, std::move(presenter));

M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp => products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp +14 -0
@@ 46,6 46,7 @@ namespace app::home_screen
    {
        getView()->setTime(timeModel->getCurrentTime());
        stateController->handleTimeUpdateEvent();
        handleCyclicDeepRefresh();
    }

    void HomeScreenPresenter::handleAlarmRingingEvent()


@@ 137,6 138,7 @@ namespace app::home_screen
    {
        return batteryModel->getLevelState().level;
    }

    bool HomeScreenPresenter::isBatteryCharging() const
    {
        return batteryModel->getLevelState().state == Store::Battery::State::Charging;


@@ 155,4 157,16 @@ namespace app::home_screen
            isStartup = false;
        }
    }

    void HomeScreenPresenter::handleCyclicDeepRefresh()
    {
        constexpr auto deepRefreshPeriod = 30;
        static auto refreshCount         = 0;

        if (refreshCount >= deepRefreshPeriod) {
            app->refreshWindow(gui::RefreshModes::GUI_REFRESH_DEEP);
            refreshCount = 0;
        }
        refreshCount++;
    }
} // namespace app::home_screen

M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.hpp => products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.hpp +17 -14
@@ 74,24 74,25 @@ namespace app::home_screen
        virtual void setBatteryLevelState(const Store::Battery &batteryContext) = 0;

        /// Various
        virtual void switchToMenu()          = 0;
        virtual void switchToBatteryStatus() = 0;
        virtual void switchToMenu()                  = 0;
        virtual void switchToBatteryStatus()         = 0;
        virtual void setSnoozeTime(std::time_t time) = 0;
    };

    class AbstractPresenter : public BasePresenter<AbstractView>
    {
      public:
        virtual ~AbstractPresenter() noexcept                                       = default;
        virtual void createData()                                                   = 0;
        virtual void handleUpdateTimeEvent()                                        = 0;
        virtual bool handleInputEvent(const gui::InputEvent &inputEvent)            = 0;
        virtual void onBeforeShow()                                                 = 0;
        virtual void onDatabaseMessage(db::NotificationMessage *msg)                = 0;
        virtual void refreshWindow()                                                = 0;
        virtual void spawnTimer(std::chrono::milliseconds timeout = defaultTimeout) = 0;
        virtual void detachTimer()                                                  = 0;
        virtual void handleAlarmRingingEvent()                                      = 0;
        virtual void handleAlarmModelReady()                                        = 0;
        virtual ~AbstractPresenter() noexcept                                                    = default;
        virtual void createData()                                                                = 0;
        virtual void handleUpdateTimeEvent()                                                     = 0;
        virtual bool handleInputEvent(const gui::InputEvent &inputEvent)                         = 0;
        virtual void onBeforeShow()                                                              = 0;
        virtual void onDatabaseMessage(db::NotificationMessage *msg)                             = 0;
        virtual void refreshWindow()                                                             = 0;
        virtual void spawnTimer(std::chrono::milliseconds timeout = defaultTimeout)              = 0;
        virtual void detachTimer()                                                               = 0;
        virtual void handleAlarmRingingEvent()                                                   = 0;
        virtual void handleAlarmModelReady()                                                     = 0;
        virtual void setSnoozeTimer(std::unique_ptr<app::ProgressTimerWithSnoozeTimer> &&_timer) = 0;
        virtual void startSnoozeTimer(std::chrono::seconds snoozeDuration)                       = 0;
        virtual void stopSnoozeTimer()                                                           = 0;


@@ 151,7 152,9 @@ namespace app::home_screen

        void setStartupAlarmState();

        static constexpr auto timerName = "HS_timer";
        void handleCyclicDeepRefresh();

        static constexpr auto timerName  = "HS_timer";
        static constexpr auto snoozeTick = std::chrono::seconds(1);
    };
} // namespace app::home_screen

M products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp => products/BellHybrid/apps/application-bell-main/presenters/StateController.cpp +23 -8
@@ 83,12 83,15 @@ namespace app::home_screen
                alarmModel.setDefaultAlarmTime();
                view.setAlarmTime(alarmModel.getAlarmTime());
            };
            auto turnOffRingingAlarm = [](AbstractAlarmModel &alarmModel) { alarmModel.turnOff(); };
        } // namespace Helpers

        namespace Events
        {
            struct BackPress
            {};
            struct LongBackPress
            {};
            struct LightPress
            {};
            struct RotateRightPress


@@ 255,7 258,7 @@ namespace app::home_screen
                view.setHeaderViewMode(HeaderViewMode::SnoozeCountdown);

                const auto snoozeDuration = alarmModel.getTimeToNextSnooze();
                presenter.startSnoozeTimer(snoozeDuration);
                view.setSnoozeTime(alarmModel.getTimeOfNextSnooze());
                const auto bottomDescription = utils::translate("app_bellmain_home_screen_bottom_desc") + " " +
                                               std::to_string(alarmModel.getSnoozeDuration()) + " min";
                view.setBottomDescription(bottomDescription);


@@ 293,7 296,7 @@ namespace app::home_screen
                                             "Deactivated"_s + event<Events::RotateRightPress> / Helpers::makeAlarmEditable = "DeactivatedEdit"_s,
                                             "Deactivated"_s + event<Events::DeepUpPress> = "ActivatedWait"_s,
                                             "Deactivated"_s + event<Events::TimeUpdate> / Helpers::updateBottomStats,
                                             "Deactivated"_s + event<Events::BackPress>  / Helpers::switchToBatteryStatus,
                                             "Deactivated"_s + event<Events::LongBackPress>  / Helpers::switchToBatteryStatus,

                                             "DeactivatedWait"_s + sml::on_entry<_> / DeactivatedWait::entry,
                                             "DeactivatedWait"_s + sml::on_exit<_> / DeactivatedWait::exit,


@@ 309,6 312,7 @@ namespace app::home_screen
                                             "DeactivatedEdit"_s + sml::on_exit<_> / AlarmEdit::exit,
                                             "DeactivatedEdit"_s + event<Events::Reset> = "Init"_s,
                                             "DeactivatedEdit"_s + event<Events::TimeUpdate> / Helpers::updateBottomStats,
                                             "DeactivatedEdit"_s + event<Events::Timer> = "Deactivated"_s,
                                             "DeactivatedEdit"_s + event<Events::RotateLeftPress> / AlarmEdit::processRotateLeft,
                                             "DeactivatedEdit"_s + event<Events::RotateRightPress> / AlarmEdit::processRotateRight,
                                             "DeactivatedEdit"_s + event<Events::DeepUpPress> / Helpers::setNewAlarmTime = "ActivatedWait"_s,


@@ 345,12 349,13 @@ namespace app::home_screen
                                             "Activated"_s + event<Events::TimeUpdate> / Helpers::updateBottomStats,
                                             "Activated"_s + event<Events::DeepDownPress>  = "DeactivatedWait"_s,
                                             "Activated"_s + event<Events::AlarmRinging>  = "AlarmRinging"_s,
                                             "Activated"_s + event<Events::BackPress>  / Helpers::switchToBatteryStatus,
                                             "Activated"_s + event<Events::LongBackPress>  / Helpers::switchToBatteryStatus,

                                             "ActivatedEdit"_s + sml::on_entry<_> / AlarmEdit::entry,
                                             "ActivatedEdit"_s + sml::on_exit<_> / AlarmEdit::exit,
                                             "ActivatedEdit"_s + event<Events::Reset> = "Init"_s,
                                             "ActivatedEdit"_s + event<Events::TimeUpdate> / Helpers::updateBottomStats,
                                             "ActivatedEdit"_s + event<Events::Timer> = "Activated"_s,
                                             "ActivatedEdit"_s + event<Events::RotateLeftPress> / AlarmEdit::processRotateLeft,
                                             "ActivatedEdit"_s + event<Events::RotateRightPress> / AlarmEdit::processRotateRight,
                                             "ActivatedEdit"_s + event<Events::LightPress> / Helpers::setNewAlarmTime = "ActivatedWait"_s,


@@ 361,10 366,15 @@ namespace app::home_screen
                                             "AlarmRinging"_s + sml::on_exit<_> / AlarmRinging::exit,
                                             "AlarmRinging"_s + event<Events::Reset> = "Init"_s,
                                             "AlarmRinging"_s + event<Events::Timer> [Helpers::isSnoozeAllowed] / Helpers::snooze = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::Timer> [!Helpers::isSnoozeAllowed] = "ActivatedWait"_s,
                                             "AlarmRinging"_s + event<Events::LightPress> = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::RotateLeftPress> = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::RotateRightPress> = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::Timer> [not Helpers::isSnoozeAllowed] / Helpers::turnOffRingingAlarm = "ActivatedWait"_s,
                                             "AlarmRinging"_s + event<Events::LightPress> [Helpers::isSnoozeAllowed] = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::LightPress> [not Helpers::isSnoozeAllowed] / Helpers::turnOffRingingAlarm  = "ActivatedWait"_s,
                                             "AlarmRinging"_s + event<Events::RotateLeftPress> [Helpers::isSnoozeAllowed] = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::RotateLeftPress> [not Helpers::isSnoozeAllowed] / Helpers::turnOffRingingAlarm  = "ActivatedWait"_s,
                                             "AlarmRinging"_s + event<Events::RotateRightPress> [Helpers::isSnoozeAllowed] = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::RotateRightPress> [not Helpers::isSnoozeAllowed] / Helpers::turnOffRingingAlarm  = "ActivatedWait"_s,
                                             "AlarmRinging"_s + event<Events::BackPress> [Helpers::isSnoozeAllowed] = "AlarmSnoozedWait"_s,
                                             "AlarmRinging"_s + event<Events::BackPress> [not Helpers::isSnoozeAllowed] / Helpers::turnOffRingingAlarm  = "ActivatedWait"_s,
                                             "AlarmRinging"_s + event<Events::DeepDownPress> = "AlarmRingingDeactivatedWait"_s,

                                             "AlarmRingingDeactivatedWait"_s + sml::on_entry<_> / AlarmRingingDeactivatedWait::entry,


@@ 451,7 461,12 @@ namespace app::home_screen
        const auto key = mapKey(inputEvent.getKeyCode());
        switch (key) {
        case KeyMap::Back:
            pimpl->sm.process_event(Events::BackPress{});
            if (inputEvent.getState() == gui::InputEvent::State::keyReleasedLong) {
                pimpl->sm.process_event(Events::LongBackPress{});
            }
            else {
                pimpl->sm.process_event(Events::BackPress{});
            }
            break;
        case KeyMap::LightPress:
            pimpl->sm.process_event(Events::LightPress{});

M products/BellHybrid/apps/application-bell-main/widgets/SnoozeTimer.cpp => products/BellHybrid/apps/application-bell-main/widgets/SnoozeTimer.cpp +4 -12
@@ 20,17 20,6 @@ namespace gui
        alarmImg->setMargins(Margins(10U, 0, 10U, 0));
        alarmImg->setMinimumSizeToFitImage();

        minusText = new TextFixedSize(this, 0, 0, 0, 0);
        minusText->setText("-");
        minusText->setFont(style::window::font::largelight);
        minusText->setMargins(Margins(0, 0, 0, 0));
        minusText->setMinimumHeightToFitText();
        minusText->setMinimumWidthToFitText();
        minusText->drawUnderline(false);
        minusText->setEditMode(EditMode::Browse);
        minusText->activeItem = false;
        minusText->setAlignment(Alignment(Alignment::Horizontal::Right, Alignment::Vertical::Center));

        timeSpinner = new TimeSetSpinner(this);
        timeSpinner->setFont(style::window::font::largelight);
        timeSpinner->setEditMode(EditMode::Browse);


@@ 44,7 33,6 @@ namespace gui
    auto SnoozeTimer::setFont(std::string newFontName) noexcept -> void
    {
        fontName = std::move(newFontName);
        minusText->setFont(fontName);
        timeSpinner->setFont(fontName);
    }



@@ 52,5 40,9 @@ namespace gui
    {
        timeSpinner->setTime(mins, secs);
    }
    auto SnoozeTimer::setTime(std::time_t time) noexcept -> void
    {
        timeSpinner->setTime(time);
    }

} /* namespace gui */

M products/BellHybrid/apps/application-bell-main/widgets/SnoozeTimer.hpp => products/BellHybrid/apps/application-bell-main/widgets/SnoozeTimer.hpp +1 -1
@@ 31,10 31,10 @@ namespace gui

        auto setFont(std::string newFontName) noexcept -> void;
        auto setTime(std::uint8_t mins, std::uint8_t secs) noexcept -> void;
        auto setTime(std::time_t time) noexcept -> void;

      private:
        TimeSetSpinner *timeSpinner = nullptr;
        TextFixedSize *minusText    = nullptr;

        Status alarmStatus   = Status::DEACTIVATED;
        std::string fontName = style::window::font::largelight;

M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp => products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp +5 -1
@@ 259,7 259,7 @@ namespace gui

    bool BellHomeScreenWindow::onInput(const InputEvent &inputEvent)
    {
        if (inputEvent.isShortRelease()) {
        if (inputEvent.isShortRelease() || inputEvent.isLongRelease()) {
            return presenter->handleInputEvent(inputEvent);
        }
        return false;


@@ 327,5 327,9 @@ namespace gui
                                  std::make_unique<gui::BellBatteryStatusWindow::Data>(presenter->getBatteryLvl(),
                                                                                       presenter->isBatteryCharging()));
    }
    void BellHomeScreenWindow::setSnoozeTime(std::time_t newTime)
    {
        snoozeTimer->setTime(newTime);
    }

} // namespace gui

M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.hpp => products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.hpp +1 -0
@@ 52,6 52,7 @@ namespace gui
        void setHeaderViewMode(app::home_screen::HeaderViewMode mode) override;
        std::time_t getAlarmTime() const override;
        void setAlarmTime(std::time_t newTime) override;
        void setSnoozeTime(std::time_t newTime) override;
        void incAlarmMinute() override;
        void decAlarmMinute() override;


M products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.cpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.cpp +3 -2
@@ 76,8 76,9 @@ namespace app::meditation
    void MeditationProgressPresenter::finish()
    {
        timer->stop();
        app->switchWindow(gui::window::bell_finished::defaultName,
                          gui::BellFinishedWindowData::Factory::create("big_namaste_W_G", "", "", true));
        app->switchWindow(
            gui::window::bell_finished::defaultName,
            gui::BellFinishedWindowData::Factory::create("big_namaste_W_G", "", "", true, endWindowTimeout));
    }

    void MeditationProgressPresenter::onProgressFinished()

M products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.hpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.hpp +2 -0
@@ 64,6 64,8 @@ namespace app::meditation
        std::chrono::minutes duration;
        std::chrono::minutes interval;

        static constexpr auto endWindowTimeout = std::chrono::seconds{5};

        void onProgressFinished();
        void onIntervalReached();


M products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationRunningWindow.cpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationRunningWindow.cpp +1 -0
@@ 96,6 96,7 @@ namespace gui
        time = new BellStatusClock(body->firstBox);
        time->setMaximumSize(body->firstBox->getWidth(), body->firstBox->getHeight());
        time->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        updateTime();
        body->firstBox->resizeItems();

        dimensionChangedCallback = [&](Item &, const BoundingBox &newDim) -> bool {

M products/BellHybrid/apps/application-bell-meditation-timer/windows/ReadyGoingWindow.cpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/ReadyGoingWindow.cpp +1 -1
@@ 7,7 7,7 @@

namespace
{
    constexpr inline auto defaultTimeout = std::chrono::seconds{5};
    constexpr inline auto defaultTimeout = std::chrono::seconds{10};
}

namespace gui

M products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp => products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp +55 -17
@@ 7,6 7,7 @@
#include <windows/OnBoardingLanguageWindow.hpp>
#include <windows/OnBoardingFinalizeWindow.hpp>
#include <windows/OnBoardingSettingsWindow.hpp>
#include <windows/OnBoardingWelcomeWindow.hpp>
#include <windows/OnBoardingInstructionPromptWindow.hpp>

#include <service-appmgr/Constants.hpp>


@@ 60,9 61,14 @@ namespace app
    {
        windowsFactory.attach(gui::name::window::main_window, [this](ApplicationCommon *app, const std::string &name) {
            return std::make_unique<gui::BellWelcomeWindow>(
                app, name, [app]() { app->switchWindow(gui::window::name::onBoardingLanguageWindow); });
                app, name, [app]() { app->switchWindow(gui::window::name::onBoardingWelcomeWindow); });
        });

        windowsFactory.attach(gui::window::name::onBoardingWelcomeWindow,
                              [this](ApplicationCommon *app, const std::string &name) {
                                  return std::make_unique<gui::OnBoardingWelcomeWindow>(app, name);
                              });

        windowsFactory.attach(
            gui::window::name::onBoardingLanguageWindow, [this](ApplicationCommon *app, const std::string &name) {
                auto presenter = std::make_unique<OnBoarding::OnBoardingLanguageWindowPresenter>(this);


@@ 158,7 164,9 @@ namespace app
        auto currentWindow = getCurrentWindow()->getName();
        return (currentWindow != gui::name::window::main_window &&
                currentWindow != gui::window::name::finalizeOnBoardingWindow &&
                currentWindow != gui::window::name::informationOnBoardingWindow);
                currentWindow != gui::window::name::onBoardingWelcomeWindow &&
                (currentWindow != gui::window::name::informationOnBoardingWindow ||
                 informationState == OnBoarding::InformationStates::DeepClickWarningInfo));
    }

    void ApplicationBellOnBoarding::startTimerOnWindows()


@@ 183,6 191,8 @@ namespace app

            informationState = OnBoarding::InformationStates::DeepClickCorrectionInfo;
            displayInformation(msg->getWindowName());
        }
        if (selectedWindowCondition && informationState == OnBoarding::InformationStates::DeepClickCorrectionInfo) {
            informationState = OnBoarding::InformationStates::RotateInfo;
        }



@@ 201,29 211,57 @@ namespace app
        auto inputEvent = static_cast<AppInputEventMessage *>(msgl)->getEvent();

        if (isInformationPromptPermittedOnCurrentWindow()) {
            startTimerOnWindows();

            if (inputEvent.isKeyRelease(gui::KeyCode::KEY_UP) || inputEvent.isKeyRelease(gui::KeyCode::KEY_DOWN)) {
                informationState = OnBoarding::InformationStates::LightClickInfo;
            }
            else if (inputEvent.isKeyRelease(gui::KeyCode::KEY_RIGHT)) {
            else if (inputEvent.isKeyRelease(gui::KeyCode::KEY_RIGHT) ||
                     inputEvent.isKeyRelease(gui::KeyCode::KEY_LEFT)) {
                informationState = OnBoarding::InformationStates::DeepClickWarningInfo;
                displayInformation(getCurrentWindow()->getName());
                if (getCurrentWindow()->getName() == gui::window::name::informationOnBoardingWindow) {
                    displayInformation(getPrevWindow());
                }
                else {
                    displayInformation(getCurrentWindow()->getName());
                }
            }
            else if (inputEvent.isKeyRelease(gui::KeyCode::KEY_ENTER)) {
                informationState = OnBoarding::InformationStates::RotateInfo;
                if (informationState == OnBoarding::InformationStates::DeepClickWarningInfo) {
                    informationPromptTimer.stop();
                    informationState = OnBoarding::InformationStates::DeepClickCorrectionInfo;
                    displayInformation(getPrevWindow());
                }
                else {
                    informationState = OnBoarding::InformationStates::RotateInfo;
                }
            }

            return false;
        }

        if (inputEvent.isKeyRelease(gui::KeyCode::KEY_ENTER) &&
            informationState == OnBoarding::InformationStates::DeepClickWarningInfo) {
            informationState = OnBoarding::InformationStates::DeepClickCorrectionInfo;

            displayInformation(getPrevWindow());
            informationState = OnBoarding::InformationStates::RotateInfo;
            return true;
        else {
            if (getCurrentWindow()->getName() == gui::window::name::informationOnBoardingWindow) {
                switch (informationState) {
                case OnBoarding::InformationStates::DeepClickCorrectionInfo:
                    if (inputEvent.isKeyRelease(gui::KeyCode::KEY_ENTER)) {
                        switchWindow(getPrevWindow());
                        return true;
                    }
                    break;
                case OnBoarding::InformationStates::LightClickInfo:
                    if (inputEvent.isKeyRelease(gui::KeyCode::KEY_ENTER)) {
                        switchWindow(getPrevWindow());
                        return true;
                    }
                    break;
                case OnBoarding::InformationStates::RotateInfo:
                    if (inputEvent.isKeyRelease(gui::KeyCode::KEY_UP) ||
                        inputEvent.isKeyRelease(gui::KeyCode::KEY_DOWN) ||
                        inputEvent.isKeyRelease(gui::KeyCode::KEY_ENTER)) {
                        switchWindow(getPrevWindow());
                        return true;
                    }
                    break;
                default:
                    break;
                }
            }
        }

        return false;

M products/BellHybrid/apps/application-bell-onboarding/CMakeLists.txt => products/BellHybrid/apps/application-bell-onboarding/CMakeLists.txt +2 -0
@@ 17,6 17,7 @@ target_sources(application-bell-onboarding
        windows/OnBoardingSettingsWindow.cpp
        windows/OnBoardingFinalizeWindow.cpp
        windows/OnBoardingInstructionPromptWindow.cpp
        windows/OnBoardingWelcomeWindow.cpp
        presenter/OnBoardingLanguageWindowPresenter.cpp
        presenter/OnBoardingFinalizeWindowPresenter.cpp



@@ 25,6 26,7 @@ target_sources(application-bell-onboarding
        windows/OnBoardingLanguageWindow.hpp
        windows/OnBoardingSettingsWindow.hpp
        windows/OnBoardingInstructionPromptWindow.hpp
        windows/OnBoardingWelcomeWindow.hpp

    PUBLIC
        include/application-bell-onboarding/ApplicationBellOnBoarding.hpp

M products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingFinalizeWindow.cpp => products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingFinalizeWindow.cpp +1 -1
@@ 38,7 38,7 @@ namespace gui
    {
        BellFinishedWindow::onBeforeShow(mode, data);

        icon->image->set("bell_big_logo", ImageTypeSpecifier::W_G);
        icon->image->set("bell_very_big_logo", ImageTypeSpecifier::W_G);
        icon->text->setFont(style::window::font::verybiglight);
        icon->text->setText(utils::translate("app_bell_onboarding_finalize"));
    }

M products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingInstructionPromptWindow.cpp => products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingInstructionPromptWindow.cpp +1 -4
@@ 27,10 27,7 @@ namespace gui

    bool OnBoardingInstructionPromptWindow::onInput(const InputEvent &inputEvent)
    {
        if (inputEvent.isShortRelease(KeyCode::KEY_ENTER)) {
            application->switchWindow(windowToReturn);
            return true;
        }
        // Inputs are handled on Application level
        return false;
    }
} // namespace gui

A products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingWelcomeWindow.cpp => products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingWelcomeWindow.cpp +59 -0
@@ 0,0 1,59 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "OnBoardingWelcomeWindow.hpp"
#include "ApplicationBellOnBoarding.hpp"

#include <InputEvent.hpp>
#include <Icon.hpp>
#include <Application.hpp>

namespace gui
{
    OnBoardingWelcomeWindow::OnBoardingWelcomeWindow(app::ApplicationCommon *app, const std::string &name)
        : WindowWithTimer(app, name, displayDuration)
    {
        buildInterface();
    }

    void OnBoardingWelcomeWindow::buildInterface()
    {
        AppWindow::buildInterface();
        buildLayout();
        registerCallbacks();
    }

    void OnBoardingWelcomeWindow::buildLayout()
    {
        statusBar->setVisible(false);
        header->setTitleVisibility(false);
        navBar->setVisible(false);
        icon = new Icon(this, 0, 0, style::window_width, style::window_height, {}, {});
    }

    void OnBoardingWelcomeWindow::registerCallbacks()
    {
        timerCallback = [this](Item &, sys::Timer &timer) {
            application->switchWindow(gui::window::name::onBoardingLanguageWindow);
            return true;
        };
    }

    bool OnBoardingWelcomeWindow::onInput(const InputEvent &inputEvent)
    {
        if (inputEvent.isShortRelease(KeyCode::KEY_ENTER)) {
            application->switchWindow(gui::window::name::onBoardingLanguageWindow);
            return true;
        }
        return false;
    }

    void OnBoardingWelcomeWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        WindowWithTimer::onBeforeShow(mode, data);

        icon->image->set("bell_very_big_logo", ImageTypeSpecifier::W_G);
        icon->text->setFont(style::window::font::verybiglight);
        icon->text->setText(utils::translate("app_bell_onboarding_welcome"));
    }
} // namespace gui

A products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingWelcomeWindow.hpp => products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingWelcomeWindow.hpp +27 -0
@@ 0,0 1,27 @@
// 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 <apps-common/popups/WindowWithTimer.hpp>

namespace gui
{
    class Icon;

    class OnBoardingWelcomeWindow : public WindowWithTimer
    {
      public:
        OnBoardingWelcomeWindow(app::ApplicationCommon *app, const std::string &name);

      private:
        constexpr static auto displayDuration = std::chrono::seconds{5};
        bool onInput(const InputEvent &inputEvent) override;
        void buildInterface() override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        void buildLayout();
        void registerCallbacks();
        Icon *icon{};
    };

} // namespace gui

M products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp => products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp +6 -4
@@ 18,8 18,11 @@ namespace app
                                                     StatusIndicators statusIndicators,
                                                     StartInBackground startInBackground,
                                                     uint32_t stackDepth)
        : Application(std::move(name), std::move(parent), statusIndicators, startInBackground, stackDepth)
    {}
        : Application(std::move(name), std::move(parent), statusIndicators, startInBackground, stackDepth),
          audioModel{std::make_unique<AudioModel>(this)}
    {
        bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
    }

    ApplicationBellPowerNap::~ApplicationBellPowerNap() = default;
    sys::ReturnCodes ApplicationBellPowerNap::InitHandler()


@@ 42,10 45,9 @@ namespace app
        windowsFactory.attach(
            gui::window::name::powernapProgress, [this](ApplicationCommon *app, const std::string &name) {
                auto timeModel        = std::make_unique<app::TimeModel>();
                auto audioModel       = std::make_unique<AudioModel>(app);
                auto soundsRepository = std::make_unique<SoundsRepository>(alarms::paths::getAlarmDir());
                auto presenter        = std::make_unique<powernap::PowerNapProgressPresenter>(
                    app, settings.get(), std::move(soundsRepository), std::move(audioModel), std::move(timeModel));
                    app, settings.get(), std::move(soundsRepository), *audioModel, std::move(timeModel));
                return std::make_unique<gui::PowerNapProgressWindow>(app, std::move(presenter));
            });
        windowsFactory.attach(gui::window::name::powernapSessionEnded,

M products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp => products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp +4 -0
@@ 4,6 4,7 @@
#pragma once

#include <Application.hpp>
#include <common/models/AbstractAudioModel.hpp>

namespace gui::window::name
{


@@ 21,6 22,9 @@ namespace app

    class ApplicationBellPowerNap : public Application
    {
      private:
        std::unique_ptr<AbstractAudioModel> audioModel;

      public:
        ApplicationBellPowerNap(std::string name                    = applicationBellPowerNapName,
                                std::string parent                  = "",

M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp +4 -5
@@ 25,10 25,10 @@ namespace app::powernap
    PowerNapProgressPresenter::PowerNapProgressPresenter(app::ApplicationCommon *app,
                                                         settings::Settings *settings,
                                                         std::unique_ptr<AbstractSoundsRepository> soundsRepository,
                                                         std::unique_ptr<AbstractAudioModel> audioModel,
                                                         AbstractAudioModel &audioModel,
                                                         std::unique_ptr<AbstractTimeModel> timeModel)
        : app{app}, settings{settings}, soundsRepository{std::move(soundsRepository)},
          audioModel{std::move(audioModel)}, timeModel{std::move(timeModel)},
          audioModel{audioModel}, timeModel{std::move(timeModel)},
          napAlarmTimer{sys::TimerFactory::createSingleShotTimer(
              app, powernapAlarmTimerName, powernapAlarmTimeout, [this](sys::Timer &) { onNapAlarmFinished(); })}



@@ 43,7 43,6 @@ namespace app::powernap
    void PowerNapProgressPresenter::activate()
    {
        Expects(timer != nullptr);
        getView()->setTimeFormat(timeModel->getTimeFormat());
        const auto value = settings->getValue(powernapDBRecordName);
        timer->reset(std::chrono::minutes{utils::getNumericValue<int>(value)});
        timer->start();


@@ 60,13 59,13 @@ 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, {});
        audioModel.play(filePath.value_or(""), AbstractAudioModel::PlaybackType::Alarm, {});
        napAlarmTimer.start();
        napFinished = true;
    }
    void PowerNapProgressPresenter::onNapAlarmFinished()
    {
        audioModel->stop({});
        audioModel.stop({});
        getView()->napEnded();
    }


M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp +2 -2
@@ 54,7 54,7 @@ namespace app::powernap
        app::ApplicationCommon *app{};
        settings::Settings *settings{};
        std::unique_ptr<AbstractSoundsRepository> soundsRepository;
        std::unique_ptr<AbstractAudioModel> audioModel;
        AbstractAudioModel &audioModel;
        std::unique_ptr<app::TimerWithCallbacks> timer;
        std::unique_ptr<AbstractTimeModel> timeModel;
        sys::TimerHandle napAlarmTimer;


@@ 73,7 73,7 @@ namespace app::powernap
        PowerNapProgressPresenter(app::ApplicationCommon *app,
                                  settings::Settings *settings,
                                  std::unique_ptr<AbstractSoundsRepository> soundsRepository,
                                  std::unique_ptr<AbstractAudioModel> audioModel,
                                  AbstractAudioModel &audioModel,
                                  std::unique_ptr<AbstractTimeModel> timeModel);
    };
} // namespace app::powernap

M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp => products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp +3 -5
@@ 62,16 62,13 @@ namespace gui
        buildInterface();
    }

    void PowerNapProgressWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        presenter->activate();
    }

    void PowerNapProgressWindow::buildInterface()
    {
        AppWindow::buildInterface();

        buildLayout();
        configureTimer();
        presenter->activate();
    }
    void PowerNapProgressWindow::buildLayout()
    {


@@ 87,6 84,7 @@ namespace gui
        time = new BellStatusClock(body->firstBox);
        time->setMaximumSize(body->firstBox->getWidth(), body->firstBox->getHeight());
        time->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        updateTime();
        body->firstBox->resizeItems();

        dimensionChangedCallback = [&](Item &, const BoundingBox &newDim) -> bool {

M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.hpp => products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.hpp +0 -1
@@ 19,7 19,6 @@ namespace gui
        gui::BellStatusClock *time  = nullptr;

        void buildInterface() override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        auto onInput(const InputEvent &inputEvent) -> bool override;

        void setTime(std::time_t newTime);

M products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp => products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp +10 -11
@@ 48,8 48,11 @@ namespace app
                                                     StatusIndicators statusIndicators,
                                                     StartInBackground startInBackground,
                                                     uint32_t stackDepth)
        : Application(std::move(name), std::move(parent), statusIndicators, startInBackground, stackDepth)
    {}
        : Application(std::move(name), std::move(parent), statusIndicators, startInBackground, stackDepth),
          audioModel{std::make_unique<AudioModel>(this)}
    {
        bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
    }

    sys::ReturnCodes ApplicationBellSettings::InitHandler()
    {


@@ 113,14 116,13 @@ namespace app

        windowsFactory.attach(
            gui::window::name::bellSettingsBedtimeTone, [this](ApplicationCommon *app, const std::string &name) {
                auto audioModel   = std::make_unique<AudioModel>(app);
                auto bedtimeModel = std::make_shared<bell_bedtime::BedtimeModel>(app, std::move(audioModel));
                auto bedtimeModel = std::make_shared<bell_bedtime::BedtimeModel>(app, *audioModel);
                auto soundsRepository =
                    std::make_unique<SoundsRepository>(alarms::paths::getBedtimeReminderChimesDir());
                auto provider = std::make_shared<bell_settings::BedtimeSettingsListItemProvider>(
                    bedtimeModel, soundsRepository->getSongTitles());
                auto presenter = std::make_unique<bell_settings::BedtimeSettingsPresenter>(
                    provider, bedtimeModel, std::move(audioModel), std::move(soundsRepository));
                    provider, bedtimeModel, *audioModel, std::move(soundsRepository));
                return std::make_unique<gui::BellSettingsBedtimeToneWindow>(app, std::move(presenter));
            });



@@ 144,7 146,6 @@ namespace app

        windowsFactory.attach(
            gui::BellSettingsPrewakeUpWindow::name, [this](ApplicationCommon *app, const std::string &name) {
                auto audioModel         = std::make_unique<AudioModel>(this);
                auto chimeDurationModel = std::make_unique<bell_settings::PrewakeUpChimeDurationModel>(this);
                auto chimeToneModel     = std::make_unique<bell_settings::PrewakeUpChimeToneModel>(this);
                auto chimeVolumeModel   = std::make_unique<bell_settings::PrewakeUpChimeVolumeModel>(*audioModel);


@@ 158,7 159,7 @@ namespace app
                auto provider         = std::make_shared<bell_settings::PrewakeUpListItemProvider>(
                    *prewakeUpSettingsModel, soundsRepository->getSongTitles());
                auto presenter = std::make_unique<bell_settings::PrewakeUpWindowPresenter>(
                    provider, std::move(prewakeUpSettingsModel), std::move(audioModel), std::move(soundsRepository));
                    provider, std::move(prewakeUpSettingsModel), *audioModel, std::move(soundsRepository));
                return std::make_unique<gui::BellSettingsPrewakeUpWindow>(app, std::move(presenter));
            });



@@ 169,7 170,6 @@ namespace app
                              });
        windowsFactory.attach(
            gui::BellSettingsAlarmSettingsSnoozeWindow::name, [this](ApplicationCommon *app, const std::string &) {
                auto audioModel               = std::make_unique<AudioModel>(this);
                auto snoozeOnOffModel         = std::make_unique<bell_settings::SnoozeOnOffModel>(this);
                auto snoozeLengthModel        = std::make_unique<bell_settings::SnoozeLengthModel>(this);
                auto snoozeChimeIntervalModel = std::make_unique<bell_settings::SnoozeChimeIntervalModel>(this);


@@ 185,12 185,11 @@ namespace app
                auto provider         = std::make_shared<bell_settings::SnoozeListItemProvider>(
                    *snoozeSettingsModel, soundsRepository->getSongTitles());
                auto presenter = std::make_unique<bell_settings::SnoozePresenter>(
                    provider, std::move(snoozeSettingsModel), std::move(audioModel), std::move(soundsRepository));
                    provider, std::move(snoozeSettingsModel), *audioModel, std::move(soundsRepository));
                return std::make_unique<gui::BellSettingsAlarmSettingsSnoozeWindow>(app, std::move(presenter));
            });
        windowsFactory.attach(
            gui::BellSettingsAlarmSettingsWindow::name, [this](ApplicationCommon *app, const std::string &) {
                auto audioModel           = std::make_unique<AudioModel>(this);
                auto alarmToneModel       = std::make_unique<bell_settings::AlarmToneModel>(this);
                auto alarmVolumeModel     = std::make_unique<bell_settings::AlarmVolumeModel>(*audioModel);
                auto alarmLightOnOffModel = std::make_unique<bell_settings::AlarmLightOnOffModel>(this);


@@ 200,7 199,7 @@ namespace app
                auto provider         = std::make_shared<bell_settings::AlarmSettingsListItemProvider>(
                    *alarmSettingsModel, soundsRepository->getSongTitles());
                auto presenter = std::make_unique<bell_settings::AlarmSettingsPresenter>(
                    provider, std::move(alarmSettingsModel), std::move(audioModel), std::move(soundsRepository));
                    provider, std::move(alarmSettingsModel), *audioModel, std::move(soundsRepository));
                return std::make_unique<gui::BellSettingsAlarmSettingsWindow>(app, std::move(presenter));
            });


M products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/ApplicationBellSettings.hpp => products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/ApplicationBellSettings.hpp +4 -0
@@ 4,6 4,7 @@
#pragma once

#include <Application.hpp>
#include <common/models/AbstractAudioModel.hpp>
#include <service-evtmgr/screen-light-control/ScreenLightControl.hpp>

namespace gui::window::name


@@ 26,6 27,9 @@ namespace app

    class ApplicationBellSettings : public Application
    {
      private:
        std::unique_ptr<AbstractAudioModel> audioModel;

      public:
        ApplicationBellSettings(std::string name                    = applicationBellSettingsName,
                                std::string parent                  = "",

M products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/models/TimeUnitsModel.hpp => products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/models/TimeUnitsModel.hpp +1 -1
@@ 63,7 63,7 @@ namespace app::bell_settings
        auto loadData() -> void override;

      private:
        static constexpr int factoryResetTime    = 60 * 60 * 12; // noon
        static constexpr int factoryResetTime    = 12; // noon
        static constexpr auto factoryRestTimeFmt = utils::time::Locale::TimeFormat::FormatTime12H;
    };
} // namespace app::bell_settings

M products/BellHybrid/apps/application-bell-settings/models/advanced/FrontlightListItemProvider.cpp => products/BellHybrid/apps/application-bell-settings/models/advanced/FrontlightListItemProvider.cpp +4 -4
@@ 34,10 34,10 @@ namespace app::bell_settings
        auto mode = new gui::UTF8ListItem(model.getModeModel(),
                                          gui::UTF8Spinner::Range{modeOnDemandsStr, modeAutoStr},
                                          utils::translate("app_bell_settings_frontlight_mode_top_message"));
        mode->setOnValueChanged([this, modeAutoStr](const auto &val) {
            model.setMode(val == modeAutoStr ? screen_light_control::ScreenLightMode::Automatic
                                             : screen_light_control::ScreenLightMode::Manual);
        });
        mode->onExit = [this, mode, modeAutoStr]() {
            model.setMode(mode->getCurrentValue() == modeAutoStr ? screen_light_control::ScreenLightMode::Automatic
                                                                 : screen_light_control::ScreenLightMode::Manual);
        };
        internalData.emplace_back(mode);
    }
    FrontlightListItemProvider::FrontlightListItemProvider(AbstractFrontlightModel &model) : model{model}

M products/BellHybrid/apps/application-bell-settings/models/advanced/FrontlightModel.cpp => products/BellHybrid/apps/application-bell-settings/models/advanced/FrontlightModel.cpp +2 -2
@@ 68,8 68,8 @@ namespace app::bell_settings
    }
    void FrontlightModel::setBrightness(Brightness value)
    {
        screen_light_control::ManualModeParameters parameters{fixedValToPercentage(value)};
        app->bus.sendUnicast(std::make_shared<sevm::ScreenLightSetManualModeParams>(parameters),
        screen_light_control::ConstLinearProgressModeParameters parameters{fixedValToPercentage(value)};
        app->bus.sendUnicast(std::make_shared<sevm::ScreenLightSetConstLinearModeParams>(parameters),
                             service::name::evt_manager);
    }
    gui::AbstractSettingsModel<std::uint8_t> &FrontlightModel::getBrightnessModel()

M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/SnoozeListItemProvider.cpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/SnoozeListItemProvider.cpp +34 -6
@@ 11,6 11,16 @@ namespace app::bell_settings
{
    using namespace gui;

    enum Intervals
    {
        Interval_1  = 1,
        Interval_2  = 2,
        Interval_5  = 5,
        Interval_10 = 10,
        Interval_15 = 15,
        Interval_30 = 30
    };

    SnoozeListItemProvider::SnoozeListItemProvider(AbstractSnoozeSettingsModel &model,
                                                   std::vector<UTF8> chimeTonesRange)
        : model{model}


@@ 47,6 57,7 @@ namespace app::bell_settings
                chimeLength->setBottomDescribtionText(utils::translate("common_minutes_lower"));
            }
        });

        chimeLength->onEnter = [onOff, this]() {
            if (not onOff->isActive()) {
                this->onExit();


@@ 56,19 67,36 @@ namespace app::bell_settings
        internalData.emplace_back(chimeLength);

        const UTF8 minStr = utils::translate("common_minute_short");
        const auto range  = NumWithStringListItem::NumWithStringSpinner::Range{
            NumWithStringListItem::Value{utils::translate("app_settings_toggle_off")},
            NumWithStringListItem::Value{1, minStr},
            NumWithStringListItem::Value{2, minStr},
            NumWithStringListItem::Value{3, minStr},
            NumWithStringListItem::Value{5, minStr}};
        const auto range  = NumWithStringListItem::NumWithStringSpinner::Range{NumWithStringListItem::Value{0, minStr}};

        auto chimeInterval = new NumWithStringListItem(
            model.getSnoozeChimeInterval(),
            range,
            utils::translate("app_bell_settings_alarm_settings_snooze_chime_interval"),
            utils::translate("app_bell_settings_alarm_settings_snooze_chime_interval_bot_desc"));

        internalData.emplace_back(chimeInterval);

        chimeLength->onProceed = [chimeInterval, chimeLength, this]() {
            if (chimeInterval != nullptr) {
                auto val = chimeLength->getCurrentValue();
                NumWithStringListItem::NumWithStringSpinner::Range chimeRange;
                const UTF8 minStr = utils::translate("common_minute_short");
                chimeRange.push_back(NumWithStringListItem::Value{utils::translate("app_alarm_clock_no_snooze")});
                for (unsigned int i = 1; i <= val; i++) {
                    if ((i != Intervals::Interval_1) && (i != Intervals::Interval_2) && (i != Intervals::Interval_5) &&
                        (i != Intervals::Interval_10) && (i != Intervals::Interval_15) &&
                        (i != Intervals::Interval_30)) {
                        continue;
                    }
                    chimeRange.push_back(NumWithStringListItem::Value{i, minStr});
                }
                chimeInterval->getSpinner()->setRange(chimeRange);
                chimeInterval->setArrowsVisibility(chimeRange);
            }
            return false;
        };

        auto snoozeChimeTone = new UTF8ListItem(model.getSnoozeChimeTone(),
                                                std::move(chimeTonesRange),
                                                utils::translate("app_bell_settings_alarm_settings_snooze_chime_tone"));

M products/BellHybrid/apps/application-bell-settings/presenter/BedtimeSettingsPresenter.cpp => products/BellHybrid/apps/application-bell-settings/presenter/BedtimeSettingsPresenter.cpp +10 -8
@@ 7,16 7,16 @@ namespace app::bell_settings
{
    BedtimeSettingsPresenter::BedtimeSettingsPresenter(std::shared_ptr<BedtimeSettingsListItemProvider> provider,
                                                       std::shared_ptr<AbstractBedtimeModel> model,
                                                       std::unique_ptr<AbstractAudioModel> audioModel,
                                                       AbstractAudioModel &audioModel,
                                                       std::unique_ptr<AbstractSoundsRepository> soundsRepository)
        : provider(std::move(provider)),
          model(std::move(model)), audioModel{std::move(audioModel)}, soundsRepository{std::move(soundsRepository)}
          model(std::move(model)), audioModel{audioModel}, soundsRepository{std::move(soundsRepository)}
    {
        auto playSound = [this](const UTF8 &val) {
            currentSoundPath = val;
            this->audioModel->play(this->soundsRepository->titleToPath(currentSoundPath).value_or(""),
                                   AbstractAudioModel::PlaybackType::Bedtime,
                                   {});
            this->audioModel.play(this->soundsRepository->titleToPath(currentSoundPath).value_or(""),
                                  AbstractAudioModel::PlaybackType::Bedtime,
                                  {});
        };

        this->provider->onExit = [this]() { getView()->exit(); };


@@ 28,8 28,10 @@ namespace app::bell_settings
        this->provider->onVolumeEnter  = playSound;
        this->provider->onVolumeExit   = [this](const auto &) { this->stopSound(); };
        this->provider->onVolumeChange = [this, playSound](const auto &val) {
            this->audioModel->setVolume(val, AbstractAudioModel::PlaybackType::Bedtime, {});
            playSound(currentSoundPath);
            this->audioModel.setVolume(val, AbstractAudioModel::PlaybackType::Bedtime, {});
            if (this->audioModel.hasPlaybackFinished()) {
                playSound(currentSoundPath);
            }
        };
    }



@@ 59,7 61,7 @@ namespace app::bell_settings

    void BedtimeSettingsPresenter::stopSound()
    {
        this->audioModel->stop({});
        this->audioModel.stop({});
    }
    void BedtimeSettingsPresenter::exitWithoutSave()
    {

M products/BellHybrid/apps/application-bell-settings/presenter/BedtimeSettingsPresenter.hpp => products/BellHybrid/apps/application-bell-settings/presenter/BedtimeSettingsPresenter.hpp +2 -2
@@ 44,7 44,7 @@ namespace app::bell_settings
      public:
        BedtimeSettingsPresenter(std::shared_ptr<BedtimeSettingsListItemProvider> provider,
                                 std::shared_ptr<AbstractBedtimeModel> model,
                                 std::unique_ptr<AbstractAudioModel> audioModel,
                                 AbstractAudioModel &audioModel,
                                 std::unique_ptr<AbstractSoundsRepository> soundsRepository);

        auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> override;


@@ 58,7 58,7 @@ namespace app::bell_settings

        std::shared_ptr<BedtimeSettingsListItemProvider> provider;
        std::shared_ptr<AbstractBedtimeModel> model;
        std::unique_ptr<AbstractAudioModel> audioModel;
        AbstractAudioModel &audioModel;
        std::unique_ptr<AbstractSoundsRepository> soundsRepository;
        UTF8 currentSoundPath;
    };

M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/AlarmSettingsPresenter.cpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/AlarmSettingsPresenter.cpp +5 -5
@@ 8,14 8,14 @@ namespace app::bell_settings
{
    AlarmSettingsPresenter::AlarmSettingsPresenter(std::shared_ptr<AlarmSettingsListItemProvider> provider,
                                                   std::unique_ptr<AbstractAlarmSettingsModel> model,
                                                   std::unique_ptr<AbstractAudioModel> audioModel,
                                                   AbstractAudioModel &audioModel,
                                                   std::unique_ptr<AbstractSoundsRepository> soundsRepository)
        : provider(provider),
          model(std::move(model)), audioModel{std::move(audioModel)}, soundsRepository{std::move(soundsRepository)}
          model(std::move(model)), audioModel{audioModel}, soundsRepository{std::move(soundsRepository)}
    {

        auto playSound = [this](const UTF8 &val) {
            this->audioModel->play(
            this->audioModel.play(
                this->soundsRepository->titleToPath(val).value_or(""), AbstractAudioModel::PlaybackType::Alarm, {});
        };



@@ 28,7 28,7 @@ namespace app::bell_settings
        this->provider->onVolumeEnter  = playSound;
        this->provider->onVolumeExit   = [this](const auto &) { stopSound(); };
        this->provider->onVolumeChange = [this](const auto &val) {
            this->audioModel->setVolume(val, AbstractAudioModel::PlaybackType::Alarm, {});
            this->audioModel.setVolume(val, AbstractAudioModel::PlaybackType::Alarm, {});
        };
    }



@@ 57,7 57,7 @@ namespace app::bell_settings
    }
    void AlarmSettingsPresenter::stopSound()
    {
        this->audioModel->stop({});
        this->audioModel.stop({});
    }
    void AlarmSettingsPresenter::exitWithoutSave()
    {

M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/AlarmSettingsPresenter.hpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/AlarmSettingsPresenter.hpp +2 -2
@@ 46,7 46,7 @@ namespace app::bell_settings
      public:
        AlarmSettingsPresenter(std::shared_ptr<AlarmSettingsListItemProvider> provider,
                               std::unique_ptr<AbstractAlarmSettingsModel> model,
                               std::unique_ptr<AbstractAudioModel> audioModel,
                               AbstractAudioModel &audioModel,
                               std::unique_ptr<AbstractSoundsRepository> soundsRepository);

        auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> override;


@@ 60,7 60,7 @@ namespace app::bell_settings

        std::shared_ptr<AlarmSettingsListItemProvider> provider;
        std::unique_ptr<AbstractAlarmSettingsModel> model;
        std::unique_ptr<AbstractAudioModel> audioModel;
        AbstractAudioModel &audioModel;
        std::unique_ptr<AbstractSoundsRepository> soundsRepository;
    };
} // namespace app::bell_settings

M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.cpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.cpp +10 -8
@@ 8,16 8,16 @@ namespace app::bell_settings
{
    PrewakeUpWindowPresenter::PrewakeUpWindowPresenter(std::shared_ptr<PrewakeUpListItemProvider> provider,
                                                       std::unique_ptr<AbstractPrewakeUpSettingsModel> model,
                                                       std::unique_ptr<AbstractAudioModel> audioModel,
                                                       AbstractAudioModel &audioModel,
                                                       std::unique_ptr<AbstractSoundsRepository> soundsRepository)
        : provider(std::move(provider)),
          model(std::move(model)), audioModel{std::move(audioModel)}, soundsRepository{std::move(soundsRepository)}
          model(std::move(model)), audioModel{audioModel}, soundsRepository{std::move(soundsRepository)}
    {
        auto playSound = [this](const UTF8 &val) {
            currentSoundPath = val;
            this->audioModel->play(this->soundsRepository->titleToPath(currentSoundPath).value_or(""),
                                   AbstractAudioModel::PlaybackType::PreWakeup,
                                   {});
            this->audioModel.play(this->soundsRepository->titleToPath(currentSoundPath).value_or(""),
                                  AbstractAudioModel::PlaybackType::PreWakeup,
                                  {});
        };

        this->provider->onExit = [this]() { getView()->exit(); };


@@ 29,8 29,10 @@ namespace app::bell_settings
        this->provider->onVolumeEnter  = playSound;
        this->provider->onVolumeExit   = [this](const auto &) { this->stopSound(); };
        this->provider->onVolumeChange = [this, playSound](const auto &val) {
            this->audioModel->setVolume(val, AbstractAudioModel::PlaybackType::PreWakeup, {});
            playSound(currentSoundPath);
            this->audioModel.setVolume(val, AbstractAudioModel::PlaybackType::PreWakeup, {});
            if (this->audioModel.hasPlaybackFinished()) {
                playSound(currentSoundPath);
            }
        };
    }



@@ 59,7 61,7 @@ namespace app::bell_settings
    }
    void PrewakeUpWindowPresenter::stopSound()
    {
        this->audioModel->stop({});
        this->audioModel.stop({});
    }
    void PrewakeUpWindowPresenter::exitWithoutSave()
    {

M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.hpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.hpp +2 -2
@@ 46,7 46,7 @@ namespace app::bell_settings
      public:
        PrewakeUpWindowPresenter(std::shared_ptr<PrewakeUpListItemProvider> provider,
                                 std::unique_ptr<AbstractPrewakeUpSettingsModel> model,
                                 std::unique_ptr<AbstractAudioModel> audioModel,
                                 AbstractAudioModel &audioModel,
                                 std::unique_ptr<AbstractSoundsRepository> soundsRepository);

        auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> override;


@@ 60,7 60,7 @@ namespace app::bell_settings

        std::shared_ptr<PrewakeUpListItemProvider> provider;
        std::unique_ptr<AbstractPrewakeUpSettingsModel> model;
        std::unique_ptr<AbstractAudioModel> audioModel;
        AbstractAudioModel &audioModel;
        std::unique_ptr<AbstractSoundsRepository> soundsRepository;
        UTF8 currentSoundPath;
    };

M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/SnoozePresenter.cpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/SnoozePresenter.cpp +10 -8
@@ 9,16 9,16 @@ namespace app::bell_settings

    SnoozePresenter::SnoozePresenter(std::shared_ptr<SnoozeListItemProvider> provider,
                                     std::unique_ptr<AbstractSnoozeSettingsModel> snoozeSettingsModel,
                                     std::unique_ptr<AbstractAudioModel> audioModel,
                                     AbstractAudioModel &audioModel,
                                     std::unique_ptr<AbstractSoundsRepository> soundsRepository)
        : provider{provider}, snoozeSettingsModel{std::move(snoozeSettingsModel)}, audioModel{std::move(audioModel)},
        : provider{provider}, snoozeSettingsModel{std::move(snoozeSettingsModel)}, audioModel{audioModel},
          soundsRepository{std::move(soundsRepository)}
    {
        auto playSound = [this](const UTF8 &val) {
            currentSoundPath = val;
            this->audioModel->play(this->soundsRepository->titleToPath(currentSoundPath).value_or(""),
                                   AbstractAudioModel::PlaybackType::Snooze,
                                   {});
            this->audioModel.play(this->soundsRepository->titleToPath(currentSoundPath).value_or(""),
                                  AbstractAudioModel::PlaybackType::Snooze,
                                  {});
        };

        this->provider->onExit = [this]() { getView()->exit(); };


@@ 30,8 30,10 @@ namespace app::bell_settings
        this->provider->onVolumeEnter  = playSound;
        this->provider->onVolumeExit   = [this](const auto &) { stopSound(); };
        this->provider->onVolumeChange = [this, playSound](const auto &val) {
            this->audioModel->setVolume(val, AbstractAudioModel::PlaybackType::Snooze, {});
            playSound(currentSoundPath);
            this->audioModel.setVolume(val, AbstractAudioModel::PlaybackType::Snooze, {});
            if (this->audioModel.hasPlaybackFinished()) {
                playSound(currentSoundPath);
            }
        };
    }



@@ 56,7 58,7 @@ namespace app::bell_settings
    }
    void SnoozePresenter::stopSound()
    {
        audioModel->stop({});
        audioModel.stop({});
    }
    void SnoozePresenter::eraseProviderData()
    {

M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/SnoozePresenter.hpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/SnoozePresenter.hpp +2 -2
@@ 41,7 41,7 @@ namespace app::bell_settings
      public:
        SnoozePresenter(std::shared_ptr<SnoozeListItemProvider> provider,
                        std::unique_ptr<AbstractSnoozeSettingsModel> snoozeSettingsModel,
                        std::unique_ptr<AbstractAudioModel> audioModel,
                        AbstractAudioModel &audioModel,
                        std::unique_ptr<AbstractSoundsRepository> soundsRepository);
        auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> override;
        void saveData() override;


@@ 54,7 54,7 @@ namespace app::bell_settings

        std::shared_ptr<SnoozeListItemProvider> provider;
        std::unique_ptr<AbstractSnoozeSettingsModel> snoozeSettingsModel;
        std::unique_ptr<AbstractAudioModel> audioModel;
        AbstractAudioModel &audioModel;
        std::unique_ptr<AbstractSoundsRepository> soundsRepository;
        UTF8 currentSoundPath;
    };

M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsBedtimeToneWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/BellSettingsBedtimeToneWindow.cpp +3 -1
@@ 68,6 68,8 @@ namespace gui

    void BellSettingsBedtimeToneWindow::onClose(CloseReason reason)
    {
        presenter->eraseProviderData();
        if (reason != CloseReason::Popup) {
            presenter->eraseProviderData();
        }
    }
} /* namespace gui */

M products/BellHybrid/apps/application-bell-settings/windows/advanced/BellSettingsFrontlightWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/advanced/BellSettingsFrontlightWindow.cpp +4 -2
@@ 64,8 64,10 @@ namespace gui
            window::bell_finished::defaultName,
            BellFinishedWindowData::Factory::create("circle_success_big", window::name::bellSettingsAdvanced));
    }
    void BellSettingsFrontlightWindow::onClose(Window::CloseReason)
    void BellSettingsFrontlightWindow::onClose(Window::CloseReason reason)
    {
        presenter->eraseProviderData();
        if (reason != CloseReason::Popup) {
            presenter->eraseProviderData();
        }
    }
} /* namespace gui */

M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsSnoozeWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsSnoozeWindow.cpp +4 -2
@@ 71,8 71,10 @@ namespace gui
            window::bell_finished::defaultName,
            BellFinishedWindowData::Factory::create("circle_success_big", BellSettingsAlarmSettingsMenuWindow::name));
    }
    void BellSettingsAlarmSettingsSnoozeWindow::onClose(Window::CloseReason)
    void BellSettingsAlarmSettingsSnoozeWindow::onClose(Window::CloseReason reason)
    {
        presenter->eraseProviderData();
        if (reason != CloseReason::Popup) {
            presenter->eraseProviderData();
        }
    }
} // namespace gui

M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsWindow.cpp +3 -1
@@ 72,6 72,8 @@ namespace gui

    void BellSettingsAlarmSettingsWindow::onClose(CloseReason reason)
    {
        presenter->eraseProviderData();
        if (reason != CloseReason::Popup) {
            presenter->eraseProviderData();
        }
    }
} /* namespace gui */

M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsPrewakeUpWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsPrewakeUpWindow.cpp +3 -1
@@ 71,6 71,8 @@ namespace gui

    void BellSettingsPrewakeUpWindow::onClose(CloseReason reason)
    {
        presenter->eraseProviderData();
        if (reason != CloseReason::Popup) {
            presenter->eraseProviderData();
        }
    }
} /* namespace gui */

M products/BellHybrid/apps/common/include/common/data/BellFinishedWindowSwitchData.hpp => products/BellHybrid/apps/common/include/common/data/BellFinishedWindowSwitchData.hpp +15 -8
@@ 6,6 6,8 @@
#include <SwitchData.hpp>
#include <utf8/UTF8.hpp>

#include <chrono>

namespace gui
{
    struct BellFinishedWindowData : public gui::SwitchData


@@ 13,13 15,15 @@ namespace gui
      public:
        struct Factory
        {
            static std::unique_ptr<BellFinishedWindowData> create(const UTF8 &icon,
                                                                  const std::string &windowToReturn,
                                                                  const UTF8 &text      = "",
                                                                  bool closeApplication = false)
            static std::unique_ptr<BellFinishedWindowData> create(
                const UTF8 &icon,
                const std::string &windowToReturn,
                const UTF8 &text                   = "",
                bool closeApplication              = false,
                const std::chrono::seconds timeout = std::chrono::seconds::zero())
            {
                return std::unique_ptr<BellFinishedWindowData>(
                    new BellFinishedWindowData(icon, windowToReturn, text, closeApplication));
                    new BellFinishedWindowData(icon, windowToReturn, text, closeApplication, timeout));
            }
        };



@@ 27,15 31,18 @@ namespace gui
        std::string windowToReturn;
        UTF8 text{};
        bool closeApplication;
        std::chrono::seconds timeout;

      private:
        BellFinishedWindowData() = default;

        BellFinishedWindowData(const UTF8 &icon,
                               const std::string &windowToReturn,
                               const UTF8 &text      = "",
                               bool closeApplication = false)
            : icon{icon}, windowToReturn{windowToReturn}, text{text}, closeApplication{closeApplication}
                               const UTF8 &text                   = "",
                               bool closeApplication              = false,
                               const std::chrono::seconds timeout = std::chrono::seconds::zero())
            : icon{icon}, windowToReturn{windowToReturn}, text{text}, closeApplication{closeApplication}, timeout{
                                                                                                              timeout}
        {}
    };
} // namespace gui

M products/BellHybrid/apps/common/include/common/models/AbstractAlarmModel.hpp => products/BellHybrid/apps/common/include/common/models/AbstractAlarmModel.hpp +11 -10
@@ 19,17 19,18 @@ namespace app
      public:
        virtual ~AbstractAlarmModel() noexcept = default;

        virtual bool isActive() const             = 0;
        virtual void setDefaultAlarmTime()        = 0;
        virtual void setAlarmTime(time_t time)    = 0;
        virtual time_t getAlarmTime() const       = 0;
        virtual void activate(bool value)         = 0;
        virtual std::uint32_t getSnoozeDuration() = 0;
        virtual bool isSnoozeAllowed()            = 0;
        virtual bool isSnoozeActive()             = 0;
        virtual void turnOff()                    = 0;
        virtual void snooze()                     = 0;
        virtual bool isActive() const                      = 0;
        virtual void setDefaultAlarmTime()                 = 0;
        virtual void setAlarmTime(time_t time)             = 0;
        virtual time_t getAlarmTime() const                = 0;
        virtual void activate(bool value)                  = 0;
        virtual std::uint32_t getSnoozeDuration()          = 0;
        virtual bool isSnoozeAllowed()                     = 0;
        virtual bool isSnoozeActive()                      = 0;
        virtual void turnOff()                             = 0;
        virtual void snooze()                              = 0;
        virtual std::chrono::seconds getTimeToNextSnooze() = 0;
        virtual std::time_t getTimeOfNextSnooze()          = 0;
        virtual alarms::AlarmStatus getAlarmStatus()       = 0;
        /// Command model to update its internal data
        virtual void update(AlarmModelReadyHandler callback = AlarmModelReadyHandler()) = 0;

M products/BellHybrid/apps/common/include/common/models/AbstractAudioModel.hpp => products/BellHybrid/apps/common/include/common/models/AbstractAudioModel.hpp +8 -5
@@ 15,11 15,12 @@ namespace app
    {
      public:
        /// 0-10 range
        static constexpr auto minVolume = 1;
        static constexpr auto maxVolume = 10;
        using Volume                    = std::uint32_t;
        using OnStateChangeCallback     = std::function<void(const audio::RetCode code)>;
        using OnGetValueCallback        = std::function<void(const audio::RetCode, Volume)>;
        static constexpr auto minVolume  = 1;
        static constexpr auto maxVolume  = 10;
        using Volume                     = std::uint32_t;
        using OnStateChangeCallback      = std::function<void(const audio::RetCode code)>;
        using OnGetValueCallback         = std::function<void(const audio::RetCode, Volume)>;
        using OnPlaybackFinishedCallback = std::function<void()>;

        enum class PlaybackType
        {


@@ 38,6 39,8 @@ namespace app
        virtual void stop(OnStateChangeCallback &&callback)                                                 = 0;
        virtual void pause(OnStateChangeCallback &&callback)                                                = 0;
        virtual void resume(OnStateChangeCallback &&callback)                                               = 0;
        virtual void setPlaybackFinishedCb(OnPlaybackFinishedCallback &&callback)                           = 0;
        virtual bool hasPlaybackFinished()                                                                  = 0;
    };

} // namespace app

M products/BellHybrid/apps/common/include/common/models/AlarmModel.hpp => products/BellHybrid/apps/common/include/common/models/AlarmModel.hpp +1 -0
@@ 38,6 38,7 @@ namespace app
        void turnOff() override;
        void snooze() override;
        std::chrono::seconds getTimeToNextSnooze() override;
        std::time_t getTimeOfNextSnooze() override;
        alarms::AlarmStatus getAlarmStatus() override;

      private:

M products/BellHybrid/apps/common/include/common/models/AudioModel.hpp => products/BellHybrid/apps/common/include/common/models/AudioModel.hpp +5 -0
@@ 12,6 12,7 @@ namespace app
    {
      public:
        explicit AudioModel(ApplicationCommon *app);
        virtual ~AudioModel();

        void setVolume(Volume volume, PlaybackType playbackType, OnStateChangeCallback &&callback) override;
        std::optional<Volume> getVolume(PlaybackType playbackType) override;


@@ 20,8 21,12 @@ namespace app
        void stop(OnStateChangeCallback &&callback) override;
        void pause(OnStateChangeCallback &&callback) override;
        void resume(OnStateChangeCallback &&callback) override;
        void setPlaybackFinishedCb(OnPlaybackFinishedCallback &&callback) override;
        bool hasPlaybackFinished() override;

      private:
        std::function<void()> playbackFinishedCallback{nullptr};
        bool playbackFinishedFlag{false};
        ApplicationCommon *app{};
    };
} // namespace app

M products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp => products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp +2 -3
@@ 65,12 65,12 @@ namespace app::bell_bedtime
      public:
        BedtimeModel() = delete;

        explicit BedtimeModel(ApplicationCommon *app, std::unique_ptr<AudioModel> &&audioModel)
        explicit BedtimeModel(ApplicationCommon *app, AbstractAudioModel &audioModel)
        {
            bedtimeOnOff  = std::make_unique<bell_bedtime::BedtimeOnOffModel>(app);
            bedtimeTime   = std::make_unique<bell_bedtime::BedtimeTimeModel>(app);
            bedtimeTone   = std::make_unique<bell_bedtime::AlarmToneModel>(app);
            bedtimeVolume = std::make_unique<bell_bedtime::BedtimeVolumeModel>(*audioModel);
            bedtimeVolume = std::make_unique<bell_bedtime::BedtimeVolumeModel>(audioModel);
        }
        gui::AbstractSettingsModel<bool> &getBedtimeOnOff() override
        {


@@ 92,7 92,6 @@ namespace app::bell_bedtime
        }

      private:
        std::unique_ptr<AudioModel> audioModel;
        std::unique_ptr<gui::AbstractSettingsModel<bool>> bedtimeOnOff;
        std::unique_ptr<gui::AbstractSettingsModel<time_t>> bedtimeTime;
        std::unique_ptr<gui::AbstractSettingsModel<UTF8>> bedtimeTone;

M products/BellHybrid/apps/common/include/common/widgets/ListItems.hpp => products/BellHybrid/apps/common/include/common/widgets/ListItems.hpp +5 -2
@@ 59,13 59,16 @@ namespace gui
                                       const std::string &bottomDescription = "");

        bool isOff() const;
        NumWithStringSpinner *getSpinner()
        {
            return spinner;
        }
        void setArrowsVisibility(const NumWithStringSpinner::Range &range);

      private:
        NumWithStringSpinner *spinner{};
        const UTF8 offStr;
        const UTF8 minStr;

        void setArrowsVisibility(const NumWithStringSpinner::Range &range);
    };

    class UTF8ListItem : public BellSideListItemWithCallbacks

M products/BellHybrid/apps/common/include/common/windows/BellWelcomeWindow.hpp => products/BellHybrid/apps/common/include/common/windows/BellWelcomeWindow.hpp +3 -5
@@ 13,11 13,9 @@ namespace gui

    class BellWelcomeWindow : public AppWindow
    {
        static constexpr auto midline_correction    = 40U;
        static constexpr auto midline_w             = 480U;
        static constexpr auto midline_h             = 1U;
        static constexpr auto sun_logo_margin_top   = 10U;
        static constexpr auto sun_logo_margin_right = 25U;
        static constexpr auto midline_correction = 40U;
        static constexpr auto midline_w          = 480U;
        static constexpr auto midline_h          = 1U;

      public:
        using Callback                    = std::function<void()>;

M products/BellHybrid/apps/common/src/AlarmModel.cpp => products/BellHybrid/apps/common/src/AlarmModel.cpp +9 -2
@@ 138,8 138,7 @@ namespace app
        const auto snoozeDuration = utils::getNumericValue<std::uint32_t>(snoozeDurationStr);

        snoozeCount++;
        nextSnoozeTime =
            std::chrono::floor<std::chrono::seconds>(TimePointNow()) + std::chrono::minutes(snoozeDuration);
        nextSnoozeTime = std::chrono::ceil<std::chrono::minutes>(TimePointNow()) + std::chrono::minutes(snoozeDuration);
        alarms::AlarmServiceAPI::requestSnoozeRingingAlarm(app, cachedRecord.parent->ID, nextSnoozeTime);
        alarmStatus = alarms::AlarmStatus::Snoozed;
    }


@@ 199,4 198,12 @@ namespace app
    {
        return alarmStatus;
    }
    std::time_t AlarmModel::getTimeOfNextSnooze()
    {
        const auto snoozeDurationStr =
            settings.getValue(bell::settings::Snooze::length, settings::SettingsScope::Global);
        const auto snoozeDuration = utils::getNumericValue<std::uint32_t>(snoozeDurationStr);
        return Clock::to_time_t(std::chrono::floor<std::chrono::minutes>(TimePointNow()) +
                                std::chrono::minutes(snoozeDuration));
    }
} // namespace app

M products/BellHybrid/apps/common/src/AudioModel.cpp => products/BellHybrid/apps/common/src/AudioModel.cpp +28 -1
@@ 55,9 55,25 @@ namespace app
{

    AudioModel::AudioModel(ApplicationCommon *app) : app::AsyncCallbackReceiver{app}, app{app}
    {}
    {
        app->connect(typeid(service::AudioEOFNotification), [&](sys::Message *msg) -> sys::MessagePointer {
            playbackFinishedFlag = true;
            if (playbackFinishedCallback) {
                playbackFinishedCallback();
            }

            return sys::msgHandled();
        });
    }

    AudioModel::~AudioModel()
    {
        app->disconnect(typeid(service::AudioEOFNotification));
    }

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


@@ 176,4 192,15 @@ namespace app

        return {};
    }

    void AudioModel::setPlaybackFinishedCb(OnPlaybackFinishedCallback &&callback)
    {
        playbackFinishedCallback = callback;
    }

    bool AudioModel::hasPlaybackFinished()
    {
        return playbackFinishedFlag;
    }

} // namespace app

M products/BellHybrid/apps/common/src/popups/BellRebootWindow.cpp => products/BellHybrid/apps/common/src/popups/BellRebootWindow.cpp +1 -1
@@ 35,7 35,7 @@ namespace gui
                        0,
                        style::window_width,
                        style::window_height,
                        "bell_mudita_logo_W_G",
                        "bell_very_big_logo_W_G",
                        utils::translate("app_bell_reset_message"));
        icon->text->setFont(style::window::font::verybiglight);
    }

M products/BellHybrid/apps/common/src/windows/BellFinishedWindow.cpp => products/BellHybrid/apps/common/src/windows/BellFinishedWindow.cpp +3 -0
@@ 63,6 63,9 @@ namespace gui
            icon->resizeItems();
            windowToReturn   = metadata->windowToReturn;
            closeApplication = metadata->closeApplication;
            if (metadata->timeout != std::chrono::seconds::zero()) {
                resetTimer(metadata->timeout);
            }
        }
    }


M products/BellHybrid/apps/common/src/windows/BellTurnOffWindow.cpp => products/BellHybrid/apps/common/src/windows/BellTurnOffWindow.cpp +8 -3
@@ 31,9 31,14 @@ namespace gui
        header->setTitleVisibility(false);
        navBar->setVisible(false);

        icon =
            new Icon(this, 0, 0, style::window_width, style::window_height, {}, utils::translate("app_bell_goodbye"));
        icon->image->setVisible(false);
        icon = new Icon(this,
                        0,
                        0,
                        style::window_width,
                        style::window_height,
                        "bell_very_big_logo_W_G",
                        utils::translate("app_bell_goodbye"));
        icon->image->setVisible(true);
        icon->text->setFont(style::window::font::verybiglight);
    }
    bool BellTurnOffWindow::onInput(const InputEvent &)

M products/BellHybrid/apps/common/src/windows/BellWelcomeWindow.cpp => products/BellHybrid/apps/common/src/windows/BellWelcomeWindow.cpp +4 -13
@@ 47,19 47,10 @@ namespace gui
        informationBody->setEdges(RectangleEdge::None);
        informationBody->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));

        auto sunLogo = new ImageBox(informationBody, new Image("button_icon_sun", ImageTypeSpecifier::W_G));
        sunLogo->setMinimumSizeToFitImage();
        sunLogo->setMargins(Margins(0, sun_logo_margin_top, sun_logo_margin_right, 0));

        auto instructionText = new TextFixedSize(informationBody);
        instructionText->setMargins(Margins(0, sun_logo_margin_top, 0, 0));
        instructionText->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
        instructionText->drawUnderline(false);
        instructionText->setFont(style::window::font::verybiglight);
        // non localized string by purpose
        instructionText->setText(": ON");
        instructionText->setMinimumWidthToFitText(instructionText->getText());
        instructionText->setMinimumHeight(sunLogo->widgetMinimumArea.h);
        auto bottomLogo = new ImageBox(informationBody, new Image("bell_off_bottom", ImageTypeSpecifier::W_G));
        bottomLogo->setMinimumSizeToFitImage();
        bottomLogo->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        bottomLogo->setMargins(Margins(0, 0, 0, 0));

        body->resize();
    }

M products/BellHybrid/services/evtmgr/CMakeLists.txt => products/BellHybrid/services/evtmgr/CMakeLists.txt +1 -0
@@ 42,6 42,7 @@ target_link_libraries(evtmgr
        keymap
        module-bsp
        module-utils
        module-sys
        service-evtmgr
        bell::appmgr
        sys

M products/BellHybrid/services/evtmgr/EventManager.cpp => products/BellHybrid/services/evtmgr/EventManager.cpp +6 -0
@@ 98,6 98,12 @@ void EventManager::initProductEvents()
        return sys::msgHandled();
    });

    connect(typeid(sevm::ScreenLightSetConstLinearModeParams), [&](sys::Message *msgl) {
        auto *m = static_cast<sevm::ScreenLightSetConstLinearModeParams *>(msgl);
        backlightHandler.processScreenRequest(m->getAction(), screen_light_control::Parameters(m->getParams()));
        return sys::msgHandled();
    });

    connect(sevm::ScreenLightControlRequestParameters(), [&](sys::Message *msgl) {
        screen_light_control::ManualModeParameters params = {backlightHandler.getScreenBrightnessValue()};
        auto msg = std::make_shared<sevm::ScreenLightControlParametersResponse>(

M products/BellHybrid/services/evtmgr/backlight-handler/BacklightHandler.cpp => products/BellHybrid/services/evtmgr/backlight-handler/BacklightHandler.cpp +89 -10
@@ 4,11 4,12 @@
#include <evtmgr/backlight-handler/BacklightHandler.hpp>

#include <screen-light-control/ScreenLightControl.hpp>

#include <service-db/agents/settings/SystemSettings.hpp>
#include <service-db/Settings.hpp>

#include <Timers/TimerFactory.hpp>
#include <keymap/KeyMap.hpp>
#include <Utils.hpp>

namespace backlight
{


@@ 19,10 20,29 @@ namespace backlight
    } // namespace timers

    Handler::Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent)
        : HandlerCommon(
              std::move(settings), std::make_shared<bell::screen_light_control::ScreenLightController>(parent), parent)
        : HandlerCommon(std::move(settings),
                        std::make_shared<bell::screen_light_control::ScreenLightController>(parent),
                        parent,
                        [this](sys::Timer &t) {
                            if (this->screenLightController->isLightOn()) {
                                this->screenLightController->processRequest(screen_light_control::Action::turnOff);
                            }
                        })
    {}

    void Handler::init()
    {
        using namespace screen_light_control;
        settings->registerValueChange(settings::Brightness::brightnessLevel, [&](const std::string &value) {
            ConstLinearProgressModeParameters params{utils::getNumericValue<float>(value)};
            screenLightController->processRequest(Action::setAutomaticModeParameters, Parameters(params));
        });

        settings->registerValueChange(settings::Brightness::autoMode, [&](const std::string &value) {
            onDemandModeOn = utils::getNumericValue<bool>(value);
        });
    }

    void Handler::handleKeyPressed([[maybe_unused]] int key)
    {
        handleScreenLightRefresh(key);


@@ 32,16 52,26 @@ namespace backlight
    {
        auto controller = getScreenLightControl();
        auto timer      = getScreenLightTimer();
        if (!controller->isLightOn() && (key == static_cast<int>(KeyMap::Frontlight))) {
            controller->processRequest(screen_light_control::Action::turnOn);
            timer->restart(timers::screenLightTimerTimeout);
        }
        else if (controller->isLightOn()) {
            if (controller->isAutoModeOn() || key == static_cast<int>(KeyMap::Frontlight)) {

        if (key == static_cast<int>(KeyMap::Frontlight)) {
            if (controller->isLightOn()) {
                setKeyPressedModeFrontlightOff();
                controller->processRequest(screen_light_control::Action::turnOff);
                timer->stop();
            }
            else {
                setKeyPressedModeFrontlightOn();
                controller->processRequest(screen_light_control::Action::turnOn);
                timer->restart(onDemandModeOn ? timers::screenLightTimerTimeout : timers::screenLightTimerHoldTimeout);
            }
        }
        else {
            if (controller->isLightOn()) {
                timer->restart(timers::screenLightTimerHoldTimeout);
            }
            else if (!onDemandModeOn) {
                setKeyPressedModeFrontlightOn();
                controller->processRequest(screen_light_control::Action::turnOn);
                timer->restart(timers::screenLightTimerHoldTimeout);
            }
        }


@@ 54,10 84,59 @@ namespace backlight
        getScreenLightControl()->processRequest(action, params);
    }

    void Handler::handleScreenLightSettings(screen_light_control::Action action,
                                            const screen_light_control::Parameters &params)
    {
        switch (action) {
        case screen_light_control::Action::turnOn:
            if (params.hasManualModeParams()) {
                auto timer = getScreenLightTimer();
                timer->stop();
                backlightMode = BacklightMode::WithoutTimer;
            }
            break;
        case screen_light_control::Action::setAutomaticModeParameters:
            if (params.hasConstLinearProgressModeParams()) {
                backlightMode = BacklightMode::WithTimer;
                setValue(settings::Brightness::brightnessLevel,
                         utils::to_string(params.getConstLinearProgressModeParams().targetBrightness));
            }
            else if (params.hasLinearProgressModeParams()) {
                backlightMode = BacklightMode::WithoutTimer;
            }
            break;
        case screen_light_control::Action::enableAutomaticMode:
            onDemandModeOn = false;
            break;
        case screen_light_control::Action::disableAutomaticMode:
            onDemandModeOn = true;
            break;
        default:
            break;
        }

        HandlerCommon::handleScreenLightSettings(action, params);
    }

    void Handler::onScreenLightTurnedOn()
    {
        if (!getScreenLightControl()->isAutoModeOn()) {
        if (backlightMode == BacklightMode::WithTimer) {
            startScreenLightTimer();
        }
    }

    void Handler::setKeyPressedModeFrontlightOn()
    {
        using namespace screen_light_control;
        auto brightnessLevel = utils::getNumericValue<float>(getValue(settings::Brightness::brightnessLevel));
        screen_light_control::ConstLinearProgressModeParameters params{brightnessLevel};
        screenLightController->processRequest(Action::setAutomaticModeParameters, Parameters(params));
    }

    void Handler::setKeyPressedModeFrontlightOff()
    {
        using namespace screen_light_control;
        screenLightController->processRequest(Action::setAutomaticModeParameters,
                                              Parameters(screen_light_control::ConstLinearProgressModeParameters{0}));
    }
} // namespace backlight

M products/BellHybrid/services/evtmgr/include/evtmgr/backlight-handler/BacklightHandler.hpp => products/BellHybrid/services/evtmgr/include/evtmgr/backlight-handler/BacklightHandler.hpp +16 -0
@@ 16,20 16,36 @@ namespace settings

namespace backlight
{
    enum class BacklightMode
    {
        WithTimer,
        WithoutTimer
    };
    /// @brief Backlight events handler
    class Handler : public HandlerCommon
    {
      public:
        Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent);

        void init() override;

        void handleKeyPressed(int key = 0);

        void processScreenRequest(screen_light_control::Action action,
                                  const screen_light_control::Parameters &params) override;

        void handleScreenLightSettings(screen_light_control::Action action,
                                       const screen_light_control::Parameters &params) override;

      private:
        void handleScreenLightRefresh(int key = 0);

        void onScreenLightTurnedOn() override;

        void setKeyPressedModeFrontlightOn();
        void setKeyPressedModeFrontlightOff();

        bool onDemandModeOn         = true;
        BacklightMode backlightMode = BacklightMode::WithTimer;
    };
} // namespace backlight

M products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp => products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp +58 -56
@@ 5,17 5,24 @@

#include <Service/Service.hpp>
#include <Timers/TimerFactory.hpp>
#include <Utils.hpp>

#include <system/Constants.hpp>
#include <system/messages/SentinelRegistrationMessage.hpp>

namespace bell::screen_light_control
{
    ScreenLightController::ScreenLightController(sys::Service *parent)
        : cpuSentinel(std::make_shared<sys::CpuSentinel>(screenLightControlName, parent))
    {
        controlTimer = sys::TimerFactory::createPeriodicTimer(parent,
        auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
        parent->bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);

        controlTimer  = sys::TimerFactory::createPeriodicTimer(parent,
                                                              "LightControlTimer",
                                                              std::chrono::milliseconds{CONTROL_TIMER_MS},
                                                              [this](sys::Timer &) { controlTimerCallback(); });

        setParameters(ManualModeParameters{});
        automaticMode = ScreenLightMode::Automatic;
    }

    ScreenLightController::~ScreenLightController()


@@ 38,37 45,35 @@ namespace bell::screen_light_control
            turnOn(params.hasManualModeParams() ? std::optional<ManualModeParameters>(params.getManualModeParams())
                                                : std::nullopt);
            break;
        case Action::enableAutomaticMode:
            enableAutomaticMode();
            break;
        case Action::disableAutomaticMode:
            disableAutomaticMode();
            setManualBrightnessLevel(brightnessValue);
            break;
        case Action::setManualModeBrightness:
            if (params.hasManualModeParams()) {
                setParameters(params.getManualModeParams());
            }
            break;
        case Action::setAutomaticModeParameters:
            if (params.hasLinearProgressModeParams()) {
                setParameters(params.getLinearProgressModeParams());
            }
            else if (params.hasConstLinearProgressModeParams()) {
                setParameters(params.getConstLinearProgressModeParams());
            }
            break;
        default:
            break;
        }
    }

    void ScreenLightController::controlTimerCallback()
    {
        auto currentBrightness = ::screen_light_control::functions::brightnessRampOut();
        auto newBrightness = ::screen_light_control::functions::brightnessRampOut();
        bsp::eink_frontlight::setBrightness(newBrightness);

        bsp::eink_frontlight::setBrightness(currentBrightness);
        if (::screen_light_control::functions::isRampTargetReached()) {
            if (!automaticModeFunctions.empty()) {
                setUpAutomaticFunction(getNextAutomaticFunction(), currentBrightness);
                setUpAutomaticFunction(getNextAutomaticFunction(), newBrightness);
            }
            else {
                disableAutomaticMode();
                if (newBrightness == MINIMAL_TARGET) {
                    turnOff();
                    bsp::eink_frontlight::turnOff();
                }
                setBrightnessInstant(MINIMAL_TARGET);
                disableTimers();
            }
        }
    }


@@ 85,7 90,7 @@ namespace bell::screen_light_control

    auto ScreenLightController::getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage
    {
        return brightnessValue;
        return brightnessWhenOn;
    }

    void ScreenLightController::enableTimers()


@@ 101,7 106,6 @@ namespace bell::screen_light_control
    void ScreenLightController::setParameters(const LinearProgressModeParameters &params)
    {
        if (params.functions.empty()) {
            LOG_ERROR("Functions are not defined. Cannot proceed with automatic mode.");
            disableTimers();
            return;
        }


@@ 113,7 117,7 @@ namespace bell::screen_light_control

        ::screen_light_control::functions::setHysteresis(params.brightnessHysteresis);
        setUpAutomaticFunction(getNextAutomaticFunction(), ::screen_light_control::functions::getRampState());
        setManualBrightnessLevel(params.startBrightnessValue);
        setBrightnessInstant(getStandarizedRampTarget(params.startBrightnessValue));

        if (lightOn && automaticMode == ScreenLightMode::Automatic) {
            enableTimers();


@@ 137,61 141,59 @@ namespace bell::screen_light_control
        ::screen_light_control::functions::LinearProgressFunction function,
        bsp::eink_frontlight::BrightnessPercentage currentBrightness)
    {
        const auto rampTarget = getStandarizedRampTarget(function.target);
        ::screen_light_control::functions::setRampStep(
            std::abs(function.target - currentBrightness) /
            std::abs(rampTarget - currentBrightness) /
            (static_cast<float>(function.duration.count()) / CONTROL_TIMER_MS));
        ::screen_light_control::functions::setRampTarget(function.target);
    }

    void ScreenLightController::setParameters(ManualModeParameters params)
    {
        brightnessValue = params.manualModeBrightness;
        ::screen_light_control::functions::setRampTarget(brightnessValue);
        setManualBrightnessLevel(brightnessValue);
    }

    void ScreenLightController::enableAutomaticMode()
    {
        if (lightOn) {
            enableTimers();
        }
        automaticMode = ScreenLightMode::Automatic;
        ::screen_light_control::functions::setRampTarget(rampTarget);
    }

    void ScreenLightController::disableAutomaticMode()
    void ScreenLightController::setParameters(const ConstLinearProgressModeParameters &params)
    {
        disableTimers();
        automaticMode = ScreenLightMode::Manual;
        automaticModeFunctions.clear();
        setBrightnessInstant(getStandarizedRampTarget(params.targetBrightness));
    }

    void ScreenLightController::turnOn(const std::optional<ManualModeParameters> &params)
    {
        if (params.has_value()) {
            const auto brightness = params->manualModeBrightness;
            ::screen_light_control::functions::setRampTarget(brightness);
            setManualBrightnessLevel(brightness);
            brightnessWhenOn = getStandarizedRampTarget(params->manualModeBrightness);
        }

        ::screen_light_control::functions::setRampTarget(brightnessWhenOn);
        bsp::eink_frontlight::turnOn();
        if (automaticMode == ScreenLightMode::Automatic) {
            enableTimers();
        }
        cpuSentinelKeepOn();
        enableTimers();
        lightOn = true;
    }

    void ScreenLightController::setManualBrightnessLevel(bsp::eink_frontlight::BrightnessPercentage brightness)
    void ScreenLightController::setBrightnessInstant(bsp::eink_frontlight::BrightnessPercentage brightness)
    {
        bsp::eink_frontlight::setBrightness(brightness);
        ::screen_light_control::functions::setRampState(brightness);
        brightnessWhenOn = getStandarizedRampTarget(brightness);
        ::screen_light_control::functions::setRampTarget(brightnessWhenOn);
        ::screen_light_control::functions::setRampStep(RAMP_STEP_PER_MS * CONTROL_TIMER_MS);
    }

    void ScreenLightController::turnOff()
    {
        bsp::eink_frontlight::turnOff();
        disableAutomaticMode();
        lightOn = false;
        ::screen_light_control::functions::setRampTarget(MINIMAL_TARGET);
        cpuSentinelRelease();
        enableTimers();
    }

        setManualBrightnessLevel(brightnessValue);
    void ScreenLightController::cpuSentinelKeepOn()
    {
        cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_6);
    }

    void ScreenLightController::cpuSentinelRelease()
    {
        cpuSentinel->ReleaseMinimumFrequency();
    }

    bsp::eink_frontlight::BrightnessPercentage ScreenLightController::getStandarizedRampTarget(
        bsp::eink_frontlight::BrightnessPercentage target)
    {
        return std::max<bsp::eink_frontlight::BrightnessPercentage>(target, MINIMAL_TARGET);
    }
} // namespace screen_light_control
} // namespace bell::screen_light_control

M products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.hpp => products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.hpp +22 -12
@@ 6,6 6,7 @@
#include <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp>

#include <SystemManager/CpuSentinel.hpp>
#include <Timers/TimerHandle.hpp>

#include <memory>


@@ 19,15 20,18 @@ namespace sys
/// Processing of ambient light sensor input to screen brightness output.
namespace bell::screen_light_control
{
    constexpr auto screenLightControlName = "ScreenLightControl";

    /// Control screen light and keeps it's current state
    class ScreenLightController : public ::screen_light_control::ScreenLightController
    {
      public:
        using Action                       = ::screen_light_control::Action;
        using Parameters                   = ::screen_light_control::Parameters;
        using ScreenLightMode              = ::screen_light_control::ScreenLightMode;
        using ManualModeParameters         = ::screen_light_control::ManualModeParameters;
        using LinearProgressModeParameters = ::screen_light_control::LinearProgressModeParameters;
        using Action                            = ::screen_light_control::Action;
        using Parameters                        = ::screen_light_control::Parameters;
        using ScreenLightMode                   = ::screen_light_control::ScreenLightMode;
        using ManualModeParameters              = ::screen_light_control::ManualModeParameters;
        using LinearProgressModeParameters      = ::screen_light_control::LinearProgressModeParameters;
        using ConstLinearProgressModeParameters = ::screen_light_control::ConstLinearProgressModeParameters;

        explicit ScreenLightController(sys::Service *parent);
        ~ScreenLightController() override;


@@ 46,8 50,8 @@ namespace bell::screen_light_control
        void disableTimers();

        void setParameters(const LinearProgressModeParameters &params);
        void setParameters(ManualModeParameters params);
        void setManualBrightnessLevel(bsp::eink_frontlight::BrightnessPercentage brightness);
        void setParameters(const ConstLinearProgressModeParameters &params);
        void setBrightnessInstant(bsp::eink_frontlight::BrightnessPercentage brightness);

        void setAutomaticModeFunctions(const LinearProgressModeParameters::LinearFunctions &functions);
        ::screen_light_control::functions::LinearProgressFunction getNextAutomaticFunction();


@@ 57,15 61,21 @@ namespace bell::screen_light_control
        void turnOff();
        void turnOn(const std::optional<ManualModeParameters> &params = std::nullopt);

        void enableAutomaticMode();
        void disableAutomaticMode();
        void cpuSentinelKeepOn();
        void cpuSentinelRelease();

        bsp::eink_frontlight::BrightnessPercentage getStandarizedRampTarget(
            bsp::eink_frontlight::BrightnessPercentage target);

        static constexpr inline auto CONTROL_TIMER_MS = 25;
        static constexpr inline auto RAMP_STEP_PER_MS = 0.1;
        static constexpr inline auto MINIMAL_TARGET   = 15;

        sys::TimerHandle controlTimer;
        bool lightOn                                               = false;
        ScreenLightMode automaticMode                              = ScreenLightMode::Manual;
        bsp::eink_frontlight::BrightnessPercentage brightnessValue = 0.0;
        std::shared_ptr<sys::CpuSentinel> cpuSentinel;
        bool lightOn                                                = false;
        ScreenLightMode automaticMode                               = ScreenLightMode::Manual;
        bsp::eink_frontlight::BrightnessPercentage brightnessWhenOn = MINIMAL_TARGET;
        LinearProgressModeParameters::LinearFunctions automaticModeFunctions;
    };
} // namespace bell::screen_light_control

M products/BellHybrid/services/time/AlarmOperations.cpp => products/BellHybrid/services/time/AlarmOperations.cpp +33 -14
@@ 152,12 152,26 @@ namespace alarms
          bedtime(std::move(bedtimeSettingsProvider))
    {}

    void AlarmOperations::minuteUpdated(TimePoint now)
    bool AlarmOperations::minuteUpdated(TimePoint now)
    {
        AlarmOperationsCommon::minuteUpdated(now);
        processPreWakeUp(now);
        processSnoozeChime(now);
        processBedtime(now);
        /**
         * A very simple alarm priority:
         * 1. Main alarm
         * 2. Pre wake up
         * 3. Snooze
         * 4. Bedtime
         * By design, there is no possibility to have both the main alarm, pre wakeup, and snooze alarm set for the same
         * timestamp hence it is safe to process these three in the one go.
         */
        auto wasAlarmConsumed = AlarmOperationsCommon::minuteUpdated(now);
        wasAlarmConsumed |= processPreWakeUp(now);
        wasAlarmConsumed |= processSnoozeChime(now);

        if (not wasAlarmConsumed) {
            processBedtime(now);
        }

        return false;
    }

    void AlarmOperations::stopAllSnoozedAlarms()


@@ 166,22 180,22 @@ namespace alarms
        AlarmOperationsCommon::stopAllSnoozedAlarms();
    }

    void AlarmOperations::processPreWakeUp(TimePoint now)
    bool AlarmOperations::processPreWakeUp(TimePoint now)
    {
        if (nextSingleEvents.empty()) {
            return;
            return false;
        }

        auto nextEvent = getNextPreWakeUpEvent();
        if (!nextEvent.isValid()) {
            return;
            return false;
        }

        const auto decision = preWakeUp.decide(now, nextEvent);
        if (!decision.timeForChime && !decision.timeForFrontlight) {
            return;
            return false;
        }
        handlePreWakeUp(nextEvent, decision);
        return handlePreWakeUp(nextEvent, decision);
    }

    void AlarmOperations::processBedtime(TimePoint now)


@@ 210,27 224,30 @@ namespace alarms
        return event;
    }

    void AlarmOperations::handlePreWakeUp(const SingleEventRecord &event, PreWakeUp::Decision decision)
    bool AlarmOperations::handlePreWakeUp(const SingleEventRecord &event, PreWakeUp::Decision decision)
    {
        if (auto alarmEventPtr = std::dynamic_pointer_cast<AlarmEventRecord>(event.parent); alarmEventPtr) {
            if (decision.timeForChime) {
                handleAlarmEvent(alarmEventPtr, alarms::AlarmType::PreWakeUpChime, true);
                return true;
            }
            if (decision.timeForFrontlight) {
                handleAlarmEvent(alarmEventPtr, alarms::AlarmType::PreWakeUpFrontlight, true);
                return true;
            }
        }
        return false;
    }

    void AlarmOperations::processSnoozeChime(TimePoint now)
    bool AlarmOperations::processSnoozeChime(TimePoint now)
    {
        if (!ongoingSingleEvents.empty()) {
            return;
            return false;
        }

        auto settings = snoozeChimeSettings->getSettings();
        if (!settings.enabled) {
            return;
            return false;
        }

        for (auto &snoozedEvent : snoozedSingleEvents) {


@@ 239,8 256,10 @@ namespace alarms
            const auto isTimeForChime = (minuteDelta % settings.chimeInterval.count()) == 0;
            if (isTimeForChime) {
                handleSnoozeChime(*snoozedEvent, true);
                return true;
            }
        }
        return false;
    }

    void AlarmOperations::handleSnoozeChime(const SingleEventRecord &event, bool newStateOn)

M products/BellHybrid/services/time/include/time/AlarmOperations.hpp => products/BellHybrid/services/time/include/time/AlarmOperations.hpp +5 -5
@@ 94,15 94,15 @@ namespace alarms
                        std::unique_ptr<SnoozeChimeSettingsProvider> &&snoozeChimeSettingsProvider,
                        std::unique_ptr<AbstractBedtimeSettingsProvider> &&BedtimeModel);

        void minuteUpdated(TimePoint now) override;
      private:
        bool minuteUpdated(TimePoint now) override;
        void stopAllSnoozedAlarms() override;
        void processPreWakeUp(TimePoint now);
        void processSnoozeChime(TimePoint now);
        bool processPreWakeUp(TimePoint now);
        bool processSnoozeChime(TimePoint now);
        void stopAllSnoozeChimes();

      private:
        SingleEventRecord getNextPreWakeUpEvent();
        void handlePreWakeUp(const SingleEventRecord &event, PreWakeUp::Decision decision);
        bool handlePreWakeUp(const SingleEventRecord &event, PreWakeUp::Decision decision);
        void handleSnoozeChime(const SingleEventRecord &event, bool newStateOn);
        void handleBedtime(const SingleEventRecord &event, bool decision);
        void processBedtime(TimePoint now);

M products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.cpp => products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.cpp +33 -2
@@ 18,14 18,45 @@ namespace backlight
    } // namespace timers

    Handler::Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent)
        : HandlerCommon(
              std::move(settings), std::make_shared<pure::screen_light_control::ScreenLightController>(parent), parent),
        : HandlerCommon(std::move(settings),
                        std::make_shared<pure::screen_light_control::ScreenLightController>(parent),
                        parent,
                        [this](sys::Timer &t) {
                            if (getScreenAutoModeState() == screen_light_control::ScreenLightMode::Automatic &&
                                this->screenLightController->isLightOn()) {
                                this->screenLightController->processRequest(screen_light_control::Action::turnOff);
                            }
                        }),
          keypadLightTimer{sys::TimerFactory::createSingleShotTimer(
              parent, timers::keypadLightTimerName, timers::keypadLightTimerTimeout, [this](sys::Timer &) {
                  bsp::keypad_backlight::shutdown();
              })}
    {}

    void Handler::init()
    {
        using namespace screen_light_control;

        settings->registerValueChange(settings::Brightness::brightnessLevel, [&](const std::string &value) {
            ManualModeParameters params{utils::getNumericValue<float>(value)};
            screenLightController->processRequest(Action::setManualModeBrightness, Parameters(params));
        });

        settings->registerValueChange(settings::Brightness::autoMode, [&]([[maybe_unused]] const std::string &value) {
            const auto action = getScreenAutoModeState() == ScreenLightMode::Automatic ? Action::enableAutomaticMode
                                                                                       : Action::disableAutomaticMode;
            screenLightController->processRequest(action);
        });

        settings->registerValueChange(settings::Brightness::state, [&]([[maybe_unused]] const std::string &value) {
            const auto action = getScreenLightState() ? Action::turnOn : Action::turnOff;
            if (action == Action::turnOn) {
                onScreenLightTurnedOn();
            }
            screenLightController->processRequest(action);
        });
    }

    void Handler::handleKeyPressed([[maybe_unused]] int key)
    {
        handleKeypadLightRefresh();

M products/PurePhone/services/evtmgr/include/evtmgr/BacklightHandler.hpp => products/PurePhone/services/evtmgr/include/evtmgr/BacklightHandler.hpp +1 -1
@@ 22,6 22,7 @@ namespace backlight
      public:
        Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent);

        void init() override;
        void handleKeyPressed(int key = 0);
        /// Process request of the keypad light control
        /// @keypad_backlight::action an action to perform


@@ 32,7 33,6 @@ namespace backlight
                                  const screen_light_control::Parameters &params) override;

      private:
        std::shared_ptr<settings::Settings> settings;
        /// Timer that keeps key backlight on for a certain time if there was key pressed
        sys::TimerHandle keypadLightTimer;
        /// Timer that keeps screen backlight on for a certain time if there was key pressed

M products/PurePhone/services/time/AlarmOperations.cpp => products/PurePhone/services/time/AlarmOperations.cpp +2 -2
@@ 25,8 25,8 @@ namespace alarms
        : AlarmOperationsCommon{std::move(alarmEventsRepo), std::move(getCurrentTimeCallback)}
    {}

    void AlarmOperations::minuteUpdated(TimePoint now)
    bool AlarmOperations::minuteUpdated(TimePoint now)
    {
        AlarmOperationsCommon::minuteUpdated(now);
        return AlarmOperationsCommon::minuteUpdated(now);
    }
} // namespace alarms

M products/PurePhone/services/time/include/time/AlarmOperations.hpp => products/PurePhone/services/time/include/time/AlarmOperations.hpp +1 -1
@@ 22,7 22,7 @@ namespace alarms
        AlarmOperations(std::unique_ptr<AbstractAlarmEventsRepository> &&alarmEventsRepo,
                        GetCurrentTime getCurrentTimeCallback);

        void minuteUpdated(TimePoint now) override;
        bool minuteUpdated(TimePoint now) override;

      private:
    };