Implemented a much more elegant handling of navigation sounds

This commit is contained in:
Leon Styhre 2020-05-15 18:21:24 +02:00
parent fc6183d918
commit 3d6adf9ade
12 changed files with 139 additions and 44 deletions

View file

@ -80,9 +80,8 @@ public:
inline void setLineSpacing(float lineSpacing) { mLineSpacing = lineSpacing; } inline void setLineSpacing(float lineSpacing) { mLineSpacing = lineSpacing; }
protected: protected:
virtual void onScroll() { soundfile->play(); } virtual void onScroll() { navigationsounds.playThemeNavigationSound(SCROLLSOUND); }
virtual void onCursorChanged(const CursorState& state); virtual void onCursorChanged(const CursorState& state);
std::shared_ptr<Sound> soundfile;
private: private:
int mMarqueeOffset; int mMarqueeOffset;
@ -390,8 +389,6 @@ void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, c
setFont(Font::getFromTheme(elem, properties, mFont)); setFont(Font::getFromTheme(elem, properties, mFont));
const float selectorHeight = Math::max(mFont->getHeight(1.0), (float)mFont->getSize()) * mLineSpacing; const float selectorHeight = Math::max(mFont->getHeight(1.0), (float)mFont->getSize()) * mLineSpacing;
setSelectorHeight(selectorHeight); setSelectorHeight(selectorHeight);
soundfile = Sound::getFromTheme(theme, "navigationsounds", "scrollSound");
if(properties & ALIGNMENT) if(properties & ALIGNMENT)
{ {

View file

@ -10,6 +10,7 @@
#include "FileSorts.h" #include "FileSorts.h"
#include "GuiMetaDataEd.h" #include "GuiMetaDataEd.h"
#include "SystemData.h" #include "SystemData.h"
#include "Sound.h"
GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system) : GuiComponent(window), GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system) : GuiComponent(window),
mSystem(system), mMenu(window, "OPTIONS"), fromPlaceholder(false), mFiltersChanged(false) mSystem(system), mMenu(window, "OPTIONS"), fromPlaceholder(false), mFiltersChanged(false)
@ -81,9 +82,11 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system) : Gui
{ {
if(mJumpToLetterList->getSelected() == FAV_CHAR) if(mJumpToLetterList->getSelected() == FAV_CHAR)
{ {
navigationsounds.playThemeNavigationSound(SCROLLSOUND);
jumpToFirstFavorite(); jumpToFirstFavorite();
return true; return true;
} }
navigationsounds.playThemeNavigationSound(SCROLLSOUND);
jumpToLetter(); jumpToLetter();
return true; return true;
} }

View file

@ -2,8 +2,6 @@
#ifndef ES_APP_GUIS_GUI_GAME_LIST_OPTIONS_H #ifndef ES_APP_GUIS_GUI_GAME_LIST_OPTIONS_H
#define ES_APP_GUIS_GUI_GAME_LIST_OPTIONS_H #define ES_APP_GUIS_GUI_GAME_LIST_OPTIONS_H
#define FAV_CHAR '*'
#include "components/MenuComponent.h" #include "components/MenuComponent.h"
#include "components/OptionListComponent.h" #include "components/OptionListComponent.h"
#include "FileData.h" #include "FileData.h"
@ -31,6 +29,8 @@ private:
void findFirstFavorite(); void findFirstFavorite();
void jumpToFirstFavorite(); void jumpToFirstFavorite();
const char FAV_CHAR = '*';
long firstFavorite = -1; long firstFavorite = -1;
MenuComponent mMenu; MenuComponent mMenu;

View file

