mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 07:35:38 +00:00
Added menu sounds. See THENMES.md for more details.
This commit is contained in:
parent
20aa6d2a6e
commit
ea1a3117a5
4
Makefile
4
Makefile
|
@ -1,7 +1,7 @@
|
|||
CC=g++
|
||||
CFLAGS=-c -Wall -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/usr/include/freetype2 -I/usr/include/SDL -I/usr/include -D_RPI_
|
||||
LDFLAGS=-L/opt/vc/lib -lbcm_host -lEGL -lGLESv2 -lfreetype -lSDL -lboost_system -lboost_filesystem -lfreeimage
|
||||
SRCSOURCES=main.cpp Renderer.cpp Renderer_init.cpp Font.cpp Renderer_draw_gl.cpp GuiComponent.cpp InputManager.cpp SystemData.cpp GameData.cpp FolderData.cpp XMLReader.cpp MathExp.cpp components/GuiGameList.cpp components/GuiInputConfig.cpp components/GuiImage.cpp components/GuiMenu.cpp components/GuiTheme.cpp components/GuiFastSelect.cpp components/GuiBox.cpp pugiXML/pugixml.cpp
|
||||
LDFLAGS=-L/opt/vc/lib -lbcm_host -lEGL -lGLESv2 -lfreetype -lSDL -lboost_system -lboost_filesystem -lfreeimage -lSDL_mixer
|
||||
SRCSOURCES=main.cpp Renderer.cpp Renderer_init.cpp Font.cpp Renderer_draw_gl.cpp GuiComponent.cpp InputManager.cpp SystemData.cpp GameData.cpp FolderData.cpp XMLReader.cpp MathExp.cpp components/GuiGameList.cpp components/GuiInputConfig.cpp components/GuiImage.cpp components/GuiMenu.cpp components/GuiTheme.cpp components/GuiFastSelect.cpp components/GuiBox.cpp AudioManager.cpp Sound.cpp pugiXML/pugixml.cpp
|
||||
SOURCES=$(addprefix src/,$(SRCSOURCES))
|
||||
OBJECTS=$(SOURCES:.cpp=.o)
|
||||
EXECUTABLE=emulationstation
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
CC=g++
|
||||
CFLAGS=-c -Wall -I/usr/include/freetype2 -I/usr/include/SDL -I/usr/include -D_DESKTOP_ -g
|
||||
LDFLAGS=-lGL -lfreetype -lSDL -lboost_system -lboost_filesystem -lfreeimage
|
||||
SRCSOURCES=main.cpp Renderer.cpp Renderer_init.cpp Font.cpp Renderer_draw_gl.cpp GuiComponent.cpp InputManager.cpp SystemData.cpp GameData.cpp FolderData.cpp XMLReader.cpp MathExp.cpp components/GuiGameList.cpp components/GuiInputConfig.cpp components/GuiImage.cpp components/GuiMenu.cpp components/GuiTheme.cpp components/GuiFastSelect.cpp components/GuiBox.cpp pugiXML/pugixml.cpp
|
||||
LDFLAGS=-lGL -lfreetype -lSDL -lboost_system -lboost_filesystem -lfreeimage -lSDL_mixer
|
||||
SRCSOURCES=main.cpp Renderer.cpp Renderer_init.cpp Font.cpp Renderer_draw_gl.cpp GuiComponent.cpp InputManager.cpp SystemData.cpp GameData.cpp FolderData.cpp XMLReader.cpp MathExp.cpp components/GuiGameList.cpp components/GuiInputConfig.cpp components/GuiImage.cpp components/GuiMenu.cpp components/GuiTheme.cpp components/GuiFastSelect.cpp components/GuiBox.cpp Sound.cpp AudioManager.cpp pugiXML/pugixml.cpp
|
||||
SOURCES=$(addprefix src/,$(SRCSOURCES))
|
||||
OBJECTS=$(SOURCES:.cpp=.o)
|
||||
EXECUTABLE=emulationstation
|
||||
|
|
|
@ -98,6 +98,14 @@ The Fast Select box can be themed with these tags:
|
|||
`<boxCorner>` - path to the "top left corner" image file. It will be flipped for the top right, bottom right, and bottom left corners. ~ and . are expanded.
|
||||
|
||||
|
||||
Audio
|
||||
=====
|
||||
|
||||
Themes can also define menu sounds. Sounds should be in the .wav format.
|
||||
|
||||
`<menuScrollSound>` - path to the sound to play when the game list is scrolling.
|
||||
|
||||
|
||||
List of variables
|
||||
=================
|
||||
|
||||
|
|
98
src/AudioManager.cpp
Normal file
98
src/AudioManager.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include "AudioManager.h"
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_mixer.h"
|
||||
#include <iostream>
|
||||
#include "Sound.h"
|
||||
#include <vector>
|
||||
|
||||
namespace AudioManager
|
||||
{
|
||||
std::vector<Sound*> sSoundVector;
|
||||
|
||||
bool sInitialized = false;
|
||||
|
||||
void init()
|
||||
{
|
||||
int result = Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, AUDIO_S16SYS, 2, 1024);
|
||||
|
||||
if(result == -1)
|
||||
{
|
||||
std::cerr << "Error initializing AudioManager!\n";
|
||||
std::cerr << " " << Mix_GetError() << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
sInitialized = true;
|
||||
|
||||
for(unsigned int i = 0; i < sSoundVector.size(); i++)
|
||||
{
|
||||
sSoundVector.at(i)->init();
|
||||
}
|
||||
}
|
||||
|
||||
void registerSound(Sound* sound)
|
||||
{
|
||||
sSoundVector.push_back(sound);
|
||||
}
|
||||
|
||||
void unregisterSound(Sound* sound)
|
||||
{
|
||||
for(unsigned int i = 0; i < sSoundVector.size(); i++)
|
||||
{
|
||||
if(sSoundVector.at(i) == sound)
|
||||
{
|
||||
sSoundVector.erase(sSoundVector.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "AudioManager Error - tried to unregister a sound that wasn't registered!\n";
|
||||
}
|
||||
|
||||
void test()
|
||||
{
|
||||
Mix_Chunk* sound = NULL;
|
||||
sound = Mix_LoadWAV("test.wav");
|
||||
|
||||
if(sound == NULL)
|
||||
{
|
||||
std::cerr << "Error loading test sound!\n";
|
||||
std::cerr << " " << Mix_GetError() << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int channel = -1;
|
||||
|
||||
//third argument is play count, -1 = infinite loop, 0 = once
|
||||
channel = Mix_PlayChannel(-1, sound, 0);
|
||||
|
||||
if(channel == -1)
|
||||
{
|
||||
std::cerr << "Error playing sound!\n";
|
||||
std::cerr << " " << Mix_GetError() << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
while(Mix_Playing(channel) != 0);
|
||||
Mix_FreeChunk(sound);
|
||||
|
||||
}
|
||||
|
||||
void deinit()
|
||||
{
|
||||
for(unsigned int i = 0; i < sSoundVector.size(); i++)
|
||||
{
|
||||
sSoundVector.at(i)->deinit();
|
||||
}
|
||||
|
||||
Mix_CloseAudio();
|
||||
|
||||
sInitialized = false;
|
||||
}
|
||||
|
||||
bool isInitialized()
|
||||
{
|
||||
return sInitialized;
|
||||
}
|
||||
}
|
18
src/AudioManager.h
Normal file
18
src/AudioManager.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef _AUDIOMANAGER_H_
|
||||
#define _AUDIOMANAGER_H_
|
||||
|
||||
class Sound;
|
||||
|
||||
namespace AudioManager
|
||||
{
|
||||
void registerSound(Sound* sound);
|
||||
void unregisterSound(Sound* sound);
|
||||
|
||||
bool isInitialized();
|
||||
|
||||
void init();
|
||||
void test();
|
||||
void deinit();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -64,11 +64,12 @@ namespace Renderer {
|
|||
//make sure our font exists
|
||||
if(!boost::filesystem::exists(fontPath))
|
||||
{
|
||||
std::cout << "Default font \"" << fontPath << "\" does not exist! Attempting to default to a system font...\n";
|
||||
std::cout << "Default font \"" << fontPath << "\" does not exist! Attempting to default to a system font...";
|
||||
fontPath = "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf";
|
||||
if(!boost::filesystem::exists(fontPath))
|
||||
{
|
||||
std::cerr << "System font \"" << fontPath << "\" wasn't found either! Well, you're kind of screwed. Sorry.\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,10 @@ namespace Renderer
|
|||
{
|
||||
std::cout << "Creating surface...";
|
||||
|
||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0)
|
||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) != 0)
|
||||
{
|
||||
std::cerr << "Error initializing SDL!\n";
|
||||
std::cerr << " " << SDL_GetError() << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
78
src/Sound.cpp
Normal file
78
src/Sound.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
#include "Sound.h"
|
||||
#include <iostream>
|
||||
#include "AudioManager.h"
|
||||
|
||||
Sound::Sound(std::string path)
|
||||
{
|
||||
mSound = NULL;
|
||||
|
||||
AudioManager::registerSound(this);
|
||||
|
||||
loadFile(path);
|
||||
}
|
||||
|
||||
Sound::~Sound()
|
||||
{
|
||||
deinit();
|
||||
|
||||
AudioManager::unregisterSound(this);
|
||||
}
|
||||
|
||||
void Sound::loadFile(std::string path)
|
||||
{
|
||||
mPath = path;
|
||||
init();
|
||||
}
|
||||
|
||||
void Sound::init()
|
||||
{
|
||||
if(!AudioManager::isInitialized())
|
||||
return;
|
||||
|
||||
if(mSound != NULL)
|
||||
deinit();
|
||||
|
||||
if(mPath.empty())
|
||||
return;
|
||||
|
||||
mSound = Mix_LoadWAV(mPath.c_str());
|
||||
|
||||
if(mSound == NULL)
|
||||
{
|
||||
std::cerr << "Error loading sound \"" << mPath << "\"!\n";
|
||||
std::cerr << " " << Mix_GetError() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void Sound::deinit()
|
||||
{
|
||||
if(mSound != NULL)
|
||||
{
|
||||
Mix_FreeChunk(mSound);
|
||||
mSound = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Sound::play()
|
||||
{
|
||||
if(mSound == NULL)
|
||||
return;
|
||||
|
||||
mChannel = -1;
|
||||
|
||||
mChannel = Mix_PlayChannel(-1, mSound, 0);
|
||||
if(mChannel == -1)
|
||||
{
|
||||
std::cerr << "Error playing sound!\n";
|
||||
std::cerr << " " << Mix_GetError() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool Sound::isPlaying()
|
||||
{
|
||||
if(mChannel != -1 && Mix_Playing(mChannel))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
26
src/Sound.h
Normal file
26
src/Sound.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef _SOUND_H_
|
||||
#define _SOUND_H_
|
||||
|
||||
#include <string>
|
||||
#include "SDL_mixer.h"
|
||||
|
||||
class Sound
|
||||
{
|
||||
public:
|
||||
Sound(std::string path = "");
|
||||
~Sound();
|
||||
|
||||
void init();
|
||||
void deinit();
|
||||
|
||||
void loadFile(std::string path);
|
||||
|
||||
void play();
|
||||
bool isPlaying();
|
||||
private:
|
||||
std::string mPath;
|
||||
int mChannel;
|
||||
Mix_Chunk* mSound;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -6,6 +6,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <SDL/SDL_joystick.h>
|
||||
#include "Renderer.h"
|
||||
#include "AudioManager.h"
|
||||
|
||||
std::vector<SystemData*> SystemData::sSystemVector;
|
||||
|
||||
|
@ -74,6 +75,7 @@ void SystemData::launchGame(GameData* game)
|
|||
//suspend SDL joystick events (these'll pile up even while something else is running)
|
||||
SDL_JoystickEventState(0);
|
||||
|
||||
AudioManager::deinit();
|
||||
Renderer::deinit();
|
||||
|
||||
std::string command = mLaunchCommand;
|
||||
|
@ -88,6 +90,7 @@ void SystemData::launchGame(GameData* game)
|
|||
std::cout << "...launch terminated!\n";
|
||||
|
||||
Renderer::init(0, 0);
|
||||
AudioManager::init();
|
||||
|
||||
//re-enable SDL joystick events
|
||||
SDL_JoystickEventState(1);
|
||||
|
|
|
@ -206,6 +206,7 @@ void GuiGameList::updateTheme()
|
|||
mList->setSelectorColor(mTheme->getSelectorColor());
|
||||
mList->setSelectedTextColor(mTheme->getSelectedTextColor());
|
||||
mList->setCentered(mTheme->getListCentered());
|
||||
mList->setScrollSound(mTheme->getMenuScrollSound());
|
||||
|
||||
if(mDetailed)
|
||||
{
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "../GameData.h"
|
||||
#include "../FolderData.h"
|
||||
|
||||
|
||||
//This is where the magic happens - GuiGameList is the parent of almost every graphical element in ES at the moment.
|
||||
//It has a GuiList child that handles the game list, a GuiTheme that handles the theming system, and a GuiImage for game images.
|
||||
class GuiGameList : GuiComponent
|
||||
|
|
|
@ -19,7 +19,7 @@ GuiList<listType>::GuiList(int offsetX, int offsetY, Renderer::FontSize fontsize
|
|||
mFont = fontsize;
|
||||
mSelectorColor = 0x000000;
|
||||
mSelectedTextColorOverride = -1;
|
||||
|
||||
mScrollSound = NULL;
|
||||
mDrawCentered = true;
|
||||
|
||||
InputManager::registerComponent(this);
|
||||
|
@ -92,13 +92,13 @@ void GuiList<listType>::onInput(InputManager::InputButton button, bool keyDown)
|
|||
if(button == InputManager::DOWN)
|
||||
{
|
||||
mScrollDir = 1;
|
||||
mSelection++;
|
||||
scroll();
|
||||
}
|
||||
|
||||
if(button == InputManager::UP)
|
||||
{
|
||||
mScrollDir = -1;
|
||||
mSelection--;
|
||||
scroll();
|
||||
}
|
||||
}else{
|
||||
if((button == InputManager::DOWN && mScrollDir > 0) || (button == InputManager::UP && mScrollDir < 0))
|
||||
|
@ -108,12 +108,6 @@ void GuiList<listType>::onInput(InputManager::InputButton button, bool keyDown)
|
|||
mScrollDir = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(mSelection < 0)
|
||||
mSelection += mRowVector.size();
|
||||
|
||||
if(mSelection >= (int)mRowVector.size())
|
||||
mSelection -= mRowVector.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,16 +135,26 @@ void GuiList<listType>::onTick(int deltaTime)
|
|||
{
|
||||
mScrollAccumulator -= SCROLLTIME;
|
||||
|
||||
mSelection += mScrollDir;
|
||||
if(mSelection < 0)
|
||||
mSelection += mRowVector.size();
|
||||
if(mSelection >= (int)mRowVector.size())
|
||||
mSelection -= mRowVector.size();
|
||||
scroll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename listType>
|
||||
void GuiList<listType>::scroll()
|
||||
{
|
||||
mSelection += mScrollDir;
|
||||
|
||||
if(mSelection < 0)
|
||||
mSelection += mRowVector.size();
|
||||
if(mSelection >= (int)mRowVector.size())
|
||||
mSelection -= mRowVector.size();
|
||||
|
||||
if(mScrollSound)
|
||||
mScrollSound->play();
|
||||
}
|
||||
|
||||
//list management stuff
|
||||
template <typename listType>
|
||||
void GuiList<listType>::addObject(std::string name, listType obj, int color)
|
||||
|
@ -249,3 +253,9 @@ void GuiList<listType>::setSelection(int i)
|
|||
{
|
||||
mSelection = i;
|
||||
}
|
||||
|
||||
template <typename listType>
|
||||
void GuiList<listType>::setScrollSound(Sound* sound)
|
||||
{
|
||||
mScrollSound = sound;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "../InputManager.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "../Sound.h"
|
||||
|
||||
//A graphical list. Supports multiple colors for rows and scrolling.
|
||||
//TODO - add truncation to text rendering if name exceeds a maximum width (a trailing elipses, perhaps).
|
||||
|
@ -34,7 +35,7 @@ public:
|
|||
void setSelectorColor(int selectorColor);
|
||||
void setSelectedTextColor(int selectedColor);
|
||||
void setCentered(bool centered);
|
||||
|
||||
void setScrollSound(Sound* sound);
|
||||
void setTextOffsetX(int textoffsetx);
|
||||
|
||||
int getObjectCount();
|
||||
|
@ -45,6 +46,8 @@ private:
|
|||
static const int SCROLLDELAY = 507;
|
||||
static const int SCROLLTIME = 200;
|
||||
|
||||
void scroll(); //helper method, scrolls in whatever direction scrollDir is
|
||||
|
||||
int mScrollDir, mScrollAccumulator;
|
||||
bool mScrolling;
|
||||
|
||||
|
@ -63,6 +66,7 @@ private:
|
|||
|
||||
std::vector<ListRow> mRowVector;
|
||||
int mSelection;
|
||||
Sound* mScrollSound;
|
||||
};
|
||||
|
||||
#include "GuiList.cpp"
|
||||
|
|
|
@ -24,6 +24,8 @@ int GuiTheme::getSelectedTextColor() { return mListSelectedColor; }
|
|||
|
||||
GuiBoxData GuiTheme::getBoxData() { return mBoxData; }
|
||||
|
||||
Sound* GuiTheme::getMenuScrollSound() { return &mMenuScrollSound; }
|
||||
|
||||
GuiTheme::GuiTheme(std::string path)
|
||||
{
|
||||
setDefaults();
|
||||
|
@ -60,6 +62,8 @@ void GuiTheme::setDefaults()
|
|||
mBoxData.verticalPath = "";
|
||||
mBoxData.verticalTiled = false;
|
||||
mBoxData.cornerPath = "";
|
||||
|
||||
mMenuScrollSound.loadFile("");
|
||||
}
|
||||
|
||||
void GuiTheme::deleteComponents()
|
||||
|
@ -127,10 +131,11 @@ void GuiTheme::readXML(std::string path)
|
|||
mGameImageOffsetY = strToFloat(root.child("gameImageOffsetY").text().get(), mGameImageOffsetY);
|
||||
mListTextOffsetX = strToFloat(root.child("listTextOffsetX").text().get(), mListTextOffsetX);
|
||||
|
||||
//sounds
|
||||
mMenuScrollSound.loadFile(root.child("menuScrollSound").text().get());
|
||||
|
||||
//recursively create children for all <components> with proper parenting
|
||||
createComponentChildren(root, this);
|
||||
|
||||
//std::cout << "Finished parsing theme.\n";
|
||||
}
|
||||
|
||||
void GuiTheme::createComponentChildren(pugi::xml_node node, GuiComponent* parent)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../GuiComponent.h"
|
||||
#include "../pugiXML/pugixml.hpp"
|
||||
#include "GuiBox.h"
|
||||
#include "../Sound.h"
|
||||
|
||||
//This class loads an XML-defined list of GuiComponents.
|
||||
class GuiTheme : public GuiComponent
|
||||
|
@ -29,6 +30,8 @@ public:
|
|||
float getGameImageOffsetY();
|
||||
|
||||
GuiBoxData getBoxData();
|
||||
|
||||
Sound* getMenuScrollSound();
|
||||
private:
|
||||
void setDefaults();
|
||||
void deleteComponents();
|
||||
|
@ -50,6 +53,8 @@ private:
|
|||
float mListOffsetX, mGameImageOffsetY, mListTextOffsetX;
|
||||
|
||||
GuiBoxData mBoxData;
|
||||
|
||||
Sound mMenuScrollSound;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <boost/filesystem.hpp>
|
||||
#include "components/GuiInputConfig.h"
|
||||
#include <SDL.h>
|
||||
#include "AudioManager.h"
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
@ -71,7 +72,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
bool running = true;
|
||||
|
||||
//the renderer also takes care of setting up SDL for input
|
||||
//the renderer also takes care of setting up SDL for input and sound
|
||||
bool renderInit = Renderer::init(width, height);
|
||||
if(!renderInit)
|
||||
{
|
||||
|
@ -80,9 +81,12 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
//initialize audio
|
||||
AudioManager::init();
|
||||
|
||||
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
|
||||
//make sure the config directory exists
|
||||
std::string home = getenv("HOME");
|
||||
std::string configDir = home + "/.emulationstation";
|
||||
|
@ -171,6 +175,7 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
|
||||
AudioManager::deinit();
|
||||
Renderer::deleteAll();
|
||||
Renderer::deinit();
|
||||
SystemData::deleteSystems();
|
||||
|
|
Loading…
Reference in a new issue