132 lines
2.7 KiB
C++
132 lines
2.7 KiB
C++
|
#include "decklink-device-discovery.hpp"
|
||
|
#include "decklink-device.hpp"
|
||
|
|
||
|
#include <util/threading.h>
|
||
|
|
||
|
DeckLinkDeviceDiscovery::DeckLinkDeviceDiscovery()
|
||
|
{
|
||
|
discovery = CreateDeckLinkDiscoveryInstance();
|
||
|
if (discovery == nullptr)
|
||
|
blog(LOG_INFO, "No blackmagic support");
|
||
|
}
|
||
|
|
||
|
DeckLinkDeviceDiscovery::~DeckLinkDeviceDiscovery(void)
|
||
|
{
|
||
|
if (discovery != nullptr) {
|
||
|
if (initialized)
|
||
|
discovery->UninstallDeviceNotifications();
|
||
|
for (DeckLinkDevice *device : devices)
|
||
|
device->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool DeckLinkDeviceDiscovery::Init(void)
|
||
|
{
|
||
|
HRESULT result = E_FAIL;
|
||
|
|
||
|
if (initialized)
|
||
|
return false;
|
||
|
|
||
|
if (discovery != nullptr)
|
||
|
result = discovery->InstallDeviceNotifications(this);
|
||
|
|
||
|
initialized = result == S_OK;
|
||
|
if (!initialized)
|
||
|
blog(LOG_INFO, "Failed to start search for DeckLink devices");
|
||
|
|
||
|
return initialized;
|
||
|
}
|
||
|
|
||
|
DeckLinkDevice *DeckLinkDeviceDiscovery::FindByHash(const char *hash)
|
||
|
{
|
||
|
DeckLinkDevice *ret = nullptr;
|
||
|
|
||
|
deviceMutex.lock();
|
||
|
for (DeckLinkDevice *device : devices) {
|
||
|
if (device->GetHash().compare(hash) == 0) {
|
||
|
ret = device;
|
||
|
ret->AddRef();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
deviceMutex.unlock();
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE DeckLinkDeviceDiscovery::DeckLinkDeviceArrived(
|
||
|
IDeckLink *device)
|
||
|
{
|
||
|
DeckLinkDevice *newDev = new DeckLinkDevice(device);
|
||
|
if (!newDev->Init()) {
|
||
|
delete newDev;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
std::lock_guard<std::recursive_mutex> lock(deviceMutex);
|
||
|
|
||
|
devices.push_back(newDev);
|
||
|
|
||
|
for (DeviceChangeInfo &cb : callbacks)
|
||
|
cb.callback(cb.param, newDev, true);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE DeckLinkDeviceDiscovery::DeckLinkDeviceRemoved(
|
||
|
IDeckLink *device)
|
||
|
{
|
||
|
std::lock_guard<std::recursive_mutex> lock(deviceMutex);
|
||
|
|
||
|
for (size_t i = 0; i < devices.size(); i++) {
|
||
|
if (devices[i]->IsDevice(device)) {
|
||
|
|
||
|
for (DeviceChangeInfo &cb : callbacks)
|
||
|
cb.callback(cb.param, devices[i], false);
|
||
|
|
||
|
devices[i]->Release();
|
||
|
devices.erase(devices.begin() + i);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
ULONG STDMETHODCALLTYPE DeckLinkDeviceDiscovery::AddRef(void)
|
||
|
{
|
||
|
return os_atomic_inc_long(&refCount);
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE DeckLinkDeviceDiscovery::QueryInterface(REFIID iid,
|
||
|
LPVOID *ppv)
|
||
|
{
|
||
|
HRESULT result = E_NOINTERFACE;
|
||
|
|
||
|
*ppv = nullptr;
|
||
|
|
||
|
CFUUIDBytes unknown = CFUUIDGetUUIDBytes(IUnknownUUID);
|
||
|
if (memcmp(&iid, &unknown, sizeof(REFIID)) == 0) {
|
||
|
*ppv = this;
|
||
|
AddRef();
|
||
|
result = S_OK;
|
||
|
} else if (memcmp(&iid, &IID_IDeckLinkDeviceNotificationCallback,
|
||
|
sizeof(REFIID)) == 0) {
|
||
|
*ppv = (IDeckLinkDeviceNotificationCallback *)this;
|
||
|
AddRef();
|
||
|
result = S_OK;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ULONG STDMETHODCALLTYPE DeckLinkDeviceDiscovery::Release(void)
|
||
|
{
|
||
|
const long newRefCount = os_atomic_dec_long(&refCount);
|
||
|
if (newRefCount == 0) {
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return newRefCount;
|
||
|
}
|