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 //---------------------------------------------------------------------------------//
WiiMoteFactoryCreator()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 //---------------------------------------------------------------------------------//
~WiiMoteFactoryCreator()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 //---------------------------------------------------------------------------------//
freeDeviceList()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 //---------------------------------------------------------------------------------//
totalDevices(Type iType)82 int WiiMoteFactoryCreator::totalDevices(Type iType)
83 {
84 	if( iType == OISJoyStick )
85 		return mCount;
86 	else
87 		return 0;
88 }
89 
90 //---------------------------------------------------------------------------------//
freeDevices(Type iType)91 int WiiMoteFactoryCreator::freeDevices(Type iType)
92 {
93 	if( iType == OISJoyStick )
94 		return (int)mFreeWiis.size();
95 	else
96 		return 0;
97 }
98 
99 //---------------------------------------------------------------------------------//
vendorExist(Type iType,const std::string & vendor)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 //---------------------------------------------------------------------------------//
createObject(InputManager * creator,Type iType,bool bufferMode,const std::string & vendor)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 //---------------------------------------------------------------------------------//
destroyObject(Object * obj)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 //---------------------------------------------------------------------------------//
_returnWiiMote(int id)172 void WiiMoteFactoryCreator::_returnWiiMote(int id)
173 {	//Restore ID to controller pool
174 	mFreeWiis.push_front(id);
175 }
176 
177 //---------------------------------------------------------------------------------//
_updateWiiMotesThread()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