~aleteoryx/muditaos

10d9658a4a66b70ec640607df0b675f2cb1cf9e2 — Maciej Gibowicz 1 year, 7 months ago f585c33
[BH-2005] Add volume setting for focus timer

The user will be able to control the volume of notifications in the
Focus Timer application
M harmony_changelog.md => harmony_changelog.md +1 -0
@@ 9,6 9,7 @@
* Added custom alarms functionality
* Added update instruction screen at end of onboarding
* Added update instruction screen in Settings
* Added volume setting for focus timer application

### Changed / Improved
* Changed the refresh rate of the progress bar screen

M image/system_a/data/lang/Deutsch.json => image/system_a/data/lang/Deutsch.json +9 -8
@@ 28,19 28,20 @@
    "app_bell_bedtime_notification": "Schlafenszeit",
    "app_bell_charging_done_notification": "Vollst\u00e4ndig aufgeladen",
    "app_bell_charging_notification": "Wird aufgeladen",
    "app_bell_focus_long_break": "Lange Pause",
    "app_bell_focus_long_break_after": "Lange Pause nach",
    "app_bell_focus_notification_volume": "<text>Umfang<br/>der Benachrichtigung</text>",
    "app_bell_focus_repeats": "Timer-Wiederholung",
    "app_bell_focus_settings": "Einstellungen",
    "app_bell_focus_short_break": "Kurze Pause",
    "app_bell_focus_start": "Nun konzentriert",
    "app_bell_focus_summary": "<text>Super! <token>$VALUE</token> Konzentration<br></br>beendet.</text>",
    "app_bell_focus_time": "Konzent.-Timer",
    "app_bell_focus_repeats": "Timer-Wiederholung",
    "app_bell_focus_short_break": "Kurze Pause",
    "app_bell_focus_long_break": "Lange Pause",
    "app_bell_focus_time_for_focus": "Konzentration",
    "app_bell_focus_time_for_break": "Nun eine Pause",
    "app_bell_focus_well_done": "Super!",
    "app_bell_focus_long_break_after": "Lange Pause nach",
    "app_bell_focus_time_once": "Konzent.-Phase",
    "app_bell_focus_time_for_focus": "Konzentration",
    "app_bell_focus_time_many": "Konzent.-Phase",
    "app_bell_focus_summary": "<text>Super! <token>$VALUE</token> Konzentration<br></br>beendet.</text>",
    "app_bell_focus_time_once": "Konzent.-Phase",
    "app_bell_focus_well_done": "Super!",
    "app_bell_goodbye": "Auf Wiedersehen",
    "app_bell_greeting_msg": [
        "Guten Morgen! Stehen Sie auf"

M image/system_a/data/lang/English.json => image/system_a/data/lang/English.json +9 -8
@@ 29,19 29,20 @@
    "app_bell_bedtime_notification": "It is your bedtime",
    "app_bell_charging_done_notification": "Fully charged",
    "app_bell_charging_notification": "Charging",
    "app_bell_focus_long_break": "Long break",
    "app_bell_focus_long_break_after": "Long break after",
    "app_bell_focus_notification_volume": "Notification volume",
    "app_bell_focus_repeats": "Focus timer repeats",
    "app_bell_focus_settings": "Settings",
    "app_bell_focus_short_break": "Short break",
    "app_bell_focus_start": "Focus now",
    "app_bell_focus_summary": "<text>Well done!  <token>$VALUE</token> focus<br></br>complete.</text>",
    "app_bell_focus_time": "Focus timer",
    "app_bell_focus_repeats": "Focus timer repeats",
    "app_bell_focus_short_break": "Short break",
    "app_bell_focus_long_break": "Long break",
    "app_bell_focus_time_for_focus": "Time to focus",
    "app_bell_focus_time_for_break": "Time for a break",
    "app_bell_focus_well_done": "Well done!",
    "app_bell_focus_long_break_after": "Long break after",
    "app_bell_focus_time_once": "focus time",
    "app_bell_focus_time_for_focus": "Time to focus",
    "app_bell_focus_time_many": "focus times",
    "app_bell_focus_summary": "<text>Well done!  <token>$VALUE</token> focus<br></br>complete.</text>",
    "app_bell_focus_time_once": "focus time",
    "app_bell_focus_well_done": "Well done!",
    "app_bell_goodbye": "Goodbye",
    "app_bell_greeting_msg": [
        "<text>Good Morning!<br />It's a Beautiful Day!</text>",

M image/system_a/data/lang/Espanol.json => image/system_a/data/lang/Espanol.json +9 -8
@@ 27,19 27,20 @@
    "app_bell_bedtime_notification": "Es tu hora de dormir",
    "app_bell_charging_done_notification": "Completamente cargado",
    "app_bell_charging_notification": "Cargando",
    "app_bell_focus_long_break": "Pausa larga",
    "app_bell_focus_long_break_after": "Pausa larga tras",
    "app_bell_focus_notification_volume": "<text>Notificaci\u00f3n<br/>de volumen</text>",
    "app_bell_focus_repeats": "Concentraci\u00f3n repite",
    "app_bell_focus_settings": "Ajustes",
    "app_bell_focus_short_break": "Pausa breve",
    "app_bell_focus_start": "Conc\u00e9ntrate",
    "app_bell_focus_summary": "<text>\u00a1Genial! Te has concentrado<br></br><token>$VALUE</token></text>",
    "app_bell_focus_time": "Tempo focus",
    "app_bell_focus_repeats": "Concentraci\u00f3n repite",
    "app_bell_focus_short_break": "Pausa breve",
    "app_bell_focus_long_break": "Pausa larga",
    "app_bell_focus_time_for_focus": "\u00a1A concentrarse!",
    "app_bell_focus_time_for_break": "\u00a1Toca descansar!",
    "app_bell_focus_well_done": "\u00a1Genial!",
    "app_bell_focus_long_break_after": "Pausa larga tras",
    "app_bell_focus_time_once": "concentraci\u00f3n",
    "app_bell_focus_time_for_focus": "\u00a1A concentrarse!",
    "app_bell_focus_time_many": "concentraciones",
    "app_bell_focus_summary": "<text>\u00a1Genial! Te has concentrado<br></br><token>$VALUE</token></text>",
    "app_bell_focus_time_once": "concentraci\u00f3n",
    "app_bell_focus_well_done": "\u00a1Genial!",
    "app_bell_goodbye": "Adi\u00f3s",
    "app_bell_greeting_msg": [
        "\u00a1Hola! Lev\u00e1ntate y brilla"

M image/system_a/data/lang/Francais.json => image/system_a/data/lang/Francais.json +9 -8
@@ 29,19 29,20 @@
    "app_bell_bedtime_notification": "C'est l'heure du coucher",
    "app_bell_charging_done_notification": "Compl\u00e8tement charg\u00e9",
    "app_bell_charging_notification": "En charge",
    "app_bell_focus_long_break": "Longue pause",
    "app_bell_focus_long_break_after": "Longue pause apr\u00e8s",
    "app_bell_focus_notification_volume": "Notification de volume",
    "app_bell_focus_repeats": "Minuteur en boucle",
    "app_bell_focus_settings": "Param\u00e8tres",
    "app_bell_focus_short_break": "Petite pause",
    "app_bell_focus_start": "Concentration",
    "app_bell_focus_summary": "<text>Super ! <token>$VALUE</token> de<br></br>concentration \u00e9coul\u00e9es.</text>",
    "app_bell_focus_time": "Minuteur concen.",
    "app_bell_focus_repeats": "Minuteur en boucle",
    "app_bell_focus_short_break": "Petite pause",
    "app_bell_focus_long_break": "Longue pause",
    "app_bell_focus_time_for_focus": "H de la concen.",
    "app_bell_focus_time_for_break": "H de la pause",
    "app_bell_focus_well_done": "Bien jou\u00e9 !",
    "app_bell_focus_long_break_after": "Longue pause apr\u00e8s",
    "app_bell_focus_time_once": "temps de concen.",
    "app_bell_focus_time_for_focus": "H de la concen.",
    "app_bell_focus_time_many": "temps de concen.",
    "app_bell_focus_summary": "<text>Super ! <token>$VALUE</token> de<br></br>concentration \u00e9coul\u00e9es.</text>",
    "app_bell_focus_time_once": "temps de concen.",
    "app_bell_focus_well_done": "Bien jou\u00e9 !",
    "app_bell_goodbye": "Au revoir",
    "app_bell_greeting_msg": [
        "Re-bonjour!"

M image/system_a/data/lang/Polski.json => image/system_a/data/lang/Polski.json +9 -8
@@ 28,19 28,20 @@
    "app_bell_bedtime_notification": "Pora na sen",
    "app_bell_charging_done_notification": "W pe\u0142ni na\u0142adowany",
    "app_bell_charging_notification": "\u0141adowanie",
    "app_bell_focus_long_break": "D\u0142uga przerwa",
    "app_bell_focus_long_break_after": "D\u0142uga przerwa po",
    "app_bell_focus_notification_volume": "G\u0142o\u015bno\u015b\u0107 powiadomie\u0144",
    "app_bell_focus_repeats": "Powtarzanie skupienia",
    "app_bell_focus_settings": "Ustawienia",
    "app_bell_focus_short_break": "Kr\u00f3tka przerwa",
    "app_bell_focus_start": "Skup si\u0119",
    "app_bell_focus_summary": "<text>\u015awietnie! <token>$VALUE</token> skupienia<br></br> za Tob\u0105.</text>",
    "app_bell_focus_time": "Czas skupienia",
    "app_bell_focus_repeats": "Powtarzanie skupienia",
    "app_bell_focus_short_break": "Kr\u00f3tka przerwa",
    "app_bell_focus_long_break": "D\u0142uga przerwa",
    "app_bell_focus_time_for_focus": "Czas si\u0119 skupi\u0107",
    "app_bell_focus_time_for_break": "Czas na przerw\u0119",
    "app_bell_focus_well_done": "Dobra robota!",
    "app_bell_focus_long_break_after": "D\u0142uga przerwa po",
    "app_bell_focus_time_once": "czasie skupienia",
    "app_bell_focus_time_for_focus": "Czas si\u0119 skupi\u0107",
    "app_bell_focus_time_many": "czasach skupienia",
    "app_bell_focus_summary": "<text>\u015awietnie! <token>$VALUE</token> skupienia<br></br> za Tob\u0105.</text>",
    "app_bell_focus_time_once": "czasie skupienia",
    "app_bell_focus_well_done": "Dobra robota!",
    "app_bell_goodbye": "Do widzenia",
    "app_bell_greeting_msg": [
        "<text>Dzie\u0144 dobry!<br />Pobudka</text>"

M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +1 -0
@@ 64,6 64,7 @@ namespace audio
        Alarm,
        PreWakeUp,
        Snooze,
        FocusTimer,
        Bedtime,
        Last = Bedtime,
    };

M module-audio/Audio/AudioMux.cpp => module-audio/Audio/AudioMux.cpp +1 -0
@@ 174,6 174,7 @@ namespace audio
        case PlaybackType::Bedtime:
        case PlaybackType::PreWakeUp:
        case PlaybackType::Snooze:
        case PlaybackType::FocusTimer:
            return false;
        }
        return false;

M products/BellHybrid/apps/application-bell-focus-timer/ApplicationFocusTimer.cpp => products/BellHybrid/apps/application-bell-focus-timer/ApplicationFocusTimer.cpp +5 -1
@@ 13,6 13,7 @@
#include "presenter/FocusTimerPresenter.hpp"

#include "models/FocusSettingsModel.hpp"
#include "models/NotificationVolumeModel.hpp"
#include "common/models/TimeModel.hpp"
#include <common/models/AudioModel.hpp>
#include <common/windows/SessionPausedWindow.hpp>


@@ 57,6 58,7 @@ namespace app
            std::make_unique<focus::models::FocusSettingsModel>(this,
                                                                focus::models::settings::longBreakOccurrenceName,
                                                                focus::models::settings::longBreakOccurrenceDefault);
        notificationVolumeModel = std::make_unique<focus::models::NotificationVolumeModel>(*audioModel);

        batteryModel                 = std::make_unique<app::BatteryModel>(this);
        lowBatteryInfoModel          = std::make_unique<app::LowBatteryInfoModel>();


@@ 82,7 84,9 @@ namespace app
                                                                             *focusRepeatsModel,
                                                                             *shortBreakTimeModel,
                                                                             *longBreakTimeModel,
                                                                             *longBreakOccurrenceModel);
                                                                             *longBreakOccurrenceModel,
                                                                             *notificationVolumeModel,
                                                                             *audioModel);
            return std::make_unique<focus::SettingsWindow>(app, std::move(presenter));
        });


