From 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d Mon Sep 17 00:00:00 2001 From: Jef Date: Tue, 24 Sep 2024 14:54:57 +0200 Subject: Initial community commit --- Src/Plugins/Library/ml_devices/navigationIcons.cpp | 343 +++++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 Src/Plugins/Library/ml_devices/navigationIcons.cpp (limited to 'Src/Plugins/Library/ml_devices/navigationIcons.cpp') diff --git a/Src/Plugins/Library/ml_devices/navigationIcons.cpp b/Src/Plugins/Library/ml_devices/navigationIcons.cpp new file mode 100644 index 00000000..038c682d --- /dev/null +++ b/Src/Plugins/Library/ml_devices/navigationIcons.cpp @@ -0,0 +1,343 @@ +#include "main.h" +#include "navigationIcons.h" + +#include + +typedef struct IconCacheRecord +{ + size_t ref; + int index; + DeviceImage *image; +} IconCacheRecord; + +typedef std::vector IconCache; + +static IconCache iconCache; + +static BOOL +NavigationIcons_GetSize(unsigned int *width, unsigned int *height) +{ + HWND libraryWindow; + MLIMAGELISTIMAGESIZE imageSize; + + libraryWindow = Plugin_GetLibraryWindow(); + + imageSize.hmlil = MLNavCtrl_GetImageList(libraryWindow); + if (NULL == imageSize.hmlil) + return FALSE; + + if (FALSE == MLImageList_GetImageSize(libraryWindow, &imageSize)) + return FALSE; + + *width = imageSize.cx; + *height = imageSize.cy; + + return TRUE; +} + +static DeviceImage* +NavigationIcons_GetDeviceImage(ifc_device *device, unsigned int width, unsigned int height) +{ + wchar_t path[MAX_PATH * 2] = {0}; + + if (NULL == device) + return NULL; + + if (FAILED(device->GetIcon(path, ARRAYSIZE(path), width, height))) + return NULL; + + return DeviceImageCache_GetImage(Plugin_GetImageCache(), + path, width, height, NULL, NULL); +} + +static DeviceImage* +NavigationIcons_GetDeviceTypeImage(ifc_device *device, unsigned int width, unsigned int height) +{ + ifc_devicetype *type; + DeviceImage *image; + wchar_t path[MAX_PATH * 2] = {0}; + + if (NULL == device || + NULL == WASABI_API_DEVICES || + S_OK != WASABI_API_DEVICES->TypeFind(device->GetName(), &type)) + { + return NULL; + } + + if (SUCCEEDED(type->GetIcon(path, ARRAYSIZE(path), width, height))) + { + + image = DeviceImageCache_GetImage(Plugin_GetImageCache(), + path, width, height, NULL, NULL); + } + else + image = NULL; + + type->Release(); + + return image; +} + +static DeviceImage* +NavigationIcons_GetDefaultImage(ifc_device *device, unsigned int width, unsigned int height) +{ + const wchar_t *path; + + path = Plugin_GetDefaultDeviceImage(width, height); + if (NULL == path) + return NULL; + + return DeviceImageCache_GetImage(Plugin_GetImageCache(), path, width, height, NULL, NULL); +} + +static int +NavigationIcons_RegisterDeviceIcon(DeviceImage *image, int iconIndex) +{ + MLIMAGESOURCE imageSource; + MLIMAGELISTITEM listItem; + HWND libraryWindow; + HBITMAP bitmap; + + if (NULL == image) + return -1; + + libraryWindow = Plugin_GetLibraryWindow(); + if (NULL == libraryWindow) + return -1; + + + bitmap = DeviceImage_GetBitmap(image, + DeviceImage_ExactSize | DeviceImage_AlignHCenter | DeviceImage_AlignVCenter); + + if (NULL == bitmap) + return -1; + + + imageSource.cbSize = sizeof(imageSource); + imageSource.lpszName = (LPCWSTR)bitmap; + imageSource.type = SRC_TYPE_HBITMAP; + imageSource.bpp = 32; + imageSource.flags = 0; + imageSource.hInst = NULL; + + listItem.cbSize = sizeof(listItem); + listItem.hmlil = MLNavCtrl_GetImageList(libraryWindow); + listItem.filterUID = MLIF_FILTER3_UID; + listItem.pmlImgSource = &imageSource; + listItem.mlilIndex = iconIndex; + + if (NULL == listItem.hmlil) + return -1; + + if (listItem.mlilIndex >= 0) + { + if (FALSE == MLImageList_Replace(libraryWindow, &listItem)) + return -1; + + return listItem.mlilIndex; + } + + return MLImageList_Add(libraryWindow, &listItem); +} + + +static IconCacheRecord * +NavigationIcons_FindCacheRecord(DeviceImage *image) +{ + size_t index; + IconCacheRecord *record; + + if (NULL == image) + return NULL; + + index = iconCache.size(); + while(index--) + { + record = &iconCache[index]; + if (record->image == image) + return record; + } + + return NULL; +} + +static IconCacheRecord * +NavigationIcons_FindAvailableCacheRecord() +{ + size_t index; + IconCacheRecord *record; + + index = iconCache.size(); + while(index--) + { + record = &iconCache[index]; + if (0 == record->ref) + return record; + } + + return NULL; +} + +static IconCacheRecord * +NavigationIcons_FindCacheRecordByIndex(int iconIndex) +{ + size_t index; + IconCacheRecord *record; + + if (iconIndex < 0) + return NULL; + + index = iconCache.size(); + while(index--) + { + record = &iconCache[index]; + if (record->index == iconIndex) + return record; + } + + return NULL; +} + +static IconCacheRecord * +NavigationIcons_CreateCacheRecord(DeviceImage *image, int iconIndex) +{ + IconCacheRecord record; + + if (NULL == image || -1 == iconIndex) + return NULL; + + record.ref = 1; + record.index = iconIndex; + record.image = image; + + DeviceImage_AddRef(image); + + iconCache.push_back(record); + return &iconCache.back(); +} + +static HBITMAP +NavigationIcons_GetDeviceImageBitmap(DeviceImage *image) +{ + return DeviceImage_GetBitmap(image, + DeviceImage_ExactSize | + DeviceImage_AlignHCenter | + DeviceImage_AlignVCenter); +} + +int +NavigationIcons_GetDeviceIconIndex(ifc_device *device) +{ + DeviceImage *image; + unsigned int width, height; + IconCacheRecord *record; + int iconIndex; + size_t attempt; + + if (FALSE == NavigationIcons_GetSize(&width, &height)) + return -1; + + for(attempt = 0; attempt < 3; attempt++) + { + switch(attempt) + { + case 0: + image = NavigationIcons_GetDeviceImage(device, width, height); + break; + case 1: + image = NavigationIcons_GetDeviceTypeImage(device, width, height); + break; + case 2: + image = NavigationIcons_GetDefaultImage(device, width, height); + break; + } + + record = (NULL != image) ? + NavigationIcons_FindCacheRecord(image) : + NULL; + + if (NULL == record && + NULL == NavigationIcons_GetDeviceImageBitmap(image)) + { + continue; + } + + break; + } + + if (NULL != record) + { + record->ref++; + iconIndex = record->index; + } + else + { + record = NavigationIcons_FindAvailableCacheRecord(); + if (NULL != record) + { + iconIndex = NavigationIcons_RegisterDeviceIcon(image, record->index); + if (-1 != iconIndex) + { + record->ref++; + record->image = image; + } + } + else + { + iconIndex = NavigationIcons_RegisterDeviceIcon(image, -1); + if (-1 != iconIndex) + { + IconCacheRecord newRecord; + newRecord.ref = 1; + newRecord.image = image; + newRecord.index = iconIndex; + iconCache.push_back(newRecord); + } + } + } + + if (-1 == iconIndex) + DeviceImage_Release(image); + + return iconIndex; +} + +BOOL +NavigationIcons_ReleaseIconIndex(int iconIndex) +{ + IconCacheRecord *record; + + record = NavigationIcons_FindCacheRecordByIndex(iconIndex); + if (NULL == record) + return FALSE; + + if (0 == record->ref) + return FALSE; + + record->ref--; + DeviceImage_Release(record->image); + if (0 == record->ref) + record->image = NULL; + + return TRUE; +} + +void +NavigationIcons_ClearCache() +{ + size_t index; + IconCacheRecord *record; + + index = iconCache.size(); + while(index--) + { + record = &iconCache[index]; + if (NULL != record->image) + { + while(record->ref--) + DeviceImage_Release(record->image); + record->image = NULL; + } + record->ref = 0; + } +} \ No newline at end of file -- cgit