diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/devices/deviceIconStore.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/devices/deviceIconStore.cpp')
-rw-r--r-- | Src/devices/deviceIconStore.cpp | 501 |
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 |