M products/BellHybrid/apps/application-bell-focus-timer/CMakeLists.txt => products/BellHybrid/apps/application-bell-focus-timer/CMakeLists.txt +1 -0
@@ 31,6 31,7 @@ target_sources(application-bell-focus-timer
        presenter/FocusTimerPresenter.cpp

        models/FocusSettingsModel.cpp
        models/NotificationVolumeModel.cpp

    PUBLIC
        include/application-bell-focus-timer/ApplicationFocusTimer.hpp

M products/BellHybrid/apps/application-bell-focus-timer/data/FocusCommon.hpp => products/BellHybrid/apps/application-bell-focus-timer/data/FocusCommon.hpp +1 -1
@@ 18,7 18,7 @@ namespace app::focus
        inline constexpr auto focusTimerLowBattery = "FocusTimerLowBatteryWindow";
    } // namespace window::name

    inline std::filesystem::path getFocusTimeAudioPath()
    inline std::filesystem::path getFocusTimerAudioPath()
    {
        return paths::audio::proprietary() / paths::audio::focusTimer() / "FocusTimer_Gong.mp3";
    }

M products/BellHybrid/apps/application-bell-focus-timer/include/application-bell-focus-timer/ApplicationFocusTimer.hpp => products/BellHybrid/apps/application-bell-focus-timer/include/application-bell-focus-timer/ApplicationFocusTimer.hpp +2 -0
@@ 11,6 11,7 @@
namespace app::focus::models
{
    class FocusSettingsModel;
    class NotificationVolumeModel;
} // namespace app::focus::models

