Archived
1
0
This repository has been archived on 2024-10-17. You can view files and clone it, but cannot push or open issues or pull requests.
winamp/Src/Plugins/Portable/pmp_p4s/deviceprovider.cpp
2024-09-24 14:54:57 +02:00

285 lines
4.2 KiB
C++

#include "P4SDevice.h"
#include "./deviceprovider.h"
#include "../devices/api_devicemanager.h"
#include "../nu/threadpool/api_threadpool.h"
void checkForDevices(BOOL *killSwitch);
BOOL
QueueThreadFunction(api_threadpool::ThreadPoolFunc func, void *user, intptr_t id);
DeviceProvider::DeviceProvider()
: ref(1), activity(0), manager(NULL), readyEvent(NULL), cancelDiscovery(FALSE)
{
InitializeCriticalSection(&lock);
}
DeviceProvider::~DeviceProvider()
{
CancelDiscovery();
if (NULL != readyEvent)
CloseHandle(readyEvent);
DeleteCriticalSection(&lock);
}
HRESULT DeviceProvider::CreateInstance(DeviceProvider **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = new DeviceProvider();
if (NULL == *instance)
return E_OUTOFMEMORY;
return S_OK;
}
size_t DeviceProvider::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t DeviceProvider::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int DeviceProvider::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object)
return E_POINTER;
if (IsEqualIID(interface_guid, IFC_DeviceProvider))
*object = static_cast<ifc_deviceprovider*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
void DeviceProvider::Lock()
{
EnterCriticalSection(&lock);
}
void DeviceProvider::Unlock()
{
LeaveCriticalSection(&lock);
}
DWORD DeviceProvider::DiscoveryThread()
{
IncrementActivity();
if (FALSE == cancelDiscovery)
{
checkForDevices(&cancelDiscovery);
}
DecrementActivity();
Lock();
if (NULL != readyEvent)
SetEvent(readyEvent);
Unlock();
return 0;
}
static int DeviceProvider_DiscoveryThreadStarter(HANDLE handle, void *user, intptr_t id)
{
DeviceProvider *self;
DWORD result;
self = (DeviceProvider*)user;
if (NULL != self)
result = self->DiscoveryThread();
else
result = -2;
return result;
}
HRESULT DeviceProvider::BeginDiscovery(api_devicemanager *manager)
{
HRESULT hr;
Lock();
if (NULL != readyEvent &&
WAIT_TIMEOUT == WaitForSingleObject(readyEvent, 0))
{
hr = E_PENDING;
}
else
{
hr = S_OK;
if (NULL == readyEvent)
{
readyEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (NULL == readyEvent)
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
cancelDiscovery = FALSE;
ResetEvent(readyEvent);
if (FALSE == QueueThreadFunction(DeviceProvider_DiscoveryThreadStarter,
this, 0))
{
SetEvent(readyEvent);
hr = E_FAIL;
}
}
}
Unlock();
return hr;
}
HRESULT DeviceProvider::CancelDiscovery()
{
HRESULT hr;
hr = S_FALSE;
Lock();
if (NULL != readyEvent)
{
cancelDiscovery = TRUE;
if (WAIT_OBJECT_0 == WaitForSingleObject(readyEvent, 0))
hr = S_OK;
cancelDiscovery = FALSE;
}
Unlock();
return hr;
}
HRESULT DeviceProvider::GetActive()
{
HRESULT hr;
Lock();
if (0 != activity)
hr = S_OK;
else
hr = S_FALSE;
Unlock();
return hr;
}
HRESULT DeviceProvider::Register(api_devicemanager *manager)
{
HRESULT hr;
if (NULL != this->manager)
return E_UNEXPECTED;
if (NULL == manager)
return E_POINTER;
hr = manager->RegisterProvider(this);
if (SUCCEEDED(hr))
{
this->manager = manager;
manager->AddRef();
}
return hr;
}
HRESULT DeviceProvider::Unregister()
{
HRESULT hr;
if (NULL == manager)
return E_UNEXPECTED;
hr = manager->UnregisterProvider(this);
manager->Release();
manager = NULL;
return hr;
}
size_t DeviceProvider::IncrementActivity()
{
size_t a;
Lock();
activity++;
if (1 == activity &&
NULL != manager)
{
manager->SetProviderActive(this, TRUE);
}
a = activity;
Unlock();
return a;
}
size_t DeviceProvider::DecrementActivity()
{
size_t a;
Lock();
if (0 != activity)
{
activity--;
if (0 == activity &&
NULL != manager)
{
manager->SetProviderActive(this, FALSE);
}
}
a = activity;
Unlock();
return a;
}
#define CBCLASS DeviceProvider
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
CB(API_BEGINDISCOVERY, BeginDiscovery)
CB(API_CANCELDISCOVERY, CancelDiscovery)
CB(API_GETACTIVE, GetActive)
END_DISPATCH;
#undef CBCLASS