~aleteoryx/muditaos

4948af4f777aa2c522a31443620b2dd2f5ed62c2 — Mateusz Piesta 4 years ago dae736c
[BH-618] Power nap fixes

Implemented various fixes:
BH-995
BH-996
BH-997
BH-998
Fixed PlayActions
and more.
20 files changed, 166 insertions(+), 236 deletions(-)

M image/user/db/settings_bell_002.sql
M module-apps/apps-common/widgets/ProgressTimer.cpp
M module-apps/apps-common/widgets/ProgressTimer.hpp
M module-services/service-db/agents/settings/Settings.cpp
M module-services/service-db/include/service-db/Settings.hpp
M products/BellHybrid/alarms/BellAlarmHandler.cpp
M products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp
M products/BellHybrid/alarms/src/actions/PlayAudioActions.hpp
M products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp
M products/BellHybrid/apps/application-bell-powernap/CMakeLists.txt
M products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp
M products/BellHybrid/apps/application-bell-powernap/models/PowerNapModel.cpp
M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp
M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp
D products/BellHybrid/apps/application-bell-powernap/widgets/PowerNapAlarm.cpp
D products/BellHybrid/apps/application-bell-powernap/widgets/PowerNapAlarm.hpp
M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp
M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapSessionEndedWindow.cpp
M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapSessionEndedWindow.hpp
M products/BellHybrid/services/db/include/db/SystemSettings.hpp
M image/user/db/settings_bell_002.sql => image/user/db/settings_bell_002.sql +3 -1
@@ 43,4 43,6 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
    ('alarm_tone','Atumnal Sea'),
    ('alarm_volume','5'),
    ('alarm_light_active','1'),
    ('alarm_duration','10000');
    ('alarm_duration','10000'),
    ('bedtime_tone','Evening Horizon'),
    ('bedtime_duration','5');

M module-apps/apps-common/widgets/ProgressTimer.cpp => module-apps/apps-common/widgets/ProgressTimer.cpp +5 -4
@@ 6,7 6,6 @@
#include <ProgressBar.hpp>
#include <ApplicationCommon.hpp>
#include <apps-common/GuiTimer.hpp>
#include <time/time_conversion.hpp>
#include <gsl/assert>

namespace


@@ 20,8 19,10 @@ namespace app
                                 gui::Item &parent,
                                 std::string timerName,
                                 std::chrono::milliseconds baseTick,
                                 ProgressCountdownMode countdownMode)
        : app{app}, parent{parent}, name{std::move(timerName)}, baseTickInterval{baseTick}, countdownMode{countdownMode}
                                 ProgressCountdownMode countdownMode,
                                 utils::time::Duration::DisplayedFormat displayFormat)
        : app{app}, parent{parent}, name{std::move(timerName)}, baseTickInterval{baseTick},
          countdownMode{countdownMode}, displayFormat{displayFormat}
    {}

    void ProgressTimer::resetProgress()


@@ 50,7 51,7 @@ namespace app
        if (countdownMode == ProgressCountdownMode::Increasing && secondsRemaining != std::chrono::seconds::zero()) {
            timerText += increasingModePrefix;
        }
        timerText += remainingDuration.str(Duration::DisplayedFormat::Fixed0M0S);
        timerText += remainingDuration.str(displayFormat);
        text->setText(std::move(timerText));
    }


M module-apps/apps-common/widgets/ProgressTimer.hpp => module-apps/apps-common/widgets/ProgressTimer.hpp +9 -5
@@ 4,6 4,7 @@

#include "TimerWithCallbacks.hpp"
#include <Timers/TimerHandle.hpp>
#include <time/time_conversion.hpp>
#include <atomic>
#include <chrono>
#include <string>


@@ 56,6 57,7 @@ namespace app
        std::function<void()> onFinishedCallback = nullptr;
        std::function<void()> onIntervalCallback = nullptr;
        ProgressCountdownMode countdownMode;
        utils::time::Duration::DisplayedFormat displayFormat;

        void startTimer();
        void update();