namespace app


@@ 46,6 47,7 @@ namespace app
        std::unique_ptr<focus::models::FocusSettingsModel> shortBreakTimeModel;
        std::unique_ptr<focus::models::FocusSettingsModel> longBreakTimeModel;
        std::unique_ptr<focus::models::FocusSettingsModel> longBreakOccurrenceModel;
        std::unique_ptr<focus::models::NotificationVolumeModel> notificationVolumeModel;

        std::unique_ptr<AbstractAudioModel> audioModel;
        std::unique_ptr<AbstractBatteryModel> batteryModel;

A products/BellHybrid/apps/application-bell-focus-timer/models/NotificationVolumeModel.cpp => products/BellHybrid/apps/application-bell-focus-timer/models/NotificationVolumeModel.cpp +27 -0
@@ 0,0 1,27 @@
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NotificationVolumeModel.hpp"

namespace app::focus::models
{
    NotificationVolumeModel::NotificationVolumeModel(AbstractAudioModel &audioModel) : audioModel{audioModel}
    {
        defaultValue = audioModel.getVolume(AbstractAudioModel::PlaybackType::FocusTimer).value_or(0);
    }

    void NotificationVolumeModel::setValue(std::uint8_t value)
    {
        audioModel.setVolume(value, AbstractAudioModel::PlaybackType::FocusTimer);
    }