@ -29,8 +29,6 @@ SystemView::SystemView(Window* window) : IList<SystemViewData, SystemData*>(wind
void SystemView::populate() void SystemView::populate()
{ {
mEntries.clear(); mEntries.clear();
mSelectSound = "";
// mScrollSound = "";
for(auto it = SystemData::sSystemVector.cbegin(); it != SystemData::sSystemVector.cend(); it++) for(auto it = SystemData::sSystemVector.cbegin(); it != SystemData::sSystemVector.cend(); it++)
{ {
@ -127,8 +125,6 @@ void SystemView::populate()
mWindow->pushGui(new GuiMsgBox(mWindow, "The selected UI mode has nothing to show,\n returning to UI mode: FULL", "OK", nullptr)); mWindow->pushGui(new GuiMsgBox(mWindow, "The selected UI mode has nothing to show,\n returning to UI mode: FULL", "OK", nullptr));
} }
} }
} }
void SystemView::goToSystem(SystemData* system, bool animate) void SystemView::goToSystem(SystemData* system, bool animate)
@ -159,13 +155,13 @@ bool SystemView::input(InputConfig* config, Input input)
case VERTICAL_WHEEL: case VERTICAL_WHEEL:
if (config->isMappedLike("up", input)) if (config->isMappedLike("up", input))
{ {
Sound::getFromTheme(theme, "navigationsounds", "systembrowseSound")->play(); navigationsounds.playThemeNavigationSound(SYSTEMBROWSE);
listInput(-1); listInput(-1);
return true; return true;
} }
if (config->isMappedLike("down", input)) if (config->isMappedLike("down", input))
{ {
Sound::getFromTheme(theme, "navigationsounds", "systembrowseSound")->play(); navigationsounds.playThemeNavigationSound(SYSTEMBROWSE);
listInput(1); listInput(1);
return true; return true;
} }
@ -175,13 +171,13 @@ bool SystemView::input(InputConfig* config, Input input)
default: default:
if (config->isMappedLike("left", input)) if (config->isMappedLike("left", input))
{ {
Sound::getFromTheme(theme, "navigationsounds", "systembrowseSound")->play(); navigationsounds.playThemeNavigationSound(SYSTEMBROWSE);
listInput(-1); listInput(-1);
return true; return true;
} }
if (config->isMappedLike("right", input)) if (config->isMappedLike("right", input))
{ {
Sound::getFromTheme(theme, "navigationsounds", "systembrowseSound")->play(); navigationsounds.playThemeNavigationSound(SYSTEMBROWSE);
listInput(1); listInput(1);
return true; return true;
} }
@ -190,16 +186,16 @@ bool SystemView::input(InputConfig* config, Input input)
if(config->isMappedTo("a", input)) if(config->isMappedTo("a", input))
{ {
Sound::getFromTheme(theme, "navigationsounds", "selectSound")->play();
stopScrolling(); stopScrolling();
ViewController::get()->goToGameList(getSelected()); ViewController::get()->goToGameList(getSelected());
navigationsounds.playThemeNavigationSound(SELECTSOUND);
return true; return true;
} }
if (config->isMappedTo("x", input)) if (config->isMappedTo("x", input))
{ {
// get random system // get random system
// go to system // go to system
Sound::getFromTheme(theme, "navigationsounds", "systembrowseSound")->play(); navigationsounds.playThemeNavigationSound(SYSTEMBROWSE);
setCursor(SystemData::getRandomSystem()); setCursor(SystemData::getRandomSystem());
return true; return true;
} }
@ -247,7 +243,6 @@ void SystemView::onCursorChanged(const CursorState& /*state*/)
if(abs(target - posMax - startPos) < dist) if(abs(target - posMax - startPos) < dist)
endPos = target - posMax; // loop around the start (max - 1 -> -1) endPos = target - posMax; // loop around the start (max - 1 -> -1)
// animate mSystemInfo's opacity (fade out, wait, fade back in) // animate mSystemInfo's opacity (fade out, wait, fade back in)
cancelAnimation(1); cancelAnimation(1);

View file

@ -62,9 +62,6 @@ public:
std::vector<HelpPrompt> getHelpPrompts() override; std::vector<HelpPrompt> getHelpPrompts() override;
virtual HelpStyle getHelpStyle() override; virtual HelpStyle getHelpStyle() override;
std::string mSelectSound;
// std::string mScrollSound;
protected: protected:
void onCursorChanged(const CursorState& state) override; void onCursorChanged(const CursorState& state) override;

View file

