diff --git a/src/api/Inc/FeatureStaging-MIDI2.h b/src/api/Inc/Feature_Servicing_MIDI2DriverHang.h similarity index 92% rename from src/api/Inc/FeatureStaging-MIDI2.h rename to src/api/Inc/Feature_Servicing_MIDI2DriverHang.h index 55ae6d41b..3ca83bc50 100644 --- a/src/api/Inc/FeatureStaging-MIDI2.h +++ b/src/api/Inc/Feature_Servicing_MIDI2DriverHang.h @@ -8,11 +8,11 @@ #pragma once -class Feature_MIDI2 +class Feature_Servicing_MIDI2DriverHang { public: static bool IsEnabled() { return true; } -}; \ No newline at end of file +}; diff --git a/src/api/Inc/MidiKS.h b/src/api/Inc/MidiKS.h index 7f9af9f0a..83ef9a735 100644 --- a/src/api/Inc/MidiKS.h +++ b/src/api/Inc/MidiKS.h @@ -89,6 +89,8 @@ class KSMidiDevice unique_mmcss_handle m_MmcssHandle; DWORD m_MmcssTaskId {0}; + + KSSTATE m_CurrentState {KSSTATE_STOP}; }; class KSMidiOutDevice : public KSMidiDevice diff --git a/src/api/Libs/MidiKs/MidiKs.cpp b/src/api/Libs/MidiKs/MidiKs.cpp index 78c9ebea6..124b3ec93 100644 --- a/src/api/Libs/MidiKs/MidiKs.cpp +++ b/src/api/Libs/MidiKs/MidiKs.cpp @@ -24,6 +24,7 @@ #include "MidiXProc.h" #include "MidiKs.h" #include "Feature_Servicing_MIDI2DeviceRemoval.h" +#include "Feature_Servicing_MIDI2DriverHang.h" KSMidiDevice::~KSMidiDevice() { @@ -431,6 +432,11 @@ KSMidiDevice::PinSetState( nullptr); })); + if (Feature_Servicing_MIDI2DriverHang::IsEnabled()) + { + m_CurrentState = pinState; + } + return S_OK; } @@ -739,6 +745,19 @@ KSMidiInDevice::Shutdown() if (m_ThreadHandle) { + if (Feature_Servicing_MIDI2DriverHang::IsEnabled()) + { + // If we have a worker thread (standard bytestream), and the pin is open and running + // pause the pin prior to stopping the worker thread. This works around an issue + // with some drivers cloning stream pointers and not registering for a cancel callback, + // which results in their IRP not being completed. Pausing before terminating the worker thread + // deletes the stream pointers to get a good cleanup, working around the driver issue. + if (m_PinHandleWrapper && m_PinHandleWrapper->IsOpen() && m_CurrentState == KSSTATE_RUN) + { + RETURN_IF_FAILED(PinSetState(KSSTATE_PAUSE)); + } + } + // First shut down the worker thread so it will not // attempt to use the pin/filter/swr lock after they've // been cleaned up by the base clase. diff --git a/src/api/Service/Exe/MidiSessionTracker.cpp b/src/api/Service/Exe/MidiSessionTracker.cpp index b6fb9c968..eed840bff 100644 --- a/src/api/Service/Exe/MidiSessionTracker.cpp +++ b/src/api/Service/Exe/MidiSessionTracker.cpp @@ -8,7 +8,6 @@ #include "stdafx.h" #include -#include _Use_decl_annotations_ @@ -99,7 +98,7 @@ CMidiSessionTracker::VerifyConnectivity() ); // if this gets called, we have connectivity - return (BOOL) Feature_MIDI2::IsEnabled(); + return TRUE; } _Use_decl_annotations_ diff --git a/src/api/Test/Libs/MidiTestCommon/MidiTestCommon.cpp b/src/api/Test/Libs/MidiTestCommon/MidiTestCommon.cpp index e7c2a5192..88aba5cdf 100644 --- a/src/api/Test/Libs/MidiTestCommon/MidiTestCommon.cpp +++ b/src/api/Test/Libs/MidiTestCommon/MidiTestCommon.cpp @@ -20,7 +20,6 @@ #include "MidiDefs.h" -#include "FeatureStaging-MIDI2.h" #include "Feature_Servicing_MIDI2WaveAPIFix.h" #include "Feature_Servicing_MIDI2SendTimeout.h" #include "Feature_Servicing_MIDI2DeviceRemoval.h" @@ -34,6 +33,7 @@ #include "Feature_Servicing_MIDI2RTTimestamp.h" #include "Feature_Servicing_MIDI2WinmmAddBufferSizeCheck.h" #include "Feature_Servicing_MIDI2ContainerIds.h" +#include "Feature_Servicing_MIDI2DriverHang.h" using unique_hdevinfo = wil::unique_any_handle_invalid; @@ -106,7 +106,6 @@ void PrintMidiMessage(PVOID payload, UINT32 payloadSize, UINT32 expectedPayloadS void PrintStagingStates() { // 2602 - LOG_FEATURE_STATE(Feature_MIDI2); LOG_FEATURE_STATE(Feature_Servicing_MIDI2WaveAPIFix); LOG_FEATURE_STATE(Feature_Servicing_MIDI2SendTimeout); LOG_FEATURE_STATE(Feature_Servicing_MIDI2DeviceRemoval); @@ -122,6 +121,7 @@ void PrintStagingStates() LOG_FEATURE_STATE(Feature_Servicing_MIDI2RTTimestamp); LOG_FEATURE_STATE(Feature_Servicing_MIDI2WinmmAddBufferSizeCheck); LOG_FEATURE_STATE(Feature_Servicing_MIDI2ContainerIds); + LOG_FEATURE_STATE(Feature_Servicing_MIDI2DriverHang); } HRESULT StartMIDIService()