    std::uint8_t NotificationVolumeModel::getValue() const
    {
        return audioModel.getVolume(AbstractAudioModel::PlaybackType::FocusTimer).value_or(0);
    }

    void NotificationVolumeModel::restoreDefault()
    {
        setValue(defaultValue);
    }
} // namespace app::focus::models

A products/BellHybrid/apps/application-bell-focus-timer/models/NotificationVolumeModel.hpp => products/BellHybrid/apps/application-bell-focus-timer/models/NotificationVolumeModel.hpp +24 -0
@@ 0,0 1,24 @@
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <common/models/SettingsModel.hpp>
#include <common/models/AudioModel.hpp>

namespace app::focus::models
{
    class NotificationVolumeModel : public gui::AbstractSettingsModel<std::uint8_t>
    {
      public:
        explicit NotificationVolumeModel(AbstractAudioModel &audioModel);

        void setValue(std::uint8_t value) override;
        std::uint8_t getValue() const override;
        void restoreDefault() override;

      private:
        AbstractAudioModel &audioModel;
        std::uint8_t defaultValue;
    };
} // namespace app::focus::models

M products/BellHybrid/apps/application-bell-focus-timer/presenter/FocusSettingsPresenter.cpp => products/BellHybrid/apps/application-bell-focus-timer/presenter/FocusSettingsPresenter.cpp +74 -8
@@ 5,15 5,28 @@
#include "data/FocusCommon.hpp"