@ -16,8 +16,10 @@
#include "Settings.h" #include "Settings.h"
#include "SystemData.h" #include "SystemData.h"
#include "Window.h" #include "Window.h"
#include "Sound.h"
ViewController* ViewController::sInstance = NULL; ViewController* ViewController::sInstance = NULL;
NavigationSounds navigationsounds;
ViewController* ViewController::get() ViewController* ViewController::get()
{ {
@ -103,6 +105,7 @@ void ViewController::goToNextGameList()
assert(mState.viewing == GAME_LIST); assert(mState.viewing == GAME_LIST);
SystemData* system = getState().getSystem(); SystemData* system = getState().getSystem();
assert(system); assert(system);
navigationsounds.playThemeNavigationSound(QUICKSYSSELECT);
goToGameList(system->getNext()); goToGameList(system->getNext());
} }
@ -111,6 +114,7 @@ void ViewController::goToPrevGameList()
assert(mState.viewing == GAME_LIST); assert(mState.viewing == GAME_LIST);
SystemData* system = getState().getSystem(); SystemData* system = getState().getSystem();
assert(system); assert(system);
navigationsounds.playThemeNavigationSound(QUICKSYSSELECT);
goToGameList(system->getPrev()); goToGameList(system->getPrev());
} }
@ -224,6 +228,11 @@ void ViewController::launch(FileData* game, Vector3f center)
mLockInput = true; mLockInput = true;
std::string transition_style = Settings::getInstance()->getString("TransitionStyle"); std::string transition_style = Settings::getInstance()->getString("TransitionStyle");
navigationsounds.playThemeNavigationSound(LAUNCHSOUND);
// let launch sound play to the end before launching game
while(navigationsounds.isPlayingThemeNavigationSound(LAUNCHSOUND));
if(transition_style == "fade") if(transition_style == "fade")
{ {
// fade out, launch game, fade back in // fade out, launch game, fade back in
@ -452,6 +461,8 @@ void ViewController::preload()
(*it)->getIndex()->resetFilters(); (*it)->getIndex()->resetFilters();
getGameListView(*it); getGameListView(*it);
} }
// load navigation sounds
navigationsounds.loadThemeNavigationSounds(SystemData::sSystemVector[0]->getTheme());
} }
void ViewController::reloadGameListView(IGameListView* view, bool reloadTheme) void ViewController::reloadGameListView(IGameListView* view, bool reloadTheme)
@ -523,6 +534,9 @@ void ViewController::reloadAll()
goToSystemView(SystemData::sSystemVector.front()); goToSystemView(SystemData::sSystemVector.front());
} }
// load navigation sounds
navigationsounds.loadThemeNavigationSounds(SystemData::sSystemVector[0]->getTheme());
updateHelpPrompts(); updateHelpPrompts();
} }

View file

