aboutsummaryrefslogtreecommitdiff
path: root/Src/devices/deviceIconStore.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/devices/deviceIconStore.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/devices/deviceIconStore.cpp')
-rw-r--r--Src/devices/deviceIconStore.cpp501
1 files changed, 501 insertions, 0 deletions
diff --git a/Src/devices/deviceIconStore.cpp b/Src/devices/deviceIconStore.cpp
new file mode 100644
index 00000000..45b48b06
--- /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