# driver.cpp

Go to the documentation of this file.

    00001 /* $Id: driver.cpp 23198 2011-11-12 13:00:29Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "debug.h"
    00014 #include "sound/sound_driver.hpp"
    00015 #include "music/music_driver.hpp"
    00016 #include "video/video_driver.hpp"
    00017 #include "string_func.h"
    00018
    00019 VideoDriver *_video_driver;
    00020 char *_ini_videodriver;
    00021 int _num_resolutions;
    00022 Dimension _resolutions[32];
    00023 Dimension _cur_resolution;
    00024 bool _rightclick_emulate;
    00025
    00026 SoundDriver *_sound_driver;
    00027 char *_ini_sounddriver;
    00028
    00029 MusicDriver *_music_driver;
    00030 char *_ini_musicdriver;
    00031
    00032 char *_ini_blitter;
    00033 bool _blitter_autodetected;
    00034
    00041 const char *GetDriverParam(const char * const *parm, const char *name)
    00042 {
    00043   size_t len;
    00044
    00045   if (parm == NULL) return NULL;
    00046
    00047   len = strlen(name);
    00048   for (; *parm != NULL; parm++) {
    00049     const char *p = *parm;
    00050
    00051     if (strncmp(p, name, len) == 0) {
    00052       if (p[len] == '=')  return p + len + 1;
    00053       if (p[len] == '\0') return p + len;
    00054     }
    00055   }
    00056   return NULL;
    00057 }
    00058
    00065 bool GetDriverParamBool(const char * const *parm, const char *name)
    00066 {
    00067   return GetDriverParam(parm, name) != NULL;
    00068 }
    00069
    00077 int GetDriverParamInt(const char * const *parm, const char *name, int def)
    00078 {
    00079   const char *p = GetDriverParam(parm, name);
    00080   return p != NULL ? atoi(p) : def;
    00081 }
    00082
    00089 Driver *DriverFactoryBase::SelectDriver(const char *name, Driver::Type type)
    00090 {
    00091   if (GetDrivers().size() == 0) return NULL;
    00092
    00093   if (StrEmpty(name)) {
    00094     /* Probe for this driver, but do not fall back to dedicated/null! */
    00095     for (int priority = 10; priority > 0; priority--) {
    00096       Drivers::iterator it = GetDrivers().begin();
    00097       for (; it != GetDrivers().end(); ++it) {
    00098         DriverFactoryBase *d = (*it).second;
    00099
    00100         /* Check driver type */
    00101         if (d->type != type) continue;
    00102         if (d->priority != priority) continue;
    00103
    00104         Driver *newd = d->CreateInstance();
    00105         const char *err = newd->Start(NULL);
    00106         if (err == NULL) {
    00107           DEBUG(driver, 1, "Successfully probed %s driver '%s'", GetDriverTypeName(type), d->name);
    00108           delete *GetActiveDriver(type);
    00109           *GetActiveDriver(type) = newd;
    00110           return newd;
    00111         }
    00112
    00113         DEBUG(driver, 1, "Probing %s driver '%s' failed with error: %s", GetDriverTypeName(type), d->name, err);
    00114         delete newd;
    00115       }
    00116     }
    00117     usererror("Couldn't find any suitable %s driver", GetDriverTypeName(type));
    00118   } else {
    00119     char *parm;
    00120     char buffer[256];
    00121     const char *parms[32];
    00122
    00123     /* Extract the driver name and put parameter list in parm */
    00124     strecpy(buffer, name, lastof(buffer));
    00125     parm = strchr(buffer, ':');
    00126     parms[0] = NULL;
    00127     if (parm != NULL) {
    00128       uint np = 0;
    00129       /* Tokenize the parm. */
    00130       do {
    00131         *parm++ = '\0';
    00132         if (np < lengthof(parms) - 1) parms[np++] = parm;
    00133         while (*parm != '\0' && *parm != ',') parm++;
    00134       } while (*parm == ',');
    00135       parms[np] = NULL;
    00136     }
    00137
    00138     /* Find this driver */
    00139     Drivers::iterator it = GetDrivers().begin();
    00140     for (; it != GetDrivers().end(); ++it) {
    00141       DriverFactoryBase *d = (*it).second;
    00142
    00143       /* Check driver type */
    00144       if (d->type != type) continue;
    00145
    00146       /* Check driver name */
    00147       if (strcasecmp(buffer, d->name) != 0) continue;
    00148
    00149       /* Found our driver, let's try it */
    00150       Driver *newd = d->CreateInstance();
    00151
    00152       const char *err = newd->Start(parms);
    00153       if (err != NULL) {
    00154         delete newd;
    00155         usererror("Unable to load driver '%s'. The error was: %s", d->name, err);
    00156       }
    00157
    00158       DEBUG(driver, 1, "Successfully loaded %s driver '%s'", GetDriverTypeName(type), d->name);
    00159       delete *GetActiveDriver(type);
    00160       *GetActiveDriver(type) = newd;
    00161       return newd;
    00162     }
    00163     usererror("No such %s driver: %s\n", GetDriverTypeName(type), buffer);
    00164   }
    00165 }
    00166
    00174 void DriverFactoryBase::RegisterDriver(const char *name, Driver::Type type, int priority)
    00175 {
    00176   /* Don't register nameless Drivers */
    00177   if (name == NULL) return;
    00178
    00179   this->name = strdup(name);
    00180   this->type = type;
    00181   this->priority = priority;
    00182
    00183   /* Prefix the name with driver type to make it unique */
    00184   char buf[32];
    00185   strecpy(buf, GetDriverTypeName(type), lastof(buf));
    00186   strecpy(buf + 5, name, lastof(buf));
    00187
    00188   const char *longname = strdup(buf);
    00189
    00190   std::pair<Drivers::iterator, bool> P = GetDrivers().insert(Drivers::value_type(longname, this));
    00191   assert(P.second);
    00192 }
    00193
    00200 char *DriverFactoryBase::GetDriversInfo(char *p, const char *last)
    00201 {
    00202   for (Driver::Type type = Driver::DT_BEGIN; type != Driver::DT_END; type++) {
    00203     p += seprintf(p, last, "List of %s drivers:\n", GetDriverTypeName(type));
    00204
    00205     for (int priority = 10; priority >= 0; priority--) {
    00206       Drivers::iterator it = GetDrivers().begin();
    00207       for (; it != GetDrivers().end(); it++) {
    00208         DriverFactoryBase *d = (*it).second;
    00209         if (d->type != type) continue;
    00210         if (d->priority != priority) continue;
    00211         p += seprintf(p, last, "%18s: %s\n", d->name, d->GetDescription());
    00212       }
    00213     }
    00214
    00215     p += seprintf(p, last, "\n");
    00216   }
    00217
    00218   return p;
    00219 }
    00220
    00224 DriverFactoryBase::~DriverFactoryBase()
    00225 {
    00226   if (this->name == NULL) return;
    00227
    00228   /* Prefix the name with driver type to make it unique */
    00229   char buf[32];
    00230   strecpy(buf, GetDriverTypeName(type), lastof(buf));
    00231   strecpy(buf + 5, this->name, lastof(buf));
    00232
    00233   Drivers::iterator it = GetDrivers().find(buf);
    00234   assert(it != GetDrivers().end());
    00235
    00236   const char *longname = (*it).first;
    00237
    00238   GetDrivers().erase(it);
    00239   free(longname);
    00240
    00241   if (GetDrivers().empty()) delete &GetDrivers();
    00242   free(this->name);
    00243 }