diff options
48 files changed, 884 insertions, 558 deletions
diff --git a/projects/openttd.vcproj b/projects/openttd.vcproj index 165758647..e681545aa 100644 --- a/projects/openttd.vcproj +++ b/projects/openttd.vcproj @@ -471,9 +471,6 @@ RelativePath=".\..\src\gui.h"> </File> <File - RelativePath=".\..\src\hal.h"> - </File> - <File RelativePath=".\..\src\heightmap.h"> </File> <File @@ -1038,6 +1035,19 @@ </File> </Filter> <Filter + Name="Drivers" + Filter=""> + <File + RelativePath=".\..\src\music\music_driver.hpp"> + </File> + <File + RelativePath=".\..\src\sound\sound_driver.hpp"> + </File> + <File + RelativePath=".\..\src\video\video_driver.hpp"> + </File> + </Filter> + <Filter Name="Sprite loaders" Filter=""> <File diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index eda607705..311f23ac1 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -856,10 +856,6 @@ > </File> <File - RelativePath=".\..\src\hal.h" - > - </File> - <File RelativePath=".\..\src\heightmap.h" > </File> @@ -1605,6 +1601,22 @@ </File> </Filter> <Filter + Name="Drivers" + > + <File + RelativePath=".\..\src\music\music_driver.hpp" + > + </File> + <File + RelativePath=".\..\src\sound\sound_driver.hpp" + > + </File> + <File + RelativePath=".\..\src\video\video_driver.hpp" + > + </File> + </Filter> + <Filter Name="Sprite loaders" > <File diff --git a/source.list b/source.list index 36ad7486b..363122fba 100644 --- a/source.list +++ b/source.list @@ -124,7 +124,6 @@ gfx.h gfxinit.h group.h gui.h -hal.h heightmap.h helpers.hpp industry.h @@ -317,6 +316,11 @@ blitter/factory.hpp blitter/null.cpp blitter/null.hpp +# Drivers +music/music_driver.hpp +sound/sound_driver.hpp +video/video_driver.hpp + # Sprite loaders spriteloader/grf.cpp spriteloader/grf.hpp diff --git a/src/blitter/32bpp_anim.cpp b/src/blitter/32bpp_anim.cpp index 5d3f32800..9dbc19fba 100644 --- a/src/blitter/32bpp_anim.cpp +++ b/src/blitter/32bpp_anim.cpp @@ -2,8 +2,8 @@ #include "../zoom.hpp" #include "../gfx.h" #include "../debug.h" -#include "../hal.h" #include "../table/sprites.h" +#include "../video/video_driver.hpp" #include "32bpp_anim.hpp" static FBlitter_32bppAnim iFBlitter_32bppAnim; @@ -269,7 +269,7 @@ void Blitter_32bppAnim::PaletteAnimate(uint start, uint count) } /* Make sure the backend redraws the whole screen */ - _video_driver->make_dirty(0, 0, _screen.width, _screen.height); + _video_driver->MakeDirty(0, 0, _screen.width, _screen.height); } Blitter::PaletteAnimation Blitter_32bppAnim::UsePaletteAnimation() diff --git a/src/driver.cpp b/src/driver.cpp index 76516af6a..ddd110bf6 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -7,177 +7,15 @@ #include "debug.h" #include "driver.h" #include "functions.h" -#include "hal.h" #include "string.h" -#include "music/bemidi.h" -#include "music/dmusic.h" -#include "music/extmidi.h" -#include "music/null_m.h" -#include "music/os2_m.h" -#include "music/win32_m.h" -#include "music/qtmidi.h" -#include "music/libtimidity.h" - -#include "sound/null_s.h" -#include "sound/sdl_s.h" -#include "sound/cocoa_s.h" -#include "sound/win32_s.h" - -#include "video/dedicated_v.h" -#include "video/null_v.h" -#include "video/sdl_v.h" -#include "video/cocoa_v.h" -#include "video/win32_v.h" - -struct DriverDesc { - const char* name; - const char* longname; - const HalCommonDriver* drv; -}; - -struct DriverClass { - const DriverDesc *descs; - const char *name; - const HalCommonDriver** drv; -}; - - -#define M(x, y, z) { x, y, (const HalCommonDriver *)(void *)z } -static const DriverDesc _music_driver_descs[] = { -#ifdef __BEOS__ - M("bemidi", "BeOS MIDI Driver", &_bemidi_music_driver), -#endif -#if defined(__OS2__) && !defined(__INNOTEK_LIBC__) - M("os2", "OS/2 Music Driver", &_os2_music_driver), -#endif -#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT - M("dmusic", "DirectMusic MIDI Driver", &_dmusic_midi_driver), -#endif -#if defined(WIN32) && !defined(WINCE) - M("win32", "Win32 MIDI Driver", &_win32_music_driver), -#endif -#if defined(__APPLE__) && !defined(DEDICATED) - M("qt", "QuickTime MIDI Driver", &_qtime_music_driver), -#endif -#ifdef UNIX -#if defined(LIBTIMIDITY) - M("libtimidity", "LibTimidity MIDI Driver", &_libtimidity_music_driver), -#endif /* LIBTIMIDITY */ -#if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(__OS2__) && !defined(PSP) - M("extmidi", "External MIDI Driver", &_extmidi_music_driver), -#endif -#endif - M("null", "Null Music Driver", &_null_music_driver), - M(NULL, NULL, NULL) -}; - -static const DriverDesc _sound_driver_descs[] = { -#if defined(WIN32) && !defined(WINCE) - M("win32", "Win32 WaveOut Driver", &_win32_sound_driver), -#endif -#ifdef WITH_SDL - M("sdl", "SDL Sound Driver", &_sdl_sound_driver), -#endif -#ifdef WITH_COCOA - M("cocoa", "Cocoa Sound Driver", &_cocoa_sound_driver), -#endif - M("null", "Null Sound Driver", &_null_sound_driver), - M(NULL, NULL, NULL) -}; - -static const DriverDesc _video_driver_descs[] = { -#ifdef WIN32 - M("win32", "Win32 GDI Video Driver", &_win32_video_driver), -#endif -#ifdef WITH_SDL - M("sdl", "SDL Video Driver", &_sdl_video_driver), -#endif -#ifdef WITH_COCOA - M("cocoa", "Cocoa Video Driver", &_cocoa_video_driver), -#endif - M("null", "Null Video Driver", &_null_video_driver), -#ifdef ENABLE_NETWORK - M("dedicated", "Dedicated Video Driver", &_dedicated_video_driver), -#endif - M(NULL, NULL, NULL) -}; -#undef M - - -#define M(x, y, z) { x, y, (const HalCommonDriver **)(void *)z } -static const DriverClass _driver_classes[] = { - M(_video_driver_descs, "video", &_video_driver), - M(_sound_driver_descs, "sound", &_sound_driver), - M(_music_driver_descs, "music", &_music_driver) -}; -#undef M - -static const DriverDesc* GetDriverByName(const DriverDesc* dd, const char* name) -{ - for (; dd->name != NULL; dd++) { - if (strcmp(dd->name, name) == 0) return dd; - } - return NULL; -} - -void LoadDriver(int driver, const char *name) -{ - const DriverClass *dc = &_driver_classes[driver]; - const DriverDesc *dd; - const char *err; - - if (*name == '\0') { - for (dd = dc->descs; dd->name != NULL; dd++) { - err = dd->drv->start(NULL); - if (err == NULL) break; - DEBUG(driver, 1, "Probing %s driver '%s' failed with error: %s", - dc->name, dd->name, err - ); - } - if (dd->name == NULL) error("Couldn't find any suitable %s driver", dc->name); - - DEBUG(driver, 1, "Successfully probed %s driver '%s'", dc->name, dd->name); - - *dc->drv = dd->drv; - } else { - char* parm; - char buffer[256]; - const char* parms[32]; - - /* Extract the driver name and put parameter list in parm */ - ttd_strlcpy(buffer, name, sizeof(buffer)); - parm = strchr(buffer, ':'); - parms[0] = NULL; - if (parm != NULL) { - uint np = 0; - /* Tokenize the parm. */ - do { - *parm++ = '\0'; - if (np < lengthof(parms) - 1) - parms[np++] = parm; - while (*parm != '\0' && *parm != ',') - parm++; - } while (*parm == ','); - parms[np] = NULL; - } - dd = GetDriverByName(dc->descs, buffer); - if (dd == NULL) - error("No such %s driver: %s\n", dc->name, buffer); - - if (*dc->drv != NULL) (*dc->drv)->stop(); - *dc->drv = NULL; - - err = dd->drv->start(parms); - if (err != NULL) { - error("Unable to load driver %s(%s). The error was: %s\n", - dd->name, dd->longname, err - ); - } - *dc->drv = dd->drv; - } -} +#include "sound/sound_driver.hpp" +#include "music/music_driver.hpp" +#include "video/video_driver.hpp" +SoundDriver *_sound_driver; +MusicDriver *_music_driver; +VideoDriver *_video_driver; static const char* GetDriverParam(const char* const* parm, const char* name) { @@ -207,21 +45,3 @@ int GetDriverParamInt(const char* const* parm, const char* name, int def) const char* p = GetDriverParam(parm, name); return p != NULL ? atoi(p) : def; } - - -char *GetDriverList(char* p, const char *last) -{ - const DriverClass* dc; - - for (dc = _driver_classes; dc != endof(_driver_classes); dc++) { - const DriverDesc* dd; - - p += snprintf(p, last - p, "List of %s drivers:\n", dc->name); - for (dd = dc->descs; dd->name != NULL; dd++) { - p += snprintf(p, last - p, "%10s: %s\n", dd->name, dd->longname); - } - p = strecpy(p, "\n", last); - } - - return p; -} diff --git a/src/driver.h b/src/driver.h index 6a504362c..d10f18688 100644 --- a/src/driver.h +++ b/src/driver.h @@ -5,11 +5,207 @@ #ifndef DRIVER_H #define DRIVER_H -void LoadDriver(int driver, const char *name); +#include "debug.h" +#include "helpers.hpp" +#include "string.h" +#include <string> +#include <map> bool GetDriverParamBool(const char* const* parm, const char* name); int GetDriverParamInt(const char* const* parm, const char* name, int def); -char *GetDriverList(char *p, const char *last); +class Driver { +public: + virtual bool CanProbe() = 0; + + virtual const char *Start(const char * const *parm) = 0; + + virtual void Stop() = 0; + + virtual ~Driver() { } + + enum Type { + DT_BEGIN = 0, + DT_SOUND = 0, + DT_MUSIC, + DT_VIDEO, + DT_END, + }; +}; + +DECLARE_POSTFIX_INCREMENT(Driver::Type); + + +class DriverFactoryBase { +private: + Driver::Type type; + char *name; + typedef std::map<std::string, DriverFactoryBase *> Drivers; + + static Drivers &GetDrivers() + { + static Drivers &s_drivers = *new Drivers(); + return s_drivers; + } + + static Driver **GetActiveDriver(Driver::Type type) + { + static Driver *s_driver[3] = { NULL, NULL, NULL }; + return &s_driver[type]; + } + + static const char *GetDriverTypeName(Driver::Type type) + { + static const char *driver_type_name[] = { "sound", "music", "video" }; + return driver_type_name[type]; + } + +protected: + /** + * Register a driver internally, based on its name. + * @param name the name of the driver. + * @note an assert() will be trigger if 2 driver with the same name try to register. + */ + void RegisterDriver(const char *name, Driver::Type type) + { + /* Don't register nameless Drivers */ + if (name == NULL) return; + + this->name = strdup(name); + this->type = type; + + /* Prefix the name with driver type to make it unique */ + char buf[32]; + strecpy(buf, GetDriverTypeName(type), lastof(buf)); + strecpy(buf + 5, name, lastof(buf)); + + std::pair<Drivers::iterator, bool> P = GetDrivers().insert(Drivers::value_type(buf, this)); + assert(P.second); + } + +public: + DriverFactoryBase() : + name(NULL) + {} + + virtual ~DriverFactoryBase() { if (this->name != NULL) GetDrivers().erase(this->name); free(this->name); } + + /** + * Find the requested driver and return its class. + * @param name the driver to select. + * @post Sets the driver so GetCurrentDriver() returns it too. + */ + static Driver *SelectDriver(const char *name, Driver::Type type) + { + if (GetDrivers().size() == 0) return NULL; + + if (*name == '\0') { + /* Probe for this driver */ + Drivers::iterator it = GetDrivers().begin(); + for (; it != GetDrivers().end(); ++it) { + DriverFactoryBase *d = (*it).second; + + /* Check driver type */ + if (d->type != type) continue; + + Driver *newd = d->CreateInstance(); + if (!newd->CanProbe()) { + DEBUG(driver, 1, "Skipping probe of driver '%s'", d->name); + } else { + const char *err = newd->Start(NULL); + if (err == NULL) { + DEBUG(driver, 1, "Successfully probed %s driver '%s'", GetDriverTypeName(type), d->name); + delete *GetActiveDriver(type); + *GetActiveDriver(type) = newd; + return newd; + } + + DEBUG(driver, 1, "Probing %s driver '%s' failed with error: %s", GetDriverTypeName(type), d->name, err); + } + + delete newd; + } + error("Couldn't find any suitable %s driver", GetDriverTypeName(type)); + } else { + char *parm; + char buffer[256]; + const char *parms[32]; + + /* Extract the driver name and put parameter list in parm */ + strecpy(buffer, name, lastof(buffer)); + parm = strchr(buffer, ':'); + parms[0] = NULL; + if (parm != NULL) { + uint np = 0; + /* Tokenize the parm. */ + do { + *parm++ = '\0'; + if (np < lengthof(parms) - 1) + parms[np++] = parm; + while (*parm != '\0' && *parm != ',') + parm++; + } while (*parm == ','); + parms[np] = NULL; + } + + /* Find this driver */ + Drivers::iterator it = GetDrivers().begin(); + for (; it != GetDrivers().end(); ++it) { + DriverFactoryBase *d = (*it).second; + + /* Check driver type */ + if (d->type != type) continue; + + /* Check driver name */ + if (strcasecmp(buffer, d->name) != 0) continue; + + /* Found our driver, let's try it */ + Driver *newd = d->CreateInstance(); + + const char *err = newd->Start(parms); + if (err != NULL) { + delete newd; + error("Unable to load driver '%s'. The error was: %s", d->name, err); + } + + DEBUG(driver, 1, "Successfully loaded %s driver '%s'", GetDriverTypeName(type), d->name); + delete *GetActiveDriver(type); + *GetActiveDriver(type) = newd; + return newd; + } + error("No such %s driver: %s\n", GetDriverTypeName(type), buffer); + } + } + + /** + * Build a human readable list of available drivers, grouped by type. + */ + static char *GetDriversInfo(char *p, const char *last) + { + for (Driver::Type type = Driver::DT_BEGIN; type != Driver::DT_END; type++) { + p += snprintf(p, last - p, "List of %s drivers:\n", GetDriverTypeName(type)); + + Drivers::iterator it = GetDrivers().begin(); + for (; it != GetDrivers().end(); it++) { + DriverFactoryBase *d = (*it).second; + if (d->type == type) p += snprintf(p, last - p, "%18s: %s\n", d->name, d->GetDescription()); + } + + p += snprintf(p, last - p, "\n"); + } + + return p; + } + + /** + * Get a nice description of the driver-class. + */ + virtual const char *GetDescription() = 0; + + /** + * Create an instance of this driver-class. + */ + virtual Driver *CreateInstance() = 0; +}; #endif /* DRIVER_H */ diff --git a/src/gfx.cpp b/src/gfx.cpp index a60c4b9b7..45de29f68 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -12,7 +12,6 @@ #include "gfx.h" #include "table/palettes.h" #include "table/sprites.h" -#include "hal.h" #include "variables.h" #include "table/control_codes.h" #include "fontcache.h" @@ -21,6 +20,7 @@ #include "zoom.hpp" #include "texteff.hpp" #include "blitter/factory.hpp" +#include "video/video_driver.hpp" byte _dirkeys; ///< 1 = left, 2 = up, 4 = right, 8 = down bool _fullscreen; @@ -66,7 +66,7 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo) blitter->ScrollBuffer(_screen.dst_ptr, left, top, width, height, xo, yo); /* This part of the screen is now dirty. */ - _video_driver->make_dirty(left, top, width, height); + _video_driver->MakeDirty(left, top, width, height); } @@ -834,7 +834,7 @@ void UndrawMouseCursor() Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); _cursor.visible = false; blitter->CopyFromBuffer(blitter->MoveTo(_screen.dst_ptr, _cursor.draw_pos.x, _cursor.draw_pos.y), _cursor_backup, _cursor.draw_size.x, _cursor.draw_size.y); - _video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); + _video_driver->MakeDirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); } } @@ -886,7 +886,7 @@ void DrawMouseCursor() _cur_dpi = &_screen; DrawSprite(_cursor.sprite, _cursor.pal, _cursor.pos.x, _cursor.pos.y); - _video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); + _video_driver->MakeDirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); _cursor.visible = true; _cursor.dirty = false; @@ -907,7 +907,7 @@ void RedrawScreenRect(int left, int top, int right, int bottom) DrawOverlappedWindowForAll(left, top, right, bottom); - _video_driver->make_dirty(left, top, right - left, bottom - top); + _video_driver->MakeDirty(left, top, right - left, bottom - top); } void DrawDirtyBlocks() @@ -1151,12 +1151,12 @@ bool ChangeResInGame(int w, int h) { return (_screen.width == w && _screen.height == h) || - _video_driver->change_resolution(w, h); + _video_driver->ChangeResolution(w, h); } void ToggleFullScreen(bool fs) { - _video_driver->toggle_fullscreen(fs); + _video_driver->ToggleFullscreen(fs); if (_fullscreen != fs && _num_resolutions == 0) { DEBUG(driver, 0, "Could not find a suitable fullscreen resolution"); } diff --git a/src/hal.h b/src/hal.h deleted file mode 100644 index ed6564e7d..000000000 --- a/src/hal.h +++ /dev/null @@ -1,47 +0,0 @@ -/* $Id$ */ - -/** @file hal.h Hardware Abstraction Layer declarations */ - -#ifndef HAL_H -#define HAL_H - -struct HalCommonDriver { - const char *(*start)(const char * const *parm); - void (*stop)(); -}; - -struct HalVideoDriver { - const char *(*start)(const char * const *parm); - void (*stop)(); - void (*make_dirty)(int left, int top, int width, int height); - void (*main_loop)(); - bool (*change_resolution)(int w, int h); - void (*toggle_fullscreen)(bool fullscreen); -}; - -struct HalSoundDriver { - const char *(*start)(const char * const *parm); - void (*stop)(); -}; - -struct HalMusicDriver { - const char *(*start)(const char * const *parm); - void (*stop)(); - - void (*play_song)(const char *filename); - void (*stop_song)(); - bool (*is_song_playing)(); - void (*set_volume)(byte vol); -}; - -extern HalMusicDriver *_music_driver; -extern HalSoundDriver *_sound_driver; -extern HalVideoDriver *_video_driver; - -enum DriverType { - VIDEO_DRIVER = 0, - SOUND_DRIVER = 1, - MUSIC_DRIVER = 2, -}; - -#endif /* HAL_H */ diff --git a/src/music/bemidi.cpp b/src/music/bemidi.cpp index 0cf500a50..ab5634cca 100644 --- a/src/music/bemidi.cpp +++ b/src/music/bemidi.cpp @@ -11,17 +11,19 @@ static BMidiSynthFile midiSynthFile; -static const char *bemidi_start(const char * const *parm) +static FMusicDriver_BeMidi iFMusicDriver_BeMidi; + +const char *MusicDriver_BeMidi::Start(const char * const *parm) { return NULL; } -static void bemidi_stop() +void MusicDriver_BeMidi::Stop() { midiSynthFile.UnloadFile(); } -static void bemidi_play_song(const char *filename) +void MusicDriver_BeMidi::PlaySong(const char *filename) { bemidi_stop(); entry_ref midiRef; @@ -30,26 +32,17 @@ static void bemidi_play_song(const char *filename) midiSynthFile.Start(); } -static void bemidi_stop_song() +void MusicDriver_BeMidi::StopSong() { midiSynthFile.UnloadFile(); } -static bool bemidi_is_playing() +bool MusicDriver_BeMidi::IsSongPlaying() { return !midiSynthFile.IsFinished(); } -static void bemidi_set_volume(byte vol) +void MusicDriver_BeMidi::SetVolume(byte vol) { fprintf(stderr, "BeMidi: Set volume not implemented\n"); } - -const HalMusicDriver _bemidi_music_driver = { - bemidi_start, - bemidi_stop, - bemidi_play_song, - bemidi_stop_song, - bemidi_is_playing, - bemidi_set_volume, -}; diff --git a/src/music/bemidi.h b/src/music/bemidi.h index 1b3d4f3de..623d6398d 100644 --- a/src/music/bemidi.h +++ b/src/music/bemidi.h @@ -3,8 +3,30 @@ #ifndef MUSIC_BEMIDI_H #define MUSIC_BEMIDI_H -#include "../hal.h" +#include "music_driver.hpp" -extern const HalMusicDriver _bemidi_music_driver; +class MusicDriver_BeMidi: public MusicDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void PlaySong(const char *filename); + + /* virtual */ void StopSong(); + + /* virtual */ bool IsSongPlaying(); + + /* virtual */ void SetVolume(byte vol); +}; + +class FMusicDriver_BeMidi: public MusicDriverFactory<FMusicDriver_BeMidi> { +public: + /* virtual */ const char *GetName() { return "bemidi"; } + /* virtual */ const char *GetDescription() { return "BeOS MIDI Driver"; } + /* virtual */ Driver *CreateInstance() { return new MusicDriver_BeMidi(); } +}; #endif /* MUSIC_BEMIDI_H */ diff --git a/src/music/dmusic.cpp b/src/music/dmusic.cpp index f0538c678..d9839cee9 100644 --- a/src/music/dmusic.cpp +++ b/src/music/dmusic.cpp @@ -47,7 +47,7 @@ struct ProcPtrs { static ProcPtrs proc; -static const char* DMusicMidiStart(const char* const* parm) +const char *MusicDriver_DMusic::Start(const char * const *parm) { if (performance != NULL) return NULL; @@ -109,7 +109,7 @@ static const char* DMusicMidiStart(const char* const* parm) } -static void DMusicMidiStop() +void MusicDriver_DMusic::Stop() { seeking = false; @@ -136,7 +136,7 @@ static void DMusicMidiStop() } -static void DMusicMidiPlaySong(const char* filename) +void MusicDriver_DMusic::PlaySong(const char* filename) { /* set up the loader object info */ DMUS_OBJECTDESC obj_desc; @@ -188,7 +188,7 @@ static void DMusicMidiPlaySong(const char* filename) } -static void DMusicMidiStopSong() +void MusicDriver_DMusic::StopSong() { if (FAILED(performance->Stop(segment, NULL, 0, 0))) { DEBUG(driver, 0, "DirectMusic: StopSegment failed"); @@ -197,7 +197,7 @@ static void DMusicMidiStopSong() } -static bool DMusicMidiIsSongPlaying() +bool MusicDriver_DMusic::IsSongPlaying() { /* Not the nicest code, but there is a short delay before playing actually * starts. OpenTTD makes no provision for this. */ @@ -210,20 +210,11 @@ static bool DMusicMidiIsSongPlaying() } -static void DMusicMidiSetVolume(byte vol) +void MusicDriver_DMusic::SetVolume(byte vol) { long db = vol * 2000 / 127 - 2000; ///< 0 - 127 -> -2000 - 0 performance->SetGlobalParam(GUID_PerfMasterVolume, &db, sizeof(db)); } -const HalMusicDriver _dmusic_midi_driver = { - DMusicMidiStart, - DMusicMidiStop, - DMusicMidiPlaySong, - DMusicMidiStopSong, - DMusicMidiIsSongPlaying, - DMusicMidiSetVolume, -}; - #endif /* WIN32_ENABLE_DIRECTMUSIC_SUPPORT */ diff --git a/src/music/dmusic.h b/src/music/dmusic.h index a01269e1d..9bfb1bb1c 100644 --- a/src/music/dmusic.h +++ b/src/music/dmusic.h @@ -3,8 +3,30 @@ #ifndef MUSIC_DMUSIC_H #define MUSIC_DMUSIC_H -#include "../hal.h" +#include "music_driver.hpp" -extern const HalMusicDriver _dmusic_midi_driver; +class MusicDriver_DMusic: public MusicDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void PlaySong(const char *filename); + + /* virtual */ void StopSong(); + + /* virtual */ bool IsSongPlaying(); + + /* virtual */ void SetVolume(byte vol); +}; + +class FMusicDriver_DMusic: public MusicDriverFactory<FMusicDriver_DMusic> { +public: + /* virtual */ const char *GetName() { return "dmusic"; } + /* virtual */ const char *GetDescription() { return "DirectMusic MIDI Driver"; } + /* virtual */ Driver *CreateInstance() { return new MusicDriver_DMusic(); } +}; #endif /* MUSIC_DMUSIC_H */ diff --git a/src/music/extmidi.cpp b/src/music/extmidi.cpp index 4c2f2f1e2..063b2cef6 100644 --- a/src/music/extmidi.cpp +++ b/src/music/extmidi.cpp @@ -24,32 +24,34 @@ static struct { static void DoPlay(); static void DoStop(); -static const char* ExtMidiStart(const char* const * parm) +static FMusicDriver_ExtMidi iFMusicDriver_ExtMidi; + +const char* MusicDriver_ExtMidi::Start(const char* const * parm) { _midi.song[0] = '\0'; _midi.pid = -1; return NULL; } -static void ExtMidiStop() +void MusicDriver_ExtMidi::Stop() { _midi.song[0] = '\0'; DoStop(); } -static void ExtMidiPlaySong(const char* filename) +void MusicDriver_ExtMidi::PlaySong(const char* filename) { ttd_strlcpy(_midi.song, filename, lengthof(_midi.song)); DoStop(); } -static void ExtMidiStopSong() +void MusicDriver_ExtMidi::StopSong() { _midi.song[0] = '\0'; DoStop(); } -static bool ExtMidiIsPlaying() +bool MusicDriver_ExtMidi::IsSongPlaying() { if (_midi.pid != -1 && waitpid(_midi.pid, NULL, WNOHANG) == _midi.pid) _midi.pid = -1; @@ -57,7 +59,7 @@ static bool ExtMidiIsPlaying() return _midi.pid != -1; } -static void ExtMidiSetVolume(byte vol) +void MusicDriver_ExtMidi::SetVolume(byte vol) { DEBUG(driver, 1, "extmidi: set volume not implemented"); } @@ -96,13 +98,4 @@ static void DoStop() if (_midi.pid != -1) kill(_midi.pid, SIGTERM); } -const HalMusicDriver _extmidi_music_driver = { - ExtMidiStart, - ExtMidiStop, - ExtMidiPlaySong, - ExtMidiStopSong, - ExtMidiIsPlaying, - ExtMidiSetVolume, -}; - #endif /* __MORPHOS__ */ diff --git a/src/music/extmidi.h b/src/music/extmidi.h index f118f933a..df1472d34 100644 --- a/src/music/extmidi.h +++ b/src/music/extmidi.h @@ -3,8 +3,30 @@ #ifndef MUSIC_EXTERNAL_H #define MUSIC_EXTERNAL_H -#include "../hal.h" +#include "music_driver.hpp" -extern const HalMusicDriver _extmidi_music_driver; +class MusicDriver_ExtMidi: public MusicDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void PlaySong(const char *filename); + + /* virtual */ void StopSong(); + + /* virtual */ bool IsSongPlaying(); + + /* virtual */ void SetVolume(byte vol); +}; + +class FMusicDriver_ExtMidi: public MusicDriverFactory<FMusicDriver_ExtMidi> { +public: + /* virtual */ const char *GetName() { return "extmidi"; } + /* virtual */ const char *GetDescription() { return "External MIDI Driver"; } + /* virtual */ Driver *CreateInstance() { return new MusicDriver_ExtMidi(); } +}; #endif /* MUSIC_EXTERNAL_H */ diff --git a/src/music/libtimidity.cpp b/src/music/libtimidity.cpp index f25b0bfff..5368bbd68 100644 --- a/src/music/libtimidity.cpp +++ b/src/music/libtimidity.cpp @@ -44,7 +44,9 @@ static void AudioOutCallback(void *buf, unsigned int _reqn, void *userdata) } #endif /* PSP */ -static const char *LibtimidityMidiStart(const char *const *param) +static FMusicDriver_LibTimidity iFMusicDriver_LibTimidity; + +const char *MusicDriver_LibTimidity::Start(const char *const *param) { _midi.status = MIDI_STOPPED; @@ -53,8 +55,7 @@ static const char *LibtimidityMidiStart(const char *const *param) * If it was not forced via param, try to load it without a * configuration. Who knows that works. */ if (param != NULL || mid_init_no_config() < 0) { - DEBUG(driver, 0, "error initializing timidity"); - return NULL; + return "error initializing timidity"; } } DEBUG(driver, 1, "successfully initialised timidity"); @@ -77,7 +78,7 @@ static const char *LibtimidityMidiStart(const char *const *param) return NULL; } -static void LibtimidityMidiStop() +void MusicDriver_LibTimidity::Stop() { if (_midi.status == MIDI_PLAYING) { _midi.status = MIDI_STOPPED; @@ -86,7 +87,7 @@ static void LibtimidityMidiStop() mid_exit(); } -static void LibtimidityMidiPlaySong(const char *filename) +void MusicDriver_LibTimidity::PlaySong(const char *filename) { _midi.stream = mid_istream_open_file(filename); if (_midi.stream == NULL) { @@ -107,13 +108,13 @@ static void LibtimidityMidiPlaySong(const char *filename) _midi.status = MIDI_PLAYING; } -static void LibtimidityMidiStopSong() +void MusicDriver_LibTimidity::StopSong() { _midi.status = MIDI_STOPPED; mid_song_free(_midi.song); } -static bool LibtimidityMidiIsPlaying() +bool MusicDriver_LibTimidity::IsSongPlaying() { if (_midi.status == MIDI_PLAYING) { _midi.song_position = mid_song_get_time(_midi.song); @@ -126,18 +127,8 @@ static bool LibtimidityMidiIsPlaying() return (_midi.status == MIDI_PLAYING); } -static void LibtimidityMidiSetVolume(byte vol) +void MusicDriver_LibTimidity::SetVolume(byte vol) { if (_midi.song != NULL) mid_song_set_volume(_midi.song, vol); } - -const HalMusicDriver _libtimidity_music_driver = { - LibtimidityMidiStart, - LibtimidityMidiStop, - LibtimidityMidiPlaySong, - LibtimidityMidiStopSong, - LibtimidityMidiIsPlaying, - LibtimidityMidiSetVolume, -}; - diff --git a/src/music/libtimidity.h b/src/music/libtimidity.h index df8b7de1c..2915841f7 100644 --- a/src/music/libtimidity.h +++ b/src/music/libtimidity.h @@ -3,8 +3,30 @@ #ifndef MUSIC_LIBTIMIDITY_H #define MUSIC_LIBTIMIDITY_H -#include "../hal.h" +#include "music_driver.hpp" -extern const HalMusicDriver _libtimidity_music_driver; +class MusicDriver_LibTimidity: public MusicDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void PlaySong(const char *filename); + + /* virtual */ void StopSong(); + + /* virtual */ bool IsSongPlaying(); + + /* virtual */ void SetVolume(byte vol); +}; + +class FMusicDriver_LibTimidity: public MusicDriverFactory<FMusicDriver_LibTimidity> { +public: + /* virtual */ const char *GetName() { return "libtimidity"; } + /* virtual */ const char *GetDescription() { return "LibTimidity MIDI Driver"; } + /* virtual */ Driver *CreateInstance() { return new MusicDriver_LibTimidity(); } +}; #endif /* MUSIC_LIBTIMIDITY_H */ diff --git a/src/music/music_driver.hpp b/src/music/music_driver.hpp new file mode 100644 index 000000000..b4486ef94 --- /dev/null +++ b/src/music/music_driver.hpp @@ -0,0 +1,35 @@ +/* $Id$ */ + +#ifndef MUSIC_MUSIC_DRIVER_HPP +#define MUSIC_MUSIC_DRIVER_HPP + +#include "../driver.h" + +class MusicDriver: public Driver { +public: + virtual void PlaySong(const char *filename) = 0; + + virtual void StopSong() = 0; + + virtual bool IsSongPlaying() = 0; + + virtual void SetVolume(byte vol) = 0; +}; + +class MusicDriverFactoryBase: public DriverFactoryBase { +}; + +template <class T> +class MusicDriverFactory: public MusicDriverFactoryBase { +public: + MusicDriverFactory() { this->RegisterDriver(((T *)this)->GetName(), Driver::DT_MUSIC); } + + /** + * Get the long, human readable, name for the Driver-class. + */ + const char *GetName(); +}; + +extern MusicDriver *_music_driver; + +#endif /* MUSIC_MUSIC_DRIVER_HPP */ diff --git a/src/music/null_m.cpp b/src/music/null_m.cpp index 01f7a401e..063ad2e10 100644 --- a/src/music/null_m.cpp +++ b/src/music/null_m.cpp @@ -3,18 +3,5 @@ #include "../stdafx.h" #include "null_m.h" -static const char* NullMidiStart(const char* const* parm) { return NULL; } -static void NullMidiStop() {} -static void NullMidiPlaySong(const char *filename) {} -static void NullMidiStopSong() {} -static bool NullMidiIsSongPlaying() { return true; } -static void NullMidiSetVolume(byte vol) {} +static FMusicDriver_Null iFMusicDriver_Null; -const HalMusicDriver _null_music_driver = { - NullMidiStart, - NullMidiStop, - NullMidiPlaySong, - NullMidiStopSong, - NullMidiIsSongPlaying, - NullMidiSetVolume, -}; diff --git a/src/music/null_m.h b/src/music/null_m.h index d6edfb71d..2b7be7581 100644 --- a/src/music/null_m.h +++ b/src/music/null_m.h @@ -3,8 +3,30 @@ #ifndef MUSIC_NULL_H #define MUSIC_NULL_H -#include "../hal.h" +#include "music_driver.hpp" -extern const HalMusicDriver _null_music_driver; +class MusicDriver_Null: public MusicDriver { +public: + /* virtual */ bool CanProbe() { return false; } + + /* virtual */ const char *Start(const char * const *param) { return NULL; } + + /* virtual */ void Stop() { } + + /* virtual */ void PlaySong(const char *filename) { } + + /* virtual */ void StopSong() { } + + /* virtual */ bool IsSongPlaying() { return true; } + + /* virtual */ void SetVolume(byte vol) { } +}; + +class FMusicDriver_Null: public MusicDriverFactory<FMusicDriver_Null> { +public: + /* virtual */ const char *GetName() { return "null"; } + /* virtual */ const char *GetDescription() { return "Null Music Driver"; } + /* virtual */ Driver *CreateInstance() { return new MusicDriver_Null(); } +}; #endif /* MUSIC_NULL_H */ diff --git a/src/music/os2_m.cpp b/src/music/os2_m.cpp index c067e8d53..04add6e95 100644 --- a/src/music/os2_m.cpp +++ b/src/music/os2_m.cpp @@ -30,7 +30,9 @@ static long CDECL MidiSendCommand(const char *cmd, ...) return mciSendString(buf, NULL, 0, NULL, 0); } -static void OS2MidiPlaySong(const char *filename) +static FMusicDriver_OS2 iFMusicDriver_OS2; + +void MusicDriver_OS2::PlaySong(const char *filename) { MidiSendCommand("close all"); @@ -40,38 +42,29 @@ static void OS2MidiPlaySong(const char *filename) MidiSendCommand("play song from 0"); } -static void OS2MidiStopSong() +void MusicDriver_OS2::StopSong() { MidiSendCommand("close all"); } -static void OS2MidiSetVolume(byte vol) +void MusicDriver_OS2::SetVolume(byte vol) { MidiSendCommand("set song audio volume %d", ((vol/127)*100)); } -static bool OS2MidiIsSongPlaying() +bool MusicDriver_OS2::IsSongPlaying() { char buf[16]; mciSendString("status song mode", buf, sizeof(buf), NULL, 0); return strcmp(buf, "playing") == 0 || strcmp(buf, "seeking") == 0; } -static const char *OS2MidiStart(const char * const *parm) +const char *MusicDriver_OS2::Start(const char * const *parm) { return 0; } -static void OS2MidiStop() +void MusicDriver_OS2::Stop() { MidiSendCommand("close all"); } - -const HalMusicDriver _os2_music_driver = { - OS2MidiStart, - OS2MidiStop, - OS2MidiPlaySong, - OS2MidiStopSong, - OS2MidiIsSongPlaying, - OS2MidiSetVolume, -}; diff --git a/src/music/os2_m.h b/src/music/os2_m.h index fef15b91f..b0f4d71ce 100644 --- a/src/music/os2_m.h +++ b/src/music/os2_m.h @@ -3,8 +3,30 @@ #ifndef MUSIC_OS2_H #define MUSIC_OS2_H -#include "../hal.h" +#include "music_driver.hpp" -extern const HalMusicDriver _os2_music_driver; +class MusicDriver_OS2: public MusicDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void PlaySong(const char *filename); + + /* virtual */ void StopSong(); + + /* virtual */ bool IsSongPlaying(); + + /* virtual */ void SetVolume(byte vol); +}; + +class FMusicDriver_OS2: public MusicDriverFactory<FMusicDriver_OS2> { +public: + /* virtual */ const char *GetName() { return "os2"; } + /* virtual */ const char *GetDescription() { return "OS/2 Music Driver"; } + /* virtual */ Driver *CreateInstance() { return new MusicDriver_OS2(); } +}; #endif /* MUSIC_OS2_H */ diff --git a/src/music/qtmidi.cpp b/src/music/qtmidi.cpp index c36dbcddc..cad83d59e 100644 --- a/src/music/qtmidi.cpp +++ b/src/music/qtmidi.cpp @@ -47,6 +47,8 @@ // we need to include debug.h after CoreServices because defining DEBUG will break CoreServices in OSX 10.2 #include "../debug.h" +static FMusicDriver_QtMidi iFMusicDriver_QtMidi; + enum { midiType = 'Midi' /**< OSType code for MIDI songs. */ @@ -207,9 +209,6 @@ static int _quicktime_state = QT_STATE_IDLE; /**< Current player state. */ #define VOLUME ((short)((0x00FF & _quicktime_volume) << 1)) -static void StopSong(); - - /** * Initialized the MIDI player, including QuickTime initialization. * @@ -217,7 +216,7 @@ static void StopSong(); * @c Gestalt() and @c EnterMovies(). Needs changes in * #InitQuickTimeIfNeeded. */ -static const char* StartDriver(const char * const *parm) +const char *MusicDriver_QtMidi::Start(const char * const *parm) { InitQuickTimeIfNeeded(); return (_quicktime_started) ? NULL : "can't initialize QuickTime"; @@ -230,7 +229,7 @@ static const char* StartDriver(const char * const *parm) * This function is called at regular intervals from OpenTTD's main loop, so * we call @c MoviesTask() from here to let QuickTime do its work. */ -static bool SongIsPlaying() +bool MusicDriver_QtMidi::IsSongPlaying() { if (!_quicktime_started) return true; @@ -258,7 +257,7 @@ static bool SongIsPlaying() * Stops playing and frees any used resources before returning. As it * deinitilizes QuickTime, the #_quicktime_started flag is set to @c false. */ -static void StopDriver() +void MusicDriver_QtMidi::Stop() { if (!_quicktime_started) return; @@ -284,7 +283,7 @@ static void StopDriver() * * @param filename Path to a MIDI file. */ -static void PlaySong(const char *filename) +void MusicDriver_QtMidi::PlaySong(const char *filename) { if (!_quicktime_started) return; @@ -312,7 +311,7 @@ static void PlaySong(const char *filename) /** * Stops playing the current song, if the player is active. */ -static void StopSong() +void MusicDriver_QtMidi::StopSong() { if (!_quicktime_started) return; @@ -340,7 +339,7 @@ static void StopSong() * * @param vol The desired volume, range of the value is @c 0-127 */ -static void SetVolume(byte vol) +void MusicDriver_QtMidi::SetVolume(byte vol) { if (!_quicktime_started) return; @@ -357,15 +356,3 @@ static void SetVolume(byte vol) } } - -/** - * Table of callbacks that implement the QuickTime MIDI player. - */ -const HalMusicDriver _qtime_music_driver = { - StartDriver, - StopDriver, - PlaySong, - StopSong, - SongIsPlaying, - SetVolume, -}; diff --git a/src/music/qtmidi.h b/src/music/qtmidi.h index 0b9e5ff2e..7ffa02fe0 100644 --- a/src/music/qtmidi.h +++ b/src/music/qtmidi.h @@ -3,8 +3,30 @@ #ifndef MUSIC_MACOSX_QUICKTIME_H #define MUSIC_MACOSX_QUICKTIME_H -#include "../hal.h" +#include "music_driver.hpp" -extern const HalMusicDriver _qtime_music_driver; +class MusicDriver_QtMidi: public MusicDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void PlaySong(const char *filename); + + /* virtual */ void StopSong(); + + /* virtual */ bool IsSongPlaying(); + + /* virtual */ void SetVolume(byte vol); +}; + +class FMusicDriver_QtMidi: public MusicDriverFactory<FMusicDriver_QtMidi> { +public: + /* virtual */ const char *GetName() { return "qt"; } + /* virtual */ const char *GetDescription() { return "QuickTime MIDI Driver"; } + /* virtual */ Driver *CreateInstance() { return new MusicDriver_QtMidi(); } +}; #endif /* MUSIC_MACOSX_QUICKTIME_H */ diff --git a/src/music/win32_m.cpp b/src/music/win32_m.cpp index 7ec9a945e..470572254 100644 --- a/src/music/win32_m.cpp +++ b/src/music/win32_m.cpp @@ -15,7 +15,9 @@ static struct { char start_song[260]; } _midi; -static void Win32MidiPlaySong(const char *filename) +static FMusicDriver_Win32 iFMusicDriver_Win32; + +void MusicDriver_Win32::PlaySong(const char *filename) { strcpy(_midi.start_song, filename); _midi.playing = true; @@ -23,7 +25,7 @@ static void Win32MidiPlaySong(const char *filename) SetEvent(_midi.wait_obj); } -static void Win32MidiStopSong() +void MusicDriver_Win32::StopSong() { if (_midi.playing) { _midi.stop_song = true; @@ -32,12 +34,12 @@ static void Win32MidiStopSong() } } -static bool Win32MidiIsSongPlaying() +bool MusicDriver_Win32::IsSongPlaying() { return _midi.playing; } -static void Win32MidiSetVolume(byte vol) +void MusicDriver_Win32::SetVolume(byte vol) { _midi.new_vol = vol; SetEvent(_midi.wait_obj); @@ -118,7 +120,7 @@ static DWORD WINAPI MidiThread(LPVOID arg) return 0; } -static const char *Win32MidiStart(const char * const *parm) +const char *MusicDriver_Win32::Start(const char * const *parm) { MIDIOUTCAPS midicaps; DWORD threadId; @@ -146,17 +148,8 @@ static const char *Win32MidiStart(const char * const *parm) return NULL; } -static void Win32MidiStop() +void MusicDriver_Win32::Stop() { _midi.terminate = true; SetEvent(_midi.wait_obj); } - -const HalMusicDriver _win32_music_driver = { - Win32MidiStart, - Win32MidiStop, - Win32MidiPlaySong, - Win32MidiStopSong, - Win32MidiIsSongPlaying, - Win32MidiSetVolume, -}; diff --git a/src/music/win32_m.h b/src/music/win32_m.h index 162be9d97..bef62bd66 100644 --- a/src/music/win32_m.h +++ b/src/music/win32_m.h @@ -3,8 +3,30 @@ #ifndef MUSIC_WIN32_H #define MUSIC_WIN32_H -#include "../hal.h" +#include "music_driver.hpp" -extern const HalMusicDriver _win32_music_driver; +class MusicDriver_Win32: public MusicDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void PlaySong(const char *filename); + + /* virtual */ void StopSong(); + + /* virtual */ bool IsSongPlaying(); + + /* virtual */ void SetVolume(byte vol); +}; + +class FMusicDriver_Win32: public MusicDriverFactory<FMusicDriver_Win32> { +public: + /* virtual */ const char *GetName() { return "win32"; } + /* virtual */ const char *GetDescription() { return "Win32 Music Driver"; } + /* virtual */ Driver *CreateInstance() { return new MusicDriver_Win32(); } +}; #endif /* MUSIC_WIN32_H */ diff --git a/src/music_gui.cpp b/src/music_gui.cpp index 0d932cb26..ea05bbe69 100644 --- a/src/music_gui.cpp +++ b/src/music_gui.cpp @@ -11,10 +11,10 @@ #include "window.h" #include "gfx.h" #include "sound.h" -#include "hal.h" #include "macros.h" #include "variables.h" #include "music.h" +#include "music/music_driver.hpp" static byte _music_wnd_cursong; static bool _song_is_active; @@ -86,7 +86,7 @@ static void SkipToNextSong() static void MusicVolumeChanged(byte new_vol) { - _music_driver->set_volume(new_vol); + _music_driver->SetVolume(new_vol); } static void DoPlaySong() @@ -94,12 +94,12 @@ static void DoPlaySong() char filename[MAX_PATH]; FioFindFullPath(filename, lengthof(filename), GM_DIR, origin_songs_specs[_music_wnd_cursong - 1].filename); - _music_driver->play_song(filename); + _music_driver->PlaySong(filename); } static void DoStopMusic() { - _music_driver->stop_song(); + _music_driver->StopSong(); } static void SelectSongToPlay() @@ -178,7 +178,7 @@ void MusicLoop() if (!_song_is_active) return; - if (!_music_driver->is_song_playing()) { + if (!_music_driver->IsSongPlaying()) { if (_game_mode != GM_MENU) { StopMusic(); SkipToNextSong(); diff --git a/src/openttd.cpp b/src/openttd.cpp index c27fc578f..7f88684e4 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -41,7 +41,6 @@ #include "sound.h" #include "economy.h" #include "fileio.h" -#include "hal.h" #include "airport.h" #include "aircraft.h" #include "console.h" @@ -65,6 +64,9 @@ #include "player_face.h" #include "group.h" #include "blitter/factory.hpp" +#include "sound/sound_driver.hpp" +#include "music/music_driver.hpp" +#include "video/video_driver.hpp" #include "bridge_map.h" #include "clear_map.h" @@ -103,7 +105,7 @@ void CDECL error(const char *s, ...) va_end(va); ShowOSErrorBox(buf); - if (_video_driver != NULL) _video_driver->stop(); + if (_video_driver != NULL) _video_driver->Stop(); assert(0); exit(1); @@ -186,7 +188,8 @@ static void showhelp() lastof(buf) ); - p = GetDriverList(p, lastof(buf)); + /* List the drivers */ + p = VideoDriverFactoryBase::GetDriversInfo(p, lastof(buf)); /* List the blitters */ p = BlitterFactoryBase::GetBlittersInfo(p, lastof(buf)); @@ -342,7 +345,7 @@ static void LoadIntroGame() MarkWholeScreenDirty(); /* Play main theme */ - if (_music_driver->is_song_playing()) ResetMusic(); + if (_music_driver->IsSongPlaying()) ResetMusic(); } #if defined(UNIX) && !defined(__MORPHOS__) @@ -514,16 +517,36 @@ int ttd_main(int argc, char *argv[]) DEBUG(misc, 1, "Loading blitter '%s'...", blitter); if (BlitterFactoryBase::SelectBlitter(blitter) == NULL) error("Failed to select requested blitter '%s'; does it exist?", blitter); + DEBUG(driver, 1, "Loading drivers..."); - LoadDriver(SOUND_DRIVER, _ini_sounddriver); - LoadDriver(MUSIC_DRIVER, _ini_musicdriver); - LoadDriver(VIDEO_DRIVER, _ini_videodriver); // load video last, to prevent an empty window while sound and music loads + + _sound_driver = (SoundDriver*)SoundDriverFactoryBase::SelectDriver(_ini_sounddriver, Driver::DT_SOUND); + if (_sound_driver == NULL) { + StrEmpty(_ini_sounddriver) ? + error("Failed to autoprobe sound driver") : + error("Failed to select requested sound driver '%s'", _ini_sounddriver); + } + + _music_driver = (MusicDriver*)MusicDriverFactoryBase::SelectDriver(_ini_musicdriver, Driver::DT_MUSIC); + if (_music_driver == NULL) { + StrEmpty(_ini_musicdriver) ? + error("Failed to autoprobe music driver") : + error("Failed to select requested music driver '%s'", _ini_musicdriver); + } + + _video_driver = (VideoDriver*)VideoDriverFactoryBase::SelectDriver(_ini_videodriver, Driver::DT_VIDEO); + if (_video_driver == NULL) { + StrEmpty(_ini_videodriver) ? + error("Failed to autoprobe video driver") : + error("Failed to select requested video driver '%s'", _ini_videodriver); + } + _savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING; /* Initialize the zoom level of the screen to normal */ _screen.zoom = ZOOM_LVL_NORMAL; /* restore saved music volume */ - _music_driver->set_volume(msf.music_vol); + _music_driver->SetVolume(msf.music_vol); NetworkStartUp(); // initialize network-core @@ -594,16 +617,16 @@ int ttd_main(int argc, char *argv[]) } #endif /* ENABLE_NETWORK */ - _video_driver->main_loop(); + _video_driver->MainLoop(); WaitTillSaved(); IConsoleFree(); if (_network_available) NetworkShutDown(); // Shut down the network and close any open connections - _video_driver->stop(); - _music_driver->stop(); - _sound_driver->stop(); + _video_driver->Stop(); + _music_driver->Stop(); + _sound_driver->Stop(); /* only save config if we have to */ if (save_config) { @@ -2097,8 +2120,3 @@ void ReloadNewGRFData() /* redraw the whole screen */ MarkWholeScreenDirty(); } - -HalMusicDriver *_music_driver; -HalSoundDriver *_sound_driver; -HalVideoDriver *_video_driver; - diff --git a/src/sound/cocoa_s.cpp b/src/sound/cocoa_s.cpp index 246cbcecf..0c1e793f9 100644 --- a/src/sound/cocoa_s.cpp +++ b/src/sound/cocoa_s.cpp @@ -36,6 +36,7 @@ #undef Point #undef Rect +static FSoundDriver_Cocoa iFSoundDriver_Cocoa; static AudioUnit _outputAudioUnit; @@ -48,7 +49,7 @@ static OSStatus audioCallback(void *inRefCon, AudioUnitRenderActionFlags inActio } -static const char *CocoaSoundStart(const char * const *parm) +const char *SoundDriver_Cocoa::Start(const char * const *parm) { Component comp; ComponentDescription desc; @@ -116,7 +117,7 @@ static const char *CocoaSoundStart(const char * const *parm) } -static void CocoaSoundStop() +void SoundDriver_Cocoa::Stop() { struct AudioUnitInputCallback callback; @@ -140,10 +141,4 @@ static void CocoaSoundStop() } } - -const HalSoundDriver _cocoa_sound_driver = { - CocoaSoundStart, - CocoaSoundStop, -}; - #endif /* WITH_COCOA */ diff --git a/src/sound/cocoa_s.h b/src/sound/cocoa_s.h index 92f67cb10..96e24522f 100644 --- a/src/sound/cocoa_s.h +++ b/src/sound/cocoa_s.h @@ -3,8 +3,22 @@ #ifndef SOUND_COCOA_H #define SOUND_COCOA_H -#include "../hal.h" +#include "sound_driver.hpp" -extern const HalSoundDriver _cocoa_sound_driver; +class SoundDriver_Cocoa: public SoundDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); +}; + +class FSoundDriver_Cocoa: public SoundDriverFactory<FSoundDriver_Cocoa> { +public: + /* virtual */ const char *GetName() { return "cocoa"; } + /* virtual */ const char *GetDescription() { return "Cocoa Sound Driver"; } + /* virtual */ Driver *CreateInstance() { return new SoundDriver_Cocoa(); } +}; #endif /* SOUND_COCOA_H */ diff --git a/src/sound/null_s.cpp b/src/sound/null_s.cpp index 00eab496f..c8fe22ca3 100644 --- a/src/sound/null_s.cpp +++ b/src/sound/null_s.cpp @@ -3,10 +3,4 @@ #include "../stdafx.h" #include "null_s.h" -static const char *NullSoundStart(const char * const *parm) { return NULL; } -static void NullSoundStop() {} - -const HalSoundDriver _null_sound_driver = { - NullSoundStart, - NullSoundStop, -}; +static FSoundDriver_Null iFSoundDriver_Null; diff --git a/src/sound/null_s.h b/src/sound/null_s.h index 204c58376..2f5c79841 100644 --- a/src/sound/null_s.h +++ b/src/sound/null_s.h @@ -3,8 +3,22 @@ #ifndef SOUND_NULL_H #define SOUND_NULL_H -#include "../hal.h" +#include "sound_driver.hpp" -extern const HalSoundDriver _null_sound_driver; +class SoundDriver_Null: public SoundDriver { +public: + /* virtual */ bool CanProbe() { return false; } + + /* virtual */ const char *Start(const char * const *param) { return NULL; } + + /* virtual */ void Stop() { } +}; + +class FSoundDriver_Null: public SoundDriverFactory<FSoundDriver_Null> { +public: + /* virtual */ const char *GetName() { return "null"; } + /* virtual */ const char *GetDescription() { return "Null Sound Driver"; } + /* virtual */ Driver *CreateInstance() { return new SoundDriver_Null(); } +}; #endif /* SOUND_NULL_H */ diff --git a/src/sound/sdl_s.cpp b/src/sound/sdl_s.cpp index b90336866..f9f40d4e3 100644 --- a/src/sound/sdl_s.cpp +++ b/src/sound/sdl_s.cpp @@ -10,12 +10,14 @@ #include "sdl_s.h" #include <SDL.h> +static FSoundDriver_SDL iFSoundDriver_SDL; + static void CDECL fill_sound_buffer(void *userdata, Uint8 *stream, int len) { MxMixSamples(stream, len / 4); } -static const char *SdlSoundStart(const char * const *parm) +const char *SoundDriver_SDL::Start(const char * const *parm) { SDL_AudioSpec spec; @@ -32,15 +34,10 @@ static const char *SdlSoundStart(const char * const *parm) return NULL; } -static void SdlSoundStop() +void SoundDriver_SDL::Stop() { SDL_CALL SDL_CloseAudio(); SdlClose(SDL_INIT_AUDIO); } -const HalSoundDriver _sdl_sound_driver = { - SdlSoundStart, - SdlSoundStop, -}; - #endif /* WITH_SDL */ diff --git a/src/sound/sdl_s.h b/src/sound/sdl_s.h index a667e137a..97a9036eb 100644 --- a/src/sound/sdl_s.h +++ b/src/sound/sdl_s.h @@ -3,8 +3,22 @@ #ifndef SOUND_SDL_H #define SOUND_SDL_H -#include "../hal.h" +#include "sound_driver.hpp" -extern const HalSoundDriver _sdl_sound_driver; +class SoundDriver_SDL: public SoundDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); +}; + +class FSoundDriver_SDL: public SoundDriverFactory<FSoundDriver_SDL> { +public: + /* virtual */ const char *GetName() { return "sdl"; } + /* virtual */ const char *GetDescription() { return "SDL Sound Driver"; } + /* virtual */ Driver *CreateInstance() { return new SoundDriver_SDL(); } +}; #endif /* SOUND_SDL_H */ diff --git a/src/sound/sound_driver.hpp b/src/sound/sound_driver.hpp new file mode 100644 index 000000000..de1a19ac8 --- /dev/null +++ b/src/sound/sound_driver.hpp @@ -0,0 +1,27 @@ +/* $Id$ */ + +#ifndef SOUND_SOUND_DRIVER_HPP +#define SOUND_SOUND_DRIVER_HPP + +#include "../driver.h" + +class SoundDriver: public Driver { +}; + +class SoundDriverFactoryBase: public DriverFactoryBase { +}; + +template <class T> +class SoundDriverFactory: public SoundDriverFactoryBase { +public: + SoundDriverFactory() { this->RegisterDriver(((T *)this)->GetName(), Driver::DT_SOUND); } + + /** + * Get the long, human readable, name for the Driver-class. + */ + const char *GetName(); +}; + +extern SoundDriver *_sound_driver; + +#endif /* SOUND_SOUND_DRIVER_HPP */ diff --git a/src/sound/win32_s.cpp b/src/sound/win32_s.cpp index 61b9ce9eb..578011986 100644 --- a/src/sound/win32_s.cpp +++ b/src/sound/win32_s.cpp @@ -10,6 +10,8 @@ #include <windows.h> #include <mmsystem.h> +static FSoundDriver_Win32 iFSoundDriver_Win32; + static HWAVEOUT _waveout; static WAVEHDR _wave_hdr[2]; static int _bufsize; @@ -48,7 +50,7 @@ static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, } } -static const char *Win32SoundStart(const char* const* parm) +const char *SoundDriver_Win32::Start(const char* const* parm) { WAVEFORMATEX wfex; wfex.wFormatTag = WAVE_FORMAT_PCM; @@ -69,7 +71,7 @@ static const char *Win32SoundStart(const char* const* parm) return NULL; } -static void Win32SoundStop() +void SoundDriver_Win32::Stop() { HWAVEOUT waveout = _waveout; @@ -79,8 +81,3 @@ static void Win32SoundStop() waveOutUnprepareHeader(waveout, &_wave_hdr[1], sizeof(WAVEHDR)); waveOutClose(waveout); } - -const HalSoundDriver _win32_sound_driver = { - Win32SoundStart, - Win32SoundStop, -}; diff --git a/src/sound/win32_s.h b/src/sound/win32_s.h index b91495edd..10a1f7502 100644 --- a/src/sound/win32_s.h +++ b/src/sound/win32_s.h @@ -3,8 +3,22 @@ #ifndef SOUND_WIN32_H #define SOUND_WIN32_H -#include "../hal.h" +#include "sound_driver.hpp" -extern const HalSoundDriver _win32_sound_driver; +class SoundDriver_Win32: public SoundDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); +}; + +class FSoundDriver_Win32: public SoundDriverFactory<FSoundDriver_Win32> { +public: + /* virtual */ const char *GetName() { return "win32"; } + /* virtual */ const char *GetDescription() { return "Win32 Sound Driver"; } + /* virtual */ Driver *CreateInstance() { return new SoundDriver_Win32(); } +}; #endif /* SOUND_WIN32_H */ diff --git a/src/texteff.cpp b/src/texteff.cpp index e5c29a4c7..d762c5bb6 100644 --- a/src/texteff.cpp +++ b/src/texteff.cpp @@ -11,7 +11,6 @@ #include "landscape.h" #include "viewport.h" #include "saveload.h" -#include "hal.h" #include "console.h" #include "string.h" #include "variables.h" @@ -20,6 +19,7 @@ #include <stdarg.h> /* va_list */ #include "date.h" #include "texteff.hpp" +#include "video/video_driver.hpp" enum { MAX_TEXTMESSAGE_LENGTH = 200, @@ -168,7 +168,7 @@ void UndrawTextMessage() /* Put our 'shot' back to the screen */ blitter->CopyFromBuffer(blitter->MoveTo(_screen.dst_ptr, x, y), _textmessage_backup, width, height); /* And make sure it is updated next time */ - _video_driver->make_dirty(x, y, width, height); + _video_driver->MakeDirty(x, y, width, height); _textmessage_dirty = true; } @@ -248,7 +248,7 @@ void DrawTextMessage() } /* Make sure the data is updated next flush */ - _video_driver->make_dirty(x, y, width, height); + _video_driver->MakeDirty(x, y, width, height); _textmessage_visible = true; _textmessage_dirty = false; diff --git a/src/video/cocoa_v.h b/src/video/cocoa_v.h index 3e39ec966..a6fd41871 100644 --- a/src/video/cocoa_v.h +++ b/src/video/cocoa_v.h @@ -3,11 +3,30 @@ #ifndef VIDEO_COCOA_H #define VIDEO_COCOA_H -#include "../hal.h" +#include "video_driver.hpp" -#include "../openttd.h" -#include "../gfx.h" +class VideoDriver_Cocoa: public VideoDriver { +public: + /* virtual */ bool CanProbe() { return true; } -extern const HalVideoDriver _cocoa_video_driver; + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void MakeDirty(int left, int top, int width, int height); + + /* virtual */ void MainLoop(); + + /* virtual */ bool ChangeResolution(int w, int h); + + /* virtual */ void ToggleFullscreen(bool fullscreen); +}; + +class FVideoDriver_Cocoa: public VideoDriverFactory<FVideoDriver_Cocoa> { +public: + /* virtual */ const char *GetName() { return "cocoa"; } + /* virtual */ const char *GetDescription() { return "Cocoa Video Driver"; } + /* virtual */ Driver *CreateInstance() { return new VideoDriver_Cocoa(); } +}; #endif /* VIDEO_COCOA_H */ diff --git a/src/video/cocoa_v.mm b/src/video/cocoa_v.mm index debbc2f53..4848ce991 100644 --- a/src/video/cocoa_v.mm +++ b/src/video/cocoa_v.mm @@ -65,10 +65,12 @@ extern "C" void HideMenuBar(); #include "../stdafx.h" +#include "../openttd.h" #include "../debug.h" #include "../macros.h" #include "../os/macosx/splash.h" #include "../variables.h" +#include "../gfx.h" #include "cocoa_v.h" #include "cocoa_keys.h" #include "../blitter/factory.hpp" @@ -131,14 +133,13 @@ static void QZ_UpdatePalette(uint start, uint count); static void QZ_WarpCursor(int x, int y); static void QZ_ShowMouse(); static void QZ_HideMouse(); -static void CocoaVideoFullScreen(bool full_screen); static NSAutoreleasePool *_ottd_autorelease_pool; static OTTDMain *_ottd_main; -static struct CocoaVideoData { +static struct VideoDriver_Cocoa::Data { bool isset; bool issetting; @@ -366,7 +367,7 @@ static void QZ_KeyEvent(unsigned short keycode, unsigned short unicode, BOOL dow case QZ_RETURN: case QZ_f: if (down && (_cocoa_video_data.current_mods & NSCommandKeyMask)) { - CocoaVideoFullScreen(!_fullscreen); + _video_driver->ToggleFullscreen(!_fullscreen); } break; } @@ -1319,9 +1320,9 @@ static uint32 QZ_FadeGammaIn(const OTTD_QuartzGammaTable* table) return 0; } -static const char* QZ_SetVideoFullScreen(int width, int height) +static const char* QZ_SetVideoToggleFullscreen(int width, int height) { - const char* errstr = "QZ_SetVideoFullScreen error"; + const char* errstr = "QZ_SetVideoToggleFullscreen error"; int exact_match; CFNumberRef number; int bpp; @@ -1707,7 +1708,7 @@ static const char* QZ_SetVideoMode(uint width, uint height, bool fullscreen) _cocoa_video_data.issetting = true; if (fullscreen) { /* Setup full screen video */ - ret = QZ_SetVideoFullScreen(width, height); + ret = QZ_SetVideoToggleFullscreen(width, height); } else { /* Setup windowed video */ ret = QZ_SetVideoWindowed(width, height); @@ -1970,7 +1971,9 @@ static void setupApplication() * Video driver interface * ******************************************************************************/ -static void CocoaVideoStop() +static FVideoDriver_Cocoa iFVideoDriver_Cocoa; + +void VideoDriver_Cocoa::Stop() { if (!_cocoa_video_started) return; @@ -1981,7 +1984,7 @@ static void CocoaVideoStop() _cocoa_video_started = false; } -static const char *CocoaVideoStart(const char * const *parm) +const char *VideoDriver_Cocoa::Start(const char * const *parm) { const char *ret; @@ -1998,12 +2001,12 @@ static const char *CocoaVideoStart(const char * const *parm) QZ_VideoInit(); ret = QZ_SetVideoMode(_cur_resolution[0], _cur_resolution[1], _fullscreen); - if (ret != NULL) CocoaVideoStop(); + if (ret != NULL) VideoDriver_Cocoa::Stop(); return ret; } -static void CocoaVideoMakeDirty(int left, int top, int width, int height) +void VideoDriver_Cocoa::MakeDirty(int left, int top, int width, int height) { if (_cocoa_video_data.num_dirty_rects < MAX_DIRTY_RECTS) { _cocoa_video_data.dirty_rects[_cocoa_video_data.num_dirty_rects].left = left; @@ -2014,41 +2017,32 @@ static void CocoaVideoMakeDirty(int left, int top, int width, int height) _cocoa_video_data.num_dirty_rects++; } -static void CocoaVideoMainLoop() +void VideoDriver_Cocoa::MainLoop() { /* Start the main event loop */ [NSApp run]; } -static bool CocoaVideoChangeRes(int w, int h) +bool VideoDriver_Cocoa::ChangeResolution(int w, int h) { const char *ret = QZ_SetVideoModeAndRestoreOnFailure((uint)w, (uint)h, _cocoa_video_data.fullscreen); if (ret != NULL) { - DEBUG(driver, 0, "cocoa_v: CocoaVideoChangeRes failed with message: %s", ret); + DEBUG(driver, 0, "cocoa_v: VideoDriver_Cocoa::ChangeResolution failed with message: %s", ret); } return ret == NULL; } -static void CocoaVideoFullScreen(bool full_screen) +void VideoDriver_Cocoa::ToggleFullscreen(bool full_screen) { const char *ret = QZ_SetVideoModeAndRestoreOnFailure(_cocoa_video_data.width, _cocoa_video_data.height, full_screen); if (ret != NULL) { - DEBUG(driver, 0, "cocoa_v: CocoaVideoFullScreen failed with message: %s", ret); + DEBUG(driver, 0, "cocoa_v: VideoDriver_Cocoa::ToggleFullscreen failed with message: %s", ret); } _fullscreen = _cocoa_video_data.fullscreen; } -const HalVideoDriver _cocoa_video_driver = { - CocoaVideoStart, - CocoaVideoStop, - CocoaVideoMakeDirty, - CocoaVideoMainLoop, - CocoaVideoChangeRes, - CocoaVideoFullScreen, -}; - /* This is needed since sometimes assert is called before the videodriver is initialized */ void CocoaDialog(const char* title, const char* message, const char* buttonLabel) @@ -2058,14 +2052,14 @@ void CocoaDialog(const char* title, const char* message, const char* buttonLabel _cocoa_video_dialog = true; wasstarted = _cocoa_video_started; - if (!_cocoa_video_started && CocoaVideoStart(NULL) != NULL) { + if (!_cocoa_video_started && VideoDriver_Cocoa::Start(NULL) != NULL) { fprintf(stderr, "%s: %s\n", title, message); return; } NSRunAlertPanel([NSString stringWithCString: title], [NSString stringWithCString: message], [NSString stringWithCString: buttonLabel], nil, nil); - if (!wasstarted) CocoaVideoStop(); + if (!wasstarted) VideoDriver_Cocoa::Stop(); _cocoa_video_dialog = false; } diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index cbcbaef3b..d4bfa7cbc 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -119,8 +119,10 @@ static void *_dedicated_video_mem; extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm, Subdirectory subdir); extern void SwitchMode(int new_mode); +static FVideoDriver_Dedicated iFVideoDriver_Dedicated; -static const char *DedicatedVideoStart(const char * const *parm) + +const char *VideoDriver_Dedicated::Start(const char * const *parm) { int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(); if (bpp == 0) _dedicated_video_mem = NULL; @@ -147,7 +149,7 @@ static const char *DedicatedVideoStart(const char * const *parm) return NULL; } -static void DedicatedVideoStop() +void VideoDriver_Dedicated::Stop() { #ifdef WIN32 CloseWindowsConsoleThread(); @@ -155,9 +157,9 @@ static void DedicatedVideoStop() free(_dedicated_video_mem); } -static void DedicatedVideoMakeDirty(int left, int top, int width, int height) {} -static bool DedicatedVideoChangeRes(int w, int h) { return false; } -static void DedicatedVideoFullScreen(bool fs) {} +void VideoDriver_Dedicated::MakeDirty(int left, int top, int width, int height) {} +bool VideoDriver_Dedicated::ChangeResolution(int w, int h) { return false; } +void VideoDriver_Dedicated::ToggleFullscreen(bool fs) {} #if defined(UNIX) || defined(__OS2__) || defined(PSP) static bool InputWaiting() @@ -232,7 +234,7 @@ static void DedicatedHandleKeyInput() IConsoleCmdExec(input_line); // execute command } -static void DedicatedVideoMainLoop() +void VideoDriver_Dedicated::MainLoop() { uint32 cur_ticks = GetTime(); uint32 next_tick = cur_ticks + 30; @@ -295,13 +297,4 @@ static void DedicatedVideoMainLoop() } } -const HalVideoDriver _dedicated_video_driver = { - DedicatedVideoStart, - DedicatedVideoStop, - DedicatedVideoMakeDirty, - DedicatedVideoMainLoop, - DedicatedVideoChangeRes, - DedicatedVideoFullScreen, -}; - #endif /* ENABLE_NETWORK */ diff --git a/src/video/dedicated_v.h b/src/video/dedicated_v.h index 5b752643e..d1dccd0c9 100644 --- a/src/video/dedicated_v.h +++ b/src/video/dedicated_v.h @@ -3,8 +3,30 @@ #ifndef VIDEO_DEDICATED_H #define VIDEO_DEDICATED_H -#include "../hal.h" +#include "video_driver.hpp" -extern const HalVideoDriver _dedicated_video_driver; +class VideoDriver_Dedicated: public VideoDriver { +public: + /* virtual */ bool CanProbe() { return false; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void MakeDirty(int left, int top, int width, int height); + + /* virtual */ void MainLoop(); + + /* virtual */ bool ChangeResolution(int w, int h); + + /* virtual */ void ToggleFullscreen(bool fullscreen); +}; + +class FVideoDriver_Dedicated: public VideoDriverFactory<FVideoDriver_Dedicated> { +public: + /* virtual */ const char *GetName() { return "dedicated"; } + /* virtual */ const char *GetDescription() { return "Dedicated Video Driver"; } + /* virtual */ Driver *CreateInstance() { return new VideoDriver_Dedicated(); } +}; #endif /* VIDEO_DEDICATED_H */ diff --git a/src/video/null_v.cpp b/src/video/null_v.cpp index d6afc7af4..0a01eb6f9 100644 --- a/src/video/null_v.cpp +++ b/src/video/null_v.cpp @@ -9,7 +9,9 @@ #include "../blitter/factory.hpp" #include "null_v.h" -static const char* NullVideoStart(const char* const* parm) +static FVideoDriver_Null iFVideoDriver_Null; + +const char *VideoDriver_Null::Start(const char* const *parm) { _screen.width = _screen.pitch = _cur_resolution[0]; _screen.height = _cur_resolution[1]; @@ -19,11 +21,11 @@ static const char* NullVideoStart(const char* const* parm) return NULL; } -static void NullVideoStop() { } +void VideoDriver_Null::Stop() { } -static void NullVideoMakeDirty(int left, int top, int width, int height) {} +void VideoDriver_Null::MakeDirty(int left, int top, int width, int height) {} -static void NullVideoMainLoop() +void VideoDriver_Null::MainLoop() { uint i; @@ -34,14 +36,6 @@ static void NullVideoMainLoop() } } -static bool NullVideoChangeRes(int w, int h) { return false; } -static void NullVideoFullScreen(bool fs) {} - -const HalVideoDriver _null_video_driver = { - NullVideoStart, - NullVideoStop, - NullVideoMakeDirty, - NullVideoMainLoop, - NullVideoChangeRes, - NullVideoFullScreen, -}; +bool VideoDriver_Null::ChangeResolution(int w, int h) { return false; } + +void VideoDriver_Null::ToggleFullscreen(bool fs) {} diff --git a/src/video/null_v.h b/src/video/null_v.h index 21f1af7a9..0e65933e8 100644 --- a/src/video/null_v.h +++ b/src/video/null_v.h @@ -3,8 +3,30 @@ #ifndef VIDEO_NULL_H #define VIDEO_NULL_H -#include "../hal.h" +#include "video_driver.hpp" -extern const HalVideoDriver _null_video_driver; +class VideoDriver_Null: public VideoDriver { +public: + /* virtual */ bool CanProbe() { return false; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void MakeDirty(int left, int top, int width, int height); + + /* virtual */ void MainLoop(); + + /* virtual */ bool ChangeResolution(int w, int h); + + /* virtual */ void ToggleFullscreen(bool fullscreen); +}; + +class FVideoDriver_Null: public VideoDriverFactory<FVideoDriver_Null> { +public: + /* virtual */ const char *GetName() { return "null"; } + /* virtual */ const char *GetDescription() { return "Null Video Driver"; } + /* virtual */ Driver *CreateInstance() { return new VideoDriver_Null(); } +}; #endif /* VIDEO_NULL_H */ diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp index bc12edb92..b6cc38a64 100644 --- a/src/video/sdl_v.cpp +++ b/src/video/sdl_v.cpp @@ -17,6 +17,8 @@ #include "sdl_v.h" #include <SDL.h> +static FVideoDriver_SDL iFVideoDriver_SDL; + static SDL_Surface *_sdl_screen; static bool _all_modes; @@ -24,7 +26,7 @@ static bool _all_modes; static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS]; static int _num_dirty_rects; -static void SdlVideoMakeDirty(int left, int top, int width, int height) +void VideoDriver_SDL::MakeDirty(int left, int top, int width, int height) { if (_num_dirty_rects < MAX_DIRTY_RECTS) { _dirty_rects[_num_dirty_rects].x = left; @@ -415,7 +417,7 @@ static int PollEvent() return -1; } -static const char *SdlVideoStart(const char * const *parm) +const char *VideoDriver_SDL::Start(const char * const *parm) { char buf[30]; @@ -434,12 +436,12 @@ static const char *SdlVideoStart(const char * const *parm) return NULL; } -static void SdlVideoStop() +void VideoDriver_SDL::Stop() { SdlClose(SDL_INIT_VIDEO); } -static void SdlVideoMainLoop() +void VideoDriver_SDL::MainLoop() { uint32 cur_ticks = SDL_CALL SDL_GetTicks(); uint32 last_cur_ticks = cur_ticks; @@ -505,28 +507,19 @@ static void SdlVideoMainLoop() } } -static bool SdlVideoChangeRes(int w, int h) +bool VideoDriver_SDL::ChangeResolution(int w, int h) { return CreateMainSurface(w, h); } -static void SdlVideoFullScreen(bool full_screen) +void VideoDriver_SDL::ToggleFullscreen(bool fullscreen) { - _fullscreen = full_screen; + _fullscreen = fullscreen; GetVideoModes(); // get the list of available video modes - if (_num_resolutions == 0 || !_video_driver->change_resolution(_cur_resolution[0], _cur_resolution[1])) { + if (_num_resolutions == 0 || !this->ChangeResolution(_cur_resolution[0], _cur_resolution[1])) { // switching resolution failed, put back full_screen to original status _fullscreen ^= true; } } -const HalVideoDriver _sdl_video_driver = { - SdlVideoStart, - SdlVideoStop, - SdlVideoMakeDirty, - SdlVideoMainLoop, - SdlVideoChangeRes, - SdlVideoFullScreen, -}; - #endif /* WITH_SDL */ diff --git a/src/video/sdl_v.h b/src/video/sdl_v.h index 2868b1c5c..ff494919d 100644 --- a/src/video/sdl_v.h +++ b/src/video/sdl_v.h @@ -3,8 +3,30 @@ #ifndef VIDEO_SDL_H #define VIDEO_SDL_H -#include "../hal.h" +#include "video_driver.hpp" -extern const HalVideoDriver _sdl_video_driver; +class VideoDriver_SDL: public VideoDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void MakeDirty(int left, int top, int width, int height); + + /* virtual */ void MainLoop(); + + /* virtual */ bool ChangeResolution(int w, int h); + + /* virtual */ void ToggleFullscreen(bool fullscreen); +}; + +class FVideoDriver_SDL: public VideoDriverFactory<FVideoDriver_SDL> { +public: + /* virtual */ const char *GetName() { return "sdl"; } + /* virtual */ const char *GetDescription() { return "SDL Video Driver"; } + /* virtual */ Driver *CreateInstance() { return new VideoDriver_SDL(); } +}; #endif /* VIDEO_SDL_H */ diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp new file mode 100644 index 000000000..eab438491 --- /dev/null +++ b/src/video/video_driver.hpp @@ -0,0 +1,35 @@ +/* $Id$ */ + +#ifndef VIDEO_VIDEO_DRIVER_HPP +#define VIDEO_VIDEO_DRIVER_HPP + +#include "../driver.h" + +class VideoDriver: public Driver { +public: + virtual void MakeDirty(int left, int top, int width, int height) = 0; + + virtual void MainLoop() = 0; + + virtual bool ChangeResolution(int w, int h) = 0; + + virtual void ToggleFullscreen(bool fullscreen) = 0; +}; + +class VideoDriverFactoryBase: public DriverFactoryBase { +}; + +template <class T> +class VideoDriverFactory: public VideoDriverFactoryBase { +public: + VideoDriverFactory() { this->RegisterDriver(((T *)this)->GetName(), Driver::DT_VIDEO); } + + /** + * Get the long, human readable, name for the Driver-class. + */ + const char *GetName(); +}; + +extern VideoDriver *_video_driver; + +#endif /* VIDEO_VIDEO_DRIVER_HPP */ diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 7fa306ff3..a1a987565 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -751,8 +751,9 @@ static void FindResolutions() SortResolutions(_num_resolutions); } +static FVideoDriver_Win32 iFVideoDriver_Win32; -static const char *Win32GdiStart(const char * const *parm) +const char *VideoDriver_Win32::Start(const char * const *parm) { memset(&_wnd, 0, sizeof(_wnd)); @@ -774,7 +775,7 @@ static const char *Win32GdiStart(const char * const *parm) return NULL; } -static void Win32GdiStop() +void VideoDriver_Win32::Stop() { DeleteObject(_wnd.gdi_palette); DeleteObject(_wnd.dib_sect); @@ -786,7 +787,7 @@ static void Win32GdiStop() MyShowCursor(true); } -static void Win32GdiMakeDirty(int left, int top, int width, int height) +void VideoDriver_Win32::MakeDirty(int left, int top, int width, int height) { RECT r = { left, top, left + width, top + height }; @@ -800,7 +801,7 @@ static void CheckPaletteAnim() InvalidateRect(_wnd.main_wnd, NULL, FALSE); } -static void Win32GdiMainLoop() +void VideoDriver_Win32::MainLoop() { MSG mesg; uint32 cur_ticks = GetTickCount(); @@ -873,7 +874,7 @@ static void Win32GdiMainLoop() } } -static bool Win32GdiChangeRes(int w, int h) +bool VideoDriver_Win32::ChangeResolution(int w, int h) { _wnd.width = _wnd.width_org = w; _wnd.height = _wnd.height_org = h; @@ -883,16 +884,7 @@ static bool Win32GdiChangeRes(int w, int h) return true; } -static void Win32GdiFullScreen(bool full_screen) +void VideoDriver_Win32::ToggleFullscreen(bool full_screen) { MakeWindow(full_screen); } - -const HalVideoDriver _win32_video_driver = { - Win32GdiStart, - Win32GdiStop, - Win32GdiMakeDirty, - Win32GdiMainLoop, - Win32GdiChangeRes, - Win32GdiFullScreen, -}; diff --git a/src/video/win32_v.h b/src/video/win32_v.h index d63a526f8..afd33a88c 100644 --- a/src/video/win32_v.h +++ b/src/video/win32_v.h @@ -3,8 +3,30 @@ #ifndef VIDEO_WIN32_H #define VIDEO_WIN32_H -#include "../hal.h" +#include "video_driver.hpp" -extern const HalVideoDriver _win32_video_driver; +class VideoDriver_Win32: public VideoDriver { +public: + /* virtual */ bool CanProbe() { return true; } + + /* virtual */ const char *Start(const char * const *param); + + /* virtual */ void Stop(); + + /* virtual */ void MakeDirty(int left, int top, int width, int height); + + /* virtual */ void MainLoop(); + + /* virtual */ bool ChangeResolution(int w, int h); + + /* virtual */ void ToggleFullscreen(bool fullscreen); +}; + +class FVideoDriver_Win32: public VideoDriverFactory<FVideoDriver_Win32> { +public: + /* virtual */ const char *GetName() { return "win32"; } + /* virtual */ const char *GetDescription() { return "Win32 Video Driver"; } + /* virtual */ Driver *CreateInstance() { return new VideoDriver_Win32(); } +}; #endif /* VIDEO_WIN32_H */ |