00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <iostream>
00012 #include <signal.h>
00013
00014 #include "gamepad/manager.h"
00015 #include "perf/perf.h"
00016 #include "threadsafe/threadsafe.h"
00017
00018
00019
00020
00021 typedef std::map<std::string, smart_ptr<gamepad::Gamepad> > gamepad_map_t;
00022
00023 static bool s_keepLooping = true;
00024
00025
00026
00027
00028
00029
00030
00031
00032 static void
00033 handleSignal
00034 (
00035 IN int sig
00036 )
00037 {
00038 s_keepLooping = false;
00039 }
00040
00041
00042
00043 static smart_ptr<gamepad::Gamepad>
00044 createDefaultGamepad
00045 (
00046 IN gamepad::Manager * mgr,
00047 IN smart_ptr<gamepad::SourceDevice>& device
00048 )
00049 {
00050 perf::Timer timer("createDefaultGamepad");
00051 ASSERT(mgr, "null");
00052 ASSERT(device, "null");
00053
00054 DPRINTF("Looking for a default gamepad mapping for device: '%s'",
00055 device->getPublicName());
00056
00057 VecString mapNames;
00058 gamepad::getRecommendedMappings(mgr, device, mapNames);
00059 DPRINTF(" Found %d recommended mappings", (int) mapNames.size());
00060 if (!mapNames.size()) {
00061 DPRINTF(" Source device not recognized! Skipping...");
00062 return NULL;
00063 }
00064
00065 const char * name = mapNames[0].c_str();
00066 ASSERT(name, "null");
00067 DPRINTF(" Using the first recommended mapping: %s", name);
00068
00069 smart_ptr<gamepad::Map> mapping = mgr->getMapping(name);
00070 if (!mapping) {
00071 DPRINTF(" Mapping not found! Skipping...");
00072 return NULL;
00073 }
00074
00075 DPRINTF(" Found mapping: %s", mapping->getName());
00076
00077
00078 smart_ptr<gamepad::Gamepad> gpad;
00079 gamepad::Manager::eResult result =
00080 mgr->createGamepad(device, mapping, gpad);
00081 if (gamepad::Manager::eResult_Success != result) {
00082 DPRINTF(" Gamepad create attempt failed!");
00083 switch (result) {
00084 case gamepad::Manager::eResult_BadSource:
00085 DPRINTF(" Source device is bad/gone.");
00086 break;
00087 case gamepad::Manager::eResult_BadMap:
00088 DPRINTF(" Mapping is bad");
00089 break;
00090 default:
00091 DPRINTF(" Unknown reason: %d", result);
00092 }
00093 DPRINTF(" Skipping...");
00094 return NULL;
00095 }
00096 ASSERT_THROW(gpad, "failed to create gamepad object");
00097 return gpad;
00098 }
00099
00100
00101
00102 static void
00103 printButtons
00104 (
00105 IN gamepad::buttons_t buttons,
00106 IN const gamepad::Type * type
00107 )
00108 {
00109 ASSERT(type, "null");
00110
00111
00112
00113
00114 char buffer[128];
00115
00116 std::string output;
00117 int nMax = type->getInputCount(gamepad::eInput_Button);
00118 int bitmask = 1;
00119 for (int i = 0; i < nMax; ++i, bitmask *= 2) {
00120 if (buttons & bitmask) {
00121
00122 const char * name =
00123 type->getLogicalName(gamepad::eInput_Button, i);
00124
00125 sprintf(buffer, " %s", name);
00126 output += buffer;
00127 }
00128 }
00129 DPRINTF(" buttons: %s", output.c_str());
00130 }
00131
00132
00133
00134 static void
00135 doTest
00136 (
00137 IN const char * dataDir
00138 )
00139 {
00140 ASSERT(dataDir, "null");
00141
00142
00143 smart_ptr<nstream::Manager> fsMgr =
00144 nstream::getFilesystemManager(dataDir);
00145 ASSERT_THROW(fsMgr,
00146 "Failed to open filesystem manager for data directory: " <<
00147 dataDir);
00148 smart_ptr<nstream::Folder> root = fsMgr->getRoot();
00149 ASSERT(root, "null");
00150 smart_ptr<gamepad::Manager> mgr = gamepad::Manager::create(root);
00151 ASSERT_THROW(mgr, "failed to create gamepad manager?");
00152
00153 int nSDevs = mgr->getSourceDeviceCount();
00154 DPRINTF("Found %d source devices", nSDevs);
00155
00156 mgr->rediscover();
00157 nSDevs = mgr->getSourceDeviceCount();
00158 DPRINTF("Found %d source devices", nSDevs);
00159 ASSERT_THROW(nSDevs > 0, "No source devices!");
00160
00161 int nSDevs2 = mgr->getSourceDeviceCount();
00162 DPRINTF("Found %d source devices (again)", nSDevs2);
00163 ASSERT_THROW(nSDevs == nSDevs2, "found different number of devices?");
00164
00165 smart_ptr<gamepad::SourceDevice> device = mgr->getSourceDevice(0);
00166 ASSERT_THROW(device, "failed to acquire first device");
00167
00168 device = mgr->getSourceDevice(nSDevs - 1);
00169 ASSERT_THROW(device, "failed to acquire last device");
00170
00171 int nTypes = mgr->getTypeCount();
00172 DPRINTF("Found %d types", nTypes);
00173 for (int i = 0; i < nTypes; ++i) {
00174 smart_ptr<gamepad::Type> type = mgr->getType(i);
00175 ASSERT_THROW(type, "failed to acquire type " << i);
00176 }
00177
00178 int nMaps = mgr->getMappingCount();
00179 DPRINTF("Found %d mappings", nMaps);
00180
00181 for (int i = 0; i < nMaps; ++i) {
00182 smart_ptr<gamepad::Map> map = mgr->getMapping(i);
00183 ASSERT_THROW(map, "Failed to acquire mapping " << i);
00184 }
00185
00186
00187
00188
00189
00190
00191 const int desiredHz = 100;
00192 long msSleep = 1000 / desiredHz;
00193 DPRINTF("Want sampling at %d Hz, so polling every %d ms",
00194 desiredHz, (int) msSleep);
00195
00196
00197 const int deviceHz = 2;
00198 const int checkCounter = desiredHz / deviceHz;
00199 DPRINTF("Will look for new source devices every %d iterations",
00200 checkCounter);
00201 int counter = 0;
00202
00203
00204 gamepad_map_t gamepads;
00205 while (s_keepLooping) {
00206 sleepMilliseconds(msSleep);
00207
00208 ++counter;
00209 if (!(counter % checkCounter)) {
00210 mgr->rediscover();
00211 int newCount = mgr->getSourceDeviceCount();
00212 if (newCount != nSDevs) {
00213 DPRINTF("Device count: %d", newCount);
00214 }
00215 nSDevs = newCount;
00216
00217
00218
00219 VecString badIds;
00220 for (int i = 0; i < nSDevs; ++i) {
00221 smart_ptr<gamepad::SourceDevice> device =
00222 mgr->getSourceDevice(i);
00223 ASSERT_THROW(device, "null");
00224 const char * id = device->getUniqueId();
00225
00226
00227 if (gamepad::eDevice_Detached == device->getState()) {
00228 badIds.push_back(id);
00229 continue;
00230 }
00231
00232
00233 if (gamepads.end() != gamepads.find(id)) {
00234 continue;
00235 }
00236
00237
00238
00239 smart_ptr<gamepad::Gamepad> gpad =
00240 createDefaultGamepad(mgr, device);
00241
00242 gamepads[id] = gpad;
00243 }
00244
00245
00246 for (VecString::iterator i = badIds.begin();
00247 i != badIds.end(); ++i) {
00248 gamepad_map_t::iterator bad =
00249 gamepads.find(*i);
00250 ASSERT(gamepads.end() != bad,
00251 "bad device not in gamepad map");
00252 gamepads.erase(bad);
00253 }
00254
00255
00256 }
00257
00258 mgr->update();
00259
00260
00261 for (gamepad_map_t::iterator i = gamepads.begin();
00262 i != gamepads.end(); ++i) {
00263 gamepad::Gamepad * gpad = i->second;
00264 if (!gpad)
00265 continue;
00266
00267 const gamepad::Type * type = gpad->getType();
00268 ASSERT(type, "null type");
00269
00270 gamepad::buttons_t buttons = gpad->getButtons();
00271 if (buttons) {
00272 printButtons(buttons, gpad->getType());
00273 }
00274 }
00275 }
00276 DPRINTF("---- Stopping due to signal ----");
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 int
00288 main
00289 (
00290 IN int argc,
00291 IN const char * argv[]
00292 )
00293 {
00294 int result = 0;
00295
00296 ASSERT(2 == argc, "Usage: gamepad-test-manager <data-directory>");
00297 const char * dataDir = argv[1];
00298 DPRINTF("Using data directory: '%s'", dataDir);
00299
00300 #ifndef WIN32
00301 struct sigaction sigact;
00302 sigact.sa_handler = handleSignal;
00303 sigact.sa_flags = 0;
00304 sigemptyset(&sigact.sa_mask);
00305 sigaction(SIGINT, &sigact, NULL);
00306 sigaction(SIGHUP, &sigact, NULL);
00307 #endif // WIN32
00308
00309 try {
00310 perf::Timer timer("overall timer");
00311
00312 doTest(dataDir);
00313
00314 } catch (std::exception& e) {
00315 DPRINTF("Exception: %s", e.what());
00316 result = 1;
00317 }
00318
00319 perf::dumpTimingSummary(std::cerr);
00320
00321 return result;
00322 }
00323