@ -149,7 +149,7 @@ bool GridGameListView::input(InputConfig* config, Input input)
{ {
if (input.value == 0 and (config->isMappedLike("left", input) || config->isMappedLike("right", input) if (input.value == 0 and (config->isMappedLike("left", input) || config->isMappedLike("right", input)
|| (config->isMappedLike("up", input)) || (config->isMappedLike("down", input)) )) || (config->isMappedLike("up", input)) || (config->isMappedLike("down", input)) ))
Sound::getFromTheme(getTheme(), "navigationsounds", "scrollSound")->play(); navigationsounds.playThemeNavigationSound(SCROLLSOUND);
if(config->isMappedLike("left", input) || config->isMappedLike("right", input)) if(config->isMappedLike("left", input) || config->isMappedLike("right", input))
return GuiComponent::input(config, input); return GuiComponent::input(config, input);

View file

@ -87,9 +87,6 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
FileData* cursor = getCursor(); FileData* cursor = getCursor();
if(cursor->getType() == GAME) if(cursor->getType() == GAME)
{ {
soundfile = Sound::getFromTheme(getTheme(), "navigationsounds", "launchSound");
soundfile->play();
while(soundfile->isPlaying());
launch(cursor); launch(cursor);
}else{ }else{
// it's a folder // it's a folder
@ -111,7 +108,7 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
setCursor(mCursorStack.top()); setCursor(mCursorStack.top());
mCursorStack.pop(); mCursorStack.pop();
}else{ }else{
Sound::getFromTheme(getTheme(), "navigationsounds", "backSound")->play(); navigationsounds.playThemeNavigationSound(BACKSOUND);
onFocusLost(); onFocusLost();
SystemData* systemToView = getCursor()->getSystem(); SystemData* systemToView = getCursor()->getSystem();
if (systemToView->isCollection()) if (systemToView->isCollection())
@ -126,7 +123,6 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
{ {
if(Settings::getInstance()->getBool("QuickSystemSelect")) if(Settings::getInstance()->getBool("QuickSystemSelect"))
{ {
Sound::getFromTheme(getTheme(), "navigationsounds", "quicksysselectSound")->play();
onFocusLost(); onFocusLost();
ViewController::get()->goToNextGameList(); ViewController::get()->goToNextGameList();
return true; return true;
@ -135,7 +131,6 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
{ {
if(Settings::getInstance()->getBool("QuickSystemSelect")) if(Settings::getInstance()->getBool("QuickSystemSelect"))
{ {
Sound::getFromTheme(getTheme(), "navigationsounds", "quicksysselectSound")->play();
onFocusLost(); onFocusLost();
ViewController::get()->goToPrevGameList(); ViewController::get()->goToPrevGameList();
return true; return true;
@ -145,7 +140,7 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
if (mRoot->getSystem()->isGameSystem()) if (mRoot->getSystem()->isGameSystem())
{ {
// go to random system game // go to random system game
Sound::getFromTheme(getTheme(), "navigationsounds", "scrollSound")->play(); navigationsounds.playThemeNavigationSound(SCROLLSOUND);
FileData* randomGame = getCursor()->getSystem()->getRandomGame(); FileData* randomGame = getCursor()->getSystem()->getRandomGame();
if (randomGame) if (randomGame)
{ {
@ -157,7 +152,7 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
{ {
if(mRoot->getSystem()->isGameSystem()) if(mRoot->getSystem()->isGameSystem())
{ {
Sound::getFromTheme(getTheme(), "navigationsounds", "favoriteSound")->play(); navigationsounds.playThemeNavigationSound(FAVORITESOUND);
if(CollectionSystemManager::get()->toggleGameInCollection(getCursor())) if(CollectionSystemManager::get()->toggleGameInCollection(getCursor()))
{ {
return true; return true;

View file

@ -27,7 +27,7 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8 *stream, int len)
//calculate rest length of current sample //calculate rest length of current sample
Uint32 restLength = (sound->getLength() - sound->getPosition()); Uint32 restLength = (sound->getLength() - sound->getPosition());
if (restLength > (Uint32)len) { if (restLength > (Uint32)len) {
//if stream length is smaller than smaple lenght, clip it //if stream length is smaller than sample length, clip it
restLength = len; restLength = len;
} }
//mix sample into stream //mix sample into stream

View file

@ -21,9 +21,6 @@ std::shared_ptr<Sound> Sound::get(const std::string& path)
std::shared_ptr<Sound> Sound::getFromTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element) std::shared_ptr<Sound> Sound::getFromTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element)
{ {
if(!Settings::getInstance()->getBool("EnableSounds"))
return get("");
LOG(LogInfo) << "Sound::getFromTheme() looking for [" << view << "." << element << "]"; LOG(LogInfo) << "Sound::getFromTheme() looking for [" << view << "." << element << "]";
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "sound"); const ThemeData::ThemeElement* elem = theme->getElement(view, element, "sound");
@ -37,6 +34,73 @@ std::shared_ptr<Sound> Sound::getFromTheme(const std::shared_ptr<ThemeData>& the
return get(elem->get<std::string>("path")); return get(elem->get<std::string>("path"));
} }
void NavigationSounds::loadThemeNavigationSounds(const std::shared_ptr<ThemeData>& theme)
{
systembrowseSound = Sound::getFromTheme(theme, "all", "systembrowseSound");
quicksysselectSound = Sound::getFromTheme(theme, "all", "quicksysselectSound");
selectSound = Sound::getFromTheme(theme, "all", "selectSound");
backSound = Sound::getFromTheme(theme, "all", "backSound");
scrollSound = Sound::getFromTheme(theme, "all", "scrollSound");
favoriteSound = Sound::getFromTheme(theme, "all", "favoriteSound");
launchSound = Sound::getFromTheme(theme, "all", "launchSound");
}
void NavigationSounds::playThemeNavigationSound(NavigationSoundsID soundID)
{
switch(soundID)
{
case SYSTEMBROWSE:
navigationsounds.systembrowseSound->play();
break;
case QUICKSYSSELECT:
navigationsounds.quicksysselectSound->play();
break;
case SELECTSOUND:
navigationsounds.selectSound->play();
break;
case BACKSOUND:
navigationsounds.backSound->play();
break;
case SCROLLSOUND:
navigationsounds.scrollSound->play();
break;
case FAVORITESOUND:
navigationsounds.favoriteSound->play();
break;
case LAUNCHSOUND:
navigationsounds.launchSound->play();
}
}
bool NavigationSounds::isPlayingThemeNavigationSound(NavigationSoundsID soundID)
{
switch(soundID)
{
case SYSTEMBROWSE:
return navigationsounds.systembrowseSound->isPlaying();
break;
case QUICKSYSSELECT:
return navigationsounds.quicksysselectSound->isPlaying();
break;
case SELECTSOUND:
return navigationsounds.selectSound->isPlaying();
break;
case BACKSOUND:
return navigationsounds.backSound->isPlaying();
break;
case SCROLLSOUND:
return navigationsounds.scrollSound->isPlaying();
break;
case FAVORITESOUND:
return navigationsounds.favoriteSound->isPlaying();
break;
case LAUNCHSOUND:
return navigationsounds.launchSound->isPlaying();
}
return false;
}
Sound::Sound(const std::string & path) : mSampleData(NULL), mSamplePos(0), mSampleLength(0), playing(false) Sound::Sound(const std::string & path) : mSampleData(NULL), mSamplePos(0), mSampleLength(0), playing(false)
{ {
loadFile(path); loadFile(path);

View file

@ -43,4 +43,34 @@ private:
static std::map< std::string, std::shared_ptr<Sound> > sMap; static std::map< std::string, std::shared_ptr<Sound> > sMap;
}; };
enum NavigationSoundsID
{
SYSTEMBROWSE,
QUICKSYSSELECT,
SELECTSOUND,
BACKSOUND,
SCROLLSOUND,
FAVORITESOUND,
LAUNCHSOUND
};
class NavigationSounds
{
public:
void loadThemeNavigationSounds(const std::shared_ptr<ThemeData>& theme);
void playThemeNavigationSound(NavigationSoundsID soundID);
bool isPlayingThemeNavigationSound(NavigationSoundsID soundID);
private:
std::shared_ptr<Sound> systembrowseSound;
std::shared_ptr<Sound> quicksysselectSound;
std::shared_ptr<Sound> selectSound;
std::shared_ptr<Sound> backSound;
std::shared_ptr<Sound> scrollSound;
std::shared_ptr<Sound> favoriteSound;
std::shared_ptr<Sound> launchSound;
};
extern NavigationSounds navigationsounds;
#endif // ES_CORE_SOUND_H #endif // ES_CORE_SOUND_H

View file

@ -10,18 +10,10 @@
#include <pugixml/src/pugixml.hpp> #include <pugixml/src/pugixml.hpp>
#include <algorithm> #include <algorithm>
std::vector<std::string> ThemeData::sSupportedViews { { "navigationsounds" }, { "system" }, { "basic" }, { "detailed" }, { "grid" }, { "video" } }; std::vector<std::string> ThemeData::sSupportedViews { { "all" }, { "system" }, { "basic" }, { "detailed" }, { "grid" }, { "video" } };
std::vector<std::string> ThemeData::sSupportedFeatures { { "video" }, { "carousel" }, { "z-index" }, { "visible" } }; std::vector<std::string> ThemeData::sSupportedFeatures { { "navigationsounds" }, { "video" }, { "carousel" }, { "z-index" }, { "visible" } };
std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> ThemeData::sElementMap { std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> ThemeData::sElementMap {
{ "navigationsounds", {
{ "systembrowseSound", PATH },
{ "quicksysselectSound", PATH },
{ "selectSound", PATH },
{ "backSound", PATH },
{ "scrollSound", PATH },
{ "favoriteSound", PATH },
{ "launchSound", PATH } } },
{ "image", { { "image", {
{ "pos", NORMALIZED_PAIR }, { "pos", NORMALIZED_PAIR },
{ "size", NORMALIZED_PAIR }, { "size", NORMALIZED_PAIR },
@ -94,7 +86,7 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> The
{ "secondaryColor", COLOR }, { "secondaryColor", COLOR },
{ "fontPath", PATH }, { "fontPath", PATH },
{ "fontSize", FLOAT }, { "fontSize", FLOAT },
{ "scrollSound", PATH }, { "scrollSound", PATH }, // need to keep this for backwards compatibility with old themes
{ "alignment", STRING }, { "alignment", STRING },
{ "horizontalMargin", FLOAT }, { "horizontalMargin", FLOAT },
{ "forceUppercase", BOOLEAN }, { "forceUppercase", BOOLEAN },
@ -150,6 +142,14 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> The
{ "iconColor", COLOR }, { "iconColor", COLOR },
{ "fontPath", PATH }, { "fontPath", PATH },
{ "fontSize", FLOAT } } }, { "fontSize", FLOAT } } },
{ "navigationsounds", {
{ "systembrowseSound", PATH },
{ "quicksysselectSound", PATH },
{ "selectSound", PATH },
{ "backSound", PATH },
{ "scrollSound", PATH },
{ "favoriteSound", PATH },
{ "launchSound", PATH } } },
{ "video", { { "video", {
{ "pos", NORMALIZED_PAIR }, { "pos", NORMALIZED_PAIR },
{ "size", NORMALIZED_PAIR }, { "size", NORMALIZED_PAIR },