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 }