From 07f7761479eba5defdcfe0bd300bc438d9245551 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 22 Oct 2006 15:42:29 +0000 Subject: Backend modularization: Create timer manager, savefile manager and audio mixer in the backends for increased flexibility svn-id: r24443 --- backends/platform/PalmOS/Src/be_base.cpp | 2 + backends/platform/ds/arm9/source/osystem_ds.cpp | 2 + backends/platform/gp2x/gp2x.cpp | 2 + backends/platform/sdl/sdl-common.h | 22 +++++++++- backends/platform/sdl/sdl.cpp | 51 ++++++++++++++++++++++ backends/platform/wince/wince-sdl.cpp | 6 +++ backends/platform/x11/x11.cpp | 3 +- backends/timer/default/default-timer.cpp | 43 ++++-------------- backends/timer/default/default-timer.h | 6 +-- base/main.cpp | 19 -------- common/system.cpp | 21 +-------- common/system.h | 58 +++++++------------------ common/timer.h | 2 - engines/saga/render.cpp | 4 +- engines/scumm/smush/smush_player.cpp | 2 +- sound/mixer.cpp | 16 +++---- sound/mixer.h | 9 ++-- sound/mods/protracker.cpp | 3 +- sound/softsynth/mt32.cpp | 4 +- 19 files changed, 134 insertions(+), 141 deletions(-) diff --git a/backends/platform/PalmOS/Src/be_base.cpp b/backends/platform/PalmOS/Src/be_base.cpp index ea3f28a45f..ad28299193 100644 --- a/backends/platform/PalmOS/Src/be_base.cpp +++ b/backends/platform/PalmOS/Src/be_base.cpp @@ -83,6 +83,8 @@ void OSystem_PalmBase::initBackend() { int_initBackend(); _keyMouseMask = (_keyMouse.bitUp | _keyMouse.bitDown | _keyMouse.bitLeft | _keyMouse.bitRight | _keyMouse.bitButLeft); + + OSystem::initBackend(); } uint32 OSystem_PalmBase::getMillis() { diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp index 0d3e1fdd75..12d3b0ad01 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.cpp +++ b/backends/platform/ds/arm9/source/osystem_ds.cpp @@ -52,6 +52,8 @@ OSystem_DS::~OSystem_DS() { void OSystem_DS::initBackend() { ConfMan.setInt("autosave_period", 0); ConfMan.setBool("FM_low_quality", true); + + OSystem::initBackend(); } bool OSystem_DS::hasFeature(Feature f) { diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp index 4ecbb928ca..975c64a7ab 100644 --- a/backends/platform/gp2x/gp2x.cpp +++ b/backends/platform/gp2x/gp2x.cpp @@ -145,6 +145,8 @@ void OSystem_GP2X::initBackend() { SDL_ShowCursor(SDL_DISABLE); + OSystem::initBackend(); + _inited = true; } diff --git a/backends/platform/sdl/sdl-common.h b/backends/platform/sdl/sdl-common.h index 093e7950f9..aeb9c5bf37 100644 --- a/backends/platform/sdl/sdl-common.h +++ b/backends/platform/sdl/sdl-common.h @@ -33,6 +33,15 @@ #include "backends/intern.h" +namespace Audio { + class Mixer; +} + +namespace Common { + class SaveFileManager; + class TimerManager; +} + #if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) // Uncomment this to enable the 'on screen display' code. #define USE_OSD 1 @@ -124,9 +133,10 @@ public: virtual bool pollEvent(Event &event); // overloaded by CE backend // Set function that generates samples + typedef void (*SoundProc)(void *param, byte *buf, int len); virtual bool setSoundCallback(SoundProc proc, void *param); // overloaded by CE backend - void clearSoundCallback(); + virtual Audio::Mixer *getMixer(); // Poll CD status // Returns true if cd audio is playing @@ -146,7 +156,9 @@ public: // Add a callback timer + typedef int (*TimerProc)(int interval); void setTimerCallback(TimerProc callback, int timer); + virtual Common::TimerManager *getTimerManager(); // Mutex handling MutexRef createMutex(); @@ -187,6 +199,8 @@ public: void displayMessageOnOSD(const char *msg); #endif + virtual Common::SaveFileManager *getSavefileManager(); + protected: bool _inited; @@ -357,6 +371,12 @@ protected: MutexRef _graphicsMutex; + Common::SaveFileManager *_savefile; + Audio::Mixer *_mixer; + Common::TimerManager *_timer; + + + void addDirtyRgnAuto(const byte *buf); void makeChecksums(const byte *buf); diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index 21f5935c58..b4677eac0f 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -27,6 +27,10 @@ #include "common/util.h" #include "base/main.h" +#include "backends/saves/default/default-saves.h" +#include "backends/timer/default/default-timer.h" +#include "sound/mixer.h" + #include "icons/scummvm.xpm" #if defined(__SYMBIAN32__) @@ -42,6 +46,11 @@ int __stdcall WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/, LPSTR /*lpC } #endif +static int timer_handler(int t) { + DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager(); + return tm->handler(t); +} + int main(int argc, char *argv[]) { #if defined(__SYMBIAN32__) @@ -169,6 +178,29 @@ void OSystem_SDL::initBackend() { printf("Using joystick: %s\n", SDL_JoystickName(0)); _joystick = SDL_JoystickOpen(joystick_num); } + + + // Create the savefile manager, if none exists yet (we check for this to + // allow subclasses to provide their own). + if (_savefile == 0) { + _savefile = new DefaultSaveFileManager(); + } + + // Create and hook up the mixer, if none exists yet (we check for this to + // allow subclasses to provide their own). + if (_mixer == 0) { + _mixer = new Audio::Mixer(); + setSoundCallback(Audio::Mixer::mixCallback, _mixer); + } + + // Create and hook up the timer manager, if none exists yet (we check for + // this to allow subclasses to provide their own). + if (_timer == 0) { + _timer = new DefaultTimerManager(); + setTimerCallback(&timer_handler, 10); + } + + OSystem::initBackend(); _inited = true; } @@ -189,6 +221,9 @@ OSystem_SDL::OSystem_SDL() _joystick(0), _currentShakePos(0), _newShakePos(0), _paletteDirtyStart(0), _paletteDirtyEnd(0), + _savefile(0), + _mixer(0), + _timer(0), _graphicsMutex(0), _transactionMode(kTransactionNone) { // allocate palette storage @@ -223,6 +258,16 @@ void OSystem_SDL::setTimerCallback(TimerProc callback, int timer) { SDL_SetTimer(timer, (SDL_TimerCallback) callback); } +Common::TimerManager *OSystem_SDL::getTimerManager() { + assert(_timer); + return _timer; +} + +Common::SaveFileManager *OSystem_SDL::getSavefileManager() { + assert(_savefile); + return _savefile; +} + void OSystem_SDL::setWindowCaption(const char *caption) { SDL_WM_SetCaption(caption, caption); } @@ -395,6 +440,7 @@ bool OSystem_SDL::setSoundCallback(SoundProc proc, void *param) { // least on some platforms SDL will lie and claim it did get the rate // even if it didn't. Probably only happens for "weird" rates, though. _samplesPerSec = obtained.freq; + debug(1, "Output sample rate: %d Hz", _samplesPerSec); SDL_PauseAudio(0); return true; } @@ -407,6 +453,11 @@ int OSystem_SDL::getOutputSampleRate() const { return _samplesPerSec; } +Audio::Mixer *OSystem_SDL::getMixer() { + assert(_mixer); + return _mixer; +} + #pragma mark - #pragma mark --- CD Audio --- #pragma mark - diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp index 4dc7d7c410..d41fe5eba6 100644 --- a/backends/platform/wince/wince-sdl.cpp +++ b/backends/platform/wince/wince-sdl.cpp @@ -246,6 +246,12 @@ void OSystem_WINCE3::initBackend() GUI_Actions::Instance()->loadMapping(); loadDeviceConfiguration(); + + // FIXME: We are currently not calling OSystem_SDL::initBackend() here. + // Maybe on purpose, but this is possibly a bit risky... E.g. _inited + // won't be set correctly due to this... Can we change this? Maybe after + // some changes to the base SDL backend? + //OSystem_SDL::initBackend(); } int OSystem_WINCE3::getScreenWidth() { diff --git a/backends/platform/x11/x11.cpp b/backends/platform/x11/x11.cpp index 7db5066c44..a16fbe8adc 100644 --- a/backends/platform/x11/x11.cpp +++ b/backends/platform/x11/x11.cpp @@ -205,7 +205,8 @@ out_of_loop: /* And finally start the local timer */ gettimeofday(&_start_time, NULL); - + + OSystem::initBackend(); } #undef CAPTURE_SOUND diff --git a/backends/timer/default/default-timer.cpp b/backends/timer/default/default-timer.cpp index 907c715a07..245291c06c 100644 --- a/backends/timer/default/default-timer.cpp +++ b/backends/timer/default/default-timer.cpp @@ -25,61 +25,34 @@ #include "common/util.h" #include "common/system.h" -namespace Common { -// FIXME: Hack: This global variable shouldn't be declared here; in fact it -// probably shouldn't be declared at all but rather a different method to -// query the TimerManager object should be invented. -TimerManager *g_timer = NULL; -} - -DefaultTimerManager::DefaultTimerManager(OSystem *system) : - _system(system), +DefaultTimerManager::DefaultTimerManager() : _timerHandler(0), _lastTime(0) { - Common::g_timer = this; - for (int i = 0; i < MAX_TIMERS; i++) { _timerSlots[i].procedure = NULL; _timerSlots[i].interval = 0; _timerSlots[i].counter = 0; } - _thisTime = _system->getMillis(); - - // Set the timer last, after everything has been initialised - _system->setTimerCallback(&timer_handler, 10); - + _thisTime = g_system->getMillis(); } DefaultTimerManager::~DefaultTimerManager() { - // Remove the timer callback. - // Note: backends *must* gurantee that after this method call returns, - // the handler is not in use anymore; else race condtions could occur. - _system->setTimerCallback(0, 0); - - { - Common::StackLock lock(_mutex); - for (int i = 0; i < MAX_TIMERS; i++) { - _timerSlots[i].procedure = NULL; - _timerSlots[i].interval = 0; - _timerSlots[i].counter = 0; - } + Common::StackLock lock(_mutex); + for (int i = 0; i < MAX_TIMERS; i++) { + _timerSlots[i].procedure = NULL; + _timerSlots[i].interval = 0; + _timerSlots[i].counter = 0; } } -int DefaultTimerManager::timer_handler(int t) { - if (Common::g_timer) - return ((DefaultTimerManager *)Common::g_timer)->handler(t); - return 0; -} - int DefaultTimerManager::handler(int t) { Common::StackLock lock(_mutex); uint32 interval, l; _lastTime = _thisTime; - _thisTime = _system->getMillis(); + _thisTime = g_system->getMillis(); interval = 1000 * (_thisTime - _lastTime); for (l = 0; l < MAX_TIMERS; l++) { diff --git a/backends/timer/default/default-timer.h b/backends/timer/default/default-timer.h index 12779cc59c..8c16122b02 100644 --- a/backends/timer/default/default-timer.h +++ b/backends/timer/default/default-timer.h @@ -32,7 +32,6 @@ private: enum { MAX_TIMERS = 8 }; - OSystem *_system; Common::Mutex _mutex; void *_timerHandler; int32 _thisTime; @@ -46,13 +45,12 @@ private: } _timerSlots[MAX_TIMERS]; public: - DefaultTimerManager(OSystem *system); + DefaultTimerManager(); ~DefaultTimerManager(); bool installTimerProc(TimerProc proc, int32 interval, void *refCon); void removeTimerProc(TimerProc proc); -protected: - static int timer_handler(int t); + // Timer callback, to be invoked at regular time intervals by the backend. int handler(int t); }; diff --git a/base/main.cpp b/base/main.cpp index 6c97e4243b..8eb981f894 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -35,16 +35,12 @@ #include "base/plugins.h" #include "base/version.h" -#include "backends/timer/default/default-timer.h" #include "common/config-manager.h" #include "common/file.h" #include "common/fs.h" #include "common/system.h" -#include "common/timer.h" #include "gui/newgui.h" #include "gui/message.h" -#include "sound/mididrv.h" -#include "sound/mixer.h" #if defined(_WIN32_WCE) #include "backends/platform/wince/CELauncherDialog.h" @@ -227,10 +223,6 @@ static int runGame(const Plugin *plugin, OSystem &system, const Common::String & } -// FIXME: Temporary hack, to be removed soon -Audio::Mixer *g_mixer = 0; - - extern "C" int scummvm_main(int argc, char *argv[]) { Common::String specialDebug; Common::String command; @@ -288,11 +280,6 @@ extern "C" int scummvm_main(int argc, char *argv[]) { // the command line params) was read. system.initBackend(); - // Create the timer services - Common::g_timer = new DefaultTimerManager(&system); - - g_mixer = new Audio::Mixer(); - // Set initial window caption system.setWindowCaption(gScummVMFullVersion); @@ -336,11 +323,5 @@ extern "C" int scummvm_main(int argc, char *argv[]) { launcherDialog(system); } - // Deinit the mixer - delete g_mixer; - - // Deinit the timer - delete Common::g_timer; - return 0; } diff --git a/common/system.cpp b/common/system.cpp index d15f026df0..7231338a85 100644 --- a/common/system.cpp +++ b/common/system.cpp @@ -27,13 +27,13 @@ #include "gui/message.h" -#include "backends/saves/default/default-saves.h" - #include "common/config-manager.h" #include "common/system.h" #include "common/timer.h" #include "common/util.h" +#include "sound/mixer.h" + OSystem *g_system = 0; bool OSystem::setGraphicsMode(const char *name) { @@ -63,23 +63,6 @@ void OSystem::displayMessageOnOSD(const char *msg) { dialog.runModal(); } -Common::SaveFileManager *OSystem::getSavefileManager() { - // TODO: Change this to always return the same - // instance, instead of a new one each time around... - return new DefaultSaveFileManager(); -} - -Audio::Mixer *OSystem::getMixer() { - // FIXME - extern Audio::Mixer *g_mixer; - return g_mixer; -} - -Common::TimerManager *OSystem::getTimerManager() { - // FIXME - return Common::g_timer; -} - bool OSystem::openCD(int drive) { return false; diff --git a/common/system.h b/common/system.h index 1682426ab0..bd0caf4575 100644 --- a/common/system.h +++ b/common/system.h @@ -66,6 +66,10 @@ public: /** * The following method is called once, from main.cpp, after all * config data (including command line params etc.) are fully loaded. + * + * @note Subclasses should always invoke the implementation of their + * parent class. They should so so near the end of their own + * implementation. */ virtual void initBackend() { } @@ -675,8 +679,6 @@ public: /** @name Events and Time */ //@{ - typedef int (*TimerProc)(int interval); - /** * The types of events backends may generate. * @see Event @@ -798,24 +800,10 @@ public: virtual void delayMillis(uint msecs) = 0; /** - * Set the timer callback, a function which is periodically invoked by the - * backend. This can for example be done via a background thread. - * There is at most one active timer; if this method is called while there - * is already an active timer, then the new timer callback should replace - * the previous one. In particular, passing a callback pointer value of 0 - * is legal and can be used to clear the current timer callback. - * @see Common::Timer - * @note The implementation of this method must be 'atomic' in the sense - * that when the method returns, the previously set callback must - * not be in use anymore (in particular, if timers are implemented - * via threads, then it must be ensured that the timer thread is - * not using the old callback function anymore). - * - * @param callback pointer to the callback. May be 0 to reset the timer - * @param interval the interval (in milliseconds) between invocations - * of the callback + * Returh the timer manager. For more information, refer to the + * TimerManager documentation. */ - virtual void setTimerCallback(TimerProc callback, int interval) = 0; + virtual Common::TimerManager *getTimerManager() = 0; //@} @@ -870,22 +858,12 @@ public: /** @name Sound */ //@{ - typedef void (*SoundProc)(void *param, byte *buf, int len); - - /** - * Set the audio callback which is invoked whenever samples need to be generated. - * Currently, only the 16-bit signed mode is ever used for Simon & Scumm - * @param proc pointer to the callback. - * @param param an arbitrary parameter which is stored and passed to proc. - */ - virtual bool setSoundCallback(SoundProc proc, void *param) = 0; /** - * Remove any audio callback previously set via setSoundCallback, thus effectively - * stopping all audio output immediately. - * @see setSoundCallback + * Returh the audio mixer. For more information, refer to the + * Audio::Mixer documentation. */ - virtual void clearSoundCallback() = 0; + virtual Audio::Mixer *getMixer() = 0; /** * Determine the output sample rate. Audio data provided by the sound @@ -972,15 +950,12 @@ public: */ virtual void displayMessageOnOSD(const char *msg); - /** Savefile management. */ - virtual Common::SaveFileManager *getSavefileManager(); - - - /** TODO */ - virtual Audio::Mixer *getMixer(); - - /** TODO */ - virtual Common::TimerManager *getTimerManager(); + /** + * Return the SaveFileManager, used to store and load savestates + * and other modifiable persistent game data. For more information, + * refer to the TimerManager documentation. + */ + virtual Common::SaveFileManager *getSavefileManager() = 0; //@} }; @@ -989,5 +964,4 @@ public: /** The global OSystem instance. Initialised in main(). */ extern OSystem *g_system; - #endif diff --git a/common/timer.h b/common/timer.h index a870784bf4..7f660e7742 100644 --- a/common/timer.h +++ b/common/timer.h @@ -52,8 +52,6 @@ public: virtual void removeTimerProc(TimerProc proc) = 0; }; -extern TimerManager *g_timer; - } // End of namespace Common #endif diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp index 7d312fb920..33e49a4653 100644 --- a/engines/saga/render.cpp +++ b/engines/saga/render.cpp @@ -48,7 +48,7 @@ Render::Render(SagaEngine *vm, OSystem *system) { _initialized = false; // Initialize FPS timer callback - Common::g_timer->installTimerProc(&fpsTimerCallback, 1000000, this); + _vm->_timer->installTimerProc(&fpsTimerCallback, 1000000, this); _backGroundSurface.create(_vm->getDisplayWidth(), _vm->getDisplayHeight(), 1); @@ -58,7 +58,7 @@ Render::Render(SagaEngine *vm, OSystem *system) { } Render::~Render(void) { - Common::g_timer->removeTimerProc(&fpsTimerCallback); + _vm->_timer->removeTimerProc(&fpsTimerCallback); _backGroundSurface.free(); _initialized = false; diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp index 246016dc8e..8c5554b9c2 100644 --- a/engines/scumm/smush/smush_player.cpp +++ b/engines/scumm/smush/smush_player.cpp @@ -308,7 +308,7 @@ void SmushPlayer::init(int32 speed) { _vm->_mixer->stopHandle(_IACTchannel); _vm->_smixer->stop(); - Common::g_timer->installTimerProc(&timerCallback, 1000000 / _speed, this); + _vm->_timer->installTimerProc(&timerCallback, 1000000 / _speed, this); _initDone = true; } diff --git a/sound/mixer.cpp b/sound/mixer.cpp index 5e26c04f66..ad203ece5b 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -119,23 +119,20 @@ Mixer::Mixer() { for (i = 0; i != NUM_CHANNELS; i++) _channels[i] = 0; - _mixerReady = _syst->setSoundCallback(mixCallback, this); - _outputRate = (uint)_syst->getOutputSampleRate(); - - if (_outputRate == 0) - error("OSystem returned invalid sample rate"); - - debug(1, "Output sample rate: %d Hz", _outputRate); + _mixerReady = false; } Mixer::~Mixer() { - _syst->clearSoundCallback(); stopAll(true); delete _premixChannel; _premixChannel = 0; } +uint Mixer::getOutputRate() const { + return (uint)_syst->getOutputSampleRate(); +} + bool Mixer::isPaused() { return _paused; } @@ -238,6 +235,9 @@ void Mixer::playInputStream(SoundType type, SoundHandle *handle, AudioStream *in void Mixer::mix(int16 *buf, uint len) { Common::StackLock lock(_mutex); + + // Since the mixer callback has been called, the mixer must be ready... + _mixerReady = true; // zero the buf memset(buf, 0, 2 * len * sizeof(int16)); diff --git a/sound/mixer.h b/sound/mixer.h index 34fd54c0ed..b799345558 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -94,8 +94,6 @@ private: Channel *_premixChannel; - uint _outputRate; - int _volumeForSoundType[4]; bool _paused; @@ -292,9 +290,9 @@ public: * * @return the output sample rate in Hz */ - uint getOutputRate() const { return _outputRate; } + uint getOutputRate() const; -private: +protected: void insertChannel(SoundHandle *handle, Channel *chan); /** @@ -302,6 +300,9 @@ private: */ void mix(int16 * buf, uint len); + // FIXME: temporary "public" to allow access to mixCallback + // from within OSystem::makeMixer() +public: /** * The mixer callback function, passed on to OSystem::setSoundCallback(). * This simply calls the mix() method. diff --git a/sound/mods/protracker.cpp b/sound/mods/protracker.cpp index 591c0276ac..74733d5c15 100644 --- a/sound/mods/protracker.cpp +++ b/sound/mods/protracker.cpp @@ -42,7 +42,8 @@ void ProtrackerPlayer::init(OSystem *system) { // subclass and hook that with the mixer. See also the // code used by other softsynths (sound/softsynth/emumidi.h). - _system->setSoundCallback(&audioCallback, this); +// _system->setSoundCallback(&audioCallback, this); +error("ProtrackerPlayer::init -- setSoundCallback is no more"); } void ProtrackerPlayer::start() { diff --git a/sound/softsynth/mt32.cpp b/sound/softsynth/mt32.cpp index 70ce6bcf8b..422231828d 100644 --- a/sound/softsynth/mt32.cpp +++ b/sound/softsynth/mt32.cpp @@ -424,10 +424,10 @@ void MidiDriver_ThreadedMT32::close() { void MidiDriver_ThreadedMT32::setTimerCallback(void *timer_param, TimerManager::TimerProc timer_proc) { if (!_timer_proc || !timer_proc) { if (_timer_proc) - g_timer->removeTimerProc(_timer_proc); + _vm->_timer->removeTimerProc(_timer_proc); _timer_proc = timer_proc; if (timer_proc) - g_timer->installTimerProc(timer_proc, getBaseTempo(), timer_param); + _vm->_timer->installTimerProc(timer_proc, getBaseTempo(), timer_param); } } -- cgit v1.2.3