| 
					
				 | 
			
			
				@@ -78,9 +78,6 @@ void RtMidi :: getCompiledApi( std::vector<RtMidi::Api> &apis ) throw() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #if defined(__WINDOWS_MM__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   apis.push_back( WINDOWS_MM ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#if defined(__WINDOWS_KS__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  apis.push_back( WINDOWS_KS ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #if defined(__RTMIDI_DUMMY__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   apis.push_back( RTMIDI_DUMMY ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -108,10 +105,6 @@ void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string clientName, uns 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( api == WINDOWS_MM ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#if defined(__WINDOWS_KS__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( api == WINDOWS_KS ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    rtapi_ = new MidiInWinKS( clientName, queueSizeLimit ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #if defined(__MACOSX_CORE__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( api == MACOSX_CORE ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     rtapi_ = new MidiInCore( clientName, queueSizeLimit ); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -181,10 +174,6 @@ void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string clientName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( api == WINDOWS_MM ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     rtapi_ = new MidiOutWinMM( clientName ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#if defined(__WINDOWS_KS__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( api == WINDOWS_KS ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    rtapi_ = new MidiOutWinKS( clientName ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #if defined(__MACOSX_CORE__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if ( api == MACOSX_CORE ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     rtapi_ = new MidiOutCore( clientName ); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2434,1040 +2423,6 @@ void MidiOutWinMM :: sendMessage( std::vector<unsigned char> *message ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif  // __WINDOWS_MM__ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// *********************************************************************// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// API: WINDOWS Kernel Streaming 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// Written by Sebastien Alaiwan, 2012. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// NOTE BY GARY: much of the KS-specific code below probably should go in a separate file. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// *********************************************************************// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#if defined(__WINDOWS_KS__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <string> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <vector> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <memory> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <stdexcept> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <sstream> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <windows.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <setupapi.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <mmsystem.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include "ks.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include "ksmedia.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define INSTANTIATE_GUID(a) GUID const a = { STATIC_ ## a } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-INSTANTIATE_GUID(GUID_NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-INSTANTIATE_GUID(KSPROPSETID_Pin); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-INSTANTIATE_GUID(KSPROPSETID_Connection); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-INSTANTIATE_GUID(KSPROPSETID_Topology); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-INSTANTIATE_GUID(KSINTERFACESETID_Standard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-INSTANTIATE_GUID(KSMEDIUMSETID_Standard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-INSTANTIATE_GUID(KSDATAFORMAT_TYPE_MUSIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-INSTANTIATE_GUID(KSDATAFORMAT_SUBTYPE_MIDI); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-INSTANTIATE_GUID(KSDATAFORMAT_SPECIFIER_NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#undef INSTANTIATE_GUID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-typedef std::basic_string<TCHAR> tstring; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-inline bool IsValid(HANDLE handle) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return handle != NULL && handle != INVALID_HANDLE_VALUE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class ComException : public std::runtime_error 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  static std::string MakeString(std::string const& s, HRESULT hr) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::stringstream ss; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ss << "(error 0x" << std::hex << hr << ")"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return s + ss.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ComException(std::string const& s, HRESULT hr) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::runtime_error(MakeString(s, hr)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-template<typename TFilterType> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class CKsEnumFilters 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ~CKsEnumFilters() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    DestroyLists(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void EnumFilters(GUID const* categories, size_t numCategories) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    DestroyLists(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (categories == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      throw std::runtime_error("CKsEnumFilters: invalid argument"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Get a handle to the device set specified by the guid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    HDEVINFO hDevInfo = ::SetupDiGetClassDevs(&categories[0], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!IsValid(hDevInfo)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      throw std::runtime_error("CKsEnumFilters: no devices found"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Loop through members of the set and get details for each 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for ( int iClassMember=0; iClassMember++ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        SP_DEVICE_INTERFACE_DATA DID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        DID.cbSize = sizeof(DID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        DID.Reserved = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        bool fRes = ::SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &categories[0], iClassMember, &DID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!fRes) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Get filter friendly name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        HKEY hRegKey = ::SetupDiOpenDeviceInterfaceRegKey(hDevInfo, &DID, 0, KEY_READ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (hRegKey == INVALID_HANDLE_VALUE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          throw std::runtime_error("CKsEnumFilters: interface has no registry"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        char friendlyName[256]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        DWORD dwSize = sizeof friendlyName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        LONG lval = ::RegQueryValueEx(hRegKey, TEXT("FriendlyName"), NULL, NULL, (LPBYTE)friendlyName, &dwSize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ::RegCloseKey(hRegKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (lval != ERROR_SUCCESS) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          throw std::runtime_error("CKsEnumFilters: interface has no friendly name"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Get details for the device registered in this class 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        DWORD const cbItfDetails = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        std::vector<BYTE> buffer(cbItfDetails); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        SP_DEVICE_INTERFACE_DETAIL_DATA* pDevInterfaceDetails = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(&buffer[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        pDevInterfaceDetails->cbSize = sizeof(*pDevInterfaceDetails); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        SP_DEVINFO_DATA DevInfoData; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        DevInfoData.cbSize = sizeof(DevInfoData); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        DevInfoData.Reserved = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        fRes = ::SetupDiGetDeviceInterfaceDetail(hDevInfo, &DID, pDevInterfaceDetails, cbItfDetails, NULL, &DevInfoData); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (!fRes) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          throw std::runtime_error("CKsEnumFilters: could not get interface details"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // check additional category guids which may (or may not) have been supplied 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (size_t i=1; i < numCategories; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          SP_DEVICE_INTERFACE_DATA DIDAlias; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          DIDAlias.cbSize = sizeof(DIDAlias); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          DIDAlias.Reserved = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          fRes = ::SetupDiGetDeviceInterfaceAlias(hDevInfo, &DID, &categories[i], &DIDAlias); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (!fRes) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            throw std::runtime_error("CKsEnumFilters: could not get interface alias"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          // Check if the this interface alias is enabled. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (!DIDAlias.Flags || (DIDAlias.Flags & SPINT_REMOVED)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            throw std::runtime_error("CKsEnumFilters: interface alias is not enabled"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        std::auto_ptr<TFilterType> pFilter(new TFilterType(pDevInterfaceDetails->DevicePath, friendlyName)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        pFilter->Instantiate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        pFilter->FindMidiPins(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        pFilter->Validate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        m_Filters.push_back(pFilter.release()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      catch (std::runtime_error const& e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ::SetupDiDestroyDeviceInfoList(hDevInfo); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void DestroyLists() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (size_t i=0;i < m_Filters.size();++i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      delete m_Filters[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    m_Filters.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // TODO: make this private. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::vector<TFilterType*> m_Filters; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class CKsObject 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsObject(HANDLE handle) : m_handle(handle) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-protected: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  HANDLE m_handle; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void SetProperty(REFGUID guidPropertySet, ULONG nProperty, void* pvValue, ULONG cbValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    KSPROPERTY ksProperty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    memset(&ksProperty, 0, sizeof ksProperty); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksProperty.Set = guidPropertySet; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksProperty.Id = nProperty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksProperty.Flags = KSPROPERTY_TYPE_SET; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    HRESULT hr = DeviceIoControlKsProperty(ksProperty, pvValue, cbValue); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (FAILED(hr)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      throw ComException("CKsObject::SetProperty: could not set property", hr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  HRESULT DeviceIoControlKsProperty(KSPROPERTY& ksProperty, void* pvValue, ULONG cbValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ULONG ulReturned; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return ::DeviceIoControl( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             m_handle, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             IOCTL_KS_PROPERTY, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             &ksProperty, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             sizeof(ksProperty), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             pvValue, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             cbValue, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             &ulReturned, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-             NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class CKsPin; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class CKsFilter : public CKsObject 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  friend class CKsPin; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsFilter(tstring const& name, std::string const& sFriendlyName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  virtual ~CKsFilter(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  virtual void Instantiate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  template<typename T> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  T GetPinProperty(ULONG nPinId, ULONG nProperty) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ULONG ulReturned = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    T value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    KSP_PIN ksPProp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksPProp.Property.Set = KSPROPSETID_Pin; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksPProp.Property.Id = nProperty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksPProp.Property.Flags = KSPROPERTY_TYPE_GET; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksPProp.PinId = nPinId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksPProp.Reserved = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    HRESULT hr = ::DeviceIoControl( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      m_handle, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      IOCTL_KS_PROPERTY, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      &ksPProp, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      sizeof(KSP_PIN), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      &value, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      sizeof(value), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      &ulReturned, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (FAILED(hr)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      throw ComException("CKsFilter::GetPinProperty: failed to retrieve property", hr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void GetPinPropertyMulti(ULONG nPinId, REFGUID guidPropertySet, ULONG nProperty, PKSMULTIPLE_ITEM* ppKsMultipleItem) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    HRESULT hr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    KSP_PIN ksPProp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksPProp.Property.Set = guidPropertySet; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksPProp.Property.Id = nProperty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksPProp.Property.Flags = KSPROPERTY_TYPE_GET; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksPProp.PinId = nPinId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ksPProp.Reserved = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ULONG cbMultipleItem = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    hr = ::DeviceIoControl(m_handle, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        IOCTL_KS_PROPERTY, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        &ksPProp.Property, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        sizeof(KSP_PIN), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        NULL, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        &cbMultipleItem, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (FAILED(hr)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      throw ComException("CKsFilter::GetPinPropertyMulti: cannot get property", hr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    *ppKsMultipleItem = (PKSMULTIPLE_ITEM) new BYTE[cbMultipleItem]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ULONG ulReturned = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    hr = ::DeviceIoControl( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        m_handle, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        IOCTL_KS_PROPERTY, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        &ksPProp, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        sizeof(KSP_PIN), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        (PVOID)*ppKsMultipleItem, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        cbMultipleItem, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        &ulReturned, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (FAILED(hr)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      throw ComException("CKsFilter::GetPinPropertyMulti: cannot get property", hr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::string const& GetFriendlyName() const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return m_sFriendlyName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-protected: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::vector<CKsPin*> m_Pins; // this list owns the pins. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::vector<CKsPin*> m_RenderPins; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::vector<CKsPin*> m_CapturePins; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::string const m_sFriendlyName; // friendly name eg "Virus TI Synth" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  tstring const m_sName; // Filter path, eg "\\?\usb#vid_133e&pid_0815...\vtimidi02" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class CKsPin : public CKsObject 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsPin(CKsFilter* pFilter, ULONG nId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  virtual ~CKsPin(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  virtual void Instantiate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void ClosePin(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void SetState(KSSTATE ksState); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void WriteData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void ReadData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  KSPIN_DATAFLOW GetDataFlow() const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return m_DataFlow; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool IsSink() const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return m_Communication == KSPIN_COMMUNICATION_SINK 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      || m_Communication == KSPIN_COMMUNICATION_BOTH; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-protected: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  PKSPIN_CONNECT m_pKsPinConnect;    // creation parameters of pin 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsFilter* const m_pFilter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ULONG m_cInterfaces; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  PKSIDENTIFIER m_pInterfaces; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  PKSMULTIPLE_ITEM m_pmiInterfaces; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ULONG m_cMediums; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  PKSIDENTIFIER m_pMediums; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  PKSMULTIPLE_ITEM m_pmiMediums; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ULONG m_cDataRanges; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  PKSDATARANGE m_pDataRanges; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  PKSMULTIPLE_ITEM m_pmiDataRanges; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  KSPIN_DATAFLOW m_DataFlow; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  KSPIN_COMMUNICATION m_Communication; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CKsFilter::CKsFilter(tstring const& sName, std::string const& sFriendlyName) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsObject(INVALID_HANDLE_VALUE), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_sFriendlyName(sFriendlyName), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_sName(sName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (sName.empty()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    throw std::runtime_error("CKsFilter::CKsFilter: name can't be empty"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CKsFilter::~CKsFilter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (size_t i=0;i < m_Pins.size();++i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    delete m_Pins[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (IsValid(m_handle)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ::CloseHandle(m_handle); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CKsFilter::Instantiate() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_handle = CreateFile( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    m_sName.c_str(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    GENERIC_READ | GENERIC_WRITE, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    NULL, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    OPEN_EXISTING, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!IsValid(m_handle)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    DWORD const dwError = GetLastError(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    throw ComException("CKsFilter::Instantiate: can't open driver", HRESULT_FROM_WIN32(dwError)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CKsPin::CKsPin(CKsFilter* pFilter, ULONG PinId) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsObject(INVALID_HANDLE_VALUE), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect(NULL), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pFilter(pFilter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_Communication = m_pFilter->GetPinProperty<KSPIN_COMMUNICATION>(PinId, KSPROPERTY_PIN_COMMUNICATION); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_DataFlow = m_pFilter->GetPinProperty<KSPIN_DATAFLOW>(PinId, KSPROPERTY_PIN_DATAFLOW); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // Interfaces 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pFilter->GetPinPropertyMulti( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      PinId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      KSPROPSETID_Pin, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      KSPROPERTY_PIN_INTERFACES, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      &m_pmiInterfaces); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_cInterfaces = m_pmiInterfaces->Count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pInterfaces = (PKSPIN_INTERFACE)(m_pmiInterfaces + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // Mediums 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pFilter->GetPinPropertyMulti( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      PinId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      KSPROPSETID_Pin, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      KSPROPERTY_PIN_MEDIUMS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      &m_pmiMediums); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_cMediums = m_pmiMediums->Count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pMediums = (PKSPIN_MEDIUM)(m_pmiMediums + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // Data ranges 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pFilter->GetPinPropertyMulti( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      PinId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      KSPROPSETID_Pin, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      KSPROPERTY_PIN_DATARANGES, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      &m_pmiDataRanges); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_cDataRanges = m_pmiDataRanges->Count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pDataRanges = (PKSDATARANGE)(m_pmiDataRanges + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CKsPin::~CKsPin() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ClosePin(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  delete[] (BYTE*)m_pKsPinConnect; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  delete[] (BYTE*)m_pmiDataRanges; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  delete[] (BYTE*)m_pmiInterfaces; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  delete[] (BYTE*)m_pmiMediums; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CKsPin::ClosePin() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (IsValid(m_handle)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    SetState(KSSTATE_STOP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ::CloseHandle(m_handle); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_handle = INVALID_HANDLE_VALUE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CKsPin::SetState(KSSTATE ksState) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  SetProperty(KSPROPSETID_Connection, KSPROPERTY_CONNECTION_STATE, &ksState, sizeof(ksState)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CKsPin::Instantiate() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!m_pKsPinConnect) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    throw std::runtime_error("CKsPin::Instanciate: abstract pin"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  DWORD const dwResult = KsCreatePin(m_pFilter->m_handle, m_pKsPinConnect, GENERIC_WRITE | GENERIC_READ, &m_handle); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (dwResult != ERROR_SUCCESS) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    throw ComException("CKsMidiCapFilter::CreateRenderPin: Pin instanciation failed", HRESULT_FROM_WIN32(dwResult)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CKsPin::WriteData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  DWORD cbWritten; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  BOOL fRes = ::DeviceIoControl( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    m_handle, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    IOCTL_KS_WRITE_STREAM, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    NULL, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pKSSTREAM_HEADER, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pKSSTREAM_HEADER->Size, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    &cbWritten, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pOVERLAPPED); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!fRes) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    DWORD const dwError = GetLastError(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (dwError != ERROR_IO_PENDING) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      throw ComException("CKsPin::WriteData: DeviceIoControl failed", HRESULT_FROM_WIN32(dwError)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CKsPin::ReadData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  DWORD cbReturned; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  BOOL fRes = ::DeviceIoControl( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    m_handle, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    IOCTL_KS_READ_STREAM, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    NULL, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pKSSTREAM_HEADER, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pKSSTREAM_HEADER->Size, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    &cbReturned, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pOVERLAPPED); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!fRes) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    DWORD const dwError = GetLastError(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (dwError != ERROR_IO_PENDING) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      throw ComException("CKsPin::ReadData: DeviceIoControl failed", HRESULT_FROM_WIN32(dwError)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class CKsMidiFilter : public CKsFilter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void FindMidiPins(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-protected: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiFilter(tstring const& sPath, std::string const& sFriendlyName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class CKsMidiPin : public CKsPin 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiPin(CKsFilter* pFilter, ULONG nId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class CKsMidiRenFilter : public CKsMidiFilter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiRenFilter(tstring const& sPath, std::string const& sFriendlyName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiPin* CreateRenderPin(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void Validate() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (m_RenderPins.empty()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      throw std::runtime_error("Could not find a MIDI render pin"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class CKsMidiCapFilter : public CKsMidiFilter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiCapFilter(tstring const& sPath, std::string const& sFriendlyName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiPin* CreateCapturePin(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void Validate() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (m_CapturePins.empty()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      throw std::runtime_error("Could not find a MIDI capture pin"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CKsMidiFilter::CKsMidiFilter(tstring const& sPath, std::string const& sFriendlyName) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsFilter(sPath, sFriendlyName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CKsMidiFilter::FindMidiPins() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ULONG numPins = GetPinProperty<ULONG>(0, KSPROPERTY_PIN_CTYPES); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (ULONG iPin = 0; iPin < numPins; ++iPin) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      KSPIN_COMMUNICATION com = GetPinProperty<KSPIN_COMMUNICATION>(iPin, KSPROPERTY_PIN_COMMUNICATION); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (com != KSPIN_COMMUNICATION_SINK && com != KSPIN_COMMUNICATION_BOTH) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        throw std::runtime_error("Unknown pin communication value"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      m_Pins.push_back(new CKsMidiPin(this, iPin)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    catch (std::runtime_error const&) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // pin instanciation has failed, continue to the next pin. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_RenderPins.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_CapturePins.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (size_t i = 0; i < m_Pins.size(); ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    CKsPin* const pPin = m_Pins[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (pPin->IsSink()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (pPin->GetDataFlow() == KSPIN_DATAFLOW_IN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        m_RenderPins.push_back(pPin); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        m_CapturePins.push_back(pPin); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (m_RenderPins.empty() && m_CapturePins.empty()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    throw std::runtime_error("No valid pins found on the filter."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CKsMidiRenFilter::CKsMidiRenFilter(tstring const& sPath, std::string const& sFriendlyName) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiFilter(sPath, sFriendlyName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CKsMidiPin* CKsMidiRenFilter::CreateRenderPin() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (m_RenderPins.empty()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    throw std::runtime_error("Could not find a MIDI render pin"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiPin* pPin = (CKsMidiPin*)m_RenderPins[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  pPin->Instantiate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return pPin; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CKsMidiCapFilter::CKsMidiCapFilter(tstring const& sPath, std::string const& sFriendlyName) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiFilter(sPath, sFriendlyName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CKsMidiPin* CKsMidiCapFilter::CreateCapturePin() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (m_CapturePins.empty()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    throw std::runtime_error("Could not find a MIDI capture pin"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiPin* pPin = (CKsMidiPin*)m_CapturePins[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  pPin->Instantiate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return pPin; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CKsMidiPin::CKsMidiPin(CKsFilter* pFilter, ULONG nId) : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsPin(pFilter, nId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  DWORD const cbPinCreateSize = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect = (PKSPIN_CONNECT) new BYTE[cbPinCreateSize]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect->Interface.Set = KSINTERFACESETID_Standard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect->Interface.Flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect->Medium.Set = KSMEDIUMSETID_Standard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect->Medium.Flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect->PinId = nId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect->PinToHandle = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pKsPinConnect->Priority.PrioritySubClass = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // point m_pDataFormat to just after the pConnect struct 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  KSDATAFORMAT* m_pDataFormat = (KSDATAFORMAT*)(m_pKsPinConnect + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pDataFormat->FormatSize = sizeof(KSDATAFORMAT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pDataFormat->Flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pDataFormat->SampleSize = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pDataFormat->Reserved = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pDataFormat->MajorFormat = GUID(KSDATAFORMAT_TYPE_MUSIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pDataFormat->SubFormat = GUID(KSDATAFORMAT_SUBTYPE_MIDI); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  m_pDataFormat->Specifier = GUID(KSDATAFORMAT_SPECIFIER_NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool hasStdStreamingInterface = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool hasStdStreamingMedium = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for ( ULONG i = 0; i < m_cInterfaces; i++ ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (m_pInterfaces[i].Set == KSINTERFACESETID_Standard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        && m_pInterfaces[i].Id == KSINTERFACE_STANDARD_STREAMING) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      hasStdStreamingInterface = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (ULONG i = 0; i < m_cMediums; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (m_pMediums[i].Set == KSMEDIUMSETID_Standard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        && m_pMediums[i].Id == KSMEDIUM_STANDARD_DEVIO) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      hasStdStreamingMedium = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!hasStdStreamingInterface) // No standard streaming interfaces on the pin 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    throw std::runtime_error("CKsMidiPin::CKsMidiPin: no standard streaming interface"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!hasStdStreamingMedium) // No standard streaming mediums on the pin 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    throw std::runtime_error("CKsMidiPin::CKsMidiPin: no standard streaming medium"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool hasMidiDataRange = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  BYTE const* pDataRangePtr = reinterpret_cast<BYTE const*>(m_pDataRanges); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (ULONG i = 0; i < m_cDataRanges; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    KSDATARANGE const* pDataRange = reinterpret_cast<KSDATARANGE const*>(pDataRangePtr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (pDataRange->SubFormat == KSDATAFORMAT_SUBTYPE_MIDI) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      hasMidiDataRange = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pDataRangePtr += pDataRange->FormatSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!hasMidiDataRange) // No MIDI dataranges on the pin 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    throw std::runtime_error("CKsMidiPin::CKsMidiPin: no MIDI datarange"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-struct WindowsKsData 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData() : m_pPin(NULL), m_Buffer(1024), m_hInputThread(NULL) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    memset(&overlapped, 0, sizeof(OVERLAPPED)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    m_hExitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    overlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    m_hInputThread = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ~WindowsKsData() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ::CloseHandle(overlapped.hEvent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ::CloseHandle(m_hExitEvent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  OVERLAPPED overlapped; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsPin* m_pPin; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::vector<unsigned char> m_Buffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::auto_ptr<CKsEnumFilters<CKsMidiCapFilter> > m_pCaptureEnum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::auto_ptr<CKsEnumFilters<CKsMidiRenFilter> > m_pRenderEnum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  HANDLE m_hInputThread; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  HANDLE m_hExitEvent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// *********************************************************************// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// API: WINDOWS Kernel Streaming 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// Class Definitions: MidiInWinKS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// *********************************************************************// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static DWORD WINAPI midiKsInputThread(VOID* pUser) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  MidiInApi::RtMidiInData* data = static_cast<MidiInApi::RtMidiInData*>(pUser); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* apiData = static_cast<WindowsKsData*>(data->apiData); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  HANDLE hEvents[] = { apiData->overlapped.hEvent, apiData->m_hExitEvent }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  while ( true ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    KSSTREAM_HEADER packet; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    memset(&packet, 0, sizeof packet); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    packet.Size = sizeof(KSSTREAM_HEADER); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    packet.PresentationTime.Time = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    packet.PresentationTime.Numerator = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    packet.PresentationTime.Denominator = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    packet.Data = &apiData->m_Buffer[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    packet.DataUsed = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    packet.FrameExtent = apiData->m_Buffer.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    apiData->m_pPin->ReadData(&packet, &apiData->overlapped); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    DWORD dwRet = ::WaitForMultipleObjects(2, hEvents, FALSE, INFINITE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if ( dwRet == WAIT_OBJECT_0 ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // parse packet 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      unsigned char* pData = (unsigned char*)packet.Data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      unsigned int iOffset = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      while ( iOffset < packet.DataUsed ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        KSMUSICFORMAT* pMusic = (KSMUSICFORMAT*)&pData[iOffset]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        iOffset += sizeof(KSMUSICFORMAT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        MidiInApi::MidiMessage message; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        message.timeStamp = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for(size_t i=0;i < pMusic->ByteCount;++i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          message.bytes.push_back(pData[iOffset+i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if ( data->usingCallback ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback)data->userCallback; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          callback(message.timeStamp, &message.bytes, data->userData); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          // As long as we haven't reached our queue size limit, push the message. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if ( data->queue.size < data->queue.ringSize ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            data->queue.ring[data->queue.back++] = message; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if(data->queue.back == data->queue.ringSize) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              data->queue.back = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            data->queue.size++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        iOffset += pMusic->ByteCount; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // re-align on 32 bits 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if ( iOffset % 4 != 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          iOffset += (4 - iOffset % 4); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-MidiInWinKS :: MidiInWinKS( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  initialize( clientName ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void MidiInWinKS :: initialize( const std::string& clientName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = new WindowsKsData; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  apiData_ = (void*)data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  inputData_.apiData = data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  GUID const aguidEnumCats[] = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    { STATIC_KSCATEGORY_AUDIO }, { STATIC_KSCATEGORY_CAPTURE } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_pCaptureEnum.reset(new CKsEnumFilters<CKsMidiCapFilter> ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_pCaptureEnum->EnumFilters(aguidEnumCats, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-MidiInWinKS :: ~MidiInWinKS() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if ( data->m_pPin ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      closePort(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  catch(...) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  delete data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void MidiInWinKS :: openPort( unsigned int portNumber, const std::string portName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size() ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::stringstream ost; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ost << "MidiInWinKS::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    errorString_ = ost.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_pPin = pFilter->CreateCapturePin(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( data->m_pPin == NULL ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::stringstream ost; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ost << "MidiInWinKS::openPort: KS error opening port (could not create pin)"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    errorString_ = ost.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_pPin->SetState(KSSTATE_RUN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  DWORD threadId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_hInputThread = ::CreateThread(NULL, 0, &midiKsInputThread, &inputData_, 0, &threadId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( data->m_hInputThread == NULL ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::stringstream ost; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ost << "MidiInWinKS::openPort: Could not create input thread : Windows error " << GetLastError() << std::endl;; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    errorString_ = ost.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  connected_ = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void MidiInWinKS :: openVirtualPort( const std::string portName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // This function cannot be implemented for the Windows KS MIDI API. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  errorString_ = "MidiInWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-unsigned int MidiInWinKS :: getPortCount() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return (unsigned int)data->m_pCaptureEnum->m_Filters.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-std::string MidiInWinKS :: getPortName(unsigned int portNumber) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::stringstream ost; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ost << "MidiInWinKS::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    errorString_ = ost.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return pFilter->GetFriendlyName(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void MidiInWinKS :: closePort() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  connected_ = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (data->m_hInputThread) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ::SignalObjectAndWait(data->m_hExitEvent, data->m_hInputThread, INFINITE, FALSE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ::CloseHandle(data->m_hInputThread); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (data->m_pPin) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    data->m_pPin->SetState(KSSTATE_PAUSE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    data->m_pPin->SetState(KSSTATE_STOP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    data->m_pPin->ClosePin(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    data->m_pPin = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// *********************************************************************// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// API: WINDOWS Kernel Streaming 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// Class Definitions: MidiOutWinKS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// *********************************************************************// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-MidiOutWinKS :: MidiOutWinKS( const std::string clientName ) : MidiOutApi() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  initialize( clientName ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void MidiOutWinKS :: initialize( const std::string& clientName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = new WindowsKsData; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_pPin = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_pRenderEnum.reset(new CKsEnumFilters<CKsMidiRenFilter> ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  GUID const aguidEnumCats[] = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    { STATIC_KSCATEGORY_AUDIO }, { STATIC_KSCATEGORY_RENDER } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_pRenderEnum->EnumFilters(aguidEnumCats, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  apiData_ = (void*)data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-MidiOutWinKS :: ~MidiOutWinKS() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // Close a connection if it exists. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  closePort(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // Cleanup. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  delete data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void MidiOutWinKS :: openPort( unsigned int portNumber, const std::string portName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::stringstream ost; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ost << "MidiOutWinKS::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    errorString_ = ost.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_pPin = pFilter->CreateRenderPin(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (data->m_pPin == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::stringstream ost; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ost << "MidiOutWinKS::openPort: KS error opening port (could not create pin)"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    errorString_ = ost.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_pPin->SetState(KSSTATE_RUN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  connected_ = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void MidiOutWinKS :: openVirtualPort( const std::string portName ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // This function cannot be implemented for the Windows KS MIDI API. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  errorString_ = "MidiOutWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-unsigned int MidiOutWinKS :: getPortCount() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return (unsigned int)data->m_pRenderEnum->m_Filters.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-std::string MidiOutWinKS :: getPortName( unsigned int portNumber ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size() ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::stringstream ost; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ost << "MidiOutWinKS::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    errorString_ = ost.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return pFilter->GetFriendlyName(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void MidiOutWinKS :: closePort() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  connected_ = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( data->m_pPin ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    data->m_pPin->SetState(KSSTATE_PAUSE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    data->m_pPin->SetState(KSSTATE_STOP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    data->m_pPin->ClosePin(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    data->m_pPin = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void MidiOutWinKS :: sendMessage(std::vector<unsigned char>* pMessage) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::vector<unsigned char> const& msg = *pMessage; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  size_t iNumMidiBytes = msg.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  size_t pos = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // write header 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  KSMUSICFORMAT* pKsMusicFormat = reinterpret_cast<KSMUSICFORMAT*>(&data->m_Buffer[pos]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  pKsMusicFormat->TimeDeltaMs = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  pKsMusicFormat->ByteCount = iNumMidiBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  pos += sizeof(KSMUSICFORMAT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // write MIDI bytes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( pos + iNumMidiBytes > data->m_Buffer.size() ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::stringstream ost; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ost << "KsMidiInput::Write: MIDI buffer too small. Required " << pos + iNumMidiBytes << " bytes, only has " << data->m_Buffer.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    errorString_ = ost.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( data->m_pPin == NULL ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::stringstream ost; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ost << "MidiOutWinKS::sendMessage: port is not open"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    errorString_ = ost.str(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error( RtMidiError::WARNING, errorString_ ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  memcpy(&data->m_Buffer[pos], &msg[0], iNumMidiBytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  pos += iNumMidiBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  KSSTREAM_HEADER packet; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  memset(&packet, 0, sizeof packet); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  packet.Size = sizeof(packet); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  packet.PresentationTime.Time = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  packet.PresentationTime.Numerator = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  packet.PresentationTime.Denominator = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  packet.Data = const_cast<unsigned char*>(&data->m_Buffer[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  packet.DataUsed = ((pos+3)/4)*4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  packet.FrameExtent = data->m_Buffer.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  data->m_pPin->WriteData(&packet, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif  // __WINDOWS_KS__ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //*********************************************************************// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //  API: UNIX JACK 
			 |