|
1 /* $Id$ */ |
|
2 |
|
3 #include "stdafx.h" |
|
4 #include "openttd.h" |
|
5 #include "debug.h" |
|
6 #include "driver.h" |
|
7 #include "functions.h" |
|
8 #include "hal.h" |
|
9 #include "string.h" |
|
10 |
|
11 #include "music/bemidi.h" |
|
12 #include "music/dmusic.h" |
|
13 #include "music/extmidi.h" |
|
14 #include "music/null_m.h" |
|
15 #include "music/os2_m.h" |
|
16 #include "music/win32_m.h" |
|
17 #include "music/qtmidi.h" |
|
18 |
|
19 #include "sound/null_s.h" |
|
20 #include "sound/sdl_s.h" |
|
21 #include "sound/cocoa_s.h" |
|
22 #include "sound/win32_s.h" |
|
23 |
|
24 #include "video/dedicated_v.h" |
|
25 #include "video/null_v.h" |
|
26 #include "video/sdl_v.h" |
|
27 #include "video/cocoa_v.h" |
|
28 #include "video/win32_v.h" |
|
29 |
|
30 typedef struct DriverDesc { |
|
31 const char* name; |
|
32 const char* longname; |
|
33 const HalCommonDriver* drv; |
|
34 } DriverDesc; |
|
35 |
|
36 typedef struct DriverClass { |
|
37 const DriverDesc *descs; |
|
38 const char *name; |
|
39 const HalCommonDriver** drv; |
|
40 } DriverClass; |
|
41 |
|
42 |
|
43 #define M(x, y, z) { x, y, (const HalCommonDriver *)(void *)z } |
|
44 static const DriverDesc _music_driver_descs[] = { |
|
45 #ifdef __BEOS__ |
|
46 M("bemidi", "BeOS MIDI Driver", &_bemidi_music_driver), |
|
47 #endif |
|
48 #if defined(__OS2__) && !defined(__INNOTEK_LIBC__) |
|
49 M("os2", "OS/2 Music Driver", &_os2_music_driver), |
|
50 #endif |
|
51 #ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT |
|
52 M("dmusic", "DirectMusic MIDI Driver", &_dmusic_midi_driver), |
|
53 #endif |
|
54 #ifdef WIN32 |
|
55 M("win32", "Win32 MIDI Driver", &_win32_music_driver), |
|
56 #endif |
|
57 #if defined(__APPLE__) && !defined(DEDICATED) |
|
58 M("qt", "QuickTime MIDI Driver", &_qtime_music_driver), |
|
59 #endif |
|
60 #ifdef UNIX |
|
61 #if !defined(__MORPHOS__) && !defined(__AMIGA__) |
|
62 M("extmidi", "External MIDI Driver", &_extmidi_music_driver), |
|
63 #endif |
|
64 #endif |
|
65 M("null", "Null Music Driver", &_null_music_driver), |
|
66 M(NULL, NULL, NULL) |
|
67 }; |
|
68 |
|
69 static const DriverDesc _sound_driver_descs[] = { |
|
70 #ifdef WIN32 |
|
71 M("win32", "Win32 WaveOut Driver", &_win32_sound_driver), |
|
72 #endif |
|
73 #ifdef WITH_SDL |
|
74 M("sdl", "SDL Sound Driver", &_sdl_sound_driver), |
|
75 #endif |
|
76 #ifdef WITH_COCOA |
|
77 M("cocoa", "Cocoa Sound Driver", &_cocoa_sound_driver), |
|
78 #endif |
|
79 M("null", "Null Sound Driver", &_null_sound_driver), |
|
80 M(NULL, NULL, NULL) |
|
81 }; |
|
82 |
|
83 static const DriverDesc _video_driver_descs[] = { |
|
84 #ifdef WIN32 |
|
85 M("win32", "Win32 GDI Video Driver", &_win32_video_driver), |
|
86 #endif |
|
87 #ifdef WITH_SDL |
|
88 M("sdl", "SDL Video Driver", &_sdl_video_driver), |
|
89 #endif |
|
90 #ifdef WITH_COCOA |
|
91 M("cocoa", "Cocoa Video Driver", &_cocoa_video_driver), |
|
92 #endif |
|
93 M("null", "Null Video Driver", &_null_video_driver), |
|
94 #ifdef ENABLE_NETWORK |
|
95 M("dedicated", "Dedicated Video Driver", &_dedicated_video_driver), |
|
96 #endif |
|
97 M(NULL, NULL, NULL) |
|
98 }; |
|
99 #undef M |
|
100 |
|
101 |
|
102 #define M(x, y, z) { x, y, (const HalCommonDriver **)(void *)z } |
|
103 static const DriverClass _driver_classes[] = { |
|
104 M(_video_driver_descs, "video", &_video_driver), |
|
105 M(_sound_driver_descs, "sound", &_sound_driver), |
|
106 M(_music_driver_descs, "music", &_music_driver) |
|
107 }; |
|
108 #undef M |
|
109 |
|
110 static const DriverDesc* GetDriverByName(const DriverDesc* dd, const char* name) |
|
111 { |
|
112 for (; dd->name != NULL; dd++) { |
|
113 if (strcmp(dd->name, name) == 0) return dd; |
|
114 } |
|
115 return NULL; |
|
116 } |
|
117 |
|
118 void LoadDriver(int driver, const char *name) |
|
119 { |
|
120 const DriverClass *dc = &_driver_classes[driver]; |
|
121 const DriverDesc *dd; |
|
122 const char *err; |
|
123 |
|
124 if (*name == '\0') { |
|
125 for (dd = dc->descs; dd->name != NULL; dd++) { |
|
126 err = dd->drv->start(NULL); |
|
127 if (err == NULL) break; |
|
128 DEBUG(driver, 1, "Probing %s driver '%s' failed with error: %s", |
|
129 dc->name, dd->name, err |
|
130 ); |
|
131 } |
|
132 if (dd->name == NULL) error("Couldn't find any suitable %s driver", dc->name); |
|
133 |
|
134 DEBUG(driver, 1, "Successfully probed %s driver '%s'", dc->name, dd->name); |
|
135 |
|
136 *dc->drv = dd->drv; |
|
137 } else { |
|
138 char* parm; |
|
139 char buffer[256]; |
|
140 const char* parms[32]; |
|
141 |
|
142 // Extract the driver name and put parameter list in parm |
|
143 ttd_strlcpy(buffer, name, sizeof(buffer)); |
|
144 parm = strchr(buffer, ':'); |
|
145 parms[0] = NULL; |
|
146 if (parm != NULL) { |
|
147 uint np = 0; |
|
148 // Tokenize the parm. |
|
149 do { |
|
150 *parm++ = '\0'; |
|
151 if (np < lengthof(parms) - 1) |
|
152 parms[np++] = parm; |
|
153 while (*parm != '\0' && *parm != ',') |
|
154 parm++; |
|
155 } while (*parm == ','); |
|
156 parms[np] = NULL; |
|
157 } |
|
158 dd = GetDriverByName(dc->descs, buffer); |
|
159 if (dd == NULL) |
|
160 error("No such %s driver: %s\n", dc->name, buffer); |
|
161 |
|
162 if (*dc->drv != NULL) (*dc->drv)->stop(); |
|
163 *dc->drv = NULL; |
|
164 |
|
165 err = dd->drv->start(parms); |
|
166 if (err != NULL) { |
|
167 error("Unable to load driver %s(%s). The error was: %s\n", |
|
168 dd->name, dd->longname, err |
|
169 ); |
|
170 } |
|
171 *dc->drv = dd->drv; |
|
172 } |
|
173 } |
|
174 |
|
175 |
|
176 static const char* GetDriverParam(const char* const* parm, const char* name) |
|
177 { |
|
178 size_t len; |
|
179 |
|
180 if (parm == NULL) return NULL; |
|
181 |
|
182 len = strlen(name); |
|
183 for (; *parm != NULL; parm++) { |
|
184 const char* p = *parm; |
|
185 |
|
186 if (strncmp(p, name, len) == 0) { |
|
187 if (p[len] == '=') return p + len + 1; |
|
188 if (p[len] == '\0') return p + len; |
|
189 } |
|
190 } |
|
191 return NULL; |
|
192 } |
|
193 |
|
194 bool GetDriverParamBool(const char* const* parm, const char* name) |
|
195 { |
|
196 return GetDriverParam(parm, name) != NULL; |
|
197 } |
|
198 |
|
199 int GetDriverParamInt(const char* const* parm, const char* name, int def) |
|
200 { |
|
201 const char* p = GetDriverParam(parm, name); |
|
202 return p != NULL ? atoi(p) : def; |
|
203 } |
|
204 |
|
205 |
|
206 char *GetDriverList(char* p, const char *last) |
|
207 { |
|
208 const DriverClass* dc; |
|
209 |
|
210 for (dc = _driver_classes; dc != endof(_driver_classes); dc++) { |
|
211 const DriverDesc* dd; |
|
212 |
|
213 p += snprintf(p, last - p, "List of %s drivers:\n", dc->name); |
|
214 for (dd = dc->descs; dd->name != NULL; dd++) { |
|
215 p += snprintf(p, last - p, "%10s: %s\n", dd->name, dd->longname); |
|
216 } |
|
217 p = strecpy(p, "\n", last); |
|
218 } |
|
219 |
|
220 return p; |
|
221 } |