locked
How to use CoreAudio API in Metro app

    Question

  • I write a dll for metro app and desktop app use. The function of the DLL is to discovery Audio Device Topology. We use the WASAPI to discovery all Audio Endpoint. In desktop app the dll is function correctly. But in Metro app when we call interface IConnect member function "GetConnectedTo" it always failed. we got follow error. 

    GetLastError = 0x05

    HResult =  0x80070005

    http://msdn.microsoft.com/en-us/library/windows/desktop/dd371061(v=vs.85).aspx

    Does WASAPI is allow to called in Metro app? Does here has any sample code address how to use it in Metro app?

    Please help me!!!!!! Thanks.


    • Edited by Robert.wang Friday, April 13, 2012 11:04 AM
    Friday, April 13, 2012 10:41 AM

Answers

  • Hi Robert,

    Parts of WASAPI can be used in Metro style apps, but not all. If you look at the documentation for the various interfaces each will say which environment it applies to. The DeviceTopology interfaces in general and IConnect::GetConnectedTo in particular say "Applies to: desktop apps only" and so are cannot be successfully called from Metro style apps. Contrast this with IAudioClient which is available to Metro style apps and is marked "Applies to: desktop apps | Metro style apps"

    --Rob

    Friday, April 13, 2012 7:40 PM
    Owner
  • The documentation is correct. This API should be stubbed out and should not return valid data. You shouldn't need to use IMMDevice in the WinRT environment.

    -James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/


    Thursday, April 19, 2012 11:18 PM
    Moderator
  • Hello Robert,

    Yes those are the default. If you want additional properties you need to request them.

    // Create a set of two additional properties.
        var propertiesToRetrieve = new Array();
        propertiesToRetrieve.push("System.Devices.InterfaceClassGuid");
        propertiesToRetrieve.push("System.Devices.ContainerId");
    
        Windows.Devices.Enumeration.findAllAsync(selectorString, 
                 propertiesToRetrieve).then(successCallback, errorCallback);)
    
    // Handles successful completion of the findAllAsync method.
    function successCallback(deviceInformationCollection) {
        var numDevices = deviceInformationCollection.length;
        if (numDevices) {
            for (var i = 0; i < numDevices; i++) {
                printProperties(document.getElementById("log"),
                     deviceInformationCollection[i].properties);
            }
        } 
    }
    
    // Handles an error completion of the findAllAsync method.
    function errorCallback(e) {
        document.getElementById("statusMessage").innerHTML = 
            "Failed to find devices, error: " + e.message;
    }
    
    function printProperties(log, prop) {
        log.innerHTML += "property store count is: " + prop.size;
        var pt = prop.first();
        while (pt.hasCurrent) {
            log.innerHTML += "<br />" + pt.current.key + " := " + pt.current.value;
            pt.moveNext();
        }
        log.innerHTML += "<br />";
    }
    
                                   

    Code above taken from the following page:

    http://msdn.microsoft.com/en-us/library/windows/apps/hh464997.aspx

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Tuesday, May 01, 2012 10:53 PM
    Moderator

