00001
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
00071 if (name == NULL) return;
00072
00073 this->name = strdup(name);
00074 this->type = type;
00075 this->priority = priority;
00076
00077
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
00084 std::pair<Drivers::iterator, bool> P =
00085 #endif
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
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
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
00137 strecpy(buffer, name, lastof(buffer));
00138 parm = strchr(buffer, ':');
00139 parms[0] = NULL;
00140 if (parm != NULL) {
00141 uint np = 0;
00142
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
00154 Drivers::iterator it = GetDrivers().begin();
00155 for (; it != GetDrivers().end(); ++it) {
00156 DriverFactoryBase *d = (*it).second;
00157
00158
00159 if (d->type != type) continue;
00160
00161
00162 if (strcasecmp(buffer, d->name) != 0) continue;
00163
00164
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