mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-04-26 18:07:30 -04:00
Stack plus minimum tests added Updated to master Removed useless or adressed TODOS Constants name applied Renamed searchModel to searchRequestModel Review applied We should remove legacy window names Bell names fixes
210 lines
7.5 KiB
C++
210 lines
7.5 KiB
C++
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
|
|
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
|
|
|
|
#include "SoundsModel.hpp"
|
|
#include "AppWindow.hpp"
|
|
|
|
#include <application-settings/widgets/apps/SettingsSoundItem.hpp>
|
|
#include <module-gui/gui/input/InputEvent.hpp>
|
|
|
|
#include <ListView.hpp>
|
|
#include <purefs/filesystem_paths.hpp>
|
|
#include <service-audio/AudioServiceAPI.hpp>
|
|
#include <tags_fetcher/TagsFetcher.hpp>
|
|
|
|
SoundsModel::SoundsModel(std::shared_ptr<AbstractSoundsPlayer> soundsPlayer) : soundsPlayer{std::move(soundsPlayer)}
|
|
{}
|
|
|
|
unsigned int SoundsModel::requestRecordsCount()
|
|
{
|
|
return internalData.size();
|
|
}
|
|
|
|
unsigned int SoundsModel::getMinimalItemSpaceRequired() const
|
|
{
|
|
return style::window::label::big_h + style::margins::big;
|
|
}
|
|
|
|
void SoundsModel::requestRecords(const uint32_t offset, const uint32_t limit)
|
|
{
|
|
setupModel(offset, limit);
|
|
list->onProviderDataUpdate();
|
|
}
|
|
|
|
gui::ListItem *SoundsModel::getItem(gui::Order order)
|
|
{
|
|
return getRecord(order);
|
|
}
|
|
|
|
void SoundsModel::createData(app::ApplicationCommon *app, audio_settings::AbstractAudioSettingsModel *model)
|
|
{
|
|
assert(model);
|
|
assert(app);
|
|
|
|
// configure according to type
|
|
std::filesystem::path folder = getSoundPath(model);
|
|
|
|
// iterate through selected folder and collect all sounds names
|
|
std::vector<std::filesystem::path> sounds;
|
|
if (std::filesystem::is_directory(folder)) {
|
|
LOG_INFO("Scanning sound folder: %s", folder.c_str());
|
|
for (const auto &entry : std::filesystem::directory_iterator(folder)) {
|
|
if (std::filesystem::is_directory(entry)) {
|
|
continue;
|
|
}
|
|
|
|
const auto &filePath = entry.path();
|
|
if (filePath.extension() == ".mp3")
|
|
sounds.push_back(filePath);
|
|
}
|
|
LOG_INFO("Found %d sounds in folder %s", static_cast<int>(sounds.size()), folder.c_str());
|
|
}
|
|
else {
|
|
LOG_ERROR("Cannot find directory: %s", folder.c_str());
|
|
}
|
|
|
|
applyItems(sounds, app, model);
|
|
}
|
|
|
|
void SoundsModel::clearData()
|
|
{
|
|
list->reset();
|
|
eraseInternalData();
|
|
}
|
|
|
|
std::filesystem::path SoundsModel::getSoundPath(audio_settings::AbstractAudioSettingsModel *model)
|
|
{
|
|
assert(model);
|
|
switch (model->getPlaybackType()) {
|
|
case audio::PlaybackType::CallRingtone:
|
|
return purefs::dir::getCurrentOSPath() / "assets/audio/ringtone";
|
|
|
|
case audio::PlaybackType::TextMessageRingtone:
|
|
return purefs::dir::getCurrentOSPath() / "assets/audio/sms";
|
|
|
|
case audio::PlaybackType::Notifications:
|
|
return purefs::dir::getCurrentOSPath() / "assets/audio/alarm";
|
|
|
|
default:
|
|
return purefs::dir::getCurrentOSPath() / "assets/audio";
|
|
}
|
|
}
|
|
|
|
void SoundsModel::applyItems(const std::vector<std::filesystem::path> &sounds,
|
|
app::ApplicationCommon *app,
|
|
audio_settings::AbstractAudioSettingsModel *model)
|
|
{
|
|
auto currentItemIndex = 0;
|
|
auto selectedItemIndex = 0;
|
|
|
|
std::string selectedSound = purefs::dir::getCurrentOSPath() / model->getSound();
|
|
for (const auto &sound : sounds) {
|
|
|
|
bool isSelected = false;
|
|
if (sound == selectedSound) {
|
|
isSelected = true;
|
|
selectedItemIndex = currentItemIndex;
|
|
}
|
|
|
|
std::string itemTitle;
|
|
auto fileTags = tags::fetcher::fetchTags(sound);
|
|
itemTitle = fileTags.title;
|
|
|
|
if (itemTitle.empty()) {
|
|
itemTitle = sound.filename();
|
|
}
|
|
|
|
auto item = new gui::SettingsSoundItem(itemTitle, isSelected);
|
|
|
|
switch (model->getPlaybackType()) {
|
|
|
|
case audio::PlaybackType::CallRingtone:
|
|
case audio::PlaybackType::TextMessageRingtone:
|
|
case audio::PlaybackType::Notifications:
|
|
item->activatedCallback = [=](gui::Item &) {
|
|
auto fileRelativePath = sound.lexically_relative(purefs::dir::getCurrentOSPath());
|
|
LOG_INFO("Setting sound to %s", fileRelativePath.c_str());
|
|
model->setSound(fileRelativePath);
|
|
soundsPlayer->stop();
|
|
app->returnToPreviousWindow();
|
|
return true;
|
|
};
|
|
|
|
// callback to handle preview of the sound
|
|
item->inputCallback = [=](gui::Item &item, const gui::InputEvent &event) {
|
|
auto fileRelativePath = sound.lexically_relative(purefs::dir::getCurrentOSPath());
|
|
|
|
if (event.isShortRelease(gui::KeyCode::KEY_RF)) {
|
|
soundsPlayer->stop();
|
|
}
|
|
else if (event.isShortRelease(gui::KeyCode::KEY_LF)) {
|
|
if (!soundsPlayer->previouslyPlayed(fileRelativePath) ||
|
|
soundsPlayer->isInState(AbstractSoundsPlayer::State::Stopped)) {
|
|
app->getCurrentWindow()->navBarTemporaryMode(
|
|
utils::translate(style::strings::common::pause), gui::nav_bar::Side::Left, false);
|
|
return soundsPlayer->play(fileRelativePath, [=]() {
|
|
app->getCurrentWindow()->navBarTemporaryMode(
|
|
utils::translate(style::strings::common::play), gui::nav_bar::Side::Left, false);
|
|
});
|
|
}
|
|
else if (soundsPlayer->isInState(AbstractSoundsPlayer::State::Playing)) {
|
|
app->getCurrentWindow()->navBarTemporaryMode(
|
|
utils::translate(style::strings::common::play), gui::nav_bar::Side::Left, false);
|
|
return soundsPlayer->pause();
|
|
}
|
|
else if (soundsPlayer->isInState(AbstractSoundsPlayer::State::Paused)) {
|
|
app->getCurrentWindow()->navBarTemporaryMode(
|
|
utils::translate(style::strings::common::pause), gui::nav_bar::Side::Left, false);
|
|
return soundsPlayer->resume();
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
item->focusChangedCallback = [=](gui::Item &item) {
|
|
if (!item.focus) {
|
|
app->getCurrentWindow()->navBarRestoreFromTemporaryMode();
|
|
return true;
|
|
}
|
|
|
|
auto fileRelativePath = sound.lexically_relative(purefs::dir::getCurrentOSPath());
|
|
if (!soundsPlayer->previouslyPlayed(fileRelativePath)) {
|
|
app->getCurrentWindow()->navBarTemporaryMode(
|
|
utils::translate(style::strings::common::play), gui::nav_bar::Side::Left, false);
|
|
return true;
|
|
}
|
|
|
|
if (soundsPlayer->isInState(AbstractSoundsPlayer::State::Playing)) {
|
|
app->getCurrentWindow()->navBarTemporaryMode(
|
|
utils::translate(style::strings::common::pause), gui::nav_bar::Side::Left, false);
|
|
return true;
|
|
}
|
|
|
|
else {
|
|
app->getCurrentWindow()->navBarTemporaryMode(
|
|
utils::translate(style::strings::common::play), gui::nav_bar::Side::Left, false);
|
|
return true;
|
|
}
|
|
};
|
|
break;
|
|
|
|
default:
|
|
item->activatedCallback = [=](gui::Item &) {
|
|
app->returnToPreviousWindow();
|
|
return true;
|
|
};
|
|
break;
|
|
}
|
|
|
|
internalData.push_back(item);
|
|
++currentItemIndex;
|
|
}
|
|
|
|
for (auto item : internalData) {
|
|
item->deleteByList = false;
|
|
}
|
|
|
|
list->rebuildList(gui::listview::RebuildType::OnPageElement, selectedItemIndex);
|
|
}
|