With C /WinRT the AudioGraphSettings
can be easily initialized with its constructor:
AudioGraphSettings settings(AudioRenderCategory::Media);
I'm having trouble to use it inside my WRL project. Below is my implementation
ComPtr<IAudioGraphSettings> settings;
Windows::Foundation::GetActivationFactory(
HStringReference(RuntimeClass_Windows_Media_Audio_AudioGraphSettings).Get(),
&settings
);
The settings
still null and I don't know how to initialize it with the required AudioRenderCategory
constructor.
If I do it like below, I got access violation crash because it's still null.
settings->put_AudioRenderCategory(AudioRenderCategory::AudioRenderCategory_Media);
CodePudding user response:
Type activation at the ABI level is more involved than, for example, instantiating types in C . The admittedly terse documentation outlines the different mechanisms:
WinRT defines three activation mechanisms: direct activation (with no constructor parameters), factory activation (with one or more constructor parameters), and composition activation.
The IAudioGraphSettings
type falls into the second category: It instantiates a type based on a single argument of type AudioRenderCategory
. Instantiating a type is thus a two-phase process:
- Retrieve an activation factory
- Use the activation factory to instantiate a type
The code in the question conflates both operations, and the call to GetActivationFactory
returns an HRESULT
value of 0x80004002, i.e. E_NOINTERFACE
. It needs to request the IAudioGraphSettingsFactory
interface instead, and subsequently use that factory to instantiate the IAudioGraphSettings
type.
The following is a complete implementation that illustrates how to activate an IAudioGraphSettings
type:
#include <wrl/wrappers/corewrappers.h>
#include <wrl/client.h>
#include <windows.foundation.h>
#include <windows.media.audio.h>
#include <windows.media.render.h>
#pragma comment(lib, "windowsapp")
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Media::Audio;
using namespace ABI::Windows::Media::Render;
int main()
{
RoInitializeWrapper init { RO_INIT_MULTITHREADED };
HRESULT hr { init };
if (FAILED(hr))
return hr;
// Retrieve activation factory
ComPtr<IAudioGraphSettingsFactory> settings_factory {};
hr = GetActivationFactory(
HStringReference(RuntimeClass_Windows_Media_Audio_AudioGraphSettings).Get(),
&settings_factory);
if (FAILED(hr))
return hr;
// Use activation factory to instantiate type
ComPtr<IAudioGraphSettings> settings {};
hr = settings_factory->Create(AudioRenderCategory_Media, &settings);
if (FAILED(hr))
return hr;
return hr;
}
This is how things look at the ABI level, which is ultimately where the WRL lives. C /WinRT takes care of all the boilerplate code, and neatly maps parameterized factory activation onto C constructor implementations. That's why the C /WinRT implementation is so much more compact.