@@ 67,11 69,13 @@ namespace app
        [[nodiscard]] auto intervalReached() const noexcept -> bool;

      public:
        ProgressTimer(app::ApplicationCommon *app,
                      gui::Item &parent,
                      std::string timerName,
                      std::chrono::milliseconds baseTick,
                      ProgressCountdownMode countdownMode = ProgressCountdownMode::Decreasing);
        ProgressTimer(
            app::ApplicationCommon *app,
            gui::Item &parent,
            std::string timerName,
            std::chrono::milliseconds baseTick,
            ProgressCountdownMode countdownMode                    = ProgressCountdownMode::Decreasing,
            utils::time::Duration::DisplayedFormat displayedFormat = utils::time::Duration::DisplayedFormat::AutoM);
        void reset(std::chrono::seconds _duration,
                   std::chrono::seconds _interval = std::chrono::seconds::zero()) override;
        void start() override;

M module-services/service-db/agents/settings/Settings.cpp => module-services/service-db/agents/settings/Settings.cpp +4 -0
@@ 112,5 112,9 @@ namespace settings
    {
        return SettingsCache::getInstance();
    }
    Settings::Settings(const service::ServiceProxy &interface)
    {
        init(interface);
    }

} // namespace settings

M module-services/service-db/include/service-db/Settings.hpp => module-services/service-db/include/service-db/Settings.hpp +1 -0
@@ 26,6 26,7 @@ namespace settings
        using ValueChangedCallback         = std::function<void(const std::string &)>;
        using ValueChangedCallbackWithName = std::function<void(const std::string &, const std::string &value)>;

        explicit Settings(const service::ServiceProxy &interface);
        Settings() = default;
        virtual ~Settings();


