From 518e75ad9b9b5f184cddf487c815707b6f717ead Mon Sep 17 00:00:00 2001 From: Samuel Grossman Date: Sat, 23 Jul 2022 13:18:31 -0700 Subject: [PATCH] Automatically invoke Acquire() on DirectInput device objects when the application attempts certain operations that require acquisition and the application has not explicitly invoke Acquire() previously. --- Include/Xidi/VirtualDirectInputDevice.h | 6 ++++ Source/VirtualDirectInputDevice.cpp | 46 +++++++++++++++++-------- Source/VirtualDirectInputEffect.cpp | 8 ++--- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/Include/Xidi/VirtualDirectInputDevice.h b/Include/Xidi/VirtualDirectInputDevice.h index 8ae4833..a94f290 100644 --- a/Include/Xidi/VirtualDirectInputDevice.h +++ b/Include/Xidi/VirtualDirectInputDevice.h @@ -145,6 +145,12 @@ namespace Xidi // -------- INSTANCE METHODS ----------------------------------------------- // + /// Obtains the force feedback device associated with this controller. + /// If this controller is not yet acquired then an attempt is made to acquire it automatically. + /// @return Pointer to the force feedback device object if successful, `nullptr` otherwise. + Controller::ForceFeedback::Device* AutoAcquireAndGetForceFeedbackDevice(void); + + /// Registers a force feedback effect by adding it to the effect registry. /// Intended to be invoked automaticaly as effects are constructed. /// @param [in] effect Address of the effect object to register. diff --git a/Source/VirtualDirectInputDevice.cpp b/Source/VirtualDirectInputDevice.cpp index 96b5914..a9f5c78 100644 --- a/Source/VirtualDirectInputDevice.cpp +++ b/Source/VirtualDirectInputDevice.cpp @@ -735,6 +735,23 @@ namespace Xidi // -------- INSTANCE METHODS ------------------------------------------- // // See "VirtualDirectInputDevice.h" for documentation. + template Controller::ForceFeedback::Device* VirtualDirectInputDevice::AutoAcquireAndGetForceFeedbackDevice(void) + { + Controller::ForceFeedback::Device* forceFeedbackDevice = controller->ForceFeedbackGetDevice(); + + if (nullptr == forceFeedbackDevice) + { + Message::OutputFormatted(Message::ESeverity::Info, L"Attempting to acquire Xidi virtual controller %u automatically because the application did not do so explicitly.", (1 + controller->GetIdentifier())); + + Acquire(); + forceFeedbackDevice = controller->ForceFeedbackGetDevice(); + } + + return forceFeedbackDevice; + } + + // -------- + template std::optional VirtualDirectInputDevice::IdentifyElement(DWORD dwObj, DWORD dwHow) const { switch (dwHow) @@ -1421,19 +1438,19 @@ namespace Xidi if (nullptr == pdwOut) LOG_INVOCATION_AND_RETURN(DIERR_INVALIDPARAM, kMethodSeverity); - if (false == controller->ForceFeedbackIsRegistered()) + Controller::ForceFeedback::Device* forceFeedbackDevice = AutoAcquireAndGetForceFeedbackDevice(); + if (nullptr == forceFeedbackDevice) LOG_INVOCATION_AND_RETURN(DIERR_NOTEXCLUSIVEACQUIRED, kMethodSeverity); - Controller::ForceFeedback::Device& forceFeedbackDevice = *controller->ForceFeedbackGetDevice(); DWORD forceFeedbackDeviceState = DIGFFS_POWERON; - if (true == forceFeedbackDevice.IsDeviceOutputMuted()) + if (true == forceFeedbackDevice->IsDeviceOutputMuted()) forceFeedbackDeviceState |= DIGFFS_ACTUATORSOFF; else forceFeedbackDeviceState |= DIGFFS_ACTUATORSON; - const bool kDeviceIsEmpty = forceFeedbackDevice.IsDeviceEmpty(); - const bool kDeviceIsPaused = forceFeedbackDevice.IsDeviceOutputPaused(); + const bool kDeviceIsEmpty = forceFeedbackDevice->IsDeviceEmpty(); + const bool kDeviceIsPaused = forceFeedbackDevice->IsDeviceOutputPaused(); if (true == kDeviceIsEmpty) { @@ -1451,7 +1468,7 @@ namespace Xidi if (true == kDeviceIsPaused) forceFeedbackDeviceState |= DIGFFS_PAUSED; - else if (false == forceFeedbackDevice.IsDevicePlayingAnyEffects()) + else if (false == forceFeedbackDevice->IsDevicePlayingAnyEffects()) forceFeedbackDeviceState |= DIGFFS_STOPPED; } @@ -1650,41 +1667,40 @@ namespace Xidi LOG_INVOCATION_AND_RETURN(DIERR_UNSUPPORTED, kMethodSeverity); } - if (false == controller->ForceFeedbackIsRegistered()) + Controller::ForceFeedback::Device* forceFeedbackDevice = AutoAcquireAndGetForceFeedbackDevice(); + if (nullptr == forceFeedbackDevice) LOG_INVOCATION_AND_RETURN(DIERR_NOTEXCLUSIVEACQUIRED, kMethodSeverity); - Controller::ForceFeedback::Device& forceFeedbackDevice = *controller->ForceFeedbackGetDevice(); - switch (dwFlags) { case DISFFC_CONTINUE: Message::Output(Message::ESeverity::Debug, L"Sending force feedback command DISFFC_CONTINUE."); - forceFeedbackDevice.SetPauseState(false); + forceFeedbackDevice->SetPauseState(false); break; case DISFFC_PAUSE: Message::Output(Message::ESeverity::Debug, L"Sending force feedback command DISFFC_PAUSE."); - forceFeedbackDevice.SetPauseState(true); + forceFeedbackDevice->SetPauseState(true); break; case DISFFC_RESET: Message::Output(Message::ESeverity::Debug, L"Sending force feedback command DISFFC_RESET."); - forceFeedbackDevice.Clear(); + forceFeedbackDevice->Clear(); break; case DISFFC_SETACTUATORSOFF: Message::Output(Message::ESeverity::Debug, L"Sending force feedback command DISFFC_SETACTUATORSOFF."); - forceFeedbackDevice.SetMutedState(true); + forceFeedbackDevice->SetMutedState(true); break; case DISFFC_SETACTUATORSON: Message::Output(Message::ESeverity::Debug, L"Sending force feedback command DISFFC_SETACTUATORSON."); - forceFeedbackDevice.SetMutedState(false); + forceFeedbackDevice->SetMutedState(false); break; case DISFFC_STOPALL: Message::Output(Message::ESeverity::Debug, L"Sending force feedback command DISFFC_STOPALL."); - forceFeedbackDevice.StopAllEffects(); + forceFeedbackDevice->StopAllEffects(); break; default: diff --git a/Source/VirtualDirectInputEffect.cpp b/Source/VirtualDirectInputEffect.cpp index ee87ced..67de2f5 100644 --- a/Source/VirtualDirectInputEffect.cpp +++ b/Source/VirtualDirectInputEffect.cpp @@ -238,7 +238,7 @@ namespace Xidi template HRESULT VirtualDirectInputEffect::DownloadInternal(void) { - Controller::ForceFeedback::Device* const forceFeedbackDevice = associatedDevice.GetVirtualController().ForceFeedbackGetDevice(); + Controller::ForceFeedback::Device* const forceFeedbackDevice = associatedDevice.AutoAcquireAndGetForceFeedbackDevice(); if (nullptr == forceFeedbackDevice) return DIERR_NOTEXCLUSIVEACQUIRED; @@ -636,7 +636,7 @@ namespace Xidi if (0 == dwIterations) return DIERR_INVALIDPARAM; - Controller::ForceFeedback::Device* const forceFeedbackDevice = associatedDevice.GetVirtualController().ForceFeedbackGetDevice(); + Controller::ForceFeedback::Device* const forceFeedbackDevice = associatedDevice.AutoAcquireAndGetForceFeedbackDevice(); if (nullptr == forceFeedbackDevice) return DIERR_NOTEXCLUSIVEACQUIRED; @@ -1023,7 +1023,7 @@ namespace Xidi { constexpr Message::ESeverity kMethodSeverity = Message::ESeverity::Info; - Controller::ForceFeedback::Device* const forceFeedbackDevice = associatedDevice.GetVirtualController().ForceFeedbackGetDevice(); + Controller::ForceFeedback::Device* const forceFeedbackDevice = associatedDevice.AutoAcquireAndGetForceFeedbackDevice(); if (nullptr == forceFeedbackDevice) LOG_INVOCATION_AND_RETURN(DIERR_NOTEXCLUSIVEACQUIRED, kMethodSeverity); @@ -1066,7 +1066,7 @@ namespace Xidi { constexpr Message::ESeverity kMethodSeverity = Message::ESeverity::Info; - Controller::ForceFeedback::Device* const forceFeedbackDevice = associatedDevice.GetVirtualController().ForceFeedbackGetDevice(); + Controller::ForceFeedback::Device* const forceFeedbackDevice = associatedDevice.AutoAcquireAndGetForceFeedbackDevice(); if (nullptr == forceFeedbackDevice) LOG_INVOCATION_AND_RETURN(DIERR_NOTEXCLUSIVEACQUIRED, kMethodSeverity);