#include "models/FocusSettingsModel.hpp"
#include "models/NotificationVolumeModel.hpp"

#include <ApplicationCommon.hpp>
#include <apps-common/InternalModel.hpp>
#include <common/widgets/list_items/Numeric.hpp>
#include <common/widgets/list_items/NumericWithBar.hpp>
#include <common/widgets/list_items/MinutesWithOff.hpp>
#include <common/widgets/list_items/Multiplicity.hpp>
#include <gui/widgets/ListViewEngine.hpp>

namespace
{
    enum class ListIndex
    {
        FocusTime = 0,
        FocusRepeats,
        ShortBreakTime,
        LongBreakTime,
        LongBreakOccurrence,
        NotificationVolume
    };

    class FocusTimeMultiplicity : public app::list_items::Numeric
    {
      public:


@@ 45,10 58,13 @@ namespace app::focus
                                         models::FocusSettingsModel &focusRepeatsModel,
                                         models::FocusSettingsModel &shortBreakTimeModel,
                                         models::FocusSettingsModel &longBreakTimeModel,
                                         models::FocusSettingsModel &longBreakOccurrenceModel)
                                         models::FocusSettingsModel &longBreakOccurrenceModel,
                                         models::NotificationVolumeModel &notificationVolumeModel,
                                         AbstractAudioModel &audioModel)
        : focusTimeModel{focusTimeModel}, focusRepeatsModel{focusRepeatsModel},
          shortBreakTimeModel{shortBreakTimeModel}, longBreakTimeModel{longBreakTimeModel},
          longBreakOccurrenceModel{longBreakOccurrenceModel}
          longBreakOccurrenceModel{longBreakOccurrenceModel}, notificationVolumeModel{notificationVolumeModel},
          audioModel{audioModel}
    {
        auto focusTime = new list_items::Numeric{
            list_items::Numeric::spinner_type::range{


@@ 89,8 105,15 @@ namespace app::focus
            utils::translate("app_bell_focus_long_break_after"),
            utils::translate("app_bell_focus_time_many")};

        listItemsProvider = std::make_shared<BellListItemProvider>(
            BellListItemProvider::Items{focusTime, focusRepeats, shortBreakTime, longBreakTime, longBreakOccurrence});
        auto notificationVolume =
            new list_items::NumericWithBar{list_items::NumericWithBar::spinner_type::range{
                                               AbstractAudioModel::minVolume, AbstractAudioModel::maxVolume, 1},
                                           notificationVolumeModel,
                                           AbstractAudioModel::maxVolume,
                                           utils::translate("app_bell_focus_notification_volume")};

        listItemsProvider = std::make_shared<BellListItemProvider>(BellListItemProvider::Items{
            focusTime, focusRepeats, shortBreakTime, longBreakTime, longBreakOccurrence, notificationVolume});

        focusRepeats->onExit = [this, focusRepeats, longBreakOccurrence]() {
            const auto currentValue = longBreakOccurrence->value();


@@ 101,18 124,54 @@ namespace app::focus
            longBreakOccurrence->set_value(std::min(currentValue, maxValue));
        };

        shortBreakTime->onEnter = [this, focusRepeats]() {
        focusRepeats->onProceed = [focusRepeats, this]() {
            if (focusRepeats->value() == 1) {
                // when the user sets only one focus session, the break settings does not matter because we do not
                // display any break after the last focus session
                getView()->exit();
                listItemsProvider->list->rebuildList(gui::listview::RebuildType::OnOffset,
                                                     static_cast<unsigned int>(ListIndex::NotificationVolume));
                return true;
            }
            return false;
        };

        longBreakOccurrence->onEnter = [this, longBreakTime]() {
        longBreakTime->onProceed = [longBreakTime, this]() {
            if (longBreakTime->value() == 0) {
                getView()->exit();
                listItemsProvider->list->rebuildList(gui::listview::RebuildType::OnOffset,
                                                     static_cast<unsigned int>(ListIndex::NotificationVolume));
                return true;
            }
            return false;
        };

        auto playSound = [this, notificationVolume]() {
            this->audioModel.setVolume(notificationVolume->value(), AbstractAudioModel::PlaybackType::FocusTimer);
            this->audioModel.play(getFocusTimerAudioPath(), AbstractAudioModel::PlaybackType::FocusTimer, {});
        };

        notificationVolume->onEnter = playSound;
        notificationVolume->onExit  = [this]() { stopSound(); };

        notificationVolume->set_on_value_change_cb([this, playSound](const auto &val) {
            this->audioModel.setVolume(
                val, AbstractAudioModel::PlaybackType::FocusTimer, audio::VolumeUpdateType::SkipUpdateDB);
            if (this->audioModel.hasPlaybackFinished()) {
                playSound();
            }
        });

        notificationVolume->onReturn = [this, focusRepeats, longBreakTime]() {
            if (focusRepeats->value() == 1) {
                listItemsProvider->list->rebuildList(gui::listview::RebuildType::OnOffset,
                                                     static_cast<unsigned int>(ListIndex::FocusRepeats));
                return true;
            }
            else if (longBreakTime->value() == 0) {
                listItemsProvider->list->rebuildList(gui::listview::RebuildType::OnOffset,
                                                     static_cast<unsigned int>(ListIndex::LongBreakTime));
                return true;
            }
            return false;
        };

        for (auto &item : listItemsProvider->getListItems()) {


@@ 152,6 211,13 @@ namespace app::focus

    void SettingsPresenter::exitWithoutSave()
    {
        stopSound();
        notificationVolumeModel.restoreDefault();
        eraseProviderData();
    }

    void SettingsPresenter::stopSound()
    {
        audioModel.stopPlayedByThis({});
    }
} // namespace app::focus

M products/BellHybrid/apps/application-bell-focus-timer/presenter/FocusSettingsPresenter.hpp => products/BellHybrid/apps/application-bell-focus-timer/presenter/FocusSettingsPresenter.hpp +9 -1
@@ 5,6 5,7 @@

#include <apps-common/BasePresenter.hpp>
#include <common/BellListItemProvider.hpp>
#include <common/models/AbstractAudioModel.hpp>
#include <memory>

namespace app


@@ 17,6 18,7 @@ namespace app::focus
    namespace models
    {
        class FocusSettingsModel;
        class NotificationVolumeModel;
    } // namespace models

    class SettingsContract


@@ 49,7 51,9 @@ namespace app::focus
                          models::FocusSettingsModel &focusRepeatsModel,
                          models::FocusSettingsModel &shortBreakTimeModel,
                          models::FocusSettingsModel &longBreakTimeModel,
                          models::FocusSettingsModel &longBreakOccurrenceModel);
                          models::FocusSettingsModel &longBreakOccurrenceModel,
                          models::NotificationVolumeModel &notificationVolumeModel,
                          AbstractAudioModel &audioModel);

        void loadData() override;
        void saveData() override;


@@ 59,11 63,15 @@ namespace app::focus
        void exitWithoutSave() override;

      private:
        void stopSound();

        models::FocusSettingsModel &focusTimeModel;
        models::FocusSettingsModel &focusRepeatsModel;
        models::FocusSettingsModel &shortBreakTimeModel;
        models::FocusSettingsModel &longBreakTimeModel;
        models::FocusSettingsModel &longBreakOccurrenceModel;
        models::NotificationVolumeModel &notificationVolumeModel;
        AbstractAudioModel &audioModel;
        std::shared_ptr<BellListItemProvider> listItemsProvider;
    };
} // namespace app::focus