M products/BellHybrid/alarms/BellAlarmHandler.cpp => products/BellHybrid/alarms/BellAlarmHandler.cpp +4 -4
@@ 38,7 38,7 @@ namespace alarms
    auto BellAlarmClockHandler::getActions(sys::Service *service) -> Actions
    {
        Actions actions;
        actions.emplace_back(std::make_unique<PlayToneAction>(*service));
        actions.emplace_back(factory::createAlarmToneAction(*service));
        actions.emplace_back(std::make_unique<NotifyGUIAction>(*service));
        actions.emplace_back(std::make_unique<FrontlightAction>(*service, FrontlightAction::Mode::Manual));
        return actions;


@@ 50,7 50,7 @@ namespace alarms
    auto PreWakeUpChimeHandler::getActions(sys::Service *service) -> Actions
    {
        Actions actions;
        actions.emplace_back(createPreWakeUpChimeAction(*service));
        actions.emplace_back(factory::createPreWakeUpChimeAction(*service));
        return actions;
    }



@@ 71,7 71,7 @@ namespace alarms
    auto SnoozeChimeHandler::getActions(sys::Service *service) -> Actions
    {
        Actions actions;
        actions.emplace_back(createSnoozeChimeAction(*service));
        actions.emplace_back(factory::createSnoozeChimeAction(*service));
        return actions;
    }



@@ 81,7 81,7 @@ namespace alarms
    auto BedtimeReminderHandler::getActions(sys::Service *service) -> Actions
    {
        Actions actions;
        actions.emplace_back(createBedtimeChimeAction(*service));
        actions.emplace_back(factory::createBedtimeChimeAction(*service));
        actions.emplace_back(std::make_unique<NotifyGUIBedtimeReminderAction>(*service));
        return actions;
    }

M products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp => products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp +42 -57
@@ 6,18 6,17 @@

#include <service-time/ServiceTime.hpp>
#include <db/SystemSettings.hpp>
#include <purefs/filesystem_paths.hpp>
#include <Timers/TimerFactory.hpp>

namespace
{
    constexpr auto timerName = "playDurationTimer";
} // namespace

namespace alarms
{
    PlayAudioAction::PlayAudioAction(sys::Service &service, audio::PlaybackType playbackType)
        : service{service}, playbackType{playbackType}
    PlayAudioAction::PlayAudioAction(sys::Service &service,
                                     const std::filesystem::path &tonesDirPath,
                                     std::string_view toneSetting,
                                     std::string_view durationSetting,
                                     audio::PlaybackType playbackType)
        : service{service}, soundsRepository{tonesDirPath}, toneSetting{toneSetting}, durationSetting{durationSetting},
          playbackType{playbackType}, settings{service::ServiceProxy{service.weak_from_this()}}
    {}

    bool PlayAudioAction::play(const std::filesystem::path &path, std::chrono::seconds duration)


@@ 30,9 29,17 @@ namespace alarms

    bool PlayAudioAction::turnOff()
    {
        detachTimer();
        auto stopPlaybackVec = std::vector<audio::PlaybackType>({playbackType});
        return AudioServiceAPI::Stop(&service, stopPlaybackVec);
    }
    bool PlayAudioAction::execute()
    {
        const auto tone        = settings.getValue(toneSetting, settings::SettingsScope::Global);
        const auto durationStr = settings.getValue(durationSetting, settings::SettingsScope::Global);
        const auto durationVal = utils::getNumericValue<int>(durationStr);
        return play(soundsRepository.titleToPath(tone).value_or(""), std::chrono::seconds{durationVal});
    }

    void PlayAudioAction::detachTimer()
    {


@@ 43,6 50,7 @@ namespace alarms
    }
    void PlayAudioAction::spawnTimer(std::chrono::seconds timeout)
    {
        constexpr auto timerName = "playDurationTimer";
        if (not timer.isValid()) {
            auto callback = [this](sys::Timer &) { turnOff(); };
            timer         = sys::TimerFactory::createSingleShotTimer(&service, timerName, timeout, callback);


@@ 50,55 58,32 @@ namespace alarms
        timer.stop();
        timer.start();
    }

    PlayToneAction::PlayToneAction(sys::Service &service) : PlayAudioAction{service, audio::PlaybackType::Alarm}
    {
        settings.init(service::ServiceProxy{service.weak_from_this()});
    }

    bool PlayToneAction::execute()
    {
        const auto tone     = settings.getValue(bell::settings::Alarm::tone, settings::SettingsScope::Global);
        const auto tonePath = paths::getMusicDir() / tone;
        const auto valueStr = settings.getValue(bell::settings::Alarm::duration, settings::SettingsScope::Global);
        const auto ringingDuration = std::chrono::seconds{utils::getNumericValue<uint32_t>(valueStr)};
        return play(tonePath, ringingDuration);
    }

    bool PlayBedtimeToneAction::execute()
    {
        return play(paths::getBedtimeReminderChimesDir() / bedtimeNotificationAudoFile, InfiniteDuration);
    }

    std::unique_ptr<PlayChimeAction> createPreWakeUpChimeAction(sys::Service &service)
    {
        return std::make_unique<PlayChimeAction>(
            service, paths::getPreWakeUpChimesDir(), bell::settings::PrewakeUp::tone);
    }

    std::unique_ptr<PlayChimeAction> createSnoozeChimeAction(sys::Service &service)
    {
        return std::make_unique<PlayChimeAction>(service, paths::getSnoozeChimesDir(), bell::settings::Snooze::tone);
    }

    std::unique_ptr<PlayBedtimeToneAction> createBedtimeChimeAction(sys::Service &service)
    {
        return std::make_unique<PlayBedtimeToneAction>(service);
    }

    PlayChimeAction::PlayChimeAction(sys::Service &service,
                                     const std::filesystem::path &tonesDirPath,
                                     std::string_view toneSetting)
        : PlayAudioAction{service, audio::PlaybackType::Multimedia}, tonesDirPath{tonesDirPath}, toneSetting{
                                                                                                     toneSetting}
    namespace factory
    {
        settings.init(service::ServiceProxy{service.weak_from_this()});
    }
        std::unique_ptr<PlayAudioAction> createPreWakeUpChimeAction(sys::Service &service)
        {
            return std::make_unique<PlayAudioAction>(service,
                                                     paths::getPreWakeUpChimesDir(),
                                                     bell::settings::PrewakeUp::tone,
                                                     bell::settings::PrewakeUp::duration);
        }

    bool PlayChimeAction::execute()
    {
        const auto tone     = settings.getValue(toneSetting.data(), settings::SettingsScope::Global);
        const auto tonePath = tonesDirPath / tone;
        return play(tonePath);
    }
        std::unique_ptr<PlayAudioAction> createSnoozeChimeAction(sys::Service &service)
        {
            return std::make_unique<PlayAudioAction>(
                service, paths::getSnoozeChimesDir(), bell::settings::Snooze::tone, bell::settings::Snooze::length);
        }
        std::unique_ptr<PlayAudioAction> createAlarmToneAction(sys::Service &service)
        {
            return std::make_unique<PlayAudioAction>(
                service, paths::getAlarmDir(), bell::settings::Alarm::tone, bell::settings::Alarm::duration);
        }
        std::unique_ptr<PlayAudioAction> createBedtimeChimeAction(sys::Service &service)
        {
            return std::make_unique<PlayAudioAction>(service,
                                                     paths::getBedtimeReminderChimesDir(),
                                                     bell::settings::Bedtime::tone,
                                                     bell::settings::Bedtime::duration);
        }
    } // namespace factory
} // namespace alarms

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

#include "AbstractAlarmAction.hpp"
#include <common/SoundsRepository.hpp>
#include <service-audio/AudioServiceAPI.hpp>
#include <module-audio/Audio/AudioCommon.hpp>
#include <service-db/Settings.hpp>


@@ 19,57 20,33 @@ namespace alarms
    {
      public:
        bool turnOff() override;
        bool execute() override;
        explicit PlayAudioAction(sys::Service &service,
                                 const std::filesystem::path &tonesDirPath,
                                 std::string_view toneSetting,
                                 std::string_view durationSetting,
                                 audio::PlaybackType = audio::PlaybackType::Alarm);

      protected:
        explicit PlayAudioAction(sys::Service &service, audio::PlaybackType = audio::PlaybackType::Alarm);

      private:
        static constexpr auto InfiniteDuration = std::chrono::seconds::max();
        bool play(const std::filesystem::path &path, std::chrono::seconds duration = InfiniteDuration);

      private:
        void spawnTimer(std::chrono::seconds timeout);
        void detachTimer();

        sys::Service &service;
        sys::TimerHandle timer;
        audio::PlaybackType playbackType;
    };

    class PlayToneAction : public PlayAudioAction
    {
      public:
        explicit PlayToneAction(sys::Service &service);
        bool execute() override;

      private:
        SoundsRepository soundsRepository;
        const std::string toneSetting;
        const std::string durationSetting;
        const audio::PlaybackType playbackType;
        settings::Settings settings;
    };

    class PlayBedtimeToneAction : public PlayToneAction
    {
        static auto constexpr bedtimeNotificationAudoFile = "Evening_Horizon.mp3";

      public:
        using PlayToneAction::PlayToneAction;
        bool execute() override;
    };

    class PlayChimeAction : public PlayAudioAction
    namespace factory
    {
      public:
        explicit PlayChimeAction(sys::Service &service,
                                 const std::filesystem::path &tonesDirPath,
                                 std::string_view toneSetting);
        bool execute() override;

      private:
        settings::Settings settings;
        std::filesystem::path tonesDirPath;
        std::string_view toneSetting;
    };

    std::unique_ptr<PlayChimeAction> createPreWakeUpChimeAction(sys::Service &service);
    std::unique_ptr<PlayChimeAction> createSnoozeChimeAction(sys::Service &service);
    std::unique_ptr<PlayBedtimeToneAction> createBedtimeChimeAction(sys::Service &service);

        std::unique_ptr<PlayAudioAction> createAlarmToneAction(sys::Service &service);
        std::unique_ptr<PlayAudioAction> createPreWakeUpChimeAction(sys::Service &service);
        std::unique_ptr<PlayAudioAction> createSnoozeChimeAction(sys::Service &service);
        std::unique_ptr<PlayAudioAction> createBedtimeChimeAction(sys::Service &service);
    } // namespace factory
} // namespace alarms

