M image/assets/lang/English.json => image/assets/lang/English.json +1 -1
@@ 30,6 30,7 @@
"common_stop": "STOP",
"common_resume": "RESUME",
"common_pause": "PAUSE",
+ "common_play": "PLAY",
"common_retry": "TRY AGAIN",
"common_replace": "REPLACE",
"common_abort": "ABORT",
@@ 37,7 38,6 @@
"common_disconnect": "DISCONNECT",
"common_forget": "FORGET",
"common_adjust": "ADJUST",
- "common_play_pause": "PLAY/PAUSE",
"common_mo": "MO",
"common_tu": "TU",
"common_we": "WE",
M module-apps/application-alarm-clock/ApplicationAlarmClock.cpp => module-apps/application-alarm-clock/ApplicationAlarmClock.cpp +22 -3
@@ 14,6 14,7 @@
#include <service-db/DBNotificationMessage.hpp>
#include <service-db/QueryMessage.hpp>
#include <service-time/api/TimeSettingsApi.hpp>
+#include <service-audio/AudioServiceAPI.hpp>
namespace app
{
@@ 23,9 24,11 @@ namespace app
StatusIndicators statusIndicators,
uint32_t stackDepth,
sys::ServicePriority priority)
- : Application(name, parent, statusIndicators, false, stackDepth, priority)
+ : Application(name, parent, statusIndicators, false, stackDepth, priority),
+ soundsPlayer{std::make_shared<SoundsPlayer>(this)}
{
bus.channels.push_back(sys::BusChannel::ServiceDBNotifications);
+ bus.channels.push_back(sys::BusChannel::ServiceAudioNotifications);
}
sys::MessagePointer ApplicationAlarmClock::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
@@ 57,6 60,16 @@ namespace app
return ret;
}
+ connect(typeid(AudioStopNotification), [&](sys::Message *msg) -> sys::MessagePointer {
+ auto notification = static_cast<AudioStopNotification *>(msg);
+ return handleAudioStop(notification);
+ });
+
+ connect(typeid(AudioEOFNotification), [&](sys::Message *msg) -> sys::MessagePointer {
+ auto notification = static_cast<AudioStopNotification *>(msg);
+ return handleAudioStop(notification);
+ });
+
createUserInterface();
return ret;
}
@@ 73,10 86,10 @@ namespace app
auto rRulePresenter = std::make_shared<alarmClock::AlarmRRulePresenter>();
windowsFactory.attach(style::alarmClock::window::name::newEditAlarm,
- [rRulePresenter](ApplicationCommon *app, const std::string &name) {
+ [this, rRulePresenter](ApplicationCommon *app, const std::string &name) {
auto alarmsRepository = std::make_unique<alarmClock::AlarmsDBRepository>(app);
auto alarmsProvider = std::make_shared<alarmClock::NewEditAlarmModel>(
- app, rRulePresenter, std::move(alarmsRepository));
+ app, soundsPlayer, rRulePresenter, std::move(alarmsRepository));
auto presenter =
std::make_unique<alarmClock::AlarmClockEditWindowPresenter>(alarmsProvider);
return std::make_unique<alarmClock::NewEditAlarmWindow>(app, std::move(presenter));
@@ 109,4 122,10 @@ namespace app
void ApplicationAlarmClock::destroyUserInterface()
{}
+ sys::MessagePointer ApplicationAlarmClock::handleAudioStop(AudioStopNotification *notification)
+ {
+ soundsPlayer->stop(notification->token);
+ return sys::MessageNone{};
+ }
+
} /* namespace app */
M module-apps/application-alarm-clock/ApplicationAlarmClock.hpp => module-apps/application-alarm-clock/ApplicationAlarmClock.hpp +7 -0
@@ 3,6 3,9 @@
#pragma once
#include "Application.hpp"
+#include <apps-common/audio/SoundsPlayer.hpp>
+
+class AudioStopNotification;
namespace app
{
@@ 29,6 32,10 @@ namespace app
void createUserInterface() override;
void destroyUserInterface() override;
+
+ private:
+ sys::MessagePointer handleAudioStop(AudioStopNotification *notification);
+ std::shared_ptr<SoundsPlayer> soundsPlayer;
};
template <> struct ManifestTraits<ApplicationAlarmClock>
M module-apps/application-alarm-clock/models/NewEditAlarmModel.cpp => module-apps/application-alarm-clock/models/NewEditAlarmModel.cpp +4 -1
@@ 15,9 15,11 @@
namespace app::alarmClock
{
NewEditAlarmModel::NewEditAlarmModel(app::ApplicationCommon *app,
+ std::shared_ptr<SoundsPlayer> player,
std::shared_ptr<alarmClock::AlarmRRulePresenter> rRulePresenter,
std::shared_ptr<AbstractAlarmsRepository> alarmsRepository)
- : application(app), alarmsRepository{std::move(alarmsRepository)}, rRulePresenter(rRulePresenter)
+ : application(app), alarmsRepository{std::move(alarmsRepository)}, soundsPlayer(player),
+ rRulePresenter(rRulePresenter)
{}
unsigned int NewEditAlarmModel::requestRecordsCount()
@@ 53,6 55,7 @@ namespace app::alarmClock
internalData.push_back(new gui::AlarmMusicOptionsItem(
application,
utils::translate("app_alarm_clock_sound"),
+ soundsPlayer,
[app](const UTF8 &text) { app->getCurrentWindow()->bottomBarTemporaryMode(text, false); },
[app]() { app->getCurrentWindow()->bottomBarRestoreFromTemporaryMode(); }));
M module-apps/application-alarm-clock/models/NewEditAlarmModel.hpp => module-apps/application-alarm-clock/models/NewEditAlarmModel.hpp +3 -0
@@ 7,6 7,7 @@
#include <application-alarm-clock/models/AlarmsRepository.hpp>
#include <application-alarm-clock/data/AlarmsData.hpp>
#include <application-alarm-clock/presenter/AlarmRRulePresenter.hpp>
+#include <apps-common/audio/SoundsPlayer.hpp>
#include <Application.hpp>
#include <InternalModel.hpp>
@@ 30,11 31,13 @@ namespace app::alarmClock
{
app::ApplicationCommon *application = nullptr;
std::shared_ptr<AbstractAlarmsRepository> alarmsRepository;
+ std::shared_ptr<SoundsPlayer> soundsPlayer = nullptr;
std::shared_ptr<alarmClock::AlarmRRulePresenter> rRulePresenter;
gui::AlarmInternalListItem *repeatOption = nullptr;
public:
NewEditAlarmModel(app::ApplicationCommon *app,
+ std::shared_ptr<SoundsPlayer> player,
std::shared_ptr<alarmClock::AlarmRRulePresenter> rRulePresenter,
std::shared_ptr<AbstractAlarmsRepository> alarmsRepository);
M module-apps/application-alarm-clock/widgets/AlarmMusicOptionsItem.cpp => module-apps/application-alarm-clock/widgets/AlarmMusicOptionsItem.cpp +32 -80
@@ 10,6 10,7 @@ namespace gui
{
AlarmMusicOptionsItem::AlarmMusicOptionsItem(app::ApplicationCommon *app,
const std::string &description,
+ std::shared_ptr<SoundsPlayer> player,
std::function<void(const UTF8 &text)> bottomBarTemporaryMode,
std::function<void()> bottomBarRestoreFromTemporaryMode)
: AlarmOptionsItem(description), bottomBarTemporaryMode(std::move(bottomBarTemporaryMode)),
@@ 17,9 18,6 @@ namespace gui
{
assert(app != nullptr);
- // create audioOperations to allow sounds preview
- audioOperations = std::make_unique<app::AsyncAudioOperations>(app);
-
alarmSoundList = getMusicFilesList();
std::vector<UTF8> printOptions;
for (const auto &musicFile : getMusicFilesList()) {
@@ 27,51 25,65 @@ namespace gui
}
optionSpinner->setData({printOptions});
- inputCallback = [&](gui::Item &item, const gui::InputEvent &event) {
+ inputCallback = [=](gui::Item &item, const gui::InputEvent &event) {
if (event.isShortRelease(gui::KeyCode::KEY_LF)) {
- if (getFilePath(optionSpinner->getCurrentValue()) != currentlyPreviewedPath) {
- playAudioPreview(getFilePath(optionSpinner->getCurrentValue()));
+ if (!player->previouslyPlayed(getFilePath(optionSpinner->getCurrentValue())) ||
+ player->isInState(SoundsPlayer::State::Stopped)) {
+ player->play(getFilePath(optionSpinner->getCurrentValue()), [=]() {
+ this->bottomBarTemporaryMode(utils::translate(style::strings::common::play));
+ });
+ this->bottomBarTemporaryMode(utils::translate(style::strings::common::pause));
}
- else if (musicStatus == MusicStatus::Stop) {
- resumeAudioPreview();
+ else if (player->isInState(SoundsPlayer::State::Paused)) {
+ player->resume();
+ this->bottomBarTemporaryMode(utils::translate(style::strings::common::pause));
}
else {
- pauseAudioPreview();
+ player->pause();
+ this->bottomBarTemporaryMode(utils::translate(style::strings::common::play));
}
}
// stop preview playback when we go back
- if (musicStatus == MusicStatus::Play && event.isShortRelease(gui::KeyCode::KEY_RF)) {
- stopAudioPreview();
+ if (player->isInState(SoundsPlayer::State::Playing) && event.isShortRelease(gui::KeyCode::KEY_RF)) {
+ player->stop();
+ }
+ auto res = optionSpinner->onInput(event);
+
+ if (res && player->previouslyPlayed(getFilePath(optionSpinner->getCurrentValue())) &&
+ player->isInState(SoundsPlayer::State::Playing)) {
+ this->bottomBarTemporaryMode(utils::translate(style::strings::common::pause));
+ }
+ else if (res) {
+ this->bottomBarTemporaryMode(utils::translate(style::strings::common::play));
}
- return optionSpinner->onInput(event);
+ return res;
};
- focusChangedCallback = [&](Item &item) {
+ focusChangedCallback = [=](Item &item) {
setFocusItem(focus ? optionSpinner : nullptr);
if (focus) {
- this->bottomBarTemporaryMode(utils::translate(style::strings::common::play_pause));
+ this->bottomBarTemporaryMode(utils::translate(style::strings::common::play));
}
else {
this->bottomBarRestoreFromTemporaryMode();
}
// stop preview playback when we loose focus
- if (musicStatus != MusicStatus::Stop) {
- stopAudioPreview();
+ if (!player->isInState(SoundsPlayer::State::Stopped)) {
+ player->stop();
}
return true;
};
- onSaveCallback = [&](std::shared_ptr<AlarmEventRecord> alarm) {
+ onSaveCallback = [=](std::shared_ptr<AlarmEventRecord> alarm) {
// stop preview playback if it is played
- if (musicStatus != MusicStatus::Stop) {
- stopAudioPreview();
+ if (!player->isInState(SoundsPlayer::State::Stopped)) {
+ player->stop();
}
-
alarm->musicTone = getFilePath(optionSpinner->getCurrentValue());
};
@@ 97,66 109,6 @@ namespace gui
return musicFiles;
}
- bool AlarmMusicOptionsItem::playAudioPreview(const std::string &path)
- {
- return audioOperations->play(path, [this, path](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;
- }
- musicStatus = MusicStatus::Play;
- currentlyPreviewedToken = token;
- currentlyPreviewedPath = path;
- });
- }
-
- bool AlarmMusicOptionsItem::pauseAudioPreview()
- {
- return audioOperations->pause(currentlyPreviewedToken, [this](audio::RetCode retCode, audio::Token token) {
- if (token != currentlyPreviewedToken) {
- LOG_ERROR("Audio preview pause failed: wrong token");
- return;
- }
- if (retCode != audio::RetCode::Success || !token.IsValid()) {
- LOG_ERROR("Audio preview pause failed with retcode = %s. Token validity: %d",
- str(retCode).c_str(),
- token.IsValid());
- return;
- }
- musicStatus = MusicStatus::Pause;
- });
- }
-
- bool AlarmMusicOptionsItem::resumeAudioPreview()
- {
- return audioOperations->resume(currentlyPreviewedToken, [this](audio::RetCode retCode, audio::Token token) {
- if (token != currentlyPreviewedToken) {
- LOG_ERROR("Audio preview resume failed: wrong token");
- return;
- }
-
- if (retCode != audio::RetCode::Success || !token.IsValid()) {
- LOG_ERROR("Audio preview pause failed with retcode = %s. Token validity: %d",
- str(retCode).c_str(),
- token.IsValid());
- return;
- }
- musicStatus = MusicStatus::Play;
- });
- }
-
- bool AlarmMusicOptionsItem::stopAudioPreview()
- {
- if (currentlyPreviewedToken.IsValid()) {
- musicStatus = MusicStatus::Stop;
- currentlyPreviewedPath = "";
- return audioOperations->stop(currentlyPreviewedToken, [](audio::RetCode, audio::Token) {});
- }
- return false;
- }
-
std::string AlarmMusicOptionsItem::getTitle(const std::string &filePath)
{
for (const auto &musicFile : alarmSoundList) {
M module-apps/application-alarm-clock/widgets/AlarmMusicOptionsItem.hpp => module-apps/application-alarm-clock/widgets/AlarmMusicOptionsItem.hpp +3 -17
@@ 8,6 8,7 @@
#include <application-alarm-clock/data/AlarmsData.hpp>
#include <apps-common/ApplicationCommon.hpp>
#include <apps-common/AudioOperations.hpp>
+#include <apps-common/audio/SoundsPlayer.hpp>
#include <tags_fetcher/TagsFetcher.hpp>
namespace gui
@@ 15,38 16,23 @@ namespace gui
class AlarmMusicOptionsItem : public AlarmOptionsItem
{
private:
- enum class MusicStatus
- {
- Stop,
- Pause,
- Play
- };
-
std::function<void(const UTF8 &text)> bottomBarTemporaryMode = nullptr;
std::function<void()> bottomBarRestoreFromTemporaryMode = nullptr;
/// pointer to audio operations which allows to make audio preview
- std::unique_ptr<app::AbstractAudioOperations> audioOperations;
std::vector<tags::fetcher::Tags> alarmSoundList;
- MusicStatus musicStatus = MusicStatus::Stop;
- audio::Token currentlyPreviewedToken;
- std::string currentlyPreviewedPath;
-
std::vector<tags::fetcher::Tags> getMusicFilesList();
public:
explicit AlarmMusicOptionsItem(app::ApplicationCommon *app,
const std::string &description,
+ std::shared_ptr<SoundsPlayer> player,
std::function<void(const UTF8 &text)> bottomBarTemporaryMode = nullptr,
std::function<void()> bottomBarRestoreFromTemporaryMode = nullptr);
private:
[[nodiscard]] std::string getTitle(const std::string &filePath);
[[nodiscard]] std::string getFilePath(const std::string &title);
- bool playAudioPreview(const std::string &path);
- bool pauseAudioPreview();
- bool resumeAudioPreview();
- bool stopAudioPreview();
};
-} /* namespace gui */>
\ No newline at end of file
+} /* namespace gui */
M module-apps/application-settings/CMakeLists.txt => module-apps/application-settings/CMakeLists.txt +0 -1
@@ 15,7 15,6 @@ target_sources(application-settings
models/apps/AudioSettingsModel.cpp
models/apps/SoundsModel.cpp
models/apps/SoundsModel.cpp
- models/apps/SoundsPlayer.cpp
models/bluetooth/BluetoothSettingsModel.cpp
models/display-keypad/CategoriesModel.cpp
models/display-keypad/CategoriesModel.cpp
M module-apps/application-settings/include/application-settings/ApplicationSettings.hpp => module-apps/application-settings/include/application-settings/ApplicationSettings.hpp +1 -1
@@ 6,7 6,7 @@
#include <Application.hpp>
#include <application-settings/windows/WindowNames.hpp>
-#include <application-settings/models/apps/SoundsPlayer.hpp>
+#include <apps-common/audio/SoundsPlayer.hpp>
#include <bsp/common.hpp>
#include <bsp/keypad_backlight/keypad_backlight.hpp>
#include <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
M module-apps/application-settings/models/apps/SoundsModel.cpp => module-apps/application-settings/models/apps/SoundsModel.cpp +37 -1
@@ 139,12 139,21 @@ void SoundsModel::applyItems(const std::vector<std::filesystem::path> &sounds,
else if (event.isShortRelease(gui::KeyCode::KEY_LF)) {
if (!soundsPlayer->previouslyPlayed(fileRelativePath) ||
soundsPlayer->isInState(AbstractSoundsPlayer::State::Stopped)) {
- return soundsPlayer->play(fileRelativePath);
+ app->getCurrentWindow()->bottomBarTemporaryMode(
+ utils::translate(style::strings::common::pause), gui::BottomBar::Side::LEFT, false);
+ return soundsPlayer->play(fileRelativePath, [=]() {
+ app->getCurrentWindow()->bottomBarTemporaryMode(
+ utils::translate(style::strings::common::play), gui::BottomBar::Side::LEFT, false);
+ });
}
else if (soundsPlayer->isInState(AbstractSoundsPlayer::State::Playing)) {
+ app->getCurrentWindow()->bottomBarTemporaryMode(
+ utils::translate(style::strings::common::play), gui::BottomBar::Side::LEFT, false);
return soundsPlayer->pause();
}
else if (soundsPlayer->isInState(AbstractSoundsPlayer::State::Paused)) {
+ app->getCurrentWindow()->bottomBarTemporaryMode(
+ utils::translate(style::strings::common::pause), gui::BottomBar::Side::LEFT, false);
return soundsPlayer->resume();
}
}
@@ 152,6 161,33 @@ void SoundsModel::applyItems(const std::vector<std::filesystem::path> &sounds,
return false;
};
+ item->focusChangedCallback = [=](gui::Item &item) {
+ if (!item.focus) {
+ app->getCurrentWindow()->bottomBarRestoreFromTemporaryMode();
+ return true;
+ }
+
+ auto fileRelativePath = sound.lexically_relative(purefs::dir::getCurrentOSPath());
+ if (!soundsPlayer->previouslyPlayed(fileRelativePath)) {
+ app->getCurrentWindow()->bottomBarTemporaryMode(
+ utils::translate(style::strings::common::play), gui::BottomBar::Side::LEFT, false);
+ return true;
+ }
+
+ if (soundsPlayer->isInState(AbstractSoundsPlayer::State::Playing)) {
+ app->getCurrentWindow()->bottomBarTemporaryMode(
+ utils::translate(style::strings::common::pause), gui::BottomBar::Side::LEFT, false);
+ return true;
+ }
+
+ else {
+ app->getCurrentWindow()->bottomBarTemporaryMode(
+ utils::translate(style::strings::common::play), gui::BottomBar::Side::LEFT, false);
+ return true;
+ }
+
+ return false;
+ };
break;
default:
M module-apps/application-settings/models/apps/SoundsModel.hpp => module-apps/application-settings/models/apps/SoundsModel.hpp +1 -1
@@ 4,7 4,7 @@
#pragma once
#include "AbstractSoundsModel.hpp"
-#include "AbstractSoundsPlayer.hpp"
+#include <apps-common/audio/AbstractSoundsPlayer.hpp>
#include <apps-common/AudioOperations.hpp>
#include <Audio/decoder/Decoder.hpp>
M module-apps/application-settings/windows/apps/SoundSelectWindow.cpp => module-apps/application-settings/windows/apps/SoundSelectWindow.cpp +0 -1
@@ 28,7 28,6 @@ namespace gui
void SoundSelectWindow::buildInterface()
{
AppWindow::buildInterface();
- bottomBar->setText(BottomBar::Side::LEFT, utils::translate(style::strings::common::play_pause));
bottomBar->setText(BottomBar::Side::CENTER, utils::translate(style::strings::common::select));
bottomBar->setText(BottomBar::Side::RIGHT, utils::translate(style::strings::common::back));
M module-apps/application-settings/windows/apps/SoundSelectWindow.hpp => module-apps/application-settings/windows/apps/SoundSelectWindow.hpp +1 -1
@@ 4,7 4,7 @@
#pragma once
#include <application-settings/models/apps/AbstractSoundsModel.hpp>
-#include <application-settings/models/apps/AbstractSoundsPlayer.hpp>
+#include <apps-common/audio/AbstractSoundsPlayer.hpp>
#include <AppWindow.hpp>
namespace gui
M module-apps/apps-common/CMakeLists.txt => module-apps/apps-common/CMakeLists.txt +1 -0
@@ 14,6 14,7 @@ target_sources(apps-common
GuiTimer.cpp
StatusBarManager.cpp
WindowsFactory.cpp
+ audio/SoundsPlayer.cpp
notifications/NotificationData.cpp
notifications/NotificationListItem.cpp
notifications/NotificationProvider.cpp
R module-apps/application-settings/models/apps/AbstractSoundsPlayer.hpp => module-apps/apps-common/audio/AbstractSoundsPlayer.hpp +9 -7
@@ 17,11 17,13 @@ class AbstractSoundsPlayer
Stopped
};
- virtual bool play(const std::string &path) = 0;
- virtual bool pause() = 0;
- virtual bool resume() = 0;
- virtual bool stop() = 0;
- virtual bool stop(audio::Token token) = 0;
- virtual bool isInState(State state) const noexcept = 0;
- virtual bool previouslyPlayed(const std::string &filePath) const = 0;
+ using AudioEofCallback = std::function<void()>;
+
+ virtual bool play(const std::string &path, AudioEofCallback cb = nullptr) = 0;
+ virtual bool pause() = 0;
+ virtual bool resume() = 0;
+ virtual bool stop() = 0;
+ virtual bool stop(audio::Token token) = 0;
+ virtual bool isInState(State state) const noexcept = 0;
+ virtual bool previouslyPlayed(const std::string &filePath) const = 0;
};
R module-apps/application-settings/models/apps/SoundsPlayer.cpp => module-apps/apps-common/audio/SoundsPlayer.cpp +9 -2
@@ 7,9 7,10 @@ SoundsPlayer::SoundsPlayer(app::ApplicationCommon *app)
: audioOperations{std::make_unique<app::AsyncAudioOperations>(app)}
{}
-bool SoundsPlayer::play(const std::string &path)
+bool SoundsPlayer::play(const std::string &path, AudioEofCallback cb)
{
- return audioOperations->play(path, [this, path](audio::RetCode retCode, audio::Token token) {
+ eofCallback = nullptr;
+ return audioOperations->play(path, [this, path, cb](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(),
@@ 19,6 20,7 @@ bool SoundsPlayer::play(const std::string &path)
currentState = State::Playing;
currentToken = token;
currentPath = path;
+ eofCallback = cb;
});
}
@@ 60,6 62,8 @@ bool SoundsPlayer::resume()
bool SoundsPlayer::stop()
{
+ eofCallback = nullptr;
+
if (currentToken.IsValid()) {
return audioOperations->stop(currentToken,
[this](audio::RetCode, audio::Token) { currentState = State::Stopped; });
@@ 71,6 75,9 @@ bool SoundsPlayer::stop(audio::Token token)
{
if (currentToken.IsValid() && currentToken == token) {
currentState = State::Stopped;
+ if (eofCallback != nullptr) {
+ eofCallback();
+ }
return true;
}
return false;
R module-apps/application-settings/models/apps/SoundsPlayer.hpp => module-apps/apps-common/audio/SoundsPlayer.hpp +4 -2
@@ 9,8 9,9 @@ class SoundsPlayer : public AbstractSoundsPlayer
{
public:
explicit SoundsPlayer(app::ApplicationCommon *app);
+ virtual ~SoundsPlayer() = default;
- bool play(const std::string &path) override;
+ bool play(const std::string &path, AudioEofCallback cb = nullptr) override;
bool pause() override;
bool resume() override;
bool stop() override;
@@ 20,8 21,9 @@ class SoundsPlayer : public AbstractSoundsPlayer
private:
std::unique_ptr<app::AbstractAudioOperations> audioOperations;
-
State currentState = State::Stopped;
audio::Token currentToken;
std::string currentPath;
+
+ AudioEofCallback eofCallback{nullptr};
};
M module-gui/gui/widgets/Style.hpp => module-gui/gui/widgets/Style.hpp +0 -1
@@ 198,7 198,6 @@ namespace style
inline constexpr auto replace = "common_replace";
inline constexpr auto abort = "common_abort";
inline constexpr auto adjust = "common_adjust";
- inline constexpr auto play_pause = "common_play_pause";
// days
inline constexpr auto Monday = "common_monday";
inline constexpr auto Tuesday = "common_tuesday";