M products/BellHybrid/apps/application-bell-focus-timer/presenter/FocusTimerPresenter.cpp => products/BellHybrid/apps/application-bell-focus-timer/presenter/FocusTimerPresenter.cpp +2 -2
@@ 179,8 179,8 @@ namespace app::focus

    void FocusTimerPresenter::playGong()
    {
        auto msg = std::make_shared<service::AudioStartPlaybackRequest>(app::focus::getFocusTimeAudioPath(),
                                                                        audio::PlaybackType::Meditation);
        auto msg = std::make_shared<service::AudioStartPlaybackRequest>(app::focus::getFocusTimerAudioPath(),
                                                                        audio::PlaybackType::FocusTimer);
        app->bus.sendUnicast(std::move(msg), service::audioServiceName);
    }


M products/BellHybrid/apps/common/include/common/models/AbstractAudioModel.hpp => products/BellHybrid/apps/common/include/common/models/AbstractAudioModel.hpp +2 -1
@@ 21,7 21,8 @@ namespace app
            Alarm,
            PreWakeup,
            Bedtime,
            Meditation
            Meditation,
            FocusTimer
        };

        enum class PlaybackFinishStatus

M products/BellHybrid/apps/common/src/AudioModel.cpp => products/BellHybrid/apps/common/src/AudioModel.cpp +2 -0
@@ 24,6 24,8 @@ namespace
            return audio::PlaybackType::Bedtime;
        case Type::Meditation:
            return audio::PlaybackType::Meditation;
        case Type::FocusTimer:
            return audio::PlaybackType::FocusTimer;
        default:
            return audio::PlaybackType::Alarm;
        }

