以下のコードは、Delphi XE2 Win32 でコンパイルされ、Win 7 64 ビットで実行され、「AudioSessionManager2.GetSessionEnumerator」行を実行すると、次の例外が発生します。
「Project22.exe が例外クラス $C0000005 を発生させ、メッセージ '0x7027edb2 でのアクセス違反: アドレス 0x0051ced6 の書き込み'」
例外クラスまたはその意味に関する私の知識が不足しているため、例外の意味や修正方法についてはわかりません。
例外を発生させるコードは次のとおりです (コードのデバッグに使用されるアサート)。
var
HRES: HRESULT;
DeviceEnumerator: IMMDeviceEnumerator;
DefaultDevice: IMMDevice;
AudioSessionManager2: IAudioSessionManager2;
Enumerator: IAudioSessionEnumerator;
begin
CoInitialize( nil );
HRES := CoCreateInstance( CLSID_MMDeviceEnumerator, nil, CLSCTX_ALL, IID_IMMDeviceEnumerator, DeviceEnumerator );
Assert( Succeeded( HRES ) );
HRES := DeviceEnumerator.GetDefaultAudioEndpoint( eRender, eMultimedia, DefaultDevice );
Assert( Succeeded( HRES ) );
HRES := DefaultDevice.Activate( IID_IAudioSessionManager2, CLSCTX_ALL, nil, IUnknown( AudioSessionManager2 ) );
Assert( Succeeded( HRES ) );
HRES := AudioSessionManager2.GetSessionEnumerator( Enumerator ); // <- EXCEPTION HERE
Assert( Succeeded( HRES ) );
[snip]
IAudioSessionManager2および IAudioSessionEnumerator インターフェイスは次のようになります。
IAudioSessionManager2 = interface(IUnknown)
['{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}']
function GetSessionEnumerator(out SessionEnum: IAudioSessionEnumerator): HResult; stdcall;
function RegisterSessionNotification(SessionNotification: IAudioSessionNotification): HResult; stdcall;
function UnregisterSessionNotification(SessionNotification: IAudioSessionNotification): HResult; stdcall;
function RegisterDuckNotification(const sessionID: LPCWSTR; const duckNotification: IAudioVolumeDuckNotification): HResult; stdcall;
function UnregisterDuckNotification(const duckNotification: IAudioVolumeDuckNotification): HResult; stdcall;
end;
IAudioSessionEnumerator = interface(IUnknown)
['{E2F5BB11-0570-40CA-ACDD-3AA01277DEE8}']
function GetCount(out SessionCount: integer): HResult; stdcall;
function GetSession(const SessionCount: integer; out Session: IAudioSessionControl): HResult; stdcall;
end;
インターフェイスは適切に定義されていると思いますし、GUID も再確認しました。
Visual Studio 2012 (Win32 プロジェクト) で意図したとおりに同じ命令シーケンスが実行されるため、問題は自分のコード (ここではほぼ間違いありません)、Core Audio インターフェイスの定義、または Delphi にあると思われます。VS で実行される C++ コードは次のとおりです。
IMMDeviceEnumerator *DeviceEnumerator = NULL;
IMMDevice* DefaultDevice = NULL;
IAudioSessionManager2* AudioSessionManager = NULL;
IAudioSessionEnumerator* Enumerator = NULL;
HRESULT HR;
HR = CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&DeviceEnumerator );
HR = DeviceEnumerator->GetDefaultAudioEndpoint( eRender, eMultimedia, &DefaultDevice );
HR = DefaultDevice->Activate( __uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL,(void**)&AudioSessionManager );
HR = AudioSessionManager->GetSessionEnumerator( &Enumerator );
C++ コードを使用すると、セッション列挙子を正しく取得し、GetCount などを使用できます。
私は自分のコードの何が問題なのかを突き止めようと数え切れないほどの時間を費やしましたが、まだ無知なので、どんな助けも大歓迎です。