1 /* 2 * Copyright (C) 2016-2018 Team Kodi 3 * This file is part of Kodi - https://kodi.tv 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * See LICENSES/README.md for more information. 7 */ 8 9 #include "RumbleGenerator.h" 10 11 #include "ServiceBroker.h" 12 #include "games/controllers/Controller.h" 13 #include "games/controllers/ControllerIDs.h" 14 #include "games/controllers/ControllerManager.h" 15 #include "input/joysticks/interfaces/IInputReceiver.h" 16 17 #include <algorithm> 18 19 #define RUMBLE_TEST_DURATION_MS 1000 // Per motor 20 #define RUMBLE_NOTIFICATION_DURATION_MS 300 21 22 // From game.controller.default profile 23 #define WEAK_MOTOR_NAME "rightmotor" 24 25 using namespace KODI; 26 using namespace JOYSTICK; 27 CRumbleGenerator()28CRumbleGenerator::CRumbleGenerator() 29 : CThread("RumbleGenerator"), m_motors(GetMotors(ControllerID())) 30 { 31 } 32 ControllerID() const33std::string CRumbleGenerator::ControllerID() const 34 { 35 return DEFAULT_CONTROLLER_ID; 36 } 37 NotifyUser(IInputReceiver * receiver)38void CRumbleGenerator::NotifyUser(IInputReceiver* receiver) 39 { 40 if (receiver && !m_motors.empty()) 41 { 42 if (IsRunning()) 43 StopThread(true); 44 45 m_receiver = receiver; 46 m_type = RUMBLE_NOTIFICATION; 47 Create(); 48 } 49 } 50 DoTest(IInputReceiver * receiver)51bool CRumbleGenerator::DoTest(IInputReceiver* receiver) 52 { 53 if (receiver && !m_motors.empty()) 54 { 55 if (IsRunning()) 56 StopThread(true); 57 58 m_receiver = receiver; 59 m_type = RUMBLE_TEST; 60 Create(); 61 62 return true; 63 } 64 return false; 65 } 66 Process(void)67void CRumbleGenerator::Process(void) 68 { 69 switch (m_type) 70 { 71 case RUMBLE_NOTIFICATION: 72 { 73 std::vector<std::string> motors; 74 75 if (std::find(m_motors.begin(), m_motors.end(), WEAK_MOTOR_NAME) != m_motors.end()) 76 motors.emplace_back(WEAK_MOTOR_NAME); 77 else 78 motors = m_motors; // Not using default profile? Just rumble all motors 79 80 for (const std::string& motor : motors) 81 m_receiver->SetRumbleState(motor, 1.0f); 82 83 CThread::Sleep(RUMBLE_NOTIFICATION_DURATION_MS); 84 85 if (m_bStop) 86 break; 87 88 for (const std::string& motor : motors) 89 m_receiver->SetRumbleState(motor, 0.0f); 90 91 break; 92 } 93 case RUMBLE_TEST: 94 { 95 for (const std::string& motor : m_motors) 96 { 97 m_receiver->SetRumbleState(motor, 1.0f); 98 99 CThread::Sleep(RUMBLE_TEST_DURATION_MS); 100 101 if (m_bStop) 102 break; 103 104 m_receiver->SetRumbleState(motor, 0.0f); 105 } 106 break; 107 } 108 default: 109 break; 110 } 111 } 112 GetMotors(const std::string & controllerId)113std::vector<std::string> CRumbleGenerator::GetMotors(const std::string& controllerId) 114 { 115 using namespace GAME; 116 117 std::vector<std::string> motors; 118 119 CControllerManager& controllerManager = CServiceBroker::GetGameControllerManager(); 120 ControllerPtr controller = controllerManager.GetController(controllerId); 121 if (controller) 122 controller->GetFeatures(motors, FEATURE_TYPE::MOTOR); 123 124 return motors; 125 } 126