M products/BellHybrid/services/audio/ServiceAudio.cpp => products/BellHybrid/services/audio/ServiceAudio.cpp +3 -0
@@ 32,6 32,7 @@ namespace
            {DbPathElement{Setting::Volume, PlaybackType::Bedtime, Profile::Type::PlaybackLoudspeaker}, defaultBedtimeVolume},
            {DbPathElement{Setting::Volume, PlaybackType::PreWakeUp, Profile::Type::PlaybackLoudspeaker}, defaultSnoozeVolume},
            {DbPathElement{Setting::Volume, PlaybackType::Snooze, Profile::Type::PlaybackLoudspeaker}, defaultSnoozeVolume},
            {DbPathElement{Setting::Volume, PlaybackType::FocusTimer, Profile::Type::PlaybackLoudspeaker}, defaultVolume},

            /// Profiles below are not used but unfortunately, must exist in order to satisfy audio module requirements
            {DbPathElement{Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackHeadphones}, defaultVolume},


@@ 46,6 47,8 @@ namespace
            {DbPathElement{Setting::Volume, PlaybackType::PreWakeUp, Profile::Type::PlaybackBluetoothA2DP},defaultVolume},
            {DbPathElement{Setting::Volume, PlaybackType::Snooze, Profile::Type::PlaybackHeadphones}, defaultVolume},
            {DbPathElement{Setting::Volume, PlaybackType::Snooze, Profile::Type::PlaybackBluetoothA2DP}, defaultVolume},
            {DbPathElement{Setting::Volume, PlaybackType::FocusTimer, Profile::Type::PlaybackHeadphones}, defaultVolume},
            {DbPathElement{Setting::Volume, PlaybackType::FocusTimer, Profile::Type::PlaybackBluetoothA2DP}, defaultVolume},
        };
        // clang-format on
    } // namespace initializer