1 #include "OISConfig.h" 2 #ifdef OIS_WIN32_WIIMOTE_SUPPORT 3 /* 4 The zlib/libpng License 5 6 Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com) 7 8 This software is provided 'as-is', without any express or implied warranty. In no event will 9 the authors be held liable for any damages arising from the use of this software. 10 11 Permission is granted to anyone to use this software for any purpose, including commercial 12 applications, and to alter it and redistribute it freely, subject to the following 13 restrictions: 14 15 1. The origin of this software must not be misrepresented; you must not claim that 16 you wrote the original software. If you use this software in a product, 17 an acknowledgment in the product documentation would be appreciated but is 18 not required. 19 20 2. Altered source versions must be plainly marked as such, and must not be 21 misrepresented as being the original software. 22 23 3. This notice may not be removed or altered from any source distribution. 24 */ 25 #include "OISWiiMoteFactoryCreator.h" 26 #include "OISException.h" 27 #include "OISWiiMote.h" 28 #include <assert.h> 29 #include <boost/thread.hpp> //include here, keep compilation times down 30 #include <boost/function.hpp> 31 #include <boost/bind.hpp> 32 33 34 using namespace OIS; 35 36 //---------------------------------------------------------------------------------// 37 WiiMoteFactoryCreator::WiiMoteFactoryCreator() : 38 mVendorName("cWiiMote"), 39 mCount(0), 40 mtThreadHandler(0), 41 mtWiiMoteListMutex(0), 42 mtThreadRunning(0) 43 { 44 //Discover how many Wii's there are 45 for( ; mCount < OIS_cWiiMote_MAX_WIIS; ++mCount ) 46 { 47 cWiiMote wii; 48 if( wii.ConnectToDevice(mCount) == false ) 49 break; 50 } 51 52 //Store how many WiiMotes there were in the form of integer handles 53 for(int i = 0; i < mCount; ++i) 54 mFreeWiis.push_back(i); 55 56 //The mutex lasts the whole life of this class. The thread does not. 57 mtWiiMoteListMutex = new boost::mutex(); 58 } 59 60 //---------------------------------------------------------------------------------// 61 WiiMoteFactoryCreator::~WiiMoteFactoryCreator() 62 { 63 //Thread (once all objects destroyed) should be killed off already 64 assert( (mtThreadRunning == false && mtThreadHandler == 0) && 65 "~WiiMoteFactoryCreator(): invalid state.. Some objects left dangling!"); 66 67 delete mtWiiMoteListMutex; 68 } 69 70 //---------------------------------------------------------------------------------// 71 DeviceList WiiMoteFactoryCreator::freeDeviceList() 72 { 73 DeviceList list; 74 for( std::deque<int>::iterator i = mFreeWiis.begin(); i != mFreeWiis.end(); ++i ) 75 { 76 list.insert(std::make_pair(OISJoyStick, mVendorName)); 77 } 78 return list; 79 } 80 81 //---------------------------------------------------------------------------------// 82 int WiiMoteFactoryCreator::totalDevices(Type iType) 83 { 84 if( iType == OISJoyStick ) 85 return mCount; 86 else 87 return 0; 88 } 89 90 //---------------------------------------------------------------------------------// 91 int WiiMoteFactoryCreator::freeDevices(Type iType) 92 { 93 if( iType == OISJoyStick ) 94 return (int)mFreeWiis.size(); 95 else 96 return 0; 97 } 98 99 //---------------------------------------------------------------------------------// 100 bool WiiMoteFactoryCreator::vendorExist(Type iType, const std::string & vendor) 101 { 102 if( iType == OISJoyStick && mVendorName == vendor ) 103 return true; 104 else 105 return false; 106 } 107 108 //---------------------------------------------------------------------------------// 109 Object* WiiMoteFactoryCreator::createObject(InputManager* creator, Type iType, bool bufferMode, const std::string & vendor) 110 { 111 if( mFreeWiis.size() > 0 && (vendor == "" || vendor == mVendorName ) ) 112 { 113 int id = mFreeWiis.front(); 114 mFreeWiis.pop_front(); 115 WiiMote *wii = new WiiMote(creator, id, bufferMode, this); 116 117 if( mtThreadRunning == false ) 118 { //Create common thread manager (this is the first wiimote created) 119 mtThreadRunning = true; 120 mtThreadHandler = new boost::thread(boost::bind(&WiiMoteFactoryCreator::_updateWiiMotesThread, this)); 121 } 122 123 //Now, add new WiiMote to thread manager for polling 124 { //Get an auto lock on the list of active wiimotes 125 boost::mutex::scoped_lock arrayLock(*mtWiiMoteListMutex); 126 mtInUseWiiMotes.push_back(wii); 127 } 128 129 return wii; 130 } 131 else 132 OIS_EXCEPT(E_InputDeviceNonExistant, "No Device found which matches description!"); 133 } 134 135 //---------------------------------------------------------------------------------// 136 void WiiMoteFactoryCreator::destroyObject(Object* obj) 137 { 138 if( obj == 0 ) 139 return; 140 141 int wiis_alive = 0; 142 143 { //Get an auto lock on the list of active wiimotes 144 boost::mutex::scoped_lock arrayLock(*mtWiiMoteListMutex); 145 146 //Find object 147 std::vector<WiiMote*>::iterator i = std::find(mtInUseWiiMotes.begin(), mtInUseWiiMotes.end(), obj); 148 if( i == mtInUseWiiMotes.end() ) 149 OIS_EXCEPT(E_General, "Device not found in wimote collection!"); 150 151 //Erase opject 152 mtInUseWiiMotes.erase(i); 153 154 //Delete object 155 delete obj; 156 157 wiis_alive = (int)mtInUseWiiMotes.size(); 158 } 159 160 //Destroy thread if no longer in use (we do this after unlocking mutex!) 161 if( wiis_alive == 0 && mtThreadRunning ) 162 { 163 mtThreadRunning = false; 164 mtThreadHandler->join(); 165 delete mtThreadHandler; 166 mtThreadHandler = 0; 167 } 168 169 } 170 171 //---------------------------------------------------------------------------------// 172 void WiiMoteFactoryCreator::_returnWiiMote(int id) 173 { //Restore ID to controller pool 174 mFreeWiis.push_front(id); 175 } 176 177 //---------------------------------------------------------------------------------// 178 bool WiiMoteFactoryCreator::_updateWiiMotesThread() 179 { 180 boost::xtime timer; 181 182 while(mtThreadRunning) 183 { 184 int numMotes = 0; 185 { //Get an auto lock on the list of active wiimotes 186 boost::mutex::scoped_lock arrayLock(*mtWiiMoteListMutex); 187 numMotes = (int)mtInUseWiiMotes.size(); 188 for( std::vector<WiiMote*>::iterator i = mtInUseWiiMotes.begin(), e = mtInUseWiiMotes.end(); i != e; ++i ) 189 { //Update it 190 (*i)->_threadUpdate(); 191 } 192 } 193 194 //ok, we have updated all wiimotes, let us rest a bit 195 //sleep time = 30 / 1000 196 //boost::thread::sleep(xtime) todo xxx wip use sleep instead?? 197 //boost::thread::yield(); 198 boost::xtime_get(&timer, boost::TIME_UTC); 199 timer.nsec += 20000000; //20 000 000 ~= 1/50 sec 200 boost::thread::sleep(timer); 201 } 202 203 return true; 204 } 205 206 #endif 207