M products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp => products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp +11 -15
@@ 5,11 5,11 @@
#include "presenter/PowerNapMainWindowPresenter.hpp"
#include "presenter/PowerNapProgressPresenter.hpp"
#include "presenter/PowerNapSessionEndedPresenter.hpp"
#include "widgets/PowerNapAlarm.hpp"
#include "windows/PowerNapMainWindow.hpp"
#include "windows/PowerNapProgressWindow.hpp"
#include "windows/PowerNapSessionEndedWindow.hpp"
#include <common/models/TimeModel.hpp>
#include <AlarmSoundPaths.hpp>
#include <service-audio/AudioMessage.hpp>

namespace app


@@ 18,8 18,7 @@ namespace app
                                                     std::string parent,
                                                     StatusIndicators statusIndicators,
                                                     StartInBackground startInBackground)
        : Application(std::move(name), std::move(parent), statusIndicators, startInBackground),
          alarm{std::make_unique<powernap::PowerNapAlarmImpl>(this)}
        : Application(std::move(name), std::move(parent), statusIndicators, startInBackground)
    {}

    ApplicationBellPowerNap::~ApplicationBellPowerNap() = default;


@@ 40,13 39,15 @@ namespace app
            auto presenter = std::make_unique<powernap::PowerNapMainWindowPresenter>(app, settings.get());
            return std::make_unique<gui::PowerNapMainWindow>(app, std::move(presenter));
        });
        windowsFactory.attach(gui::window::name::powernapProgress,
                              [this](ApplicationCommon *app, const std::string &name) {
                                  auto timeModel = std::make_unique<app::TimeModel>();
                                  auto presenter = std::make_unique<powernap::PowerNapProgressPresenter>(
                                      app, settings.get(), *alarm, std::move(timeModel));
                                  return std::make_unique<gui::PowerNapProgressWindow>(app, std::move(presenter));
                              });
        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));
                return std::make_unique<gui::PowerNapProgressWindow>(app, std::move(presenter));
            });
        windowsFactory.attach(gui::window::name::powernapSessionEnded,
                              [](ApplicationCommon *app, const std::string &name) {
                                  auto presenter = std::make_unique<powernap::PowerNapSessionEndPresenter>(app);


@@ 68,11 69,6 @@ namespace app
            return retMsg;
        }

        if ((resp != nullptr) && typeid(*resp) == typeid(AudioStartPlaybackResponse)) {
            auto *msg = static_cast<AudioStartPlaybackResponse *>(resp);
            alarm->registerAudioStream(msg->token);
        }

        return handleAsyncResponse(resp);
    }


