///////////////////////////////////////////////////////////////////////////////
// GetInputJack() -- Gets the IPart interface for the input jack on the
//                   specified device.
///////////////////////////////////////////////////////////////////////////////
HRESULT GetInputJack(IMMDevice* pDevice, CComPtr<IPart>& spPart)
{
    HRESULT hr = S_OK;

    if (pDevice == NULL)
        return E_POINTER;

    CComPtr<IDeviceTopology>    spTopology;
    CComPtr<IConnector>         spPlug;
    CComPtr<IConnector>         spJack = NULL;

    // Get the Device Topology interface
    hr = pDevice->Activate(__uuidof(IDeviceTopology), 
                                  CLSCTX_INPROC_SERVER, NULL,
                                  reinterpret_cast<void**>(&spTopology));
    IF_FAILED_RETURN(hr);

    hr = spTopology->GetConnector(0, &spPlug);
    IF_FAILED_RETURN(hr);

    hr = spPlug->GetConnectedTo(&spJack);
    IF_FAILED_RETURN(hr);

    // QI for the part
    spPart = spJack;
    if (spPart == NULL)
        return E_NOINTERFACE;
    
    return hr;
}// GetInputJack()
///////////////////////////////////////////////////////////////////////////////
//
// Function:
//      GetDeviceNum
//
// Description:
//      Enumerate audio device and return the device information.
//
//  Parameters:
//      eDataFlow: eRender for render device, eCapture for capture device
//      uDevCount: Number of device
//
// Return:
//      S_OK if successful
//
///////////////////////////////////////////////////////////////////////////////
HRESULT GetDeviceNum(EDataFlow eDataFlow, UINT &uDevCount)
{
    HRESULT hResult = S_OK;

    CComPtr<IMMDeviceEnumerator> spEnumerator;
    CComPtr<IMMDeviceCollection> spEndpoints;    

    hResult = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_RETURN(hResult);

    hResult = spEnumerator->EnumAudioEndpoints(eDataFlow, DEVICE_STATE_ACTIVE, &spEndpoints);
    IF_FAILED_RETURN(hResult);

    hResult = spEndpoints->GetCount(&uDevCount);
    IF_FAILED_RETURN(hResult);

    return hResult;

}
///////////////////////////////////////////////////////////////////////////////
// Function:
//      DeviceIsMicArray
//
// Description:
//      Determines if a given IMMDevice is a microphone array by device ID
//
// Returns:
//      S_OK on success
///////////////////////////////////////////////////////////////////////////////
HRESULT DeviceIsMicArray(wchar_t szDeviceId[], bool &bIsMicArray)
{
    HRESULT hr = S_OK;
    
    if (szDeviceId == NULL)
        return E_INVALIDARG;
   
    CComPtr<IMMDeviceEnumerator> spEnumerator;
    CComPtr<IMMDevice> spDevice;

    hr = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_RETURN(hr);

    hr = spEnumerator->GetDevice(szDeviceId, &spDevice);
    IF_FAILED_RETURN(hr);

    hr = EndpointIsMicArray(spDevice, bIsMicArray);

    return hr;
}
Example #4
0
HRESULT CameraMoveTool::ProcessEvent(UserInputEvent &evnt)
{
	HRESULT hr = S_OK;
	
	ShowCursor(true);

	// Cancel dragging
	if (evnt.buttons == 0)
	{
		m_IsDragging = false;
	}

	// Store screen midpoint or the last dragged position
	if (evnt.eventType == UserEventType::UET_DRAG)
	{
		m_IsDragging = true;

		m_ClickPoint.x = evnt.x;
		m_ClickPoint.y = evnt.y;
	}

	// Compute the difference based on the last dragged position
	if (evnt.eventType == UserEventType::UET_MOVE)
	{
		if (m_IsDragging)
		{
			// Check for imidiate changes in direction
			if (abs(((FLOAT)evnt.x - (FLOAT)m_ClickPoint.x ) / ((FLOAT)m_LastPoint.x - (FLOAT)m_ClickPoint.x)) < 1.0f)
			{
				m_ClickPoint.x = evnt.x;
			}

			if (abs(((FLOAT)evnt.y - (FLOAT)m_ClickPoint.y ) / ((FLOAT)m_LastPoint.y - (FLOAT)m_ClickPoint.y)) < 1.0f)
			{
				m_ClickPoint.y = evnt.y;
			}

			int xDelta = evnt.x - m_ClickPoint.x;
			int yDelta = evnt.y - m_ClickPoint.y;
	
			SmartPtr<ISceneObjectCamera> spCamera;
			hr = GetCameraFromViewController(evnt.spView, &spCamera);
			
			if (SUCCEEDED(hr))
			{	
				if (evnt.buttons & MK_LBUTTON )
				{
					// Change rotation
					hr = spCamera->Look((0.0001f * xDelta), (0.0001f * yDelta), 0.0f, 0.000f);
                    IF_FAILED_RETURN(hr);
				}
				if (evnt.buttons & MK_RBUTTON)
				{
					// Move forward and backward
					hr = spCamera->Move(0.001f * yDelta, 0.001f * xDelta, 0.0f);
                    IF_FAILED_RETURN(hr);
				}
			}
		}
	}

	if (evnt.eventType == UserEventType::UET_WHEEL)
	{
		SmartPtr<ISceneObjectCamera> spCamera;
		hr = GetCameraFromViewController(evnt.spView, &spCamera);
			
		if (SUCCEEDED(hr))
		{	
			float camScaleDelta = -0.5f;
			if (evnt.z < 0)
				camScaleDelta = 0.5f;
		
			if (evnt.buttons & MK_LBUTTON)
			{
				// Move up and down
				hr = spCamera->Move(0.0f, 0.0f, -camScaleDelta);
			}
			else
			{
				// Change scale
				hr = spCamera->Look(0.0f, 0.0f, 0.0f, camScaleDelta);
			}
		}
	}

	m_LastPoint.x = evnt.x;
	m_LastPoint.y = evnt.y;

	return hr;
}
///////////////////////////////////////////////////////////////////////////////
// Function:
//      GetMicArrayGeometry()
//
// Description:
//      Obtains the geometry for the specified mic array.
//
// Parameters:  szDeviceId -- The requested device ID, which can be obtained
//                            from calling EnumAudioCaptureDevices()
//              
//              ppGeometry -- Address of the pointer to the mic-array gemometry.  
//                            Caller is ressponsible for calling CoTaskMemFree()
//                            if the call is successfull.
//
//              cbSize -- size of the geometry structure
//
// Returns:     S_OK on success
///////////////////////////////////////////////////////////////////////////////
HRESULT GetMicArrayGeometry(wchar_t szDeviceId[], KSAUDIO_MIC_ARRAY_GEOMETRY** ppGeometry, ULONG& cbSize)
{
    HRESULT hr = S_OK;

    if (szDeviceId == NULL)
        return E_INVALIDARG;
    if (ppGeometry == NULL)
        return E_POINTER;
   
    cbSize = 0;
    CComPtr<IMMDeviceEnumerator> spEnumerator;
    CComPtr<IMMDevice>           spDevice;
    CComQIPtr<IPart>             spPart;
    bool bIsMicArray;

    hr = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_RETURN(hr);

    hr = spEnumerator->GetDevice(szDeviceId, &spDevice);
    IF_FAILED_RETURN(hr);

    hr = EndpointIsMicArray(spDevice, bIsMicArray);
    IF_FAILED_RETURN(hr);

    if (!bIsMicArray)
        return E_FAIL;
    
    UINT nPartId = 0;
    hr = GetInputJack(spDevice, spPart);
    IF_FAILED_RETURN(hr);

    hr = spPart->GetLocalId(&nPartId);
    IF_FAILED_RETURN(hr);

    CComPtr<IDeviceTopology>     spTopology;
    CComPtr<IMMDeviceEnumerator> spEnum;
    CComPtr<IMMDevice>           spJackDevice;
    CComPtr<IKsControl>          spKsControl;
    wchar_t *                    pwstrDevice = 0;

    // Get the topology object for the part
    hr = spPart->GetTopologyObject(&spTopology);
    IF_FAILED_RETURN(hr);

    // Get the id of the IMMDevice that this topology object describes.
    hr = spTopology->GetDeviceId(&pwstrDevice);
    IF_FAILED_RETURN(hr);

    // Get an IMMDevice pointer using the ID
    hr = spEnum.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_JUMP(hr, Exit);

    hr = spEnum->GetDevice(pwstrDevice, &spJackDevice);
    IF_FAILED_JUMP(hr, Exit);

    // Activate IKsControl on the IMMDevice
    hr = spJackDevice->Activate(__uuidof(IKsControl), CLSCTX_INPROC_SERVER, 
                               NULL, reinterpret_cast<void**>(&spKsControl));
    IF_FAILED_JUMP(hr, Exit);

    // At this point we can use IKsControl just as we would use DeviceIoControl
    KSP_PIN ksp;
    ULONG   cbData     = 0;
    ULONG   cbGeometry = 0;

    // Inititialize the pin property
    ::ZeroMemory(&ksp, sizeof(ksp));
    ksp.Property.Set     = KSPROPSETID_Audio;
    ksp.Property.Id      = KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY;
    ksp.Property.Flags   = KSPROPERTY_TYPE_GET;
    ksp.PinId            = nPartId & PARTID_MASK;  

    // Get data size by passing NULL
    hr = spKsControl->KsProperty(reinterpret_cast<PKSPROPERTY>(&ksp), 
                                sizeof(ksp), NULL, 0, &cbGeometry);
    IF_FAILED_JUMP(hr, Exit);
   
    // Allocate memory for the microphone array geometry
    *ppGeometry = reinterpret_cast<KSAUDIO_MIC_ARRAY_GEOMETRY*>
                                   (::CoTaskMemAlloc(cbGeometry));

    if(*ppGeometry == 0)
    {
        hr = E_OUTOFMEMORY;
    }
    IF_FAILED_JUMP(hr, Exit);
   
    // Now retriev the mic-array structure...
    DWORD cbOut = 0;
    hr = spKsControl->KsProperty(reinterpret_cast<PKSPROPERTY>(&ksp), 
                                sizeof(ksp), *ppGeometry, cbGeometry,
                                &cbOut);
    IF_FAILED_JUMP(hr, Exit);
    cbSize = cbGeometry;
   
Exit:
    if(pwstrDevice != 0)
    {
        ::CoTaskMemFree(pwstrDevice);
    }
    return hr;
}//GetMicArrayGeometry()