summaryrefslogtreecommitdiffstats
path: root/Src/devices
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 14:54:57 +0200
committerJef <jef@targetspot.com>2024-09-24 14:54:57 +0200
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/devices
parentAdding .gitignore (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.bz2
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.lz
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.xz
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.zst
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.zip
Diffstat (limited to 'Src/devices')
-rw-r--r--Src/devices/api_devicemanager.h305
-rw-r--r--Src/devices/common.h76
-rw-r--r--Src/devices/component.cpp84
-rw-r--r--Src/devices/component.h39
-rw-r--r--Src/devices/deviceCommand.cpp239
-rw-r--r--Src/devices/deviceCommand.h64
-rw-r--r--Src/devices/deviceConnection.cpp200
-rw-r--r--Src/devices/deviceConnection.h59
-rw-r--r--Src/devices/deviceEventManager.cpp303
-rw-r--r--Src/devices/deviceEventManager.h64
-rw-r--r--Src/devices/deviceIconStore.cpp501
-rw-r--r--Src/devices/deviceIconStore.h71
-rw-r--r--Src/devices/deviceManager.cpp650
-rw-r--r--Src/devices/deviceManager.h111
-rw-r--r--Src/devices/deviceManagerFactory.cpp100
-rw-r--r--Src/devices/deviceManagerFactory.h42
-rw-r--r--Src/devices/deviceObjectEnum.cpp175
-rw-r--r--Src/devices/deviceObjectEnum.h44
-rw-r--r--Src/devices/deviceObjectStore.cpp356
-rw-r--r--Src/devices/deviceObjectStore.h55
-rw-r--r--Src/devices/deviceSupportedCommand.cpp120
-rw-r--r--Src/devices/deviceSupportedCommand.h47
-rw-r--r--Src/devices/deviceSupportedCommandEnum.cpp172
-rw-r--r--Src/devices/deviceSupportedCommandEnum.h48
-rw-r--r--Src/devices/deviceSupportedCommandStore.cpp342
-rw-r--r--Src/devices/deviceSupportedCommandStore.h69
-rw-r--r--Src/devices/deviceType.cpp200
-rw-r--r--Src/devices/deviceType.h59
-rw-r--r--Src/devices/devices.rc63
-rw-r--r--Src/devices/devices.sln31
-rw-r--r--Src/devices/devices.vcxproj323
-rw-r--r--Src/devices/devices.vcxproj.filters194
-rw-r--r--Src/devices/discoveryMonitor.cpp105
-rw-r--r--Src/devices/discoveryMonitor.h43
-rw-r--r--Src/devices/ifc_device.h203
-rw-r--r--Src/devices/ifc_deviceactivity.h74
-rw-r--r--Src/devices/ifc_devicecommand.h58
-rw-r--r--Src/devices/ifc_devicecommandeditor.h55
-rw-r--r--Src/devices/ifc_devicecommandinfo.h50
-rw-r--r--Src/devices/ifc_deviceconnection.h24
-rw-r--r--Src/devices/ifc_deviceconnectioneditor.h49
-rw-r--r--Src/devices/ifc_deviceevent.h119
-rw-r--r--Src/devices/ifc_deviceeventmanager.h133
-rw-r--r--Src/devices/ifc_deviceiconstore.h107
-rw-r--r--Src/devices/ifc_devicemanagerevent.h104
-rw-r--r--Src/devices/ifc_deviceobject.h55
-rw-r--r--Src/devices/ifc_deviceobjectenum.h63
-rw-r--r--Src/devices/ifc_deviceprovider.h54
-rw-r--r--Src/devices/ifc_devicesupportedcommand.h46
-rw-r--r--Src/devices/ifc_devicesupportedcommandenum.h63
-rw-r--r--Src/devices/ifc_devicesupportedcommandstore.h102
-rw-r--r--Src/devices/ifc_devicetype.h25
-rw-r--r--Src/devices/ifc_devicetypeeditor.h47
-rw-r--r--Src/devices/main.cpp3
-rw-r--r--Src/devices/main.h48
-rw-r--r--Src/devices/plugin.cpp31
-rw-r--r--Src/devices/plugin.h14
-rw-r--r--Src/devices/resource.h14
-rw-r--r--Src/devices/strings.cpp152
-rw-r--r--Src/devices/strings.h59
-rw-r--r--Src/devices/version.rc239
61 files changed, 7145 insertions, 0 deletions
diff --git a/Src/devices/api_devicemanager.h b/Src/devices/api_devicemanager.h
new file mode 100644
index 000000000..13eaac0e9
--- /dev/null
+++ b/Src/devices/api_devicemanager.h
@@ -0,0 +1,305 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {CB360A8F-0636-4a0d-9374-3BBCC18C8B40}
+static const GUID DeviceManagerGUID =
+{ 0xcb360a8f, 0x636, 0x4a0d, { 0x93, 0x74, 0x3b, 0xbc, 0xc1, 0x8c, 0x8b, 0x40 } };
+
+
+#include <bfc/dispatch.h>
+#include "ifc_device.h"
+#include "ifc_deviceobjectenum.h"
+#include "ifc_devicetype.h"
+#include "ifc_devicetypeeditor.h"
+#include "ifc_devicecommand.h"
+#include "ifc_devicecommandeditor.h"
+#include "ifc_deviceconnection.h"
+#include "ifc_deviceconnectioneditor.h"
+#include "ifc_devicemanagerevent.h"
+#include "ifc_deviceprovider.h"
+#include "ifc_deviceeventmanager.h"
+#include "ifc_devicesupportedcommand.h"
+#include "ifc_devicesupportedcommandstore.h"
+#include "ifc_devicesupportedcommandenum.h"
+#include "ifc_deviceiconstore.h"
+#include "ifc_deviceactivity.h"
+
+typedef ifc_devicetype *(_cdecl *DeviceTypeCreator)(const char * /*name*/, void * /*user*/);
+typedef ifc_devicecommand *(_cdecl *DeviceCommandCreator)(const char * /*name*/, void * /*user*/);
+typedef ifc_deviceconnection *(_cdecl *DeviceConnectionCreator)(const char * /*name*/, void * /*user*/);
+
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) api_devicemanager : public Dispatchable
+{
+protected:
+ api_devicemanager() {}
+ ~api_devicemanager() {}
+
+public:
+
+ /* types */
+ size_t TypeRegister(ifc_devicetype **types, size_t count); // return number of registered types
+ size_t TypeRegisterIndirect(const char **names, size_t count, DeviceTypeCreator callback, void *user);
+ HRESULT TypeUnregister(const char *name);
+ HRESULT TypeFind(const char *name, ifc_devicetype **type);
+ HRESULT TypeEnumerate(ifc_deviceobjectenum **enumerator);
+
+ /* connections */
+ size_t ConnectionRegister(ifc_deviceconnection **connections, size_t count);
+ size_t ConnectionRegisterIndirect(const char **names, size_t count, DeviceConnectionCreator callback, void *user);
+ HRESULT ConnectionUnregister(const char *name);
+ HRESULT ConnectionFind(const char *name, ifc_deviceconnection **connection);
+ HRESULT ConnectionEnumerate(ifc_deviceobjectenum **enumerator);
+
+ /* commmands */
+ size_t CommandRegister(ifc_devicecommand **commands, size_t count);
+ size_t CommandRegisterIndirect(const char **names, size_t count, DeviceCommandCreator callback, void *user);
+ HRESULT CommandUnregister(const char *name);
+ HRESULT CommandFind(const char *name, ifc_devicecommand **command);
+ HRESULT CommandEnumerate(ifc_deviceobjectenum **enumerator);
+
+ /* devices */
+ size_t DeviceRegister(ifc_device **devices, size_t count);
+ HRESULT DeviceUnregister(const char *name);
+ HRESULT DeviceFind(const char *name, ifc_device **device);
+ HRESULT DeviceEnumerate(ifc_deviceobjectenum **enumerator);
+
+ /* discovery */
+ HRESULT IsDiscoveryActive();
+ HRESULT BeginDiscovery();
+ HRESULT CancelDiscovery();
+ HRESULT RegisterProvider(ifc_deviceprovider *provider);
+ HRESULT UnregisterProvider(ifc_deviceprovider *provider);
+ HRESULT SetProviderActive(ifc_deviceprovider *provider, BOOL activeState);
+
+ /* events */
+ HRESULT Advise(ifc_devicemanagerevent *handler);
+ HRESULT Unadvise(ifc_devicemanagerevent *handler);
+
+ /* misc helpers */
+ HRESULT CreateDeviceEventManager(ifc_deviceeventmanager **eventManager);
+ HRESULT CreateSupportedCommandStore(ifc_devicesupportedcommandstore **store);
+ HRESULT CreateSupportedCommandEnum(ifc_devicesupportedcommand **commands, size_t count, ifc_devicesupportedcommandenum **enumerator);
+ HRESULT CreateIconStore(ifc_deviceiconstore **store);
+ HRESULT CreateType(const char *name, ifc_devicetype **type);
+ HRESULT CreateCommand(const char *name, ifc_devicecommand **command);
+ HRESULT CreateConnection(const char *name, ifc_deviceconnection **connection);
+
+public:
+ DISPATCH_CODES
+ {
+ API_TYPEREGISTER = 10,
+ API_TYPEREGISTERINDIRECT = 20,
+ API_TYPEUNREGISTER = 30,
+ API_TYPEFIND = 40,
+ API_TYPEENUMERATE = 50,
+ API_CONNECTIONREGISTER = 60,
+ API_CONNECTIONREGISTERINDIRECT = 70,
+ API_CONNECTIONUNREGISTER = 80,
+ API_CONNECTIONFIND = 90,
+ API_CONNECTIONENUMERATE = 100,
+ API_COMMANDREGISTER = 110,
+ API_COMMANDREGISTERINDIRECT = 120,
+ API_COMMANDUNREGISTER = 130,
+ API_COMMANDFIND = 140,
+ API_COMMANDENUMERATE = 150,
+ API_DEVICEREGISTER = 160,
+ API_DEVICEUNREGISTER = 170,
+ API_DEVICEFIND = 180,
+ API_DEVICEENUMERATE = 190,
+ API_ISDISCOVERYACTIVE = 200,
+ API_BEGINDISCOVERY = 210,
+ API_CANCELDISCOVERY = 220,
+ API_REGISTERPROVIDER = 230,
+ API_UNREGISTERPROVIDER = 240,
+ API_SETPROVIDERACTIVE = 250,
+ API_ADVISE = 260,
+ API_UNADVISE = 270,
+ API_CREATEDEVICEEVENTMANAGER = 400,
+ API_CREATESUPPORTEDCOMMANDSTORE = 410,
+ API_CREATESUPPORTEDCOMMANDENUM = 420,
+ API_CREATEICONSTORE = 430,
+ API_CREATETYPE = 440,
+ API_CREATECOMMAND = 450,
+ API_CREATECONNECTION = 460,
+ };
+};
+
+inline size_t api_devicemanager::TypeRegister(ifc_devicetype **types, size_t count)
+{
+ return _call(API_TYPEREGISTER, (size_t)0, types, count);
+}
+
+inline size_t api_devicemanager::TypeRegisterIndirect(const char **names, size_t count, DeviceTypeCreator callback, void *user)
+{
+ return _call(API_TYPEREGISTERINDIRECT, (size_t)0, names, count, callback, user);
+}
+
+inline HRESULT api_devicemanager::TypeUnregister(const char *name)
+{
+ return _call(API_TYPEUNREGISTER, (HRESULT)E_NOTIMPL, name);
+}
+
+inline HRESULT api_devicemanager::TypeFind(const char *name, ifc_devicetype **type)
+{
+ return _call(API_TYPEFIND, (HRESULT)E_NOTIMPL, name, type);
+}
+
+inline HRESULT api_devicemanager::TypeEnumerate(ifc_deviceobjectenum **enumerator)
+{
+ return _call(API_TYPEENUMERATE, (HRESULT)E_NOTIMPL, enumerator);
+}
+
+inline size_t api_devicemanager::ConnectionRegister(ifc_deviceconnection **connections, size_t count)
+{
+ return _call(API_CONNECTIONREGISTER, (size_t)0, connections, count);
+}
+
+inline size_t api_devicemanager::ConnectionRegisterIndirect(const char **names, size_t count, DeviceConnectionCreator callback, void *user)
+{
+ return _call(API_CONNECTIONREGISTERINDIRECT, (size_t)0, names, count, callback, user);
+}
+
+inline HRESULT api_devicemanager::ConnectionUnregister(const char *name)
+{
+ return _call(API_CONNECTIONUNREGISTER, (HRESULT)E_NOTIMPL, name);
+}
+
+inline HRESULT api_devicemanager::ConnectionFind(const char *name, ifc_deviceconnection **connection)
+{
+ return _call(API_CONNECTIONFIND, (HRESULT)E_NOTIMPL, name, connection);
+}
+
+inline HRESULT api_devicemanager::ConnectionEnumerate(ifc_deviceobjectenum **enumerator)
+{
+ return _call(API_CONNECTIONENUMERATE, (HRESULT)E_NOTIMPL, enumerator);
+}
+
+inline size_t api_devicemanager::CommandRegister(ifc_devicecommand **commands, size_t count)
+{
+ return _call(API_COMMANDREGISTER, (size_t)0, commands, count);
+}
+
+inline size_t api_devicemanager::CommandRegisterIndirect(const char **names, size_t count, DeviceCommandCreator callback, void *user)
+{
+ return _call(API_COMMANDREGISTERINDIRECT, (size_t)0, names, count, callback, user);
+}
+
+inline HRESULT api_devicemanager::CommandUnregister(const char *name)
+{
+ return _call(API_COMMANDUNREGISTER, (HRESULT)E_NOTIMPL, name);
+}
+
+inline HRESULT api_devicemanager::CommandFind(const char *name, ifc_devicecommand **command)
+{
+ return _call(API_COMMANDFIND, (HRESULT)E_NOTIMPL, name, command);
+}
+
+inline HRESULT api_devicemanager::CommandEnumerate(ifc_deviceobjectenum **enumerator)
+{
+ return _call(API_COMMANDENUMERATE, (HRESULT)E_NOTIMPL, enumerator);
+}
+
+inline size_t api_devicemanager::DeviceRegister(ifc_device **devices, size_t count)
+{
+ return _call(API_DEVICEREGISTER, (size_t)0, devices, count);
+}
+
+inline HRESULT api_devicemanager::DeviceUnregister(const char *name)
+{
+ return _call(API_DEVICEUNREGISTER, (HRESULT)E_NOTIMPL, name);
+}
+
+inline HRESULT api_devicemanager::DeviceFind(const char *name, ifc_device **device)
+{
+ return _call(API_DEVICEFIND, (HRESULT)E_NOTIMPL, name, device);
+}
+
+inline HRESULT api_devicemanager::DeviceEnumerate(ifc_deviceobjectenum **enumerator)
+{
+ return _call(API_DEVICEENUMERATE, (HRESULT)E_NOTIMPL, enumerator);
+}
+
+inline HRESULT api_devicemanager::IsDiscoveryActive()
+{
+ return _call(API_ISDISCOVERYACTIVE, (HRESULT)E_NOTIMPL);
+}
+
+inline HRESULT api_devicemanager::BeginDiscovery()
+{
+ return _call(API_BEGINDISCOVERY, (HRESULT)E_NOTIMPL);
+}
+
+inline HRESULT api_devicemanager::CancelDiscovery()
+{
+ return _call(API_CANCELDISCOVERY, (HRESULT)E_NOTIMPL);
+}
+
+inline HRESULT api_devicemanager::RegisterProvider(ifc_deviceprovider *provider)
+{
+ return _call(API_REGISTERPROVIDER, (HRESULT)E_NOTIMPL, provider);
+}
+
+inline HRESULT api_devicemanager::UnregisterProvider(ifc_deviceprovider *provider)
+{
+ return _call(API_UNREGISTERPROVIDER, (HRESULT)E_NOTIMPL, provider);
+}
+
+inline HRESULT api_devicemanager::SetProviderActive(ifc_deviceprovider *provider, BOOL activeState)
+{
+ return _call(API_SETPROVIDERACTIVE, (HRESULT)E_NOTIMPL, provider, activeState);
+}
+
+inline HRESULT api_devicemanager::Advise(ifc_devicemanagerevent *handler)
+{
+ return _call(API_ADVISE, (HRESULT)E_NOTIMPL, handler);
+}
+
+inline HRESULT api_devicemanager::Unadvise(ifc_devicemanagerevent *handler)
+{
+ return _call(API_UNADVISE, (HRESULT)E_NOTIMPL, handler);
+}
+
+inline HRESULT api_devicemanager::CreateDeviceEventManager(ifc_deviceeventmanager **eventManager)
+{
+ return _call(API_CREATEDEVICEEVENTMANAGER, (HRESULT)E_NOTIMPL, eventManager);
+}
+
+inline HRESULT api_devicemanager::CreateSupportedCommandStore(ifc_devicesupportedcommandstore **store)
+{
+ return _call(API_CREATESUPPORTEDCOMMANDSTORE, (HRESULT)E_NOTIMPL, store);
+}
+
+inline HRESULT api_devicemanager::CreateSupportedCommandEnum(ifc_devicesupportedcommand **commands, size_t count, ifc_devicesupportedcommandenum **enumerator)
+{
+ return _call(API_CREATESUPPORTEDCOMMANDENUM, (HRESULT)E_NOTIMPL, commands, count, enumerator);
+}
+
+inline HRESULT api_devicemanager::CreateIconStore(ifc_deviceiconstore **store)
+{
+ return _call(API_CREATEICONSTORE, (HRESULT)E_NOTIMPL, store);
+}
+
+inline HRESULT api_devicemanager::CreateType(const char *name, ifc_devicetype **type)
+{
+ return _call(API_CREATETYPE, (HRESULT)E_NOTIMPL, name, type);
+}
+
+inline HRESULT api_devicemanager::CreateCommand(const char *name, ifc_devicecommand **command)
+{
+ return _call(API_CREATECOMMAND, (HRESULT)E_NOTIMPL, name, command);
+}
+
+inline HRESULT api_devicemanager::CreateConnection(const char *name, ifc_deviceconnection **connection)
+{
+ return _call(API_CREATECONNECTION, (HRESULT)E_NOTIMPL, name, connection);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/common.h b/Src/devices/common.h
new file mode 100644
index 000000000..d1d8f19c5
--- /dev/null
+++ b/Src/devices/common.h
@@ -0,0 +1,76 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_COMMON_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_COMMON_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#ifndef LONGX86
+#ifdef _WIN64
+ #define LONGX86 LONG_PTR
+#else /*_WIN64*/
+ #define LONGX86 LONG
+#endif /*_WIN64*/
+#endif // LONGX86
+
+#define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
+
+#ifdef __cplusplus
+ #define SENDMSG(__hwnd, __msgId, __wParam, __lParam) ::SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
+#else
+ #define SENDMSG(__hwnd, __msgId, __wParam, __lParam) SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam))
+#endif // __cplusplus
+
+#define SENDMLIPC(__hwndML, __ipcMsgId, __param) SENDMSG((__hwndML), WM_ML_IPC, (WPARAM)(__param), (LPARAM)(__ipcMsgId))
+
+#define SENDWAIPC(__hwndWA, __ipcMsgId, __param) SENDMSG((__hwndWA), WM_WA_IPC, (WPARAM)(__param), (LPARAM)(__ipcMsgId))
+
+#define SENDCMD(__hwnd, __ctrlId, __eventId, __hctrl) (SENDMSG((__hwnd), WM_COMMAND, MAKEWPARAM(__ctrlId, __eventId), (LPARAM)(__hctrl)))
+
+#define DIALOG_RESULT(__hwnd, __result) { SetWindowLongPtrW((__hwnd), DWLP_MSGRESULT, ((LONGX86)(LONG_PTR)(__result))); return TRUE; }
+
+#ifndef GetWindowStyle
+ #define GetWindowStyle(__hwnd) ((UINT)GetWindowLongPtr((__hwnd), GWL_STYLE))
+#endif //GetWindowStyle
+
+#ifndef SetWindowStyle
+ #define SetWindowStyle(__hwnd, __style) (SetWindowLongPtr((__hwnd), GWL_STYLE, (__style)))
+#endif //SetWindowStyle
+
+#ifndef GetWindowStyleEx
+ #define GetWindowStyleEx(__hwnd) ((UINT)GetWindowLongPtr((__hwnd), GWL_EXSTYLE))
+#endif // GetWindowStyleEx
+
+#ifndef SetWindowStyleEx
+ #define SetWindowStyleEx(__hwnd, __style) (SetWindowLongPtr((__hwnd), GWL_EXSTYLE, (__style)))
+#endif //SetWindowStyle
+
+#ifndef RECTWIDTH
+ #define RECTWIDTH(__r) ((__r).right - (__r).left)
+#endif
+
+#ifndef RECTHEIGHT
+ #define RECTHEIGHT(__r) ((__r).bottom - (__r).top)
+#endif
+
+#undef CLAMP
+#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
+
+#ifndef ARRAYSIZE
+ #define ARRAYSIZE(_a) (sizeof(_a)/sizeof((_a)[0]))
+#endif
+
+#ifndef ABS
+ #define ABS(x) (((x) > 0) ? (x) : (-x))
+#endif
+
+#ifndef MIN
+ #define MIN(v1, v2) (((v1) < (v2)) ? (v1) : (v2))
+#endif
+
+#ifndef MAX
+ #define MAX(v1, v2) (((v1) > (v2)) ? (v1) : (v2))
+#endif
+
+
+#endif //_NULLSOFT_WINAMP_DEVICES_COMMON_HEADER
diff --git a/Src/devices/component.cpp b/Src/devices/component.cpp
new file mode 100644
index 000000000..3f4bd8fe4
--- /dev/null
+++ b/Src/devices/component.cpp
@@ -0,0 +1,84 @@
+#include "main.h"
+#include "./component.h"
+#include "./deviceManagerFactory.h"
+
+static DeviceManagerFactory deviceManagerFactory;
+
+DevicesComponent::DevicesComponent()
+{
+ InitializeCriticalSection(&lock);
+}
+
+DevicesComponent::~DevicesComponent()
+{
+ EnterCriticalSection(&lock);
+
+ ReleaseServices();
+
+ LeaveCriticalSection(&lock);
+
+ DeleteCriticalSection(&lock);
+}
+
+size_t DevicesComponent::AddRef()
+{
+ return 1;
+}
+
+size_t DevicesComponent::Release()
+{
+ return 1;
+}
+
+int DevicesComponent::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object)
+ return E_POINTER;
+
+ *object = NULL;
+ return E_NOINTERFACE;
+}
+
+void DevicesComponent::RegisterServices(api_service *service)
+{
+ EnterCriticalSection(&lock);
+
+ deviceManagerFactory.Register(service);
+
+ LeaveCriticalSection(&lock);
+
+ aTRACE_LINE("Devices Service Registered");
+}
+
+int DevicesComponent::RegisterServicesSafeModeOk()
+{
+ return 1;
+}
+
+void DevicesComponent::DeregisterServices(api_service *service)
+{
+ EnterCriticalSection(&lock);
+
+ deviceManagerFactory.Unregister(service);
+
+ ReleaseServices();
+
+ LeaveCriticalSection(&lock);
+
+ aTRACE_LINE("Devices Service Unregistered");
+}
+
+void DevicesComponent::ReleaseServices()
+{
+}
+
+#define CBCLASS DevicesComponent
+START_DISPATCH;
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(QUERYINTERFACE, QueryInterface)
+VCB(API_WA5COMPONENT_REGISTERSERVICES, RegisterServices)
+CB(15, RegisterServicesSafeModeOk)
+VCB(API_WA5COMPONENT_DEREEGISTERSERVICES, DeregisterServices)
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/devices/component.h b/Src/devices/component.h
new file mode 100644
index 000000000..7d1babe2c
--- /dev/null
+++ b/Src/devices/component.h
@@ -0,0 +1,39 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_COMPONENT_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_COMPONENT_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <wtypes.h>
+#include "../Agave/Component/ifc_wa5component.h"
+
+class DevicesComponent : public ifc_wa5component
+{
+public:
+ DevicesComponent();
+ ~DevicesComponent();
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* ifc_wa5component */
+ void RegisterServices(api_service *service);
+ int RegisterServicesSafeModeOk();
+ void DeregisterServices(api_service *service);
+
+protected:
+ void ReleaseServices(void);
+
+protected:
+ RECVS_DISPATCH;
+
+private:
+ CRITICAL_SECTION lock;
+};
+
+
+#endif //_NULLSOFT_WINAMP_DEVICES_COMPONENT_HEADER \ No newline at end of file
diff --git a/Src/devices/deviceCommand.cpp b/Src/devices/deviceCommand.cpp
new file mode 100644
index 000000000..b41d198de
--- /dev/null
+++ b/Src/devices/deviceCommand.cpp
@@ -0,0 +1,239 @@
+#include "main.h"
+#include "./deviceCommand.h"
+
+#include <strsafe.h>
+
+DeviceCommand::DeviceCommand()
+ : ref(1), name(NULL), displayName(NULL), description(NULL)
+{
+ if (FAILED(DeviceIconStore::CreateInstance(&iconStore)))
+ iconStore = NULL;
+
+ InitializeCriticalSection(&lock);
+}
+
+DeviceCommand::~DeviceCommand()
+{
+ AnsiString_Free(name);
+ String_Free(displayName);
+ String_Free(description);
+
+ if (NULL != iconStore)
+ iconStore->Release();
+
+ DeleteCriticalSection(&lock);
+}
+
+HRESULT DeviceCommand::CreateInstance(const char *name, DeviceCommand **instance)
+{
+ char *nameCopy;
+
+ if (NULL == instance)
+ return E_POINTER;
+
+ if (FALSE != IS_STRING_EMPTY(name))
+ return E_INVALIDARG;
+
+ *instance = new DeviceCommand();
+
+ if (NULL == *instance)
+ return E_OUTOFMEMORY;
+
+ nameCopy = AnsiString_Duplicate(name);
+ if (NULL == nameCopy)
+ {
+ (*instance)->Release();
+ return E_OUTOFMEMORY;
+ }
+
+ (*instance)->name = nameCopy;
+
+ return S_OK;
+}
+
+size_t DeviceCommand::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t DeviceCommand::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int DeviceCommand::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object) return E_POINTER;
+
+ if (IsEqualIID(interface_guid, IFC_DeviceCommand))
+ *object = static_cast<ifc_devicecommand*>(this);
+ else if (IsEqualIID(interface_guid, IFC_DeviceCommandEditor))
+ *object = static_cast<ifc_devicecommandeditor*>(this);
+ else if (IsEqualIID(interface_guid, IFC_DeviceObject))
+ *object = static_cast<ifc_deviceobject*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+void DeviceCommand::Lock()
+{
+ EnterCriticalSection(&lock);
+}
+
+void DeviceCommand::Unlock()
+{
+ LeaveCriticalSection(&lock);
+}
+
+const char *DeviceCommand::GetName()
+{
+ return name;
+}
+
+HRESULT DeviceCommand::GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
+{
+ HRESULT hr;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ Lock();
+
+ if (NULL == iconStore)
+ hr = E_UNEXPECTED;
+ else
+ hr = iconStore->Get(buffer, bufferSize, width, height);
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceCommand::GetDisplayName(wchar_t *buffer, size_t bufferSize)
+{
+ HRESULT hr;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ Lock();
+
+ hr = StringCchCopyExW(buffer, bufferSize, displayName, NULL, NULL, STRSAFE_IGNORE_NULLS);
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceCommand::GetDescription(wchar_t *buffer, size_t bufferSize)
+{
+ HRESULT hr;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ Lock();
+
+ hr = StringCchCopyExW(buffer, bufferSize, description, NULL, NULL, STRSAFE_IGNORE_NULLS);
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceCommand::GetIconStore(ifc_deviceiconstore **store)
+{
+ HRESULT hr;
+
+ if (NULL == store)
+ return E_POINTER;
+
+ Lock();
+
+ if (NULL == iconStore)
+ hr = E_UNEXPECTED;
+ else
+ {
+ iconStore->AddRef();
+ *store = iconStore;
+ hr = S_OK;
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceCommand::SetDisplayName(const wchar_t *displayName)
+{
+ HRESULT hr;
+
+ Lock();
+
+ String_Free(this->displayName);
+ this->displayName = String_Duplicate(displayName);
+
+ if (NULL == this->displayName && NULL != displayName)
+ hr = E_OUTOFMEMORY;
+ else
+ hr = S_OK;
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceCommand::SetDescription(const wchar_t *description)
+{
+ HRESULT hr;
+
+ Lock();
+
+ String_Free(this->description);
+ this->description = String_Duplicate(description);
+
+ if (NULL == this->description && NULL != description)
+ hr = E_OUTOFMEMORY;
+ else
+ hr = S_OK;
+
+ Unlock();
+
+ return hr;
+}
+
+#define CBCLASS DeviceCommand
+START_MULTIPATCH;
+ START_PATCH(MPIID_DEVICECOMMAND)
+ M_CB(MPIID_DEVICECOMMAND, ifc_devicecommand, ADDREF, AddRef);
+ M_CB(MPIID_DEVICECOMMAND, ifc_devicecommand, RELEASE, Release);
+ M_CB(MPIID_DEVICECOMMAND, ifc_devicecommand, QUERYINTERFACE, QueryInterface);
+ M_CB(MPIID_DEVICECOMMAND, ifc_devicecommand, API_GETNAME, GetName);
+ M_CB(MPIID_DEVICECOMMAND, ifc_devicecommand, API_GETICON, GetIcon);
+ M_CB(MPIID_DEVICECOMMAND, ifc_devicecommand, API_GETDISPLAYNAME, GetDisplayName);
+ M_CB(MPIID_DEVICECOMMAND, ifc_devicecommand, API_GETDESCRIPTION, GetDescription);
+ NEXT_PATCH(MPIID_DEVICECOMMANDEDITOR)
+ M_CB(MPIID_DEVICECOMMANDEDITOR, ifc_devicecommandeditor, ADDREF, AddRef);
+ M_CB(MPIID_DEVICECOMMANDEDITOR, ifc_devicecommandeditor, RELEASE, Release);
+ M_CB(MPIID_DEVICECOMMANDEDITOR, ifc_devicecommandeditor, QUERYINTERFACE, QueryInterface);
+ M_CB(MPIID_DEVICECOMMANDEDITOR, ifc_devicecommandeditor, API_SETDISPLAYNAME, SetDisplayName);
+ M_CB(MPIID_DEVICECOMMANDEDITOR, ifc_devicecommandeditor, API_SETDESCRIPTION, SetDescription);
+ M_CB(MPIID_DEVICECOMMANDEDITOR, ifc_devicecommandeditor, API_GETICONSTORE, GetIconStore);
+ END_PATCH
+END_MULTIPATCH;
diff --git a/Src/devices/deviceCommand.h b/Src/devices/deviceCommand.h
new file mode 100644
index 000000000..60b9ee706
--- /dev/null
+++ b/Src/devices/deviceCommand.h
@@ -0,0 +1,64 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include "./ifc_devicecommand.h"
+#include "./ifc_devicecommandeditor.h"
+#include "./ifc_deviceiconstore.h"
+#include "./deviceIconStore.h"
+
+#include <bfc/multipatch.h>
+
+#define MPIID_DEVICECOMMAND 10
+#define MPIID_DEVICECOMMANDEDITOR 20
+
+
+class DeviceCommand : public MultiPatch<MPIID_DEVICECOMMAND, ifc_devicecommand>,
+ public MultiPatch<MPIID_DEVICECOMMANDEDITOR, ifc_devicecommandeditor>
+{
+
+protected:
+ DeviceCommand();
+ ~DeviceCommand();
+
+public:
+ static HRESULT CreateInstance(const char *name, DeviceCommand **instance);
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* ifc_devicecommand */
+ const char *GetName();
+ HRESULT GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height);
+ HRESULT GetDisplayName(wchar_t *buffer, size_t bufferSize);
+ HRESULT GetDescription(wchar_t *buffer, size_t bufferSize);
+
+ /* ifc_devicetypeeditor */
+ HRESULT GetIconStore(ifc_deviceiconstore **store);
+ HRESULT SetDisplayName(const wchar_t *displayName);
+ HRESULT SetDescription(const wchar_t *description);
+
+public:
+ void Lock();
+ void Unlock();
+
+
+protected:
+ size_t ref;
+ char *name;
+ wchar_t *displayName;
+ wchar_t *description;
+ DeviceIconStore *iconStore;
+ CRITICAL_SECTION lock;
+
+protected:
+ RECVS_MULTIPATCH;
+};
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_HEADER
diff --git a/Src/devices/deviceConnection.cpp b/Src/devices/deviceConnection.cpp
new file mode 100644
index 000000000..b8d6697a7
--- /dev/null
+++ b/Src/devices/deviceConnection.cpp
@@ -0,0 +1,200 @@
+#include "main.h"
+#include "./deviceConnection.h"
+
+#include <strsafe.h>
+
+DeviceConnection::DeviceConnection()
+ : ref(1), name(NULL), displayName(NULL)
+{
+ if (FAILED(DeviceIconStore::CreateInstance(&iconStore)))
+ iconStore = NULL;
+
+ InitializeCriticalSection(&lock);
+}
+
+DeviceConnection::~DeviceConnection()
+{
+ AnsiString_Free(name);
+ String_Free(displayName);
+ if (NULL != iconStore)
+ iconStore->Release();
+
+ DeleteCriticalSection(&lock);
+}
+
+HRESULT DeviceConnection::CreateInstance(const char *name, DeviceConnection **instance)
+{
+ char *nameCopy;
+
+ if (NULL == instance)
+ return E_POINTER;
+
+ if (FALSE != IS_STRING_EMPTY(name))
+ return E_INVALIDARG;
+
+ *instance = new DeviceConnection();
+
+ if (NULL == *instance)
+ return E_OUTOFMEMORY;
+
+ nameCopy = AnsiString_Duplicate(name);
+ if (NULL == nameCopy)
+ {
+ (*instance)->Release();
+ return E_OUTOFMEMORY;
+ }
+
+ (*instance)->name = nameCopy;
+
+ return S_OK;
+}
+
+size_t DeviceConnection::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t DeviceConnection::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int DeviceConnection::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object) return E_POINTER;
+
+ if (IsEqualIID(interface_guid, IFC_DeviceConnection))
+ *object = static_cast<ifc_deviceconnection*>(this);
+ else if (IsEqualIID(interface_guid, IFC_DeviceConnectionEditor))
+ *object = static_cast<ifc_deviceconnectioneditor*>(this);
+ else if (IsEqualIID(interface_guid, IFC_DeviceObject))
+ *object = static_cast<ifc_deviceobject*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+void DeviceConnection::Lock()
+{
+ EnterCriticalSection(&lock);
+}
+
+void DeviceConnection::Unlock()
+{
+ LeaveCriticalSection(&lock);
+}
+
+const char *DeviceConnection::GetName()
+{
+ return name;
+}
+
+HRESULT DeviceConnection::GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
+{
+ HRESULT hr;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ Lock();
+
+ if (NULL == iconStore)
+ hr = E_UNEXPECTED;
+ else
+ hr = iconStore->Get(buffer, bufferSize, width, height);
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceConnection::GetDisplayName(wchar_t *buffer, size_t bufferSize)
+{
+ HRESULT hr;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ Lock();
+
+ hr = StringCchCopyExW(buffer, bufferSize, displayName, NULL, NULL, STRSAFE_IGNORE_NULLS);
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceConnection::GetIconStore(ifc_deviceiconstore **store)
+{
+ HRESULT hr;
+
+ if (NULL == store)
+ return E_POINTER;
+
+ Lock();
+
+ if (NULL == iconStore)
+ hr = E_UNEXPECTED;
+ else
+ {
+ iconStore->AddRef();
+ *store = iconStore;
+ hr = S_OK;
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceConnection::SetDisplayName(const wchar_t *displayName)
+{
+ HRESULT hr;
+
+ Lock();
+
+ String_Free(this->displayName);
+ this->displayName = String_Duplicate(displayName);
+
+ if (NULL == this->displayName && NULL != displayName)
+ hr = E_OUTOFMEMORY;
+ else
+ hr = S_OK;
+
+ Unlock();
+
+ return hr;
+}
+
+#define CBCLASS DeviceConnection
+START_MULTIPATCH;
+ START_PATCH(MPIID_DEVICECONNECTION)
+ M_CB(MPIID_DEVICECONNECTION, ifc_deviceconnection, ADDREF, AddRef);
+ M_CB(MPIID_DEVICECONNECTION, ifc_deviceconnection, RELEASE, Release);
+ M_CB(MPIID_DEVICECONNECTION, ifc_deviceconnection, QUERYINTERFACE, QueryInterface);
+ M_CB(MPIID_DEVICECONNECTION, ifc_deviceconnection, API_GETNAME, GetName);
+ M_CB(MPIID_DEVICECONNECTION, ifc_deviceconnection, API_GETICON, GetIcon);
+ M_CB(MPIID_DEVICECONNECTION, ifc_deviceconnection, API_GETDISPLAYNAME, GetDisplayName);
+ NEXT_PATCH(MPIID_DEVICECONNECTIONEDITOR)
+ M_CB(MPIID_DEVICECONNECTIONEDITOR, ifc_deviceconnectioneditor, ADDREF, AddRef);
+ M_CB(MPIID_DEVICECONNECTIONEDITOR, ifc_deviceconnectioneditor, RELEASE, Release);
+ M_CB(MPIID_DEVICECONNECTIONEDITOR, ifc_deviceconnectioneditor, QUERYINTERFACE, QueryInterface);
+ M_CB(MPIID_DEVICECONNECTIONEDITOR, ifc_deviceconnectioneditor, API_SETDISPLAYNAME, SetDisplayName);
+ M_CB(MPIID_DEVICECONNECTIONEDITOR, ifc_deviceconnectioneditor, API_GETICONSTORE, GetIconStore);
+ END_PATCH
+END_MULTIPATCH; \ No newline at end of file
diff --git a/Src/devices/deviceConnection.h b/Src/devices/deviceConnection.h
new file mode 100644
index 000000000..3d2dd8e24
--- /dev/null
+++ b/Src/devices/deviceConnection.h
@@ -0,0 +1,59 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_CONNECTION_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_CONNECTION_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include "./ifc_deviceconnection.h"
+#include "./ifc_deviceconnectioneditor.h"
+#include "./ifc_deviceiconstore.h"
+#include "./deviceIconStore.h"
+
+#include <bfc/multipatch.h>
+
+#define MPIID_DEVICECONNECTION 10
+#define MPIID_DEVICECONNECTIONEDITOR 20
+
+class DeviceConnection : public MultiPatch<MPIID_DEVICECONNECTION, ifc_deviceconnection>,
+ public MultiPatch<MPIID_DEVICECONNECTIONEDITOR, ifc_deviceconnectioneditor>
+{
+
+protected:
+ DeviceConnection();
+ ~DeviceConnection();
+
+public:
+ static HRESULT CreateInstance(const char *name, DeviceConnection **instance);
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* ifc_deviceconnection */
+ const char *GetName();
+ HRESULT GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height);
+ HRESULT GetDisplayName(wchar_t *buffer, size_t bufferSize);
+
+ /* ifc_deviceconnectioneditor */
+ HRESULT GetIconStore(ifc_deviceiconstore **store);
+ HRESULT SetDisplayName(const wchar_t *displayName);
+
+public:
+ void Lock();
+ void Unlock();
+
+protected:
+ size_t ref;
+ char *name;
+ wchar_t *displayName;
+ DeviceIconStore *iconStore;
+ CRITICAL_SECTION lock;
+
+protected:
+ RECVS_MULTIPATCH;
+};
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_CONNECTION_HEADER
diff --git a/Src/devices/deviceEventManager.cpp b/Src/devices/deviceEventManager.cpp
new file mode 100644
index 000000000..73afe55a5
--- /dev/null
+++ b/Src/devices/deviceEventManager.cpp
@@ -0,0 +1,303 @@
+#include "main.h"
+#include "./deviceEventManager.h"
+
+DeviceEventManager::DeviceEventManager()
+ : ref(1)
+{
+ InitializeCriticalSection(&lock);
+}
+
+DeviceEventManager::~DeviceEventManager()
+{
+ Lock();
+
+ size_t index = handlerList.size();
+ while(index--)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->Release();
+ }
+
+ Unlock();
+
+ DeleteCriticalSection(&lock);
+}
+
+HRESULT DeviceEventManager::CreateInstance(DeviceEventManager **instance)
+{
+ if (NULL == instance)
+ return E_POINTER;
+
+ *instance = new DeviceEventManager();
+
+ if (NULL == *instance)
+ return E_OUTOFMEMORY;
+
+ return S_OK;
+}
+
+size_t DeviceEventManager::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t DeviceEventManager::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int DeviceEventManager::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object) return E_POINTER;
+
+ if (IsEqualIID(interface_guid, IFC_DeviceEventManager))
+ *object = static_cast<ifc_deviceeventmanager*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+void DeviceEventManager::Lock()
+{
+ EnterCriticalSection(&lock);
+}
+
+void DeviceEventManager::Unlock()
+{
+ LeaveCriticalSection(&lock);
+}
+
+HRESULT DeviceEventManager::Advise(ifc_deviceevent *handler)
+{
+ HRESULT hr;
+ size_t index;
+
+ Lock();
+
+ hr = S_OK;
+ index = handlerList.size();
+
+ while(index--)
+ {
+ if (handler == handlerList[index])
+ {
+ hr = E_FAIL;
+ break;
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ handlerList.push_back(handler);
+ handler->AddRef();
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceEventManager::Unadvise(ifc_deviceevent *handler)
+{
+ Lock();
+
+ HRESULT hr = S_FALSE;
+ size_t index = handlerList.size();
+
+ while(index--)
+ {
+ if (handler == handlerList[index])
+ {
+ handlerList.erase(handlerList.begin() + index);
+ handler->Release();
+ hr = S_OK;
+ break;
+ }
+ }
+ Unlock();
+
+ return hr;
+}
+
+void DeviceEventManager::Notify_IconChanged(ifc_device *device)
+{
+ Lock();
+
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->IconChanged(device);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notify_DisplayNameChanged(ifc_device *device, const wchar_t *displayName)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->DisplayNameChanged(device, displayName);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notify_AttachmentChanged(ifc_device *device, BOOL attached)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->AttachmentChanged(device, attached);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notify_VisibilityChanged(ifc_device *device, BOOL visible)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->VisibilityChanged(device, visible);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notify_TotalSpaceChanged(ifc_device *device, uint64_t space)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->TotalSpaceChanged(device, space);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notify_UsedSpaceChanged(ifc_device *device, uint64_t space)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->UsedSpaceChanged(device, space);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notfiy_CommandChanged(ifc_device *device)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->CommandChanged(device);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notify_ActivityStarted(ifc_device *device, ifc_deviceactivity *activity)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->ActivityStarted(device, activity);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notify_ActivityFinished(ifc_device *device, ifc_deviceactivity *activity)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->ActivityFinished(device, activity);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notify_ActivityChanged(ifc_device *device, ifc_deviceactivity *activity)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->ActivityChanged(device, activity);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notify_ModelChanged(ifc_device *device, const wchar_t *model)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->ModelChanged(device, model);
+ }
+ Unlock();
+}
+
+void DeviceEventManager::Notify_StatusChanged(ifc_device *device, const wchar_t *status)
+{
+ Lock();
+ size_t index, count = handlerList.size();
+ for(index = 0; index < count;index++)
+ {
+ ifc_deviceevent *handler = handlerList[index];
+ handler->StatusChanged(device, status);
+ }
+ Unlock();
+}
+
+
+#define CBCLASS DeviceEventManager
+START_DISPATCH;
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(QUERYINTERFACE, QueryInterface)
+CB(API_ADVISE, Advise)
+CB(API_UNADVISE, Unadvise)
+VCB(API_NOTIFY_ICONCHANGED, Notify_IconChanged)
+VCB(API_NOTIFY_DISPLAYNAMECHANGED, Notify_DisplayNameChanged)
+VCB(API_NOTIFY_ATTACHMENTCHANGED, Notify_AttachmentChanged)
+VCB(API_NOTIFY_VISIBILITYCHANGED, Notify_VisibilityChanged)
+VCB(API_NOTIFY_TOTALSPACECHANGED, Notify_TotalSpaceChanged)
+VCB(API_NOTIFY_USEDSPACECHANGED, Notify_UsedSpaceChanged)
+VCB(API_NOTIFY_COMMANDCHANGED, Notfiy_CommandChanged)
+VCB(API_NOTIFY_ACTIVITYSTARTED, Notify_ActivityStarted)
+VCB(API_NOTIFY_ACTIVITYFINISHED, Notify_ActivityFinished)
+VCB(API_NOTIFY_ACTIVITYCHANGED, Notify_ActivityChanged)
+VCB(API_NOTIFY_MODELCHANGED, Notify_ModelChanged)
+VCB(API_NOTIFY_STATUSCHANGED, Notify_StatusChanged)
+END_DISPATCH;
+#undef CBCLASS
diff --git a/Src/devices/deviceEventManager.h b/Src/devices/deviceEventManager.h
new file mode 100644
index 000000000..c5790fe9b
--- /dev/null
+++ b/Src/devices/deviceEventManager.h
@@ -0,0 +1,64 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_EVENT_MANAGER_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_EVENT_MANAGER_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include "./ifc_deviceevent.h"
+#include "./ifc_deviceeventmanager.h"
+#include <vector>
+
+class DeviceEventManager : public ifc_deviceeventmanager
+{
+
+protected:
+ DeviceEventManager();
+ ~DeviceEventManager();
+
+public:
+ static HRESULT CreateInstance(DeviceEventManager **instance);
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* ifc_deviceeventmanager */
+ HRESULT Advise(ifc_deviceevent *handler);
+ HRESULT Unadvise(ifc_deviceevent *handler);
+
+ void Notify_IconChanged(ifc_device *device);
+ void Notify_DisplayNameChanged(ifc_device *device, const wchar_t *displayName);
+ void Notify_AttachmentChanged(ifc_device *device, BOOL attached);
+ void Notify_VisibilityChanged(ifc_device *device, BOOL visible);
+ void Notify_TotalSpaceChanged(ifc_device *device, uint64_t space);
+ void Notify_UsedSpaceChanged(ifc_device *device, uint64_t space);
+ void Notfiy_CommandChanged(ifc_device *device);
+ void Notify_ActivityStarted(ifc_device *device, ifc_deviceactivity *activity);
+ void Notify_ActivityFinished(ifc_device *device, ifc_deviceactivity *activity);
+ void Notify_ActivityChanged(ifc_device *device, ifc_deviceactivity *activity);
+ void Notify_ModelChanged(ifc_device *device, const wchar_t *model);
+ void Notify_StatusChanged(ifc_device *device, const wchar_t *status);
+
+public:
+ void Lock();
+ void Unlock();
+
+protected:
+ typedef std::vector<ifc_deviceevent*> HandlerList;
+
+protected:
+ size_t ref;
+ HandlerList handlerList;
+ CRITICAL_SECTION lock;
+
+protected:
+ RECVS_DISPATCH;
+
+
+
+};
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_EVENT_MANAGER_HEADER \ No newline at end of file
diff --git a/Src/devices/deviceIconStore.cpp b/Src/devices/deviceIconStore.cpp
new file mode 100644
index 000000000..45b48b067
--- /dev/null
+++ b/Src/devices/deviceIconStore.cpp
@@ -0,0 +1,501 @@
+#include "main.h"
+#include "./deviceIconStore.h"
+
+#include <strsafe.h>
+
+DeviceIconStore::DeviceIconStore()
+ : ref(1), base(NULL)
+{
+ InitializeCriticalSection(&lock);
+}
+
+DeviceIconStore::~DeviceIconStore()
+{
+ RemoveAll();
+ String_Free(base);
+ DeleteCriticalSection(&lock);
+}
+
+HRESULT DeviceIconStore::CreateInstance(DeviceIconStore **instance)
+{
+ if (NULL == instance)
+ return E_POINTER;
+
+ *instance = new DeviceIconStore();
+
+ if (NULL == *instance)
+ return E_OUTOFMEMORY;
+
+ return S_OK;
+}
+
+size_t DeviceIconStore::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t DeviceIconStore::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int DeviceIconStore::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object) return E_POINTER;
+
+ if (IsEqualIID(interface_guid, IFC_DeviceIconStore))
+ *object = static_cast<ifc_deviceiconstore*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+void DeviceIconStore::Lock()
+{
+ EnterCriticalSection(&lock);
+}
+
+void DeviceIconStore::Unlock()
+{
+ LeaveCriticalSection(&lock);
+}
+
+HRESULT DeviceIconStore::Add(const wchar_t *path, unsigned int width, unsigned int height, BOOL replaceExisting)
+{
+ if (FALSE != IS_STRING_EMPTY(path))
+ return E_INVALIDARG;
+
+ if(width < 1)
+ width = 1;
+
+ if(height < 1)
+ height = 1;
+
+ HRESULT hr = S_FALSE;
+
+ Lock();
+
+ size_t index = list.size();
+ while(index--)
+ {
+ Record *record = &list[index];
+ if (width == record->width &&
+ height == record->height)
+ {
+ if (FALSE == replaceExisting)
+ hr = E_FAIL;
+ else
+ {
+ wchar_t *pathCopy;
+ pathCopy = String_Duplicate(path);
+ if (NULL == pathCopy)
+ hr = E_OUTOFMEMORY;
+ else
+ {
+ record->path = pathCopy;
+ hr = S_OK;
+ }
+ }
+ break;
+ }
+ }
+
+ if (S_FALSE == hr)
+ {
+ Record newRecord;
+ newRecord.path = String_Duplicate(path);
+ if (NULL == newRecord.path)
+ hr = E_OUTOFMEMORY;
+ else
+ {
+ newRecord.width = width;
+ newRecord.height = height;
+ list.push_back(newRecord);
+ hr = S_OK;
+ }
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceIconStore::Remove(unsigned int width, unsigned int height)
+{
+ HRESULT hr;
+ size_t index;
+ Record *record;
+
+ if(width < 1)
+ width = 1;
+
+ if(height < 1)
+ height = 1;
+
+ hr = S_FALSE;
+
+ Lock();
+
+ index = list.size();
+ while(index--)
+ {
+ record = &list[index];
+ if (record->width == width &&
+ record->height == height)
+ {
+ String_Free(record->path);
+ list.erase(list.begin() + index);
+ hr = S_OK;
+ break;
+ }
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceIconStore::RemovePath(const wchar_t *path)
+{
+ HRESULT hr;
+ size_t index;
+ Record *record;
+
+ if (FALSE != IS_STRING_EMPTY(path))
+ return E_INVALIDARG;
+
+ hr = S_FALSE;
+
+ Lock();
+
+ index = list.size();
+ while(index--)
+ {
+ record = &list[index];
+ if(CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, record->path, -1, path, -1))
+ {
+ String_Free(record->path);
+ list.erase(list.begin() + index);
+ hr = S_OK;
+ }
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceIconStore::RemoveAll()
+{
+ size_t index;
+ Record *record;
+
+ Lock();
+
+ index = list.size();
+ while(index--)
+ {
+ record = &list[index];
+ String_Free(record->path);
+ }
+ list.clear();
+
+ Unlock();
+
+ return S_OK;
+}
+
+HRESULT DeviceIconStore::Get(wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height)
+{
+ HRESULT hr;
+ Record *record;
+ const wchar_t *path;
+ size_t index;
+ double widthDbl, heightDbl;
+ double scaleMin, scaleHorz, scaleVert;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ if (width < 1)
+ width = 1;
+
+ if (height < 1)
+ height = 1;
+
+ path = NULL;
+
+ widthDbl = width;
+ heightDbl = height;
+
+ Lock();
+
+ index = list.size();
+ if (index > 0)
+ {
+ record = &list[--index];
+ scaleHorz = widthDbl/record->width;
+ scaleVert = heightDbl/record->height;
+ scaleMin = (scaleHorz < scaleVert) ? scaleHorz : scaleVert;
+ path = record->path;
+ if (1.0 != scaleMin)
+ {
+ scaleMin = fabs(1.0 - scaleMin);
+ while(index--)
+ {
+ record = &list[index];
+ scaleHorz = widthDbl/record->width;
+ scaleVert = heightDbl/record->height;
+ if (scaleHorz > scaleVert)
+ scaleHorz = scaleVert;
+
+ if (1.0 == scaleHorz)
+ {
+ path = record->path;
+ break;
+ }
+
+ scaleHorz = fabs(1.0 - scaleHorz);
+ if (scaleHorz < scaleMin)
+ {
+ scaleMin = scaleHorz;
+ path = record->path;
+ }
+ }
+ }
+ }
+
+ if (NULL == path)
+ hr = E_FAIL;
+ else
+ hr = GetFullPath(buffer, bufferMax, path);
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceIconStore::GetExact(wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height)
+{
+ HRESULT hr;
+ size_t index;
+ Record *record;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ if(width < 1)
+ width = 1;
+
+ if(height < 1)
+ height = 1;
+
+ hr = E_FAIL;
+
+ Lock();
+
+ index = list.size();
+ while(index--)
+ {
+ record = &list[index];
+ if (record->width == width &&
+ record->height == height)
+ {
+ hr = GetFullPath(buffer, bufferMax, record->path);
+ break;
+ }
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceIconStore::SetBasePath(const wchar_t *path)
+{
+ HRESULT hr;
+
+ Lock();
+
+ String_Free(base);
+ base = String_Duplicate(path);
+
+ if (NULL == base && NULL != path)
+ hr = E_OUTOFMEMORY;
+ else
+ hr = S_OK;
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceIconStore::GetBasePath(wchar_t *buffer, size_t bufferMax)
+{
+ HRESULT hr;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ Lock();
+
+ if (0 == String_CopyTo(buffer, base, bufferMax) &&
+ FALSE == IS_STRING_EMPTY(base))
+ {
+ hr = E_FAIL;
+ }
+ else
+ hr = S_OK;
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceIconStore::Clone(ifc_deviceiconstore **instance)
+{
+ HRESULT hr;
+ DeviceIconStore *clone;
+
+ if (NULL == instance)
+ return E_POINTER;
+
+ hr = DeviceIconStore::CreateInstance(&clone);
+ if (FAILED(hr))
+ return hr;
+
+ Lock();
+
+ clone->base = String_Duplicate(base);
+ if (NULL == clone->base && NULL != base)
+ hr = E_OUTOFMEMORY;
+ else
+ {
+ size_t index, count;
+ Record target;
+ const Record *source;
+
+ count = list.size();
+
+ for(index = 0; index < count; index++)
+ {
+ source = &list[index];
+ target.path = String_Duplicate(source->path);
+ if (NULL == target.path)
+ {
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+ else
+ {
+ target.width = source->width;
+ target.height = source->height;
+ clone->list.push_back(target);
+ }
+ }
+ }
+
+ Unlock();
+
+ if (FAILED(hr))
+ clone->Release();
+ else
+ *instance = clone;
+
+ return hr;
+}
+
+HRESULT DeviceIconStore::Enumerate(EnumeratorCallback callback, void *user)
+{
+ size_t index, count;
+ wchar_t buffer[MAX_PATH*2] = {0};
+ Record *record;
+
+ if (NULL == callback)
+ return E_POINTER;
+
+ Lock();
+
+ count = list.size();
+ for(index = 0; index < count; index++)
+ {
+ record = &list[index];
+ if (SUCCEEDED(GetFullPath(buffer, ARRAYSIZE(buffer), record->path)))
+ {
+ if (FALSE == callback(buffer, record->width, record->height, user))
+ {
+ break;
+ }
+ }
+ }
+
+ Unlock();
+
+ return S_OK;
+}
+
+HRESULT DeviceIconStore::GetFullPath(wchar_t *buffer, size_t bufferMax, const wchar_t *path)
+{
+ HRESULT hr;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ if (FALSE != IS_STRING_EMPTY(path))
+ return E_INVALIDARG;
+
+ Lock();
+
+ if (FALSE == PathIsRelative(path) ||
+ FALSE != IS_STRING_EMPTY(base))
+ {
+ if (0 == String_CopyTo(buffer, path, bufferMax))
+ hr = E_OUTOFMEMORY;
+ else
+ hr = S_OK;
+ }
+ else
+ {
+ if (NULL == PathCombine(buffer, base, path))
+ hr = E_FAIL;
+ else
+ hr = S_OK;
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+#define CBCLASS DeviceIconStore
+START_DISPATCH;
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(QUERYINTERFACE, QueryInterface)
+CB(API_ADD, Add)
+CB(API_REMOVE, Remove)
+CB(API_REMOVEPATH, RemovePath)
+CB(API_REMOVEALL, RemoveAll)
+CB(API_GET, Get)
+CB(API_GETEXACT, GetExact)
+CB(API_SETBASEPATH, SetBasePath)
+CB(API_GETBASEPATH, GetBasePath)
+CB(API_CLONE, Clone)
+CB(API_ENUMERATE, Enumerate)
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/devices/deviceIconStore.h b/Src/devices/deviceIconStore.h
new file mode 100644
index 000000000..6b23151d8
--- /dev/null
+++ b/Src/devices/deviceIconStore.h
@@ -0,0 +1,71 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_ICON_STORE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_ICON_STORE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include "./ifc_deviceiconstore.h"
+#include <vector>
+
+class DeviceIconStore : public ifc_deviceiconstore
+{
+
+protected:
+ DeviceIconStore();
+ ~DeviceIconStore();
+
+public:
+ static HRESULT CreateInstance(DeviceIconStore **instance);
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* ifc_deviceiconstore */
+ HRESULT Add(const wchar_t *path, unsigned int width, unsigned int height, BOOL replaceExisting);
+ HRESULT Remove(unsigned int width, unsigned int height);
+ HRESULT RemovePath(const wchar_t *path);
+ HRESULT RemoveAll();
+ HRESULT Get(wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height);
+ HRESULT GetExact(wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height);
+
+ HRESULT SetBasePath(const wchar_t *path);
+ HRESULT GetBasePath(wchar_t *buffer, size_t bufferMax);
+
+ HRESULT Clone(ifc_deviceiconstore **instance);
+
+ HRESULT Enumerate(EnumeratorCallback callback, void *user);
+
+public:
+ void Lock();
+ void Unlock();
+
+ HRESULT GetFullPath(wchar_t *buffer, size_t bufferMax, const wchar_t *path);
+
+protected:
+ typedef struct Record
+ {
+ unsigned int width;
+ unsigned int height;
+ wchar_t *path;
+ } Record;
+
+ typedef std::vector<Record> RecordList;
+
+protected:
+ size_t ref;
+ wchar_t *base;
+ RecordList list;
+ CRITICAL_SECTION lock;
+
+protected:
+ RECVS_DISPATCH;
+
+
+
+};
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_ICON_STORE_HEADER \ No newline at end of file
diff --git a/Src/devices/deviceManager.cpp b/Src/devices/deviceManager.cpp
new file mode 100644
index 000000000..a68eec698
--- /dev/null
+++ b/Src/devices/deviceManager.cpp
@@ -0,0 +1,650 @@
+#include "main.h"
+#include "./deviceManager.h"
+#include "./deviceEventManager.h"
+
+static void
+DeviceManager_ReleaseDispatchables(Dispatchable** buffer, size_t count)
+{
+ if(NULL == buffer)
+ return;
+
+ while(count--)
+ {
+ Dispatchable *object = buffer[count];
+ if (NULL != object)
+ object->Release();
+ }
+}
+
+DeviceManager::DeviceManager()
+ : ref(1),
+ #pragma warning(push)
+ #pragma warning(disable:4355)
+ typeStore(ObjectAddedCallback, ObjectRemovedCallback, this),
+ connectionStore(ObjectAddedCallback, ObjectRemovedCallback, this),
+ commandStore(ObjectAddedCallback, ObjectRemovedCallback, this),
+ deviceStore(ObjectAddedCallback, ObjectRemovedCallback, this)
+ #pragma warning(pop)
+{
+ InitializeCriticalSection(&eventLock);
+ InitializeCriticalSection(&providerLock);
+}
+
+
+DeviceManager::~DeviceManager()
+{
+ EnterCriticalSection(&providerLock);
+ DeviceManager_ReleaseDispatchables((Dispatchable**)(providerList.size() ? &providerList.at(0) : nullptr), providerList.size());
+ providerList.clear();
+ LeaveCriticalSection(&providerLock);
+ DeleteCriticalSection(&providerLock);
+
+ EnterCriticalSection(&eventLock);
+ DeviceManager_ReleaseDispatchables((Dispatchable**)(eventList.size() ? &eventList.at(0) : nullptr), eventList.size());
+ eventList.clear();
+ LeaveCriticalSection(&eventLock);
+ DeleteCriticalSection(&eventLock);
+}
+
+HRESULT DeviceManager::CreateInstance(DeviceManager **instance)
+{
+ if (NULL == instance)
+ return E_POINTER;
+
+ *instance = new DeviceManager();
+
+ if (NULL == *instance)
+ return E_OUTOFMEMORY;
+
+ return S_OK;
+}
+
+size_t DeviceManager::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t DeviceManager::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int DeviceManager::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object) return E_POINTER;
+
+ if (IsEqualIID(interface_guid, DeviceManagerGUID))
+ *object = static_cast<api_devicemanager*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+size_t DeviceManager::TypeRegister(ifc_devicetype **types, size_t count)
+{
+ return typeStore.AddRange((ifc_deviceobject**)types, count);
+}
+
+size_t DeviceManager::TypeRegisterIndirect(const char **names, size_t count, DeviceTypeCreator callback, void *user)
+{
+ return typeStore.AddIndirect(names, count, (DeviceObjectCreator)callback, user);
+}
+
+HRESULT DeviceManager::TypeUnregister(const char *name)
+{
+ return typeStore.Remove(name);
+}
+
+HRESULT DeviceManager::TypeFind(const char *name, ifc_devicetype **type)
+{
+ return typeStore.Find(name, (ifc_deviceobject**)type);
+}
+
+HRESULT DeviceManager::TypeEnumerate(ifc_deviceobjectenum **enumerator)
+{
+ return typeStore.Enumerate((DeviceObjectEnum**)enumerator);
+}
+
+size_t DeviceManager::ConnectionRegister(ifc_deviceconnection **connections, size_t count)
+{
+
+ return connectionStore.AddRange((ifc_deviceobject**)connections, count);
+}
+
+size_t DeviceManager::ConnectionRegisterIndirect(const char **names, size_t count, DeviceConnectionCreator callback, void *user)
+{
+ return connectionStore.AddIndirect(names, count, (DeviceObjectCreator)callback, user);
+}
+
+HRESULT DeviceManager::ConnectionUnregister(const char *name)
+{
+ return connectionStore.Remove(name);
+}
+
+HRESULT DeviceManager::ConnectionFind(const char *name, ifc_deviceconnection **connection)
+{
+ return connectionStore.Find(name, (ifc_deviceobject**)connection);
+}
+
+HRESULT DeviceManager::ConnectionEnumerate(ifc_deviceobjectenum **enumerator)
+{
+ return connectionStore.Enumerate((DeviceObjectEnum**)enumerator);
+}
+
+size_t DeviceManager::CommandRegister(ifc_devicecommand **commands, size_t count)
+{
+ return commandStore.AddRange((ifc_deviceobject**)commands, count);
+}
+
+size_t DeviceManager::CommandRegisterIndirect(const char **names, size_t count, DeviceCommandCreator callback, void *user)
+{
+ return commandStore.AddIndirect(names, count, (DeviceObjectCreator)callback, user);
+}
+
+HRESULT DeviceManager::CommandUnregister(const char *name)
+{
+ return commandStore.Remove(name);
+}
+
+HRESULT DeviceManager::CommandFind(const char *name, ifc_devicecommand **command)
+{
+ return commandStore.Find(name, (ifc_deviceobject**)command);
+}
+
+HRESULT DeviceManager::CommandEnumerate(ifc_deviceobjectenum **enumerator)
+{
+ return commandStore.Enumerate((DeviceObjectEnum**)enumerator);
+}
+
+size_t DeviceManager::DeviceRegister(ifc_device **devices, size_t count)
+{
+ return deviceStore.AddRange((ifc_deviceobject**)devices, count);
+}
+
+HRESULT DeviceManager::DeviceUnregister(const char *name)
+{
+ return deviceStore.Remove(name);
+}
+
+HRESULT DeviceManager::DeviceFind(const char *name, ifc_device **device)
+{
+ return deviceStore.Find(name, (ifc_deviceobject**)device);
+}
+
+HRESULT DeviceManager::DeviceEnumerate(ifc_deviceobjectenum **enumerator)
+{
+ return deviceStore.Enumerate((DeviceObjectEnum**)enumerator);
+}
+
+
+HRESULT DeviceManager::IsDiscoveryActive()
+{
+ return (FALSE != discoveryMonitor.IsActive()) ? S_OK : S_FALSE;
+}
+
+HRESULT DeviceManager::BeginDiscovery()
+{
+ size_t index, started;
+
+ EnterCriticalSection(&providerLock);
+
+ started = 0;
+ index = providerList.size();
+
+ while(index--)
+ {
+ if (providerList[index] && SUCCEEDED(providerList[index]->BeginDiscovery((api_devicemanager*)this)))
+ started++;
+ }
+
+ LeaveCriticalSection(&providerLock);
+
+ return (0 != started) ? S_OK : E_FAIL;
+}
+
+HRESULT DeviceManager::CancelDiscovery()
+{
+ size_t index;
+
+ EnterCriticalSection(&providerLock);
+
+ index = providerList.size();
+
+ while(index--)
+ {
+ providerList[index]->CancelDiscovery();
+ }
+
+ LeaveCriticalSection(&providerLock);
+
+ return S_OK;
+}
+
+HRESULT DeviceManager::SetProviderActive(ifc_deviceprovider *provider, BOOL activeState)
+{
+
+ if (FALSE != activeState)
+ {
+ if (FALSE != discoveryMonitor.Register(provider))
+ EventDiscoveryStarted();
+ }
+ else
+ {
+ if (FALSE != discoveryMonitor.Unregister(provider))
+ EventDiscoveryFinished();
+ }
+
+ return S_OK;
+}
+
+HRESULT DeviceManager::RegisterProvider(ifc_deviceprovider *provider)
+{
+ HRESULT hr;
+ size_t index;
+
+ if (NULL == provider)
+ return E_INVALIDARG;
+
+ hr = S_OK;
+
+ EnterCriticalSection(&providerLock);
+
+ index = providerList.size();
+ while(index--)
+ {
+ if (provider == providerList[index])
+ {
+ hr = S_FALSE;
+ break;
+ }
+ }
+
+ if(S_OK == hr)
+ {
+ providerList.push_back(provider);
+ provider->AddRef();
+
+ SetProviderActive(provider, (S_OK == provider->GetActive()));
+ }
+
+ LeaveCriticalSection(&providerLock);
+
+ return hr;
+}
+
+HRESULT DeviceManager::UnregisterProvider(ifc_deviceprovider *provider)
+{
+ HRESULT hr;
+ size_t index;
+
+ if (NULL == provider)
+ return E_INVALIDARG;
+
+ hr = S_FALSE;
+
+ EnterCriticalSection(&providerLock);
+
+ index = providerList.size();
+ while(index--)
+ {
+ if (provider == providerList[index])
+ {
+ ifc_deviceprovider *object;
+ object = providerList[index];
+
+ SetProviderActive(object, (S_OK == object->GetActive()));
+
+ providerList.erase(providerList.begin() + index);
+ object->Release();
+
+ hr = S_OK;
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&providerLock);
+
+ return hr;
+}
+
+HRESULT DeviceManager::Advise(ifc_devicemanagerevent *handler)
+{
+ HRESULT hr;
+ size_t index;
+
+ if (NULL == handler)
+ return E_INVALIDARG;
+
+ hr = S_OK;
+
+ EnterCriticalSection(&eventLock);
+
+ index = eventList.size();
+ while(index--)
+ {
+ if (handler == eventList[index])
+ {
+ hr = S_FALSE;
+ break;
+ }
+ }
+
+ if(S_OK == hr)
+ {
+ eventList.push_back(handler);
+ handler->AddRef();
+ }
+
+ LeaveCriticalSection(&eventLock);
+
+ return hr;
+}
+
+HRESULT DeviceManager::Unadvise(ifc_devicemanagerevent *handler)
+{
+ HRESULT hr;
+ size_t index;
+
+ if (NULL == handler)
+ return E_INVALIDARG;
+
+ hr = S_FALSE;
+
+ EnterCriticalSection(&eventLock);
+
+ index = eventList.size();
+ while(index--)
+ {
+ if (handler == eventList[index])
+ {
+ ifc_devicemanagerevent *object;
+ object = eventList[index];
+
+ eventList.erase(eventList.begin() + index);
+ object->Release();
+
+ hr = S_OK;
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&eventLock);
+
+ return hr;
+}
+
+HRESULT DeviceManager::CreateDeviceEventManager(ifc_deviceeventmanager **eventManager)
+{
+ return DeviceEventManager::CreateInstance(
+ reinterpret_cast<DeviceEventManager**>(eventManager));
+}
+
+HRESULT DeviceManager::CreateSupportedCommandStore(ifc_devicesupportedcommandstore **store)
+{
+ return DeviceSupportedCommandStore::CreateInstance(
+ reinterpret_cast<DeviceSupportedCommandStore**>(store));
+}
+
+HRESULT DeviceManager::CreateSupportedCommandEnum(ifc_devicesupportedcommand **commands, size_t count, ifc_devicesupportedcommandenum **enumerator)
+{
+ return DeviceSupportedCommandEnum::CreateInstance(commands, count,
+ reinterpret_cast<DeviceSupportedCommandEnum**>(enumerator));
+}
+
+HRESULT DeviceManager::CreateIconStore(ifc_deviceiconstore **store)
+{
+ return DeviceIconStore::CreateInstance(
+ reinterpret_cast<DeviceIconStore**>(store));
+}
+
+HRESULT DeviceManager::CreateType(const char *name, ifc_devicetype **type)
+{
+ return DeviceType::CreateInstance(name, reinterpret_cast<DeviceType**>(type));
+}
+
+HRESULT DeviceManager::CreateCommand(const char *name, ifc_devicecommand **command)
+{
+ return DeviceCommand::CreateInstance(name, reinterpret_cast<DeviceCommand**>(command));
+
+}
+
+HRESULT DeviceManager::CreateConnection(const char *name, ifc_deviceconnection **connection)
+{
+ return DeviceConnection::CreateInstance(name, reinterpret_cast<DeviceConnection**>(connection));
+}
+
+void
+DeviceManager::ObjectAddedCallback(DeviceObjectStore *store, ifc_deviceobject *object, void *userData)
+{
+ DeviceManager *manager;
+ manager = (DeviceManager*)userData;
+
+ if (NULL == manager)
+ return;
+
+ if (store == &manager->typeStore)
+ manager->EventTypeAdded((ifc_devicetype*)object);
+ else if (store == &manager->connectionStore)
+ manager->EventConnectionAdded((ifc_deviceconnection*)object);
+ else if (store == &manager->commandStore)
+ manager->EventCommandAdded((ifc_devicecommand*)object);
+ else if (store == &manager->deviceStore)
+ manager->EventDeviceAdded((ifc_device*)object);
+}
+
+void
+DeviceManager::ObjectRemovedCallback(DeviceObjectStore *store, ifc_deviceobject *object, void *userData)
+{
+ DeviceManager *manager;
+ manager = (DeviceManager*)userData;
+
+ if (NULL == manager)
+ return;
+
+ if (store == &manager->typeStore)
+ manager->EventTypeRemoved((ifc_devicetype*)object);
+ else if (store == &manager->connectionStore)
+ manager->EventConnectionRemoved((ifc_deviceconnection*)object);
+ else if (store == &manager->commandStore)
+ manager->EventCommandRemoved((ifc_devicecommand*)object);
+ else if (store == &manager->deviceStore)
+ manager->EventDeviceRemoved((ifc_device*)object);
+}
+
+
+void DeviceManager::EventTypeAdded(ifc_devicetype *type)
+{
+ EnterCriticalSection(&eventLock);
+
+ size_t index = eventList.size();
+ while(index--)
+ {
+ ifc_devicemanagerevent *handler = eventList[index];
+ handler->TypeAdded((api_devicemanager*)this, type);
+ }
+
+ LeaveCriticalSection(&eventLock);
+}
+
+void DeviceManager::EventTypeRemoved(ifc_devicetype *type)
+{
+ EnterCriticalSection(&eventLock);
+
+ size_t index = eventList.size();
+ while(index--)
+ {
+ ifc_devicemanagerevent *handler = eventList[index];
+ handler->TypeRemoved((api_devicemanager*)this, type);
+ }
+
+ LeaveCriticalSection(&eventLock);
+}
+
+void DeviceManager::EventConnectionAdded(ifc_deviceconnection *connection)
+{
+ EnterCriticalSection(&eventLock);
+
+ size_t index = eventList.size();
+ while(index--)
+ {
+ ifc_devicemanagerevent *handler = eventList[index];
+ handler->ConnectionAdded((api_devicemanager*)this, connection);
+ }
+
+ LeaveCriticalSection(&eventLock);
+}
+
+void DeviceManager::EventConnectionRemoved(ifc_deviceconnection *connection)
+{
+ EnterCriticalSection(&eventLock);
+
+ size_t index = eventList.size();
+ while(index--)
+ {
+ ifc_devicemanagerevent *handler = eventList[index];
+ handler->ConnectionRemoved((api_devicemanager*)this, connection);
+ }
+
+ LeaveCriticalSection(&eventLock);
+}
+
+void DeviceManager::EventCommandAdded(ifc_devicecommand *command)
+{
+ EnterCriticalSection(&eventLock);
+
+ size_t index = eventList.size();
+ while(index--)
+ {
+ ifc_devicemanagerevent *handler = eventList[index];
+ handler->CommandAdded((api_devicemanager*)this, command);
+ }
+
+ LeaveCriticalSection(&eventLock);
+}
+
+void DeviceManager::EventCommandRemoved(ifc_devicecommand *command)
+{
+ EnterCriticalSection(&eventLock);
+
+ size_t index = eventList.size();
+ while(index--)
+ {
+ ifc_devicemanagerevent *handler = eventList[index];
+ handler->CommandRemoved((api_devicemanager*)this, command);
+ }
+
+ LeaveCriticalSection(&eventLock);
+}
+
+void DeviceManager::EventDeviceAdded(ifc_device *device)
+{
+ EnterCriticalSection(&eventLock);
+
+ size_t index = eventList.size();
+ while(index--)
+ {
+ ifc_devicemanagerevent *handler = eventList[index];
+ handler->DeviceAdded((api_devicemanager*)this, device);
+ }
+
+ LeaveCriticalSection(&eventLock);
+}
+
+void DeviceManager::EventDeviceRemoved(ifc_device *device)
+{
+ EnterCriticalSection(&eventLock);
+
+ size_t index = eventList.size();
+ while(index--)
+ {
+ ifc_devicemanagerevent *handler = eventList[index];
+ handler->DeviceRemoved((api_devicemanager*)this, device);
+ }
+
+ LeaveCriticalSection(&eventLock);
+}
+
+void DeviceManager::EventDiscoveryStarted()
+{
+ EnterCriticalSection(&eventLock);
+
+ size_t index = eventList.size();
+ while(index--)
+ {
+ ifc_devicemanagerevent *handler = eventList[index];
+ handler->DiscoveryStarted((api_devicemanager*)this);
+ }
+
+ LeaveCriticalSection(&eventLock);
+}
+
+void DeviceManager::EventDiscoveryFinished()
+{
+ EnterCriticalSection(&eventLock);
+
+ size_t index = eventList.size();
+ while(index--)
+ {
+ ifc_devicemanagerevent *handler = eventList[index];
+ handler->DiscoveryFinished((api_devicemanager*)this);
+ }
+
+ LeaveCriticalSection(&eventLock);
+}
+
+#define CBCLASS DeviceManager
+START_DISPATCH;
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(QUERYINTERFACE, QueryInterface)
+CB(API_TYPEREGISTER, TypeRegister)
+CB(API_TYPEREGISTERINDIRECT, TypeRegisterIndirect)
+CB(API_TYPEUNREGISTER, TypeUnregister)
+CB(API_TYPEFIND, TypeFind)
+CB(API_TYPEENUMERATE, TypeEnumerate)
+CB(API_CONNECTIONREGISTER, ConnectionRegister)
+CB(API_CONNECTIONREGISTERINDIRECT, ConnectionRegisterIndirect)
+CB(API_CONNECTIONUNREGISTER, ConnectionUnregister)
+CB(API_CONNECTIONFIND, ConnectionFind)
+CB(API_CONNECTIONENUMERATE, ConnectionEnumerate)
+CB(API_COMMANDREGISTER, CommandRegister)
+CB(API_COMMANDREGISTERINDIRECT, CommandRegisterIndirect)
+CB(API_COMMANDUNREGISTER, CommandUnregister)
+CB(API_COMMANDFIND, CommandFind)
+CB(API_COMMANDENUMERATE, CommandEnumerate)
+CB(API_DEVICEREGISTER, DeviceRegister)
+CB(API_DEVICEUNREGISTER, DeviceUnregister)
+CB(API_DEVICEFIND, DeviceFind)
+CB(API_DEVICEENUMERATE, DeviceEnumerate)
+CB(API_ISDISCOVERYACTIVE, IsDiscoveryActive)
+CB(API_BEGINDISCOVERY, BeginDiscovery)
+CB(API_CANCELDISCOVERY, CancelDiscovery)
+CB(API_REGISTERPROVIDER, RegisterProvider)
+CB(API_UNREGISTERPROVIDER, UnregisterProvider)
+CB(API_SETPROVIDERACTIVE, SetProviderActive)
+CB(API_ADVISE, Advise)
+CB(API_UNADVISE, Unadvise)
+CB(API_CREATEDEVICEEVENTMANAGER, CreateDeviceEventManager)
+CB(API_CREATESUPPORTEDCOMMANDSTORE, CreateSupportedCommandStore)
+CB(API_CREATESUPPORTEDCOMMANDENUM, CreateSupportedCommandEnum)
+CB(API_CREATEICONSTORE, CreateIconStore)
+CB(API_CREATETYPE, CreateType)
+CB(API_CREATECOMMAND, CreateCommand)
+CB(API_CREATECONNECTION, CreateConnection)
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/devices/deviceManager.h b/Src/devices/deviceManager.h
new file mode 100644
index 000000000..df076cb9a
--- /dev/null
+++ b/Src/devices/deviceManager.h
@@ -0,0 +1,111 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include "./api_devicemanager.h"
+#include "./deviceObjectStore.h"
+#include "./discoveryMonitor.h"
+#include <vector>
+
+class DeviceManager : public api_devicemanager
+{
+
+protected:
+ DeviceManager();
+ ~DeviceManager();
+
+public:
+ static HRESULT CreateInstance(DeviceManager **instance);
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* api_devicemanager */
+ size_t TypeRegister(ifc_devicetype **types, size_t count);
+ size_t TypeRegisterIndirect(const char **names, size_t count, DeviceTypeCreator callback, void *user);
+ HRESULT TypeUnregister(const char *name);
+ HRESULT TypeFind(const char *name, ifc_devicetype **type);
+ HRESULT TypeEnumerate(ifc_deviceobjectenum **enumerator);
+
+ size_t ConnectionRegister(ifc_deviceconnection **connections, size_t count);
+ size_t ConnectionRegisterIndirect(const char **names, size_t count, DeviceConnectionCreator callback, void *user);
+ HRESULT ConnectionUnregister(const char *name);
+ HRESULT ConnectionFind(const char *name, ifc_deviceconnection **connection);
+ HRESULT ConnectionEnumerate(ifc_deviceobjectenum **enumerator);
+
+ size_t CommandRegister(ifc_devicecommand **commands, size_t count);
+ size_t CommandRegisterIndirect(const char **names, size_t count, DeviceCommandCreator callback, void *user);
+ HRESULT CommandUnregister(const char *name);
+ HRESULT CommandFind(const char *name, ifc_devicecommand **command);
+ HRESULT CommandEnumerate(ifc_deviceobjectenum **enumerator);
+
+ size_t DeviceRegister(ifc_device **devices, size_t count);
+ HRESULT DeviceUnregister(const char *name);
+ HRESULT DeviceFind(const char *name, ifc_device **device);
+ HRESULT DeviceEnumerate(ifc_deviceobjectenum **enumerator);
+
+ HRESULT IsDiscoveryActive();
+ HRESULT BeginDiscovery();
+ HRESULT CancelDiscovery();
+ HRESULT RegisterProvider(ifc_deviceprovider *provider);
+ HRESULT UnregisterProvider(ifc_deviceprovider *provider);
+ HRESULT SetProviderActive(ifc_deviceprovider *provider, BOOL activeState);
+
+ HRESULT Advise(ifc_devicemanagerevent *handler);
+ HRESULT Unadvise(ifc_devicemanagerevent *handler);
+
+ HRESULT CreateDeviceEventManager(ifc_deviceeventmanager **eventManager);
+ HRESULT CreateSupportedCommandStore(ifc_devicesupportedcommandstore **store);
+ HRESULT CreateSupportedCommandEnum(ifc_devicesupportedcommand **commands, size_t count, ifc_devicesupportedcommandenum **enumerator);
+ HRESULT CreateIconStore(ifc_deviceiconstore **store);
+ HRESULT CreateType(const char *name, ifc_devicetype **type);
+ HRESULT CreateCommand(const char *name, ifc_devicecommand **command);
+ HRESULT CreateConnection(const char *name, ifc_deviceconnection **connection);
+
+protected:
+ void EventTypeAdded(ifc_devicetype *type);
+ void EventTypeRemoved(ifc_devicetype *type);
+ void EventConnectionAdded(ifc_deviceconnection *connection);
+ void EventConnectionRemoved(ifc_deviceconnection *connection);
+ void EventCommandAdded(ifc_devicecommand *command);
+ void EventCommandRemoved(ifc_devicecommand *command);
+ void EventDeviceAdded(ifc_device *device);
+ void EventDeviceRemoved(ifc_device *device);
+ void EventDiscoveryStarted();
+ void EventDiscoveryFinished();
+
+protected:
+ static void ObjectAddedCallback(DeviceObjectStore *store, ifc_deviceobject *object, void *userData);
+ static void ObjectRemovedCallback(DeviceObjectStore *store, ifc_deviceobject *object, void *userData);
+
+protected:
+ typedef std::vector<ifc_devicemanagerevent*> EventList;
+ typedef std::vector<ifc_deviceprovider*> ProviderList;
+
+protected:
+ size_t ref;
+
+ DeviceObjectStore typeStore;
+ DeviceObjectStore connectionStore;
+ DeviceObjectStore commandStore;
+ DeviceObjectStore deviceStore;
+
+ CRITICAL_SECTION eventLock;
+ EventList eventList;
+
+ CRITICAL_SECTION providerLock;
+ ProviderList providerList;
+
+ DiscoveryMonitor discoveryMonitor;
+
+protected:
+ RECVS_DISPATCH;
+};
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_HEADER
diff --git a/Src/devices/deviceManagerFactory.cpp b/Src/devices/deviceManagerFactory.cpp
new file mode 100644
index 000000000..8ee804cde
--- /dev/null
+++ b/Src/devices/deviceManagerFactory.cpp
@@ -0,0 +1,100 @@
+#include "main.h"
+#include "./deviceManager.h"
+#include "./deviceManagerFactory.h"
+
+DeviceManagerFactory::DeviceManagerFactory()
+ : object(NULL)
+{
+}
+
+DeviceManagerFactory::~DeviceManagerFactory()
+{
+ if (NULL != object)
+ object->Release();
+}
+
+FOURCC DeviceManagerFactory::GetServiceType()
+{
+ return WaSvc::UNIQUE;
+}
+
+const char *DeviceManagerFactory::GetServiceName()
+{
+ return "Device Manager Interface";
+}
+
+GUID DeviceManagerFactory::GetGUID()
+{
+ return DeviceManagerGUID;
+}
+
+void *DeviceManagerFactory::GetInterface(int global_lock)
+{
+ if (NULL == object)
+ {
+ if (FAILED(DeviceManager::CreateInstance(&object)))
+ object = NULL;
+
+ if (NULL == object)
+ return NULL;
+ }
+
+ object->AddRef();
+ return object;
+}
+
+int DeviceManagerFactory::SupportNonLockingInterface()
+{
+ return 1;
+}
+
+int DeviceManagerFactory::ReleaseInterface(void *ifc)
+{
+ DeviceManager *object = (DeviceManager*)ifc;
+ if (NULL != object)
+ object->Release();
+
+ return 1;
+}
+
+const char *DeviceManagerFactory::GetTestString()
+{
+ return NULL;
+}
+
+int DeviceManagerFactory::ServiceNotify(int msg, int param1, int param2)
+{
+ return 1;
+}
+
+HRESULT DeviceManagerFactory::Register(api_service *service)
+{
+ if (NULL == service)
+ return E_INVALIDARG;
+
+ service->service_register(this);
+ return S_OK;
+}
+
+HRESULT DeviceManagerFactory::Unregister(api_service *service)
+{
+ if (NULL == service)
+ return E_INVALIDARG;
+
+ service->service_deregister(this);
+ return S_OK;
+}
+
+#define CBCLASS DeviceManagerFactory
+START_DISPATCH;
+CB( WASERVICEFACTORY_GETSERVICETYPE, GetServiceType )
+CB( WASERVICEFACTORY_GETSERVICENAME, GetServiceName )
+CB( WASERVICEFACTORY_GETGUID, GetGUID )
+CB( WASERVICEFACTORY_GETINTERFACE, GetInterface )
+CB( WASERVICEFACTORY_SUPPORTNONLOCKINGGETINTERFACE, SupportNonLockingInterface )
+CB( WASERVICEFACTORY_RELEASEINTERFACE, ReleaseInterface )
+CB( WASERVICEFACTORY_GETTESTSTRING, GetTestString )
+CB( WASERVICEFACTORY_SERVICENOTIFY, ServiceNotify )
+END_DISPATCH;
+
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/devices/deviceManagerFactory.h b/Src/devices/deviceManagerFactory.h
new file mode 100644
index 000000000..f57595876
--- /dev/null
+++ b/Src/devices/deviceManagerFactory.h
@@ -0,0 +1,42 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_FACTORY_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_FACTORY_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <api/service/waservicefactory.h>
+#include <api/service/services.h>
+
+class DeviceManager;
+
+class DeviceManagerFactory : public waServiceFactory
+{
+public:
+ DeviceManagerFactory();
+ ~DeviceManagerFactory();
+
+public:
+ FOURCC GetServiceType();
+ const char *GetServiceName();
+ GUID GetGUID();
+ void *GetInterface(int global_lock);
+ int SupportNonLockingInterface();
+ int ReleaseInterface(void *ifc);
+ const char *GetTestString();
+ int ServiceNotify(int msg, int param1, int param2);
+
+public:
+ HRESULT Register(api_service *service);
+ HRESULT Unregister(api_service *service);
+
+protected:
+ RECVS_DISPATCH;
+
+protected:
+ DeviceManager *object;
+};
+
+
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_FACTORY_HEADER
diff --git a/Src/devices/deviceObjectEnum.cpp b/Src/devices/deviceObjectEnum.cpp
new file mode 100644
index 000000000..e60b39d63
--- /dev/null
+++ b/Src/devices/deviceObjectEnum.cpp
@@ -0,0 +1,175 @@
+#include "main.h"
+#include "./deviceObjectEnum.h"
+#include <new>
+
+DeviceObjectEnum::DeviceObjectEnum()
+ : ref(1), buffer(NULL), size(0), cursor(0)
+{
+}
+
+DeviceObjectEnum::~DeviceObjectEnum()
+{
+ if (NULL != buffer)
+ {
+ while(size--)
+ {
+ buffer[size]->Release();
+ }
+ }
+}
+
+HRESULT DeviceObjectEnum::CreateInstance(ifc_deviceobject **objects,
+ size_t count,
+ DeviceObjectEnum **instance)
+{
+ size_t index, size;
+ void *storage;
+ ifc_deviceobject *o;
+ DeviceObjectEnum *enumerator;
+
+
+ if (NULL == instance)
+ return E_POINTER;
+
+ *instance = NULL;
+
+ size = sizeof(DeviceObjectEnum) + (sizeof(ifc_deviceobject**) * count);
+ storage = calloc(1, size);
+ if (NULL == storage)
+ return E_OUTOFMEMORY;
+
+ enumerator = new(storage) DeviceObjectEnum();
+ if (NULL == enumerator)
+ {
+ free(storage);
+ return E_FAIL;
+ }
+
+ enumerator->buffer = (ifc_deviceobject**)(((BYTE*)enumerator) + sizeof(DeviceObjectEnum));
+
+ for (index = 0; index < count; index++)
+ {
+ o = objects[index];
+ if (NULL != o)
+ {
+ enumerator->buffer[enumerator->size] = o;
+ o->AddRef();
+ enumerator->size++;
+ }
+ }
+
+ *instance = enumerator;
+ return S_OK;
+}
+
+
+
+size_t DeviceObjectEnum::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t DeviceObjectEnum::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int DeviceObjectEnum::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object) return E_POINTER;
+
+ if (IsEqualIID(interface_guid, IFC_DeviceObjectEnum))
+ *object = static_cast<ifc_deviceobjectenum*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+HRESULT DeviceObjectEnum::Next(ifc_deviceobject **objects, size_t bufferMax, size_t *fetched)
+{
+ size_t available, copied, index;
+ ifc_deviceobject **source;
+
+ if (NULL == objects)
+ return E_POINTER;
+
+ if (0 == bufferMax)
+ return E_INVALIDARG;
+
+ if (cursor >= size)
+ {
+ if (NULL != fetched)
+ *fetched = 0;
+
+ return S_FALSE;
+ }
+
+ available = size - cursor;
+ copied = ((available > bufferMax) ? bufferMax : available);
+
+ source = buffer + cursor;
+ CopyMemory(objects, source, copied * sizeof(ifc_deviceobject*));
+
+ for(index = 0; index < copied; index++)
+ objects[index]->AddRef();
+
+ cursor += copied;
+
+ if (NULL != fetched)
+ *fetched = copied;
+
+ return (bufferMax == copied) ? S_OK : S_FALSE;
+}
+
+HRESULT DeviceObjectEnum::Reset(void)
+{
+ cursor = 0;
+ return S_OK;
+}
+
+HRESULT DeviceObjectEnum::Skip(size_t count)
+{
+ cursor += count;
+ if (cursor > size)
+ cursor = size;
+
+ return (cursor < size) ? S_OK : S_FALSE;
+}
+
+
+HRESULT DeviceObjectEnum::GetCount(size_t *count)
+{
+ if (NULL == count)
+ return E_POINTER;
+
+ *count = size;
+
+ return S_OK;
+}
+
+#define CBCLASS DeviceObjectEnum
+START_DISPATCH;
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(QUERYINTERFACE, QueryInterface)
+CB(API_NEXT, Next)
+CB(API_RESET, Reset)
+CB(API_SKIP, Skip)
+CB(API_GETCOUNT, GetCount)
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/devices/deviceObjectEnum.h b/Src/devices/deviceObjectEnum.h
new file mode 100644
index 000000000..7efbcbb4d
--- /dev/null
+++ b/Src/devices/deviceObjectEnum.h
@@ -0,0 +1,44 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_ENUMERATOR_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_ENUMERATOR_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include "./ifc_deviceobject.h"
+#include "./ifc_deviceobjectenum.h"
+
+class DeviceObjectEnum : public ifc_deviceobjectenum
+{
+protected:
+ DeviceObjectEnum();
+ ~DeviceObjectEnum();
+
+public:
+ static HRESULT CreateInstance(ifc_deviceobject **objects,
+ size_t count,
+ DeviceObjectEnum **instance);
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* ifc_deviceobjectenum */
+ HRESULT Next(ifc_deviceobject **objects, size_t bufferMax, size_t *fetched);
+ HRESULT Reset(void);
+ HRESULT Skip(size_t count);
+ HRESULT GetCount(size_t *count);
+
+protected:
+ size_t ref;
+ ifc_deviceobject **buffer;
+ size_t size;
+ size_t cursor;
+
+protected:
+ RECVS_DISPATCH;
+};
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_ENUMERATOR_HEADER \ No newline at end of file
diff --git a/Src/devices/deviceObjectStore.cpp b/Src/devices/deviceObjectStore.cpp
new file mode 100644
index 000000000..075270cd5
--- /dev/null
+++ b/Src/devices/deviceObjectStore.cpp
@@ -0,0 +1,356 @@
+#include "main.h"
+#include "./deviceObjectStore.h"
+#include <algorithm>
+
+template <typename T>
+struct GenericComparator
+{
+ typedef const char* (T::*GETTER)();
+ GETTER m_getterFunc;
+ const char *m_data;
+ GenericComparator(GETTER getterFunc, const char *data)
+ {
+ m_getterFunc = getterFunc;
+ m_data = data;
+ }
+ bool operator()(const T& obj)
+ {
+ return strcmp(((obj).*m_getterFunc)(), m_data) == 0;
+ }
+};
+
+static ifc_deviceobject *
+DeviceObjectStore_FindLocation(const char *name, std::vector<ifc_deviceobject*> &list)
+{
+ if (FALSE != IS_STRING_EMPTY(name))
+ return NULL;
+
+ //size_t name_length;
+ //name_length = lstrlenA(name) * sizeof(char);
+ //
+ //return (ifc_deviceobject*)bsearch_s(name, buffer, length,
+ // sizeof(ifc_deviceobject*),
+ // DeviceObjectStore_FindComparer,
+ // (void*)name_length);
+
+ //auto it = std::find_if(list.begin(), list.begin(), GenericComparator<ifc_deviceobject>(&ifc_deviceobject::GetName, name));
+
+ const auto it = std::find_if(list.begin(), list.end(),
+ [&](ifc_deviceobject* upT) -> bool
+ {
+ return strcmp(upT->GetName(), name) == 0;
+ }
+ );
+ if (it != list.end())
+ {
+ return *it;
+ }
+ return nullptr;
+}
+
+int DeviceObjectComparer(const char* arg1, const char* arg2)
+{
+ return stricmp(arg1, arg2);
+}
+
+
+// Created for std::sort
+static bool DeviceObjectStore_SortComparer_V2(const void* element1, const void* element2)
+{
+ //return DeviceObjectStore_SortComparer(element1, element2) < 0;
+ const char* name1 = (((ifc_deviceobject*)element1))->GetName();
+ const char* name2 = (((ifc_deviceobject*)element2))->GetName();
+ return DeviceObjectComparer(name1, name2) < 0;
+}
+
+static ifc_deviceobject *
+DeviceObjectStore_FindUnsortedObject(const char *name, ifc_deviceobject **objects, size_t count)
+{
+ size_t index;
+ size_t length;
+
+ if (0 == count)
+ return NULL;
+
+ length = lstrlenA(name) * sizeof(char);
+
+ for(index = 0; index < count; index++)
+ {
+ //if (0 == DeviceObjectStore_NameCompare(name, length, objects[index]->GetName()))
+ if(0 == DeviceObjectComparer(name, objects[index]->GetName()))
+ return objects[index];
+ }
+
+ return NULL;
+}
+
+
+DeviceObjectStore::DeviceObjectStore(DeviceObjectCallback addCallback,
+ DeviceObjectCallback _removeCallback, void *callbackData)
+{
+ this->addCallback = addCallback;
+ this->removeCallback = _removeCallback;
+ this->callbackData = callbackData;
+
+ InitializeCriticalSection(&lock);
+}
+
+DeviceObjectStore::~DeviceObjectStore()
+{
+ RemoveAll();
+ DeleteCriticalSection(&lock);
+}
+
+void DeviceObjectStore::Lock()
+{
+ EnterCriticalSection(&lock);
+}
+
+void DeviceObjectStore::Unlock()
+{
+ LeaveCriticalSection(&lock);
+}
+
+CRITICAL_SECTION *DeviceObjectStore::GetLock()
+{
+ return &lock;
+}
+
+HRESULT DeviceObjectStore::Add(ifc_deviceobject *object)
+{
+ const char *name;
+
+ if (NULL == object)
+ return E_POINTER;
+
+ name = object->GetName();
+
+ if (NULL == name || '\0' == *name)
+ return E_INVALIDARG;
+
+ return (1 == AddRange(&object, 1)) ? S_OK : S_FALSE;
+}
+
+size_t DeviceObjectStore::AddRange(ifc_deviceobject **objects, size_t count)
+{
+ const char *name;
+ size_t index, registered, added;
+ ifc_deviceobject *object;
+
+
+ if (NULL == objects || 0 == count)
+ return 0;
+
+ Lock();
+
+ added = 0;
+ registered = list.size();
+
+ for(index = 0; index < count; index++)
+ {
+ object = objects[index];
+ if (NULL != object)
+ {
+ name = object->GetName();
+
+ if (NULL != name &&
+ '\0' != *name &&
+ NULL == DeviceObjectStore_FindLocation(name, list))
+ //&& NULL == DeviceObjectStore_FindUnsortedObject(name, buffer + registered, added))
+ {
+ list.push_back(object);
+ object->AddRef();
+
+ if (NULL != addCallback)
+ this->addCallback(this, object, callbackData);
+
+ added++;
+ }
+ }
+ }
+
+ if (0 != added)
+ {
+ //qsort(list.first(), list.size(),
+ // sizeof(ifc_deviceobject**),
+ // DeviceObjectStore_SortComparer);
+
+ std::sort(list.begin(), list.end(), DeviceObjectStore_SortComparer_V2);
+ }
+
+ Unlock();
+
+ return added;
+}
+
+size_t DeviceObjectStore::AddIndirect(const char **names, size_t count, DeviceObjectCreator callback, void *user)
+{
+ size_t index, registered, added;
+ ifc_deviceobject *object;
+
+ if (NULL == names || 0 == count || NULL == callback)
+ return 0;
+
+ Lock();
+
+ added = 0;
+ registered = list.size();
+
+
+ for(index = 0; index < count; index++)
+ {
+ const char *name = names[index];
+
+ if (NULL != name &&
+ '\0' != *name &&
+ NULL == DeviceObjectStore_FindLocation(name, list) )
+ //&& NULL == DeviceObjectStore_FindUnsortedObject(name, buffer + registered, added))
+ {
+ object = callback(name, user);
+ if (NULL != object)
+ {
+ list.push_back(object);
+
+ if (NULL != addCallback)
+ this->addCallback(this, object, callbackData);
+
+ added++;
+ }
+ }
+ }
+
+ if (0 != added)
+ {
+ //qsort(list.first(), list.size(),
+ // sizeof(ifc_deviceobject**),
+ // DeviceObjectStore_SortComparer);
+
+ std::sort(list.begin(), list.end(), DeviceObjectStore_SortComparer_V2);
+ }
+
+ Unlock();
+
+ return added;
+}
+
+HRESULT DeviceObjectStore::Remove(const char *name)
+{
+ HRESULT hr = hr = S_FALSE;
+
+ if (NULL == name || '\0' == *name)
+ return E_INVALIDARG;
+
+ Lock();
+
+ //object_ptr = DeviceObjectStore_FindLocation(name, list);
+ //if (NULL != object_ptr)
+ //{
+ // hr = S_OK;
+
+ // ifc_deviceobject *object = *object_ptr;
+
+ // size_t index = (size_t)(object_ptr - buffer);
+ // list.erase(list.begin() + index);
+
+ // if (NULL != removeCallback)
+ // removeCallback(this, object, callbackData);
+
+ // object->Release();
+ //}
+ //else
+ //{
+ // hr = S_FALSE;
+ //}
+
+ const auto it = std::find_if(list.begin(), list.end(),
+ [&](ifc_deviceobject* upT) -> bool
+ {
+ return strcmp(upT->GetName(), name) == 0;
+ }
+ );
+
+ if (it != list.end())
+ {
+ ifc_deviceobject* object = *it;
+ list.erase(it);
+ if (NULL != removeCallback)
+ {
+ removeCallback(this, object, callbackData);
+ }
+ object->Release();
+ hr = S_OK;
+ }
+ Unlock();
+
+ return hr;
+}
+
+void DeviceObjectStore::RemoveAll()
+{
+ Lock();
+
+ size_t index = list.size();
+ while(index--)
+ {
+ ifc_deviceobject *object = list[index];
+ if (NULL != removeCallback)
+ removeCallback(this, object, callbackData);
+
+ object->Release();
+ }
+
+ list.clear();
+ Unlock();
+}
+
+HRESULT DeviceObjectStore::Find(const char *name, ifc_deviceobject **object)
+{
+ HRESULT hr;
+ ifc_deviceobject *object_ptr;
+
+ if (NULL == name || '\0' == *name)
+ return E_INVALIDARG;
+
+ if (NULL == object)
+ return E_POINTER;
+
+ Lock();
+
+ object_ptr = DeviceObjectStore_FindLocation(name, list);
+
+ if (NULL != object_ptr)
+ {
+ if (NULL != object)
+ {
+ *object = object_ptr;
+ (*object)->AddRef();
+ }
+ hr = S_OK;
+ }
+ else
+ {
+ if (NULL != object)
+ *object = NULL;
+ hr = S_FALSE;
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceObjectStore::Enumerate(DeviceObjectEnum **enumerator)
+{
+ HRESULT hr;
+
+ if (NULL == enumerator)
+ return E_POINTER;
+
+ Lock();
+
+ hr = DeviceObjectEnum::CreateInstance(list.size() ? &list.at(0) : nullptr, list.size(), enumerator);
+
+ Unlock();
+
+ return hr;
+}
diff --git a/Src/devices/deviceObjectStore.h b/Src/devices/deviceObjectStore.h
new file mode 100644
index 000000000..fad1f8585
--- /dev/null
+++ b/Src/devices/deviceObjectStore.h
@@ -0,0 +1,55 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_STORE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_STORE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include "./ifc_deviceobject.h"
+#include "./deviceObjectEnum.h"
+#include <vector>
+
+class DeviceObjectStore;
+
+typedef void (__cdecl *DeviceObjectCallback)(DeviceObjectStore * /*store*/,
+ ifc_deviceobject * /*object*/,
+ void * /*user*/);
+
+typedef ifc_deviceobject *(_cdecl *DeviceObjectCreator)(const char * /*name*/,
+ void * /*user*/);
+
+class DeviceObjectStore
+{
+public:
+ DeviceObjectStore(DeviceObjectCallback addCallback,
+ DeviceObjectCallback removeCallback,
+ void *callbackData);
+
+ ~DeviceObjectStore();
+
+public:
+ void Lock();
+ void Unlock();
+ CRITICAL_SECTION *GetLock();
+
+ HRESULT Add(ifc_deviceobject *object);
+ size_t AddRange(ifc_deviceobject **objects, size_t count);
+ size_t AddIndirect(const char **names, size_t count, DeviceObjectCreator callback, void *user);
+
+ HRESULT Remove(const char *name);
+ void RemoveAll();
+ HRESULT Find(const char *name, ifc_deviceobject **object);
+ HRESULT Enumerate(DeviceObjectEnum **enumerator);
+
+private:
+ std::vector<ifc_deviceobject*> list;
+ CRITICAL_SECTION lock;
+ DeviceObjectCallback addCallback;
+ DeviceObjectCallback removeCallback;
+ void *callbackData;
+
+
+
+};
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_STORE_HEADER \ No newline at end of file
diff --git a/Src/devices/deviceSupportedCommand.cpp b/Src/devices/deviceSupportedCommand.cpp
new file mode 100644
index 000000000..b5e091471
--- /dev/null
+++ b/Src/devices/deviceSupportedCommand.cpp
@@ -0,0 +1,120 @@
+#include "main.h"
+#include "./deviceSupportedCommand.h"
+
+DeviceSupportedCommand::DeviceSupportedCommand()
+ : ref(1), name(NULL), flags(DeviceCommandFlag_None)
+{
+}
+
+DeviceSupportedCommand::~DeviceSupportedCommand()
+{
+ AnsiString_Free(name);
+}
+
+HRESULT DeviceSupportedCommand::CreateInstance(const char *name, DeviceSupportedCommand **instance)
+{
+ DeviceSupportedCommand *self;
+
+ if (NULL == instance)
+ return E_POINTER;
+
+ *instance = NULL;
+
+ self = new DeviceSupportedCommand();
+ if (NULL == self)
+ return E_OUTOFMEMORY;
+
+ self->name = AnsiString_Duplicate(name);
+
+ *instance = self;
+ return S_OK;
+}
+
+size_t DeviceSupportedCommand::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t DeviceSupportedCommand::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int DeviceSupportedCommand::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object)
+ return E_POINTER;
+
+ if (IsEqualIID(interface_guid, IFC_DeviceSupportedCommand))
+ *object = static_cast<ifc_devicesupportedcommand*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+const char *DeviceSupportedCommand::GetName()
+{
+ return name;
+}
+
+HRESULT DeviceSupportedCommand::GetFlags(DeviceCommandFlags *flagsOut)
+{
+ if (NULL == flagsOut)
+ return E_POINTER;
+
+ *flagsOut = flags;
+
+ return S_OK;
+}
+
+HRESULT DeviceSupportedCommand::SetFlags(DeviceCommandFlags mask, DeviceCommandFlags value)
+{
+ DeviceCommandFlags temp;
+ temp = (flags & mask) | (mask & value);
+
+ if (temp == flags)
+ return S_FALSE;
+
+ flags = temp;
+
+ return S_OK;
+}
+
+HRESULT DeviceSupportedCommand::Clone(DeviceSupportedCommand **instance)
+{
+ HRESULT hr;
+
+ hr = DeviceSupportedCommand::CreateInstance(name, instance);
+ if (SUCCEEDED(hr))
+ {
+ (*instance)->flags = flags;
+ }
+
+ return hr;
+
+}
+
+#define CBCLASS DeviceSupportedCommand
+START_DISPATCH;
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(QUERYINTERFACE, QueryInterface)
+CB(API_GETNAME, GetName)
+CB(API_GETFLAGS, GetFlags)
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/devices/deviceSupportedCommand.h b/Src/devices/deviceSupportedCommand.h
new file mode 100644
index 000000000..c0d0fce54
--- /dev/null
+++ b/Src/devices/deviceSupportedCommand.h
@@ -0,0 +1,47 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <wtypes.h>
+#include "./ifc_devicesupportedcommand.h"
+
+
+class DeviceSupportedCommand : public ifc_devicesupportedcommand
+{
+protected:
+ DeviceSupportedCommand();
+ ~DeviceSupportedCommand();
+
+public:
+ static HRESULT CreateInstance(const char *name,
+ DeviceSupportedCommand **instance);
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* ifc_devicesupportedcommand */
+ const char *GetName();
+ HRESULT GetFlags(DeviceCommandFlags *flags);
+
+public:
+ HRESULT SetFlags(DeviceCommandFlags mask, DeviceCommandFlags value);
+ HRESULT Clone(DeviceSupportedCommand **instance);
+
+protected:
+ size_t ref;
+ char *name;
+ DeviceCommandFlags flags;
+
+
+protected:
+ RECVS_DISPATCH;
+};
+
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_HEADER \ No newline at end of file
diff --git a/Src/devices/deviceSupportedCommandEnum.cpp b/Src/devices/deviceSupportedCommandEnum.cpp
new file mode 100644
index 000000000..9466f378d
--- /dev/null
+++ b/Src/devices/deviceSupportedCommandEnum.cpp
@@ -0,0 +1,172 @@
+#include "main.h"
+#include "./deviceSupportedCommandEnum.h"
+#include <new>
+
+DeviceSupportedCommandEnum::DeviceSupportedCommandEnum()
+ : ref(1), commands(NULL), count(0), cursor(0)
+{
+}
+
+DeviceSupportedCommandEnum::~DeviceSupportedCommandEnum()
+{
+ if (NULL != commands)
+ {
+ while(count--)
+ commands[count]->Release();
+ }
+}
+
+HRESULT DeviceSupportedCommandEnum::CreateInstance(ifc_devicesupportedcommand **commands, size_t count,
+ DeviceSupportedCommandEnum **instance)
+{
+ size_t index, size;
+ void *storage;
+ ifc_devicesupportedcommand *c;
+ DeviceSupportedCommandEnum *enumerator;
+
+
+ if (NULL == instance)
+ return E_POINTER;
+
+ *instance = NULL;
+
+ size = sizeof(DeviceSupportedCommandEnum) + (sizeof(ifc_devicesupportedcommand**) * count);
+ storage = calloc(1, size);
+ if (NULL == storage)
+ return E_OUTOFMEMORY;
+
+ enumerator = new(storage) DeviceSupportedCommandEnum();
+ if (NULL == enumerator)
+ {
+ free(storage);
+ return E_FAIL;
+ }
+
+ enumerator->commands = (ifc_devicesupportedcommand**)(((BYTE*)enumerator) + sizeof(DeviceSupportedCommandEnum));
+
+ for (index = 0; index < count; index++)
+ {
+ c = commands[index];
+ if (NULL != c)
+ {
+ enumerator->commands[enumerator->count] = c;
+ c->AddRef();
+ enumerator->count++;
+ }
+ }
+
+ *instance = enumerator;
+ return S_OK;
+}
+
+
+
+size_t DeviceSupportedCommandEnum::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t DeviceSupportedCommandEnum::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int DeviceSupportedCommandEnum::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object) return E_POINTER;
+
+ if (IsEqualIID(interface_guid, IFC_DeviceSupportedCommandEnum))
+ *object = static_cast<ifc_devicesupportedcommandenum*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+HRESULT DeviceSupportedCommandEnum::Next(ifc_devicesupportedcommand **objects, size_t bufferMax, size_t *fetched)
+{
+ size_t available, copied, index;
+ ifc_devicesupportedcommand **source;
+
+ if (NULL == objects)
+ return E_POINTER;
+
+ if (0 == bufferMax)
+ return E_INVALIDARG;
+
+ if (cursor >= count)
+ {
+ if (NULL != fetched)
+ *fetched = 0;
+
+ return S_FALSE;
+ }
+
+ available = count - cursor;
+ copied = ((available > bufferMax) ? bufferMax : available);
+
+ source = commands + cursor;
+ CopyMemory(objects, source, copied * sizeof(ifc_devicesupportedcommand*));
+
+ for(index = 0; index < copied; index++)
+ objects[index]->AddRef();
+
+ cursor += copied;
+
+ if (NULL != fetched)
+ *fetched = copied;
+
+ return (bufferMax == copied) ? S_OK : S_FALSE;
+}
+
+HRESULT DeviceSupportedCommandEnum::Reset(void)
+{
+ cursor = 0;
+ return S_OK;
+}
+
+HRESULT DeviceSupportedCommandEnum::Skip(size_t count)
+{
+ cursor += count;
+ if (cursor > this->count)
+ cursor = this->count;
+
+ return (cursor < this->count) ? S_OK : S_FALSE;
+}
+
+
+HRESULT DeviceSupportedCommandEnum::GetCount(size_t *count)
+{
+ if (NULL == count)
+ return E_POINTER;
+
+ *count = this->count;
+
+ return S_OK;
+}
+
+#define CBCLASS DeviceSupportedCommandEnum
+START_DISPATCH;
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(QUERYINTERFACE, QueryInterface)
+CB(API_NEXT, Next)
+CB(API_RESET, Reset)
+CB(API_SKIP, Skip)
+CB(API_GETCOUNT, GetCount)
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/devices/deviceSupportedCommandEnum.h b/Src/devices/deviceSupportedCommandEnum.h
new file mode 100644
index 000000000..976595eec
--- /dev/null
+++ b/Src/devices/deviceSupportedCommandEnum.h
@@ -0,0 +1,48 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_ENUM_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_ENUM_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include "./ifc_devicesupportedcommandenum.h"
+#include "./ifC_devicesupportedcommand.h"
+
+class DeviceSupportedCommandEnum : public ifc_devicesupportedcommandenum
+{
+
+protected:
+ DeviceSupportedCommandEnum();
+ ~DeviceSupportedCommandEnum();
+
+public:
+ static HRESULT CreateInstance(ifc_devicesupportedcommand **commands,
+ size_t count,
+ DeviceSupportedCommandEnum **instance);
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* ifc_devicesupportedcommandenum*/
+ HRESULT Next(ifc_devicesupportedcommand **buffer, size_t bufferMax, size_t *count);
+ HRESULT Reset(void);
+ HRESULT Skip(size_t count);
+ HRESULT GetCount(size_t *count);
+
+protected:
+ size_t ref;
+ ifc_devicesupportedcommand **commands;
+ size_t count;
+ size_t cursor;
+
+protected:
+ RECVS_DISPATCH;
+
+
+
+};
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_ENUM_HEADER \ No newline at end of file
diff --git a/Src/devices/deviceSupportedCommandStore.cpp b/Src/devices/deviceSupportedCommandStore.cpp
new file mode 100644
index 000000000..8e6c90343
--- /dev/null
+++ b/Src/devices/deviceSupportedCommandStore.cpp
@@ -0,0 +1,342 @@
+#include "main.h"
+#include "./deviceSupportedCommandStore.h"
+
+DeviceSupportedCommandStore::DeviceSupportedCommandStore()
+ : ref(1)
+{
+ InitializeCriticalSection(&lock);
+}
+
+DeviceSupportedCommandStore::~DeviceSupportedCommandStore()
+{
+ RemoveAll();
+ DeleteCriticalSection(&lock);
+}
+
+HRESULT DeviceSupportedCommandStore::CreateInstance(DeviceSupportedCommandStore **instance)
+{
+ if (NULL == instance)
+ return E_POINTER;
+
+ *instance = new DeviceSupportedCommandStore();
+
+ if (NULL == *instance)
+ return E_OUTOFMEMORY;
+
+ return S_OK;
+}
+
+size_t DeviceSupportedCommandStore::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t DeviceSupportedCommandStore::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int DeviceSupportedCommandStore::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object) return E_POINTER;
+
+ if (IsEqualIID(interface_guid, IFC_DeviceSupportedCommandStore))
+ *object = static_cast<ifc_devicesupportedcommandstore*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+void DeviceSupportedCommandStore::Lock()
+{
+ EnterCriticalSection(&lock);
+}
+
+void DeviceSupportedCommandStore::Unlock()
+{
+ LeaveCriticalSection(&lock);
+}
+
+int
+DeviceSupportedCommandStore::SortCallback(const void *element1, const void *element2)
+{
+ DeviceSupportedCommand *command1, *command2;
+
+ command1 = *(DeviceSupportedCommand**)element1;
+ command2 = *(DeviceSupportedCommand**)element2;
+
+ return CompareStringA(CSTR_INVARIANT, 0, command1->GetName(), -1, command2->GetName(), -1) - 2;
+}
+
+int
+DeviceSupportedCommandStore::SearchCallback(const void *key, const void *element)
+{
+ const char *name;
+ DeviceSupportedCommand *command;
+
+ name = (const char*)key;
+ command = *(DeviceSupportedCommand**)element;
+
+ return CompareStringA(CSTR_INVARIANT, 0, name, -1, command->GetName(), -1) - 2;
+}
+
+DeviceSupportedCommand *DeviceSupportedCommandStore::Find(const char *name, size_t *indexOut)
+{
+ DeviceSupportedCommand *command;
+ int length;
+ size_t index, count;
+
+ if (NULL == name || '\0' == *name)
+ return NULL;
+
+ length = lstrlenA(name);
+
+ count = commandList.size();
+ for(index = 0; index < count; index++)
+ {
+ command = commandList[index];
+ if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, name, length, command->GetName(), -1))
+ break;
+ }
+
+ if (count == index)
+ return NULL;
+
+ if (NULL != indexOut)
+ *indexOut = index;
+
+ return command;
+
+}
+
+
+HRESULT DeviceSupportedCommandStore::Add(const char *name, DeviceCommandFlags flags)
+{
+ HRESULT hr;
+ DeviceSupportedCommand *command;
+
+
+ hr = DeviceSupportedCommand::CreateInstance(name, &command);
+ if (FAILED(hr))
+ return hr;
+
+ Lock();
+
+ if (NULL == Find(name, NULL))
+ {
+ command->SetFlags(flags, flags);
+ commandList.push_back(command);
+ }
+ else
+ {
+ command->Release();
+ hr = S_FALSE;
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceSupportedCommandStore::Remove(const char *name)
+{
+ HRESULT hr;
+ size_t index;
+ DeviceSupportedCommand *command;
+
+ Lock();
+
+ command = Find(name, &index);
+ if (NULL != command)
+ {
+ commandList.erase(commandList.begin() + index);
+ command->Release();
+ hr = S_OK;
+ }
+ else
+ {
+ hr = S_FALSE;
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceSupportedCommandStore::RemoveAll()
+{
+ Lock();
+
+ size_t index = commandList.size();
+ while(index--)
+ {
+ DeviceSupportedCommand *command = commandList[index];
+ command->Release();
+ }
+
+ commandList.clear();
+
+ Unlock();
+
+ return S_OK;
+}
+
+HRESULT DeviceSupportedCommandStore::GetFlags(const char *name, DeviceCommandFlags *flagsOut)
+{
+ HRESULT hr;
+ DeviceSupportedCommand *command;
+
+ if (NULL == flagsOut)
+ return E_POINTER;
+
+ Lock();
+
+ command = Find(name, NULL);
+ hr = (NULL != command) ? command->GetFlags(flagsOut) : E_FAIL;
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceSupportedCommandStore::SetFlags(const char *name, DeviceCommandFlags mask, DeviceCommandFlags value)
+{
+ HRESULT hr;
+ DeviceSupportedCommand *command;
+
+ Lock();
+
+ command = Find(name, NULL);
+ hr = (NULL != command) ? command->SetFlags(mask, value) : E_FAIL;
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceSupportedCommandStore::Get(const char *name, ifc_devicesupportedcommand **command)
+{
+ HRESULT hr;
+
+ if (NULL == command)
+ return E_POINTER;
+
+ Lock();
+
+ *command = Find(name, NULL);
+ if (NULL != *command)
+ {
+ (*command)->AddRef();
+ hr = S_OK;
+ }
+ else
+ hr = E_FAIL;
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceSupportedCommandStore::GetActive(ifc_devicesupportedcommand **command)
+{
+ return E_NOTIMPL;
+}
+
+HRESULT DeviceSupportedCommandStore::Enumerate(ifc_devicesupportedcommandenum **enumerator)
+{
+ HRESULT hr;
+
+ Lock();
+ hr = DeviceSupportedCommandEnum::CreateInstance(
+ reinterpret_cast<ifc_devicesupportedcommand**>(commandList.size() ? &commandList.at(0) : nullptr),
+ commandList.size(),
+ reinterpret_cast<DeviceSupportedCommandEnum**>(enumerator));
+
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceSupportedCommandStore::Clone(ifc_devicesupportedcommandstore **instance, BOOL fullCopy)
+{
+ HRESULT hr;
+ DeviceSupportedCommandStore *clone;
+ DeviceSupportedCommand *command;
+
+ if (NULL == instance)
+ return E_POINTER;
+
+ Lock();
+
+ hr = CreateInstance(&clone);
+ if (SUCCEEDED(hr))
+ {
+ size_t index, count;
+
+ count = commandList.size();
+
+ for(index = 0; index < count; index++)
+ {
+ command = commandList[index];
+ if (FALSE != fullCopy)
+ {
+ DeviceSupportedCommand *commandClone;
+
+ hr = command->Clone(&commandClone);
+ if(SUCCEEDED(hr))
+ command = commandClone;
+ else
+ break;
+ }
+ else
+ command->AddRef();
+
+ clone->commandList.push_back(command);
+ }
+ }
+
+ Unlock();
+
+ if (FAILED(hr) && NULL != clone)
+ {
+ clone->Release();
+ *instance = NULL;
+ }
+ else
+ *instance = clone;
+
+ return hr;
+}
+
+#define CBCLASS DeviceSupportedCommandStore
+START_DISPATCH;
+CB(ADDREF, AddRef)
+CB(RELEASE, Release)
+CB(QUERYINTERFACE, QueryInterface)
+CB(API_ADD, Add)
+CB(API_REMOVE, Remove)
+CB(API_REMOVEALL, RemoveAll)
+CB(API_GETFLAGS, GetFlags)
+CB(API_SETFLAGS, SetFlags)
+CB(API_GET, Get)
+CB(API_GETACTIVE, GetActive)
+CB(API_ENUMERATE, Enumerate)
+CB(API_CLONE, Clone)
+END_DISPATCH;
+#undef CBCLASS
diff --git a/Src/devices/deviceSupportedCommandStore.h b/Src/devices/deviceSupportedCommandStore.h
new file mode 100644
index 000000000..88e6f142b
--- /dev/null
+++ b/Src/devices/deviceSupportedCommandStore.h
@@ -0,0 +1,69 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_STORE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_STORE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+
+#include "./ifc_devicesupportedcommandstore.h"
+#include "./deviceSupportedCommand.h"
+#include "./ifc_devicesupportedcommandenum.h"
+#include <vector>
+
+class DeviceSupportedCommandStore : public ifc_devicesupportedcommandstore
+{
+
+protected:
+ DeviceSupportedCommandStore();
+ ~DeviceSupportedCommandStore();
+
+public:
+ static HRESULT CreateInstance(DeviceSupportedCommandStore **instance);
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* ifc_devicesupportedcommandstore*/
+ HRESULT Add(const char *name, DeviceCommandFlags flags);
+ HRESULT Remove(const char *name);
+ HRESULT RemoveAll();
+
+ HRESULT GetFlags(const char *name, DeviceCommandFlags *flagsOut);
+ HRESULT SetFlags(const char *name, DeviceCommandFlags mask, DeviceCommandFlags value);
+
+ HRESULT Get(const char *name, ifc_devicesupportedcommand **command);
+ HRESULT GetActive(ifc_devicesupportedcommand **command);
+
+ HRESULT Enumerate(ifc_devicesupportedcommandenum **enumerator);
+
+ HRESULT Clone(ifc_devicesupportedcommandstore **instance, BOOL fullCopy);
+
+public:
+ void Lock();
+ void Unlock();
+
+protected:
+ static int SearchCallback(const void *key, const void *element);
+ static int SortCallback(const void *element1, const void *element2);
+ DeviceSupportedCommand *Find(const char *name, size_t *indexOut);
+
+protected:
+ typedef std::vector<DeviceSupportedCommand*> CommandList;
+
+protected:
+ size_t ref;
+ CommandList commandList;
+ CRITICAL_SECTION lock;
+
+protected:
+ RECVS_DISPATCH;
+
+
+
+};
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_STORE_HEADER \ No newline at end of file
diff --git a/Src/devices/deviceType.cpp b/Src/devices/deviceType.cpp
new file mode 100644
index 000000000..ae8feabe6
--- /dev/null
+++ b/Src/devices/deviceType.cpp
@@ -0,0 +1,200 @@
+#include "main.h"
+#include "./deviceType.h"
+
+#include <strsafe.h>
+
+DeviceType::DeviceType()
+ : ref(1), name(NULL), displayName(NULL)
+{
+ if (FAILED(DeviceIconStore::CreateInstance(&iconStore)))
+ iconStore = NULL;
+
+ InitializeCriticalSection(&lock);
+}
+
+DeviceType::~DeviceType()
+{
+ AnsiString_Free(name);
+ String_Free(displayName);
+ if (NULL != iconStore)
+ iconStore->Release();
+
+ DeleteCriticalSection(&lock);
+}
+
+HRESULT DeviceType::CreateInstance(const char *name, DeviceType **instance)
+{
+ char *nameCopy;
+
+ if (NULL == instance)
+ return E_POINTER;
+
+ if (FALSE != IS_STRING_EMPTY(name))
+ return E_INVALIDARG;
+
+ *instance = new DeviceType();
+
+ if (NULL == *instance)
+ return E_OUTOFMEMORY;
+
+ nameCopy = AnsiString_Duplicate(name);
+ if (NULL == nameCopy)
+ {
+ (*instance)->Release();
+ return E_OUTOFMEMORY;
+ }
+
+ (*instance)->name = nameCopy;
+
+ return S_OK;
+}
+
+size_t DeviceType::AddRef()
+{
+ return InterlockedIncrement((LONG*)&ref);
+}
+
+size_t DeviceType::Release()
+{
+ if (0 == ref)
+ return ref;
+
+ LONG r = InterlockedDecrement((LONG*)&ref);
+ if (0 == r)
+ delete(this);
+
+ return r;
+}
+
+int DeviceType::QueryInterface(GUID interface_guid, void **object)
+{
+ if (NULL == object) return E_POINTER;
+
+ if (IsEqualIID(interface_guid, IFC_DeviceType))
+ *object = static_cast<ifc_devicetype*>(this);
+ else if (IsEqualIID(interface_guid, IFC_DeviceTypeEditor))
+ *object = static_cast<ifc_devicetypeeditor*>(this);
+ else if (IsEqualIID(interface_guid, IFC_DeviceObject))
+ *object = static_cast<ifc_deviceobject*>(this);
+ else
+ {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+
+ if (NULL == *object)
+ return E_UNEXPECTED;
+
+ AddRef();
+ return S_OK;
+}
+
+void DeviceType::Lock()
+{
+ EnterCriticalSection(&lock);
+}
+
+void DeviceType::Unlock()
+{
+ LeaveCriticalSection(&lock);
+}
+
+const char *DeviceType::GetName()
+{
+ return name;
+}
+
+HRESULT DeviceType::GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
+{
+ HRESULT hr;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ Lock();
+
+ if (NULL == iconStore)
+ hr = E_UNEXPECTED;
+ else
+ hr = iconStore->Get(buffer, bufferSize, width, height);
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceType::GetDisplayName(wchar_t *buffer, size_t bufferSize)
+{
+ HRESULT hr;
+
+ if (NULL == buffer)
+ return E_POINTER;
+
+ Lock();
+
+ hr = StringCchCopyExW(buffer, bufferSize, displayName, NULL, NULL, STRSAFE_IGNORE_NULLS);
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceType::GetIconStore(ifc_deviceiconstore **store)
+{
+ HRESULT hr;
+
+ if (NULL == store)
+ return E_POINTER;
+
+ Lock();
+
+ if (NULL == iconStore)
+ hr = E_UNEXPECTED;
+ else
+ {
+ iconStore->AddRef();
+ *store = iconStore;
+ hr = S_OK;
+ }
+
+ Unlock();
+
+ return hr;
+}
+
+HRESULT DeviceType::SetDisplayName(const wchar_t *displayName)
+{
+ HRESULT hr;
+
+ Lock();
+
+ String_Free(this->displayName);
+ this->displayName = String_Duplicate(displayName);
+
+ if (NULL == this->displayName && NULL != displayName)
+ hr = E_OUTOFMEMORY;
+ else
+ hr = S_OK;
+
+ Unlock();
+
+ return hr;
+}
+
+#define CBCLASS DeviceType
+START_MULTIPATCH;
+ START_PATCH(MPIID_DEVICETYPE)
+ M_CB(MPIID_DEVICETYPE, ifc_devicetype, ADDREF, AddRef);
+ M_CB(MPIID_DEVICETYPE, ifc_devicetype, RELEASE, Release);
+ M_CB(MPIID_DEVICETYPE, ifc_devicetype, QUERYINTERFACE, QueryInterface);
+ M_CB(MPIID_DEVICETYPE, ifc_devicetype, API_GETNAME, GetName);
+ M_CB(MPIID_DEVICETYPE, ifc_devicetype, API_GETICON, GetIcon);
+ M_CB(MPIID_DEVICETYPE, ifc_devicetype, API_GETDISPLAYNAME, GetDisplayName);
+ NEXT_PATCH(MPIID_DEVICETYPEEDITOR)
+ M_CB(MPIID_DEVICETYPEEDITOR, ifc_devicetypeeditor, ADDREF, AddRef);
+ M_CB(MPIID_DEVICETYPEEDITOR, ifc_devicetypeeditor, RELEASE, Release);
+ M_CB(MPIID_DEVICETYPEEDITOR, ifc_devicetypeeditor, QUERYINTERFACE, QueryInterface);
+ M_CB(MPIID_DEVICETYPEEDITOR, ifc_devicetypeeditor, API_SETDISPLAYNAME, SetDisplayName);
+ M_CB(MPIID_DEVICETYPEEDITOR, ifc_devicetypeeditor, API_GETICONSTORE, GetIconStore);
+ END_PATCH
+END_MULTIPATCH; \ No newline at end of file
diff --git a/Src/devices/deviceType.h b/Src/devices/deviceType.h
new file mode 100644
index 000000000..9b9caf43c
--- /dev/null
+++ b/Src/devices/deviceType.h
@@ -0,0 +1,59 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_TYPE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_TYPE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include "./ifc_devicetype.h"
+#include "./ifc_devicetypeeditor.h"
+#include "./ifc_deviceiconstore.h"
+#include "./deviceIconStore.h"
+
+#include <bfc/multipatch.h>
+
+#define MPIID_DEVICETYPE 10
+#define MPIID_DEVICETYPEEDITOR 20
+
+class DeviceType : public MultiPatch<MPIID_DEVICETYPE, ifc_devicetype>,
+ public MultiPatch<MPIID_DEVICETYPEEDITOR, ifc_devicetypeeditor>
+{
+
+protected:
+ DeviceType();
+ ~DeviceType();
+
+public:
+ static HRESULT CreateInstance(const char *name, DeviceType **instance);
+
+public:
+ /* Dispatchable */
+ size_t AddRef();
+ size_t Release();
+ int QueryInterface(GUID interface_guid, void **object);
+
+ /* ifc_devicetype */
+ const char *GetName();
+ HRESULT GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height);
+ HRESULT GetDisplayName(wchar_t *buffer, size_t bufferSize);
+
+ /* ifc_devicetypeeditor */
+ HRESULT GetIconStore(ifc_deviceiconstore **store);
+ HRESULT SetDisplayName(const wchar_t *displayName);
+
+public:
+ void Lock();
+ void Unlock();
+
+protected:
+ size_t ref;
+ char *name;
+ wchar_t *displayName;
+ DeviceIconStore *iconStore;
+ CRITICAL_SECTION lock;
+
+protected:
+ RECVS_MULTIPATCH;
+};
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_TYPE_HEADER
diff --git a/Src/devices/devices.rc b/Src/devices/devices.rc
new file mode 100644
index 000000000..c0624c79b
--- /dev/null
+++ b/Src/devices/devices.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#include ""version.rc2""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc2"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/devices/devices.sln b/Src/devices/devices.sln
new file mode 100644
index 000000000..9d1b6fc95
--- /dev/null
+++ b/Src/devices/devices.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29424.173
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "devices", "devices.vcxproj", "{06F6E796-653F-48A9-BA2F-46B679D35F9E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {06F6E796-653F-48A9-BA2F-46B679D35F9E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {06F6E796-653F-48A9-BA2F-46B679D35F9E}.Debug|Win32.Build.0 = Debug|Win32
+ {06F6E796-653F-48A9-BA2F-46B679D35F9E}.Release|Win32.ActiveCfg = Release|Win32
+ {06F6E796-653F-48A9-BA2F-46B679D35F9E}.Release|Win32.Build.0 = Release|Win32
+ {06F6E796-653F-48A9-BA2F-46B679D35F9E}.Debug|x64.ActiveCfg = Debug|x64
+ {06F6E796-653F-48A9-BA2F-46B679D35F9E}.Debug|x64.Build.0 = Debug|x64
+ {06F6E796-653F-48A9-BA2F-46B679D35F9E}.Release|x64.ActiveCfg = Release|x64
+ {06F6E796-653F-48A9-BA2F-46B679D35F9E}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {D0F6DA48-1297-47B2-83FC-D727EAA945AF}
+ EndGlobalSection
+EndGlobal
diff --git a/Src/devices/devices.vcxproj b/Src/devices/devices.vcxproj
new file mode 100644
index 000000000..33ce27f71
--- /dev/null
+++ b/Src/devices/devices.vcxproj
@@ -0,0 +1,323 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{06F6E796-653F-48A9-BA2F-46B679D35F9E}</ProjectGuid>
+ <RootNamespace>devices</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;..;../wasabi;../agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <EnablePREfast>false</EnablePREfast>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <SupportUnloadOfDelayLoadedDLL>true</SupportUnloadOfDelayLoadedDLL>
+ <ImportLibrary>$(ProjectDir)x86_Debug\$(ProjectName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <Xdcmake>
+ <OutputFile>$(ProjectDir)x86_Debug\$(ProjectName).xml</OutputFile>
+ </Xdcmake>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;..;../wasabi;../agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <EnablePREfast>false</EnablePREfast>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <SupportUnloadOfDelayLoadedDLL>true</SupportUnloadOfDelayLoadedDLL>
+ <ImportLibrary>$(ProjectDir)x64_Debug\$(ProjectName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <Xdcmake>
+ <OutputFile>$(ProjectDir)x64_Debug\$(ProjectName).xml</OutputFile>
+ </Xdcmake>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>.;..;../wasabi;../agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <SupportUnloadOfDelayLoadedDLL>true</SupportUnloadOfDelayLoadedDLL>
+ <ImportLibrary>$(ProjectDir)x86_Release\$(ProjectName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <Xdcmake>
+ <OutputFile>$(ProjectDir)x86_Release\$(ProjectName).xml</OutputFile>
+ </Xdcmake>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>.;..;../wasabi;../agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <SupportUnloadOfDelayLoadedDLL>true</SupportUnloadOfDelayLoadedDLL>
+ <ImportLibrary>$(ProjectDir)x64_Release\$(ProjectName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <Xdcmake>
+ <OutputFile>$(ProjectDir)x64_Release\$(ProjectName).xml</OutputFile>
+ </Xdcmake>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\nu\trace.cpp" />
+ <ClCompile Include="component.cpp" />
+ <ClCompile Include="deviceCommand.cpp" />
+ <ClCompile Include="deviceConnection.cpp" />
+ <ClCompile Include="deviceEventManager.cpp" />
+ <ClCompile Include="deviceIconStore.cpp" />
+ <ClCompile Include="deviceManager.cpp" />
+ <ClCompile Include="deviceManagerFactory.cpp" />
+ <ClCompile Include="deviceObjectEnum.cpp" />
+ <ClCompile Include="deviceObjectStore.cpp" />
+ <ClCompile Include="deviceSupportedCommand.cpp" />
+ <ClCompile Include="deviceSupportedCommandEnum.cpp" />
+ <ClCompile Include="deviceSupportedCommandStore.cpp" />
+ <ClCompile Include="deviceType.cpp" />
+ <ClCompile Include="discoveryMonitor.cpp" />
+ <ClCompile Include="main.cpp" />
+ <ClCompile Include="plugin.cpp" />
+ <ClCompile Include="strings.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\nu\trace.h" />
+ <ClInclude Include="api_devicemanager.h" />
+ <ClInclude Include="common.h" />
+ <ClInclude Include="component.h" />
+ <ClInclude Include="deviceCommand.h" />
+ <ClInclude Include="deviceConnection.h" />
+ <ClInclude Include="deviceEventManager.h" />
+ <ClInclude Include="deviceIconStore.h" />
+ <ClInclude Include="deviceManager.h" />
+ <ClInclude Include="deviceManagerFactory.h" />
+ <ClInclude Include="deviceObjectEnum.h" />
+ <ClInclude Include="deviceObjectStore.h" />
+ <ClInclude Include="deviceSupportedCommand.h" />
+ <ClInclude Include="deviceSupportedCommandEnum.h" />
+ <ClInclude Include="deviceSupportedCommandStore.h" />
+ <ClInclude Include="deviceType.h" />
+ <ClInclude Include="discoveryMonitor.h" />
+ <ClInclude Include="ifc_device.h" />
+ <ClInclude Include="ifc_deviceactivity.h" />
+ <ClInclude Include="ifc_devicecommand.h" />
+ <ClInclude Include="ifc_devicecommandeditor.h" />
+ <ClInclude Include="ifc_deviceconnection.h" />
+ <ClInclude Include="ifc_deviceconnectioneditor.h" />
+ <ClInclude Include="ifc_deviceevent.h" />
+ <ClInclude Include="ifc_deviceeventmanager.h" />
+ <ClInclude Include="ifc_deviceiconstore.h" />
+ <ClInclude Include="ifc_devicemanagerevent.h" />
+ <ClInclude Include="ifc_deviceobject.h" />
+ <ClInclude Include="ifc_deviceobjectenum.h" />
+ <ClInclude Include="ifc_deviceprovider.h" />
+ <ClInclude Include="ifc_devicesupportedcommand.h" />
+ <ClInclude Include="ifc_devicesupportedcommandenum.h" />
+ <ClInclude Include="ifc_devicesupportedcommandstore.h" />
+ <ClInclude Include="ifc_devicetype.h" />
+ <ClInclude Include="ifc_devicetypeeditor.h" />
+ <ClInclude Include="main.h" />
+ <ClInclude Include="plugin.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="strings.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="devices.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Wasabi\Wasabi.vcxproj">
+ <Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Src/devices/devices.vcxproj.filters b/Src/devices/devices.vcxproj.filters
new file mode 100644
index 000000000..6c7f4487e
--- /dev/null
+++ b/Src/devices/devices.vcxproj.filters
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="..\nu\trace.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="component.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceCommand.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceConnection.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceEventManager.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceIconStore.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceManager.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceManagerFactory.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceObjectEnum.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceObjectStore.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceSupportedCommand.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceSupportedCommandEnum.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceSupportedCommandStore.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="deviceType.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="discoveryMonitor.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="plugin.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="strings.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="api_devicemanager.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="common.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="component.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceCommand.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceConnection.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceEventManager.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceIconStore.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceManager.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceManagerFactory.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceObjectEnum.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceObjectStore.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceSupportedCommand.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceSupportedCommandEnum.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceSupportedCommandStore.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="deviceType.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_device.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="discoveryMonitor.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_deviceactivity.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_devicecommand.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_devicecommandeditor.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_deviceconnection.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_deviceconnectioneditor.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_deviceevent.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_deviceeventmanager.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_deviceiconstore.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_devicemanagerevent.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_deviceobject.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_deviceobjectenum.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_deviceprovider.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_devicesupportedcommand.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_devicesupportedcommandenum.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_devicesupportedcommandstore.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_devicetype.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ifc_devicetypeeditor.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="main.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="plugin.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="strings.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\nu\trace.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{f4644265-34b9-4067-a619-473804a3f141}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Ressource Files">
+ <UniqueIdentifier>{1284fd85-642e-4ad1-8852-9ac396edb47e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{cdd62d9b-fcfc-49c5-bbb9-ab546b57bb1e}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="devices.rc">
+ <Filter>Ressource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Src/devices/discoveryMonitor.cpp b/Src/devices/discoveryMonitor.cpp
new file mode 100644
index 000000000..3a42bd082
--- /dev/null
+++ b/Src/devices/discoveryMonitor.cpp
@@ -0,0 +1,105 @@
+#include "main.h"
+#include "./discoveryMonitor.h"
+
+DiscoveryMonitor::DiscoveryMonitor()
+{
+ InitializeCriticalSection(&lock);
+}
+
+DiscoveryMonitor::~DiscoveryMonitor()
+{
+ DeleteCriticalSection(&lock);
+}
+
+void DiscoveryMonitor::Lock()
+{
+ EnterCriticalSection(&lock);
+}
+
+void DiscoveryMonitor::Unlock()
+{
+ LeaveCriticalSection(&lock);
+}
+
+BOOL DiscoveryMonitor::Register(ifc_deviceprovider *provider)
+{
+ Lock();
+
+ size_t index = activityList.size();
+ while(index--)
+ {
+ ActiveDiscovery *entry = &activityList[index];
+ if ((intptr_t)provider == entry->providerId)
+ {
+ entry->ref++;
+ Unlock();
+ return FALSE;
+ }
+ }
+
+ ActiveDiscovery record;
+ record.providerId = (intptr_t)provider;
+ record.ref = 1;
+
+ activityList.push_back(record);
+ index = activityList.size();
+
+ Unlock();
+ return (1 == index);
+}
+
+BOOL DiscoveryMonitor::Unregister(ifc_deviceprovider *provider)
+{
+ Lock();
+
+ size_t index = activityList.size();
+ while(index--)
+ {
+ ActiveDiscovery *entry = &activityList[index];
+ if ((intptr_t)provider == entry->providerId)
+ {
+ if (1 == entry->ref)
+ {
+ activityList.erase(activityList.begin() + index);
+ index = activityList.size();
+ Unlock();
+ return (0 == index);
+ }
+
+ entry->ref--;
+ break;
+ }
+ }
+
+ Unlock();
+ return FALSE;
+}
+
+BOOL DiscoveryMonitor::IsActive()
+{
+ size_t count;
+
+ Lock();
+
+ count = activityList.size();
+
+ Unlock();
+
+ return (0 != count);
+}
+
+BOOL DiscoveryMonitor::Reset()
+{
+ size_t count;
+
+ Lock();
+
+ count = activityList.size();
+ activityList.clear();
+
+ Unlock();
+
+ return (0 != count);
+}
+
+
diff --git a/Src/devices/discoveryMonitor.h b/Src/devices/discoveryMonitor.h
new file mode 100644
index 000000000..7b838c151
--- /dev/null
+++ b/Src/devices/discoveryMonitor.h
@@ -0,0 +1,43 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DISCOVERY_MONITOR_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DISCOVERY_MONITOR_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include "ifc_deviceprovider.h"
+#include <vector>
+
+class DiscoveryMonitor
+{
+public:
+ DiscoveryMonitor();
+ ~DiscoveryMonitor();
+
+public:
+ BOOL Register(ifc_deviceprovider *provider);
+ BOOL Unregister(ifc_deviceprovider *provider);
+ BOOL IsActive();
+ BOOL Reset();
+
+protected:
+ void Lock();
+ void Unlock();
+
+private:
+ typedef struct ActiveDiscovery
+ {
+ intptr_t providerId;
+ size_t ref;
+ } ActiveDiscovery;
+
+ typedef std::vector<ActiveDiscovery> ActivityList;
+
+private:
+ CRITICAL_SECTION lock;
+ ActivityList activityList;
+};
+
+
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DISCOVERY_MONITOR_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_device.h b/Src/devices/ifc_device.h
new file mode 100644
index 000000000..b672b1e81
--- /dev/null
+++ b/Src/devices/ifc_device.h
@@ -0,0 +1,203 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {CAC1D7F6-AA27-47eb-BAF7-512BAAE04F07}
+static const GUID IFC_Device =
+{ 0xcac1d7f6, 0xaa27, 0x47eb, { 0xba, 0xf7, 0x51, 0x2b, 0xaa, 0xe0, 0x4f, 0x7 } };
+
+#include "ifc_deviceobject.h"
+
+class ifc_deviceevent;
+class ifc_devicesupportedcommandenum;
+class ifc_deviceactivity;
+
+typedef enum DeviceCommandFlags DeviceCommandFlags;
+typedef enum DeviceCommandContext DeviceCommandContext;
+
+
+class __declspec(novtable) ifc_device : public ifc_deviceobject
+{
+protected:
+ ifc_device() {}
+ ~ifc_device() {}
+
+public:
+ const char *GetType();
+ const char *GetDisplayType();
+ const char *GetConnection();
+
+ BOOL GetHidden();
+
+ HRESULT GetTotalSpace(uint64_t *size);
+ HRESULT GetUsedSpace(uint64_t *size);
+
+ BOOL GetAttached();
+ HRESULT Attach(HWND hostWindow);
+ HRESULT Detach(HWND hostWindow);
+
+ HRESULT EnumerateCommands(ifc_devicesupportedcommandenum **enumerator, DeviceCommandContext context);
+ HRESULT SendCommand(const char *command, HWND hostWindow, ULONG_PTR param);
+ HRESULT GetCommandFlags(const char *command, DeviceCommandFlags *flags);
+
+ HRESULT GetActivity(ifc_deviceactivity **activity);
+
+ HRESULT Advise(ifc_deviceevent *handler);
+ HRESULT Unadvise(ifc_deviceevent *handler);
+
+ HWND CreateView(HWND parentWindow);
+ void SetNavigationItem(void *navigationItem);
+
+ HRESULT GetDropSupported(unsigned int dataType);
+ HRESULT Drop(void *data, unsigned int dataType);
+
+ HRESULT SetDisplayName(const wchar_t *displayName);
+
+ HRESULT GetModel(wchar_t *buffer, size_t bufferSize); // - end-user-visible name for the end produt.
+ HRESULT GetStatus(wchar_t *buffer, size_t bufferSize); // - free-form status message (example: "Last synchronized 19:20 01/10/10").
+
+public:
+ DISPATCH_CODES
+ {
+ API_GETTYPE = 10,
+ API_GETCONNECTION = 20,
+ API_GETHIDDEN = 30,
+ API_GETTOTALSPACE = 40,
+ API_GETUSEDSPACE = 50,
+ API_GETATTACHED = 60,
+ API_ATTACH = 70,
+ API_DETACH = 80,
+ API_ENUMERATECOMMANDS = 90,
+ API_SENDCOMMAND = 100,
+ API_GETCOMMANDFLAGS = 110,
+ API_GETACTIVITY = 120,
+ API_ADVISE = 130,
+ API_UNADVISE = 140,
+ API_CREATEVIEW = 150,
+ API_SETNAVIGATIONITEM = 160,
+ API_GETDROPSUPPORTED = 170,
+ API_DROP = 180,
+ API_SETDISPLAYNAME = 190,
+ API_GETMODEL = 200,
+ API_GETSTATUS = 210,
+ API_GETDISPLAYTYPE = 220,
+ };
+};
+
+
+inline const char *ifc_device::GetType()
+{
+ return _call(API_GETTYPE, (const char*)NULL);
+}
+
+inline const char *ifc_device::GetDisplayType()
+{
+ return _call(API_GETDISPLAYTYPE, (const char*)NULL);
+}
+
+inline const char *ifc_device::GetConnection()
+{
+ return _call(API_GETCONNECTION, (const char*)NULL);
+}
+
+inline BOOL ifc_device::GetHidden()
+{
+ return _call(API_GETHIDDEN, (BOOL)FALSE);
+}
+
+inline HRESULT ifc_device::GetTotalSpace(uint64_t *size)
+{
+ return _call(API_GETTOTALSPACE, (HRESULT)E_NOTIMPL, size);
+}
+
+inline HRESULT ifc_device::GetUsedSpace(uint64_t *size)
+{
+ return _call(API_GETUSEDSPACE, (HRESULT)E_NOTIMPL, size);
+}
+
+inline BOOL ifc_device::GetAttached()
+{
+ return _call(API_GETATTACHED, (BOOL)FALSE);
+}
+
+inline HRESULT ifc_device::Attach(HWND hostWindow)
+{
+ return _call(API_ATTACH, (HRESULT)E_NOTIMPL, hostWindow);
+}
+
+inline HRESULT ifc_device::Detach(HWND hostWindow)
+{
+ return _call(API_DETACH, (HRESULT)E_NOTIMPL, hostWindow);
+}
+
+inline HRESULT ifc_device::EnumerateCommands(ifc_devicesupportedcommandenum **enumerator, DeviceCommandContext context)
+{
+ return _call(API_ENUMERATECOMMANDS, (HRESULT)E_NOTIMPL, enumerator, context);
+}
+
+inline HRESULT ifc_device::SendCommand(const char *command, HWND hostWindow, ULONG_PTR param)
+{
+ return _call(API_SENDCOMMAND, (HRESULT)E_NOTIMPL, command, hostWindow, param);
+}
+
+inline HRESULT ifc_device::GetCommandFlags(const char *command, DeviceCommandFlags *flags)
+{
+ return _call(API_GETCOMMANDFLAGS, (HRESULT)E_NOTIMPL, command, flags);
+}
+
+inline HRESULT ifc_device::GetActivity(ifc_deviceactivity **activity)
+{
+ return _call(API_GETACTIVITY, (HRESULT)E_NOTIMPL, activity);
+}
+
+inline HRESULT ifc_device::Advise(ifc_deviceevent *handler)
+{
+ return _call(API_ADVISE, (HRESULT)E_NOTIMPL, handler);
+}
+
+inline HRESULT ifc_device::Unadvise(ifc_deviceevent *handler)
+{
+ return _call(API_UNADVISE, (HRESULT)E_NOTIMPL, handler);
+}
+
+inline HWND ifc_device::CreateView(HWND parentWindow)
+{
+ return _call(API_CREATEVIEW, (HWND)NULL, parentWindow);
+}
+
+inline void ifc_device::SetNavigationItem(void *navigationItem)
+{
+ _voidcall(API_SETNAVIGATIONITEM, navigationItem);
+}
+
+inline HRESULT ifc_device::GetDropSupported(unsigned int dataType)
+{
+ return _call(API_GETDROPSUPPORTED, (HRESULT)E_NOTIMPL, dataType);
+}
+
+inline HRESULT ifc_device::Drop(void *data, unsigned int dataType)
+{
+ return _call(API_DROP, (HRESULT)E_NOTIMPL, data, dataType);
+}
+
+inline HRESULT ifc_device::SetDisplayName(const wchar_t *displayName)
+{
+ return _call(API_SETDISPLAYNAME, (HRESULT)E_NOTIMPL, displayName);
+}
+
+inline HRESULT ifc_device::GetModel(wchar_t *buffer, size_t bufferSize)
+{
+ return _call(API_GETMODEL, (HRESULT)E_NOTIMPL, buffer, bufferSize);
+}
+
+inline HRESULT ifc_device::GetStatus(wchar_t *buffer, size_t bufferSize)
+{
+ return _call(API_GETSTATUS, (HRESULT)E_NOTIMPL, buffer, bufferSize);
+}
+
+#endif // _NULLSOFT_WINAMP_DEVICES_DEVICE_INTERFACE_HEADER
diff --git a/Src/devices/ifc_deviceactivity.h b/Src/devices/ifc_deviceactivity.h
new file mode 100644
index 000000000..357bdbc1e
--- /dev/null
+++ b/Src/devices/ifc_deviceactivity.h
@@ -0,0 +1,74 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_ACTIVITY_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_ACTIVITY_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {6FE2E838-6C56-4b14-8CE0-FA9B19113DA5}
+static const GUID IFC_DeviceActivity =
+{ 0x6fe2e838, 0x6c56, 0x4b14, { 0x8c, 0xe0, 0xfa, 0x9b, 0x19, 0x11, 0x3d, 0xa5 } };
+
+
+#include <bfc/dispatch.h>
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_deviceactivity: public Dispatchable
+{
+protected:
+ ifc_deviceactivity() {}
+ ~ifc_deviceactivity() {}
+
+public:
+ BOOL GetActive();
+ BOOL GetCancelable();
+ HRESULT GetProgress(unsigned int *percentCompleted);
+ HRESULT GetDisplayName(wchar_t *buffer, size_t bufferMax);
+ HRESULT GetStatus(wchar_t *buffer, size_t bufferMax);
+ HRESULT Cancel(HWND hostWindow);
+
+public:
+ DISPATCH_CODES
+ {
+ API_GETACTIVE = 10,
+ API_GETCANCELABLE = 20,
+ API_GETPROGRESS = 30,
+ API_GETDISPLAYNAME = 40,
+ API_GETSTATUS = 50,
+ API_CANCEL = 60,
+ };
+};
+
+inline BOOL ifc_deviceactivity::GetActive()
+{
+ return _call(API_GETACTIVE, (BOOL)FALSE);
+}
+
+inline BOOL ifc_deviceactivity::GetCancelable()
+{
+ return _call(API_GETCANCELABLE, (BOOL)FALSE);
+}
+
+inline HRESULT ifc_deviceactivity::GetProgress(unsigned int *percentCompleted)
+{
+ return _call(API_GETPROGRESS, (HRESULT)E_NOTIMPL, percentCompleted);
+}
+
+inline HRESULT ifc_deviceactivity::GetDisplayName(wchar_t *buffer, size_t bufferMax)
+{
+ return _call(API_GETDISPLAYNAME, (HRESULT)E_NOTIMPL, buffer, bufferMax);
+}
+
+inline HRESULT ifc_deviceactivity::GetStatus(wchar_t *buffer, size_t bufferMax)
+{
+ return _call(API_GETSTATUS, (HRESULT)E_NOTIMPL, buffer, bufferMax);
+}
+
+inline HRESULT ifc_deviceactivity::Cancel(HWND hostWindow)
+{
+ return _call(API_CANCEL, (HRESULT)E_NOTIMPL, hostWindow);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_ACTIVITY_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_devicecommand.h b/Src/devices/ifc_devicecommand.h
new file mode 100644
index 000000000..810f40b28
--- /dev/null
+++ b/Src/devices/ifc_devicecommand.h
@@ -0,0 +1,58 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {52C5C581-65DC-435e-AEFA-1616CB81B283}
+static const GUID IFC_DeviceCommand =
+{ 0x52c5c581, 0x65dc, 0x435e, { 0xae, 0xfa, 0x16, 0x16, 0xcb, 0x81, 0xb2, 0x83 } };
+
+
+#include "ifc_deviceobject.h"
+
+typedef enum DeviceCommandFlags
+{
+ DeviceCommandFlag_None = 0,
+ DeviceCommandFlag_Primary = (1 << 0),
+ DeviceCommandFlag_Disabled = (1 << 1),
+ DeviceCommandFlag_Active = (1 << 2),
+ DeviceCommandFlag_Hidden = (1 << 3),
+ DeviceCommandFlag_Group = (1 << 4),
+}DeviceCommandFlags;
+DEFINE_ENUM_FLAG_OPERATORS(DeviceCommandFlags);
+
+typedef enum DeviceCommandContext
+{
+ DeviceCommandContext_Unknown = 0,
+ DeviceCommandContext_NavigationMenu = 1,
+ DeviceCommandContext_ViewMenu = 2,
+ DeviceCommandContext_View = 3,
+
+} DeviceCommandContext;
+
+class __declspec(novtable) ifc_devicecommand : public ifc_deviceobject
+{
+protected:
+ ifc_devicecommand() {}
+ ~ifc_devicecommand() {}
+
+public:
+ HRESULT GetDescription(wchar_t *buffer, size_t bufferSize);
+
+public:
+ DISPATCH_CODES
+ {
+ API_GETDESCRIPTION = 10,
+ };
+};
+
+inline HRESULT ifc_devicecommand::GetDescription(wchar_t *buffer, size_t bufferSize)
+{
+ return _call(API_GETDESCRIPTION, (HRESULT)E_NOTIMPL, buffer, bufferSize);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_devicecommandeditor.h b/Src/devices/ifc_devicecommandeditor.h
new file mode 100644
index 000000000..678610bd2
--- /dev/null
+++ b/Src/devices/ifc_devicecommandeditor.h
@@ -0,0 +1,55 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_EDITOR_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_EDITOR_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {94A35125-3AD5-4339-870E-4ACB24F00FE8}
+static const GUID IFC_DeviceCommandEditor =
+{ 0x94a35125, 0x3ad5, 0x4339, { 0x87, 0xe, 0x4a, 0xcb, 0x24, 0xf0, 0xf, 0xe8 } };
+
+
+#include <bfc/dispatch.h>
+
+class ifc_deviceiconstore;
+
+class __declspec(novtable) ifc_devicecommandeditor : public Dispatchable
+{
+protected:
+ ifc_devicecommandeditor() {}
+ ~ifc_devicecommandeditor() {}
+
+public:
+ HRESULT GetIconStore(ifc_deviceiconstore **iconStore);
+ HRESULT SetDisplayName(const wchar_t *displayName);
+ HRESULT SetDescription(const wchar_t *description);
+
+public:
+ DISPATCH_CODES
+ {
+ API_GETICONSTORE = 10,
+ API_SETDISPLAYNAME = 20,
+ API_SETDESCRIPTION = 30,
+ };
+};
+
+inline HRESULT ifc_devicecommandeditor::GetIconStore(ifc_deviceiconstore **iconStore)
+{
+ return _call(API_GETICONSTORE, (HRESULT)E_NOTIMPL, iconStore);
+}
+
+inline HRESULT ifc_devicecommandeditor::SetDisplayName(const wchar_t *displayName)
+{
+ return _call(API_SETDISPLAYNAME, (HRESULT)E_NOTIMPL, displayName);
+}
+
+inline HRESULT ifc_devicecommandeditor::SetDescription(const wchar_t *description)
+{
+ return _call(API_SETDESCRIPTION, (HRESULT)E_NOTIMPL, description);
+}
+
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_EDITOR_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_devicecommandinfo.h b/Src/devices/ifc_devicecommandinfo.h
new file mode 100644
index 000000000..3e327728b
--- /dev/null
+++ b/Src/devices/ifc_devicecommandinfo.h
@@ -0,0 +1,50 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_INFO_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_INFO_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+
+// {EFFB983B-D087-4021-8894-BA795626048B}
+static const GUID IFC_DeviceCommandInfo =
+{ 0xeffb983b, 0xd087, 0x4021, { 0x88, 0x94, 0xba, 0x79, 0x56, 0x26, 0x4, 0x8b } };
+
+#include <bfc/dispatch.h>
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_devicecommandinfo : public Dispatchable
+{
+protected:
+ ifc_devicecommandinfo() {}
+ ~ifc_devicecommandinfo() {}
+
+public:
+ const wchar_t *GetName();
+ HRESULT GetState(DeviceCommandState *state);
+
+public:
+ DISPATCH_CODES
+ {
+ API_GETNAME = 10,
+ API_GETSTATE = 20,
+ };
+};
+
+
+inline const wchar_t *ifc_devicetype::GetName()
+{
+ return _call(API_GETNAME, (const wchar_t *)NULL);
+}
+
+inline HRESULT ifc_devicetype::GetIcon(wchar_t *buffer, size_t bufferSize, DeviceIconType preferredType)
+{
+ return _call(API_GETICON, (HRESULT)E_NOTIMPL, buffer, bufferSize, preferredType);
+}
+
+inline HRESULT ifc_devicetype::GetDisplayName(wchar_t *buffer, size_t bufferSize)
+{
+ return _call(API_GETDISPLAYNAME, (HRESULT)E_NOTIMPL, buffer, bufferSize);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_COMMAND_INFO_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_deviceconnection.h b/Src/devices/ifc_deviceconnection.h
new file mode 100644
index 000000000..84eed3078
--- /dev/null
+++ b/Src/devices/ifc_deviceconnection.h
@@ -0,0 +1,24 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_CONNECTION_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_CONNECTION_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {0CF89CC5-AD4E-4c81-AF74-AB2FDB6F56CE}
+static const GUID IFC_DeviceConnection =
+{ 0xcf89cc5, 0xad4e, 0x4c81, { 0xaf, 0x74, 0xab, 0x2f, 0xdb, 0x6f, 0x56, 0xce } };
+
+#include "ifc_deviceobject.h"
+
+class __declspec(novtable) ifc_deviceconnection : public ifc_deviceobject
+{
+protected:
+ ifc_deviceconnection() {}
+ ~ifc_deviceconnection() {}
+
+};
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_CONNECTION_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_deviceconnectioneditor.h b/Src/devices/ifc_deviceconnectioneditor.h
new file mode 100644
index 000000000..6d9c5a096
--- /dev/null
+++ b/Src/devices/ifc_deviceconnectioneditor.h
@@ -0,0 +1,49 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_CONNECTION_EDITOR_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_CONNECTION_EDITOR_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {B4CAEAF3-4488-4313-8A66-DEA916DEFCCC}
+static const GUID IFC_DeviceConnectionEditor =
+{ 0xb4caeaf3, 0x4488, 0x4313, { 0x8a, 0x66, 0xde, 0xa9, 0x16, 0xde, 0xfc, 0xcc } };
+
+
+
+#include <bfc/dispatch.h>
+
+class ifc_deviceiconstore;
+
+class __declspec(novtable) ifc_deviceconnectioneditor : public Dispatchable
+{
+protected:
+ ifc_deviceconnectioneditor() {}
+ ~ifc_deviceconnectioneditor() {}
+
+public:
+ HRESULT GetIconStore(ifc_deviceiconstore **iconStore);
+ HRESULT SetDisplayName(const wchar_t *displayName);
+
+public:
+ DISPATCH_CODES
+ {
+ API_GETICONSTORE = 10,
+ API_SETDISPLAYNAME = 20,
+ };
+};
+
+inline HRESULT ifc_deviceconnectioneditor::GetIconStore(ifc_deviceiconstore **iconStore)
+{
+ return _call(API_GETICONSTORE, (HRESULT)E_NOTIMPL, iconStore);
+}
+
+inline HRESULT ifc_deviceconnectioneditor::SetDisplayName(const wchar_t *displayName)
+{
+ return _call(API_SETDISPLAYNAME, (HRESULT)E_NOTIMPL, displayName);
+}
+
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_CONNECTION_EDITOR_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_deviceevent.h b/Src/devices/ifc_deviceevent.h
new file mode 100644
index 000000000..feda77f22
--- /dev/null
+++ b/Src/devices/ifc_deviceevent.h
@@ -0,0 +1,119 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_EVENT_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_EVENT_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {4D0B21E9-B3D0-4f51-8264-575CBF6A2CFA}
+static const GUID IFC_DeviceEvent =
+{ 0x4d0b21e9, 0xb3d0, 0x4f51, { 0x82, 0x64, 0x57, 0x5c, 0xbf, 0x6a, 0x2c, 0xfa } };
+
+#include <bfc/dispatch.h>
+
+class ifc_device;
+class ifc_deviceactivity;
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_deviceevent : public Dispatchable
+{
+protected:
+ ifc_deviceevent() {}
+ ~ifc_deviceevent() {}
+
+public:
+ void IconChanged(ifc_device *device);
+ void DisplayNameChanged(ifc_device *device, const wchar_t *displayName);
+ void AttachmentChanged(ifc_device *device, BOOL attached);
+ void VisibilityChanged(ifc_device *device, BOOL visible);
+ void TotalSpaceChanged(ifc_device *device, uint64_t space);
+ void UsedSpaceChanged(ifc_device *device, uint64_t space);
+ void CommandChanged(ifc_device *device);
+ void ActivityStarted(ifc_device *device, ifc_deviceactivity *activity);
+ void ActivityFinished(ifc_device *device, ifc_deviceactivity *activity);
+ void ActivityChanged(ifc_device *device, ifc_deviceactivity *activity);
+ void ModelChanged(ifc_device *device, const wchar_t *model);
+ void StatusChanged(ifc_device *device, const wchar_t *status);
+
+
+public:
+ DISPATCH_CODES
+ {
+ API_ICONCHANGED = 10,
+ API_DISPLAYNAMECHANGED = 20,
+ API_ATTACHMENTCHANGED = 30,
+ API_VISIBILITYCHANGED = 40,
+ API_TOTALSPACECHANGED = 50,
+ API_USEDSPACECHANGED = 60,
+ API_COMMANDCHANGED = 70,
+ API_ACTIVITYSTARTED = 80,
+ API_ACTIVITYFINISHED = 90,
+ API_ACTIVITYCHANGED = 100,
+ API_MODELCHANGED = 110,
+ API_STATUSCHANGED = 120,
+ };
+};
+
+inline void ifc_deviceevent::IconChanged(ifc_device *device)
+{
+ _voidcall(API_ICONCHANGED, device);
+}
+
+inline void ifc_deviceevent::DisplayNameChanged(ifc_device *device, const wchar_t *displayName)
+{
+ _voidcall(API_DISPLAYNAMECHANGED, device, displayName);
+}
+
+inline void ifc_deviceevent::AttachmentChanged(ifc_device *device, BOOL attached)
+{
+ _voidcall(API_ATTACHMENTCHANGED, device, attached);
+}
+
+inline void ifc_deviceevent::VisibilityChanged(ifc_device *device, BOOL visible)
+{
+ _voidcall(API_VISIBILITYCHANGED, device, visible);
+}
+
+inline void ifc_deviceevent::TotalSpaceChanged(ifc_device *device, uint64_t space)
+{
+ _voidcall(API_TOTALSPACECHANGED, device, space);
+}
+
+inline void ifc_deviceevent::UsedSpaceChanged(ifc_device *device, uint64_t space)
+{
+ _voidcall(API_USEDSPACECHANGED, device, space);
+}
+
+inline void ifc_deviceevent::CommandChanged(ifc_device *device)
+{
+ _voidcall(API_COMMANDCHANGED, device);
+}
+
+inline void ifc_deviceevent::ActivityStarted(ifc_device *device, ifc_deviceactivity *activity)
+{
+ _voidcall(API_ACTIVITYSTARTED, device, activity);
+}
+
+inline void ifc_deviceevent::ActivityFinished(ifc_device *device, ifc_deviceactivity *activity)
+{
+ _voidcall(API_ACTIVITYFINISHED, device, activity);
+}
+
+inline void ifc_deviceevent::ActivityChanged(ifc_device *device, ifc_deviceactivity *activity)
+{
+ _voidcall(API_ACTIVITYCHANGED, device, activity);
+}
+
+inline void ifc_deviceevent::ModelChanged(ifc_device *device, const wchar_t *model)
+{
+ _voidcall(API_MODELCHANGED, device, model);
+}
+
+inline void ifc_deviceevent::StatusChanged(ifc_device *device, const wchar_t *status)
+{
+ _voidcall(API_STATUSCHANGED, device, status);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_EVENT_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_deviceeventmanager.h b/Src/devices/ifc_deviceeventmanager.h
new file mode 100644
index 000000000..287a81fea
--- /dev/null
+++ b/Src/devices/ifc_deviceeventmanager.h
@@ -0,0 +1,133 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_EVENT_MANAGER_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_EVENT_MANAGER_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {C563C537-DFFC-4210-BB1E-E424426789E2}
+static const GUID IFC_DeviceEventManager =
+{ 0xc563c537, 0xdffc, 0x4210, { 0xbb, 0x1e, 0xe4, 0x24, 0x42, 0x67, 0x89, 0xe2 } };
+
+#include <bfc/dispatch.h>
+
+class ifc_deviceevent;
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_deviceeventmanager : public Dispatchable
+{
+protected:
+ ifc_deviceeventmanager() {}
+ ~ifc_deviceeventmanager() {}
+
+public:
+ HRESULT Advise(ifc_deviceevent *handler);
+ HRESULT Unadvise(ifc_deviceevent *handler);
+
+ void Notify_IconChanged(ifc_device *device);
+ void Notify_DisplayNameChanged(ifc_device *device, const wchar_t *displayName);
+ void Notify_AttachmentChanged(ifc_device *device, BOOL attached);
+ void Notify_VisibilityChanged(ifc_device *device, BOOL visible);
+ void Notify_TotalSpaceChanged(ifc_device *device, uint64_t space);
+ void Notify_UsedSpaceChanged(ifc_device *device, uint64_t space);
+ void Notify_CommandChanged(ifc_device *device);
+ void Notify_ActivityStarted(ifc_device *device, ifc_deviceactivity *activity);
+ void Notify_ActivityFinished(ifc_device *device, ifc_deviceactivity *activity);
+ void Notify_ActivityChanged(ifc_device *device, ifc_deviceactivity *activity);
+ void Notify_ModelChanged(ifc_device *device, const wchar_t *model);
+ void Notify_StatusChanged(ifc_device *device, const wchar_t *status);
+
+public:
+ DISPATCH_CODES
+ {
+ API_ADVISE = 10,
+ API_UNADVISE = 20,
+ API_NOTIFY_ICONCHANGED = 30,
+ API_NOTIFY_DISPLAYNAMECHANGED = 40,
+ API_NOTIFY_ATTACHMENTCHANGED = 50,
+ API_NOTIFY_VISIBILITYCHANGED = 60,
+ API_NOTIFY_TOTALSPACECHANGED = 70,
+ API_NOTIFY_USEDSPACECHANGED = 80,
+ API_NOTIFY_COMMANDCHANGED = 90,
+ API_NOTIFY_ACTIVITYSTARTED = 100,
+ API_NOTIFY_ACTIVITYFINISHED = 110,
+ API_NOTIFY_ACTIVITYCHANGED = 120,
+ API_NOTIFY_MODELCHANGED = 130,
+ API_NOTIFY_STATUSCHANGED = 140,
+ };
+};
+
+inline HRESULT ifc_deviceeventmanager::Advise(ifc_deviceevent *handler)
+{
+ return _call(API_ADVISE, (HRESULT)E_NOTIMPL, handler);
+}
+
+inline HRESULT ifc_deviceeventmanager::Unadvise(ifc_deviceevent *handler)
+{
+ return _call(API_UNADVISE, (HRESULT)E_NOTIMPL, handler);
+}
+
+inline void ifc_deviceeventmanager::Notify_IconChanged(ifc_device *device)
+{
+ _voidcall(API_NOTIFY_ICONCHANGED, device);
+}
+
+inline void ifc_deviceeventmanager::Notify_DisplayNameChanged(ifc_device *device, const wchar_t *displayName)
+{
+ _voidcall(API_NOTIFY_DISPLAYNAMECHANGED, device, displayName);
+}
+
+inline void ifc_deviceeventmanager::Notify_AttachmentChanged(ifc_device *device, BOOL attached)
+{
+ _voidcall(API_NOTIFY_ATTACHMENTCHANGED, device, attached);
+}
+
+inline void ifc_deviceeventmanager::Notify_VisibilityChanged(ifc_device *device, BOOL visible)
+{
+ _voidcall(API_NOTIFY_VISIBILITYCHANGED, device, visible);
+}
+
+inline void ifc_deviceeventmanager::Notify_TotalSpaceChanged(ifc_device *device, uint64_t space)
+{
+ _voidcall(API_NOTIFY_TOTALSPACECHANGED, device, space);
+}
+
+inline void ifc_deviceeventmanager::Notify_UsedSpaceChanged(ifc_device *device, uint64_t space)
+{
+ _voidcall(API_NOTIFY_USEDSPACECHANGED, device, space);
+}
+
+
+inline void ifc_deviceeventmanager::Notify_CommandChanged(ifc_device *device)
+{
+ _voidcall(API_NOTIFY_COMMANDCHANGED, device);
+}
+
+inline void ifc_deviceeventmanager::Notify_ActivityStarted(ifc_device *device, ifc_deviceactivity *activity)
+{
+ _voidcall(API_NOTIFY_ACTIVITYSTARTED, device, activity);
+}
+
+inline void ifc_deviceeventmanager::Notify_ActivityFinished(ifc_device *device, ifc_deviceactivity *activity)
+{
+ _voidcall(API_NOTIFY_ACTIVITYFINISHED, device, activity);
+}
+
+inline void ifc_deviceeventmanager::Notify_ActivityChanged(ifc_device *device, ifc_deviceactivity *activity)
+{
+ _voidcall(API_NOTIFY_ACTIVITYCHANGED, device, activity);
+}
+
+inline void ifc_deviceeventmanager::Notify_ModelChanged(ifc_device *device, const wchar_t *model)
+{
+ _voidcall(API_NOTIFY_MODELCHANGED, device, model);
+}
+
+inline void ifc_deviceeventmanager::Notify_StatusChanged(ifc_device *device, const wchar_t *status)
+{
+ _voidcall(API_NOTIFY_STATUSCHANGED, device, status);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_EVENT_MANAGER_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_deviceiconstore.h b/Src/devices/ifc_deviceiconstore.h
new file mode 100644
index 000000000..03939c9c3
--- /dev/null
+++ b/Src/devices/ifc_deviceiconstore.h
@@ -0,0 +1,107 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_ICON_STORE_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_ICON_STORE_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {0CEFAC39-DCA5-4c6f-89E3-1C7573B98664}
+static const GUID IFC_DeviceIconStore =
+{ 0xcefac39, 0xdca5, 0x4c6f, { 0x89, 0xe3, 0x1c, 0x75, 0x73, 0xb9, 0x86, 0x64 } };
+
+#include <bfc/dispatch.h>
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_deviceiconstore : public Dispatchable
+{
+public:
+ typedef BOOL (*EnumeratorCallback)(const wchar_t *path, unsigned int width, unsigned int height, void *user);
+
+protected:
+ ifc_deviceiconstore() {}
+ ~ifc_deviceiconstore() {}
+
+public:
+ HRESULT Add(const wchar_t *path, unsigned int width, unsigned int height, BOOL replaceExisting);
+ HRESULT Remove(unsigned int width, unsigned int height);
+ HRESULT RemovePath(const wchar_t *path);
+ HRESULT RemoveAll();
+ HRESULT Get(wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height);
+ HRESULT GetExact(wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height);
+
+ HRESULT SetBasePath(const wchar_t *path);
+ HRESULT GetBasePath(wchar_t *buffer, size_t bufferMax);
+
+ HRESULT Clone(ifc_deviceiconstore **instance);
+
+ HRESULT Enumerate(EnumeratorCallback callback, void *user);
+
+public:
+ DISPATCH_CODES
+ {
+ API_ADD = 10,
+ API_REMOVE = 20,
+ API_REMOVEPATH = 30,
+ API_REMOVEALL = 40,
+ API_GET = 50,
+ API_GETEXACT = 60,
+ API_GETBASEPATH = 70,
+ API_SETBASEPATH = 80,
+ API_CLONE = 90,
+ API_ENUMERATE = 100,
+ };
+};
+
+inline HRESULT ifc_deviceiconstore::Add(const wchar_t *path, unsigned int width, unsigned int height, BOOL replaceExisting)
+{
+ return _call(API_ADD, (HRESULT)E_NOTIMPL, path, width, height, replaceExisting);
+}
+
+inline HRESULT ifc_deviceiconstore::Remove(unsigned int width, unsigned int height)
+{
+ return _call(API_REMOVE, (HRESULT)E_NOTIMPL, width, height);
+}
+
+inline HRESULT ifc_deviceiconstore::RemovePath(const wchar_t *path)
+{
+ return _call(API_REMOVEPATH, (HRESULT)E_NOTIMPL, path);
+}
+
+inline HRESULT ifc_deviceiconstore::RemoveAll()
+{
+ return _call(API_REMOVEALL, (HRESULT)E_NOTIMPL);
+}
+
+inline HRESULT ifc_deviceiconstore::Get(wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height)
+{
+ return _call(API_GET, (HRESULT)E_NOTIMPL, buffer, bufferMax, width, height);
+}
+
+inline HRESULT ifc_deviceiconstore::GetExact(wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height)
+{
+ return _call(API_GETEXACT, (HRESULT)E_NOTIMPL, buffer, bufferMax, width, height);
+}
+
+inline HRESULT ifc_deviceiconstore::SetBasePath(const wchar_t *path)
+{
+ return _call(API_SETBASEPATH, (HRESULT)E_NOTIMPL, path);
+}
+
+inline HRESULT ifc_deviceiconstore::GetBasePath(wchar_t *buffer, size_t bufferMax)
+{
+ return _call(API_GETBASEPATH, (HRESULT)E_NOTIMPL, buffer, bufferMax);
+}
+
+inline HRESULT ifc_deviceiconstore::Clone(ifc_deviceiconstore **instance)
+{
+ return _call(API_CLONE, (HRESULT)E_NOTIMPL, instance);
+}
+
+inline HRESULT ifc_deviceiconstore::Enumerate(EnumeratorCallback callback, void *user)
+{
+ return _call(API_ENUMERATE, (HRESULT)E_NOTIMPL, callback, user);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_ICON_STORE_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_devicemanagerevent.h b/Src/devices/ifc_devicemanagerevent.h
new file mode 100644
index 000000000..68cc1c14a
--- /dev/null
+++ b/Src/devices/ifc_devicemanagerevent.h
@@ -0,0 +1,104 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_EVENT_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_EVENT_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {3D58B8B4-74C8-4fa2-B28D-86E96ABC7200}
+static const GUID IFC_DeviceManagerEvent =
+{ 0x3d58b8b4, 0x74c8, 0x4fa2, { 0xb2, 0x8d, 0x86, 0xe9, 0x6a, 0xbc, 0x72, 0x0 } };
+
+
+#include <bfc/dispatch.h>
+
+class api_devicemanager;
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_devicemanagerevent : public Dispatchable
+{
+protected:
+ ifc_devicemanagerevent() {}
+ ~ifc_devicemanagerevent() {}
+
+public:
+ void TypeAdded(api_devicemanager *manager, ifc_devicetype *type);
+ void TypeRemoved(api_devicemanager *manager, ifc_devicetype *type);
+ void ConnectionAdded(api_devicemanager *manager, ifc_deviceconnection *connection);
+ void ConnectionRemoved(api_devicemanager *manager, ifc_deviceconnection *connection);
+ void CommandAdded(api_devicemanager *manager, ifc_devicecommand *command);
+ void CommandRemoved(api_devicemanager *manager, ifc_devicecommand *command);
+ void DeviceAdded(api_devicemanager *manager, ifc_device *device);
+ void DeviceRemoved(api_devicemanager *manager, ifc_device *device);
+ void DiscoveryStarted(api_devicemanager *manager);
+ void DiscoveryFinished(api_devicemanager *manager);
+
+public:
+ DISPATCH_CODES
+ {
+ API_TYPEADDED = 10,
+ API_TYPEREMOVED = 20,
+ API_CONNECTIONADDED = 30,
+ API_CONNECTIONREMOVED = 40,
+ API_COMMANDADDED = 50,
+ API_COMMANDREMOVED = 60,
+ API_DEVICEADDED = 70,
+ API_DEVICEREMOVED = 80,
+ API_DISCOVERYSTARTED = 90,
+ API_DISCOVERYFINISHED = 100,
+ };
+};
+
+inline void ifc_devicemanagerevent::TypeAdded(api_devicemanager *manager, ifc_devicetype *type)
+{
+ _voidcall(API_TYPEADDED, manager, type);
+}
+
+inline void ifc_devicemanagerevent::TypeRemoved(api_devicemanager *manager, ifc_devicetype *type)
+{
+ _voidcall(API_TYPEREMOVED, manager, type);
+}
+
+inline void ifc_devicemanagerevent::ConnectionAdded(api_devicemanager *manager, ifc_deviceconnection *connection)
+{
+ _voidcall(API_CONNECTIONADDED, manager, connection);
+}
+
+inline void ifc_devicemanagerevent::ConnectionRemoved(api_devicemanager *manager, ifc_deviceconnection *connection)
+{
+ _voidcall(API_CONNECTIONREMOVED, manager, connection);
+}
+
+inline void ifc_devicemanagerevent::CommandAdded(api_devicemanager *manager, ifc_devicecommand *command)
+{
+ _voidcall(API_COMMANDADDED, manager, command);
+}
+
+inline void ifc_devicemanagerevent::CommandRemoved(api_devicemanager *manager, ifc_devicecommand *command)
+{
+ _voidcall(API_COMMANDREMOVED, manager, command);
+}
+
+inline void ifc_devicemanagerevent::DeviceAdded(api_devicemanager *manager, ifc_device *device)
+{
+ _voidcall(API_DEVICEADDED, manager, device);
+}
+
+inline void ifc_devicemanagerevent::DeviceRemoved(api_devicemanager *manager, ifc_device *device)
+{
+ _voidcall(API_DEVICEREMOVED, manager, device);
+}
+
+inline void ifc_devicemanagerevent::DiscoveryStarted(api_devicemanager *manager)
+{
+ _voidcall(API_DISCOVERYSTARTED, manager);
+}
+
+inline void ifc_devicemanagerevent::DiscoveryFinished(api_devicemanager *manager)
+{
+ _voidcall(API_DISCOVERYFINISHED, manager);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_MANAGER_EVENT_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_deviceobject.h b/Src/devices/ifc_deviceobject.h
new file mode 100644
index 000000000..3653e649b
--- /dev/null
+++ b/Src/devices/ifc_deviceobject.h
@@ -0,0 +1,55 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {90A1273D-3E52-415f-ADC1-F151E6240C5B}
+static const GUID IFC_DeviceObject =
+{ 0x90a1273d, 0x3e52, 0x415f, { 0xad, 0xc1, 0xf1, 0x51, 0xe6, 0x24, 0xc, 0x5b } };
+
+
+#include <bfc/dispatch.h>
+
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_deviceobject : public Dispatchable
+{
+protected:
+ ifc_deviceobject() {}
+ ~ifc_deviceobject() {}
+
+public:
+ const char *GetName();
+ HRESULT GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height);
+ HRESULT GetDisplayName(wchar_t *buffer, size_t bufferSize);
+
+public:
+ DISPATCH_CODES
+ {
+ API_GETNAME = -10,
+ API_GETICON = -11,
+ API_GETDISPLAYNAME = -12,
+ };
+};
+
+
+inline const char *ifc_deviceobject::GetName()
+{
+ return _call(API_GETNAME, (const char *)NULL);
+}
+
+inline HRESULT ifc_deviceobject::GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
+{
+ return _call(API_GETICON, (HRESULT)E_NOTIMPL, buffer, bufferSize, width, height);
+}
+
+inline HRESULT ifc_deviceobject::GetDisplayName(wchar_t *buffer, size_t bufferSize)
+{
+ return _call(API_GETDISPLAYNAME, (HRESULT)E_NOTIMPL, buffer, bufferSize);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_deviceobjectenum.h b/Src/devices/ifc_deviceobjectenum.h
new file mode 100644
index 000000000..5dcfbaf6e
--- /dev/null
+++ b/Src/devices/ifc_deviceobjectenum.h
@@ -0,0 +1,63 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_ENUMERATOR_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_ENUMERATOR_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {21135710-8161-46c8-83C5-134CC1E832DF}
+static const GUID IFC_DeviceObjectEnum =
+{ 0x21135710, 0x8161, 0x46c8, { 0x83, 0xc5, 0x13, 0x4c, 0xc1, 0xe8, 0x32, 0xdf } };
+
+
+#include <bfc/dispatch.h>
+
+class ifc_deviceobject;
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_deviceobjectenum : public Dispatchable
+{
+protected:
+ ifc_deviceobjectenum() {}
+ ~ifc_deviceobjectenum() {}
+
+public:
+ HRESULT Next(ifc_deviceobject **buffer, size_t bufferMax, size_t *fetched);
+ HRESULT Reset(void);
+ HRESULT Skip(size_t count);
+ HRESULT GetCount(size_t *count);
+
+public:
+ DISPATCH_CODES
+ {
+ API_NEXT = 10,
+ API_RESET = 20,
+ API_SKIP = 30,
+ API_GETCOUNT = 40,
+
+ };
+};
+
+inline HRESULT ifc_deviceobjectenum::Next(ifc_deviceobject **buffer, size_t bufferMax, size_t *fetched)
+{
+ return _call(API_NEXT, (HRESULT)E_NOTIMPL, buffer, bufferMax, fetched);
+}
+
+inline HRESULT ifc_deviceobjectenum::Reset(void)
+{
+ return _call(API_RESET, (HRESULT)E_NOTIMPL);
+}
+
+inline HRESULT ifc_deviceobjectenum::Skip(size_t count)
+{
+ return _call(API_SKIP, (HRESULT)E_NOTIMPL, count);
+}
+
+inline HRESULT ifc_deviceobjectenum::GetCount(size_t *count)
+{
+ return _call(API_GETCOUNT, (HRESULT)E_NOTIMPL, count);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_OBJECT_ENUMERATOR_INTERFACE_HEADER
diff --git a/Src/devices/ifc_deviceprovider.h b/Src/devices/ifc_deviceprovider.h
new file mode 100644
index 000000000..6f5f5da6e
--- /dev/null
+++ b/Src/devices/ifc_deviceprovider.h
@@ -0,0 +1,54 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_PROVIDER_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_PROVIDER_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {FAC6EBEE-107A-4133-A620-856A281EC704}
+static const GUID IFC_DeviceProvider =
+{ 0xfac6ebee, 0x107a, 0x4133, { 0xa6, 0x20, 0x85, 0x6a, 0x28, 0x1e, 0xc7, 0x4 } };
+
+#include <bfc/dispatch.h>
+
+class api_devicemanager;
+
+class __declspec(novtable) ifc_deviceprovider : public Dispatchable
+{
+protected:
+ ifc_deviceprovider() {}
+ ~ifc_deviceprovider() {}
+
+public:
+ HRESULT BeginDiscovery(api_devicemanager *manager);
+ HRESULT CancelDiscovery();
+ HRESULT GetActive();
+
+public:
+ DISPATCH_CODES
+ {
+ API_BEGINDISCOVERY = 10,
+ API_CANCELDISCOVERY = 20,
+ API_GETACTIVE = 30,
+ };
+};
+
+
+inline HRESULT ifc_deviceprovider::BeginDiscovery(api_devicemanager *manager)
+{
+ return _call(API_BEGINDISCOVERY, (HRESULT)E_NOTIMPL, manager);
+}
+
+inline HRESULT ifc_deviceprovider::CancelDiscovery()
+{
+ return _call(API_CANCELDISCOVERY, (HRESULT)E_NOTIMPL);
+}
+
+inline HRESULT ifc_deviceprovider::GetActive()
+{
+ return _call(API_GETACTIVE, (HRESULT)E_NOTIMPL);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_PROVIDER_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_devicesupportedcommand.h b/Src/devices/ifc_devicesupportedcommand.h
new file mode 100644
index 000000000..f7dc4c7db
--- /dev/null
+++ b/Src/devices/ifc_devicesupportedcommand.h
@@ -0,0 +1,46 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {EFFB983B-D087-4021-8894-BA795626048B}
+static const GUID IFC_DeviceSupportedCommand =
+{ 0xeffb983b, 0xd087, 0x4021, { 0x88, 0x94, 0xba, 0x79, 0x56, 0x26, 0x4, 0x8b } };
+
+
+#include <bfc/dispatch.h>
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_devicesupportedcommand : public Dispatchable
+{
+protected:
+ ifc_devicesupportedcommand() {}
+ ~ifc_devicesupportedcommand() {}
+
+public:
+ const char *GetName();
+ HRESULT GetFlags(DeviceCommandFlags *flags);
+
+public:
+ DISPATCH_CODES
+ {
+ API_GETNAME = 10,
+ API_GETFLAGS = 20,
+ };
+};
+
+inline const char *ifc_devicesupportedcommand::GetName()
+{
+ return _call(API_GETNAME, (const char *)NULL);
+}
+
+inline HRESULT ifc_devicesupportedcommand::GetFlags(DeviceCommandFlags *flags)
+{
+ return _call(API_GETFLAGS, (HRESULT)E_NOTIMPL, flags);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_devicesupportedcommandenum.h b/Src/devices/ifc_devicesupportedcommandenum.h
new file mode 100644
index 000000000..ca68df508
--- /dev/null
+++ b/Src/devices/ifc_devicesupportedcommandenum.h
@@ -0,0 +1,63 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_ENUMERATOR_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_ENUMERATOR_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {BE64390B-D4D0-41d5-87A7-60597F410D97}
+static const GUID IFC_DeviceSupportedCommandEnum =
+{ 0xbe64390b, 0xd4d0, 0x41d5, { 0x87, 0xa7, 0x60, 0x59, 0x7f, 0x41, 0xd, 0x97 } };
+
+
+#include <bfc/dispatch.h>
+
+class ifc_devicesupportedcommand;
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_devicesupportedcommandenum : public Dispatchable
+{
+protected:
+ ifc_devicesupportedcommandenum() {}
+ ~ifc_devicesupportedcommandenum() {}
+
+public:
+ HRESULT Next(ifc_devicesupportedcommand **buffer, size_t bufferMax, size_t *count);
+ HRESULT Reset(void);
+ HRESULT Skip(size_t count);
+ HRESULT GetCount(size_t *count);
+
+public:
+ DISPATCH_CODES
+ {
+ API_NEXT = 10,
+ API_RESET = 20,
+ API_SKIP = 30,
+ API_GETCOUNT = 40,
+ };
+};
+
+inline HRESULT ifc_devicesupportedcommandenum::Next(ifc_devicesupportedcommand **buffer, size_t bufferMax, size_t *count)
+{
+ return _call(API_NEXT, (HRESULT)E_NOTIMPL, buffer, bufferMax, count);
+}
+
+inline HRESULT ifc_devicesupportedcommandenum::Reset(void)
+{
+ return _call(API_RESET, (HRESULT)E_NOTIMPL);
+}
+
+inline HRESULT ifc_devicesupportedcommandenum::Skip(size_t count)
+{
+ return _call(API_SKIP, (HRESULT)E_NOTIMPL, count);
+}
+
+inline HRESULT ifc_devicesupportedcommandenum::GetCount(size_t *count)
+{
+ return _call(API_GETCOUNT, (HRESULT)E_NOTIMPL, count);
+}
+
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_ENUMERATOR_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_devicesupportedcommandstore.h b/Src/devices/ifc_devicesupportedcommandstore.h
new file mode 100644
index 000000000..26373fd87
--- /dev/null
+++ b/Src/devices/ifc_devicesupportedcommandstore.h
@@ -0,0 +1,102 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_STORE_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_STORE_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {098C1639-7E02-4f03-9F75-B871EC867E61}
+static const GUID IFC_DeviceSupportedCommandStore =
+{ 0x98c1639, 0x7e02, 0x4f03, { 0x9f, 0x75, 0xb8, 0x71, 0xec, 0x86, 0x7e, 0x61 } };
+
+
+#include <bfc/dispatch.h>
+
+class ifc_devicesupportedcommand;
+
+// supports AddRef(), Release(), QueryInterface()
+class __declspec(novtable) ifc_devicesupportedcommandstore : public Dispatchable
+{
+protected:
+ ifc_devicesupportedcommandstore() {}
+ ~ifc_devicesupportedcommandstore() {}
+
+public:
+ HRESULT Add(const char *name, DeviceCommandFlags flags);
+ HRESULT Remove(const char *name);
+ HRESULT RemoveAll();
+
+ HRESULT GetFlags(const char *name, DeviceCommandFlags *flagsOut);
+ HRESULT SetFlags(const char *name, DeviceCommandFlags mask, DeviceCommandFlags value);
+
+ HRESULT Get(const char *name, ifc_devicesupportedcommand **command);
+ HRESULT GetActive(ifc_devicesupportedcommand **command);
+
+ HRESULT Enumerate(ifc_devicesupportedcommandenum **enumerator);
+
+ HRESULT Clone(ifc_devicesupportedcommandstore **instance, BOOL fullCopy);
+
+public:
+ DISPATCH_CODES
+ {
+ API_ADD = 10,
+ API_REMOVE = 20,
+ API_REMOVEALL = 30,
+ API_GETFLAGS = 40,
+ API_SETFLAGS = 50,
+ API_GET = 60,
+ API_GETACTIVE = 70,
+ API_ENUMERATE = 80,
+ API_CLONE = 90,
+ };
+};
+
+
+inline HRESULT ifc_devicesupportedcommandstore::Add(const char *name, DeviceCommandFlags flags)
+{
+ return _call(API_ADD, (HRESULT)E_NOTIMPL, name, flags);
+}
+
+inline HRESULT ifc_devicesupportedcommandstore::Remove(const char *name)
+{
+ return _call(API_REMOVE, (HRESULT)E_NOTIMPL, name);
+}
+
+inline HRESULT ifc_devicesupportedcommandstore::RemoveAll()
+{
+ return _call(API_REMOVEALL, (HRESULT)E_NOTIMPL);
+}
+
+inline HRESULT ifc_devicesupportedcommandstore::GetFlags(const char *name, DeviceCommandFlags *flagsOut)
+{
+ return _call(API_GETFLAGS, (HRESULT)E_NOTIMPL, name, flagsOut);
+}
+
+inline HRESULT ifc_devicesupportedcommandstore::SetFlags(const char *name, DeviceCommandFlags mask, DeviceCommandFlags value)
+{
+ return _call(API_SETFLAGS, (HRESULT)E_NOTIMPL, name, mask, value);
+}
+
+inline HRESULT ifc_devicesupportedcommandstore::Get(const char *name, ifc_devicesupportedcommand **command)
+{
+ return _call(API_GET, (HRESULT)E_NOTIMPL, name, command);
+}
+
+inline HRESULT ifc_devicesupportedcommandstore::GetActive(ifc_devicesupportedcommand **command)
+{
+ return _call(API_GETACTIVE, (HRESULT)E_NOTIMPL, command);
+}
+
+inline HRESULT ifc_devicesupportedcommandstore::Enumerate(ifc_devicesupportedcommandenum **enumerator)
+{
+ return _call(API_ENUMERATE, (HRESULT)E_NOTIMPL, enumerator);
+}
+
+inline HRESULT ifc_devicesupportedcommandstore::Clone(ifc_devicesupportedcommandstore **instance, BOOL fullCopy)
+{
+ return _call(API_CLONE, (HRESULT)E_NOTIMPL, instance, fullCopy);
+}
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_SUPPORTED_COMMAND_STORE_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_devicetype.h b/Src/devices/ifc_devicetype.h
new file mode 100644
index 000000000..e03aaa686
--- /dev/null
+++ b/Src/devices/ifc_devicetype.h
@@ -0,0 +1,25 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_TYPE_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_TYPE_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {C2AB1F06-1D88-4d21-A8F4-1B36A1929281}
+static const GUID IFC_DeviceType =
+{ 0xc2ab1f06, 0x1d88, 0x4d21, { 0xa8, 0xf4, 0x1b, 0x36, 0xa1, 0x92, 0x92, 0x81 } };
+
+
+#include "ifc_deviceobject.h"
+
+class __declspec(novtable) ifc_devicetype : public ifc_deviceobject
+{
+protected:
+ ifc_devicetype() {}
+ ~ifc_devicetype() {}
+
+};
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_TYPE_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/ifc_devicetypeeditor.h b/Src/devices/ifc_devicetypeeditor.h
new file mode 100644
index 000000000..e6f3c817b
--- /dev/null
+++ b/Src/devices/ifc_devicetypeeditor.h
@@ -0,0 +1,47 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_DEVICE_TYPE_EDITOR_INTERFACE_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_DEVICE_TYPE_EDITOR_INTERFACE_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <bfc/platform/guid.h>
+
+// {D6CE88AA-94F1-4c7f-BEDB-A45B637CF804}
+static const GUID IFC_DeviceTypeEditor =
+{ 0xd6ce88aa, 0x94f1, 0x4c7f, { 0xbe, 0xdb, 0xa4, 0x5b, 0x63, 0x7c, 0xf8, 0x4 } };
+
+#include <bfc/dispatch.h>
+
+class ifc_deviceiconstore;
+
+class __declspec(novtable) ifc_devicetypeeditor : public Dispatchable
+{
+protected:
+ ifc_devicetypeeditor() {}
+ ~ifc_devicetypeeditor() {}
+
+public:
+ HRESULT GetIconStore(ifc_deviceiconstore **iconStore);
+ HRESULT SetDisplayName(const wchar_t *displayName);
+
+public:
+ DISPATCH_CODES
+ {
+ API_GETICONSTORE = 10,
+ API_SETDISPLAYNAME = 20,
+ };
+};
+
+inline HRESULT ifc_devicetypeeditor::GetIconStore(ifc_deviceiconstore **iconStore)
+{
+ return _call(API_GETICONSTORE, (HRESULT)E_NOTIMPL, iconStore);
+}
+
+inline HRESULT ifc_devicetypeeditor::SetDisplayName(const wchar_t *displayName)
+{
+ return _call(API_SETDISPLAYNAME, (HRESULT)E_NOTIMPL, displayName);
+}
+
+
+#endif //_NULLSOFT_WINAMP_DEVICES_DEVICE_TYPE_EDITOR_INTERFACE_HEADER \ No newline at end of file
diff --git a/Src/devices/main.cpp b/Src/devices/main.cpp
new file mode 100644
index 000000000..707f9b5f3
--- /dev/null
+++ b/Src/devices/main.cpp
@@ -0,0 +1,3 @@
+#include <initguid.h>
+
+#include "main.h"
diff --git a/Src/devices/main.h b/Src/devices/main.h
new file mode 100644
index 000000000..6e20467d8
--- /dev/null
+++ b/Src/devices/main.h
@@ -0,0 +1,48 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_MAIN_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_MAIN_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <wtypes.h>
+
+#include "./common.h"
+#include "./strings.h"
+#include "./plugin.h"
+#include "./ifc_deviceobject.h"
+#include "./ifc_deviceobjectenum.h"
+#include "./api_devicemanager.h"
+#include "./ifc_device.h"
+#include "./ifc_devicetype.h"
+#include "./ifc_devicetypeeditor.h"
+#include "./ifc_devicecommand.h"
+#include "./ifc_devicecommandeditor.h"
+#include "./ifc_deviceconnection.h"
+#include "./ifc_deviceconnectioneditor.h"
+#include "./ifc_deviceevent.h"
+#include "./ifc_deviceeventmanager.h"
+#include "./ifc_deviceprovider.h"
+#include "./ifc_devicesupportedcommand.h"
+#include "./ifc_devicesupportedcommandenum.h"
+#include "./ifc_deviceiconstore.h"
+#include "./deviceManager.h"
+#include "./deviceEventManager.h"
+#include "./deviceObjectStore.h"
+#include "./deviceObjectEnum.h"
+#include "./deviceCommand.h"
+#include "./deviceSupportedCommand.h"
+#include "./deviceSupportedCommandStore.h"
+#include "./deviceSupportedCommandEnum.h"
+#include "./deviceType.h"
+#include "./deviceConnection.h"
+#include "./deviceIconStore.h"
+#include "./component.h"
+
+
+#include "../nu/trace.h"
+
+#include <math.h>
+#include <shlwapi.h>
+
+#endif //_NULLSOFT_WINAMP_DEVICES_MAIN_HEADER \ No newline at end of file
diff --git a/Src/devices/plugin.cpp b/Src/devices/plugin.cpp
new file mode 100644
index 000000000..60c4e0df1
--- /dev/null
+++ b/Src/devices/plugin.cpp
@@ -0,0 +1,31 @@
+#include "main.h"
+#include "./plugin.h"
+#include "./component.h"
+
+static HINSTANCE pluginInstance = NULL;
+static DevicesComponent component;
+
+HINSTANCE
+Plugin_GetInstance()
+{
+ return pluginInstance;
+}
+
+extern "C" __declspec(dllexport) ifc_wa5component *
+GetWinamp5SystemComponent()
+{
+ return &component;
+}
+
+
+BOOL APIENTRY
+DllMain(HANDLE hModule, DWORD uReason, void *reserved)
+{
+ switch(uReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ pluginInstance = (HINSTANCE)hModule;
+ break;
+ }
+ return TRUE;
+}
diff --git a/Src/devices/plugin.h b/Src/devices/plugin.h
new file mode 100644
index 000000000..767c4cc68
--- /dev/null
+++ b/Src/devices/plugin.h
@@ -0,0 +1,14 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_PLUGIN_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_PLUGIN_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#include <wtypes.h>
+
+HINSTANCE
+Plugin_GetInstance(void);
+
+
+#endif //_NULLSOFT_WINAMP_DEVICES_PLUGIN_HEADER \ No newline at end of file
diff --git a/Src/devices/resource.h b/Src/devices/resource.h
new file mode 100644
index 000000000..f1cbc7b36
--- /dev/null
+++ b/Src/devices/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by devices.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Src/devices/strings.cpp b/Src/devices/strings.cpp
new file mode 100644
index 000000000..f3d4b5ccd
--- /dev/null
+++ b/Src/devices/strings.cpp
@@ -0,0 +1,152 @@
+#include "main.h"
+#include "./strings.h"
+#include <strsafe.h>
+
+
+wchar_t *
+String_Malloc(size_t size)
+{
+ return (wchar_t *)calloc(size, sizeof(wchar_t));
+}
+
+wchar_t *
+String_ReAlloc(wchar_t *string, size_t size)
+{
+ return (wchar_t *)realloc(string, sizeof(wchar_t) * size);
+}
+
+void
+String_Free(wchar_t *string)
+{
+ if (NULL != string)
+ free(string);
+}
+
+wchar_t *
+String_Duplicate(const wchar_t *string)
+{
+ int length;
+ wchar_t *copy;
+
+ if (NULL == string)
+ return NULL;
+
+ length = lstrlenW(string) + 1;
+
+ copy = String_Malloc(length);
+ if (NULL != copy)
+ CopyMemory(copy, string, sizeof(wchar_t) * length);
+
+ return copy;
+}
+
+
+char *
+String_ToAnsi(unsigned int codePage, unsigned long flags, const wchar_t *string,
+ int stringLength, const char *defaultChar, BOOL *usedDefaultChar)
+{
+ char *buffer;
+ int bufferSize;
+
+ if (stringLength < 0)
+ stringLength = lstrlen(string);
+
+ bufferSize = WideCharToMultiByte(codePage, flags, string, stringLength,
+ NULL, 0, defaultChar, usedDefaultChar);
+ if (0 == bufferSize)
+ return NULL;
+
+ buffer = AnsiString_Malloc(bufferSize + 1);
+ if (NULL == buffer)
+ return NULL;
+
+ bufferSize = WideCharToMultiByte(codePage, flags, string, stringLength,
+ buffer, bufferSize, defaultChar, usedDefaultChar);
+ if (0 == bufferSize)
+ {
+ AnsiString_Free(buffer);
+ return NULL;
+ }
+ buffer[bufferSize] = '\0';
+ return buffer;
+}
+
+size_t
+String_CopyTo(wchar_t *destination, const wchar_t *source, size_t size)
+{
+ size_t remaining;
+ if (FAILED(StringCchCopyExW(destination, size, source, NULL, &remaining, 0)))
+ return 0;
+
+ return (size - remaining);
+}
+
+char *
+AnsiString_Malloc(size_t size)
+{
+ return (char*)calloc(size, sizeof(char));
+}
+
+char *
+AnsiString_ReAlloc(char *string, size_t size)
+{
+ return (char*)realloc(string, sizeof(char) * size);
+}
+
+void
+AnsiString_Free(char *string)
+{
+ if (NULL != string)
+ free(string);
+}
+
+char *
+AnsiString_Duplicate(const char *string)
+{
+ char *copy;
+ INT length;
+
+ if (NULL == string)
+ return NULL;
+
+ length = lstrlenA(string) + 1;
+
+ copy = AnsiString_Malloc(length);
+ if (NULL != copy)
+ CopyMemory(copy, string, sizeof(char) * length);
+
+ return copy;
+}
+
+
+wchar_t *
+AnsiString_ToUnicode(unsigned int codePage, unsigned long flags, const char* string, INT stringLength)
+{
+ wchar_t *buffer;
+ int buffferSize;
+
+ if (NULL == string)
+ return NULL;
+
+ buffferSize = MultiByteToWideChar(codePage, flags, string, stringLength, NULL, 0);
+ if (0 == buffferSize)
+ return NULL;
+
+ if (stringLength > 0)
+ buffferSize++;
+
+ buffer = String_Malloc(buffferSize);
+ if (NULL == buffer)
+ return NULL;
+
+ if (0 == MultiByteToWideChar(codePage, flags, string, stringLength, buffer, buffferSize))
+ {
+ String_Free(buffer);
+ return NULL;
+ }
+
+ if (stringLength > 0)
+ buffer[buffferSize - 1] = L'\0';
+
+ return buffer;
+} \ No newline at end of file
diff --git a/Src/devices/strings.h b/Src/devices/strings.h
new file mode 100644
index 000000000..c5a0316cb
--- /dev/null
+++ b/Src/devices/strings.h
@@ -0,0 +1,59 @@
+#ifndef _NULLSOFT_WINAMP_DEVICES_STRINGS_HEADER
+#define _NULLSOFT_WINAMP_DEVICES_STRINGS_HEADER
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#define IS_STRING_EMPTY(_string) (NULL == (_string) || L'\0' == *(_string))
+
+wchar_t *
+String_Malloc(size_t size);
+
+wchar_t *
+String_ReAlloc(wchar_t *string,
+ size_t size);
+
+void
+String_Free(wchar_t *string);
+
+wchar_t *
+String_Duplicate(const wchar_t *string);
+
+char *
+String_ToAnsi(unsigned int codePage,
+ unsigned long flags,
+ const wchar_t *string,
+ int stringLength,
+ const char *defaultChar,
+ BOOL *usedDefaultChar);
+
+size_t
+String_CopyTo(wchar_t *destination,
+ const wchar_t *source,
+ size_t size);
+
+/*
+ Ansi String
+*/
+
+char *
+AnsiString_Malloc(size_t size);
+
+char *
+AnsiString_ReAlloc(char *string,
+ size_t size);
+
+void
+AnsiString_Free(char *string);
+
+char *
+AnsiString_Duplicate(const char *string);
+
+wchar_t *
+AnsiString_ToUnicode(unsigned int codePage,
+ unsigned long flags,
+ const char *string,
+ int stringLength);
+
+#endif //_NULLSOFT_WINAMP_DEVICES_STRINGS_HEADER \ No newline at end of file
diff --git a/Src/devices/version.rc2 b/Src/devices/version.rc2
new file mode 100644
index 000000000..4a0e82ec3
--- /dev/null
+++ b/Src/devices/version.rc2
@@ -0,0 +1,39 @@
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+#include "../Winamp/buildType.h"
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION WINAMP_PRODUCTVER
+ PRODUCTVERSION WINAMP_PRODUCTVER
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Winamp SA"
+ VALUE "FileDescription", "Winamp 5.x System Component"
+ VALUE "FileVersion", STR_WINAMP_PRODUCTVER
+ VALUE "InternalName", "devices.w5s"
+ VALUE "LegalCopyright", "Copyright © 2006-2023 Winamp SA"
+ VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
+ VALUE "OriginalFilename", "devices.w5s"
+ VALUE "ProductName", "Winamp Devices Support Service"
+ VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END