~aleteoryx/muditaos

75a0a758468d54b16bd644ba0f1de5f1e5f2b73c — Tigran Soghbatyan 4 years ago caa5d70
[BH-1195] Fix audio playback while volume change

Prevent audio restart on volume setting change
23 files changed, 125 insertions(+), 83 deletions(-)

M products/BellHybrid/apps/application-bell-background-sounds/ApplicationBellBackgroundSounds.cpp
M products/BellHybrid/apps/application-bell-background-sounds/include/application-bell-background-sounds/ApplicationBellBackgroundSounds.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-bedtime/ApplicationBellBedtime.cpp
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-settings/ApplicationBellSettings.cpp
M products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/ApplicationBellSettings.hpp
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/common/include/common/models/AbstractAudioModel.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/src/AudioModel.cpp
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/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/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-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-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 -4
@@ 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(); })}



@@ 60,13 60,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-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/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/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/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/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