00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <iostream>
00012 #include <stdio.h>
00013
00014 #include "gamepad-config/gamepad-config.h"
00015 #include "i18n/i18n.h"
00016 #include "perf/perf.h"
00017 #include "threadsafe/threadsafe.h"
00018 #include "threadsafe/threadsafe_multimap.h"
00019
00020
00021
00022 static const char * s_defaultLocale = "en_US.UTF-8";
00023
00024
00025
00026 typedef threadsafe_multimap<std::string, int> string_int_map_t;
00027
00028
00029
00030
00031
00032
00033
00034
00035 static int
00036 selectFromMap
00037 (
00038 IN string_int_map_t& map,
00039 IN const char * title
00040 )
00041 {
00042 ASSERT(title, "null");
00043
00044 int N = map.size();
00045 ASSERT(N > 0, "Empty map?");
00046 fprintf(stdout, "\n%s\n", title);
00047
00048
00049 int ctr = 0;
00050 string_int_map_t::iterator_t i;
00051 map.getIterator(i);
00052 std::string name;
00053 int idx;
00054 while (map.getNextElement(i, name, idx)) {
00055 ++ctr;
00056 fprintf(stdout, " %2d...%s\n", ctr, name.c_str());
00057 }
00058
00059
00060 int iSelected = 1;
00061 if (N > 1) {
00062 iSelected = 0;
00063 while (iSelected < 1 || iSelected > N) {
00064 fprintf(stdout,
00065 "Please enter your selection [1-%d]: ", N);
00066 const int bufsize = 16;
00067 char buffer[bufsize];
00068
00069 fgets(buffer, bufsize, stdin);
00070 iSelected = atoi(buffer);
00071 }
00072 }
00073
00074
00075 map.getIterator(i);
00076 while (iSelected && map.getNextElement(i, name, idx)) {
00077 --iSelected;
00078 }
00079 ASSERT(!iSelected, "map changed size?");
00080 DPRINTF(" Selected option %d --> index %d", iSelected, idx);
00081 return idx;
00082 }
00083
00084
00085
00086 static smart_ptr<gamepad::SourceDevice>
00087 selectDevice
00088 (
00089 IN gamepad::Manager * mgr
00090 )
00091 {
00092 ASSERT(mgr, "null");
00093
00094 string_int_map_t map;
00095
00096 int nDevs = mgr->getSourceDeviceCount();
00097 ASSERT_THROW(nDevs > 0,
00098 "No source devices found! Is everything plugged in?");
00099 for (int i = 0; i < nDevs; ++i) {
00100 smart_ptr<gamepad::SourceDevice> device =
00101 mgr->getSourceDevice(i);
00102 ASSERT_THROW(device, "manager returned null device for index: "
00103 << i);
00104 std::string name = device->getPublicName();
00105
00106
00107
00108 map.insert(name, i);
00109 }
00110 int iSelected = selectFromMap(map, "What is the input source device?");
00111 ASSERT_THROW(iSelected >= 0 && iSelected < nDevs,
00112 "Invalid input device selection: " << iSelected);
00113
00114 smart_ptr<gamepad::SourceDevice> device =
00115 mgr->getSourceDevice(iSelected);
00116 ASSERT_THROW(device, "manager returned null for selected device?");
00117 fprintf(stdout, "Selected input device '%s'\n",
00118 device->getPublicName());
00119
00120 return device;
00121 }
00122
00123
00124
00125 static smart_ptr<gamepad::Type>
00126 selectType
00127 (
00128 IN gamepad::Manager * mgr
00129 )
00130 {
00131 ASSERT(mgr, "null");
00132
00133 string_int_map_t map;
00134 int nTypes = mgr->getTypeCount();
00135 ASSERT_THROW(nTypes > 0, "No valid gamepad types found!");
00136 for (int i = 0; i < nTypes; ++i) {
00137 smart_ptr<gamepad::Type> type = mgr->getType(i);
00138 ASSERT_THROW(type, "manager returned null type for index: "
00139 << i);
00140 const char * name = type->getName();
00141 map.insert(name, i);
00142 }
00143 int iSelected = selectFromMap(map,
00144 "What type of gamepad is being configured?");
00145 ASSERT_THROW(iSelected >= 0 && iSelected < nTypes,
00146 "Invalid gamepad type selection: " << iSelected);
00147 smart_ptr<gamepad::Type> type = mgr->getType(iSelected);
00148 ASSERT_THROW(type, "manager returned null for selected type?");
00149 fprintf(stdout, "Selected gamepad type '%s'\n", type->getName());
00150
00151 return type;
00152 }
00153
00154
00155
00156 static void
00157 displayHints
00158 (
00159 IN i18n::Manager * mgr
00160 )
00161 {
00162 ASSERT(mgr, "null");
00163
00164 const char * friendly = i18n::getString(mgr, "friendlyName");
00165 fprintf(stdout, "\nConfiguring gamepad: %s\n", friendly);
00166
00167 const int bufsize = 16;
00168 char buffer[bufsize];
00169 for (int i = 1; ; ++i) {
00170 snprintf(buffer, bufsize, "hint%d", i);
00171 const char * hint = mgr->getString(buffer);
00172 if (!hint)
00173 break;
00174 fprintf(stdout, " %s\n", hint);
00175 }
00176
00177 fprintf(stdout, "Press Enter when ready: ");
00178 fgets(buffer, bufsize, stdin);
00179 }
00180
00181
00182
00183 static int
00184 atExtreme
00185 (
00186 IN const gamepad::pot_value_t& pv
00187 )
00188 throw()
00189 {
00190 if (!pv.isValid())
00191 return 0;
00192
00193 int range = pv.maxSeen - pv.minSeen;
00194 ASSERT(range > 0, "supposed to be valid!");
00195 int threshold = (int) (0.2 * range) + 1;
00196
00197 int dx = pv.value - pv.minSeen;
00198 if (dx <= threshold) {
00199 return -1;
00200 }
00201 dx = pv.maxSeen - pv.value;
00202 if (dx <= threshold) {
00203 return +1;
00204 }
00205 return 0;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 int
00217 main
00218 (
00219 IN int argc,
00220 IN const char * argv[]
00221 )
00222 {
00223 int retval = 0;
00224 ASSERT(2 == argc, "Usage: configureGamepad <configDataDirectory>");
00225 const char * dataDir = argv[1];
00226 DPRINTF("Using data directory: %s", dataDir);
00227
00228 try {
00229 perf::Timer timer("overall timer");
00230
00231
00232 smart_ptr<nstream::Manager> fsMgr =
00233 nstream::getFilesystemManager(dataDir);
00234 ASSERT_THROW(fsMgr,
00235 "failed to create filesystem stream manager for path: " <<
00236 dataDir);
00237 smart_ptr<nstream::Folder> root = fsMgr->getRoot();
00238 ASSERT(root, "null");
00239
00240
00241 fprintf(stdout, "Initializing gamepad manager...\n");
00242 smart_ptr<gamepad::Manager> mgr =
00243 gamepad::Manager::create(root);
00244 ASSERT_THROW(mgr, "failed to create gamepad manager");
00245 fprintf(stdout, "Discovering devices...\n");
00246 mgr->rediscover();
00247
00248
00249 smart_ptr<gamepad::SourceDevice> device = selectDevice(mgr);
00250 ASSERT_THROW(device, "no gamepad input device selected");
00251
00252
00253 smart_ptr<gamepad::Type> type = selectType(mgr);
00254 ASSERT_THROW(type, "no gamepad type selected");
00255
00256 const char * name = "Test Gamepad Mapping";
00257
00258
00259 const char * locale = i18n::getHostLocale();
00260 smart_ptr<i18n::Manager> configMgr =
00261 gamepad::getConfigLocaleMgr(locale, s_defaultLocale,
00262 root);
00263 ASSERT_THROW(configMgr, "failed to create locale mgr");
00264 DPRINTF("Using strings for locale: '%s'",
00265 configMgr->getLocale());
00266
00267 const char * endCalibrate =
00268 getString(configMgr, "endCalibrate");
00269
00270
00271 smart_ptr<i18n::Manager> gamepadMgr =
00272 gamepad::getTypeLocaleMgr(type, locale, s_defaultLocale,
00273 root);
00274 ASSERT_THROW(gamepadMgr,
00275 "failed to create locale manager for gamepad type");
00276 const char * pressMainButton =
00277 getString(gamepadMgr, "pressMainAction");
00278
00279 displayHints(gamepadMgr);
00280
00281
00282 smart_ptr<gamepad::Configurator> config =
00283 gamepad::Configurator::create(mgr, device, type, name);
00284 ASSERT_THROW(config, "failed to create gamepad configurator");
00285
00286
00287 const int s_hz = 100;
00288 fprintf(stdout, "\nConfiguring gamepad (sampling at %d hz)\n",
00289 s_hz);
00290 ASSERT_THROW(s_hz > 0, "Bad sample rate: " << s_hz);
00291 int msSleep = 1000 / s_hz;
00292 int currStep = -1;
00293 gamepad::config_status_t status;
00294 std::string friendlyInstruction;
00295 int counter = 0;
00296 const int displayFriendly = s_hz / 5;
00297 int waitCount = 0;
00298 const int calibrateCount = 8 * s_hz;
00299 const int endCalibrateCount = 3 * s_hz;
00300 while (true) {
00301 mgr->update();
00302 if (!config->update(status))
00303 break;
00304
00305 sleepMilliseconds(msSleep);
00306
00307 ++counter;
00308 if (counter >= displayFriendly) {
00309 counter = 0;
00310 fprintf(stdout, "%s",
00311 friendlyInstruction.c_str());
00312 if (gamepad::eInstruction_ExternalEvent & status.instruct) {
00313 waitCount -= displayFriendly;
00314 float secRemaining;
00315 if (waitCount >= 0) {
00316 secRemaining = waitCount / (1.0 * s_hz);
00317 } else {
00318 secRemaining = (endCalibrateCount + waitCount) / (1.0 * s_hz);
00319 }
00320 fprintf(stdout,
00321 " %3.1f seconds remaining...",
00322 secRemaining);
00323 if (waitCount < 1) {
00324 friendlyInstruction = endCalibrate;
00325 } if (waitCount < -endCalibrateCount) {
00326 config->calibrationComplete();
00327 }
00328 }
00329 fprintf(stdout, "\n");
00330 }
00331
00332 if (currStep != status.currStep) {
00333
00334
00335
00336
00337 const char * token =
00338 gamepad::getInstructionToken(status.instruct);
00339
00340 const char * friendly =
00341 getString(configMgr, token);
00342
00343
00344
00345 const char * localName =
00346 getString(gamepadMgr, status.logical);
00347
00348
00349
00350 currStep = status.currStep;
00351
00352 friendlyInstruction = "";
00353 if (gamepad::eInstruction_RequestControl & status.instruct) {
00354 friendlyInstruction = localName;
00355 friendlyInstruction += " : ";
00356 }
00357 friendlyInstruction += friendly;
00358 if (gamepad::eInstruction_PressMainAction & status.instruct) {
00359 friendlyInstruction += " ";
00360 friendlyInstruction += pressMainButton;
00361 }
00362 if (gamepad::eInstruction_ExternalEvent & status.instruct) {
00363 waitCount = calibrateCount;
00364 }
00365 }
00366 }
00367
00368 smart_ptr<gamepad::Map> map = config->getMapping();
00369 ASSERT(map, "null");
00370
00371
00372
00373 smart_ptr<gamepad::Gamepad> gamepad;
00374 gamepad::Manager::eResult res =
00375 mgr->createGamepad(device, map, gamepad);
00376 ASSERT_THROW(gamepad::Manager::eResult_Success == res,
00377 "Failed to create gamepad. result: " << res);
00378 ASSERT(gamepad, "null");
00379
00380
00381 const int bufsize = 16;
00382 char buffer[bufsize];
00383 fprintf(stdout, "\nSuccessfully created gamepad mapping!\n");
00384 fprintf(stdout, "Press <Enter> to test mapping with gamepad: ");
00385 fgets(buffer, bufsize, stdin);
00386
00387 while (true) {
00388 sleepMilliseconds(msSleep);
00389
00390 mgr->update();
00391
00392 if (gamepad::eDevice_Detached == gamepad->getState()) {
00393 DPRINTF("Gamepad detached: halting!\n");
00394 break;
00395 }
00396
00397 const gamepad::Type * type = gamepad->getType();
00398 ASSERT(type, "null");
00399
00400 gamepad::buttons_t buttons = gamepad->getButtons();
00401 int mask = 1;
00402 int nButtons = type->getInputCount(gamepad::eInput_Button);
00403 for (int i = 0; i < nButtons; ++i) {
00404 if (mask & buttons) {
00405
00406 const char * logical =
00407 type->getLogicalName(gamepad::eInput_Button, i);
00408 const char * localName =
00409 getString(gamepadMgr, logical);
00410 gamepad::eButton btn = gamepad->getButton(i);
00411 std::string out;
00412 if (gamepad::eButtonDown & btn) {
00413 out += "isDown ";
00414 }
00415 if (gamepad::eButtonWasPushed & btn) {
00416 out += "wasPushed ";
00417 }
00418 if (gamepad::eButtonWasReleased & btn) {
00419 out += "wasReleased ";
00420 }
00421 printf("Button %d = %s = '%s': %s\n",
00422 i, logical, localName, out.c_str());
00423 }
00424 mask *= 2;
00425 }
00426
00427 int nDpads = type->getInputCount(gamepad::eInput_Dpad);
00428 for (int i = 0; i < nDpads; ++i) {
00429 gamepad::eDpad dpad = gamepad->getDpad(i);
00430 if (dpad) {
00431 const char * logical =
00432 type->getLogicalName(gamepad::eInput_Dpad, i);
00433 const char * localName =
00434 getString(gamepadMgr, logical);
00435 std::string out;
00436 if (gamepad::eDpad_Up & dpad) {
00437 out += "up ";
00438 }
00439 if (gamepad::eDpad_Down & dpad) {
00440 out += "down ";
00441 }
00442 if (gamepad::eDpad_Left & dpad) {
00443 out += "left ";
00444 }
00445 if (gamepad::eDpad_Right & dpad) {
00446 out += "right ";
00447 }
00448 printf("dpad %d = %s = '%s': %s\n", i,
00449 logical, localName, out.c_str());
00450 }
00451 }
00452
00453 int nJoys = type->getInputCount(gamepad::eInput_Joystick);
00454 for (int i = 0; i < nJoys; ++i) {
00455 gamepad::joystick_t joy;
00456 gamepad->getJoystick(i, joy);
00457
00458 int x = atExtreme(joy.x);
00459 int y = atExtreme(joy.y);
00460 if (x || y) {
00461 const int bufsize = 256;
00462 char buffer[bufsize];
00463 const char * logical =
00464 type->getLogicalName(gamepad::eInput_Joystick, i);
00465 const char * localName =
00466 getString(gamepadMgr, logical);
00467
00468 std::string out;
00469 if (x) {
00470 snprintf(buffer, bufsize,
00471 "X:%d [%d, %d]", joy.x.value,
00472 joy.x.minSeen, joy.x.maxSeen);
00473 out += buffer;
00474 out += " ";
00475 }
00476 if (y) {
00477 snprintf(buffer, bufsize,
00478 "Y:%d [%d, %d]", joy.y.value,
00479 joy.y.minSeen, joy.y.maxSeen);
00480 out += buffer;
00481 }
00482 printf("joystick %d = %s = '%s': %s\n", i,
00483 logical, localName, out.c_str());
00484
00485 }
00486 }
00487
00488 int nPots = type->getInputCount(gamepad::eInput_Pot);
00489 for (int i = 0; i < nPots; ++i) {
00490 gamepad::pot_value_t pv;
00491 gamepad->getPot(i, pv);
00492
00493 int range = pv.maxSeen - pv.minSeen;
00494 if (range < 0)
00495 continue;
00496 int threshold = (int) (0.1 * range) + 1;
00497 if (pv.value >= threshold) {
00498 const char * logical =
00499 type->getLogicalName(gamepad::eInput_Pot, i);
00500 const char * localName =
00501 getString(gamepadMgr, logical);
00502 printf("pot %d = %s = '%s': %d range=[%d, %d]\n",
00503 i, logical, localName, pv.value,
00504 pv.minSeen, pv.maxSeen);
00505 }
00506 }
00507 }
00508
00509 } catch (std::exception& e) {
00510 DPRINTF("EXCEPTION: %s", e.what());
00511 retval = 1;
00512 }
00513
00514 perf::dumpTimingSummary(std::cerr);
00515 return retval;
00516 }
00517