driver.h

Go to the documentation of this file.
00001 /* $Id: driver.h 11777 2008-01-07 14:23:25Z rubidium $ */
00002 
00005 #ifndef DRIVER_H
00006 #define DRIVER_H
00007 
00008 #include "debug.h"
00009 #include "core/enum_type.hpp"
00010 #include "string_func.h"
00011 #include <string>
00012 #include <map>
00013 
00014 bool GetDriverParamBool(const char * const *parm, const char *name);
00015 int GetDriverParamInt(const char * const *parm, const char *name, int def);
00016 
00017 class Driver {
00018 public:
00019   virtual const char *Start(const char * const *parm) = 0;
00020 
00021   virtual void Stop() = 0;
00022 
00023   virtual ~Driver() { }
00024 
00025   enum Type {
00026     DT_BEGIN = 0,
00027     DT_SOUND = 0,
00028     DT_MUSIC,
00029     DT_VIDEO,
00030     DT_END,
00031   };
00032 };
00033 
00034 DECLARE_POSTFIX_INCREMENT(Driver::Type);
00035 
00036 
00037 class DriverFactoryBase {
00038 private:
00039   Driver::Type type;
00040   char *name;
00041   int priority;
00042   typedef std::map<std::string, DriverFactoryBase *> Drivers;
00043 
00044   static Drivers &GetDrivers()
00045   {
00046     static Drivers &s_drivers = *new Drivers();
00047     return s_drivers;
00048   }
00049 
00050   static Driver **GetActiveDriver(Driver::Type type)
00051   {
00052     static Driver *s_driver[3] = { NULL, NULL, NULL };
00053     return &s_driver[type];
00054   }
00055 
00056   static const char *GetDriverTypeName(Driver::Type type)
00057   {
00058     static const char *driver_type_name[] = { "sound", "music", "video" };
00059     return driver_type_name[type];
00060   }
00061 
00062 protected:
00068   void RegisterDriver(const char *name, Driver::Type type, int priority)
00069   {
00070     /* Don't register nameless Drivers */
00071     if (name == NULL) return;
00072 
00073     this->name = strdup(name);
00074     this->type = type;
00075     this->priority = priority;
00076 
00077     /* Prefix the name with driver type to make it unique */
00078     char buf[32];
00079     strecpy(buf, GetDriverTypeName(type), lastof(buf));
00080     strecpy(buf + 5, name, lastof(buf));
00081 
00082 #if !defined(NDEBUG) || defined(WITH_ASSERT)
00083     /* NDEBUG disables asserts and gives a warning: unused variable 'P' */
00084     std::pair<Drivers::iterator, bool> P =
00085 #endif /* !NDEBUG */
00086     GetDrivers().insert(Drivers::value_type(buf, this));
00087     assert(P.second);
00088   }
00089 
00090 public:
00091   DriverFactoryBase() :
00092     name(NULL)
00093   {}
00094 
00095   virtual ~DriverFactoryBase() { if (this->name != NULL) GetDrivers().erase(this->name); free(this->name); }
00096 
00102   static Driver *SelectDriver(const char *name, Driver::Type type)
00103   {
00104     if (GetDrivers().size() == 0) return NULL;
00105 
00106     if (*name == '\0') {
00107       /* Probe for this driver */
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 *newd = d->CreateInstance();
00118           const char *err = newd->Start(NULL);
00119           if (err == NULL) {
00120             DEBUG(driver, 1, "Successfully probed %s driver '%s'", GetDriverTypeName(type), d->name);
00121             delete *GetActiveDriver(type);
00122             *GetActiveDriver(type) = newd;
00123             return newd;
00124           }
00125 
00126           DEBUG(driver, 1, "Probing %s driver '%s' failed with error: %s", GetDriverTypeName(type), d->name, err);
00127           delete newd;
00128         }
00129       }
00130       error("Couldn't find any suitable %s driver", GetDriverTypeName(type));
00131     } else {
00132       char *parm;
00133       char buffer[256];
00134       const char *parms[32];
00135 
00136       /* Extract the driver name and put parameter list in parm */
00137       strecpy(buffer, name, lastof(buffer));
00138       parm = strchr(buffer, ':');
00139       parms[0] = NULL;
00140       if (parm != NULL) {
00141         uint np = 0;
00142         /* Tokenize the parm. */
00143         do {
00144           *parm++ = '\0';
00145           if (np < lengthof(parms) - 1)
00146             parms[np++] = parm;
00147           while (*parm != '\0' && *parm != ',')
00148             parm++;
00149         } while (*parm == ',');
00150         parms[np] = NULL;
00151       }
00152 
00153       /* Find this driver */
00154       Drivers::iterator it = GetDrivers().begin();
00155       for (; it != GetDrivers().end(); ++it) {
00156         DriverFactoryBase *d = (*it).second;
00157 
00158         /* Check driver type */
00159         if (d->type != type) continue;
00160 
00161         /* Check driver name */
00162         if (strcasecmp(buffer, d->name) != 0) continue;
00163 
00164         /* Found our driver, let's try it */
00165         Driver *newd = d->CreateInstance();
00166 
00167         const char *err = newd->Start(parms);
00168         if (err != NULL) {
00169           delete newd;
00170           error("Unable to load driver '%s'. The error was: %s", d->name, err);
00171         }
00172 
00173         DEBUG(driver, 1, "Successfully loaded %s driver '%s'", GetDriverTypeName(type), d->name);
00174         delete *GetActiveDriver(type);
00175         *GetActiveDriver(type) = newd;
00176         return newd;
00177       }
00178       error("No such %s driver: %s\n", GetDriverTypeName(type), buffer);
00179     }
00180   }
00181 
00185   static char *GetDriversInfo(char *p, const char *last)
00186   {
00187     for (Driver::Type type = Driver::DT_BEGIN; type != Driver::DT_END; type++) {
00188       p += snprintf(p, last - p, "List of %s drivers:\n", GetDriverTypeName(type));
00189 
00190       for (int priority = 10; priority >= 0; priority--) {
00191         Drivers::iterator it = GetDrivers().begin();
00192         for (; it != GetDrivers().end(); it++) {
00193           DriverFactoryBase *d = (*it).second;
00194           if (d->type != type) continue;
00195           if (d->priority != priority) continue;
00196           p += snprintf(p, last - p, "%18s: %s\n", d->name, d->GetDescription());
00197         }
00198       }
00199 
00200       p += snprintf(p, last - p, "\n");
00201     }
00202 
00203     return p;
00204   }
00205 
00209   virtual const char *GetDescription() = 0;
00210 
00214   virtual Driver *CreateInstance() = 0;
00215 };
00216 
00217 #endif /* DRIVER_H */

Generated on Mon Sep 22 20:34:15 2008 for openttd by  doxygen 1.5.6