If there's no endpoint available, that failure is expected error Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9521>
172 lines
4.2 KiB
C++
172 lines
4.2 KiB
C++
/* GStreamer
|
|
* Copyright (C) 2025 Seungha Yang <seungha@centricular.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "gstwasapi2activator.h"
|
|
#include <objidl.h>
|
|
|
|
GST_DEBUG_CATEGORY_EXTERN (gst_wasapi2_debug);
|
|
#define GST_CAT_DEFAULT gst_wasapi2_debug
|
|
|
|
/* *INDENT-OFF* */
|
|
using namespace Microsoft::WRL;
|
|
|
|
void
|
|
Wasapi2ActivationHandler::CreateInstance (Wasapi2ActivationHandler ** handler,
|
|
const wchar_t * device_id,
|
|
const AUDIOCLIENT_ACTIVATION_PARAMS * params)
|
|
{
|
|
auto self = new Wasapi2ActivationHandler ();
|
|
self->device_id_ = device_id;
|
|
|
|
if (params) {
|
|
self->params_ = *params;
|
|
self->prop_.vt = VT_BLOB;
|
|
self->prop_.blob.cbSize = sizeof (AUDIOCLIENT_ACTIVATION_PARAMS);
|
|
self->prop_.blob.pBlobData = (BYTE *) &self->params_;
|
|
self->have_params_ = true;
|
|
}
|
|
|
|
*handler = self;
|
|
}
|
|
|
|
STDMETHODIMP_ (ULONG)
|
|
Wasapi2ActivationHandler::AddRef (void)
|
|
{
|
|
return InterlockedIncrement (&refcount_);
|
|
}
|
|
|
|
STDMETHODIMP_ (ULONG)
|
|
Wasapi2ActivationHandler::Release (void)
|
|
{
|
|
ULONG ref_count;
|
|
|
|
ref_count = InterlockedDecrement (&refcount_);
|
|
|
|
if (ref_count == 0)
|
|
delete this;
|
|
|
|
return ref_count;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
Wasapi2ActivationHandler::QueryInterface (REFIID riid, void ** object)
|
|
{
|
|
if (riid == __uuidof(IUnknown) || riid == __uuidof(IAgileObject)) {
|
|
*object = static_cast<IUnknown *>(static_cast<Wasapi2ActivationHandler*>(this));
|
|
} else if (riid == __uuidof(IActivateAudioInterfaceCompletionHandler)) {
|
|
*object = static_cast<IActivateAudioInterfaceCompletionHandler *>(
|
|
static_cast<Wasapi2ActivationHandler*>(this));
|
|
} else if (riid == IID_Wasapi2ActivationHandler) {
|
|
*object = this;
|
|
} else {
|
|
*object = nullptr;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef ();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
Wasapi2ActivationHandler::ActivateCompleted (IActivateAudioInterfaceAsyncOperation * op)
|
|
{
|
|
ComPtr<IUnknown> iface;
|
|
HRESULT hr = S_OK;
|
|
HRESULT activate_hr = S_OK;
|
|
hr = op->GetActivateResult (&activate_hr, &iface);
|
|
if (!gst_wasapi2_result (hr))
|
|
GST_WARNING ("Couldn't get activate result, hr: 0x%x", (guint) hr);
|
|
|
|
if (!gst_wasapi2_result (activate_hr)) {
|
|
GST_WARNING ("GetActivateResult failed, hr: 0x%x", (guint) activate_hr);
|
|
hr = activate_hr;
|
|
}
|
|
|
|
if (SUCCEEDED (hr) && !iface) {
|
|
GST_ERROR ("Couldn't get inteface from asyncop");
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
if (FAILED (hr)) {
|
|
activate_hr_ = hr;
|
|
SetEvent (event_);
|
|
return hr;
|
|
}
|
|
|
|
{
|
|
std::lock_guard<std::mutex> lk (lock_);
|
|
hr = iface.As (&client_);
|
|
activate_hr_ = hr;
|
|
}
|
|
|
|
GST_LOG ("Activation result 0x%x", (guint) hr);
|
|
|
|
SetEvent (event_);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
Wasapi2ActivationHandler::ActivateAsync ()
|
|
{
|
|
ComPtr<IActivateAudioInterfaceAsyncOperation> async_op;
|
|
auto hr = ActivateAudioInterfaceAsync (device_id_.c_str (),
|
|
__uuidof (IAudioClient), have_params_ ? &prop_ : nullptr,
|
|
this, &async_op);
|
|
if (!gst_wasapi2_result (hr)) {
|
|
activate_hr_ = hr;
|
|
SetEvent (event_);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
Wasapi2ActivationHandler::GetClient (IAudioClient ** client, DWORD timeout)
|
|
{
|
|
WaitForSingleObject (event_, timeout);
|
|
auto hr = activate_hr_.load ();
|
|
if (!gst_wasapi2_result (hr))
|
|
return hr;
|
|
|
|
if (!client)
|
|
return S_OK;
|
|
|
|
std::lock_guard<std::mutex> lk (lock_);
|
|
if (!client_)
|
|
return E_FAIL;
|
|
|
|
*client = client_.Get ();
|
|
(*client)->AddRef ();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
Wasapi2ActivationHandler::Wasapi2ActivationHandler ()
|
|
{
|
|
event_ = CreateEvent (nullptr, TRUE, FALSE, nullptr);
|
|
}
|
|
|
|
Wasapi2ActivationHandler::~Wasapi2ActivationHandler ()
|
|
{
|
|
CloseHandle (event_);
|
|
}
|
|
/* *INDENT-ON* */
|