M products/BellHybrid/apps/application-bell-powernap/CMakeLists.txt => products/BellHybrid/apps/application-bell-powernap/CMakeLists.txt +3 -2
@@ 19,7 19,6 @@ target_sources(application-bell-powernap
        presenter/PowerNapMainWindowPresenter.cpp
        presenter/PowerNapProgressPresenter.cpp
        presenter/PowerNapSessionEndedPresenter.cpp
        widgets/PowerNapAlarm.cpp
        windows/PowerNapMainWindow.cpp
        windows/PowerNapProgressWindow.cpp
        windows/PowerNapSessionEndedWindow.cpp


@@ 29,7 28,6 @@ target_sources(application-bell-powernap
        presenter/PowerNapMainWindowPresenter.hpp
        presenter/PowerNapProgressPresenter.hpp
        presenter/PowerNapSessionEndedPresenter.hpp
        widgets/PowerNapAlarm.hpp
        windows/PowerNapMainWindow.hpp
        windows/PowerNapProgressWindow.hpp
        windows/PowerNapSessionEndedWindow.hpp


@@ 47,6 45,9 @@ target_link_libraries(application-bell-powernap
        app
        bell::app-common
        bell::app-main
        bell::keymap
        bell::alarms
        bell::db

    PUBLIC
        module-gui

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 +0 -2
@@ 21,8 21,6 @@ namespace app

    class ApplicationBellPowerNap : public Application
    {
        std::unique_ptr<powernap::PowerNapAlarmImpl> alarm;

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

M products/BellHybrid/apps/application-bell-powernap/models/PowerNapModel.cpp => products/BellHybrid/apps/application-bell-powernap/models/PowerNapModel.cpp +1 -1
@@ 9,7 9,7 @@
namespace
{
    constexpr std::chrono::minutes emptyValue{0};
    constexpr std::chrono::minutes spinnerDefaultValue{15};
    constexpr std::chrono::minutes spinnerDefaultValue{20};
} // namespace

namespace app::powernap

M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp +27 -7
@@ 4,10 4,10 @@
#include "PowerNapProgressPresenter.hpp"
#include "application-bell-powernap/ApplicationBellPowerNap.hpp"
#include "data/PowerNapCommon.hpp"
#include "widgets/PowerNapAlarm.hpp"

#include <apps-common/widgets/ProgressTimer.hpp>
#include <common/models/TimeModel.hpp>
#include <db/SystemSettings.hpp>
#include <service-db/Settings.hpp>
#include <Timers/TimerFactory.hpp>
#include <Utils.hpp>


@@ 17,15 17,18 @@
namespace
{
    inline constexpr auto powernapAlarmTimerName = "PowerNapAlarmTimer";
    inline constexpr std::chrono::minutes powernapAlarmTimeout{3};
    inline constexpr std::chrono::minutes powernapAlarmTimeout{5};
} // namespace

namespace app::powernap
{
    PowerNapProgressPresenter::PowerNapProgressPresenter(app::ApplicationCommon *app,
                                                         settings::Settings *settings,
                                                         PowerNapAlarm &alarm,
                                                         std::unique_ptr<AbstractSoundsRepository> soundsRepository,
                                                         std::unique_ptr<AbstractAudioModel> audioModel,
                                                         std::unique_ptr<AbstractTimeModel> timeModel)
        : app{app}, settings{settings}, alarm{alarm}, timeModel{std::move(timeModel)},
        : app{app}, settings{settings}, soundsRepository{std::move(soundsRepository)},
          audioModel{std::move(audioModel)}, timeModel{std::move(timeModel)},
          napAlarmTimer{sys::TimerFactory::createSingleShotTimer(
              app, powernapAlarmTimerName, powernapAlarmTimeout, [this](sys::Timer &) { onNapAlarmFinished(); })}



@@ 40,24 43,37 @@ namespace app::powernap
    void PowerNapProgressPresenter::activate()
    {
        Expects(timer != nullptr);
        const auto value = settings->getValue(powernapDBRecordName, settings::SettingsScope::AppLocal);
        const auto value = settings->getValue(powernapDBRecordName);
        timer->reset(std::chrono::minutes{utils::getNumericValue<int>(value)});
        timer->start();
    }
    void PowerNapProgressPresenter::endNap()
    {
        napFinished = false;
        timer->stop();
        napAlarmTimer.stop();
        onNapAlarmFinished();
    }
    void PowerNapProgressPresenter::onNapFinished()
    {
        alarm.start();
        const auto filePath = soundsRepository->titleToPath(
            settings->getValue(bell::settings::Alarm::tone, settings::SettingsScope::Global));
        auto playResponseCb = [this](audio::RetCode retCode, audio::Token token) {
            if (retCode != audio::RetCode::Success || !token.IsValid()) {
                LOG_ERROR("Audio preview callback failed with retcode = %s. Token validity: %d",
                          str(retCode).c_str(),
                          token.IsValid());
                return;
            }
            this->currentToken = token;
        };
        audioModel->play(filePath.value_or(""), playResponseCb, AbstractAudioModel::PlaybackType::Alarm);
        napAlarmTimer.start();
        napFinished = true;
    }
    void PowerNapProgressPresenter::onNapAlarmFinished()
    {
        alarm.stop();
        audioModel->stop(currentToken, nullptr);
        getView()->napEnded();
    }



@@ 65,5 81,9 @@ namespace app::powernap
    {
        getView()->setTime(timeModel->getCurrentTime());
    }
    bool PowerNapProgressPresenter::isNapFinished()
    {
        return napFinished;
    }

} // namespace app::powernap

M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp +13 -6
@@ 5,6 5,8 @@

#include <apps-common/BasePresenter.hpp>
#include <apps-common/widgets/TimerWithCallbacks.hpp>
#include <common/models/AudioModel.hpp>
#include <common/SoundsRepository.hpp>
#include <time/time_locale.hpp>
#include <Timers/TimerHandle.hpp>
#include <memory>


@@ 24,14 26,13 @@ namespace settings

namespace app::powernap
{
    class PowerNapAlarm;
    class PowerNapProgressContract
    {
      public:
        class View
        {
          public:
            ~View() = default;
            ~View()                                                         = default;
            virtual void napEnded()                                         = 0;
            virtual void setTime(std::time_t newTime)                       = 0;
            virtual void setTimeFormat(utils::time::Locale::TimeFormat fmt) = 0;


@@ 44,22 45,27 @@ namespace app::powernap
            virtual void endNap()                                                   = 0;
            virtual void setTimer(std::unique_ptr<app::TimerWithCallbacks> &&timer) = 0;
            virtual void handleUpdateTimeEvent()                                    = 0;
            virtual bool isNapFinished()                                            = 0;
        };
    };

    class PowerNapProgressPresenter : public PowerNapProgressContract::Presenter
    {
        app::ApplicationCommon *app  = nullptr;
        settings::Settings *settings = nullptr;
        PowerNapAlarm &alarm;
        app::ApplicationCommon *app{};
        settings::Settings *settings{};
        std::unique_ptr<AbstractSoundsRepository> soundsRepository;
        std::unique_ptr<AbstractAudioModel> audioModel;
        std::unique_ptr<app::TimerWithCallbacks> timer;
        std::unique_ptr<AbstractTimeModel> timeModel;
        sys::TimerHandle napAlarmTimer;
        audio::Token currentToken;
        bool napFinished{false};

        void activate() override;
        void endNap() override;
        void setTimer(std::unique_ptr<app::TimerWithCallbacks> &&_timer) override;
        void handleUpdateTimeEvent() override;
        bool isNapFinished() override;

        void onNapFinished();
        void onNapAlarmFinished();


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

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

#include "PowerNapAlarm.hpp"

#include <purefs/filesystem_paths.hpp>
#include <service-audio/AudioServiceAPI.hpp>

namespace
{
    constexpr auto alarmAudioPath = "assets/audio/alarm/alarm_mudita_bell.mp3";
}

namespace app::powernap
{
    PowerNapAlarmImpl::PowerNapAlarmImpl(app::ApplicationCommon *app) : app{app}
    {}

    void PowerNapAlarmImpl::start()
    {
        AudioServiceAPI::PlaybackStart(
            app, audio::PlaybackType::Alarm, purefs::dir::getCurrentOSPath() / alarmAudioPath);
    }

    void PowerNapAlarmImpl::stop()
    {
        if (token.IsValid()) {
            AudioServiceAPI::Stop(app, token);
            token = audio::Token::MakeBadToken();
        }
    }

    void PowerNapAlarmImpl::registerAudioStream(audio::Token _token)
    {
        token = _token;
    }
} // namespace app::powernap

D products/BellHybrid/apps/application-bell-powernap/widgets/PowerNapAlarm.hpp => products/BellHybrid/apps/application-bell-powernap/widgets/PowerNapAlarm.hpp +0 -36
@@ 1,36 0,0 @@
// 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 <module-audio/Audio/AudioCommon.hpp>

namespace app
{
    class ApplicationCommon;
}

namespace app::powernap
{
    class PowerNapAlarm
    {
      public:
        virtual ~PowerNapAlarm() = default;

        virtual void start() = 0;
        virtual void stop()  = 0;
    };

    class PowerNapAlarmImpl : public PowerNapAlarm
    {
        app::ApplicationCommon *app{};
        audio::Token token;

        void start() override;
        void stop() override;

      public:
        explicit PowerNapAlarmImpl(app::ApplicationCommon *app);
        void registerAudioStream(audio::Token _token);
    };

} // namespace app::powernap

M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp => products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp +8 -2
@@ 10,8 10,8 @@
#include <apps-common/widgets/ProgressTimer.hpp>
#include <apps-common/GuiTimer.hpp>
#include <Text.hpp>
#include <keymap/KeyMap.hpp>

#include <time/dateCommon.hpp>
namespace
{
    void decorateProgressItem(gui::Rect *item, gui::Alignment::Vertical alignment)


@@ 106,10 106,16 @@ namespace gui
    auto PowerNapProgressWindow::onInput(const InputEvent &inputEvent) -> bool
    {
        if (inputEvent.isShortRelease()) {
            if (inputEvent.is(KeyCode::KEY_RF) || inputEvent.is(KeyCode::KEY_ENTER)) {
            const auto key = mapKey(inputEvent.getKeyCode());
            if (presenter->isNapFinished() && key == KeyMap::LightPress) {
                presenter->endNap();
                return true;
            }
            else if (not presenter->isNapFinished() && key == KeyMap::Back) {
                application->returnToPreviousWindow();
                return true;
            }
            return false;
        }
        return AppWindow::onInput(inputEvent);
    }

M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapSessionEndedWindow.cpp => products/BellHybrid/apps/application-bell-powernap/windows/PowerNapSessionEndedWindow.cpp +11 -14
@@ 4,11 4,7 @@
#include "PowerNapSessionEndedWindow.hpp"
#include "data/PowerNapStyle.hpp"
#include <application-bell-powernap/ApplicationBellPowerNap.hpp>
#include <RichTextParser.hpp>
#include <BoxLayout.hpp>
#include <Image.hpp>
#include <Text.hpp>
#include <gui/core/FontManager.hpp>
#include <gui/widgets/Icon.hpp>

namespace gui
{


@@ 32,15 28,16 @@ namespace gui
        auto body = new VBox(this, 0, 0, style::window_width, style::window_height);
        body->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));

        new Image(body, "big_namaste_W_G");

        auto text = new Text(body, 0, 0, body->getWidth(), powerNapStyle::sessionEnd::textH);
        TextFormat format(FontManager::getInstance().getFont(powerNapStyle::descriptionFont));
        text::RichTextParser parser;
        auto textParsed = parser.parse(utils::translate("app_bell_powernap_session_ended_message"), &format);
        text->setText(std::move(textParsed));
        text->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        text->setVisible(true);
        auto icon = new Icon(this,
                             0,
                             0,
                             style::window_width,
                             style::window_height,
                             "big_namaste_W_G",
                             utils::translate("app_bell_powernap_session_ended_message"));
        icon->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        icon->image->setMargins({0, image_top_margin, 0, image_bottom_margin});
        icon->text->setFont(style::window::font::verybiglight);
    }

    void PowerNapSessionEndedWindow::registerCallbacks()

M products/BellHybrid/apps/application-bell-powernap/windows/PowerNapSessionEndedWindow.hpp => products/BellHybrid/apps/application-bell-powernap/windows/PowerNapSessionEndedWindow.hpp +2 -0
@@ 10,6 10,8 @@ namespace gui
{
    class PowerNapSessionEndedWindow : public WindowWithTimer, public app::powernap::PowerNapSessionEndedContract::View
    {
        static constexpr auto image_top_margin    = 112U;
        static constexpr auto image_bottom_margin = 30U;
        std::shared_ptr<app::powernap::PowerNapSessionEndedContract::Presenter> presenter;
        void buildInterface() override;
        void buildLayout();

M products/BellHybrid/services/db/include/db/SystemSettings.hpp => products/BellHybrid/services/db/include/db/SystemSettings.hpp +4 -2
@@ 33,7 33,9 @@ namespace bell::settings
    } // namespace Alarm
    namespace Bedtime
    {
        constexpr inline auto active = "bedtime_active";
        constexpr inline auto time   = "bedtime_time";
        constexpr inline auto tone     = "bedtime_tone";
        constexpr inline auto active   = "bedtime_active";
        constexpr inline auto time     = "bedtime_time";
        constexpr inline auto duration = "bedtime_duration";
    } // namespace Bedtime
};    // namespace bell::settings