src/driver.h
branchnoai
changeset 9869 6404afe43575
parent 9723 eee46cb39750
child 10455 22c441f5adf9
equal deleted inserted replaced
9868:3998f2e73dda 9869:6404afe43575
    58 		static const char *driver_type_name[] = { "sound", "music", "video" };
    58 		static const char *driver_type_name[] = { "sound", "music", "video" };
    59 		return driver_type_name[type];
    59 		return driver_type_name[type];
    60 	}
    60 	}
    61 
    61 
    62 protected:
    62 protected:
    63 	/**
    63 	void RegisterDriver(const char *name, Driver::Type type, int priority);
    64 	 * Register a driver internally, based on its name.
       
    65 	 * @param name the name of the driver.
       
    66 	 * @note an assert() will be trigger if 2 driver with the same name try to register.
       
    67 	 */
       
    68 	void RegisterDriver(const char *name, Driver::Type type, int priority)
       
    69 	{
       
    70 		/* Don't register nameless Drivers */
       
    71 		if (name == NULL) return;
       
    72 
       
    73 		this->name = strdup(name);
       
    74 		this->type = type;
       
    75 		this->priority = priority;
       
    76 
       
    77 		/* Prefix the name with driver type to make it unique */
       
    78 		char buf[32];
       
    79 		strecpy(buf, GetDriverTypeName(type), lastof(buf));
       
    80 		strecpy(buf + 5, name, lastof(buf));
       
    81 
       
    82 #if !defined(NDEBUG) || defined(WITH_ASSERT)
       
    83 		/* NDEBUG disables asserts and gives a warning: unused variable 'P' */
       
    84 		std::pair<Drivers::iterator, bool> P =
       
    85 #endif /* !NDEBUG */
       
    86 		GetDrivers().insert(Drivers::value_type(buf, this));
       
    87 		assert(P.second);
       
    88 	}
       
    89 
    64 
    90 public:
    65 public:
    91 	DriverFactoryBase() :
    66 	DriverFactoryBase() :
    92 		name(NULL)
    67 		name(NULL)
    93 	{}
    68 	{}
    94 
    69 
    95 	virtual ~DriverFactoryBase() { if (this->name != NULL) GetDrivers().erase(this->name); free(this->name); }
    70 	virtual ~DriverFactoryBase() { if (this->name != NULL) GetDrivers().erase(this->name); free(this->name); }
    96 
    71 
    97 	/**
    72 	static const Driver *SelectDriver(const char *name, Driver::Type type);
    98 	 * Find the requested driver and return its class.
    73 	static char *GetDriversInfo(char *p, const char *last);
    99 	 * @param name the driver to select.
       
   100 	 * @post Sets the driver so GetCurrentDriver() returns it too.
       
   101 	 */
       
   102 	static Driver *SelectDriver(const char *name, Driver::Type type)
       
   103 	{
       
   104 		if (GetDrivers().size() == 0) return NULL;
       
   105 
       
   106 		if (*name == '\0') {
       
   107 			/* Probe for this driver */
       
   108 			for (int priority = 10; priority >= 0; priority--) {
       
   109 				Drivers::iterator it = GetDrivers().begin();
       
   110 				for (; it != GetDrivers().end(); ++it) {
       
   111 					DriverFactoryBase *d = (*it).second;
       
   112 
       
   113 					/* Check driver type */
       
   114 					if (d->type != type) continue;
       
   115 					if (d->priority != priority) continue;
       
   116 
       
   117 					Driver *newd = d->CreateInstance();
       
   118 					const char *err = newd->Start(NULL);
       
   119 					if (err == NULL) {
       
   120 						DEBUG(driver, 1, "Successfully probed %s driver '%s'", GetDriverTypeName(type), d->name);
       
   121 						delete *GetActiveDriver(type);
       
   122 						*GetActiveDriver(type) = newd;
       
   123 						return newd;
       
   124 					}
       
   125 
       
   126 					DEBUG(driver, 1, "Probing %s driver '%s' failed with error: %s", GetDriverTypeName(type), d->name, err);
       
   127 					delete newd;
       
   128 				}
       
   129 			}
       
   130 			error("Couldn't find any suitable %s driver", GetDriverTypeName(type));
       
   131 		} else {
       
   132 			char *parm;
       
   133 			char buffer[256];
       
   134 			const char *parms[32];
       
   135 
       
   136 			/* Extract the driver name and put parameter list in parm */
       
   137 			strecpy(buffer, name, lastof(buffer));
       
   138 			parm = strchr(buffer, ':');
       
   139 			parms[0] = NULL;
       
   140 			if (parm != NULL) {
       
   141 				uint np = 0;
       
   142 				/* Tokenize the parm. */
       
   143 				do {
       
   144 					*parm++ = '\0';
       
   145 					if (np < lengthof(parms) - 1)
       
   146 						parms[np++] = parm;
       
   147 					while (*parm != '\0' && *parm != ',')
       
   148 						parm++;
       
   149 				} while (*parm == ',');
       
   150 				parms[np] = NULL;
       
   151 			}
       
   152 
       
   153 			/* Find this driver */
       
   154 			Drivers::iterator it = GetDrivers().begin();
       
   155 			for (; it != GetDrivers().end(); ++it) {
       
   156 				DriverFactoryBase *d = (*it).second;
       
   157 
       
   158 				/* Check driver type */
       
   159 				if (d->type != type) continue;
       
   160 
       
   161 				/* Check driver name */
       
   162 				if (strcasecmp(buffer, d->name) != 0) continue;
       
   163 
       
   164 				/* Found our driver, let's try it */
       
   165 				Driver *newd = d->CreateInstance();
       
   166 
       
   167 				const char *err = newd->Start(parms);
       
   168 				if (err != NULL) {
       
   169 					delete newd;
       
   170 					error("Unable to load driver '%s'. The error was: %s", d->name, err);
       
   171 				}
       
   172 
       
   173 				DEBUG(driver, 1, "Successfully loaded %s driver '%s'", GetDriverTypeName(type), d->name);
       
   174 				delete *GetActiveDriver(type);
       
   175 				*GetActiveDriver(type) = newd;
       
   176 				return newd;
       
   177 			}
       
   178 			error("No such %s driver: %s\n", GetDriverTypeName(type), buffer);
       
   179 		}
       
   180 	}
       
   181 
       
   182 	/**
       
   183 	 * Build a human readable list of available drivers, grouped by type.
       
   184 	 */
       
   185 	static char *GetDriversInfo(char *p, const char *last)
       
   186 	{
       
   187 		for (Driver::Type type = Driver::DT_BEGIN; type != Driver::DT_END; type++) {
       
   188 			p += snprintf(p, last - p, "List of %s drivers:\n", GetDriverTypeName(type));
       
   189 
       
   190 			for (int priority = 10; priority >= 0; priority--) {
       
   191 				Drivers::iterator it = GetDrivers().begin();
       
   192 				for (; it != GetDrivers().end(); it++) {
       
   193 					DriverFactoryBase *d = (*it).second;
       
   194 					if (d->type != type) continue;
       
   195 					if (d->priority != priority) continue;
       
   196 					p += snprintf(p, last - p, "%18s: %s\n", d->name, d->GetDescription());
       
   197 				}
       
   198 			}
       
   199 
       
   200 			p += snprintf(p, last - p, "\n");
       
   201 		}
       
   202 
       
   203 		return p;
       
   204 	}
       
   205 
    74 
   206 	/**
    75 	/**
   207 	 * Get a nice description of the driver-class.
    76 	 * Get a nice description of the driver-class.
   208 	 */
    77 	 */
   209 	virtual const char *GetDescription() = 0;
    78 	virtual const char *GetDescription() = 0;