1 /* $Id: driver.cpp 26107 2013-11-25 14:26:46Z rubidium $ */
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 #include "safeguards.h"
21 char *_ini_videodriver
; ///< The video driver a stored in the configuration file.
22 int _num_resolutions
; ///< The number of resolutions.
23 Dimension _resolutions
[32]; ///< List of resolutions.
24 Dimension _cur_resolution
; ///< The current resolution.
25 bool _rightclick_emulate
; ///< Whether right clicking is emulated.
27 char *_ini_sounddriver
; ///< The sound driver a stored in the configuration file.
29 char *_ini_musicdriver
; ///< The music driver a stored in the configuration file.
31 char *_ini_blitter
; ///< The blitter as stored in the configuration file.
32 bool _blitter_autodetected
; ///< Was the blitter autodetected or specified by the user?
35 * Get a string parameter the list of parameters.
36 * @param parm The parameters.
37 * @param name The parameter name we're looking for.
38 * @return The parameter value.
40 const char *GetDriverParam(const char * const *parm
, const char *name
)
44 if (parm
== nullptr) return nullptr;
47 for (; *parm
!= nullptr; parm
++) {
48 const char *p
= *parm
;
50 if (strncmp(p
, name
, len
) == 0) {
51 if (p
[len
] == '=') return p
+ len
+ 1;
52 if (p
[len
] == '\0') return p
+ len
;
59 * Get a boolean parameter the list of parameters.
60 * @param parm The parameters.
61 * @param name The parameter name we're looking for.
62 * @return The parameter value.
64 bool GetDriverParamBool(const char * const *parm
, const char *name
)
66 return GetDriverParam(parm
, name
) != nullptr;
70 * Get an integer parameter the list of parameters.
71 * @param parm The parameters.
72 * @param name The parameter name we're looking for.
73 * @param def The default value if the parameter doesn't exist.
74 * @return The parameter value.
76 int GetDriverParamInt(const char * const *parm
, const char *name
, int def
)
78 const char *p
= GetDriverParam(parm
, name
);
79 return p
!= nullptr ? atoi(p
) : def
;
83 * Find the requested driver and return its class.
84 * @param name the driver to select.
85 * @param type the type of driver to select
86 * @post Sets the driver so GetCurrentDriver() returns it too.
88 void DriverFactoryBase::SelectDriver(const char *name
, Driver::Type type
)
90 if (!DriverFactoryBase::SelectDriverImpl(name
, type
)) {
92 usererror("Failed to autoprobe %s driver", GetDriverTypeName(type
)) :
93 usererror("Failed to select requested %s driver '%s'", GetDriverTypeName(type
), name
);
98 * Find the requested driver and return its class.
99 * @param name the driver to select.
100 * @param type the type of driver to select
101 * @post Sets the driver so GetCurrentDriver() returns it too.
102 * @return True upon success, otherwise false.
104 bool DriverFactoryBase::SelectDriverImpl(const char *name
, Driver::Type type
)
106 if (GetDrivers().size() == 0) return false;
108 if (StrEmpty(name
)) {
109 /* Probe for this driver, but do not fall back to dedicated/null! */
110 for (int priority
= 10; priority
> 0; priority
--) {
111 Drivers::iterator it
= GetDrivers().begin();
112 for (; it
!= GetDrivers().end(); ++it
) {
113 DriverFactoryBase
*d
= (*it
).second
;
115 /* Check driver type */
116 if (d
->type
!= type
) continue;
117 if (d
->priority
!= priority
) continue;
119 Driver
*oldd
= *GetActiveDriver(type
);
120 Driver
*newd
= d
->CreateInstance();
121 *GetActiveDriver(type
) = newd
;
123 const char *err
= newd
->Start(nullptr);
124 if (err
== nullptr) {
125 DEBUG(driver
, 1, "Successfully probed %s driver '%s'", GetDriverTypeName(type
), d
->name
);
130 *GetActiveDriver(type
) = oldd
;
131 DEBUG(driver
, 1, "Probing %s driver '%s' failed with error: %s", GetDriverTypeName(type
), d
->name
, err
);
135 usererror("Couldn't find any suitable %s driver", GetDriverTypeName(type
));
139 const char *parms
[32];
141 /* Extract the driver name and put parameter list in parm */
142 strecpy(buffer
, name
, lastof(buffer
));
143 parm
= strchr(buffer
, ':');
145 if (parm
!= nullptr) {
147 /* Tokenize the parm. */
150 if (np
< lengthof(parms
) - 1) parms
[np
++] = parm
;
151 while (*parm
!= '\0' && *parm
!= ',') parm
++;
152 } while (*parm
== ',');
156 /* Find this driver */
157 Drivers::iterator it
= GetDrivers().begin();
158 for (; it
!= GetDrivers().end(); ++it
) {
159 DriverFactoryBase
*d
= (*it
).second
;
161 /* Check driver type */
162 if (d
->type
!= type
) continue;
164 /* Check driver name */
165 if (strcasecmp(buffer
, d
->name
) != 0) continue;
167 /* Found our driver, let's try it */
168 Driver
*newd
= d
->CreateInstance();
170 const char *err
= newd
->Start(parms
);
171 if (err
!= nullptr) {
173 usererror("Unable to load driver '%s'. The error was: %s", d
->name
, err
);
176 DEBUG(driver
, 1, "Successfully loaded %s driver '%s'", GetDriverTypeName(type
), d
->name
);
177 delete *GetActiveDriver(type
);
178 *GetActiveDriver(type
) = newd
;
181 usererror("No such %s driver: %s\n", GetDriverTypeName(type
), buffer
);
186 * Build a human readable list of available drivers, grouped by type.
187 * @param p The buffer to write to.
188 * @param last The last element in the buffer.
189 * @return The end of the written buffer.
191 char *DriverFactoryBase::GetDriversInfo(char *p
, const char *last
)
193 for (Driver::Type type
= Driver::DT_BEGIN
; type
!= Driver::DT_END
; type
++) {
194 p
+= seprintf(p
, last
, "List of %s drivers:\n", GetDriverTypeName(type
));
196 for (int priority
= 10; priority
>= 0; priority
--) {
197 Drivers::iterator it
= GetDrivers().begin();
198 for (; it
!= GetDrivers().end(); it
++) {
199 DriverFactoryBase
*d
= (*it
).second
;
200 if (d
->type
!= type
) continue;
201 if (d
->priority
!= priority
) continue;
202 p
+= seprintf(p
, last
, "%18s: %s\n", d
->name
, d
->GetDescription());
206 p
+= seprintf(p
, last
, "\n");
213 * Construct a new DriverFactory.
214 * @param type The type of driver.
215 * @param priority The priority within the driver class.
216 * @param name The name of the driver.
217 * @param description A long-ish description of the driver.
219 DriverFactoryBase::DriverFactoryBase(Driver::Type type
, int priority
, const char *name
, const char *description
) :
220 type(type
), priority(priority
), name(name
), description(description
)
222 /* Prefix the name with driver type to make it unique */
224 strecpy(buf
, GetDriverTypeName(type
), lastof(buf
));
225 strecpy(buf
+ 5, name
, lastof(buf
));
227 const char *longname
= stredup(buf
);
229 std::pair
<Drivers::iterator
, bool> P
= GetDrivers().insert(Drivers::value_type(longname
, this));
234 * Frees memory used for this->name
236 DriverFactoryBase::~DriverFactoryBase()
238 /* Prefix the name with driver type to make it unique */
240 strecpy(buf
, GetDriverTypeName(type
), lastof(buf
));
241 strecpy(buf
+ 5, this->name
, lastof(buf
));
243 Drivers::iterator it
= GetDrivers().find(buf
);
244 assert(it
!= GetDrivers().end());
246 const char *longname
= (*it
).first
;
248 GetDrivers().erase(it
);
251 if (GetDrivers().empty()) delete &GetDrivers();