0

Here's a very simple program using the function:

#include <windows.h>
#include <tchar.h>
#include <atlstr.h>
#include <mmdeviceapi.h>
#include <devicetopology.h>
#include <functiondiscoverykeys.h>

#include <iostream>

using namespace std;

int main()
{
    HRESULT hr;
    CComPtr<IMMDeviceEnumerator> pMMDeviceEnumerator;
    pMMDeviceEnumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, 0);
    //cout << hr;
    return 0;
}

When I try to run this, I get the following error:

Debug Assertion Failed!

Program: ...
File: c:\program files\microsoft visual studio 8\vc\atlmfc\include\atlcomcli.h
Line: 154

Expression: p!=0

What's wrong with this? I'm just now trying to learn how to use this function. Thanks!


EDIT:

I've changed the program to this:

//#include <windows.h>
//#include <tchar.h>

#include <atlstr.h>
#include <mmdeviceapi.h>
//#include <devicetopology.h>
//#include <functiondiscoverykeys.h>

#include <iostream>

using namespace std;

// helper class to CoInitialize/CoUninitialize
class CCoInitialize {
private:
    HRESULT m_hr;
public:
    CCoInitialize(PVOID pReserved, HRESULT &hr)
        : m_hr(E_UNEXPECTED) { hr = m_hr = CoInitialize(pReserved); }
    ~CCoInitialize() { if (SUCCEEDED(m_hr)) { CoUninitialize(); } }
};

int main()
{


    CComPtr<IMMDeviceEnumerator> pMMDeviceEnumerator;
HRESULT hr = pMMDeviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
if (FAILED(hr)) {
    cout << "failed" << endl;
    return __LINE__;
    }

CCoInitialize ci(NULL, hr);
pMMDeviceEnumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, 0);
//cout << hr;
return 0;
}

When I run it, I get the output of "failed". What's happening?


EDIT:

Alright, now I've changed the code enough to get it running all the way through without any failures. i.e.,

HRESULT hr = S_OK;  
cout << hr;
// initialize COM
CCoInitialize ci(NULL, hr);
if (FAILED(hr)) {
    cout << "failed1" << endl;
    return __LINE__;
}
cout << hr;
// get enumerator
CComPtr<IMMDeviceEnumerator> pMMDeviceEnumerator;
hr = pMMDeviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
if (FAILED(hr)) {
    cout << "failed2" << endl;
    return __LINE__;
}
cout << hr;
// get default render/capture endpoints
CComPtr<IMMDevice> pRenderEndpoint;
hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pRenderEndpoint);
if (FAILED(hr)) {
    cout << "failed3" << endl;
    return __LINE__;
}

cout << hr;
return 0;

Some of the trouble I was having earlier with this example (see comments on the answers) was fixed just by removing some of the code. But as I run this new body of the main() function, I get the output "0000", meaning that cout << hr always evaluates to "0". Is this a good thing? What info can I get about the default device now? hr. and hr-> don't really bring up any menus, so I'm kind of in the dark. Thanks!

Panzercrisis
  • 4,590
  • 6
  • 46
  • 85

1 Answers1

1

pMMDeviceEnumerator variable holds a pointer, which is NULL. When you try to call an interface method on this pointer, -> operator checks this nullness and issues an assertion failure.

Windows SDK samples show how to use this function and API, check them under: \Samples\multimedia\audio, e.g. osd sample.

This sample is a Win32-based application that demonstrates the use of the Vista APIs for monitoring the default audio output device and its current volume setting. The sample is written in C++.

OSD does not run on earlier versions of Windows, including Windows XP, Windows 2000, Windows Me, and Windows 98.

UPD: Things in main one needs to reach the GetDefaultAudioEndpoint API call - Sample: find out if your default audio playback and audio capture devices are on the same hardware.

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • I don't have that folder. Is there just a couple of lines of code that could be changed real quick to make it work? – Panzercrisis Mar 19 '12 at 14:11
  • Check this out: http://blogs.msdn.com/b/matthew_van_eerde/archive/2008/06/13/sample-find-out-if-your-default-playback-and-capture-devices-are-on-the-same-hardware.aspx This is a small code snippet and it has everything that should go in `main` above the `GetDefaultAudioEndpoint` call you want. – Roman R. Mar 19 '12 at 14:16
  • Unfortunately upon trying to build his project, I get an error in atlbase.h. 'CLSID_StdGlobalInterfaceTable' : undeclared identifier c:\program files\microsoft visual studio 8\vc\atlmfc\include\atlbase.h 2782 – Panzercrisis Mar 19 '12 at 14:21
  • Just check what he's doing with `pMMDeviceEnumerator`, in particular `CoInitialize` and `CoCreateInstance` calls. – Roman R. Mar 19 '12 at 14:23
  • Zero `hr` means the method call was successful. Your `pRenderEndpoint` holds a pointer through which you can continue the actual enumeration. – Roman R. Mar 19 '12 at 15:28
  • Thanks for the help, man. This will hopefully be the last question. What's a good way to get device information from that? – Panzercrisis Mar 19 '12 at 15:40
  • `IMMDevice` is a value (pointer to object) which corresponds to certain device/endpoint. So you can call certain methods and query for information. One of the properties, for example, which might be of your interest is `PKEY_DeviceInterface_FriendlyName` which gets you a friendly name. You need to open device's property store and read this property. MSDN gives you another code snippet how to do this: http://msdn.microsoft.com/en-us/library/windows/desktop/dd370812%28v=vs.85%29.aspx Another thing I can provide you with is an utility which enumerates these properties http://alax.info/blog/1279 – Roman R. Mar 19 '12 at 15:50
  • I saw your new question, so the answer is there http://stackoverflow.com/questions/9773358/how-do-i-get-information-out-of-immdevice/9773479#9773479 – Roman R. Mar 19 '12 at 15:57