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