void GfDrivers::reload() { // Clear all. clear(); // (Re)Load robot modules from the "drivers" installed folder. std::string strDriversDirName(GfLibDir()); strDriversDirName += "drivers"; tModList* lstDriverModules = 0; const int nDriverModules = GfModInfoDir(CAR_IDENT, strDriversDirName.c_str(), 1, &lstDriverModules); if (nDriverModules <= 0 || !lstDriverModules) { GfLogFatal("Could not load any driver module from %s", strDriversDirName.c_str()); return; } // For each module found, load drivers information. tModList *pCurModule = lstDriverModules; do { pCurModule = pCurModule->next; // Determine the module name. std::string strModName(pCurModule->sopath); strModName.erase(strlen(pCurModule->sopath) - strlen(DLLEXT) - 1); // Truncate file ext. const size_t nLastSlashInd = strModName.rfind('/'); if (nLastSlashInd != std::string::npos) strModName = strModName.substr(nLastSlashInd+1); // Remove heading folder path. // Load the module XML descriptor file (try user settings first, and then installed one) std::ostringstream ossRobotFileName; ossRobotFileName << GfLocalDir() << "drivers/" << strModName << '/' << strModName << PARAMEXT; void *hparmRobot = GfParmReadFile(ossRobotFileName.str().c_str(), GFPARM_RMODE_STD | GFPARM_RMODE_REREAD); if (!hparmRobot) { ossRobotFileName.str(""); ossRobotFileName << "drivers/" << strModName << '/' << strModName << PARAMEXT; hparmRobot = GfParmReadFile(ossRobotFileName.str().c_str(), GFPARM_RMODE_STD | GFPARM_RMODE_REREAD); } if (!hparmRobot) { // Do not waste log with drivers that do not exists or do not have to exist! if (strncmp("dandroid",strModName.c_str(),8) == 0) continue; else if (strncmp("usr",strModName.c_str(),3) == 0) continue; else if (strncmp("replay",strModName.c_str(),6) == 0) continue; GfLogError("No usable '%s' driver (%s.xml not found or not readable)\n", strModName.c_str(), strModName.c_str()); continue; } // For each driver (= interface) "in" the module for (int nItfInd = 0; nItfInd < pCurModule->modInfoSize; nItfInd++) { // Ignore undefined drivers or showing an empty name if (!pCurModule->modInfo[nItfInd].name || pCurModule->modInfo[nItfInd].name[0] == '\0') { GfLogInfo("Ignoring '%s' driver #%d (not defined or empty name)\n", strModName.c_str(), nItfInd); continue; } // Create the driver and load info from the XML file. GfDriver* pDriver = new GfDriver(strModName, pCurModule->modInfo[nItfInd].index, pCurModule->modInfo[nItfInd].name, hparmRobot); // For human drivers, if the car was not found, select the 1st possible one. if (!pDriver->getCar() && pDriver->isHuman()) { GfCar* pSubstCar = GfCars::self()->getCarsInCategory()[0]; // Should never fail. if (pSubstCar) { std::ostringstream ossDrvSecPath; ossDrvSecPath << ROB_SECT_ROBOTS << '/' << ROB_LIST_INDEX << '/' << pCurModule->modInfo[nItfInd].index; const char* pszCarId = GfParmGetStr(hparmRobot, ossDrvSecPath.str().c_str(), ROB_ATTR_CAR, ""); GfLogWarning("Changing '%s' driver '%s' (#%d) 's car to %s (default one '%s' not available)\n", strModName.c_str(), pCurModule->modInfo[nItfInd].name, pCurModule->modInfo[nItfInd].index, pSubstCar->getId().c_str(), pszCarId); pDriver->setCar(pSubstCar); } } // Keep the driver only if he drives an existing car. if (pDriver->getCar()) { // Update the GfDrivers singleton. _pPrivate->vecDrivers.push_back(pDriver); const std::pair<std::string, int> driverKey(pDriver->getModuleName(), pDriver->getInterfaceIndex()); _pPrivate->mapDriversByKey[driverKey] = pDriver; if (std::find(_pPrivate->vecTypes.begin(), _pPrivate->vecTypes.end(), pDriver->getType()) == _pPrivate->vecTypes.end()) _pPrivate->vecTypes.push_back(pDriver->getType()); if (std::find(_pPrivate->vecCarCategoryIds.begin(), _pPrivate->vecCarCategoryIds.end(), pDriver->getCar()->getCategoryId()) == _pPrivate->vecCarCategoryIds.end()) _pPrivate->vecCarCategoryIds.push_back(pDriver->getCar()->getCategoryId()); } else { delete pDriver; std::ostringstream ossDrvSecPath; ossDrvSecPath << ROB_SECT_ROBOTS << '/' << ROB_LIST_INDEX << '/' << pCurModule->modInfo[nItfInd].index; const char* pszCarId = GfParmGetStr(hparmRobot, ossDrvSecPath.str().c_str(), ROB_ATTR_CAR, ""); GfLogInfo("Ignoring '%s' driver '%s' (#%d) (not defined or default car '%s' not available)\n", strModName.c_str(), pCurModule->modInfo[nItfInd].name, pCurModule->modInfo[nItfInd].index, pszCarId); } } // Close driver module descriptor file if open GfParmReleaseHandle(hparmRobot); } while (pCurModule != lstDriverModules); // Free the module list. GfModFreeInfoList(&lstDriverModules); // Sort the car category ids and driver types vectors. std::sort(_pPrivate->vecCarCategoryIds.begin(), _pPrivate->vecCarCategoryIds.end()); std::sort(_pPrivate->vecTypes.begin(), _pPrivate->vecTypes.end()); // Trace what we got. print(); }
/** Interactive Drivers list selection @param vs Pointer on tRmDrvSelect structure (cast to void) @warning The race manager params are modified but not saved. */ void RmDriversSelect(void *vs) { tModList *list; tModList *curmod; char dname[256]; char *sp; char *cardllname; int i, index; tDrvElt *curDrv; int nCars, robotIdx; void *robhdle; struct stat st; char *carName; void *carhdle; int human; #define B_BASE 380 #define B_HT 30 ds = (tRmDrvSelect*)vs; GF_TAILQ_INIT(&DrvList); scrHandle = GfuiScreenCreateEx((float*)NULL, NULL, rmdsActivate, NULL, (tfuiCallback)NULL, 1); GfuiScreenAddBgImg(scrHandle, "data/img/splash-qrdrv.png"); GfuiTitleCreate(scrHandle, "Select Drivers", sizeof("Select Drivers")); GfuiLabelCreate(scrHandle, "Selected", GFUI_FONT_LARGE, 120, 400, GFUI_ALIGN_HC_VB, 0); GfuiLabelCreate(scrHandle, "Not Selected", GFUI_FONT_LARGE, 496, 400, GFUI_ALIGN_HC_VB, 0); selectedScrollList = GfuiScrollListCreate(scrHandle, GFUI_FONT_MEDIUM_C, 20, 80, GFUI_ALIGN_HL_VB, 200, 310, GFUI_SB_RIGHT, NULL, rmdsClickOnDriver); unselectedScrollList = GfuiScrollListCreate(scrHandle, GFUI_FONT_MEDIUM_C, 396, 80, GFUI_ALIGN_HL_VB, 200, 310, GFUI_SB_RIGHT, NULL, rmdsClickOnDriver); GfuiButtonCreate(scrHandle, "Accept", GFUI_FONT_LARGE, 210, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, NULL, rmdsSelect, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiButtonCreate(scrHandle, "Cancel", GFUI_FONT_LARGE, 430, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, ds->prevScreen, rmdsDeactivate, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiButtonCreate(scrHandle, "Move Up", GFUI_FONT_MEDIUM, 320, B_BASE, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, (void*)-1, rmMove, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiButtonCreate(scrHandle, "Move Down", GFUI_FONT_MEDIUM, 320, B_BASE - B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, (void*)1, rmMove, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiButtonCreate(scrHandle, "(De)Select", GFUI_FONT_MEDIUM, 320, B_BASE - 2 * B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, (void*)0, rmSelectDeselect, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiButtonCreate(scrHandle, "Set Focus", GFUI_FONT_MEDIUM, 320, B_BASE - 3 * B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, NULL, rmdsSetFocus, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); list = (tModList *)NULL; sprintf(buf, "%sdrivers", GetLibDir ()); GfModInfoDir(CAR_IDENT, buf, 1, &list); curmod = list; if (curmod != NULL) { do { curmod = curmod->next; for (i = 0; i < MAX_MOD_ITF; i++) { if (curmod->modInfo[i].name) { sp = strrchr(curmod->sopath, '/'); if (sp == NULL) { sp = curmod->sopath; } else { sp++; } strcpy(dname, sp); dname[strlen(dname) - strlen(DLLEXT) - 1] = 0; /* cut .so or .dll */ sprintf(buf, "%sdrivers/%s/%s.xml", GetLocalDir(), dname, dname); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); if (!robhdle) { sprintf(buf, "drivers/%s/%s.xml", dname, dname); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); } sprintf(path, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, curmod->modInfo[i].index); carName = GfParmGetStr(robhdle, path, ROB_ATTR_CAR, ""); if (strcmp(GfParmGetStr(robhdle, path, ROB_ATTR_TYPE, ROB_VAL_ROBOT), ROB_VAL_ROBOT)) { human = 1; } else { human = 0; } sprintf(path, "cars/%s/%s.xml", carName, carName); if (!stat(path, &st)) { carhdle = GfParmReadFile(path, GFPARM_RMODE_STD); if (carhdle) { curDrv = (tDrvElt*)calloc(1, sizeof(tDrvElt)); curDrv->index = curmod->modInfo[i].index; curDrv->dname = strdup(dname); curDrv->name = strdup(curmod->modInfo[i].name); curDrv->car = carhdle; if (human) { curDrv->human = 1; GF_TAILQ_INSERT_HEAD(&DrvList, curDrv, link); } else { curDrv->human = 0; GF_TAILQ_INSERT_TAIL(&DrvList, curDrv, link); } } else { GfOut("Driver %s not selected because car %s is not readable\n", curmod->modInfo[i].name, carName); } } else { GfOut("Driver %s not selected because car %s is not present\n", curmod->modInfo[i].name, carName); } GfParmReleaseHandle(robhdle); } } } while (curmod != list); } nbSelectedDrivers = 0; nbMaxSelectedDrivers = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_MAXNUM, NULL, 0); nCars = GfParmGetEltNb(ds->param, RM_SECT_DRIVERS); index = 1; for (i = 1; i < nCars+1; i++) { sprintf(dname, "%s/%d", RM_SECT_DRIVERS, i); cardllname = GfParmGetStr(ds->param, dname, RM_ATTR_MODULE, ""); robotIdx = (int)GfParmGetNum(ds->param, dname, RM_ATTR_IDX, (char*)NULL, 0); curDrv = GF_TAILQ_FIRST(&DrvList); if (curDrv != NULL) { do { if ((curDrv->index == robotIdx) && (strcmp(curDrv->dname, cardllname) == 0)) { if (nbSelectedDrivers < nbMaxSelectedDrivers) { GfuiScrollListInsertElement(scrHandle, selectedScrollList, curDrv->name, index, (void*)curDrv); curDrv->sel = index++; nbSelectedDrivers++; } break; } } while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL); } } curDrv = GF_TAILQ_FIRST(&DrvList); if (curDrv != NULL) { do { if (curDrv->sel == 0) { GfuiScrollListInsertElement(scrHandle, unselectedScrollList, curDrv->name, 1000, (void*)curDrv); } } while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL); } GfuiLabelCreate(scrHandle, "Focused:", GFUI_FONT_MEDIUM, 320, B_BASE - 5 * B_HT, GFUI_ALIGN_HC_VB, 0); cardllname = GfParmGetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, ""); robotIdx = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0); curDrv = GF_TAILQ_FIRST(&DrvList); if (curDrv != NULL) { do { if ((curDrv->index == robotIdx) && (strcmp(curDrv->dname, cardllname) == 0)) { break; } } while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL); } if (curDrv == NULL) { curDrv = GF_TAILQ_FIRST(&DrvList); } if (curDrv == NULL) { FocDrvLabelId = GfuiLabelCreate(scrHandle, "", GFUI_FONT_MEDIUM_C, 320, B_BASE - 5 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256); } else { FocDrvLabelId = GfuiLabelCreate(scrHandle, curDrv->name, GFUI_FONT_MEDIUM_C, 320, B_BASE - 5 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256); } /* Picked Driver Info */ GfuiLabelCreate(scrHandle, "Driver:", GFUI_FONT_MEDIUM, 320, B_BASE - 7 * B_HT, GFUI_ALIGN_HC_VB, 0); PickDrvNameLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C, 320, B_BASE - 7 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256); GfuiLabelCreate(scrHandle, "Car:", GFUI_FONT_MEDIUM, 320, B_BASE - 8 * B_HT, GFUI_ALIGN_HC_VB, 0); PickDrvCarLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C, 320, B_BASE - 8 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256); GfuiLabelCreate(scrHandle, "Category:", GFUI_FONT_MEDIUM, 320, B_BASE - 9 * B_HT, GFUI_ALIGN_HC_VB, 0); PickDrvCategoryLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C, 320, B_BASE - 9 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256); GfuiMenuDefaultKeysAdd(scrHandle); rmdsAddKeys(); GfuiScreenActivate(scrHandle); }