4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
10 /** @file driver.cpp Base for all driver handling. */
14 #include "sound/sound_driver.hpp"
15 #include "music/music_driver.hpp"
16 #include "video/video_driver.hpp"
17 #include "string_func.h"
19 VideoDriver
*_video_driver
; ///< The currently active video driver.
20 char *_ini_videodriver
; ///< The video driver a stored in the configuration file.
21 int _num_resolutions
; ///< The number of resolutions.
22 Dimension _resolutions
[32]; ///< List of resolutions.
23 Dimension _cur_resolution
; ///< The current resolution.
24 bool _rightclick_emulate
; ///< Whether right clicking is emulated.
26 SoundDriver
*_sound_driver
; ///< The currently active sound driver.
27 char *_ini_sounddriver
; ///< The sound driver a stored in the configuration file.
29 MusicDriver
*_music_driver
; ///< The currently active music driver.
30 char *_ini_musicdriver
; ///< The music driver a stored in the configuration file.
32 char *_ini_blitter
; ///< The blitter as stored in the configuration file.
33 bool _blitter_autodetected
; ///< Was the blitter autodetected or specified by the user?
36 * Get a string parameter the list of parameters.
37 * @param parm The parameters.
38 * @param name The parameter name we're looking for.
39 * @return The parameter value.
41 const char *GetDriverParam(const char * const *parm
, const char *name
)
45 if (parm
== NULL
) return NULL
;
48 for (; *parm
!= NULL
; parm
++) {
49 const char *p
= *parm
;
51 if (strncmp(p
, name
, len
) == 0) {
52 if (p
[len
] == '=') return p
+ len
+ 1;
53 if (p
[len
] == '\0') return p
+ len
;
60 * Get a boolean parameter the list of parameters.
61 * @param parm The parameters.
62 * @param name The parameter name we're looking for.
63 * @return The parameter value.
65 bool GetDriverParamBool(const char * const *parm
, const char *name
)
67 return GetDriverParam(parm
, name
) != NULL
;
71 * Get an integer parameter the list of parameters.
72 * @param parm The parameters.
73 * @param name The parameter name we're looking for.
74 * @param def The default value if the parameter doesn't exist.
75 * @return The parameter value.
77 int GetDriverParamInt(const char * const *parm
, const char *name
, int def
)
79 const char *p
= GetDriverParam(parm
, name
);
80 return p
!= NULL
? atoi(p
) : def
;
84 * Find the requested driver and return its class.
85 * @param name the driver to select.
86 * @param type the type of driver to select
87 * @post Sets the driver so GetCurrentDriver() returns it too.
89 Driver
*DriverFactoryBase::SelectDriver(const char *name
, Driver::Type type
)
91 if (GetDrivers().size() == 0) return NULL
;
94 /* Probe for this driver, but do not fall back to dedicated/null! */
95 for (int priority
= 10; priority
> 0; priority
--) {
96 Drivers::iterator it
= GetDrivers().begin();
97 for (; it
!= GetDrivers().end(); ++it
) {
98 DriverFactoryBase
*d
= (*it
).second
;
100 /* Check driver type */
101 if (d
->type
!= type
) continue;
102 if (d
->priority
!= priority
) continue;
104 Driver
*newd
= d
->CreateInstance();
105 const char *err
= newd
->Start(NULL
);
107 DEBUG(driver
, 1, "Successfully probed %s driver '%s'", GetDriverTypeName(type
), d
->name
);
108 delete *GetActiveDriver(type
);
109 *GetActiveDriver(type
) = newd
;
113 DEBUG(driver
, 1, "Probing %s driver '%s' failed with error: %s", GetDriverTypeName(type
), d
->name
, err
);
117 usererror("Couldn't find any suitable %s driver", GetDriverTypeName(type
));
121 const char *parms
[32];
123 /* Extract the driver name and put parameter list in parm */
124 strecpy(buffer
, name
, lastof(buffer
));
125 parm
= strchr(buffer
, ':');
129 /* Tokenize the parm. */
132 if (np
< lengthof(parms
) - 1) parms
[np
++] = parm
;
133 while (*parm
!= '\0' && *parm
!= ',') parm
++;
134 } while (*parm
== ',');
138 /* Find this driver */
139 Drivers::iterator it
= GetDrivers().begin();
140 for (; it
!= GetDrivers().end(); ++it
) {
141 DriverFactoryBase
*d
= (*it
).second
;
143 /* Check driver type */
144 if (d
->type
!= type
) continue;
146 /* Check driver name */
147 if (strcasecmp(buffer
, d
->name
) != 0) continue;
149 /* Found our driver, let's try it */
150 Driver
*newd
= d
->CreateInstance();
152 const char *err
= newd
->Start(parms
);
155 usererror("Unable to load driver '%s'. The error was: %s", d
->name
, err
);
158 DEBUG(driver
, 1, "Successfully loaded %s driver '%s'", GetDriverTypeName(type
), d
->name
);
159 delete *GetActiveDriver(type
);
160 *GetActiveDriver(type
) = newd
;
163 usererror("No such %s driver: %s\n", GetDriverTypeName(type
), buffer
);
168 * Register a driver internally, based on its name.
169 * @param name the name of the driver.
170 * @param type the type of driver to register
171 * @param priority the priority; how badly do we want this as default?
172 * @note an assert() will be trigger if 2 driver with the same name try to register.
174 void DriverFactoryBase::RegisterDriver(const char *name
, Driver::Type type
, int priority
)
176 /* Don't register nameless Drivers */
177 if (name
== NULL
) return;
179 this->name
= strdup(name
);
181 this->priority
= priority
;
183 /* Prefix the name with driver type to make it unique */
185 strecpy(buf
, GetDriverTypeName(type
), lastof(buf
));
186 strecpy(buf
+ 5, name
, lastof(buf
));
188 const char *longname
= strdup(buf
);
190 std::pair
<Drivers::iterator
, bool> P
= GetDrivers().insert(Drivers::value_type(longname
, this));
195 * Build a human readable list of available drivers, grouped by type.
196 * @param p The buffer to write to.
197 * @param last The last element in the buffer.
198 * @return The end of the written buffer.
200 char *DriverFactoryBase::GetDriversInfo(char *p
, const char *last
)
202 for (Driver::Type type
= Driver::DT_BEGIN
; type
!= Driver::DT_END
; type
++) {
203 p
+= seprintf(p
, last
, "List of %s drivers:\n", GetDriverTypeName(type
));
205 for (int priority
= 10; priority
>= 0; priority
--) {
206 Drivers::iterator it
= GetDrivers().begin();
207 for (; it
!= GetDrivers().end(); it
++) {
208 DriverFactoryBase
*d
= (*it
).second
;
209 if (d
->type
!= type
) continue;
210 if (d
->priority
!= priority
) continue;
211 p
+= seprintf(p
, last
, "%18s: %s\n", d
->name
, d
->GetDescription());
215 p
+= seprintf(p
, last
, "\n");
222 * Frees memory used for this->name
224 DriverFactoryBase::~DriverFactoryBase()
226 if (this->name
== NULL
) return;
228 /* Prefix the name with driver type to make it unique */
230 strecpy(buf
, GetDriverTypeName(type
), lastof(buf
));
231 strecpy(buf
+ 5, this->name
, lastof(buf
));
233 Drivers::iterator it
= GetDrivers().find(buf
);
234 assert(it
!= GetDrivers().end());
236 const char *longname
= (*it
).first
;
238 GetDrivers().erase(it
);
239 free((void *)longname
);
241 if (GetDrivers().empty()) delete &GetDrivers();
242 free((void *)this->name
);