00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "manager.h"
00036
00037 #ifdef WIN32
00038
00039 #include "direct-input/direct-input.h"
00040 #else // WIN32
00041
00042 #include "linux-joystick/linux-joystick.h"
00043 #endif // WIN32
00044
00045 #include "datahash/datahash_text.h"
00046 #include "perf/perf.h"
00047 #include "resources/resources-internal.h"
00048 #include "util/file.h"
00049
00050
00051 namespace gamepad {
00052
00053
00054 Gamepad::~Gamepad(void) throw() { }
00055 Manager::~Manager(void) throw() { }
00056
00057
00058
00059 static const float s_buttonRatio = 0.2;
00060
00061 static const float s_4potRatio = 0.08;
00062
00063
00064 static const char * s_gamepadExtension = "gamepad";
00065 static const char * s_mappingExtension = "map";
00066
00067
00068
00069
00070
00071
00072
00073
00074 static smart_ptr<Map>
00075 readMapFromString
00076 (
00077 IN const char * val
00078 )
00079 {
00080 ASSERT(val, "null");
00081
00082 smart_ptr<Datahash> hash = readHashFromString(val);
00083 ASSERT(hash, "null");
00084
00085 smart_ptr<Map> map = readMap(hash);
00086 ASSERT(map, "null");
00087
00088 return map;
00089 }
00090
00091
00092
00093 static int
00094 getDpadFromPot
00095 (
00096 IN SourceDevice * device,
00097 IN int idx
00098 )
00099 {
00100 ASSERT(device, "null");
00101 ASSERT(idx >= 0, "Bad pot index: %d", idx);
00102
00103 const pot_value_t& pv = device->getPotValue(idx);
00104
00105 int iThreshold = s_buttonRatio * (pv.maxSeen - pv.minSeen);
00106 if ((pv.value - pv.minSeen) <= iThreshold)
00107 return -1;
00108 if ((pv.maxSeen - pv.value) <= iThreshold)
00109 return +1;
00110 return 0;
00111 }
00112
00113
00114
00115 static bool
00116 potMoved
00117 (
00118 IN SourceDevice * device,
00119 IN int idx
00120 )
00121 {
00122 ASSERT(device, "null");
00123 ASSERT(idx >= 0, "bad index: %d", idx);
00124
00125 const pot_value_t& pv = device->getPotValue(idx);
00126
00127 int iThreshold = s_4potRatio * (pv.maxSeen - pv.minSeen);
00128 if ((pv.value - pv.minSeen) >= iThreshold)
00129 return true;
00130 return false;
00131 }
00132
00133
00134
00135 static nstream::eIterationFlag
00136 loadFilesCallback
00137 (
00138 IN nstream::Entry * entry,
00139 IN void * context
00140 )
00141 {
00142 ASSERT(entry, "null");
00143 Manager * mgr = (Manager *) context;
00144 ASSERT(mgr, "null context");
00145
00146
00147 nstream::File * file = dynamic_cast<nstream::File *>(entry);
00148 if (!file)
00149 return nstream::eIterate_Continue;
00150
00151
00152 const char * filename = file->getName();
00153 const char * ext = GetExtension(filename);
00154
00155 if (!strcmp(s_gamepadExtension, ext)) {
00156
00157
00158 smart_ptr<nstream::Stream> stream = file->openStream();
00159 ASSERT(stream, "null");
00160 if (stream->good()) {
00161 smart_ptr<Type> type = readType(stream);
00162 ASSERT(type, "null");
00163
00164 mgr->addType(type);
00165 } else {
00166 DPRINTF("File is bad: '%s'", filename);
00167 }
00168 } else if (!strcmp(s_mappingExtension, ext)) {
00169
00170
00171 smart_ptr<nstream::Stream> stream = file->openStream();
00172 ASSERT(stream, "null");
00173 std::istream& in = stream->getStream();
00174 if (in.good()) {
00175 smart_ptr<Datahash> hash =
00176 readHashFromStream("map", in);
00177 ASSERT(hash, "null");
00178 smart_ptr<Map> map = readMap(hash);
00179 ASSERT(map, "null");
00180
00181 mgr->addMapping(map);
00182 } else {
00183 DPRINTF("File is bad: '%s'", filename);
00184 }
00185 }
00186
00187
00188 return nstream::eIterate_Continue;
00189 }
00190
00191
00192
00193 static bool
00194 sourceAndMapInUse
00195 (
00196 IN Manager * mgr,
00197 IN const char * deviceId,
00198 IN const char * mappingId
00199 )
00200 {
00201 ASSERT(mgr, "null");
00202 ASSERT(deviceId, "null");
00203 ASSERT(mappingId, "null");
00204
00205
00206 int nGamepads = mgr->getGamepadCount();
00207 for (int i = 0; i < nGamepads; ++i) {
00208 smart_ptr<Gamepad> gp = mgr->getGamepad(i);
00209 if (!gp) {
00210 DPRINTF("Gamepad %d has disappeared", i);
00211 continue;
00212 }
00213
00214 if (!strcmp(deviceId, gp->getSourceDeviceId()) &&
00215 !strcmp(mappingId, gp->getMappingId())) {
00216
00217 return true;
00218 }
00219 }
00220
00221
00222 return false;
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 class GPad : public Gamepad {
00234 public:
00235
00236 ~GPad(void) throw() { }
00237
00238
00239 void initialize(IN Type * type,
00240 IN smart_ptr<SourceDevice>& device,
00241 IN smart_ptr<Map>& mapping);
00242
00243
00244 Type * getType(void) const throw();
00245 const char * getId(void) throw();
00246 const char * getSourceDeviceId(void) throw();
00247 const char * getMappingId(void) throw();
00248 eDeviceState getState(void) throw();
00249 buttons_t getButtons(void) throw();
00250 eButton getButton(IN int idx) throw();
00251 void getJoystick(IN int idx,
00252 OUT joystick_t& joy) throw();
00253 void getPot(IN int idx,
00254 OUT pot_value_t& pv) throw();
00255 eDpad getDpad(IN int idx) throw();
00256
00257 private:
00258
00259 typedef std::vector<button_map_t> btn_vec_t;
00260 typedef std::vector<dpad_map_t> dpad_vec_t;
00261 typedef std::vector<joystick_map_t> joy_vec_t;
00262 typedef std::vector<pot_map_t> pot_vec_t;
00263
00264
00265
00266 Type * m_type;
00267 smart_ptr<SourceDevice> m_device;
00268 std::string m_mappingId;
00269 std::string m_id;
00270
00271 btn_vec_t m_button;
00272 dpad_vec_t m_dpad;
00273 pot_vec_t m_pot;
00274 joy_vec_t m_joystick;
00275 };
00276
00277
00278
00279 void
00280 GPad::initialize
00281 (
00282 IN Type * type,
00283 IN smart_ptr<SourceDevice>& device,
00284 IN smart_ptr<Map>& mapping
00285 )
00286 {
00287 ASSERT(type, "null");
00288 ASSERT(device, "null");
00289 ASSERT(mapping, "null");
00290
00291
00292
00293 m_type = type;
00294 m_device = device;
00295
00296 m_mappingId = mapping->getId();
00297
00298
00299 m_id = device->getUniqueId();
00300 m_id += ":";
00301 m_id += mapping->getId();
00302
00303 DPRINTF("Gamepad id: '%s'", m_id.c_str());
00304
00305
00306 int nButtons = type->getInputCount(eInput_Button);
00307
00308 m_button.reserve(nButtons);
00309 for (int i = 0; i < nButtons; ++i) {
00310 const char * name = type->getLogicalName(eInput_Button, i);
00311
00312 const button_map_t * bmap = mapping->getButtonMapping(name);
00313
00314
00315 ASSERT_THROW(bmap && bmap->isValid(),
00316 "Missing or invalid mapping found for button: '" << name
00317 << "', gamepad type: '" << type->getName() <<
00318 "', mapping name: '" << mapping->getName() << "'");
00319
00320 m_button.push_back(*bmap);
00321 }
00322
00323 ASSERT(nButtons == (int) m_button.size(), "should match");
00324
00325
00326 int nJoys = type->getInputCount(eInput_Joystick);
00327
00328 m_joystick.reserve(nJoys);
00329 for (int i = 0; i < nJoys; ++i) {
00330 const char * name = type->getLogicalName(eInput_Joystick, i);
00331
00332 const joystick_map_t * jmap = mapping->getJoystickMapping(name);
00333
00334
00335 ASSERT_THROW(jmap && jmap->isValid(),
00336 "Missing or invalid mapping found for joystick: '" << name
00337 << "', gamepad type: '" << type->getName() <<
00338 "', mapping name: '" << mapping->getName() << "'");
00339
00340 m_joystick.push_back(*jmap);
00341 }
00342
00343
00344 int nDpads = type->getInputCount(eInput_Dpad);
00345
00346 m_dpad.reserve(nDpads);
00347 for (int i = 0; i < nDpads; ++i) {
00348 const char * name = type->getLogicalName(eInput_Dpad, i);
00349
00350 const dpad_map_t * dmap = mapping->getDpadMapping(name);
00351
00352
00353 ASSERT_THROW(dmap && dmap->isValid(),
00354 "Missing or invalid mapping found for dpad: '" << name
00355 << "', gamepad type: '" << type->getName() <<
00356 "', mapping name: '" << mapping->getName() << "'");
00357
00358 m_dpad.push_back(*dmap);
00359 }
00360
00361 ASSERT(nDpads == (int) m_dpad.size(), "should match");
00362
00363
00364 int nPots = type->getInputCount(eInput_Pot);
00365
00366 m_pot.reserve(nPots);
00367 for (int i = 0; i < nPots; ++i) {
00368 const char * name = type->getLogicalName(eInput_Pot, i);
00369
00370 const pot_map_t * pmap = mapping->getPotMapping(name);
00371 if (pmap) {
00372
00373
00374 m_pot.push_back(*pmap);
00375 } else {
00376 ASSERT_THROW(false,
00377 "Missing or invalid mapping found for potentiometer: '" <<
00378 name << "', gamepad type: '" << type->getName() <<
00379 "', mapping name: '" << mapping->getName() << "'");
00380 }
00381 }
00382
00383 ASSERT(nPots == (int) m_pot.size(), "should match");
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 Type *
00395 GPad::getType
00396 (
00397 void
00398 )
00399 const
00400 throw()
00401 {
00402 return m_type;
00403 }
00404
00405
00406
00407 const char *
00408 GPad::getId
00409 (
00410 void
00411 )
00412 throw()
00413 {
00414 return m_id.c_str();
00415 }
00416
00417
00418
00419 const char *
00420 GPad::getSourceDeviceId
00421 (
00422 void
00423 )
00424 throw()
00425 {
00426 ASSERT(m_device, "null");
00427
00428 return m_device->getUniqueId();
00429 }
00430
00431
00432
00433 const char *
00434 GPad::getMappingId
00435 (
00436 void
00437 )
00438 throw()
00439 {
00440 return m_mappingId.c_str();
00441 }
00442
00443
00444
00445 eDeviceState
00446 GPad::getState
00447 (
00448 void
00449 )
00450 throw()
00451 {
00452 ASSERT(m_device, "null");
00453 return m_device->getState();
00454 }
00455
00456
00457
00458 buttons_t
00459 GPad::getButtons
00460 (
00461 void
00462 )
00463 throw()
00464 {
00465 ASSERT(m_device, "null");
00466 buttons_t retval = 0;
00467
00468 int bit = 1;
00469 for (btn_vec_t::iterator i = m_button.begin(); i != m_button.end();
00470 ++i, bit = 2 * bit) {
00471 const button_map_t& bmap = *i;
00472 eButton val = m_device->getButtonValue(bmap.index);
00473
00474 if (val) {
00475 retval |= bit;
00476 }
00477 }
00478 return retval;
00479 }
00480
00481
00482
00483 eButton
00484 GPad::getButton
00485 (
00486 IN int idx
00487 )
00488 throw()
00489 {
00490 ASSERT(idx >= 0 && idx < (int) m_button.size(), "Bad index: %d", idx);
00491
00492 const button_map_t& bmap = m_button[idx];
00493 return m_device->getButtonValue(bmap.index);
00494 }
00495
00496
00497
00498 void
00499 GPad::getJoystick
00500 (
00501 IN int idx,
00502 OUT joystick_t& joy
00503 )
00504 throw()
00505 {
00506 ASSERT(idx >= 0, "Bad joystick index: %d", idx);
00507 ASSERT(idx < (int) m_joystick.size(), "Bad joystick index: %d", idx);
00508 ASSERT(m_device, "NULL");
00509 joy.clear();
00510
00511 const joystick_map_t& jmap = m_joystick[idx];
00512 joy.x = m_device->getPotValue(jmap.xIndex);
00513 joy.y = m_device->getPotValue(jmap.yIndex);
00514 }
00515
00516
00517
00518 void
00519 GPad::getPot
00520 (
00521 IN int idx,
00522 OUT pot_value_t& pv
00523 )
00524 throw()
00525 {
00526 ASSERT(idx >= 0, "Bad pot index: %d", idx);
00527 ASSERT(idx < (int) m_pot.size(), "Bad pot index: %d", idx);
00528 ASSERT(m_device, "null");
00529
00530 const pot_map_t& pmap = m_pot[idx];
00531 pv = m_device->getPotValue(pmap.index);
00532 }
00533
00534
00535
00536 eDpad
00537 GPad::getDpad
00538 (
00539 IN int idx
00540 )
00541 throw()
00542 {
00543 ASSERT(idx >= 0, "Bad dpad index: %d", idx);
00544 ASSERT(idx < (int) m_dpad.size(), "Bad dpad index: %d", idx);
00545 ASSERT(m_device, "null");
00546
00547 const dpad_map_t& dmap = m_dpad[idx];
00548
00549 int xPos = 0;
00550 int yPos = 0;
00551
00552 if (dpad_map_t::eType_2Pot == dmap.type) {
00553
00554 xPos = getDpadFromPot(m_device, dmap.index[dpad_map_t::eLeft]);
00555 yPos = getDpadFromPot(m_device, dmap.index[dpad_map_t::eUp]);
00556 } else if (dpad_map_t::eType_4Pot == dmap.type) {
00557
00558 if (potMoved(m_device, dmap.index[dpad_map_t::eLeft]))
00559 xPos = -1;
00560 if (potMoved(m_device, dmap.index[dpad_map_t::eRight]))
00561 xPos = +1;
00562 if (potMoved(m_device, dmap.index[dpad_map_t::eUp]))
00563 yPos = -1;
00564 if (potMoved(m_device, dmap.index[dpad_map_t::eDown]))
00565 yPos = +1;
00566 } else {
00567
00568 if (eButtonDown & m_device->getButtonValue(dmap.index[dpad_map_t::eLeft]))
00569 xPos = -1;
00570 if (eButtonDown & m_device->getButtonValue(dmap.index[dpad_map_t::eRight]))
00571 xPos = +1;
00572 if (eButtonDown & m_device->getButtonValue(dmap.index[dpad_map_t::eUp]))
00573 yPos = -1;
00574 if (eButtonDown & m_device->getButtonValue(dmap.index[dpad_map_t::eDown]))
00575 yPos = +1;
00576
00577 }
00578
00579
00580 if (dmap.flipX)
00581 xPos = -xPos;
00582 if (dmap.flipY)
00583 yPos = -yPos;
00584
00585
00586 int retval = eDpad_Centered;
00587 if (xPos < 0)
00588 retval = eDpad_Left;
00589 else if (xPos > 0)
00590 retval = eDpad_Right;
00591
00592 if (yPos < 0)
00593 retval |= eDpad_Up;
00594 else if (yPos > 0)
00595 retval |= eDpad_Down;
00596
00597 return (eDpad) retval;
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 class Mgr : public Manager {
00609 public:
00610
00611 ~Mgr(void) throw() { }
00612
00613
00614 void initialize(IN smart_ptr<nstream::Folder>& dataDir);
00615
00616
00617 nstream::Folder * getDataDirectory(void);
00618 bool rediscover(void);
00619 int getSourceDeviceCount(void) { return m_devices.size(); }
00620 smart_ptr<SourceDevice> getSourceDevice(IN int index);
00621 smart_ptr<SourceDevice> getSourceDeviceById(IN const char * id);
00622 int getTypeCount(void);
00623 smart_ptr<Type> getType(IN int index);
00624 smart_ptr<Type> getType(IN const char * id);
00625 void addType(IN smart_ptr<Type>& type);
00626 int getMappingCount(void);
00627 smart_ptr<Map> getMapping(IN int index);
00628 smart_ptr<Map> getMapping(IN const char * id);
00629 void addMapping(IN smart_ptr<Map>& map);
00630 eResult createGamepad(IN smart_ptr<SourceDevice>& device,
00631 IN smart_ptr<Map>& map,
00632 OUT smart_ptr<Gamepad>& gamepad);
00633 int getGamepadCount(void);
00634 smart_ptr<Gamepad> getGamepad(IN int index);
00635 smart_ptr<Gamepad> getGamepad(IN const char * id);
00636 bool deleteGamepad(IN const char * id);
00637 void update(void);
00638
00639 private:
00640
00641 typedef std::vector<smart_ptr<SourceDeviceFactory> > vec_factory_t;
00642 typedef std::map<std::string, smart_ptr<SourceDevice> > device_map_t;
00643 typedef std::map<std::string, smart_ptr<Type> > map_type_t;
00644 typedef std::map<std::string, smart_ptr<Map> > map_map_t;
00645 typedef std::map<std::string, smart_ptr<Gamepad> > gamepad_map_t;
00646
00647
00648 smart_ptr<nstream::Folder> m_folder;
00649 vec_factory_t m_factories;
00650 device_map_t m_devices;
00651 map_type_t m_types;
00652 map_map_t m_mappings;
00653 gamepad_map_t m_gamepads;
00654 };
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 nstream::Folder *
00665 Mgr::getDataDirectory
00666 (
00667 void
00668 )
00669 {
00670 ASSERT(m_folder, "null");
00671
00672 return m_folder;
00673 }
00674
00675
00676
00677 void
00678 Mgr::initialize
00679 (
00680 IN smart_ptr<nstream::Folder>& folder
00681 )
00682 {
00683 ASSERT(folder, "null");
00684
00685
00686 m_folder = folder;
00687 void * context = (Manager *) this;
00688 nstream::walkChildFolders(folder, loadFilesCallback, context);
00689
00690
00691 #if WIN32
00692
00693 smart_ptr<SourceDeviceFactory> factory =
00694 getDirectInputSourceDeviceFactory();
00695 ASSERT(factory, "failed to create direct input source device factory");
00696 m_factories.push_back(factory);
00697
00698 #else // WIN32
00699
00700 smart_ptr<SourceDeviceFactory> factory =
00701 getLinuxJoystickSourceDeviceFactory();
00702 ASSERT(factory, "failed to create linux joystick source device factory");
00703 m_factories.push_back(factory);
00704
00705 #endif // WIN32
00706
00707 DPRINTF("Have %d factory objects", (int) m_factories.size());
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 bool
00719 Mgr::rediscover
00720 (
00721 void
00722 )
00723 {
00724 perf::Timer timer("gamepad::Manager::rediscover");
00725
00726 bool changes = false;
00727
00728
00729 VecString badIds;
00730 for (device_map_t::iterator i = m_devices.begin(); i != m_devices.end();
00731 ++i) {
00732 const char * id = i->first.c_str();
00733 SourceDevice * sd = i->second;
00734 ASSERT(sd, "null device in map");
00735
00736
00737
00738 if (eDevice_Detached == sd->getState()) {
00739 badIds.push_back(id);
00740 changes = true;
00741 }
00742 }
00743
00744
00745 for (VecString::const_iterator i = badIds.begin(); i != badIds.end();
00746 ++i) {
00747 const char * id = i->c_str();
00748 device_map_t::iterator bad = m_devices.find(id);
00749 if (m_devices.end() == bad) {
00750 DPRINTF("ERROR: bad id not in map? '%s'", id);
00751 continue;
00752 }
00753 m_devices.erase(bad);
00754 }
00755
00756
00757
00758 for (vec_factory_t::iterator i = m_factories.begin();
00759 i != m_factories.end(); ++i) {
00760 SourceDeviceFactory * factory = *i;
00761 ASSERT(factory, "null factory in map");
00762
00763 int N = factory->getCount();
00764
00765
00766 for (int j = 0; j < N; ++j) {
00767 smart_ptr<SourceDevice> device =
00768 factory->getSourceDevice(j);
00769 if (!device) {
00770 DPRINTF("Device %d was null", j);
00771 continue;
00772 }
00773
00774 const char * id = device->getUniqueId();
00775
00776
00777 device_map_t::iterator existing = m_devices.find(id);
00778 if (m_devices.end() != existing) {
00779
00780 continue;
00781 }
00782
00783
00784 changes = true;
00785 m_devices[id] = device;
00786 }
00787 }
00788
00789
00790 VecString badGamepadIds;
00791 int nGamepads = this->getGamepadCount();
00792 for (int i = 0; i < nGamepads; ++i) {
00793 smart_ptr<gamepad::Gamepad> gp = this->getGamepad(i);
00794 if (!gp)
00795 continue;
00796
00797 const char * deviceId = gp->getSourceDeviceId();
00798 if (!deviceId || !this->getSourceDeviceById(deviceId)) {
00799 DPRINTF("Gamepad is gone");
00800 badGamepadIds.push_back(gp->getId());
00801 }
00802 }
00803
00804 int nBadIds = badGamepadIds.size();
00805 for (int i = 0; i < nBadIds; ++i) {
00806 const char * badId = badGamepadIds[i].c_str();
00807 this->deleteGamepad(badId);
00808 }
00809
00810
00811 return changes;
00812 }
00813
00814
00815
00816 smart_ptr<SourceDevice>
00817 Mgr::getSourceDevice
00818 (
00819 IN int index
00820 )
00821 {
00822 ASSERT(index >= 0, "Bad index: %d", index);
00823
00824
00825 for (device_map_t::iterator i = m_devices.begin();
00826 i != m_devices.end(); ++i, --index) {
00827 if (!index) {
00828
00829 return i->second;
00830 }
00831 }
00832
00833
00834 return NULL;
00835 }
00836
00837
00838
00839 smart_ptr<SourceDevice>
00840 Mgr::getSourceDeviceById
00841 (
00842 IN const char * id
00843 )
00844 {
00845 ASSERT(id, "null");
00846
00847
00848 for (device_map_t::iterator i = m_devices.begin();
00849 i != m_devices.end(); ++i) {
00850 smart_ptr<SourceDevice> device = i->second;
00851 if (device &&
00852 !strcmp(id, device->getUniqueId())) {
00853 return device;
00854 }
00855 }
00856
00857
00858 return NULL;
00859 }
00860
00861
00862
00863 int
00864 Mgr::getTypeCount
00865 (
00866 void
00867 )
00868 {
00869 return m_types.size();
00870 }
00871
00872
00873
00874 smart_ptr<Type>
00875 Mgr::getType
00876 (
00877 IN int index
00878 )
00879 {
00880 ASSERT(index >= 0, "Bad index: %d", index);
00881
00882 for (map_type_t::iterator i = m_types.begin();
00883 i != m_types.end(), index >= 0; ++i, --index) {
00884 if (!index) {
00885 return i->second;
00886 }
00887 }
00888
00889
00890 return NULL;
00891 }
00892
00893
00894
00895 smart_ptr<Type>
00896 Mgr::getType
00897 (
00898 IN const char * id
00899 )
00900 {
00901 ASSERT(id, "null");
00902
00903 map_type_t::iterator i = m_types.find(id);
00904 if (m_types.end() == i) {
00905 return NULL;
00906 }
00907 return i->second;
00908 }
00909
00910
00911
00912 void
00913 Mgr::addType
00914 (
00915 IN smart_ptr<Type>& type
00916 )
00917 {
00918 ASSERT(type, "null");
00919
00920 const char * id = type->getId();
00921 ASSERT(id, "null id from type");
00922
00923
00924 m_types[id] = type;
00925 }
00926
00927
00928
00929 int
00930 Mgr::getMappingCount
00931 (
00932 void
00933 )
00934 {
00935 return m_mappings.size();
00936 }
00937
00938
00939
00940 smart_ptr<Map>
00941 Mgr::getMapping
00942 (
00943 IN int index
00944 )
00945 {
00946 ASSERT(index >= 0, "Bad index: %d", index);
00947
00948 for (map_map_t::iterator i = m_mappings.begin();
00949 i != m_mappings.end(), index >= 0; ++i, --index) {
00950 if (!index) {
00951 return i->second;
00952 }
00953 }
00954
00955
00956 return NULL;
00957 }
00958
00959
00960
00961 smart_ptr<Map>
00962 Mgr::getMapping
00963 (
00964 IN const char * id
00965 )
00966 {
00967 ASSERT(id, "null");
00968
00969 map_map_t::iterator i = m_mappings.find(id);
00970 if (m_mappings.end() == i) {
00971 return NULL;
00972 }
00973 return i->second;
00974 }
00975
00976
00977
00978 void
00979 Mgr::addMapping
00980 (
00981 IN smart_ptr<Map>& map
00982 )
00983 {
00984 ASSERT(map, "null");
00985
00986 const char * id = map->getId();
00987 ASSERT(id, "null id for gamepad mapping");
00988
00989
00990 m_mappings[id] = map;
00991 }
00992
00993
00994
00995 Manager::eResult
00996 Mgr::createGamepad
00997 (
00998 IN smart_ptr<SourceDevice>& device,
00999 IN smart_ptr<Map>& map,
01000 OUT smart_ptr<Gamepad>& gamepad
01001 )
01002 {
01003 ASSERT(device, "null");
01004 ASSERT(map, "null");
01005 gamepad = NULL;
01006
01007
01008 const char * typeId = map->getTypeId();
01009 DPRINTF("Creating gamepad from mapping with type=%s", typeId);
01010 ASSERT(typeId, "bad type id");
01011
01012 map_type_t::iterator i = m_types.find(typeId);
01013 ASSERT_THROW(m_types.end() != i,
01014 "Cannot create gamepad since type specified in mapping is not "
01015 "recognized. Mapping name: '" << map->getName() << "', type id: '"
01016 << typeId << "'");
01017 Type * type = i->second;
01018 ASSERT(type, "null type object in type map?");
01019
01020
01021 if (sourceAndMapInUse(this, device->getUniqueId(), map->getId())) {
01022 DPRINTF(" Cannot create gamepad: source and map already used");
01023 return Manager::eResult_SourceInUse;
01024 }
01025
01026
01027 smart_ptr<GPad> gpad = new GPad;
01028 ASSERT(gpad, "out of memory");
01029 gpad->initialize(type, device, map);
01030
01031
01032 gamepad = gpad;
01033
01034
01035 m_gamepads[gamepad->getId()] = gamepad;
01036
01037 return Manager::eResult_Success;
01038 }
01039
01040
01041
01042 int
01043 Mgr::getGamepadCount
01044 (
01045 void
01046 )
01047 {
01048 return m_gamepads.size();
01049 }
01050
01051
01052
01053 smart_ptr<Gamepad>
01054 Mgr::getGamepad
01055 (
01056 IN int index
01057 )
01058 {
01059 ASSERT(index >= 0, "invalid gamepad index: %d", index);
01060
01061 for (gamepad_map_t::iterator i = m_gamepads.begin();
01062 index >= 0 && i != m_gamepads.end(); ++i, --index) {
01063 if (!index)
01064 return i->second;
01065 }
01066
01067
01068 return NULL;
01069 }
01070
01071
01072
01073 smart_ptr<Gamepad>
01074 Mgr::getGamepad
01075 (
01076 IN const char * id
01077 )
01078 {
01079 ASSERT(id, "null");
01080
01081 gamepad_map_t::iterator i = m_gamepads.find(id);
01082 if (m_gamepads.end() == i) {
01083 DPRINTF("Gamepad not found, id='%s'", id);
01084 return NULL;
01085 }
01086
01087 return i->second;
01088 }
01089
01090
01091
01092 bool
01093 Mgr::deleteGamepad
01094 (
01095 IN const char * id
01096 )
01097 {
01098 ASSERT(id, "null");
01099
01100 gamepad_map_t::iterator i = m_gamepads.find(id);
01101 if (m_gamepads.end() == i) {
01102 DPRINTF("Gamepad not found, id='%s'", id);
01103 return false;
01104 }
01105
01106 m_gamepads.erase(i);
01107 return true;
01108 }
01109
01110
01111
01112 void
01113 Mgr::update
01114 (
01115 void
01116 )
01117 {
01118 for (device_map_t::iterator i = m_devices.begin(); i != m_devices.end();
01119 ++i) {
01120 SourceDevice * device = i->second;
01121 ASSERT(device, "null");
01122
01123 device->poll();
01124 }
01125 }
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135 smart_ptr<Manager>
01136 Manager::create
01137 (
01138 IN smart_ptr<nstream::Folder>& dataDirectory
01139 )
01140 {
01141 ASSERT(dataDirectory, "null");
01142
01143 smart_ptr<Mgr> local = new Mgr;
01144 ASSERT(local, "out of memory");
01145
01146 local->initialize(dataDirectory);
01147
01148 return local;
01149 }
01150
01151
01152
01153 void
01154 getRecommendedMappings
01155 (
01156 IN Manager * mgr,
01157 IN SourceDevice * device,
01158 OUT VecString& mapNames
01159 )
01160 {
01161 ASSERT(mgr, "null");
01162 ASSERT(device, "null");
01163 mapNames.clear();
01164
01165
01166 const char * devName = device->getPublicName();
01167 ASSERT(devName, "null");
01168
01169
01170
01171 int nMaps = mgr->getMappingCount();
01172 for (int i = 0; i < nMaps; ++i) {
01173 smart_ptr<Map> mapping = mgr->getMapping(i);
01174 ASSERT(mapping, "null");
01175
01176
01177 const VecString& mapDevNames = mapping->getDeviceNames();
01178 for (VecString::const_iterator j = mapDevNames.begin();
01179 j != mapDevNames.end(); ++j) {
01180 if (*j == devName) {
01181
01182 const char * id = mapping->getId();
01183 ASSERT(id, "null");
01184 mapNames.push_back(id);
01185 }
01186 }
01187 }
01188
01189
01190 }
01191
01192
01193
01194 void
01195 autoconfigureGamepads
01196 (
01197 IN Manager * mgr
01198 )
01199 {
01200 ASSERT(mgr, "null");
01201
01202 DPRINTF("Attempting to autoconfigure gamepads...");
01203
01204
01205 int nDevices = mgr->getSourceDeviceCount();
01206 for (int i = 0; i < nDevices; ++i) {
01207 smart_ptr<SourceDevice> device = mgr->getSourceDevice(i);
01208 if (!device) {
01209 DPRINTF("Source device %d is no longer available", i);
01210 continue;
01211 }
01212
01213 VecString names;
01214 getRecommendedMappings(mgr, device, names);
01215
01216 DPRINTF(" Seeing if I can autoconfigure device: '%s'",
01217 device->getPublicName());
01218 int nMappings = names.size();
01219 DPRINTF(" %d recommended mappings found", nMappings);
01220 if (nMappings < 1) {
01221 continue;
01222 }
01223 if (nMappings > 1) {
01224 DPRINTF(" Found %d recommended mappings.",
01225 nMappings);
01226 DPRINTF(" I'll use the first one that works.");
01227 }
01228 smart_ptr<Map> map;
01229 for (int j = 0; j < nMappings; ++j) {
01230 const char * mapName = names[j].c_str();
01231 DPRINTF(" Trying mapping: %d='%s'", j, mapName);
01232 map = mgr->getMapping(mapName);
01233 if (map)
01234 break;
01235
01236 DPRINTF(" ...could not generate mapping");
01237 }
01238 if (!map) {
01239 DPRINTF(" No mappings worked! Skipping device.");
01240 continue;
01241 }
01242
01243
01244 smart_ptr<Gamepad> gamepad;
01245 Manager::eResult result =
01246 mgr->createGamepad(device, map, gamepad);
01247 if (Manager::eResult_Success == result) {
01248 DPRINTF(" Autoconfigured gamepad!");
01249 } else if (Manager::eResult_SourceInUse == result) {
01250 DPRINTF(" (this gamepad is already configured)");
01251 } else {
01252 DPRINTF(" Autoconfig failed, reason: %d", result);
01253 }
01254 }
01255 }
01256
01257
01258
01259 };
01260