All replies

  • Hi Robert,

    Parts of WASAPI can be used in Metro style apps, but not all. If you look at the documentation for the various interfaces each will say which environment it applies to. The DeviceTopology interfaces in general and IConnect::GetConnectedTo in particular say "Applies to: desktop apps only" and so are cannot be successfully called from Metro style apps. Contrast this with IAudioClient which is available to Metro style apps and is marked "Applies to: desktop apps | Metro style apps"

    --Rob

    Friday, April 13, 2012 7:40 PM
    Owner
  • Many  APIs it say "Applies to: desktop apps only" but we still can be successfully called from Metro style apps.

    Example:

    The IMMDeviceEnumerator::EnumAudioEndpoints (IDeviceTopology::GetConnector )method in particular say "Applies to: desktop apps only".

    Is this wrote the wrong word on document??

    http://msdn.microsoft.com/en-us/library/windows/desktop/dd371400(v=vs.85).aspx




    • Edited by Robert.wang Wednesday, April 18, 2012 2:14 AM
    Wednesday, April 18, 2012 2:07 AM
  • I am confused.

    The method  IMMDevice::Activate in particular say "Applies to:desktop apps only".

    But IAudioEndpointVolume in particular say  Applies to: desktop apps | Metro style apps

    IMMDevice *pDevice=NULL; 

    hr=pDevice->Activate(__uuidof(IAudioEndpointVolume),CLSCTX_ALL,NULL,(void **)(&pVolumeAPI));  

    if IMMDevice::Activate  can not be used, how can we get IAudioEndpointVolume  interface ?




    • Edited by Robert.wang Thursday, April 19, 2012 7:32 AM
    Wednesday, April 18, 2012 2:43 AM
  • The documentation is correct. This API should be stubbed out and should not return valid data. You shouldn't need to use IMMDevice in the WinRT environment.

    -James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/


    Thursday, April 19, 2012 11:18 PM
    Moderator
  • You can get the underlying audio endpoint but you must use the WinRT APIs to access the device.

    Platform::String^ id = Windows::Media::Devices::MediaDevice::GetDefaultAudioCaptureId(Windows::Media::Devices::AudioDeviceRole::Console );
     
    Microsoft::WRL::ComPtr<IAudioClient> pAudioClient = NULL;
     
    ActivateAudioInterface( id->Data(), __uuidof( IAudioClient ), (void**)&pAudioClient );

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Thursday, April 19, 2012 11:28 PM
    Moderator
  • Thanks for your help~~

    BUT my DLL is not WinRT DLL ,and we use Win32 DLL to get IMMDevice interface. Is it possibly(use LoadPackageLibrary)?



    And if we want change to WinRT DLL did you have more sample code about Core audio use WinRT APIs ?

    Ex:

    1.IPropertyStore GetValue/SetValue for APO(custome effect).

    hr = pDevice->OpenPropertyStore(STGM_READ,&pProperties);  
    PROPVARIANT varName;  
    PropVariantInit(&varName);  
    hr = pProperties->GetValue(PKEY_APO_KEY, &varName);  

    2.if our audio device is not default could we control it?

    3.if we have 2  or more audio endpoints  could we streaming to not default default device? 



    Friday, April 20, 2012 1:36 AM
  • 1) You can only load your DLL from Metro if it doesn't use any APIs that are explicitly banned for use in the Metro environment. Most of the time you will need to modify your DLL so that it uses only the APIs that are allowed from the Metro environment.

    2) You can choose what audio device endpoint to instantiate at runtime. You do not have to use the default device. See the following link for more information: http://msdn.microsoft.com/en-us/library/windows/apps/hh464974.aspx

    3) I apologize but I don't understand this question. Please rephrase it and I will do what I can to answer it for you.

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Monday, April 23, 2012 9:33 PM
    Moderator
  • thanks James~

    Yes, we can use " FindAllAsync" to enumerate the audio endpoint but i got another problem.

    1.Before ActivateAudioInterface i want get a symbolic link to call CreateDeviceAccessInstance to specific our device and now i can not get enough information in DeviceInformationCollection  interface.

    2.I can not get endpoint type in DeviceInformationCollection  interface.

    example : Line in ,Mic ,Sperker, Headphone.

    Any information you can provide me would be greatly appreciated.


    Thursday, April 26, 2012 3:14 AM
  • Hello Robert,

    How are you checking for the endpoint type? Are you enumerating through the properties? Is this information not included?

    DeviceInformation.Properties
    http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.enumeration.deviceinformation.properties.aspx

    -James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Friday, April 27, 2012 11:28 PM
    Moderator
  • We had check that "DeviceInformation.Properties" is not include endpoint type.

    Enumerating through the properties as below.

    System.Devices.Icon

    System.ItemNameDisplay

    System.Devices.IsDefault

    System.Devices.DeviceInstanceID

    System.Devices.InterfaceEnable

     

    Monday, April 30, 2012 2:35 AM
  • Hello Robert,

    Yes those are the default. If you want additional properties you need to request them.

    // Create a set of two additional properties.
        var propertiesToRetrieve = new Array();
        propertiesToRetrieve.push("System.Devices.InterfaceClassGuid");
        propertiesToRetrieve.push("System.Devices.ContainerId");
    
        Windows.Devices.Enumeration.findAllAsync(selectorString, 
                 propertiesToRetrieve).then(successCallback, errorCallback);)
    
    // Handles successful completion of the findAllAsync method.
    function successCallback(deviceInformationCollection) {
        var numDevices = deviceInformationCollection.length;
        if (numDevices) {
            for (var i = 0; i < numDevices; i++) {
                printProperties(document.getElementById("log"),
                     deviceInformationCollection[i].properties);
            }
        } 
    }
    
    // Handles an error completion of the findAllAsync method.
    function errorCallback(e) {
        document.getElementById("statusMessage").innerHTML = 
            "Failed to find devices, error: " + e.message;
    }
    
    function printProperties(log, prop) {
        log.innerHTML += "property store count is: " + prop.size;
        var pt = prop.first();
        while (pt.hasCurrent) {
            log.innerHTML += "<br />" + pt.current.key + " := " + pt.current.value;
            pt.moveNext();
        }
        log.innerHTML += "<br />";
    }
    
                                   

    Code above taken from the following page:

    http://msdn.microsoft.com/en-us/library/windows/apps/hh464997.aspx

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Tuesday, May 01, 2012 10:53 PM
    Moderator
  • Thanks~I can get endpoint type.

    I use FindAllAsync api to enumeration audio interface but it only can get enable endpoint.(Paramter:DeviceClass.AudioRender)

    But i also need to get Device (active & Unplugged & disable ).

    How can i do that??


     

    Wednesday, May 09, 2012 10:05 AM
  • Hello Robert, I’m not sure that I understand what data you are looking for. If it doesn't exist when using "find all async" I'm not sure that the data exists at the metro level. However, If I understand your question correctly  using the DeviceWatcher class may give you the information you are looking for.

    DeviceWatcher class
    http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.enumeration.devicewatcher.aspx

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Wednesday, May 09, 2012 9:06 PM
    Moderator