M board/rt1051/crashdump/crashcatcher_impl.cpp => board/rt1051/crashdump/crashcatcher_impl.cpp +15 -15
@@ 7,24 7,25 @@
#include <log/log.hpp>
#include <date/date.h>
-#include "crashdumpwriter.hpp"
+#include "crashdumpwriter_vfs.hpp"
#include "consoledump.hpp"
+namespace
+{
+ crashdump::CrashDumpWriterVFS cwrite;
+}
+
const CrashCatcherMemoryRegion *CrashCatcher_GetMemoryRegions(void)
{
- // board/rt1051/ldscripts/memory.ld
+ /* board/rt1051/ldscripts/memory.ld
+ * NOTE: Text section and stacks sections are intentionally ommited
+ * because can cause throubles in the running system
+ */
static const CrashCatcherMemoryRegion regions[] = {
// SRAM_OC
{0x20200000, 0x20210000, CRASH_CATCHER_BYTE},
// SRAM_DTC
{0x20000000, 0x20070000, CRASH_CATCHER_BYTE},
- // intentionally skip text section
- // BOARD_SDRAM_HEAP
-#if defined(HW_SDRAM_64_MB) && (HW_SDRAM_64_MB == 1)
- {0x80620000, 0x84000000, CRASH_CATCHER_BYTE},
-#else
- {0x80620000, 0x81000000, CRASH_CATCHER_BYTE},
-#endif
// end tag
{0xFFFFFFFF, 0xFFFFFFFF, CRASH_CATCHER_BYTE},
};
@@ 35,28 36,27 @@ const CrashCatcherMemoryRegion *CrashCatcher_GetMemoryRegions(void)
void CrashCatcher_DumpStart(const CrashCatcherInfo *pInfo)
{
crashdump::printCrashInfo(pInfo);
- crashdump::CrashDumpWriter::instance().openDump();
+ cwrite.openDump();
}
void CrashCatcher_DumpMemory(const void *pvMemory, CrashCatcherElementSizes elementSize, size_t elementCount)
{
switch (elementSize) {
case CRASH_CATCHER_BYTE:
- crashdump::CrashDumpWriter::instance().writeBytes(static_cast<const std::uint8_t *>(pvMemory), elementCount);
+ cwrite.writeBytes(static_cast<const std::uint8_t *>(pvMemory), elementCount);
break;
case CRASH_CATCHER_HALFWORD:
- crashdump::CrashDumpWriter::instance().writeHalfWords(static_cast<const std::uint16_t *>(pvMemory),
- elementCount);
+ cwrite.writeHalfWords(static_cast<const std::uint16_t *>(pvMemory), elementCount);
break;
case CRASH_CATCHER_WORD:
- crashdump::CrashDumpWriter::instance().writeWords(static_cast<const std::uint32_t *>(pvMemory), elementCount);
+ cwrite.writeWords(static_cast<const std::uint32_t *>(pvMemory), elementCount);
break;
}
}
CrashCatcherReturnCodes CrashCatcher_DumpEnd(void)
{
- crashdump::CrashDumpWriter::instance().saveDump();
+ cwrite.saveDump();
abort();
return CRASH_CATCHER_EXIT;
}
D board/rt1051/crashdump/crashdumpwriter.hpp => board/rt1051/crashdump/crashdumpwriter.hpp +0 -25
@@ 1,25 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 <cstdint>
-
-namespace crashdump
-{
- class CrashDumpWriter
- {
- public:
- static CrashDumpWriter &instance();
-
- virtual ~CrashDumpWriter() = default;
-
- virtual void openDump() = 0;
- virtual void saveDump() = 0;
-
- virtual void writeBytes(const std::uint8_t *buff, std::size_t size) = 0;
- virtual void writeHalfWords(const std::uint16_t *buff, std::size_t size) = 0;
- virtual void writeWords(const std::uint32_t *buff, std::size_t size) = 0;
- };
-
-} // namespace crashdump
M board/rt1051/crashdump/crashdumpwriter_vfs.cpp => board/rt1051/crashdump/crashdumpwriter_vfs.cpp +24 -19
@@ 3,12 3,15 @@
#include "crashdumpwriter_vfs.hpp"
+#include <cstdio>
#include <log/log.hpp>
#include <fcntl.h>
#include "purefs/vfs_subsystem.hpp"
#include <purefs/filesystem_paths.hpp>
#include <filesystem>
+#include <stdint.h>
+#include <unistd.h>
namespace crashdump
{
@@ 16,47 19,49 @@ namespace crashdump
void CrashDumpWriterVFS::openDump()
{
- vfs = purefs::subsystem::vfs_core();
const auto crashDumpFilePath = purefs::dir::getCrashDumpsPath() / crashDumpFileName;
-
+ LOG_INFO("Crash dump %s preparing ...", crashDumpFilePath.c_str());
if (!rotator.rotateFile(crashDumpFilePath)) {
- LOG_FATAL("Failed to rotate crash dumps.");
+ LOG_FATAL("Failed to rotate crash dumps errno: %i", errno);
+ std::abort();
}
- dumpFd = vfs->open(crashDumpFilePath.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
-
- if (dumpFd < 0) {
- LOG_FATAL("Failed to open crash dump file. Won't be able to save crash info.");
+ file = std::fopen(crashDumpFilePath.c_str(), "w");
+ if (!file) {
+ LOG_FATAL("Failed to open crash dump file errno %i", errno);
+ std::abort();
}
}
void CrashDumpWriterVFS::saveDump()
{
- vfs->close(dumpFd);
+ LOG_INFO("Crash dump create finished.");
+ fflush(file);
+ fsync(fileno(file));
+ std::fclose(file);
}
void CrashDumpWriterVFS::writeBytes(const uint8_t *buff, std::size_t size)
{
- vfs->write(dumpFd, reinterpret_cast<const char *>(buff), size);
+ if (std::fwrite(buff, sizeof(*buff), size, file) != size) {
+ LOG_FATAL("Unable to write crash dump errno: %i", errno);
+ std::abort();
+ }
}
void CrashDumpWriterVFS::writeHalfWords(const uint16_t *buff, std::size_t size)
{
- for (std::size_t n = 0; n < size; ++n) {
- writeBytes(reinterpret_cast<const uint8_t *>(buff + n), sizeof(uint16_t));
+ if (std::fwrite(buff, sizeof(*buff), size, file) != size) {
+ LOG_FATAL("Unable to write crash dump");
+ std::abort();
}
}
void CrashDumpWriterVFS::writeWords(const uint32_t *buff, std::size_t size)
{
- for (std::size_t n = 0; n < size; ++n) {
- writeBytes(reinterpret_cast<const uint8_t *>(buff + n), sizeof(uint32_t));
+ if (std::fwrite(buff, sizeof(*buff), size, file) != size) {
+ LOG_FATAL("Unable to write crash dump");
+ std::abort();
}
}
- CrashDumpWriter &CrashDumpWriter::instance()
- {
- static CrashDumpWriterVFS writer;
- return writer;
- }
-
} // namespace crashdump
M board/rt1051/crashdump/crashdumpwriter_vfs.hpp => board/rt1051/crashdump/crashdumpwriter_vfs.hpp +8 -10
@@ 3,12 3,12 @@
#pragma once
-#include "crashdumpwriter.hpp"
#include <rotator/Rotator.hpp>
#include <array>
#include <ctime>
#include <memory>
+#include <cstdio>
namespace purefs::fs
{
@@ 18,23 18,21 @@ namespace purefs::fs
namespace crashdump
{
constexpr inline auto maxRotationFilesCount = 5;
- class CrashDumpWriterVFS : public CrashDumpWriter
+ class CrashDumpWriterVFS
{
public:
CrashDumpWriterVFS() : rotator{".hex"}
{}
- void openDump() override;
- void saveDump() override;
+ void openDump();
+ void saveDump();
- void writeBytes(const std::uint8_t *buff, std::size_t size) override;
- void writeHalfWords(const std::uint16_t *buff, std::size_t size) override;
- void writeWords(const std::uint32_t *buff, std::size_t size) override;
+ void writeBytes(const std::uint8_t *buff, std::size_t size);
+ void writeHalfWords(const std::uint16_t *buff, std::size_t size);
+ void writeWords(const std::uint32_t *buff, std::size_t size);
private:
utils::Rotator<maxRotationFilesCount> rotator;
- int dumpFd{-1};
-
- std::shared_ptr<purefs::fs::filesystem> vfs;
+ std::FILE *file{};
};
} // namespace crashdump
M image/user/db/settings_bell_002.sql => image/user/db/settings_bell_002.sql +0 -4
@@ 35,20 35,16 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
('snooze_length','10'),
('snooze_interval','1'),
('snooze_tone','Gentle Chime'),
- ('snooze_volume','5'),
('prewake_up_duration', '10'),
('prewake_up_tone','Joyful Awakening'),
- ('prewake_up_volume','5'),
('prewake_up_light_duration','10'),
('alarm_tone','Gentle Daybreak'),
- ('alarm_volume','5'),
('alarm_light_active','1'),
('alarm_duration','10000'),
('bedtime_active','0'),
('bedtime_time','21:00'),
('bedtime_tone','Evening Horizon'),
('bedtime_duration','5'),
- ('bedtime_volume','1'),
('\ServiceEink\\display_inverted_mode', '0');
M module-apps/apps-common/widgets/ProgressTimer.cpp => module-apps/apps-common/widgets/ProgressTimer.cpp +1 -1
@@ 54,6 54,7 @@ namespace app
auto ProgressTimer::onTimerTimeout(sys::Timer &task) -> bool
{
+ ++elapsed;
if (isStopped() || isFinished()) {
task.stop();
if (isFinished() && onFinishedCallback != nullptr) {
@@ 62,7 63,6 @@ namespace app
return true;
}
- ++elapsed;
if ((intervalReached() || isFinished()) && onIntervalCallback != nullptr) {
onIntervalCallback();
}
M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +5 -2
@@ 66,7 66,10 @@ namespace audio
TextMessageRingtone,
Meditation,
Alarm,
- Last = Alarm,
+ PreWakeUp,
+ Snooze,
+ Bedtime,
+ Last = Bedtime,
};
/// Used to describe audio operations
@@ 174,7 177,7 @@ namespace audio
std::bitset<magic_enum::enum_count<EventType>()> audioSinkState;
};
- enum class RetCode
+ enum class RetCode : std::uint8_t
{
Success = 0,
InvokedInIncorrectState,
M module-audio/Audio/AudioMux.cpp => module-audio/Audio/AudioMux.cpp +3 -6
@@ 163,20 163,17 @@ namespace audio
{
switch (type) {
case PlaybackType::None:
- [[fallthrough]];
case PlaybackType::Notifications:
- [[fallthrough]];
case PlaybackType::KeypadSound:
- [[fallthrough]];
case PlaybackType::TextMessageRingtone:
return true;
case PlaybackType::CallRingtone:
- [[fallthrough]];
case PlaybackType::Meditation:
- [[fallthrough]];
case PlaybackType::Alarm:
- [[fallthrough]];
case PlaybackType::Multimedia:
+ case PlaybackType::Bedtime:
+ case PlaybackType::PreWakeUp:
+ case PlaybackType::Snooze:
return false;
}
return false;
M module-audio/board/rt1051/bellpx/BellPxAudioCodec.cpp => module-audio/board/rt1051/bellpx/BellPxAudioCodec.cpp +2 -3
@@ 3,7 3,6 @@
#include "BellPxAudioCodec.hpp"
#include "board.h"
-#include "dma_config.h"
#include <log/log.hpp>
#include "board/BoardDefinitions.hpp"
@@ 104,7 103,7 @@ namespace audio
AudioDevice::RetCode BellPxAudioCodec::setOutputVolume(float vol)
{
currentFormat.outputVolume = vol;
- CodecParams params;
+ CodecParamsAW8898 params;
params.outVolume = vol;
params.opCmd = CodecParams::Cmd::SetOutVolume;
codec.Ioctrl(params);
@@ 114,7 113,7 @@ namespace audio
AudioDevice::RetCode BellPxAudioCodec::setInputGain(float gain)
{
currentFormat.inputGain = gain;
- CodecParams params;
+ CodecParamsAW8898 params;
params.inGain = gain;
params.opCmd = CodecParams::Cmd::SetInGain;
codec.Ioctrl(params);
M module-bsp/board/rt1051/bellpx/bsp/audio/AW8898driver.cpp => module-bsp/board/rt1051/bellpx/bsp/audio/AW8898driver.cpp +2 -2
@@ 469,7 469,7 @@ namespace bsp::audio::AW8898
return res;
}
- status_t GetVolume(std::uint8_t *gian)
+ status_t GetVolume(std::uint8_t *gain)
{
status_t res = kStatus_Success;
std::uint16_t reg = 0;
@@ 480,7 480,7 @@ namespace bsp::audio::AW8898
return res;
}
- *gian = reg >> 8;
+ *gain = reg >> 8;
return res;
}
M module-bsp/board/rt1051/bellpx/bsp/audio/CodecAW8898.cpp => module-bsp/board/rt1051/bellpx/bsp/audio/CodecAW8898.cpp +23 -18
@@ 21,10 21,23 @@ using namespace bsp::audio;
namespace
{
- constexpr auto ReadStatusRetries = 5;
- constexpr auto OneByteAddressing = 1;
- constexpr auto PositiveLogic = 0;
- constexpr auto defaultVolumeLevel = 3.0f;
+ constexpr auto ReadStatusRetries = 5;
+ constexpr auto OneByteAddressing = 1;
+ constexpr auto PositiveLogic = 0;
+ constexpr auto maxInVolume = 10;
+ constexpr auto minInVolume = 0;
+
+ /// Higher layers operate using 0-10 range. Here we are transforming it into more usable one.
+ /// Anything above 9 is going to distort the speaker and values below 5 are too quiet.
+ constexpr float transformVolumeLvl(float value)
+ {
+ constexpr auto maxOutVolume = 9;
+ constexpr auto minOutVolume = 5;
+ constexpr auto inputRange = std::make_pair(minInVolume, maxInVolume);
+ constexpr auto outputRange = std::make_pair(minOutVolume, maxOutVolume);
+ constexpr float slope = 1.0 * (outputRange.second - outputRange.first) / (inputRange.second - inputRange.first);
+ return outputRange.first + slope * (value - inputRange.first);
+ }
} // namespace
CodecAW8898::CodecAW8898()
@@ 83,10 96,7 @@ CodecRetCode CodecAW8898::Start(const CodecParams ¶m)
// Store param configuration
currentParams = params;
- auto currVol = currentParams.outVolume;
- // remove this once volume control in application is working
- currVol = defaultVolumeLevel;
- SetOutputVolume(currVol);
+ SetOutputVolume(currentParams.outVolume);
AW8898::ReadAllReg();
@@ 115,10 125,8 @@ CodecRetCode CodecAW8898::Stop()
CodecRetCode CodecAW8898::Ioctrl(const CodecParams ¶m)
{
-
const CodecParamsAW8898 ¶ms = static_cast<const CodecParamsAW8898 &>(param);
-
- CodecRetCode ret = CodecRetCode::Success;
+ CodecRetCode ret = CodecRetCode::Success;
switch (params.opCmd) {
case CodecParamsAW8898::Cmd::SetOutVolume:
@@ 152,14 160,13 @@ CodecRetCode CodecAW8898::Ioctrl(const CodecParams ¶m)
std::uint8_t CodecAW8898::VolumeTo8Bit(const float vol)
{
- static constexpr auto maxVolumeLevel = 10.0f;
- static constexpr auto conversionRatio = static_cast<float>(UINT8_MAX) / maxVolumeLevel;
+ static constexpr auto conversionRatio = static_cast<float>(UINT8_MAX) / maxInVolume;
if (vol < 0) {
return 0;
}
- if (vol > maxVolumeLevel) {
+ if (vol > maxInVolume) {
return UINT8_MAX;
}
@@ 168,12 175,10 @@ std::uint8_t CodecAW8898::VolumeTo8Bit(const float vol)
CodecRetCode CodecAW8898::SetOutputVolume(const float vol)
{
- uint8_t mute = 0;
-
// If volume set to 0 then mute output
AW8898::RunMute(vol == 0); //(PWMCTRL.HMUTE=0) - disable mute
-
- AW8898::SetVolume(VolumeTo8Bit(vol));
+ // AW8898 has "negative" gain control - higher the absolute value, lower the volume
+ AW8898::SetVolume(UINT8_MAX - VolumeTo8Bit(transformVolumeLvl(vol)));
currentParams.outVolume = vol;
return CodecRetCode::Success;
}
M module-bsp/board/rt1051/bellpx/bsp/audio/CodecAW8898.hpp => module-bsp/board/rt1051/bellpx/bsp/audio/CodecAW8898.hpp +0 -26
@@ 17,29 17,6 @@ extern "C"
class CodecParamsAW8898 : public CodecParams
{
public:
- enum class Cmd
- {
- SetOutVolume,
- SetInGain,
- SetMute,
- SetOutput,
- SetInput,
- Reset,
- MicBiasCtrl,
- None
- };
-
- enum class SampleRate
- {
- Rate8KHz = 8000,
- Rate16KHz = 16000,
- Rate44K1Hz = 44100,
- Rate48KHz = 48000,
- Rate32KHz = 32000,
- Rate96KHz = 96000,
- Invalid
- };
-
enum class MonoStereo
{
Left,
@@ 97,10 74,7 @@ class CodecParamsAW8898 : public CodecParams
}
}
- Cmd opCmd = Cmd::None;
- float outVolume = 0;
MonoStereo monoStereo = MonoStereo::Mono;
- SampleRate sampleRate = SampleRate ::Rate44K1Hz;
};
class CodecAW8898 : public Codec
M module-bsp/board/rt1051/bellpx/bsp/switches/switches.cpp => module-bsp/board/rt1051/bellpx/bsp/switches/switches.cpp +24 -15
@@ 67,22 67,22 @@ namespace bsp::bell_switches
private:
static constexpr std::chrono::milliseconds latchPressEventTimeout = 1000ms;
cpp_freertos::MutexStandard latchFlagMutex;
- std::chrono::time_point<std::chrono::system_clock> timeOfLastLatchEvent = std::chrono::system_clock::now();
- bool pressed = false;
+ bool pressed = false;
+ bool changeFlag = false;
public:
void setPressed()
{
cpp_freertos::LockGuard lock(latchFlagMutex);
- pressed = true;
- timeOfLastLatchEvent = std::chrono::system_clock::now();
+ pressed = true;
+ changeFlag = true;
}
void setReleased()
{
cpp_freertos::LockGuard lock(latchFlagMutex);
- pressed = false;
- timeOfLastLatchEvent = std::chrono::system_clock::now();
+ pressed = false;
+ changeFlag = true;
}
bool isPressed()
@@ 91,12 91,16 @@ namespace bsp::bell_switches
return pressed;
}
- bool wasJustPressed()
+ bool wasMarkedChanged()
{
cpp_freertos::LockGuard lock(latchFlagMutex);
- auto ret = ((std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::system_clock::now() - timeOfLastLatchEvent)) <= latchPressEventTimeout);
- return ret;
+ return changeFlag;
+ }
+
+ void clearChangedMark()
+ {
+ cpp_freertos::LockGuard lock(latchFlagMutex);
+ changeFlag = false;
}
} latchEventFlag;
@@ 122,7 126,7 @@ namespace bsp::bell_switches
latchEventFlag.setPressed();
}
auto val = static_cast<std::uint16_t>(timerState->notificationSource);
- xQueueSendFromISR(qHandleIrq, &val, &xHigherPriorityTaskWoken);
+ xQueueSend(qHandleIrq, &val, 0);
timerState->lastState = KeyEvents::Released;
}
else {
@@ 149,7 153,7 @@ namespace bsp::bell_switches
default:
break;
}
- xQueueSendFromISR(qHandleIrq, &val, &xHigherPriorityTaskWoken);
+ xQueueSend(qHandleIrq, &val, 0);
timerState->lastState = KeyEvents::Pressed;
}
}
@@ 163,9 167,14 @@ namespace bsp::bell_switches
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTimerStop(timerState->timer, 0);
- if (!latchEventFlag.wasJustPressed() && qHandleIrq != nullptr) {
- auto val = static_cast<std::uint16_t>(timerState->notificationSource);
- xQueueSendFromISR(qHandleIrq, &val, &xHigherPriorityTaskWoken);
+ if (qHandleIrq != nullptr) {
+ if (latchEventFlag.wasMarkedChanged()) {
+ latchEventFlag.clearChangedMark();
+ }
+ else {
+ auto val = static_cast<std::uint16_t>(timerState->notificationSource);
+ xQueueSend(qHandleIrq, &val, 0);
+ }
}
timerState->gpio->ClearPortInterrupts(1U << static_cast<uint32_t>(timerState->pin));
M module-vfs/drivers/src/purefs/fs/filesystem_ext4.cpp => module-vfs/drivers/src/purefs/fs/filesystem_ext4.cpp +6 -2
@@ 130,8 130,12 @@ namespace purefs::fs::drivers
LOG_ERROR("Unable to append volume err: %i", err);
return err;
}
- // Test only
- ext4_dmask_set(DEBUG_ALL);
+ /** If verbosed lwext4 debug is required please uncomment
+ * this line. It may cause to print a lot of messages
+ * especially when the ext4 journal is recovered
+ * on the log output device so it is disabled by default
+ */
+ // ext4_dmask_set(DEBUG_ALL);
err = ext4_device_register(bd, disk->name().c_str());
if (err) {
LOG_ERROR("Unable to register device with err: %i", err);
M module-vfs/drivers/src/thirdparty/lwext4/ext4_bdev.cpp => module-vfs/drivers/src/thirdparty/lwext4/ext4_bdev.cpp +9 -2
@@ 5,6 5,7 @@
#include <ext4_config.h>
#include <ext4_blockdev.h>
#include <ext4_errno.h>
+#include <stdint.h>
#include <unordered_map>
#include <log/log.hpp>
#include <mutex.hpp>
@@ 47,29 48,34 @@ namespace purefs::fs::drivers::ext4::internal
if (!ctx) {
return -EIO;
}
+ cpp_freertos::LockGuard _lck(ctx->mutex);
auto diskmm = ctx->disk.lock();
if (!diskmm) {
return -EIO;
}
const auto err = diskmm->write(ctx->disk_h, buf, blk_id, blk_cnt);
if (err) {
- LOG_ERROR("Sector write error errno: %i", err);
+ LOG_ERROR(
+ "Sector write error errno: %i on block: %u cnt: %u", err, unsigned(blk_id), unsigned(blk_cnt));
}
return -err;
}
+
int read(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id, uint32_t blk_cnt)
{
auto ctx = reinterpret_cast<context *>(bdev->bdif->p_user);
if (!ctx) {
return -EIO;
}
+ cpp_freertos::LockGuard _lck(ctx->mutex);
auto diskmm = ctx->disk.lock();
if (!diskmm) {
return -EIO;
}
const auto err = diskmm->read(ctx->disk_h, buf, blk_id, blk_cnt);
if (err) {
- LOG_ERROR("Sector read error errno: %i", err);
+ LOG_ERROR(
+ "Sector read error errno: %i on block: %u cnt: %u", err, unsigned(blk_id), unsigned(blk_cnt));
}
return -err;
}
@@ 78,6 84,7 @@ namespace purefs::fs::drivers::ext4::internal
{
return 0;
}
+
int close(struct ext4_blockdev *bdev)
{
return 0;
M products/BellHybrid/BellHybridMain.cpp => products/BellHybrid/BellHybridMain.cpp +2 -2
@@ 19,11 19,11 @@
// services
#include <appmgr/ApplicationManager.hpp>
+#include <audio/ServiceAudio.hpp>
#include <db/ServiceDB.hpp>
#include <evtmgr/EventManager.hpp>
#include <Service/ServiceCreator.hpp>
#include <service-appmgr/Constants.hpp>
-#include <service-audio/ServiceAudio.hpp>
#include <service-desktop/ServiceDesktop.hpp>
#include <service-eink/ServiceEink.hpp>
#include <service-gui/ServiceGUI.hpp>
@@ 68,7 68,7 @@ int main()
std::vector<std::unique_ptr<sys::BaseServiceCreator>> systemServices;
systemServices.emplace_back(sys::CreatorFor<EventManager>());
systemServices.emplace_back(sys::CreatorFor<ServiceDB>());
- systemServices.emplace_back(sys::CreatorFor<ServiceAudio>());
+ systemServices.emplace_back(sys::CreatorFor<service::Audio>());
systemServices.emplace_back(sys::CreatorFor<ServiceDesktop>());
systemServices.emplace_back(sys::CreatorFor<stm::ServiceTime>(std::make_shared<alarms::AlarmOperationsFactory>()));
systemServices.emplace_back(sys::CreatorFor<service::eink::ServiceEink>(service::eink::ExitAction::None));
M products/BellHybrid/CMakeLists.txt => products/BellHybrid/CMakeLists.txt +2 -2
@@ 48,12 48,12 @@ target_link_libraries(BellHybrid
bell::app-powernap
bell::app-settings
bell::db
- evtmgr
+ bell::audio
+ bell::evtmgr
log
messagetype
module-bsp
module-vfs
- service-audio
service-desktop
service-time
sys
M products/BellHybrid/alarms/CMakeLists.txt => products/BellHybrid/alarms/CMakeLists.txt +1 -1
@@ 33,12 33,12 @@ target_include_directories(alarms
target_link_libraries(alarms
PRIVATE
- module-audio
module-vfs
bell::db
bell::appmgr
bell::app-common
bell::evtmgr
+ bell::audio
apps-common
PUBLIC
module-db
M products/BellHybrid/alarms/include/BellAlarmHandler.hpp => products/BellHybrid/alarms/include/BellAlarmHandler.hpp +0 -1
@@ 4,7 4,6 @@
#pragma once
#include "AbstractAlarmAction.hpp"
-#include <service-audio/AudioServiceAPI.hpp>
#include <service-time/AlarmHandler.hpp>
#include <Service/Service.hpp>
M products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp => products/BellHybrid/alarms/src/actions/PlayAudioActions.cpp +8 -6
@@ 4,7 4,7 @@
#include "AlarmSoundPaths.hpp"
#include "PlayAudioActions.hpp"
-#include <service-time/ServiceTime.hpp>
+#include <audio/AudioMessage.hpp>
#include <db/SystemSettings.hpp>
#include <Timers/TimerFactory.hpp>
@@ 24,14 24,16 @@ namespace alarms
if (duration != InfiniteDuration) {
spawnTimer(duration);
}
- return AudioServiceAPI::PlaybackStart(&service, playbackType, path);
+ return service.bus.sendUnicast(std::make_shared<service::AudioStartPlaybackRequest>(path, playbackType),
+ service::audioServiceName);
}
bool PlayAudioAction::turnOff()
{
detachTimer();
auto stopPlaybackVec = std::vector<audio::PlaybackType>({playbackType});
- return AudioServiceAPI::Stop(&service, stopPlaybackVec);
+ const auto msg = std::make_shared<service::AudioStopRequest>(stopPlaybackVec);
+ return service.bus.sendUnicast(msg, service::audioServiceName);
}
bool PlayAudioAction::execute()
{
@@ 66,7 68,7 @@ namespace alarms
paths::getPreWakeUpChimesDir(),
bell::settings::PrewakeUp::tone,
bell::settings::PrewakeUp::duration,
- audio::PlaybackType::Multimedia);
+ audio::PlaybackType::PreWakeUp);
}
std::unique_ptr<PlayAudioAction> createSnoozeChimeAction(sys::Service &service)
@@ 75,7 77,7 @@ namespace alarms
paths::getSnoozeChimesDir(),
bell::settings::Snooze::tone,
bell::settings::Snooze::length,
- audio::PlaybackType::Multimedia);
+ audio::PlaybackType::Snooze);
}
std::unique_ptr<PlayAudioAction> createAlarmToneAction(sys::Service &service)
{
@@ 88,7 90,7 @@ namespace alarms
paths::getBedtimeReminderChimesDir(),
bell::settings::Bedtime::tone,
bell::settings::Bedtime::duration,
- audio::PlaybackType::Multimedia);
+ audio::PlaybackType::Bedtime);
}
} // namespace factory
} // namespace alarms
M products/BellHybrid/alarms/src/actions/PlayAudioActions.hpp => products/BellHybrid/alarms/src/actions/PlayAudioActions.hpp +1 -2
@@ 4,9 4,8 @@
#pragma once
#include "AbstractAlarmAction.hpp"
+#include <audio/AudioMessage.hpp>
#include <common/SoundsRepository.hpp>
-#include <service-audio/AudioServiceAPI.hpp>
-#include <module-audio/Audio/AudioCommon.hpp>
#include <service-db/Settings.hpp>
#include <Timers/TimerHandle.hpp>
#include <Service/Service.hpp>
M products/BellHybrid/apps/application-bell-background-sounds/ApplicationBellBackgroundSounds.cpp => products/BellHybrid/apps/application-bell-background-sounds/ApplicationBellBackgroundSounds.cpp +11 -8
@@ 15,7 15,8 @@
#include "widgets/BGSoundsPlayer.hpp"
#include <apps-common/messages/AppMessage.hpp>
#include <common/models/TimeModel.hpp>
-#include <service-audio/AudioMessage.hpp>
+#include <common/models/AudioModel.hpp>
+#include <audio/AudioMessage.hpp>
#include <log/log.hpp>
namespace app
@@ 26,11 27,12 @@ namespace app
StartInBackground startInBackground,
uint32_t stackDepth)
: Application(std::move(name), std::move(parent), statusIndicators, startInBackground, stackDepth),
- player{std::make_unique<bgSounds::BGSoundsPlayer>(this)}
+ audioModel{std::make_unique<AudioModel>(this)}, player{
+ std::make_unique<bgSounds::BGSoundsPlayer>(*audioModel)}
{
bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
- connect(typeid(AudioEOFNotification), [&](sys::Message *msg) -> sys::MessagePointer {
- auto notification = static_cast<AudioEOFNotification *>(msg);
+ connect(typeid(service::AudioEOFNotification), [&](sys::Message *msg) -> sys::MessagePointer {
+ auto notification = static_cast<service::AudioEOFNotification *>(msg);
return player->handle(notification);
});
}
@@ 71,10 73,11 @@ namespace app
return std::make_unique<gui::BGSoundsPausedWindow>(app);
});
- windowsFactory.attach(gui::popup::window::volume_window, [](ApplicationCommon *app, const std::string &name) {
- auto presenter = std::make_unique<bgSounds::BGSoundsVolumePresenter>(*app);
- return std::make_unique<gui::BGSoundsVolumeWindow>(app, std::move(presenter));
- });
+ windowsFactory.attach(gui::popup::window::volume_window,
+ [this](ApplicationCommon *app, const std::string &name) {
+ auto presenter = std::make_unique<bgSounds::BGSoundsVolumePresenter>(*audioModel);
+ return std::make_unique<gui::BGSoundsVolumeWindow>(app, std::move(presenter));
+ });
attachPopups({gui::popup::ID::AlarmActivated,
gui::popup::ID::AlarmDeactivated,
M products/BellHybrid/apps/application-bell-background-sounds/CMakeLists.txt => products/BellHybrid/apps/application-bell-background-sounds/CMakeLists.txt +1 -1
@@ 47,8 47,8 @@ target_sources(application-bell-background-sounds
target_link_libraries(application-bell-background-sounds
PRIVATE
- app
apps-common
+ bell::audio
PUBLIC
module-gui
M products/BellHybrid/apps/application-bell-background-sounds/data/BGSoundsCommon.hpp => products/BellHybrid/apps/application-bell-background-sounds/data/BGSoundsCommon.hpp +0 -1
@@ 6,5 6,4 @@
namespace app::bgSounds
{
constexpr auto timerValueDBRecordName = "BGSoundsTimerValue";
- constexpr auto soundsVolumeDBRecordName = "BGSoundsVolume";
}
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 +2 -0
@@ 4,6 4,7 @@
#pragma once
#include <Application.hpp>
+#include <common/models/AbstractAudioModel.hpp>
namespace gui::window::name
{
@@ 21,6 22,7 @@ namespace app
class ApplicationBellBackgroundSounds : public Application
{
+ std::unique_ptr<AbstractAudioModel> audioModel;
std::unique_ptr<bgSounds::BGSoundsPlayer> player;
sys::MessagePointer handleSwitchWindow(sys::Message *msgl) override;
M products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsProgressPresenter.cpp => products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsProgressPresenter.cpp +4 -1
@@ 20,7 20,6 @@ namespace app::bgSounds
std::unique_ptr<AbstractTimeModel> timeModel)
: settings{settings}, player{player}, timeModel{std::move(timeModel)}
{}
- BGSoundsProgressPresenter::~BGSoundsProgressPresenter() = default;
void BGSoundsProgressPresenter::setTimer(std::unique_ptr<app::TimerWithCallbacks> &&_timer)
{
@@ 89,4 88,8 @@ namespace app::bgSounds
{
getView()->setTime(timeModel->getCurrentTime());
}
+ bool BGSoundsProgressPresenter::isPaused()
+ {
+ return player.isPaused();
+ }
} // namespace app::bgSounds
M products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsProgressPresenter.hpp => products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsProgressPresenter.hpp +5 -4
@@ 30,9 30,9 @@ namespace app::bgSounds
class View
{
public:
- ~View() = default;
- virtual void onFinished() = 0;
- virtual void onPaused() = 0;
+ virtual ~View() = default;
+ virtual void onFinished() = 0;
+ virtual void onPaused() = 0;
virtual void setTime(std::time_t newTime) = 0;
virtual void setTimeFormat(utils::time::Locale::TimeFormat fmt) = 0;
};
@@ 46,6 46,7 @@ namespace app::bgSounds
virtual void resume() = 0;
virtual void setTimer(std::unique_ptr<app::TimerWithCallbacks> &&timer) = 0;
virtual void handleUpdateTimeEvent() = 0;
+ virtual bool isPaused() = 0;
};
};
@@ 64,6 65,7 @@ namespace app::bgSounds
void resume() override;
void setTimer(std::unique_ptr<app::TimerWithCallbacks> &&_timer) override;
void handleUpdateTimeEvent() override;
+ bool isPaused() override;
void onFinished();
@@ 71,6 73,5 @@ namespace app::bgSounds
BGSoundsProgressPresenter(settings::Settings *settings,
AbstractBGSoundsPlayer &player,
std::unique_ptr<AbstractTimeModel> timeModel);
- ~BGSoundsProgressPresenter();
};
} // namespace app::bgSounds
M products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsTimerSelectPresenter.hpp => products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsTimerSelectPresenter.hpp +2 -1
@@ 30,12 30,13 @@ namespace app::bgSounds
class View
{
public:
- ~View() = default;
+ virtual ~View() = default;
};
class Presenter : public BasePresenter<BGSoundsTimerSelectContract::View>
{
public:
+ virtual ~Presenter() = default;
virtual const Range &getTimerValuesRange() const noexcept = 0;
virtual std::chrono::minutes getCurrentTimerValue() const = 0;
virtual void setTimerValue(std::chrono::minutes) = 0;
M products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsVolumePresenter.cpp => products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsVolumePresenter.cpp +5 -14
@@ 2,11 2,10 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "BGSoundsVolumePresenter.hpp"
-#include <Application.hpp>
namespace app::bgSounds
{
- BGSoundsVolumePresenter::BGSoundsVolumePresenter(app::ApplicationCommon &app) : app{app}
+ BGSoundsVolumePresenter::BGSoundsVolumePresenter(AbstractAudioModel &audioModel) : audioModel{audioModel}
{}
VolumeData BGSoundsVolumePresenter::getVolumeData()
@@ 14,20 13,12 @@ namespace app::bgSounds
return volumeData;
}
- audio::Volume BGSoundsVolumePresenter::getDefaultVolume()
+ void BGSoundsVolumePresenter::setVolume(AbstractAudioModel::Volume volume)
{
- return audio::defaultVolume;
+ audioModel.setVolume(volume, AbstractAudioModel::PlaybackType::Multimedia, {});
}
-
- void BGSoundsVolumePresenter::increaseVolume()
- {
- app.increaseCurrentVolume();
- }
-
- void BGSoundsVolumePresenter::decreaseVolume()
+ AbstractAudioModel::Volume BGSoundsVolumePresenter::getVolume()
{
- if (getView()->getCurrentVolume() != minVolume) {
- app.decreaseCurrentVolume();
- }
+ return audioModel.getVolume(AbstractAudioModel::PlaybackType::Multimedia).value_or(defaultVolume);
}
} // namespace app::bgSounds
M products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsVolumePresenter.hpp => products/BellHybrid/apps/application-bell-background-sounds/presenter/BGSoundsVolumePresenter.hpp +17 -28
@@ 3,8 3,7 @@
#pragma once
-#include <apps-common/BasePresenter.hpp>
-#include <module-audio/Audio/AudioCommon.hpp>
+#include <common/models/AbstractAudioModel.hpp>
namespace app
{
@@ 12,47 11,37 @@ namespace app
}
namespace app::bgSounds
{
- constexpr audio::Volume minVolume = 1u;
using VolumeData = struct VolumeData
{
- audio::Volume min;
- audio::Volume max;
- audio::Volume step;
+ AbstractAudioModel::Volume min;
+ AbstractAudioModel::Volume max;
+ AbstractAudioModel::Volume step;
};
- class BGSoundsVolumeContract
+ class AbstractBGSoundsVolumePresenter
{
public:
- class View
- {
- public:
- virtual ~View() = default;
- virtual audio::Volume getCurrentVolume() const noexcept = 0;
- };
- class Presenter : public BasePresenter<BGSoundsVolumeContract::View>
- {
- public:
- virtual VolumeData getVolumeData() = 0;
- virtual audio::Volume getDefaultVolume() = 0;
- virtual void increaseVolume() = 0;
- virtual void decreaseVolume() = 0;
- };
+ virtual ~AbstractBGSoundsVolumePresenter() = default;
+ virtual VolumeData getVolumeData() = 0;
+ virtual void setVolume(AbstractAudioModel::Volume volume) = 0;
+ virtual AbstractAudioModel::Volume getVolume() = 0;
};
- class BGSoundsVolumePresenter : public BGSoundsVolumeContract::Presenter
+ class BGSoundsVolumePresenter : public AbstractBGSoundsVolumePresenter
{
- app::ApplicationCommon &app;
constexpr static struct VolumeData volumeData
{
- bgSounds::minVolume, audio::maxVolume, audio::defaultVolumeStep
+ AbstractAudioModel::minVolume, AbstractAudioModel::maxVolume, 1
};
+ static constexpr AbstractAudioModel::Volume defaultVolume = 5;
+
+ AbstractAudioModel &audioModel;
VolumeData getVolumeData() override;
- audio::Volume getDefaultVolume() override;
- void increaseVolume() override;
- void decreaseVolume() override;
+ void setVolume(AbstractAudioModel::Volume volume) override;
+ AbstractAudioModel::Volume getVolume() override;
public:
- explicit BGSoundsVolumePresenter(app::ApplicationCommon &app);
+ explicit BGSoundsVolumePresenter(AbstractAudioModel &audioModel);
};
} // namespace app::bgSounds
M products/BellHybrid/apps/application-bell-background-sounds/widgets/BGSoundsPlayer.cpp => products/BellHybrid/apps/application-bell-background-sounds/widgets/BGSoundsPlayer.cpp +29 -85
@@ 2,104 2,48 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "BGSoundsPlayer.hpp"
-#include <service-audio/AudioMessage.hpp>
-#include <service-audio/AudioServiceName.hpp>
+#include <audio/AudioMessage.hpp>
namespace app::bgSounds
{
- BGSoundsPlayer::BGSoundsPlayer(app::ApplicationCommon *app) : app::AsyncCallbackReceiver{app}, app{app}
- {}
- void BGSoundsPlayer::start(const std::string &filePath, PlaybackMode mode, OnStateChangeCallback callback)
+ auto BGSoundsPlayer::handle(service::AudioEOFNotification *msg) -> std::shared_ptr<sys::Message>
{
- auto msg = std::make_unique<AudioStartPlaybackRequest>(filePath, audio::PlaybackType::Multimedia);
- auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::name::audio);
- auto cb = [this, _callback = std::move(callback), filePath, mode](auto response) {
- auto result = dynamic_cast<AudioStartPlaybackResponse *>(response);
- if (result == nullptr) {
- return false;
- }
- token = result->token;
- recentFilePath = std::move(filePath);
- playbackMode = mode;
- if (_callback) {
- _callback(result->retCode);
- }
- return true;
- };
- task->execute(app, this, std::move(cb));
+ if (playbackMode == PlaybackMode::Looped) {
+ audioModel.play(recentFilePath, AbstractAudioModel::PlaybackType::Multimedia, {});
+ }
+ return sys::msgHandled();
}
- void BGSoundsPlayer::stop(OnStateChangeCallback callback)
+ AbstractBGSoundsPlayer::PlaybackMode BGSoundsPlayer::getCurrentMode() const noexcept
{
- if (token.IsValid()) {
- auto msg = std::make_unique<AudioStopRequest>(token);
- auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::name::audio);
- auto cb = [_callback = std::move(callback)](auto response) {
- auto result = dynamic_cast<AudioStopResponse *>(response);
- if (result == nullptr) {
- return false;
- }
- if (_callback) {
- _callback(result->retCode);
- }
- return true;
- };
- task->execute(app, this, std::move(cb));
- }
+ return playbackMode;
}
- void BGSoundsPlayer::pause(OnStateChangeCallback callback)
+ BGSoundsPlayer::BGSoundsPlayer(AbstractAudioModel &audioModel) : audioModel{audioModel}
+ {}
+ void BGSoundsPlayer::start(const std::string &filePath,
+ AbstractBGSoundsPlayer::PlaybackMode mode,
+ AbstractAudioModel::OnStateChangeCallback &&callback)
{
- if (token.IsValid()) {
- auto msg = std::make_unique<AudioPauseRequest>(token);
- auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::name::audio);
- auto cb = [_callback = std::move(callback)](auto response) {
- auto result = dynamic_cast<AudioPauseResponse *>(response);
- if (result == nullptr) {
- return false;
- }
- if (_callback) {
- _callback(result->retCode);
- }
- return true;
- };
- task->execute(app, this, std::move(cb));
- }
+ recentFilePath = filePath;
+ playbackMode = mode;
+ audioModel.play(filePath, AbstractAudioModel::PlaybackType::Multimedia, std::move(callback));
}
- void BGSoundsPlayer::resume(OnStateChangeCallback callback)
+ void BGSoundsPlayer::stop(AbstractAudioModel::OnStateChangeCallback &&callback)
{
- auto msg = std::make_unique<AudioResumeRequest>(token);
- auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::name::audio);
- auto cb = [_callback = std::move(callback)](auto response) {
- auto result = dynamic_cast<AudioResumeResponse *>(response);
- if (result == nullptr) {
- return false;
- }
- if (_callback) {
- _callback(result->retCode);
- }
- return true;
- };
- task->execute(app, this, std::move(cb));
+ paused = false;
+ audioModel.stop(std::move(callback));
}
-
- auto BGSoundsPlayer::handle(AudioEOFNotification *msg) -> std::shared_ptr<sys::Message>
+ void BGSoundsPlayer::pause(AbstractAudioModel::OnStateChangeCallback &&callback)
{
- if (token == msg->token && playbackMode == PlaybackMode::Looped) {
- auto msg = std::make_unique<AudioStartPlaybackRequest>(recentFilePath, audio::PlaybackType::Multimedia);
- auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::name::audio);
- auto cb = [this](auto response) {
- auto result = dynamic_cast<AudioStartPlaybackResponse *>(response);
- if (result == nullptr) {
- return false;
- }
- token = result->token;
- return true;
- };
- task->execute(app, this, std::move(cb));
- }
- return sys::msgHandled();
+ paused = true;
+ audioModel.pause(std::move(callback));
}
- AbstractBGSoundsPlayer::PlaybackMode BGSoundsPlayer::getCurrentMode() const noexcept
+ void BGSoundsPlayer::resume(AbstractAudioModel::OnStateChangeCallback &&callback)
{
- return playbackMode;
+ paused = false;
+ audioModel.resume(std::move(callback));
+ }
+ bool BGSoundsPlayer::isPaused()
+ {
+ return paused;
}
} // namespace app::bgSounds
M products/BellHybrid/apps/application-bell-background-sounds/widgets/BGSoundsPlayer.hpp => products/BellHybrid/apps/application-bell-background-sounds/widgets/BGSoundsPlayer.hpp +33 -24
@@ 2,14 2,18 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include <module-audio/Audio/AudioCommon.hpp>
-#include <AsyncTask.hpp>
+
+#include <common/models/AbstractAudioModel.hpp>
namespace app
{
class ApplicationCommon;
}
-class AudioEOFNotification;
+namespace service
+{
+ class AudioEOFNotification;
+}
+
namespace app::bgSounds
{
class AbstractBGSoundsPlayer
@@ 21,32 25,37 @@ namespace app::bgSounds
SingleShot
};
- virtual ~AbstractBGSoundsPlayer() = default;
-
- using OnStateChangeCallback = std::function<void(audio::RetCode retCode)>;
- virtual void start(const std::string &filePath, PlaybackMode mode, OnStateChangeCallback callback) = 0;
- virtual void stop(OnStateChangeCallback callback) = 0;
- virtual void pause(OnStateChangeCallback callback) = 0;
- virtual void resume(OnStateChangeCallback callback) = 0;
- virtual PlaybackMode getCurrentMode() const noexcept = 0;
+ virtual ~AbstractBGSoundsPlayer() = default;
+ virtual void start(const std::string &filePath,
+ PlaybackMode mode,
+ AbstractAudioModel::OnStateChangeCallback &&callback) = 0;
+ virtual void stop(AbstractAudioModel::OnStateChangeCallback &&callback) = 0;
+ virtual void pause(AbstractAudioModel::OnStateChangeCallback &&callback) = 0;
+ virtual void resume(AbstractAudioModel::OnStateChangeCallback &&callback) = 0;
+ virtual PlaybackMode getCurrentMode() const noexcept = 0;
+ virtual bool isPaused() = 0;
};
- class BGSoundsPlayer : public AbstractBGSoundsPlayer, public app::AsyncCallbackReceiver
+ class BGSoundsPlayer : public AbstractBGSoundsPlayer
{
- app::ApplicationCommon *app{};
- audio::Token token;
- std::string recentFilePath;
- PlaybackMode playbackMode = PlaybackMode::SingleShot;
+ public:
+ explicit BGSoundsPlayer(AbstractAudioModel &audioModel);
- void start(const std::string &filePath, PlaybackMode mode, OnStateChangeCallback callback) override;
- void stop(OnStateChangeCallback callback) override;
- void pause(OnStateChangeCallback callback) override;
- void resume(OnStateChangeCallback callback) override;
- PlaybackMode getCurrentMode() const noexcept override;
+ auto handle(service::AudioEOFNotification *msg) -> std::shared_ptr<sys::Message>;
- public:
- explicit BGSoundsPlayer(app::ApplicationCommon *app);
+ private:
+ void start(const std::string &filePath,
+ PlaybackMode mode,
+ AbstractAudioModel::OnStateChangeCallback &&callback) override;
+ void stop(AbstractAudioModel::OnStateChangeCallback &&callback) override;
+ void pause(AbstractAudioModel::OnStateChangeCallback &&callback) override;
+ void resume(AbstractAudioModel::OnStateChangeCallback &&callback) override;
+ PlaybackMode getCurrentMode() const noexcept override;
+ bool isPaused() override;
- auto handle(AudioEOFNotification *msg) -> std::shared_ptr<sys::Message>;
+ AbstractAudioModel &audioModel;
+ std::string recentFilePath;
+ PlaybackMode playbackMode = PlaybackMode::SingleShot;
+ bool paused{false};
};
} // namespace app::bgSounds
M products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsProgressWindow.cpp => products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsProgressWindow.cpp +4 -8
@@ 12,7 12,7 @@
#include <time/dateCommon.hpp>
namespace
{
- inline constexpr auto bgSoundsTimerName = "BGSoundsProgressTimer";
+ inline constexpr auto bgSoundsTimerName = "BGSoundsProgressTimer";
inline constexpr std::chrono::seconds timerTick{1};
void decorateProgressItem(gui::Rect *item, gui::Alignment::Vertical alignment)
@@ 75,7 75,7 @@ namespace gui
void BGSoundsProgressWindow::onBeforeShow(ShowMode mode, SwitchData *data)
{
- if (mode == ShowMode::GUI_SHOW_RETURN) {
+ if (mode == ShowMode::GUI_SHOW_RETURN && presenter->isPaused()) {
presenter->resume();
return;
}
@@ 133,12 133,8 @@ namespace gui
presenter->pause();
return true;
}
- else if (inputEvent.is(KeyCode::KEY_DOWN)) {
- application->decreaseCurrentVolume();
- return true;
- }
- else if (inputEvent.is(KeyCode::KEY_UP)) {
- application->increaseCurrentVolume();
+ else if (inputEvent.is(KeyCode::KEY_DOWN) || inputEvent.is(KeyCode::KEY_UP)) {
+ application->switchWindow(gui::popup::window::volume_window);
return true;
}
}
M products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsVolumeWindow.cpp => products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsVolumeWindow.cpp +15 -36
@@ 10,11 10,10 @@
namespace gui
{
BGSoundsVolumeWindow::BGSoundsVolumeWindow(
- app::ApplicationCommon *app, std::unique_ptr<app::bgSounds::BGSoundsVolumeContract::Presenter> &&presenter)
+ app::ApplicationCommon *app, std::unique_ptr<app::bgSounds::AbstractBGSoundsVolumePresenter> &&presenter)
: WindowWithTimer(app, gui::popup::window::volume_window), presenter{std::move(presenter)}
{
buildInterface();
- this->presenter->attach(this);
}
void BGSoundsVolumeWindow::buildInterface()
@@ 45,47 44,27 @@ namespace gui
spinner->setFont(bgSoundsStyle::valumeValueFont);
spinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
spinner->setFocusEdges(RectangleEdge::None);
- spinner->setCurrentValue(static_cast<UIntegerSpinner::Type>(presenter->getDefaultVolume()));
+ spinner->setCurrentValue(static_cast<UIntegerSpinner::Type>(presenter->getVolume()));
body->getCenterBox()->addWidget(spinner);
- setFocusItem(spinner);
+ spinner->onValueChanged = [this](const auto &value) { presenter->setVolume(value); };
+ body->setMinMaxArrowsVisibility(spinner->getCurrentValue() == data.min, spinner->getCurrentValue() == data.max);
+
+ setFocusItem(body);
body->resize();
}
- bool BGSoundsVolumeWindow::onInput(const gui::InputEvent &inputEvent)
+ bool BGSoundsVolumeWindow::onInput(const InputEvent &inputEvent)
{
- resetTimer();
-
- if (inputEvent.isShortRelease(KeyCode::KEY_DOWN)) {
- presenter->decreaseVolume();
+ if (inputEvent.isShortRelease(KeyCode::KEY_ENTER) || inputEvent.isShortRelease(KeyCode::KEY_RF)) {
+ application->returnToPreviousWindow();
return true;
}
- else if (inputEvent.isShortRelease(KeyCode::KEY_UP)) {
- presenter->increaseVolume();
- return true;
- }
- return WindowWithTimer::onInput(inputEvent);
- }
-
- void BGSoundsVolumeWindow::onBeforeShow(ShowMode mode, SwitchData *data)
- {
- WindowWithTimer::onBeforeShow(mode, data);
- const auto popupData = dynamic_cast<VolumePopupData *>(data);
- if (popupData) {
- volume = popupData->getVolume();
- audioContext = popupData->getAudioContext();
- spinner->setCurrentValue(static_cast<UIntegerSpinner::Type>(volume));
- auto currentVolume = spinner->getCurrentValue();
-
- auto isMax = currentVolume == presenter->getVolumeData().max;
- auto isMin = currentVolume == presenter->getVolumeData().min;
- body->setArrowVisible(BellBaseLayout::Arrow::Left, not isMin);
- body->setArrowVisible(BellBaseLayout::Arrow::Right, not isMax);
- }
- }
-
- audio::Volume BGSoundsVolumeWindow::getCurrentVolume() const noexcept
- {
- return spinner->getCurrentValue();
+ resetTimer();
+ auto data = presenter->getVolumeData();
+ const auto ret = body->onInput(inputEvent);
+ const auto selectedVal = spinner->getCurrentValue();
+ body->setMinMaxArrowsVisibility(selectedVal == data.min, selectedVal == data.max);
+ return ret;
}
} // namespace gui
M products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsVolumeWindow.hpp => products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsVolumeWindow.hpp +4 -11
@@ 7,29 7,22 @@
#include <apps-common/popups/WindowWithTimer.hpp>
#include <apps-common/widgets/spinners/Spinners.hpp>
+#include <common/models/AbstractAudioModel.hpp>
-#include <module-audio/Audio/AudioCommon.hpp>
-#include <module-audio/Audio/Profiles/Profile.hpp>
namespace gui
{
class BellBaseLayout;
- class BGSoundsVolumeWindow : public WindowWithTimer, public app::bgSounds::BGSoundsVolumeContract::View
+ class BGSoundsVolumeWindow : public WindowWithTimer
{
- std::unique_ptr<app::bgSounds::BGSoundsVolumeContract::Presenter> presenter;
- audio::Volume volume = 1;
- audio::Context audioContext;
-
+ std::unique_ptr<app::bgSounds::AbstractBGSoundsVolumePresenter> presenter;
BellBaseLayout *body{};
UIntegerSpinner *spinner = nullptr;
void buildInterface() override;
bool onInput(const gui::InputEvent &inputEvent) override;
- void onBeforeShow(ShowMode mode, SwitchData *data);
-
- audio::Volume getCurrentVolume() const noexcept override;
public:
BGSoundsVolumeWindow(app::ApplicationCommon *app,
- std::unique_ptr<app::bgSounds::BGSoundsVolumeContract::Presenter> &&windowPresenter);
+ std::unique_ptr<app::bgSounds::AbstractBGSoundsVolumePresenter> &&windowPresenter);
};
} // namespace gui
M products/BellHybrid/apps/application-bell-bedtime/ApplicationBellBedtime.cpp => products/BellHybrid/apps/application-bell-bedtime/ApplicationBellBedtime.cpp +1 -1
@@ 32,7 32,7 @@ namespace app
void ApplicationBellBedtime::createUserInterface()
{
- windowsFactory.attach(gui::name::window::main_window, [this](ApplicationCommon *app, const std::string &) {
+ windowsFactory.attach(gui::name::window::main_window, [](ApplicationCommon *app, const std::string &) {
auto bedtimeModel = std::make_unique<bell_bedtime::BedtimeModel>(app);
auto provider = std::make_shared<bell_bedtime::BedtimeListItemProvider>(std::move(bedtimeModel));
auto presenter = std::make_unique<bell_bedtime::BellBedtimeWindowPresenter>(provider);
M products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp => products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp +0 -1
@@ 19,7 19,6 @@
#include <common/windows/BellFactoryReset.hpp>
#include <service-db/DBNotificationMessage.hpp>
#include <windows/Dialog.hpp>
-#include <service-audio/AudioMessage.hpp>
#include <common/popups/BedtimeNotificationWindow.hpp>
namespace app
M products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt => products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt +1 -0
@@ 37,6 37,7 @@ target_sources(application-bell-meditation-timer
target_link_libraries(application-bell-meditation-timer
PRIVATE
app
+ bell::audio
bell::app-common
bell::app-main
bellgui
M products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationRunningWindow.cpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationRunningWindow.cpp +4 -3
@@ 5,10 5,10 @@
#include "MeditationRunningWindow.hpp"
#include "MeditationStyle.hpp"
+#include <audio/AudioMessage.hpp>
#include <apps-common/widgets/BellBaseLayout.hpp>
#include <apps-common/widgets/ProgressTimerWithBarGraphAndCounter.hpp>
#include <purefs/filesystem_paths.hpp>
-#include <service-audio/AudioServiceAPI.hpp>
namespace
{
@@ 182,7 182,8 @@ namespace gui
void MeditationRunningWindow::playGong()
{
- AudioServiceAPI::PlaybackStart(
- application, audio::PlaybackType::Meditation, purefs::dir::getCurrentOSPath() / meditationAudioPath);
+ auto msg = std::make_shared<service::AudioStartPlaybackRequest>(
+ purefs::dir::getCurrentOSPath() / meditationAudioPath, audio::PlaybackType::Meditation);
+ application->bus.sendUnicast(std::move(msg), service::audioServiceName);
}
} // namespace gui
M products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp => products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp +0 -1
@@ 10,7 10,6 @@
#include "windows/PowerNapSessionEndedWindow.hpp"
#include <common/models/TimeModel.hpp>
#include <AlarmSoundPaths.hpp>
-#include <service-audio/AudioMessage.hpp>
namespace app
{
M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.cpp +3 -11
@@ 59,22 59,14 @@ namespace app::powernap
{
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);
+
+ audioModel->play(filePath.value_or(""), AbstractAudioModel::PlaybackType::Alarm, {});
napAlarmTimer.start();
napFinished = true;
}
void PowerNapProgressPresenter::onNapAlarmFinished()
{
- audioModel->stop(currentToken, nullptr);
+ audioModel->stop({});
getView()->napEnded();
}
M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp +0 -1
@@ 58,7 58,6 @@ namespace app::powernap
std::unique_ptr<app::TimerWithCallbacks> timer;
std::unique_ptr<AbstractTimeModel> timeModel;
sys::TimerHandle napAlarmTimer;
- audio::Token currentToken;
bool napFinished{false};
void activate() override;
M products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp => products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp +6 -6
@@ 144,16 144,16 @@ 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>(this);
+ auto chimeVolumeModel = std::make_unique<bell_settings::PrewakeUpChimeVolumeModel>(*audioModel);
auto lightDurationModel = std::make_unique<bell_settings::PrewakeUpLightDurationModel>(this);
auto prewakeUpSettingsModel =
std::make_unique<bell_settings::PrewakeUpSettingsModel>(std::move(chimeDurationModel),
std::move(chimeToneModel),
std::move(chimeVolumeModel),
std::move(lightDurationModel));
- auto audioModel = std::make_unique<AudioModel>(this);
auto soundsRepository = std::make_unique<SoundsRepository>(alarms::paths::getPreWakeUpChimesDir());
auto provider = std::make_shared<bell_settings::PrewakeUpListItemProvider>(
*prewakeUpSettingsModel, soundsRepository->getSongTitles());
@@ 169,18 169,18 @@ 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);
auto snoozeChimeToneModel = std::make_unique<bell_settings::SnoozeChimeToneModel>(this);
- auto snoozeChimeVolumeModel = std::make_unique<bell_settings::SnoozeChimeVolumeModel>(this);
+ auto snoozeChimeVolumeModel = std::make_unique<bell_settings::SnoozeChimeVolumeModel>(*audioModel);
auto snoozeSettingsModel =
std::make_unique<bell_settings::SnoozeSettingsModel>(std::move(snoozeOnOffModel),
std::move(snoozeLengthModel),
std::move(snoozeChimeIntervalModel),
std::move(snoozeChimeToneModel),
std::move(snoozeChimeVolumeModel));
- auto audioModel = std::make_unique<AudioModel>(this);
auto soundsRepository = std::make_unique<SoundsRepository>(alarms::paths::getSnoozeChimesDir());
auto provider = std::make_shared<bell_settings::SnoozeListItemProvider>(
*snoozeSettingsModel, soundsRepository->getSongTitles());
@@ 190,12 190,12 @@ namespace app
});
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>(this);
+ auto alarmVolumeModel = std::make_unique<bell_settings::AlarmVolumeModel>(*audioModel);
auto alarmLightOnOffModel = std::make_unique<bell_settings::AlarmLightOnOffModel>(this);
auto alarmSettingsModel = std::make_unique<bell_settings::AlarmSettingsModel>(
std::move(alarmToneModel), std::move(alarmVolumeModel), std::move(alarmLightOnOffModel));
- auto audioModel = std::make_unique<AudioModel>(this);
auto soundsRepository = std::make_unique<SoundsRepository>(alarms::paths::getAlarmDir());
auto provider = std::make_shared<bell_settings::AlarmSettingsListItemProvider>(
*alarmSettingsModel, soundsRepository->getSongTitles());
M products/BellHybrid/apps/application-bell-settings/CMakeLists.txt => products/BellHybrid/apps/application-bell-settings/CMakeLists.txt +1 -0
@@ 120,6 120,7 @@ target_sources(application-bell-settings
target_link_libraries(application-bell-settings
PRIVATE
app
+ bell::audio
bellgui
bell::db
bell::alarms
M products/BellHybrid/apps/application-bell-settings/models/advanced/FrontlightModel.cpp => products/BellHybrid/apps/application-bell-settings/models/advanced/FrontlightModel.cpp +12 -4
@@ 10,15 10,23 @@
namespace
{
- constexpr auto multiplier = 10U;
+ constexpr auto minPercent = 0.0f;
+ constexpr auto maxPercent = 100.0f;
+ constexpr auto minimumLightOnPercentOffsetValue = 16.0f;
+ constexpr auto minBrightness = 1U;
+ constexpr auto maxBrightness = 10U;
+ constexpr float multiplier = (maxPercent - minimumLightOnPercentOffsetValue) / maxBrightness;
+
float fixedValToPercentage(app::bell_settings::AbstractFrontlightModel::Brightness value)
{
- return value * multiplier;
+ float scaled = minimumLightOnPercentOffsetValue + (value - minBrightness) * multiplier;
+ return std::min(maxPercent, std::max(minPercent, scaled));
}
- app::bell_settings::AbstractFrontlightModel::Brightness percentageToFixedVal(float value)
+ app::bell_settings::AbstractFrontlightModel::Brightness percentageToFixedVal(float percent)
{
- return value / multiplier;
+ auto value = (percent - minimumLightOnPercentOffsetValue) / multiplier;
+ return std::round(value + minBrightness);
}
} // namespace
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/AlarmSettingsModel.cpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/AlarmSettingsModel.cpp +10 -3
@@ 21,13 21,20 @@ namespace app::bell_settings
void AlarmVolumeModel::setValue(std::uint8_t value)
{
const auto valStr = std::to_string(value);
- settings.setValue(bell::settings::Alarm::volume, valStr, settings::SettingsScope::Global);
+ audioModel.setVolume(value, AbstractAudioModel::PlaybackType::Alarm, {});
}
std::uint8_t AlarmVolumeModel::getValue() const
{
- const auto str = settings.getValue(bell::settings::Alarm::volume, settings::SettingsScope::Global);
- return std::stoi(str);
+ return defaultValue;
+ }
+ void AlarmVolumeModel::restoreDefault()
+ {
+ setValue(defaultValue);
+ }
+ AlarmVolumeModel::AlarmVolumeModel(AbstractAudioModel &audioModel) : audioModel{audioModel}
+ {
+ defaultValue = audioModel.getVolume(AbstractAudioModel::PlaybackType::Alarm).value_or(0);
}
void AlarmLightOnOffModel::setValue(bool value)
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/AlarmSettingsModel.hpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/AlarmSettingsModel.hpp +8 -3
@@ 5,6 5,7 @@
#include "AbstractAlarmSettingsModel.hpp"
#include <common/models/SettingsModel.hpp>
+#include <common/models/AudioModel.hpp>
namespace app::bell_settings
{
@@ 17,13 18,17 @@ namespace app::bell_settings
UTF8 getValue() const override;
};
- class AlarmVolumeModel : public gui::SettingsModel<std::uint8_t>
+ class AlarmVolumeModel : public gui::AbstractSettingsModel<std::uint8_t>
{
public:
- using SettingsModel::SettingsModel;
-
+ explicit AlarmVolumeModel(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;
};
class AlarmLightOnOffModel : public gui::SettingsModel<bool>
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpSettingsModel.cpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpSettingsModel.cpp +10 -3
@@ 33,13 33,20 @@ namespace app::bell_settings
void PrewakeUpChimeVolumeModel::setValue(std::uint8_t value)
{
const auto valStr = std::to_string(value);
- settings.setValue(bell::settings::PrewakeUp::volume, valStr, settings::SettingsScope::Global);
+ audioModel.setVolume(value, AbstractAudioModel::PlaybackType::PreWakeup, {});
}
std::uint8_t PrewakeUpChimeVolumeModel::getValue() const
{
- const auto str = settings.getValue(bell::settings::PrewakeUp::volume, settings::SettingsScope::Global);
- return std::stoi(str);
+ return defaultValue;
+ }
+ PrewakeUpChimeVolumeModel::PrewakeUpChimeVolumeModel(AbstractAudioModel &audioModel) : audioModel{audioModel}
+ {
+ defaultValue = audioModel.getVolume(AbstractAudioModel::PlaybackType::PreWakeup).value_or(0);
+ }
+ void PrewakeUpChimeVolumeModel::restoreDefault()
+ {
+ setValue(defaultValue);
}
void PrewakeUpLightDurationModel::setValue(std::uint8_t value)
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpSettingsModel.hpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpSettingsModel.hpp +8 -3
@@ 5,6 5,7 @@
#include "AbstractPrewakeUpSettingsModel.hpp"
#include <common/models/SettingsModel.hpp>
+#include <common/models/AudioModel.hpp>
namespace app::bell_settings
{
@@ 26,13 27,17 @@ namespace app::bell_settings
UTF8 getValue() const override;
};
- class PrewakeUpChimeVolumeModel : public gui::SettingsModel<std::uint8_t>
+ class PrewakeUpChimeVolumeModel : public gui::AbstractSettingsModel<std::uint8_t>
{
public:
- using SettingsModel::SettingsModel;
-
+ explicit PrewakeUpChimeVolumeModel(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;
};
class PrewakeUpLightDurationModel : public gui::SettingsModel<std::uint8_t>
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/SnoozeSettingsModel.cpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/SnoozeSettingsModel.cpp +10 -2
@@ 74,11 74,19 @@ namespace app::bell_settings
void SnoozeChimeVolumeModel::setValue(std::uint8_t value)
{
const auto valStr = std::to_string(value);
- settings.setValue(bell::settings::Snooze::volume, valStr, settings::SettingsScope::Global);
+ audioModel.setVolume(value, AbstractAudioModel::PlaybackType::Snooze, {});
}
std::uint8_t SnoozeChimeVolumeModel::getValue() const
{
- return get_helper<std::uint8_t>(settings, bell::settings::Snooze::volume).value_or(0);
+ return defaultValue;
+ }
+ SnoozeChimeVolumeModel::SnoozeChimeVolumeModel(AbstractAudioModel &audioModel) : audioModel{audioModel}
+ {
+ defaultValue = audioModel.getVolume(AbstractAudioModel::PlaybackType::Snooze).value_or(0);
+ }
+ void SnoozeChimeVolumeModel::restoreDefault()
+ {
+ setValue(defaultValue);
}
} // namespace app::bell_settings
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/SnoozeSettingsModel.hpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/SnoozeSettingsModel.hpp +8 -2
@@ 5,6 5,7 @@
#include "AbstractSnoozeSettingsModel.hpp"
#include <common/models/SettingsModel.hpp>
+#include <common/models/AudioModel.hpp>
namespace app::bell_settings
{
@@ 44,13 45,18 @@ namespace app::bell_settings
UTF8 getValue() const override;
};
- class SnoozeChimeVolumeModel : public gui::SettingsModel<std::uint8_t>
+ class SnoozeChimeVolumeModel : public gui::AbstractSettingsModel<std::uint8_t>
{
public:
- using SettingsModel::SettingsModel;
+ explicit SnoozeChimeVolumeModel(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;
};
class SnoozeSettingsModel : public AbstractSnoozeSettingsModel
M products/BellHybrid/apps/application-bell-settings/presenter/BedtimeSettingsPresenter.cpp => products/BellHybrid/apps/application-bell-settings/presenter/BedtimeSettingsPresenter.cpp +10 -16
@@ 12,21 12,11 @@ namespace app::bell_settings
: provider(std::move(provider)),
model(std::move(model)), audioModel{std::move(audioModel)}, soundsRepository{std::move(soundsRepository)}
{
- 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;
- };
-
- auto playSound = [this, playResponseCb](const UTF8 &val) {
+ auto playSound = [this](const UTF8 &val) {
currentSoundPath = val;
this->audioModel->play(this->soundsRepository->titleToPath(currentSoundPath).value_or(""),
- playResponseCb,
- AbstractAudioModel::PlaybackType::Bedtime);
+ AbstractAudioModel::PlaybackType::Bedtime,
+ {});
};
this->provider->onExit = [this]() { getView()->exit(); };
@@ 36,9 26,9 @@ namespace app::bell_settings
this->provider->onToneChange = playSound;
this->provider->onVolumeEnter = playSound;
- this->provider->onVolumeExit = [this](const auto &) { this->audioModel->stop(currentToken, nullptr); };
+ this->provider->onVolumeExit = [this](const auto &) { this->stopSound(); };
this->provider->onVolumeChange = [this, playSound](const auto &val) {
- this->audioModel->setVolume(val, AbstractAudioModel::PlaybackType::Bedtime);
+ this->audioModel->setVolume(val, AbstractAudioModel::PlaybackType::Bedtime, {});
playSound(currentSoundPath);
};
}
@@ 69,6 59,10 @@ namespace app::bell_settings
void BedtimeSettingsPresenter::stopSound()
{
- this->audioModel->stop(currentToken, nullptr);
+ this->audioModel->stop({});
+ }
+ void BedtimeSettingsPresenter::exitWithoutSave()
+ {
+ model->getBedtimeVolume().restoreDefault();
}
} // namespace app::bell_settings
M products/BellHybrid/apps/application-bell-settings/presenter/BedtimeSettingsPresenter.hpp => products/BellHybrid/apps/application-bell-settings/presenter/BedtimeSettingsPresenter.hpp +2 -1
@@ 35,6 35,7 @@ namespace app::bell_settings
virtual auto saveData() -> void = 0;
virtual auto loadData() -> void = 0;
virtual auto eraseProviderData() -> void = 0;
+ virtual void exitWithoutSave() = 0;
};
};
@@ 50,6 51,7 @@ namespace app::bell_settings
auto saveData() -> void override;
auto loadData() -> void override;
auto eraseProviderData() -> void override;
+ void exitWithoutSave() override;
private:
void stopSound();
@@ 58,7 60,6 @@ namespace app::bell_settings
std::shared_ptr<AbstractBedtimeModel> model;
std::unique_ptr<AbstractAudioModel> audioModel;
std::unique_ptr<AbstractSoundsRepository> soundsRepository;
- audio::Token currentToken;
UTF8 currentSoundPath;
};
} // namespace app::bell_settings
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/AlarmSettingsPresenter.cpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/AlarmSettingsPresenter.cpp +9 -15
@@ 13,20 13,10 @@ namespace app::bell_settings
: provider(provider),
model(std::move(model)), audioModel{std::move(audioModel)}, soundsRepository{std::move(soundsRepository)}
{
- 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;
- };
- auto playSound = [this, playResponseCb](const UTF8 &val) {
- this->audioModel->play(this->soundsRepository->titleToPath(val).value_or(""),
- playResponseCb,
- AbstractAudioModel::PlaybackType::Alarm);
+ auto playSound = [this](const UTF8 &val) {
+ this->audioModel->play(
+ this->soundsRepository->titleToPath(val).value_or(""), AbstractAudioModel::PlaybackType::Alarm, {});
};
this->provider->onExit = [this]() { getView()->exit(); };
@@ 38,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, {});
};
}
@@ 67,6 57,10 @@ namespace app::bell_settings
}
void AlarmSettingsPresenter::stopSound()
{
- this->audioModel->stop(currentToken, nullptr);
+ this->audioModel->stop({});
+ }
+ void AlarmSettingsPresenter::exitWithoutSave()
+ {
+ model->getAlarmVolume().restoreDefault();
}
} // namespace app::bell_settings
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/AlarmSettingsPresenter.hpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/AlarmSettingsPresenter.hpp +2 -1
@@ 37,6 37,7 @@ namespace app::bell_settings
virtual auto saveData() -> void = 0;
virtual auto loadData() -> void = 0;
virtual auto eraseProviderData() -> void = 0;
+ virtual void exitWithoutSave() = 0;
};
};
@@ 52,6 53,7 @@ namespace app::bell_settings
auto saveData() -> void override;
auto loadData() -> void override;
auto eraseProviderData() -> void override;
+ void exitWithoutSave() override;
private:
void stopSound();
@@ 60,6 62,5 @@ namespace app::bell_settings
std::unique_ptr<AbstractAlarmSettingsModel> model;
std::unique_ptr<AbstractAudioModel> audioModel;
std::unique_ptr<AbstractSoundsRepository> soundsRepository;
- audio::Token currentToken;
};
} // 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 -17
@@ 13,22 13,11 @@ namespace app::bell_settings
: provider(std::move(provider)),
model(std::move(model)), audioModel{std::move(audioModel)}, soundsRepository{std::move(soundsRepository)}
{
-
- 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;
- };
-
- auto playSound = [this, playResponseCb](const UTF8 &val) {
+ auto playSound = [this](const UTF8 &val) {
currentSoundPath = val;
this->audioModel->play(this->soundsRepository->titleToPath(currentSoundPath).value_or(""),
- playResponseCb,
- AbstractAudioModel::PlaybackType::PreWakeup);
+ AbstractAudioModel::PlaybackType::PreWakeup,
+ {});
};
this->provider->onExit = [this]() { getView()->exit(); };
@@ 38,9 27,9 @@ namespace app::bell_settings
this->provider->onToneChange = playSound;
this->provider->onVolumeEnter = playSound;
- this->provider->onVolumeExit = [this](const auto &) { this->audioModel->stop(currentToken, nullptr); };
+ this->provider->onVolumeExit = [this](const auto &) { this->stopSound(); };
this->provider->onVolumeChange = [this, playSound](const auto &val) {
- this->audioModel->setVolume(val, AbstractAudioModel::PlaybackType::PreWakeup);
+ this->audioModel->setVolume(val, AbstractAudioModel::PlaybackType::PreWakeup, {});
playSound(currentSoundPath);
};
}
@@ 70,6 59,10 @@ namespace app::bell_settings
}
void PrewakeUpWindowPresenter::stopSound()
{
- this->audioModel->stop(currentToken, nullptr);
+ this->audioModel->stop({});
+ }
+ void PrewakeUpWindowPresenter::exitWithoutSave()
+ {
+ model->getChimeVolume().restoreDefault();
}
} // namespace app::bell_settings
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.hpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.hpp +2 -1
@@ 37,6 37,7 @@ namespace app::bell_settings
virtual auto saveData() -> void = 0;
virtual auto loadData() -> void = 0;
virtual auto eraseProviderData() -> void = 0;
+ virtual void exitWithoutSave() = 0;
};
};
@@ 52,6 53,7 @@ namespace app::bell_settings
auto saveData() -> void override;
auto loadData() -> void override;
auto eraseProviderData() -> void override;
+ void exitWithoutSave() override;
private:
void stopSound();
@@ 60,7 62,6 @@ namespace app::bell_settings
std::unique_ptr<AbstractPrewakeUpSettingsModel> model;
std::unique_ptr<AbstractAudioModel> audioModel;
std::unique_ptr<AbstractSoundsRepository> soundsRepository;
- audio::Token currentToken;
UTF8 currentSoundPath;
};
} // namespace app::bell_settings
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/SnoozePresenter.cpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/SnoozePresenter.cpp +10 -15
@@ 14,21 14,11 @@ namespace app::bell_settings
: provider{provider}, snoozeSettingsModel{std::move(snoozeSettingsModel)}, audioModel{std::move(audioModel)},
soundsRepository{std::move(soundsRepository)}
{
- 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;
- };
-
- auto playSound = [this, playResponseCb](const UTF8 &val) {
+ auto playSound = [this](const UTF8 &val) {
currentSoundPath = val;
this->audioModel->play(this->soundsRepository->titleToPath(currentSoundPath).value_or(""),
- playResponseCb,
- AbstractAudioModel::PlaybackType::Chime);
+ AbstractAudioModel::PlaybackType::Snooze,
+ {});
};
this->provider->onExit = [this]() { getView()->exit(); };
@@ 38,8 28,9 @@ namespace app::bell_settings
this->provider->onToneChange = playSound;
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::Chime);
+ this->audioModel->setVolume(val, AbstractAudioModel::PlaybackType::Snooze, {});
playSound(currentSoundPath);
};
}
@@ 65,10 56,14 @@ namespace app::bell_settings
}
void SnoozePresenter::stopSound()
{
- audioModel->stop(currentToken, nullptr);
+ audioModel->stop({});
}
void SnoozePresenter::eraseProviderData()
{
provider->clearData();
}
+ void SnoozePresenter::exitWithoutSave()
+ {
+ snoozeSettingsModel->getSnoozeChimeVolume().restoreDefault();
+ }
} // namespace app::bell_settings
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
@@ 33,6 33,7 @@ namespace app::bell_settings
virtual void saveData() = 0;
virtual void loadData() = 0;
virtual void eraseProviderData() = 0;
+ virtual void exitWithoutSave() = 0;
};
class SnoozePresenter : public AbstractSnoozePresenter
@@ 46,6 47,7 @@ namespace app::bell_settings
void saveData() override;
void loadData() override;
void eraseProviderData() override;
+ void exitWithoutSave() override;
private:
void stopSound();
@@ 54,8 56,6 @@ namespace app::bell_settings
std::unique_ptr<AbstractSnoozeSettingsModel> snoozeSettingsModel;
std::unique_ptr<AbstractAudioModel> audioModel;
std::unique_ptr<AbstractSoundsRepository> soundsRepository;
-
- audio::Token currentToken;
UTF8 currentSoundPath;
};
} // namespace app::bell_settings
M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsBedtimeToneWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/BellSettingsBedtimeToneWindow.cpp +3 -0
@@ 51,6 51,9 @@ namespace gui
exit();
return true;
}
+ if (inputEvent.isShortRelease(KeyCode::KEY_RF)) {
+ presenter->exitWithoutSave();
+ }
return AppWindow::onInput(inputEvent);
}
M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsSnoozeWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsSnoozeWindow.cpp +5 -0
@@ 50,6 50,11 @@ namespace gui
exit();
return true;
}
+
+ if (inputEvent.isShortRelease(KeyCode::KEY_RF)) {
+ presenter->exitWithoutSave();
+ }
+
return AppWindow::onInput(inputEvent);
}
M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsWindow.cpp +3 -0
@@ 55,6 55,9 @@ namespace gui
exit();
return true;
}
+ if (inputEvent.isShortRelease(KeyCode::KEY_RF)) {
+ presenter->exitWithoutSave();
+ }
return AppWindow::onInput(inputEvent);
}
M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsPrewakeUpWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsPrewakeUpWindow.cpp +3 -0
@@ 54,6 54,9 @@ namespace gui
exit();
return true;
}
+ if (inputEvent.isShortRelease(KeyCode::KEY_RF)) {
+ presenter->exitWithoutSave();
+ }
return AppWindow::onInput(inputEvent);
}
M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +1 -0
@@ 79,6 79,7 @@ target_link_libraries(application-bell-common
PRIVATE
bell::app-main
bell::app-alarm
+ bell::audio
module-gui
bell::db
)
M products/BellHybrid/apps/common/include/common/models/AbstractAudioModel.hpp => products/BellHybrid/apps/common/include/common/models/AbstractAudioModel.hpp +17 -16
@@ 3,40 3,41 @@
#pragma once
-#include <Audio/AudioCommon.hpp>
+#include <module-audio/Audio/AudioCommon.hpp>
#include <string>
#include <functional>
+#include <optional>
namespace app
{
- using AlarmModelReadyHandler = std::function<void()>;
-
class AbstractAudioModel
{
public:
/// 0-10 range
- using Volume = std::uint8_t;
-
- using OnPlayCallback = std::function<void(audio::RetCode retCode, audio::Token token)>;
- using OnStopCallback = OnPlayCallback;
- using OnPauseCallback = OnPlayCallback;
- using OnResumeCallback = OnPlayCallback;
+ 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)>;
enum class PlaybackType
{
- Chime,
+ Multimedia,
+ Snooze,
Alarm,
PreWakeup,
Bedtime
};
- virtual ~AbstractAudioModel() noexcept = default;
- virtual void setVolume(Volume volume, PlaybackType playbackType) = 0;
- virtual bool play(const std::string &filePath, const OnPlayCallback &callback, PlaybackType type) = 0;
- virtual bool pause(const audio::Token &token, const OnPauseCallback &callback) = 0;
- virtual bool resume(const audio::Token &token, const OnResumeCallback &callback) = 0;
- virtual bool stop(const audio::Token &token, const OnStopCallback &callback) = 0;
+ virtual ~AbstractAudioModel() noexcept = default;
+ virtual void setVolume(Volume volume, PlaybackType playbackType, OnStateChangeCallback &&callback) = 0;
+ virtual std::optional<Volume> getVolume(PlaybackType playbackType) = 0;
+ virtual void getVolume(PlaybackType playbackType, OnGetValueCallback &&callback) = 0;
+ virtual void play(const std::string &filePath, PlaybackType type, OnStateChangeCallback &&callback) = 0;
+ virtual void stop(OnStateChangeCallback &&callback) = 0;
+ virtual void pause(OnStateChangeCallback &&callback) = 0;
+ virtual void resume(OnStateChangeCallback &&callback) = 0;
};
} // namespace app
M products/BellHybrid/apps/common/include/common/models/AbstractSettingsModel.hpp => products/BellHybrid/apps/common/include/common/models/AbstractSettingsModel.hpp +44 -0
@@ 3,6 3,13 @@
#pragma once
+#include <apps-common/AsyncTask.hpp>
+
+namespace app
+{
+ class ApplicationCommon;
+}
+
namespace gui
{
template <class ValueType> class AbstractSettingsModel
@@ 12,5 19,42 @@ namespace gui
virtual void setValue(ValueType value) = 0;
virtual ValueType getValue() const = 0;
+ virtual void restoreDefault()
+ {}
+ };
+
+ template <typename ValueT> class AsyncSettingsAdapter : public AbstractSettingsModel<ValueT>
+ {
+ public:
+ std::function<void(ValueT)> onReady;
+
+ void setValue(ValueT value) final
+ {
+ onSet(value);
+ }
+
+ ValueT getValue() const final
+ {
+ return currentValue;
+ }
+
+ void restoreDefault() final
+ {
+ onSet(defaultValue);
+ }
+
+ protected:
+ std::function<void(ValueT)> onSet;
+
+ void onUpdate(ValueT value)
+ {
+ currentValue = value;
+ defaultValue = currentValue;
+ onReady(currentValue);
+ }
+
+ private:
+ ValueT currentValue{};
+ ValueT defaultValue{};
};
} // namespace gui
M products/BellHybrid/apps/common/include/common/models/AudioModel.hpp => products/BellHybrid/apps/common/include/common/models/AudioModel.hpp +9 -13
@@ 4,28 4,24 @@
#pragma once
#include "AbstractAudioModel.hpp"
-#include <apps-common/AudioOperations.hpp>
+#include <apps-common/AsyncTask.hpp>
namespace app
{
- class ApplicationCommon;
-}
-
-namespace app
-{
- class AudioModel : public AbstractAudioModel
+ class AudioModel : public AbstractAudioModel, public app::AsyncCallbackReceiver
{
public:
explicit AudioModel(ApplicationCommon *app);
- void setVolume(Volume volume, PlaybackType playbackType) override;
- bool play(const std::string &filePath, const OnPlayCallback &callback, PlaybackType type) override;
- bool pause(const audio::Token &token, const OnPauseCallback &callback) override;
- bool resume(const audio::Token &token, const OnResumeCallback &callback) override;
- bool stop(const audio::Token &token, const OnStopCallback &callback) override;
+ void setVolume(Volume volume, PlaybackType playbackType, OnStateChangeCallback &&callback) override;
+ std::optional<Volume> getVolume(PlaybackType playbackType) override;
+ void getVolume(PlaybackType playbackType, OnGetValueCallback &&callback) override;
+ void play(const std::string &filePath, PlaybackType type, OnStateChangeCallback &&callback) override;
+ void stop(OnStateChangeCallback &&callback) override;
+ void pause(OnStateChangeCallback &&callback) override;
+ void resume(OnStateChangeCallback &&callback) override;
private:
ApplicationCommon *app{};
- AsyncAudioOperations asyncAudioOperations;
};
} // namespace app
M products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp => products/BellHybrid/apps/common/include/common/models/BedtimeModel.hpp +14 -6
@@ 6,13 6,14 @@
#include "AbstractBedtimeModel.hpp"
#include "SettingsModel.hpp"
#include <Service/Service.hpp>
+#include <common/models/AudioModel.hpp>
+#include <ApplicationCommon.hpp>
#include <ctime>
namespace app::bell_bedtime
{
- inline constexpr auto DEFAULT_BEDTIME_TIME = "21:00";
- inline constexpr auto DEFAULT_BEDTIME_TONE = "Evening Horizon";
- inline constexpr auto DEFAULT_BEDTIME_VOLUME = 1;
+ inline constexpr auto DEFAULT_BEDTIME_TIME = "21:00";
+ inline constexpr auto DEFAULT_BEDTIME_TONE = "Evening Horizon";
class BedtimeOnOffModel : public gui::SettingsModel<bool>
{
@@ 36,13 37,18 @@ namespace app::bell_bedtime
auto getValue() const -> time_t override;
};
- class BedtimeVolumeModel : public gui::SettingsModel<std::uint8_t>
+ class BedtimeVolumeModel : public gui::AbstractSettingsModel<std::uint8_t>
{
public:
- using SettingsModel::SettingsModel;
+ explicit BedtimeVolumeModel(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;
};
class AlarmToneModel : public gui::SettingsModel<UTF8>
@@ 61,10 67,11 @@ namespace app::bell_bedtime
explicit BedtimeModel(sys::Service *app)
{
+ audioModel = std::make_unique<AudioModel>(static_cast<ApplicationCommon *>(app));
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>(app);
+ bedtimeVolume = std::make_unique<bell_bedtime::BedtimeVolumeModel>(*audioModel);
}
gui::AbstractSettingsModel<bool> &getBedtimeOnOff() override
{
@@ 86,6 93,7 @@ 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 +143 -18
@@ 2,7 2,9 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "models/AudioModel.hpp"
-#include <service-audio/AudioServiceAPI.hpp>
+
+#include <ApplicationCommon.hpp>
+#include <audio/AudioMessage.hpp>
namespace
{
@@ 10,45 12,168 @@ namespace
{
using Type = app::AbstractAudioModel::PlaybackType;
switch (type) {
+ case Type::Multimedia:
+ return audio::PlaybackType::Multimedia;
case Type::Alarm:
return audio::PlaybackType::Alarm;
- case Type::Chime:
- return audio::PlaybackType::Alarm;
+ case Type::Snooze:
+ return audio::PlaybackType::Snooze;
case Type::PreWakeup:
- return audio::PlaybackType::Alarm;
+ return audio::PlaybackType::PreWakeUp;
case Type::Bedtime:
- return audio::PlaybackType::Alarm;
+ return audio::PlaybackType::Bedtime;
default:
return audio::PlaybackType::Alarm;
}
}
+
+ void reportError(const char *prefix, audio::RetCode code)
+ {
+ if (code != audio::RetCode::Success) {
+ LOG_ERROR("%s request error: %s", prefix, magic_enum::enum_name(code).data());
+ }
+ }
+
+ auto SendAudioRequest(sys::Service *serv, std::shared_ptr<service::AudioMessage> msg)
+ {
+ auto msgType = static_cast<int>(msg->type);
+ auto ret = serv->bus.sendUnicastSync(msg, service::audioServiceName, sys::BusProxy::defaultTimeout);
+ if (ret.first == sys::ReturnCodes::Success) {
+ if (auto resp = std::dynamic_pointer_cast<service::AudioResponseMessage>(ret.second)) {
+ return resp;
+ }
+ LOG_ERROR("msgType %d - not AudioResponseMessage", msgType);
+ return std::make_shared<service::AudioResponseMessage>(audio::RetCode::Failed);
+ }
+ LOG_ERROR("Command %d Failed with %d error", msgType, static_cast<int>(ret.first));
+ return std::make_shared<service::AudioResponseMessage>(audio::RetCode::Failed);
+ }
+
} // namespace
namespace app
{
- AudioModel::AudioModel(ApplicationCommon *app) : app{app}, asyncAudioOperations{app}
+ AudioModel::AudioModel(ApplicationCommon *app) : app::AsyncCallbackReceiver{app}, app{app}
{}
- void AudioModel::setVolume(AbstractAudioModel::Volume volume, PlaybackType playbackType)
+ void AudioModel::play(const std::string &filePath, PlaybackType type, OnStateChangeCallback &&callback)
+ {
+ 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) {
+ auto result = dynamic_cast<service::AudioStartPlaybackResponse *>(response);
+ if (result == nullptr) {
+ return false;
+ }
+ if (_callback) {
+ _callback(result->retCode);
+ }
+ reportError("play", result->retCode);
+
+ return true;
+ };
+ task->execute(app, this, std::move(cb));
+ }
+
+ void AudioModel::stop(OnStateChangeCallback &&callback)
+ {
+ auto msg = std::make_unique<service::AudioStopRequest>();
+ auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::audioServiceName);
+ auto cb = [_callback = callback](auto response) {
+ auto result = dynamic_cast<service::AudioStopResponse *>(response);
+ if (result == nullptr) {
+ return false;
+ }
+ if (_callback) {
+ _callback(result->retCode);
+ }
+ reportError("stop", result->retCode);
+ return true;
+ };
+ task->execute(app, this, std::move(cb));
+ }
+
+ void AudioModel::setVolume(AbstractAudioModel::Volume volume,
+ PlaybackType playbackType,
+ OnStateChangeCallback &&callback)
{
- AudioServiceAPI::SetVolume(app, volume, convertPlaybackType(playbackType));
+ auto msg = std::make_unique<service::AudioSetVolume>(convertPlaybackType(playbackType), std::to_string(volume));
+ auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::audioServiceName);
+ auto cb = [_callback = callback](auto response) {
+ auto result = dynamic_cast<service::AudioResponseMessage *>(response);
+ if (result == nullptr) {
+ return false;
+ }
+ if (_callback) {
+ _callback(result->retCode);
+ }
+ reportError("setVolume", result->retCode);
+ return true;
+ };
+ task->execute(app, this, std::move(cb));
}
- bool AudioModel::play(const std::string &filePath,
- const AbstractAudioOperations::OnPlayCallback &callback,
- PlaybackType type)
+ void AudioModel::pause(OnStateChangeCallback &&callback)
{
- return asyncAudioOperations.play(filePath, callback, convertPlaybackType(type));
+ auto msg = std::make_unique<service::AudioPauseRequest>();
+ auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::audioServiceName);
+ auto cb = [_callback = callback](auto response) {
+ auto result = dynamic_cast<service::AudioResponseMessage *>(response);
+ if (result == nullptr) {
+ return false;
+ }
+ if (_callback) {
+ _callback(result->retCode);
+ }
+
+ reportError("pause", result->retCode);
+ return true;
+ };
+ task->execute(app, this, std::move(cb));
}
- bool AudioModel::pause(const audio::Token &token, const AbstractAudioOperations::OnPauseCallback &callback)
+ void AudioModel::resume(OnStateChangeCallback &&callback)
{
- return asyncAudioOperations.pause(token, callback);
+ auto msg = std::make_unique<service::AudioResumeRequest>();
+ auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::audioServiceName);
+ auto cb = [_callback = callback](auto response) {
+ auto result = dynamic_cast<service::AudioResponseMessage *>(response);
+ if (result == nullptr) {
+ return false;
+ }
+ if (_callback) {
+ _callback(result->retCode);
+ }
+ reportError("resume", result->retCode);
+ return true;
+ };
+ task->execute(app, this, std::move(cb));
}
- bool AudioModel::resume(const audio::Token &token, const AbstractAudioOperations::OnResumeCallback &callback)
+ void AudioModel::getVolume(AbstractAudioModel::PlaybackType playbackType,
+ AbstractAudioModel::OnGetValueCallback &&callback)
{
- return asyncAudioOperations.resume(token, callback);
+ auto msg = std::make_unique<service::AudioGetVolume>(convertPlaybackType(playbackType));
+ auto task = app::AsyncRequest::createFromMessage(std::move(msg), service::audioServiceName);
+ auto cb = [_callback = callback](auto response) {
+ auto result = dynamic_cast<service::AudioResponseMessage *>(response);
+ if (result == nullptr) {
+ return false;
+ }
+ if (_callback) {
+ _callback(result->retCode, utils::getNumericValue<AbstractAudioModel::Volume>(result->val));
+ }
+
+ reportError("getVolume", result->retCode);
+ return true;
+ };
+ task->execute(app, this, std::move(cb));
}
- bool AudioModel::stop(const audio::Token &token, const AbstractAudioOperations::OnStopCallback &callback)
+ std::optional<AbstractAudioModel::Volume> AudioModel::getVolume(AbstractAudioModel::PlaybackType playbackType)
{
- return asyncAudioOperations.stop(token, callback);
+ auto msg = std::make_shared<service::AudioGetVolume>(convertPlaybackType(playbackType));
+ const auto ret = SendAudioRequest(app, msg);
+ if (ret) {
+ return utils::getNumericValue<audio::Volume>(ret->val);
+ }
+
+ return {};
}
} // namespace app
M products/BellHybrid/apps/common/src/models/BedtimeModel.cpp => products/BellHybrid/apps/common/src/models/BedtimeModel.cpp +10 -8
@@ 78,18 78,20 @@ namespace app::bell_bedtime
void BedtimeVolumeModel::setValue(std::uint8_t value)
{
const auto valStr = std::to_string(value);
- settings.setValue(bell::settings::Bedtime::volume, valStr, settings::SettingsScope::Global);
+ audioModel.setVolume(value, AbstractAudioModel::PlaybackType::Bedtime, {});
}
auto BedtimeVolumeModel::getValue() const -> std::uint8_t
{
- const auto str = settings.getValue(bell::settings::Bedtime::volume, settings::SettingsScope::Global);
- try {
- return std::stoi(str);
- }
- catch (const std::invalid_argument &) {
- return DEFAULT_BEDTIME_VOLUME;
- }
+ return defaultValue;
+ }
+ BedtimeVolumeModel::BedtimeVolumeModel(AbstractAudioModel &audioModel) : audioModel{audioModel}
+ {
+ defaultValue = audioModel.getVolume(AbstractAudioModel::PlaybackType::Bedtime).value_or(0);
+ }
+ void BedtimeVolumeModel::restoreDefault()
+ {
+ setValue(defaultValue);
}
} // namespace app::bell_bedtime
M => +3 -3
@@ 1,13 1,14 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <audio/AudioMessage.hpp>
#include <apps-common/popups/Popups.hpp>
#include <apps-common/popups/data/PopupRequestParams.hpp>
#include <common/popups/BedtimeNotificationWindow.hpp>
#include <gui/input/InputEvent.hpp>
#include <gui/widgets/Icon.hpp>
#include <i18n/i18n.hpp>
#include <purefs/filesystem_paths.hpp>
#include <service-audio/AudioServiceAPI.hpp>
#include <service-appmgr/Controller.hpp>
namespace gui
@@ 72,8 73,7 @@ namespace gui
void BedtimeNotificationWindow::onClose(CloseReason reason)
{
auto stopPlaybackVec = std::vector<audio::PlaybackType>({audio::PlaybackType::Multimedia});
AudioServiceAPI::Stop(app, stopPlaybackVec);
application->bus.sendUnicast(std::make_shared<service::AudioStopRequest>(), service::audioServiceName);
}
} /* namespace gui */
M products/BellHybrid/services/CMakeLists.txt => products/BellHybrid/services/CMakeLists.txt +1 -0
@@ 5,3 5,4 @@ add_subdirectory(evtmgr)
add_subdirectory(db)
add_subdirectory(desktop)
add_subdirectory(time)
+add_subdirectory(audio)
A products/BellHybrid/services/audio/CMakeLists.txt => products/BellHybrid/services/audio/CMakeLists.txt +33 -0
@@ 0,0 1,33 @@
+# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+add_library(bell-audio STATIC)
+add_library(bell::audio ALIAS bell-audio)
+
+target_include_directories(bell-audio
+ PRIVATE
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/audio>
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+ )
+
+target_sources(bell-audio
+ PRIVATE
+ ServiceAudio.cpp
+
+ PUBLIC
+ include/audio/AudioMessage.hpp
+ include/audio/ServiceAudio.hpp
+
+ )
+
+
+target_link_libraries(bell-audio
+ PRIVATE
+ log
+ module-utils
+ service-db
+ PUBLIC
+ messagetype
+ module-audio
+ module-sys
+ )
A products/BellHybrid/services/audio/ServiceAudio.cpp => products/BellHybrid/services/audio/ServiceAudio.cpp +307 -0
@@ 0,0 1,307 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ServiceAudio.hpp"
+#include "system/Constants.hpp"
+
+#include <audio/AudioMessage.hpp>
+#include <service-db/Settings.hpp>
+#include <system/messages/SentinelRegistrationMessage.hpp>
+
+namespace
+{
+ constexpr auto stackSize = 1024 * 4;
+ constexpr auto defaultVolume = "5";
+ constexpr audio::Volume maxInVolume = 10;
+ constexpr audio::Volume minVolume = 0;
+ constexpr auto profileType = audio::Profile::Type::PlaybackLoudspeaker;
+ namespace initializer
+ {
+ using namespace audio;
+ // clang-format off
+ static constexpr std::initializer_list<std::pair<audio::DbPathElement, const char *>> values{
+ {DbPathElement{Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackLoudspeaker},defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackLoudspeaker},defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackLoudspeaker}, defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::Bedtime, Profile::Type::PlaybackLoudspeaker}, defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::PreWakeUp, Profile::Type::PlaybackLoudspeaker},defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::Snooze, 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},
+ {DbPathElement{Setting::Volume, PlaybackType::Meditation, Profile::Type::PlaybackBluetoothA2DP},defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackHeadphones},defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackBluetoothA2DP},defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackHeadphones}, defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::Alarm, Profile::Type::PlaybackBluetoothA2DP}, defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::Bedtime, Profile::Type::PlaybackHeadphones}, defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::Bedtime, Profile::Type::PlaybackBluetoothA2DP},defaultVolume},
+ {DbPathElement{Setting::Volume, PlaybackType::PreWakeUp, Profile::Type::PlaybackHeadphones}, defaultVolume},
+ {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},
+ };
+ // clang-format on
+ } // namespace initializer
+
+ class AudioInternalEOFNotificationMessage : public service::AudioNotificationMessage
+ {
+ public:
+ explicit AudioInternalEOFNotificationMessage(audio::Token token) : AudioNotificationMessage(token)
+ {}
+ };
+} // namespace
+
+namespace service
+{
+ Audio::Audio()
+ : sys::Service(audioServiceName, "", stackSize, sys::ServicePriority::Idle),
+ audioMux([this](auto... params) { return this->AudioServicesCallback(params...); }),
+ cpuSentinel(std::make_shared<sys::CpuSentinel>(audioServiceName, this)),
+ settingsProvider(std::make_unique<settings::Settings>())
+ {
+ LOG_INFO("%s Initializing", audioServiceName);
+ bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
+
+ auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
+ bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);
+
+ connect(typeid(AudioStartPlaybackRequest), [this](sys::Message *msg) -> sys::MessagePointer {
+ auto *msgl = static_cast<AudioStartPlaybackRequest *>(msg);
+ return handleStart(audio::Operation::Type::Playback, msgl->fileName.c_str(), msgl->playbackType);
+ });
+
+ connect(typeid(AudioInternalEOFNotificationMessage), [this](sys::Message *msg) -> sys::MessagePointer {
+ auto *msgl = static_cast<AudioInternalEOFNotificationMessage *>(msg);
+ handleEOF(msgl->token);
+ return sys::msgHandled();
+ });
+
+ connect(typeid(AudioStopRequest), [this](sys::Message *msg) -> sys::MessagePointer {
+ auto *msgl = static_cast<AudioStopRequest *>(msg);
+ return handleStop(msgl->stopVec, msgl->token);
+ });
+
+ connect(typeid(AudioSetVolume), [this](sys::Message *msg) -> sys::MessagePointer {
+ auto *msgl = static_cast<AudioSetVolume *>(msg);
+ return handleSetVolume(msgl->playbackType, msgl->val);
+ });
+
+ connect(typeid(AudioGetVolume), [this](sys::Message *msg) -> sys::MessagePointer {
+ auto *msgl = static_cast<AudioGetVolume *>(msg);
+ return handleGetVolume(msgl->playbackType);
+ });
+
+ connect(typeid(AudioPauseRequest), [this](sys::Message *msg) -> sys::MessagePointer { return handlePause(); });
+
+ connect(typeid(AudioResumeRequest),
+ [this](sys::Message *msg) -> sys::MessagePointer { return handleResume(); });
+ }
+ sys::MessagePointer Audio::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
+ {
+ return sys::msgNotHandled();
+ }
+ sys::ReturnCodes Audio::InitHandler()
+ {
+ settingsProvider->init(service::ServiceProxy(weak_from_this()));
+ initializeDatabase();
+
+ return sys::ReturnCodes::Success;
+ }
+ sys::ReturnCodes Audio::DeinitHandler()
+ {
+ return sys::ReturnCodes::Success;
+ }
+ void Audio::ProcessCloseReason([[maybe_unused]] sys::CloseReason closeReason)
+ {
+ if (const auto &activeInputOpt = audioMux.GetActiveInput(); activeInputOpt.has_value()) {
+ const auto activeInput = activeInputOpt.value();
+ activeInput->audio->Stop();
+ }
+ sendCloseReadyMessage(this);
+ }
+ auto Audio::handleStart(const audio::Operation::Type opType,
+ const std::string &fileName,
+ const audio::PlaybackType &playbackType) -> std::unique_ptr<AudioResponseMessage>
+ {
+ auto retCode = audio::RetCode::Failed;
+ auto retToken = audio::Token::MakeBadToken();
+
+ auto AudioStart = [&](auto &input) {
+ if (input) {
+ for (auto &audioInput : audioMux.GetAllInputs()) {
+ stopInput(&audioInput);
+ }
+ retToken = audioMux.ResetInput(input);
+
+ try {
+ retCode = (*input)->audio->Start(opType, retToken, fileName.c_str(), playbackType);
+ }
+ catch (const audio::AudioInitException &audioException) {
+ retCode = audio::RetCode::FailedToAllocateMemory;
+ }
+ }
+ };
+ auto input = audioMux.GetPlaybackInput(playbackType);
+ AudioStart(input);
+
+ return std::make_unique<AudioStartPlaybackResponse>(retCode, retToken);
+ }
+ auto Audio::handleStop(const std::vector<audio::PlaybackType> &stopTypes, const audio::Token &token)
+ -> std::unique_ptr<AudioResponseMessage>
+ {
+ std::vector<std::pair<audio::Token, audio::RetCode>> retCodes;
+
+ for (auto &input : audioMux.GetAllInputs()) {
+ auto t = input.token;
+ retCodes.emplace_back(t, stopInput(&input));
+ }
+
+ // on failure return first false code
+ auto it = std::find_if_not(
+ retCodes.begin(), retCodes.end(), [](auto p) { return p.second == audio::RetCode::Success; });
+ if (it != retCodes.end()) {
+ return std::make_unique<AudioStopResponse>(it->second, it->first);
+ }
+
+ return std::make_unique<AudioStopResponse>(audio::RetCode::Success, token);
+ }
+ auto Audio::stopInput(audio::AudioMux::Input *input, Audio::StopReason stopReason) -> audio::RetCode
+ {
+ if (input->audio->GetCurrentState() == audio::Audio::State::Idle) {
+ return audio::RetCode::Success;
+ }
+ const auto retCode = input->audio->Stop();
+ // Send notification that audio file was stopped
+ std::shared_ptr<AudioNotificationMessage> msg;
+ if (stopReason == StopReason::Eof) {
+ msg = std::make_shared<AudioEOFNotification>(input->token);
+ }
+ else {
+ msg = std::make_shared<AudioStopNotification>(input->token);
+ }
+ bus.sendMulticast(std::move(msg), sys::BusChannel::ServiceAudioNotifications);
+ audioMux.ResetInput(input);
+ return retCode;
+ }
+ constexpr auto Audio::shouldLoop(const std::optional<audio::PlaybackType> &type) const -> bool
+ {
+ return type == audio::PlaybackType::Alarm;
+ }
+ auto Audio::isBusy() const -> bool
+ {
+ const auto &inputs = audioMux.GetAllInputs();
+ return std::any_of(inputs.begin(), inputs.end(), [](const auto &input) {
+ return input.audio->GetCurrentState() != audio::Audio::State::Idle;
+ });
+ }
+ void Audio::handleEOF(const audio::Token &token)
+ {
+ if (const auto input = audioMux.GetInput(token); input) {
+ if (shouldLoop((*input)->audio->GetCurrentOperationPlaybackType())) {
+ (*input)->audio->Start();
+ if ((*input)->audio->IsMuted()) {
+ (*input)->audio->Mute();
+ }
+ }
+ else {
+ stopInput(*input, StopReason::Eof);
+ }
+ }
+ }
+ auto Audio::AudioServicesCallback(const sys::Message *msg) -> std::optional<std::string>
+ {
+ std::optional<std::string> ret;
+ if (const auto *eof = dynamic_cast<const AudioServiceMessage::EndOfFile *>(msg); eof) {
+ bus.sendUnicast(std::make_shared<AudioInternalEOFNotificationMessage>(eof->GetToken()), audioServiceName);
+ }
+ else if (const auto *dbReq = dynamic_cast<const AudioServiceMessage::DbRequest *>(msg); dbReq) {
+ auto selectedPlayback = dbReq->playback;
+ auto selectedProfile = dbReq->profile;
+ if (const auto result =
+ settingsProvider->getValue(dbPath(dbReq->setting, selectedPlayback, selectedProfile));
+ not result.empty()) {
+ ret.emplace(result);
+ }
+ }
+ else {
+ LOG_DEBUG("Message received but not handled - no effect.");
+ }
+
+ return ret;
+ }
+ auto Audio::handleSetVolume(const audio::PlaybackType &playbackType, const std::string &value)
+ -> std::unique_ptr<AudioResponseMessage>
+ {
+ constexpr auto setting = audio::Setting::Volume;
+ auto retCode = audio::RetCode::Success;
+ const auto clampedValue = std::clamp(utils::getNumericValue<audio::Volume>(value), minVolume, maxInVolume);
+
+ if (const auto activeInput = audioMux.GetActiveInput(); activeInput) {
+ if (activeInput) {
+ retCode = activeInput.value()->audio->SetOutputVolume(clampedValue);
+ }
+ }
+
+ if (retCode == audio::RetCode::Success) {
+ settingsProvider->setValue(dbPath(setting, playbackType, profileType), std::to_string(clampedValue));
+ }
+ return std::make_unique<AudioResponseMessage>(retCode);
+ }
+ auto Audio::handleGetVolume(const audio::PlaybackType &playbackType) -> std::unique_ptr<AudioResponseMessage>
+ {
+ constexpr auto setting = audio::Setting::Volume;
+
+ const auto path = dbPath(setting, playbackType, profileType);
+ if (const auto value = settingsProvider->getValue(path); not value.empty()) {
+ return std::make_unique<AudioResponseMessage>(audio::RetCode::Success, value);
+ }
+
+ return std::make_unique<AudioResponseMessage>(audio::RetCode::Failed);
+ }
+ sys::ReturnCodes Audio::SwitchPowerModeHandler([[maybe_unused]] const sys::ServicePowerMode mode)
+ {
+ return sys::ReturnCodes::Success;
+ }
+ auto Audio::handlePause() -> std::unique_ptr<AudioResponseMessage>
+ {
+ auto retCode = audio::RetCode::InvokedInIncorrectState;
+ if (const auto activeInput = audioMux.GetActiveInput(); activeInput) {
+ auto playbackType = (*activeInput)->audio->GetCurrentOperationPlaybackType();
+ if (isResumable(playbackType)) {
+ retCode = activeInput.value()->audio->Pause();
+ }
+ else {
+ retCode = audio::RetCode::UnsupportedEvent;
+ }
+ }
+ return std::make_unique<AudioResponseMessage>(retCode);
+ }
+ auto Audio::handleResume() -> std::unique_ptr<AudioResponseMessage>
+ {
+ auto retCode = audio::RetCode::InvokedInIncorrectState;
+ if (const auto activeInput = audioMux.GetActiveInput();
+ activeInput && activeInput.value()->audio->GetCurrentOperationState() == audio::Operation::State::Paused) {
+ retCode = activeInput.value()->audio->Resume();
+ }
+ return std::make_unique<AudioResponseMessage>(retCode);
+ }
+ constexpr auto Audio::isResumable(audio::PlaybackType type) const -> bool
+ {
+ return type == audio::PlaybackType::Multimedia;
+ }
+ void Audio::manageCpuSentinel()
+ {
+ isBusy() ? cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_6)
+ : cpuSentinel->ReleaseMinimumFrequency();
+ }
+ void Audio::initializeDatabase()
+ {
+ for (const auto &entry : initializer::values) {
+ const auto path = dbPath(entry.first);
+ if (settingsProvider->getValue(path).empty()) {
+ settingsProvider->setValue(path, entry.second);
+ }
+ }
+ }
+} // namespace service
A products/BellHybrid/services/audio/include/audio/AudioMessage.hpp => products/BellHybrid/services/audio/include/audio/AudioMessage.hpp +141 -0
@@ 0,0 1,141 @@
+// 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 <Audio/AudioCommon.hpp>
+#include <MessageType.hpp>
+#include <Service/Message.hpp>
+
+#include <memory>
+#include <variant>
+
+namespace service
+{
+ inline constexpr auto audioServiceName = "ServiceAudio";
+
+ class AudioMessage : public sys::DataMessage
+ {
+ public:
+ AudioMessage() : sys::DataMessage(MessageType::AudioMessage)
+ {}
+ };
+
+ class AudioResponseMessage : public sys::ResponseMessage
+ {
+ public:
+ explicit AudioResponseMessage(audio::RetCode retCode = audio::RetCode::Success, const std::string &val = {})
+ : sys::ResponseMessage(), retCode(retCode), val(val)
+ {}
+
+ const audio::RetCode retCode = audio::RetCode::Success;
+ std::string val;
+ };
+
+ class AudioNotificationMessage : public AudioMessage
+ {
+ public:
+ explicit AudioNotificationMessage(audio::Token token) : token{token}
+ {}
+
+ const audio::Token token;
+ };
+
+ class AudioStopNotification : public AudioNotificationMessage
+ {
+ public:
+ explicit AudioStopNotification(audio::Token token) : AudioNotificationMessage{token}
+ {}
+ };
+
+ class AudioEOFNotification : public AudioNotificationMessage
+ {
+ public:
+ explicit AudioEOFNotification(audio::Token token) : AudioNotificationMessage{token}
+ {}
+ };
+
+ class AudioSettingsMessage : public AudioMessage
+ {
+ public:
+ AudioSettingsMessage(const audio::PlaybackType &playbackType, const std::string &val = {})
+ : AudioMessage{}, playbackType{playbackType}, val{val}
+ {}
+
+ audio::PlaybackType playbackType = audio::PlaybackType::None;
+ std::string val{};
+ };
+
+ class AudioGetVolume : public AudioSettingsMessage
+ {
+ public:
+ AudioGetVolume(const audio::PlaybackType &playbackType) : AudioSettingsMessage{playbackType}
+ {}
+ };
+
+ class AudioSetVolume : public AudioSettingsMessage
+ {
+ public:
+ AudioSetVolume(const audio::PlaybackType &playbackType, const std::string &val)
+ : AudioSettingsMessage{playbackType, val}
+ {}
+ };
+
+ class AudioStopRequest : public AudioMessage
+ {
+ public:
+ explicit AudioStopRequest(const std::vector<audio::PlaybackType> &stopVec = {}) : stopVec(stopVec)
+ {}
+
+ explicit AudioStopRequest(const audio::Token &token) : token(token)
+ {}
+
+ const std::vector<audio::PlaybackType> stopVec;
+ const audio::Token token;
+ };
+
+ class AudioStopResponse : public AudioResponseMessage
+ {
+ public:
+ AudioStopResponse(audio::RetCode retCode, const audio::Token &token)
+ : AudioResponseMessage(retCode), token(token)
+ {}
+
+ const audio::Token token;
+ };
+
+ class AudioStartPlaybackRequest : public AudioMessage
+ {
+ public:
+ AudioStartPlaybackRequest(const std::string &fileName, const audio::PlaybackType &playbackType)
+ : AudioMessage(), fileName(fileName), playbackType(playbackType)
+ {}
+
+ const std::string fileName;
+ const audio::PlaybackType playbackType;
+ };
+
+ class AudioStartPlaybackResponse : public AudioResponseMessage
+ {
+ public:
+ AudioStartPlaybackResponse(audio::RetCode retCode, const audio::Token &token)
+ : AudioResponseMessage(retCode), token(token)
+ {}
+
+ const audio::Token token;
+ };
+
+ class AudioPauseRequest : public AudioMessage
+ {
+ public:
+ AudioPauseRequest() : AudioMessage()
+ {}
+ };
+
+ class AudioResumeRequest : public AudioMessage
+ {
+ public:
+ AudioResumeRequest() : AudioMessage()
+ {}
+ };
+} // namespace service
A products/BellHybrid/services/audio/include/audio/ServiceAudio.hpp => products/BellHybrid/services/audio/include/audio/ServiceAudio.hpp +87 -0
@@ 0,0 1,87 @@
+// 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 "AudioMessage.hpp"
+#include <Audio/Audio.hpp>
+#include <Audio/AudioMux.hpp>
+#include <MessageType.hpp>
+#include <service-db/DBServiceName.hpp>
+#include <Service/Service.hpp>
+#include <SystemManager/CpuSentinel.hpp>
+
+#include <functional>
+
+namespace settings
+{
+ class Settings;
+}
+
+namespace service
+{
+ class Audio : public sys::Service
+ {
+ public:
+ Audio();
+
+ sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp = nullptr) final;
+ sys::ReturnCodes InitHandler() final;
+ sys::ReturnCodes DeinitHandler() final;
+ sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) final;
+ void ProcessCloseReason(sys::CloseReason closeReason) final;
+
+ private:
+ enum class StopReason
+ {
+ Eof,
+ Other
+ };
+
+ auto handleStart(audio::Operation::Type opType,
+ const std::string &fileName = {},
+ const audio::PlaybackType &playbackType = audio::PlaybackType::None)
+ -> std::unique_ptr<AudioResponseMessage>;
+ auto handleStop(const std::vector<audio::PlaybackType> &stopTypes, const audio::Token &token)
+ -> std::unique_ptr<AudioResponseMessage>;
+
+ auto handleSetVolume(const audio::PlaybackType &playbackType, const std::string &value)
+ -> std::unique_ptr<AudioResponseMessage>;
+ auto handleGetVolume(const audio::PlaybackType &playbackType) -> std::unique_ptr<AudioResponseMessage>;
+
+ auto handlePause() -> std::unique_ptr<AudioResponseMessage>;
+ auto handleResume() -> std::unique_ptr<AudioResponseMessage>;
+
+ void handleEOF(const audio::Token &token);
+
+ auto AudioServicesCallback(const sys::Message *msg) -> std::optional<std::string>;
+
+ auto stopInput(audio::AudioMux::Input *input, StopReason stopReason = StopReason::Other) -> audio::RetCode;
+
+ constexpr auto shouldLoop(const std::optional<audio::PlaybackType> &type) const -> bool;
+ constexpr auto isResumable(audio::PlaybackType type) const -> bool;
+ auto isBusy() const -> bool;
+
+ void manageCpuSentinel();
+ void initializeDatabase();
+
+ mutable audio::AudioMux audioMux;
+ std::shared_ptr<sys::CpuSentinel> cpuSentinel;
+ std::unique_ptr<settings::Settings> settingsProvider;
+ };
+
+} // namespace service
+
+namespace sys
+{
+ template <> struct ManifestTraits<service::Audio>
+ {
+ static auto GetManifest() -> ServiceManifest
+ {
+ ServiceManifest manifest;
+ manifest.name = service::audioServiceName;
+ manifest.dependencies = {service::name::db};
+ return manifest;
+ }
+ };
+} // namespace sys
M products/BellHybrid/services/db/include/db/SystemSettings.hpp => products/BellHybrid/services/db/include/db/SystemSettings.hpp +0 -4
@@ 15,19 15,16 @@ namespace bell::settings
constexpr inline auto length = "snooze_length";
constexpr inline auto interval = "snooze_interval";
constexpr inline auto tone = "snooze_tone";
- constexpr inline auto volume = "snooze_volume";
} // namespace Snooze
namespace PrewakeUp
{
constexpr inline auto duration = "prewake_up_duration";
constexpr inline auto tone = "prewake_up_tone";
- constexpr inline auto volume = "prewake_up_volume";
constexpr inline auto lightDuration = "prewake_up_light_duration";
} // namespace PrewakeUp
namespace Alarm
{
constexpr inline auto tone = "alarm_tone";
- constexpr inline auto volume = "alarm_volume";
constexpr inline auto lightActive = "alarm_light_active";
constexpr inline auto duration = "alarm_duration";
} // namespace Alarm
@@ 36,7 33,6 @@ namespace bell::settings
constexpr inline auto active = "bedtime_active";
constexpr inline auto time = "bedtime_time";
constexpr inline auto tone = "bedtime_tone";
- constexpr inline auto volume = "bedtime_volume";
constexpr inline auto duration = "bedtime_duration";
} // namespace Bedtime
}; // namespace bell::settings
M products/BellHybrid/services/evtmgr/CMakeLists.txt => products/BellHybrid/services/evtmgr/CMakeLists.txt +2 -0
@@ 12,6 12,7 @@ target_sources(evtmgr
internal/StaticData.hpp
screen-light-control/ScreenLightControl.cpp
backlight-handler/BacklightHandler.cpp
+ user-activity-handler/UserActivityHandler.cpp
internal/key_sequences/AbstractKeySequence.hpp
internal/key_sequences/KeySequenceMgr.hpp
@@ 26,6 27,7 @@ target_sources(evtmgr
include/evtmgr/EventManager.hpp
include/evtmgr/api/TemperatureApi.hpp
include/evtmgr/backlight-handler/BacklightHandler.hpp
+ include/evtmgr/user-activity-handler/UserActivityHandler.hpp
)
target_include_directories(evtmgr
M products/BellHybrid/services/evtmgr/EventManager.cpp => products/BellHybrid/services/evtmgr/EventManager.cpp +2 -1
@@ 38,7 38,7 @@ namespace
EventManager::EventManager(const std::string &name)
: EventManagerCommon(name), temperatureSource{hal::temperature::AbstractTemperatureSource::Factory::create()},
- backlightHandler(settings, this)
+ backlightHandler(settings, this), userActivityHandler(std::make_shared<sys::CpuSentinel>(name, this), this)
{
buildKeySequences();
updateTemperature(*temperatureSource);
@@ 56,6 56,7 @@ void EventManager::handleKeyEvent(sys::Message *msg)
}
if (kbdMessage->key.state == RawKey::State::Pressed || kbdMessage->key.state == RawKey::State::Moved) {
+ userActivityHandler.handleUserInput();
backlightHandler.handleKeyPressed(static_cast<int>(mapKey(static_cast<gui::KeyCode>(kbdMessage->key.keyCode))));
}
M products/BellHybrid/services/evtmgr/WorkerEvent.cpp => products/BellHybrid/services/evtmgr/WorkerEvent.cpp +0 -1
@@ 4,7 4,6 @@
#include "WorkerEvent.hpp"
#include <bsp/eink_frontlight/eink_frontlight.hpp>
-#include <service-audio/AudioMessage.hpp>
#include <service-evtmgr/EVMessages.hpp>
namespace bell
M products/BellHybrid/services/evtmgr/include/evtmgr/EventManager.hpp => products/BellHybrid/services/evtmgr/include/evtmgr/EventManager.hpp +2 -0
@@ 6,6 6,7 @@
#include <service-evtmgr/EventManagerCommon.hpp>
#include "backlight-handler/BacklightHandler.hpp"
+#include "user-activity-handler/UserActivityHandler.hpp"
class KeySequenceMgr;
@@ 27,6 28,7 @@ class EventManager : public EventManagerCommon
void buildKeySequences();
std::shared_ptr<hal::temperature::AbstractTemperatureSource> temperatureSource;
backlight::Handler backlightHandler;
+ evm::UserActivityHandler userActivityHandler;
std::shared_ptr<KeySequenceMgr> keySequenceMgr;
};
A products/BellHybrid/services/evtmgr/include/evtmgr/user-activity-handler/UserActivityHandler.hpp => products/BellHybrid/services/evtmgr/include/evtmgr/user-activity-handler/UserActivityHandler.hpp +25 -0
@@ 0,0 1,25 @@
+// 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 <Timers/TimerHandle.hpp>
+#include <SystemManager/CpuSentinel.hpp>
+#include <Service/Service.hpp>
+
+namespace evm
+{
+ class UserActivityHandler
+ {
+ public:
+ UserActivityHandler(std::shared_ptr<sys::CpuSentinel> cpuSentinel, sys::Service *parent);
+
+ void handleUserInput();
+
+ private:
+ void onUserActivityTimeout();
+
+ std::shared_ptr<sys::CpuSentinel> cpuSentinel;
+ sys::TimerHandle activityTimer;
+ };
+} // namespace evm
A products/BellHybrid/services/evtmgr/user-activity-handler/UserActivityHandler.cpp => products/BellHybrid/services/evtmgr/user-activity-handler/UserActivityHandler.cpp +36 -0
@@ 0,0 1,36 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <evtmgr/user-activity-handler/UserActivityHandler.hpp>
+#include <Timers/TimerFactory.hpp>
+
+namespace evm
+{
+ namespace
+ {
+ constexpr auto userActivityTimerTime = std::chrono::seconds(10);
+ constexpr auto userActivityCPULevel = bsp::CpuFrequencyHz::Level_5;
+ } // namespace
+
+ UserActivityHandler::UserActivityHandler(std::shared_ptr<sys::CpuSentinel> cpuSentinel, sys::Service *parent)
+ : cpuSentinel{std::move(cpuSentinel)},
+ activityTimer{sys::TimerFactory::createSingleShotTimer(
+ parent, "UserActivityTimer", userActivityTimerTime, [this]([[maybe_unused]] sys::Timer &timer) {
+ onUserActivityTimeout();
+ })}
+ {}
+
+ void UserActivityHandler::handleUserInput()
+ {
+ if (!activityTimer.isActive()) {
+ cpuSentinel->HoldMinimumFrequency(userActivityCPULevel);
+ }
+ activityTimer.restart(userActivityTimerTime);
+ }
+
+ void UserActivityHandler::onUserActivityTimeout()
+ {
+ cpuSentinel->ReleaseMinimumFrequency();
+ }
+
+} // namespace evm