00001 /* 00002 Copyright (c) 2002-2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 00003 00004 Redistribution and use in source and binary forms, with or without 00005 modification, are permitted provided that the following conditions are met: 00006 00007 * Redistributions of source code must retain the above copyright notice, this 00008 list of conditions and the following disclaimer. 00009 * Redistributions in binary form must reproduce the above copyright notice, 00010 this list of conditions and the following disclaimer in the documentation 00011 and/or other materials provided with the distribution. 00012 * Neither the name of Nokia Corporation nor the names of its contributors 00013 may be used to endorse or promote products derived from this software 00014 without specific prior written permission. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 00027 Description: 00028 */ 00029 00030 #include "rpsgamescreens.h" 00031 #include "BluetoothManager.h" 00032 #include "BluetoothDeviceDiscoverer.h" 00033 #include "BluetoothConnector.h" 00034 #include "common.hrh" 00035 00036 // ----------------------------------------------------------------------------------- 00037 // CBluetoothManager class 00038 // ----------------------------------------------------------------------------------- 00039 CBluetoothManager* CBluetoothManager::NewL(CGameScreenManager& aGameScreenMgr) 00040 { 00041 CBluetoothManager* me = new (ELeave) CBluetoothManager(aGameScreenMgr); 00042 CleanupStack::PushL(me); 00043 me->ConstructL(); 00044 CleanupStack::Pop(me); 00045 return (me); 00046 } 00047 00048 void CBluetoothManager::ConstructL() 00049 { 00050 // Get socket server session 00051 User::LeaveIfError(iSocketServer.Connect()); 00052 iBtDeviceDiscoverer = CBluetoothDeviceDiscoverer::NewL(*this); 00053 } 00054 00055 CBluetoothManager::CBluetoothManager(CGameScreenManager& aGameScreenMgr) 00056 : iGameScreenMgr(aGameScreenMgr) 00057 { 00058 TUUID targetServiceClass(KRPS_BTServiceID); 00059 //Use by the RNotifier dialog to get only BT devices that supports the RPS's service 00060 iDevSelFilter.SetUUID(targetServiceClass); 00061 } 00062 00063 CBluetoothManager::~CBluetoothManager() 00064 { 00065 if(iBtConnBase) 00066 { 00067 iBtConnBase->Cancel(); 00068 delete iBtConnBase; 00069 } 00070 00071 if (iBtDeviceDiscoverer) 00072 { 00073 iBtDeviceDiscoverer->Cancel(); 00074 delete iBtDeviceDiscoverer; 00075 } 00076 00077 iSocketServer.Close(); 00078 00079 //iBtConnBaseArray.ResetAndDestroy();//Not used for 2 player multiplay, see header file for details 00080 } 00081 00082 /* 00083 ============================================================================ 00084 Callback from the Control Screen. The player has decided to control the game. 00085 The CRpsGameEngine takes the Master role of the game. 00086 ============================================================================ 00087 */ 00088 void CBluetoothManager::StartBtMaster() 00089 { 00090 iGameScreenMgr.GameData().iRpsError = KErrNone; 00091 00092 //Display the Connecting screen 00093 iGameScreenMgr.SetGameState(CGameScreenManager::ENotifierScreen); 00094 00095 //Start BT device discovery 00096 TBTDeviceSelectionParamsPckg pckg(iDevSelFilter); 00097 TRAPD(err, iBtDeviceDiscoverer->DiscoverAndSelectDeviceL(pckg)); 00098 if(err!=KErrNone) 00099 { 00100 DisplayError(err); 00101 } 00102 } 00103 00104 /* 00105 ============================================================================ 00106 Callback from the Control Screen. The player has decided to wait for a connection. 00107 The CRpsGameEngine takes the Slave role of the game. 00108 ============================================================================ 00109 */ 00110 void CBluetoothManager::StartBtSlave() 00111 { 00112 iGameScreenMgr.GameData().iRpsError = KErrNone; 00113 00114 //Display the Waiting Screen 00115 iGameScreenMgr.SetGameState(CGameScreenManager::EWaitConnScreen); 00116 00117 ASSERT(!iBtConnBase); 00118 00119 TRAPD(err, iBtConnBase = CBluetoothResponder::NewL(*this, iSocketServer); 00120 iBtConnBase->StartL()); 00121 00122 if(err != KErrNone) 00123 { 00124 if(iBtConnBase) 00125 { 00126 delete iBtConnBase; 00127 iBtConnBase = NULL; 00128 } 00129 DisplayError(err); 00130 } 00131 } 00132 00133 /* 00134 ============================================================================ 00135 Quit the game either because the player decided to exit the game (KErrNone) 00136 or because an error occurred during the game 00137 ============================================================================ 00138 */ 00139 void CBluetoothManager::QuitMultiplayerGame() 00140 { 00141 iConnected = EFalse; 00142 00143 if(iBtConnBase) 00144 { 00145 iBtConnBase->Cancel(); 00146 delete iBtConnBase; 00147 iBtConnBase = NULL; 00148 } 00149 } 00150 00151 00152 /* 00153 ============================================================================ 00154 Master kick off the game. 00155 ============================================================================ 00156 */ 00157 void CBluetoothManager::StartGame() 00158 { 00159 //We assume only the Master can start the game since it's the one that controls the game. 00160 ASSERT(iBtConnBase); 00161 ASSERT(iBtConnBase->Master()); 00162 00163 if(iConnected) 00164 { 00165 //Send the control flag EPlay to the slave asking to start the game 00166 TPckgBuf<TRpsData> rpsData; 00167 rpsData().iRpsControl = TRpsData::EPlay; 00168 iBtConnBase->SendData(rpsData); 00169 // Reset the game data before play starts 00170 iGameScreenMgr.Roshambo().ResetPlayers(); 00171 //Show the play screen 00172 iGameScreenMgr.SetGameState(CGameScreenManager::EPlayScreen); 00173 } 00174 } 00175 00176 /* 00177 ============================================================================ 00178 Start another session of the game. 00179 ============================================================================ 00180 */ 00181 void CBluetoothManager::ReplayGame() 00182 { 00183 //Master and Slave restart the game 00184 ASSERT(iBtConnBase); 00185 if(iConnected) 00186 { 00187 if(iBtConnBase->Master()) 00188 { 00189 //Master displays the Start Screen 00190 iGameScreenMgr.SetGameState(CGameScreenManager::EStartScreen); 00191 } 00192 else 00193 { 00194 //Slave displays the Wait Start Screen 00195 iGameScreenMgr.SetGameState(CGameScreenManager::EWaitStartScreen); 00196 } 00197 } 00198 } 00199 00200 /* 00201 ============================================================================ 00202 Send the RPS's player choice to the remote BT device. On completion calls SendDataComplete() 00203 ============================================================================ 00204 */ 00205 void CBluetoothManager::SendData(TRoshambo::TElement aElement) 00206 { 00207 //Note that the code here to send the data to the remote device is the same for the 00208 //Master and slave. Change the code to be like ReplayGame() above if your multiplayer game needs to handle 00209 //the Master and Slave differently. 00210 if(iConnected) 00211 { 00212 TPckgBuf<TRpsData> rpsData; 00213 rpsData().iElement = aElement; 00214 rpsData().iRpsControl = TRpsData::EElement; 00215 00216 //Since the sending is an asynchronous operation we need to cache the local player's choice 00217 iGameScreenMgr.Roshambo().SetLocalPlayer(aElement); 00218 // Now wait for the opponent to choose 00219 iGameScreenMgr.SetGameState(CGameScreenManager::EWaitOpponentScreen); 00220 iBtConnBase->SendData(rpsData); 00221 } 00222 } 00223 00224 /* 00225 ============================================================================ 00226 Query function to see if Master/Slave are connected 00227 ============================================================================ 00228 */ 00229 TBool CBluetoothManager::Connected() 00230 { 00231 return iConnected; 00232 } 00233 00234 /* 00235 ============================================================================ 00236 RNotifier's callback. aResponse contains the player's selected BT device 00237 ============================================================================ 00238 */ 00239 void CBluetoothManager::OnDeviceDiscoveryComplete(const TBTDeviceResponseParamsPckg& aResponse) 00240 { 00241 iGameScreenMgr.SetGameState(CGameScreenManager::EConnectingScreen); 00242 iBtDevAddr = aResponse().BDAddr(); 00243 00244 if(iBtConnBase) 00245 { 00246 iBtConnBase->Cancel(); 00247 delete iBtConnBase; 00248 iBtConnBase = NULL; 00249 } 00250 00251 //It's important to note that in a multiplayer game with more then two players, the engine needs to create an 00252 //array of iBtConnBase, one for each Master<->Slave connection in the BT piconet. The BT piconet contains 00253 //the BT devices (Slaves) selected by the player (Master). RHostResolver needs to be use instead of RNotifier 00254 //if your application needs to select more then two BT devices at one time. A customized UI needs also to be 00255 //implemented to show the player and the available BT devices (s)he can select.The engine needs also to manage 00256 //the bidirectional communication between the Master<->Slaves and SlaveN<->Master<->SlaveM. 00257 00258 TRAPD(err, StartConnectorL()); 00259 if(err != KErrNone) 00260 { 00261 delete iBtConnBase; 00262 iBtConnBase = NULL; 00263 DisplayError(err); 00264 } 00265 } 00266 00267 void CBluetoothManager::StartConnectorL() 00268 { 00269 iBtConnBase = CBluetoothConnector::NewL(*this, iSocketServer, iBtDevAddr); 00270 iBtConnBase->StartL(); 00271 } 00272 /* 00273 ============================================================================ 00274 Callback from CBluetoothDeviceDiscoverer if an error occur during device discovery 00275 ============================================================================ 00276 */ 00277 void CBluetoothManager::OnDeviceDiscoveryErr(const TInt aError) 00278 { 00279 DisplayError(aError); 00280 } 00281 00282 /* 00283 ============================================================================ 00284 Callback either from the Connector or Responder to report a connection error 00285 ============================================================================ 00286 */ 00287 void CBluetoothManager::ConnectionErr(const TInt /*aConnHandle*/, const TInt aError) 00288 { 00289 //See RpsGameEngine.h to see how your multiplayer game could use aConnHandle 00290 if(aError == KErrNone) 00291 { 00292 //KErrNone means succesful connection 00293 iConnected = ETrue; 00294 //Master and Slave need to take different action at this point 00295 ASSERT(iBtConnBase); 00296 if(iBtConnBase->Master()) 00297 { 00298 iGameScreenMgr.SetGameState(CGameScreenManager::EStartScreen); 00299 } 00300 else 00301 { 00302 iGameScreenMgr.SetGameState(CGameScreenManager::EWaitStartScreen); 00303 } 00304 } 00305 else 00306 { 00307 QuitMultiplayerGame(); 00308 DisplayError(aError); 00309 } 00310 } 00311 00312 /* 00313 ============================================================================ 00314 Callback either from the Connector or Responder to report incoming data from the remote BT device 00315 ============================================================================ 00316 */ 00317 void CBluetoothManager::DataReceived(const TInt /*aConnHandle*/, const TDesC8& aData) 00318 { 00319 //See RpsGameEngine.h to see how your multiplayer game could use aConnHandle 00320 TPckgBuf<TRpsData> rpsData; 00321 rpsData.Copy(aData); 00322 if(rpsData().iRpsControl == TRpsData::EPlay) 00323 { 00324 //We assume that only the Responder deals with game's control flags. 00325 ASSERT(!iBtConnBase->Master()); 00326 iGameScreenMgr.Roshambo().ResetPlayers(); 00327 //Start the game by displaying the Play Screen 00328 iGameScreenMgr.SetGameState(CGameScreenManager::EPlayScreen); 00329 } 00330 else if(rpsData().iRpsControl == TRpsData::EElement) 00331 { 00332 TPckgBuf<TRpsData> rpsData; 00333 rpsData.Copy(aData); 00334 if(iGameScreenMgr.Roshambo().LocalPlayer() != TRoshambo::EInvalid) 00335 { 00336 //Player already sent the rps's element, display the result. 00337 iGameScreenMgr.Roshambo().SetOpponent(rpsData().iElement); 00338 iGameScreenMgr.SetGameState(CGameScreenManager::EResultScreen); 00339 } 00340 else 00341 { 00342 //Cache the opponent element and wait for the player 00343 iGameScreenMgr.Roshambo().SetOpponent(rpsData().iElement); 00344 } 00345 } 00346 } 00347 00348 /* 00349 ============================================================================ 00350 Callback either from the Connector or Responder to report the sending data completion 00351 ============================================================================ 00352 */ 00353 void CBluetoothManager::SendDataComplete(const TInt /*aConnHandle*/) 00354 { 00355 //See RpsGameEngine.h to see how your multiplayer game could use aConnHandle 00356 //We already cached the local player's move 00357 if(iGameScreenMgr.Roshambo().Opponent() != TRoshambo::EInvalid) 00358 { 00359 //Opponent already submitted the move, so result can be calculated and displayed 00360 iGameScreenMgr.SetGameState(CGameScreenManager::EResultScreen); 00361 } 00362 } 00363 00364 void CBluetoothManager::DisplayError(TInt aError) 00365 { 00366 iGameScreenMgr.GameData().iRpsError = aError; 00367 iGameScreenMgr.SetGameState(CGameScreenManager::EErrorScreen); 00368 } 00369