tron@2186: /* $Id$ */ tron@2186: tron@2171: #include "stdafx.h" tron@2171: #include "openttd.h" tron@2210: #include "debug.h" tron@2171: #include "driver.h" tron@2171: #include "functions.h" tron@2171: #include "hal.h" tron@2171: #include "string.h" tron@2171: tron@2210: #include "music/bemidi.h" tron@2210: #include "music/dmusic.h" tron@2210: #include "music/extmidi.h" tron@2210: #include "music/null_m.h" tron@2210: #include "music/os2_m.h" tron@2210: #include "music/win32_m.h" bjarni@2496: #include "music/qtmidi.h" tron@2210: tron@2210: #include "sound/null_s.h" tron@2210: #include "sound/sdl_s.h" bjarni@2736: #include "sound/cocoa_s.h" tron@2210: #include "sound/win32_s.h" tron@2210: tron@2210: #include "video/dedicated_v.h" tron@2210: #include "video/null_v.h" tron@2210: #include "video/sdl_v.h" bjarni@2736: #include "video/cocoa_v.h" tron@2210: #include "video/win32_v.h" tron@2210: tron@2219: typedef struct DriverDesc { tron@2219: const char* name; tron@2219: const char* longname; tron@2224: const HalCommonDriver* drv; tron@2219: } DriverDesc; tron@2219: tron@2219: typedef struct DriverClass { tron@2171: const DriverDesc *descs; tron@2171: const char *name; tron@2224: const HalCommonDriver** drv; tron@2171: } DriverClass; tron@2171: tron@2222: truelight@2902: #define M(x, y, z) { x, y, (const HalCommonDriver *)(void *)z } tron@2222: static const DriverDesc _music_driver_descs[] = { tron@2222: #ifdef __BEOS__ tron@2224: M("bemidi", "BeOS MIDI Driver", &_bemidi_music_driver), tron@2222: #endif tron@2222: #ifdef __OS2__ tron@2224: M("os2", "OS/2 Music Driver", &_os2_music_driver), tron@2222: #endif tron@2222: #ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT tron@2224: M("dmusic", "DirectMusic MIDI Driver", &_dmusic_midi_driver), tron@2222: #endif tron@2222: #ifdef WIN32 tron@2224: M("win32", "Win32 MIDI Driver", &_win32_music_driver), tron@2222: #endif bjarni@2500: #if defined(__APPLE__) && !defined(DEDICATED) bjarni@2496: M("qt", "QuickTime MIDI Driver", &_qtime_music_driver), bjarni@2496: #endif tron@2222: #ifdef UNIX tron@2303: #if !defined(__MORPHOS__) && !defined(__AMIGA__) tron@2224: M("extmidi", "External MIDI Driver", &_extmidi_music_driver), tron@2222: #endif tron@2222: #endif tron@2224: M("null", "Null Music Driver", &_null_music_driver), tron@2224: M(NULL, NULL, NULL) tron@2222: }; tron@2222: tron@2222: static const DriverDesc _sound_driver_descs[] = { tron@2222: #ifdef WIN32 tron@2224: M("win32", "Win32 WaveOut Driver", &_win32_sound_driver), tron@2222: #endif tron@2222: #ifdef WITH_SDL tron@2224: M("sdl", "SDL Sound Driver", &_sdl_sound_driver), tron@2222: #endif bjarni@2736: #ifdef WITH_COCOA bjarni@2736: M("cocoa", "Cocoa Sound Driver", &_cocoa_sound_driver), bjarni@2736: #endif tron@2224: M("null", "Null Sound Driver", &_null_sound_driver), tron@2224: M(NULL, NULL, NULL) tron@2222: }; tron@2222: tron@2222: static const DriverDesc _video_driver_descs[] = { tron@2222: #ifdef WIN32 tron@2224: M("win32", "Win32 GDI Video Driver", &_win32_video_driver), tron@2222: #endif tron@2222: #ifdef WITH_SDL tron@2224: M("sdl", "SDL Video Driver", &_sdl_video_driver), tron@2222: #endif bjarni@2736: #ifdef WITH_COCOA bjarni@2736: M("cocoa", "Cocoa Video Driver", &_cocoa_video_driver), bjarni@2736: #endif tron@2224: M("null", "Null Video Driver", &_null_video_driver), tron@2222: #ifdef ENABLE_NETWORK tron@2224: M("dedicated", "Dedicated Video Driver", &_dedicated_video_driver), tron@2222: #endif tron@2224: M(NULL, NULL, NULL) tron@2222: }; tron@2224: #undef M tron@2222: tron@2219: truelight@2902: #define M(x, y, z) { x, y, (const HalCommonDriver **)(void *)z } tron@2219: static const DriverClass _driver_classes[] = { tron@2224: M(_video_driver_descs, "video", &_video_driver), tron@2224: M(_sound_driver_descs, "sound", &_sound_driver), tron@2224: M(_music_driver_descs, "music", &_music_driver) tron@2171: }; tron@2224: #undef M tron@2171: tron@2171: static const DriverDesc* GetDriverByName(const DriverDesc* dd, const char* name) tron@2171: { tron@2171: for (; dd->name != NULL; dd++) { tron@2171: if (strcmp(dd->name, name) == 0) return dd; tron@2171: } tron@2171: return NULL; tron@2171: } tron@2171: tron@2171: void LoadDriver(int driver, const char *name) tron@2171: { tron@2171: const DriverClass *dc = &_driver_classes[driver]; tron@2171: const DriverDesc *dd; tron@2171: const char *err; tron@2171: tron@2210: if (*name == '\0') { tron@2210: for (dd = dc->descs; dd->name != NULL; dd++) { tron@2224: err = dd->drv->start(NULL); tron@2210: if (err == NULL) break; tron@2210: DEBUG(driver, 1) ("Probing %s driver \"%s\" failed with error: %s", tron@2210: dc->name, dd->name, err tron@2210: ); tron@2210: } tron@2210: if (dd->name == NULL) { tron@2210: error("Couldn't find any suitable %s driver", dc->name); tron@2210: } tron@2210: tron@2210: DEBUG(driver, 1) tron@2210: ("Successfully probed %s driver \"%s\"", dc->name, dd->name); tron@2210: tron@2224: *dc->drv = dd->drv; tron@2171: } else { tron@2224: char* parm; tron@2224: char buffer[256]; tron@2224: const char* parms[32]; tron@2224: tron@2171: // Extract the driver name and put parameter list in parm tron@2171: ttd_strlcpy(buffer, name, sizeof(buffer)); tron@2171: parm = strchr(buffer, ':'); tron@2224: parms[0] = NULL; tron@2224: if (parm != NULL) { tron@2171: uint np = 0; tron@2171: // Tokenize the parm. tron@2171: do { tron@2224: *parm++ = '\0'; tron@2171: if (np < lengthof(parms) - 1) tron@2171: parms[np++] = parm; tron@2224: while (*parm != '\0' && *parm != ',') tron@2171: parm++; tron@2171: } while (*parm == ','); tron@2171: parms[np] = NULL; tron@2171: } tron@2171: dd = GetDriverByName(dc->descs, buffer); tron@2171: if (dd == NULL) tron@2171: error("No such %s driver: %s\n", dc->name, buffer); tron@2210: tron@2224: if (*dc->drv != NULL) (*dc->drv)->stop(); tron@2224: *dc->drv = NULL; tron@2210: tron@2224: err = dd->drv->start(parms); tron@2210: if (err != NULL) { tron@2210: error("Unable to load driver %s(%s). The error was: %s\n", tron@2210: dd->name, dd->longname, err tron@2210: ); tron@2210: } tron@2224: *dc->drv = dd->drv; tron@2171: } tron@2171: } tron@2171: tron@2171: tron@2171: static const char* GetDriverParam(const char* const* parm, const char* name) tron@2171: { tron@2458: size_t len; tron@2171: tron@2224: if (parm == NULL) return NULL; tron@2224: tron@2224: len = strlen(name); tron@2171: for (; *parm != NULL; parm++) { tron@2171: const char* p = *parm; tron@2171: tron@2171: if (strncmp(p, name, len) == 0) { tron@2171: if (p[len] == '=') return p + len + 1; tron@2171: if (p[len] == '\0') return p + len; tron@2171: } tron@2171: } tron@2171: return NULL; tron@2171: } tron@2171: tron@2171: bool GetDriverParamBool(const char* const* parm, const char* name) tron@2171: { tron@2171: return GetDriverParam(parm, name) != NULL; tron@2171: } tron@2171: tron@2171: int GetDriverParamInt(const char* const* parm, const char* name, int def) tron@2171: { tron@2171: const char* p = GetDriverParam(parm, name); tron@2171: return p != NULL ? atoi(p) : def; tron@2171: } tron@2171: tron@2171: truelight@2832: char *GetDriverList(char* p) tron@2171: { tron@2171: const DriverClass* dc; tron@2171: tron@2171: for (dc = _driver_classes; dc != endof(_driver_classes); dc++) { tron@2171: const DriverDesc* dd; tron@2171: truelight@2832: p += sprintf(p, "List of %s drivers:\n", dc->name); tron@2171: for (dd = dc->descs; dd->name != NULL; dd++) { truelight@2832: p += sprintf(p, "%10s: %s\n", dd->name, dd->longname); tron@2171: } truelight@2832: p += sprintf(p, "\n"); tron@2171: } truelight@2831: truelight@2832: return p; tron@2171: }