# driver.cpp

Go to the documentation of this file.

    00001 /* $Id: driver.cpp 26544 2014-04-29 18:41:19Z frosch $ */
    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 char *_ini_videodriver;
    00020 int _num_resolutions;
    00021 Dimension _resolutions[32];
    00022 Dimension _cur_resolution;
    00023 bool _rightclick_emulate;
    00024
    00025 char *_ini_sounddriver;
    00026
    00027 char *_ini_musicdriver;
    00028
    00029 char *_ini_blitter;
    00030 bool _blitter_autodetected;
    00031
    00038 const char *GetDriverParam(const char * const *parm, const char *name)
    00039 {
    00040   size_t len;
    00041
    00042   if (parm == NULL) return NULL;
    00043
    00044   len = strlen(name);
    00045   for (; *parm != NULL; parm++) {
    00046     const char *p = *parm;
    00047
    00048     if (strncmp(p, name, len) == 0) {
    00049       if (p[len] == '=')  return p + len + 1;
    00050       if (p[len] == '\0') return p + len;
    00051     }
    00052   }
    00053   return NULL;
    00054 }
    00055
    00062 bool GetDriverParamBool(const char * const *parm, const char *name)
    00063 {
    00064   return GetDriverParam(parm, name) != NULL;
    00065 }
    00066
    00074 int GetDriverParamInt(const char * const *parm, const char *name, int def)
    00075 {
    00076   const char *p = GetDriverParam(parm, name);
    00077   return p != NULL ? atoi(p) : def;
    00078 }
    00079
    00086 void DriverFactoryBase::SelectDriver(const char *name, Driver::Type type)
    00087 {
    00088   if (!DriverFactoryBase::SelectDriverImpl(name, type)) {
    00089     StrEmpty(name) ?
    00090       usererror("Failed to autoprobe %s driver", GetDriverTypeName(type)) :
    00091       usererror("Failed to select requested %s driver '%s'", GetDriverTypeName(type), name);
    00092   }
    00093 }
    00094
    00102 bool DriverFactoryBase::SelectDriverImpl(const char *name, Driver::Type type)
    00103 {
    00104   if (GetDrivers().size() == 0) return false;
    00105
    00106   if (StrEmpty(name)) {
    00107     /* Probe for this driver, but do not fall back to dedicated/null! */
    00108     for (int priority = 10; priority > 0; priority--) {
    00109       Drivers::iterator it = GetDrivers().begin();
    00110       for (; it != GetDrivers().end(); ++it) {
    00111         DriverFactoryBase *d = (*it).second;
    00112
    00113         /* Check driver type */
    00114         if (d->type != type) continue;
    00115         if (d->priority != priority) continue;
    00116
    00117         Driver *oldd = *GetActiveDriver(type);
    00118         Driver *newd = d->CreateInstance();
    00119         *GetActiveDriver(type) = newd;
    00120
    00121         const char *err = newd->Start(NULL);
    00122         if (err == NULL) {
    00123           DEBUG(driver, 1, "Successfully probed %s driver '%s'", GetDriverTypeName(type), d->name);
    00124           delete oldd;
    00125           return true;
    00126         }
    00127
    00128         *GetActiveDriver(type) = oldd;
    00129         DEBUG(driver, 1, "Probing %s driver '%s' failed with error: %s", GetDriverTypeName(type), d->name, err);
    00130         delete newd;
    00131       }
    00132     }
    00133     usererror("Couldn't find any suitable %s driver", GetDriverTypeName(type));
    00134   } else {
    00135     char *parm;
    00136     char buffer[256];
    00137     const char *parms[32];
    00138
    00139     /* Extract the driver name and put parameter list in parm */
    00140     strecpy(buffer, name, lastof(buffer));
    00141     parm = strchr(buffer, ':');
    00142     parms[0] = NULL;
    00143     if (parm != NULL) {
    00144       uint np = 0;
    00145       /* Tokenize the parm. */
    00146       do {
    00147         *parm++ = '\0';
    00148         if (np < lengthof(parms) - 1) parms[np++] = parm;
    00149         while (*parm != '\0' && *parm != ',') parm++;
    00150       } while (*parm == ',');
    00151       parms[np] = NULL;
    00152     }
    00153
    00154     /* Find this driver */
    00155     Drivers::iterator it = GetDrivers().begin();
    00156     for (; it != GetDrivers().end(); ++it) {
    00157       DriverFactoryBase *d = (*it).second;
    00158
    00159       /* Check driver type */
    00160       if (d->type != type) continue;
    00161
    00162       /* Check driver name */
    00163       if (strcasecmp(buffer, d->name) != 0) continue;
    00164
    00165       /* Found our driver, let's try it */
    00166       Driver *newd = d->CreateInstance();
    00167
    00168       const char *err = newd->Start(parms);
    00169       if (err != NULL) {
    00170         delete newd;
    00171         usererror("Unable to load driver '%s'. The error was: %s", d->name, err);
    00172       }
    00173
    00174       DEBUG(driver, 1, "Successfully loaded %s driver '%s'", GetDriverTypeName(type), d->name);
    00175       delete *GetActiveDriver(type);
    00176       *GetActiveDriver(type) = newd;
    00177       return true;
    00178     }
    00179     usererror("No such %s driver: %s\n", GetDriverTypeName(type), buffer);
    00180   }
    00181 }
    00182
    00189 char *DriverFactoryBase::GetDriversInfo(char *p, const char *last)
    00190 {
    00191   for (Driver::Type type = Driver::DT_BEGIN; type != Driver::DT_END; type++) {
    00192     p += seprintf(p, last, "List of %s drivers:\n", GetDriverTypeName(type));
    00193
    00194     for (int priority = 10; priority >= 0; priority--) {
    00195       Drivers::iterator it = GetDrivers().begin();
    00196       for (; it != GetDrivers().end(); it++) {
    00197         DriverFactoryBase *d = (*it).second;
    00198         if (d->type != type) continue;
    00199         if (d->priority != priority) continue;
    00200         p += seprintf(p, last, "%18s: %s\n", d->name, d->GetDescription());
    00201       }
    00202     }
    00203
    00204     p += seprintf(p, last, "\n");
    00205   }
    00206
    00207   return p;
    00208 }
    00209
    00217 DriverFactoryBase::DriverFactoryBase(Driver::Type type, int priority, const char *name, const char *description) :
    00218   type(type), priority(priority), name(name), description(description)
    00219 {
    00220   /* Prefix the name with driver type to make it unique */
    00221   char buf[32];
    00222   strecpy(buf, GetDriverTypeName(type), lastof(buf));
    00223   strecpy(buf + 5, name, lastof(buf));
    00224
    00225   const char *longname = strdup(buf);
    00226
    00227   std::pair<Drivers::iterator, bool> P = GetDrivers().insert(Drivers::value_type(longname, this));
    00228   assert(P.second);
    00229 }
    00230
    00234 DriverFactoryBase::~DriverFactoryBase()
    00235 {
    00236   /* Prefix the name with driver type to make it unique */
    00237   char buf[32];
    00238   strecpy(buf, GetDriverTypeName(type), lastof(buf));
    00239   strecpy(buf + 5, this->name, lastof(buf));
    00240
    00241   Drivers::iterator it = GetDrivers().find(buf);
    00242   assert(it != GetDrivers().end());
    00243
    00244   const char *longname = (*it).first;
    00245
    00246   GetDrivers().erase(it);
    00247   free(longname);
    00248
    00249   if (GetDrivers().empty()) delete &GetDrivers();
    00250 }