#ifndef SMXManager_h #define SMXManager_h #include #include #include #include using namespace std; #include "Helpers.h" #include "../SMX.h" #include "SMXHelperThread.h" namespace SMX { class SMXDevice; class SMXDeviceSearchThreaded; struct SMXControllerState { // True bool m_bConnected[2]; // Pressed panels for player 1 and player 2: uint16_t m_Inputs[2]; }; // This implements the main thread that controller communication and device searching // happens in, finding and opening devices, and running device updates. // // Connected controllers can be accessed with GetDevice(), // This also abstracts controller numbers. GetDevice(SMX_PadNumber_1) will return the // first device that connected, class SMXManager { public: // Our singleton: static shared_ptr g_pSMX; // pCallback is a function to be called when something changes on any device. This allows // efficiently detecting when a panel is pressed or other changes happen. SMXManager(function pCallback); ~SMXManager(); void Shutdown(); shared_ptr GetDevice(int pad); void SetLights(const string sLights[2]); void ReenableAutoLights(); // Run a function in the user callback thread. void RunInHelperThread(function func); private: static DWORD WINAPI ThreadMainStart(void *self_); void ThreadMain(); void AttemptConnections(); void CorrectDeviceOrder(); void SendLightUpdates(); HANDLE m_hThread = INVALID_HANDLE_VALUE; shared_ptr m_hEvent; shared_ptr m_pSMXDeviceSearchThreaded; bool m_bShutdown = false; vector> m_pDevices; // We make user callbacks asynchronously in this thread, to avoid any locking or timing // issues that could occur by calling them in our I/O thread. SMXHelperThread m_UserCallbackThread; // A list of queued lights commands to send to the controllers. This is always sorted // by iTimeToSend. struct PendingCommand { PendingCommand(float fTime): fTimeToSend(fTime) { } double fTimeToSend = 0; string sPadCommand[2]; }; vector m_aPendingLightsCommands; double m_fDelayLightCommandsUntil = 0; }; } #endif