Home | History | Annotate | Download | only in WiiMote
      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