Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
276
Src/Plugins/Library/ml_devices/backBuffer.cpp
Normal file
276
Src/Plugins/Library/ml_devices/backBuffer.cpp
Normal file
|
@ -0,0 +1,276 @@
|
|||
#include "main.h"
|
||||
#include "./backBuffer.h"
|
||||
|
||||
|
||||
BOOL
|
||||
BackBuffer_Initialize(BackBuffer *self, HWND hwnd)
|
||||
{
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
ZeroMemory(self, sizeof(BackBuffer));
|
||||
|
||||
self->hwnd = hwnd;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
BackBuffer_Uninitialize(BackBuffer *self)
|
||||
{
|
||||
BackBuffer_Reset(self);
|
||||
}
|
||||
|
||||
void
|
||||
BackBuffer_Reset(BackBuffer *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
if (NULL != self->hdc)
|
||||
{
|
||||
if (NULL != self->previous)
|
||||
SelectBitmap(self->hdc, self->previous);
|
||||
|
||||
DeleteDC(self->hdc);
|
||||
}
|
||||
|
||||
if (NULL != self->bitmap)
|
||||
{
|
||||
DeleteObject(self->bitmap);
|
||||
}
|
||||
|
||||
ZeroMemory(self, sizeof(BackBuffer));
|
||||
}
|
||||
|
||||
BOOL
|
||||
BackBuffer_EnsureSize(BackBuffer *self, long width, long height)
|
||||
{
|
||||
return BackBuffer_EnsureSizeEx(self, width, height, width, height);
|
||||
}
|
||||
|
||||
BOOL
|
||||
BackBuffer_EnsureSizeEx(BackBuffer *self, long width, long height, long allocWidth, long allocHeight)
|
||||
{
|
||||
BOOL result;
|
||||
HDC windowDC;
|
||||
HBITMAP bitmap;
|
||||
long bitmapWidth, bitmapHeight;
|
||||
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
if (width < 0)
|
||||
width = 0;
|
||||
|
||||
if (height < 0)
|
||||
height = 0;
|
||||
|
||||
if (NULL != self->bitmap)
|
||||
{
|
||||
BITMAP bitmapInfo;
|
||||
if (sizeof(bitmapInfo) == GetObject(self->bitmap, sizeof(bitmapInfo), &bitmapInfo))
|
||||
{
|
||||
if (bitmapInfo.bmWidth >= width && bitmapInfo.bmHeight >= height)
|
||||
return TRUE;
|
||||
|
||||
bitmapWidth = bitmapInfo.bmWidth;
|
||||
bitmapHeight = bitmapInfo.bmHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmapWidth = 0;
|
||||
bitmapHeight = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmapWidth = 0;
|
||||
bitmapHeight = 0;
|
||||
}
|
||||
|
||||
result = FALSE;
|
||||
bitmap = NULL;
|
||||
|
||||
windowDC = GetDCEx(self->hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if(NULL != windowDC)
|
||||
{
|
||||
if (allocWidth < width)
|
||||
allocWidth = width;
|
||||
|
||||
if (allocWidth < bitmapWidth)
|
||||
allocWidth = bitmapWidth;
|
||||
|
||||
if (allocHeight < height)
|
||||
allocHeight = height;
|
||||
|
||||
if (allocHeight < bitmapHeight)
|
||||
allocHeight = bitmapHeight;
|
||||
|
||||
bitmap = CreateCompatibleBitmap(windowDC, allocWidth, allocHeight);
|
||||
ReleaseDC(self->hwnd, windowDC);
|
||||
}
|
||||
|
||||
if (NULL != bitmap)
|
||||
{
|
||||
if (NULL != self->hdc)
|
||||
SelectBitmap(self->hdc, bitmap);
|
||||
|
||||
if (NULL != self->bitmap)
|
||||
DeleteObject(self->bitmap);
|
||||
|
||||
self->bitmap = bitmap;
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HDC
|
||||
BackBuffer_GetDC(BackBuffer *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == self->hdc)
|
||||
{
|
||||
HDC windowDC;
|
||||
windowDC = GetDCEx(self->hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL != windowDC)
|
||||
{
|
||||
self->hdc = CreateCompatibleDC(windowDC);
|
||||
ReleaseDC(self->hwnd, windowDC);
|
||||
|
||||
if (NULL != self->hdc)
|
||||
{
|
||||
if (NULL != self->bitmap)
|
||||
self->previous = SelectBitmap(self->hdc, self->bitmap);
|
||||
else
|
||||
self->previous = GetCurrentBitmap(self->hdc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self->hdc;
|
||||
}
|
||||
|
||||
BOOL
|
||||
BackBuffer_Copy(BackBuffer *self, HDC hdc, long x, long y, long width, long height)
|
||||
{
|
||||
HDC sourceDC;
|
||||
|
||||
if (NULL == self || NULL == self->bitmap)
|
||||
return FALSE;
|
||||
|
||||
sourceDC = BackBuffer_GetDC(self);
|
||||
if (NULL == sourceDC)
|
||||
return FALSE;
|
||||
|
||||
return BitBlt(hdc, x, y, width, height, sourceDC, 0, 0, SRCCOPY);
|
||||
}
|
||||
|
||||
BOOL
|
||||
BackBuffer_DrawTextEx(BackBuffer *self, HDC hdc, const wchar_t *string,
|
||||
int length, RECT *rect, unsigned int format,
|
||||
HFONT font, COLORREF backColor, COLORREF textColor, int backMode)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
RECT bufferRect;
|
||||
|
||||
if (NULL == hdc || NULL == rect)
|
||||
return FALSE;
|
||||
|
||||
SetRect(&bufferRect, 0, 0, RECTWIDTH(*rect), RECTHEIGHT(*rect));
|
||||
|
||||
if (NULL != self &&
|
||||
FALSE != BackBuffer_EnsureSize(self, bufferRect.right, bufferRect.bottom))
|
||||
{
|
||||
HDC bufferDC = BackBuffer_GetDC(self);
|
||||
if (NULL != bufferDC)
|
||||
{
|
||||
HFONT prevFont;
|
||||
prevFont = SelectFont(bufferDC, font);
|
||||
SetTextColor(bufferDC, textColor);
|
||||
SetBkColor(bufferDC, backColor);
|
||||
SetBkMode(bufferDC, backMode);
|
||||
|
||||
if (OPAQUE == backMode)
|
||||
ExtTextOut(bufferDC, 0, 0, ETO_OPAQUE, &bufferRect, NULL, 0, NULL);
|
||||
|
||||
if (FALSE != DrawText(bufferDC, string, length, &bufferRect, format))
|
||||
{
|
||||
result = BackBuffer_Copy(self, hdc, rect->left, rect->top,
|
||||
bufferRect.right, bufferRect.bottom);
|
||||
}
|
||||
|
||||
SelectFont(bufferDC, prevFont);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (FALSE == result)
|
||||
{
|
||||
HFONT prevFont;
|
||||
COLORREF prevBackColor, prevTextColor;
|
||||
int prevBkMode;
|
||||
|
||||
prevFont = SelectFont(hdc, font);
|
||||
prevTextColor = SetTextColor(hdc, textColor);
|
||||
prevBackColor = SetBkColor(hdc, backColor);
|
||||
prevBkMode= SetBkMode(hdc, backMode);
|
||||
|
||||
result = DrawText(hdc, string, length, rect, format);
|
||||
|
||||
SelectFont(hdc, prevFont);
|
||||
SetTextColor(hdc, prevTextColor);
|
||||
SetBkColor(hdc, prevBackColor);
|
||||
SetBkMode(hdc, prevBkMode);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL
|
||||
BackBuffer_DrawText(BackBuffer *self, HDC hdc, const wchar_t *string,
|
||||
int length, RECT *rect, unsigned int format)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
RECT bufferRect;
|
||||
|
||||
if (NULL == hdc || NULL == rect)
|
||||
return FALSE;
|
||||
|
||||
SetRect(&bufferRect, 0, 0, RECTWIDTH(*rect), RECTHEIGHT(*rect));
|
||||
|
||||
if (NULL != self &&
|
||||
FALSE != BackBuffer_EnsureSize(self, bufferRect.right, bufferRect.bottom))
|
||||
{
|
||||
HDC bufferDC = BackBuffer_GetDC(self);
|
||||
if (NULL != bufferDC)
|
||||
{
|
||||
HFONT prevFont;
|
||||
int backMode;
|
||||
prevFont = SelectFont(bufferDC, GetCurrentFont(hdc));
|
||||
SetTextColor(bufferDC, GetTextColor(hdc));
|
||||
SetBkColor(bufferDC, GetBkColor(hdc));
|
||||
backMode = GetBkMode(hdc);
|
||||
SetBkMode(bufferDC, backMode);
|
||||
|
||||
if (OPAQUE == backMode)
|
||||
ExtTextOut(bufferDC, 0, 0, ETO_OPAQUE, &bufferRect, NULL, 0, NULL);
|
||||
|
||||
if (FALSE != DrawText(bufferDC, string, length, &bufferRect, format))
|
||||
{
|
||||
result = BackBuffer_Copy(self, hdc, rect->left, rect->top,
|
||||
bufferRect.right, bufferRect.bottom);
|
||||
}
|
||||
|
||||
SelectFont(bufferDC, prevFont);
|
||||
}
|
||||
}
|
||||
|
||||
if (FALSE == result)
|
||||
result = DrawText(hdc, string, length, rect, format);
|
||||
|
||||
return result;
|
||||
}
|
64
Src/Plugins/Library/ml_devices/backBuffer.h
Normal file
64
Src/Plugins/Library/ml_devices/backBuffer.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_BACK_BUFFER_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_BACK_BUFFER_HEADER
|
||||
|
||||
typedef struct BackBuffer
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
HWND hwnd;
|
||||
HDC hdc;
|
||||
HBITMAP previous;
|
||||
} BackBuffer;
|
||||
|
||||
BOOL
|
||||
BackBuffer_Initialize(BackBuffer *self, HWND hwnd);
|
||||
|
||||
void
|
||||
BackBuffer_Uninitialize(BackBuffer *self);
|
||||
|
||||
BOOL
|
||||
BackBuffer_EnsureSize(BackBuffer *self,
|
||||
long width,
|
||||
long height);
|
||||
|
||||
BOOL
|
||||
BackBuffer_EnsureSizeEx(BackBuffer *self,
|
||||
long width,
|
||||
long height,
|
||||
long allocWidth,
|
||||
long allocHeight);
|
||||
|
||||
HDC
|
||||
BackBuffer_GetDC(BackBuffer *self);
|
||||
|
||||
BOOL
|
||||
BackBuffer_Copy(BackBuffer *self,
|
||||
HDC hdc,
|
||||
long x,
|
||||
long y,
|
||||
long width,
|
||||
long height);
|
||||
|
||||
void
|
||||
BackBuffer_Reset(BackBuffer *self);
|
||||
|
||||
BOOL
|
||||
BackBuffer_DrawText(BackBuffer *self,
|
||||
HDC hdc,
|
||||
const wchar_t *string,
|
||||
int length,
|
||||
RECT *rect,
|
||||
unsigned int format);
|
||||
|
||||
BOOL
|
||||
BackBuffer_DrawTextEx(BackBuffer *self,
|
||||
HDC hdc,
|
||||
const wchar_t *string,
|
||||
int length,
|
||||
RECT *rect,
|
||||
unsigned int format,
|
||||
HFONT font,
|
||||
COLORREF backColor,
|
||||
COLORREF textColor,
|
||||
int backMode);
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_BACK_BUFFER_HEADER
|
76
Src/Plugins/Library/ml_devices/common.h
Normal file
76
Src/Plugins/Library/ml_devices/common.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_COMMON_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_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_ML_DEVICES_COMMON_HEADER
|
119
Src/Plugins/Library/ml_devices/config.cpp
Normal file
119
Src/Plugins/Library/ml_devices/config.cpp
Normal file
|
@ -0,0 +1,119 @@
|
|||
#include "main.h"
|
||||
#include "./config.h"
|
||||
|
||||
#include <strsafe.h>
|
||||
|
||||
#define CONFIG_SUFFIX L"Plugins\\ml"
|
||||
#define CONFIG_FILE L"ml_devices.ini"
|
||||
|
||||
static const char *
|
||||
Config_GetPath(BOOL ensureExist)
|
||||
{
|
||||
static const char *configPath = NULL;
|
||||
if (NULL == configPath)
|
||||
{
|
||||
const wchar_t *userPath;
|
||||
wchar_t buffer[MAX_PATH * 2] = {0};
|
||||
|
||||
if (NULL == WASABI_API_APP)
|
||||
return NULL;
|
||||
|
||||
userPath = WASABI_API_APP->path_getUserSettingsPath();
|
||||
if (NULL == userPath)
|
||||
return NULL;
|
||||
|
||||
if (0 != PathCombine(buffer, userPath, CONFIG_SUFFIX))
|
||||
{
|
||||
if ((FALSE == ensureExist || SUCCEEDED(Plugin_EnsurePathExist(buffer))) &&
|
||||
FALSE != PathAppend(buffer,CONFIG_FILE))
|
||||
{
|
||||
configPath = String_ToAnsi(CP_UTF8, 0, buffer, -1, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return configPath;
|
||||
}
|
||||
|
||||
|
||||
unsigned long
|
||||
Config_ReadString(const char *section, const char *key, const char *defaultValue, char *returnedString, unsigned long size)
|
||||
{
|
||||
return GetPrivateProfileStringA(section, key, defaultValue, returnedString, size, Config_GetPath(FALSE));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
Config_ReadInt(const char *section, const char *key, int defaultValue)
|
||||
{
|
||||
return GetPrivateProfileIntA(section, key, defaultValue, Config_GetPath(FALSE));
|
||||
}
|
||||
|
||||
BOOL
|
||||
Config_ReadBool(const char *section, const char *key, BOOL defaultValue)
|
||||
{
|
||||
char buffer[32] = {0};
|
||||
int length = Config_ReadString(section, key, NULL, buffer, ARRAYSIZE(buffer));
|
||||
|
||||
if (0 == length)
|
||||
return defaultValue;
|
||||
|
||||
if (1 == length)
|
||||
{
|
||||
switch(*buffer)
|
||||
{
|
||||
case '0':
|
||||
case 'n':
|
||||
case 'f':
|
||||
return FALSE;
|
||||
case '1':
|
||||
case 'y':
|
||||
case 't':
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "yes", -1, buffer, length) ||
|
||||
CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "true", -1, buffer, length))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "no", -1, buffer, length) ||
|
||||
CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "false", -1, buffer, length))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (FALSE != StrToIntExA(buffer, STIF_SUPPORT_HEX, &length))
|
||||
return (0 != length);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Config_WriteString(const char *section, const char *key, const char *value)
|
||||
{
|
||||
const char *configPath = Config_GetPath(TRUE);
|
||||
if (NULL == configPath || '\0' == *configPath)
|
||||
return FALSE;
|
||||
|
||||
return (0 != WritePrivateProfileStringA(section, key, value, configPath));
|
||||
}
|
||||
|
||||
BOOL
|
||||
Config_WriteInt(const char *section, const char *key, int value)
|
||||
{
|
||||
char buffer[32] = {0};
|
||||
if (FAILED(StringCchPrintfA(buffer, ARRAYSIZE(buffer), "%d", value)))
|
||||
return FALSE;
|
||||
|
||||
return Config_WriteString(section, key, buffer);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Config_WriteBool(const char *section, const char *key, BOOL value)
|
||||
{
|
||||
return Config_WriteString(section, key, (FALSE != value) ? "yes" : "no");
|
||||
}
|
44
Src/Plugins/Library/ml_devices/config.h
Normal file
44
Src/Plugins/Library/ml_devices/config.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_CONFIG_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_CONFIG_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
|
||||
unsigned long
|
||||
Config_ReadString(const char *section,
|
||||
const char *key,
|
||||
const char *defaultValue,
|
||||
char *returnedStrign,
|
||||
unsigned long size);
|
||||
|
||||
unsigned int
|
||||
Config_ReadInt(const char *section,
|
||||
const char *key,
|
||||
int defaultValue);
|
||||
|
||||
BOOL
|
||||
Config_ReadBool(const char *section,
|
||||
const char *key,
|
||||
BOOL defaultValue);
|
||||
|
||||
BOOL
|
||||
Config_WriteString(const char *section,
|
||||
const char *key,
|
||||
const char *value);
|
||||
|
||||
|
||||
BOOL
|
||||
Config_WriteInt(const char *section,
|
||||
const char *key,
|
||||
int value);
|
||||
|
||||
BOOL
|
||||
Config_WriteBool(const char *section,
|
||||
const char *key,
|
||||
BOOL value);
|
||||
|
||||
#endif // _NULLSOFT_WINAMP_ML_DEVICES_CONFIG_HEADER
|
207
Src/Plugins/Library/ml_devices/deviceCommands.cpp
Normal file
207
Src/Plugins/Library/ml_devices/deviceCommands.cpp
Normal file
|
@ -0,0 +1,207 @@
|
|||
#include "main.h"
|
||||
#include "deviceCommands.h"
|
||||
|
||||
|
||||
typedef struct DeviceCommandInfo
|
||||
{
|
||||
const char *name;
|
||||
unsigned int title;
|
||||
unsigned int description;
|
||||
unsigned int smallIcon;
|
||||
unsigned int largeIcon;
|
||||
} DeviceCommandInfo;
|
||||
|
||||
|
||||
static DeviceCommandInfo registeredCommands[] =
|
||||
{
|
||||
{ "sync",
|
||||
IDS_SYNC_COMMAND_TITLE,
|
||||
IDS_SYNC_COMMAND_DESC,
|
||||
IDR_SYNC_COMMAND_SMALL_IMAGE,
|
||||
IDR_SYNC_COMMAND_LARGE_IMAGE },
|
||||
{ "cancel_sync",
|
||||
IDS_CANCEL_SYNC_COMMAND_TITLE,
|
||||
IDS_CANCEL_SYNC_COMMAND_DESC,
|
||||
IDR_CANCEL_SYNC_COMMAND_SMALL_IMAGE,
|
||||
IDR_CANCEL_SYNC_COMMAND_LARGE_IMAGE },
|
||||
{ "attach",
|
||||
IDS_ATTACH_COMMAND_TITLE,
|
||||
IDS_ATTACH_COMMAND_DESC,
|
||||
IDR_ATTACH_COMMAND_SMALL_IMAGE,
|
||||
IDR_ATTACH_COMMAND_LARGE_IMAGE },
|
||||
{ "detach",
|
||||
IDS_DETACH_COMMAND_TITLE,
|
||||
IDS_DETACH_COMMAND_DESC,
|
||||
IDR_DETACH_COMMAND_SMALL_IMAGE,
|
||||
IDR_DETACH_COMMAND_LARGE_IMAGE },
|
||||
{ "eject",
|
||||
IDS_EJECT_COMMAND_TITLE,
|
||||
IDS_EJECT_COMMAND_DESC,
|
||||
IDR_EJECT_COMMAND_SMALL_IMAGE,
|
||||
IDR_EJECT_COMMAND_LARGE_IMAGE },
|
||||
{ "rename",
|
||||
IDS_RENAME_COMMAND_TITLE,
|
||||
IDS_RENAME_COMMAND_DESC,
|
||||
IDR_RENAME_COMMAND_SMALL_IMAGE,
|
||||
IDR_RENAME_COMMAND_LARGE_IMAGE },
|
||||
{ "view_open",
|
||||
IDS_VIEW_OPEN_COMMAND_TITLE,
|
||||
IDS_VIEW_OPEN_COMMAND_DESC,
|
||||
IDR_VIEW_OPEN_COMMAND_SMALL_IMAGE,
|
||||
IDR_VIEW_OPEN_COMMAND_LARGE_IMAGE },
|
||||
{ "preferences",
|
||||
IDS_PREFERENCES_COMMAND_TITLE,
|
||||
IDS_PREFERENCES_COMMAND_DESC,
|
||||
IDR_PREFERENCES_COMMAND_SMALL_IMAGE,
|
||||
IDR_PREFERENCES_COMMAND_LARGE_IMAGE },
|
||||
{ "playlist_create",
|
||||
IDS_PLAYLIST_CREATE_COMMAND_TITLE,
|
||||
IDS_PLAYLIST_CREATE_COMMAND_DESC,
|
||||
IDR_PLAYLIST_CREATE_COMMAND_SMALL_IMAGE,
|
||||
IDR_PLAYLIST_CREATE_COMMAND_LARGE_IMAGE },
|
||||
};
|
||||
|
||||
static ifc_devicecommand * _cdecl
|
||||
DeviceCommands_RegisterCommandCb(const char *name, void *user)
|
||||
{
|
||||
size_t index;
|
||||
wchar_t buffer[2048] = {0};
|
||||
DeviceCommandInfo *commandInfo;
|
||||
ifc_devicecommand *command;
|
||||
ifc_devicecommandeditor *editor;
|
||||
|
||||
commandInfo = NULL;
|
||||
for(index = 0; index < ARRAYSIZE(registeredCommands); index++)
|
||||
{
|
||||
if (name == registeredCommands[index].name)
|
||||
{
|
||||
commandInfo = ®isteredCommands[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == commandInfo)
|
||||
return NULL;
|
||||
|
||||
if (NULL == WASABI_API_DEVICES)
|
||||
return NULL;
|
||||
|
||||
if (FAILED(WASABI_API_DEVICES->CreateCommand(commandInfo->name, &command)))
|
||||
return NULL;
|
||||
|
||||
if (FAILED(command->QueryInterface(IFC_DeviceCommandEditor, (void**)&editor)))
|
||||
{
|
||||
command->Release();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (0 != commandInfo->title)
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF(commandInfo->title, buffer, ARRAYSIZE(buffer));
|
||||
editor->SetDisplayName(buffer);
|
||||
}
|
||||
|
||||
if (0 != commandInfo->description)
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF(commandInfo->description, buffer, ARRAYSIZE(buffer));
|
||||
editor->SetDescription(buffer);
|
||||
}
|
||||
|
||||
if (0 != commandInfo->smallIcon || 0 != commandInfo->largeIcon)
|
||||
{
|
||||
ifc_deviceiconstore *iconStore;
|
||||
if (SUCCEEDED(editor->GetIconStore(&iconStore)))
|
||||
{
|
||||
if (0 != commandInfo->smallIcon)
|
||||
{
|
||||
if (FALSE != Plugin_GetResourceString(MAKEINTRESOURCE(commandInfo->smallIcon), RT_RCDATA, buffer, ARRAYSIZE(buffer)))
|
||||
iconStore->Add(buffer, 16, 16, TRUE);
|
||||
}
|
||||
|
||||
if (0 != commandInfo->largeIcon)
|
||||
{
|
||||
if (FALSE != Plugin_GetResourceString(MAKEINTRESOURCE(commandInfo->largeIcon), RT_RCDATA, buffer, ARRAYSIZE(buffer)))
|
||||
iconStore->Add(buffer, 43, 24, TRUE);
|
||||
}
|
||||
|
||||
iconStore->Release();
|
||||
}
|
||||
}
|
||||
|
||||
editor->Release();
|
||||
return command;
|
||||
}
|
||||
|
||||
BOOL
|
||||
DeviceCommands_Register()
|
||||
{
|
||||
const char *commands[ARRAYSIZE(registeredCommands)];
|
||||
size_t index;
|
||||
|
||||
if (NULL == WASABI_API_DEVICES)
|
||||
return FALSE;
|
||||
|
||||
for(index = 0; index < ARRAYSIZE(commands); index++)
|
||||
{
|
||||
commands[index] = registeredCommands[index].name;
|
||||
}
|
||||
|
||||
WASABI_API_DEVICES->CommandRegisterIndirect(commands, ARRAYSIZE(commands), DeviceCommands_RegisterCommandCb, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
DeviceCommand_GetSupported(ifc_device *device, const char *name, DeviceCommandContext context,
|
||||
ifc_devicesupportedcommand **commandOut)
|
||||
{
|
||||
ifc_devicesupportedcommandenum *enumerator;
|
||||
ifc_devicesupportedcommand *command;
|
||||
BOOL foundCommand;
|
||||
|
||||
if (NULL == device ||
|
||||
NULL == name ||
|
||||
FAILED(device->EnumerateCommands(&enumerator, context)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
foundCommand = FALSE;
|
||||
|
||||
while (S_OK == enumerator->Next(&command, 1, NULL))
|
||||
{
|
||||
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, name, -1, command->GetName(), -1))
|
||||
{
|
||||
foundCommand = TRUE;
|
||||
|
||||
if (NULL != commandOut)
|
||||
*commandOut = command;
|
||||
else
|
||||
command->Release();
|
||||
|
||||
break;
|
||||
}
|
||||
command->Release();
|
||||
}
|
||||
|
||||
enumerator->Release();
|
||||
return foundCommand;
|
||||
}
|
||||
|
||||
BOOL
|
||||
DeviceCommand_GetEnabled(ifc_device *device, const char *name, DeviceCommandContext context)
|
||||
{
|
||||
ifc_devicesupportedcommand *command;
|
||||
DeviceCommandFlags flags;
|
||||
|
||||
if (FALSE == DeviceCommand_GetSupported(device, name, context, &command))
|
||||
return FALSE;
|
||||
|
||||
if (FAILED(command->GetFlags(&flags)))
|
||||
flags = DeviceCommandFlag_Disabled;
|
||||
|
||||
command->Release();
|
||||
|
||||
return (0 == (DeviceCommandFlag_Disabled & flags));
|
||||
}
|
24
Src/Plugins/Library/ml_devices/deviceCommands.h
Normal file
24
Src/Plugins/Library/ml_devices/deviceCommands.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_COMMANDS_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_COMMANDS_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
BOOL
|
||||
DeviceCommands_Register();
|
||||
|
||||
BOOL
|
||||
DeviceCommand_GetSupported(ifc_device *device,
|
||||
const char *name,
|
||||
DeviceCommandContext context,
|
||||
ifc_devicesupportedcommand **commandOut);
|
||||
|
||||
BOOL
|
||||
DeviceCommand_GetEnabled(ifc_device *device,
|
||||
const char *name,
|
||||
DeviceCommandContext context);
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_DEVICE_COMMANDS_HEADER
|
206
Src/Plugins/Library/ml_devices/deviceHandler.cpp
Normal file
206
Src/Plugins/Library/ml_devices/deviceHandler.cpp
Normal file
|
@ -0,0 +1,206 @@
|
|||
#include "main.h"
|
||||
#include "./deviceHandler.h"
|
||||
|
||||
DeviceHandler::DeviceHandler()
|
||||
: ref(1), relayWindow(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceHandler::~DeviceHandler()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT DeviceHandler::CreateInstance(DeviceHandler **instance)
|
||||
{
|
||||
if (NULL == instance)
|
||||
return E_POINTER;
|
||||
|
||||
*instance = new DeviceHandler();
|
||||
|
||||
if (NULL == *instance)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
size_t DeviceHandler::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
size_t DeviceHandler::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int DeviceHandler::QueryInterface(GUID interface_guid, void **object)
|
||||
{
|
||||
if (NULL == object) return E_POINTER;
|
||||
|
||||
if (IsEqualIID(interface_guid, IFC_DeviceEvent))
|
||||
*object = static_cast<ifc_deviceevent*>(this);
|
||||
else
|
||||
{
|
||||
*object = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
if (NULL == *object)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void DeviceHandler::IconChanged(ifc_device *device)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceIconChanged);
|
||||
}
|
||||
|
||||
void DeviceHandler::DisplayNameChanged(ifc_device *device, const wchar_t *displayName)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceDisplayNameChanged);
|
||||
}
|
||||
|
||||
void DeviceHandler::AttachmentChanged(ifc_device *device, BOOL attached)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
{
|
||||
if (FALSE != attached)
|
||||
{
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceAttached);
|
||||
}
|
||||
else
|
||||
{
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceDetached);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandler::VisibilityChanged(ifc_device *device, BOOL visible)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
{
|
||||
if (FALSE == visible)
|
||||
{
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceHidden);
|
||||
}
|
||||
else
|
||||
{
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceShown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandler::TotalSpaceChanged(ifc_device *device, size_t space)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceTotalSpaceChanged);
|
||||
}
|
||||
|
||||
void DeviceHandler::UsedSpaceChanged(ifc_device *device, size_t space)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceUsedSpaceChanged);
|
||||
}
|
||||
|
||||
void DeviceHandler::CommandChanged(ifc_device *device)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceCommandChanged);
|
||||
}
|
||||
|
||||
|
||||
void DeviceHandler::ActivityStarted(ifc_device *device, ifc_deviceactivity *activity)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceActivityStarted);
|
||||
}
|
||||
|
||||
void DeviceHandler::ActivityFinished(ifc_device *device, ifc_deviceactivity *activity)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceActivityFinished);
|
||||
}
|
||||
|
||||
void DeviceHandler::ActivityChanged(ifc_device *device, ifc_deviceactivity *activity)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceActivityChanged);
|
||||
}
|
||||
|
||||
void DeviceHandler::ModelChanged(ifc_device *device, const wchar_t *model)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceModelChanged);
|
||||
}
|
||||
|
||||
void DeviceHandler::StatusChanged(ifc_device *device, const wchar_t *status)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceStatusChanged);
|
||||
}
|
||||
|
||||
HRESULT DeviceHandler::SetRelayWindow(HWND hwnd)
|
||||
{
|
||||
relayWindow = hwnd;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeviceHandler::Advise(ifc_device *device)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == device)
|
||||
return E_INVALIDARG;
|
||||
|
||||
hr = device->Advise(this);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceHandler::Unadvise(ifc_device *device)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == device)
|
||||
return E_INVALIDARG;
|
||||
|
||||
hr = device->Unadvise(this);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceHandler
|
||||
START_DISPATCH;
|
||||
CB(ADDREF, AddRef)
|
||||
CB(RELEASE, Release)
|
||||
CB(QUERYINTERFACE, QueryInterface)
|
||||
VCB(API_ICONCHANGED, IconChanged)
|
||||
VCB(API_DISPLAYNAMECHANGED, DisplayNameChanged)
|
||||
VCB(API_ATTACHMENTCHANGED, AttachmentChanged)
|
||||
VCB(API_VISIBILITYCHANGED, VisibilityChanged)
|
||||
VCB(API_TOTALSPACECHANGED, TotalSpaceChanged)
|
||||
VCB(API_USEDSPACECHANGED, UsedSpaceChanged)
|
||||
VCB(API_COMMANDCHANGED, CommandChanged)
|
||||
VCB(API_ACTIVITYSTARTED, ActivityStarted)
|
||||
VCB(API_ACTIVITYFINISHED, ActivityFinished)
|
||||
VCB(API_ACTIVITYCHANGED, ActivityChanged)
|
||||
VCB(API_MODELCHANGED, ModelChanged)
|
||||
VCB(API_STATUSCHANGED, StatusChanged)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
56
Src/Plugins/Library/ml_devices/deviceHandler.h
Normal file
56
Src/Plugins/Library/ml_devices/deviceHandler.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_HANDLER_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_HANDLER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
#include "../devices/ifc_deviceevent.h"
|
||||
|
||||
class DeviceHandler: public ifc_deviceevent
|
||||
{
|
||||
protected:
|
||||
DeviceHandler();
|
||||
~DeviceHandler();
|
||||
|
||||
public:
|
||||
static HRESULT CreateInstance(DeviceHandler **instance);
|
||||
|
||||
public:
|
||||
/* Dispatchable */
|
||||
size_t AddRef();
|
||||
size_t Release();
|
||||
int QueryInterface(GUID interface_guid, void **object);
|
||||
|
||||
/* ifc_deviceevent */
|
||||
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, size_t space);
|
||||
void UsedSpaceChanged(ifc_device *device, size_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:
|
||||
HRESULT SetRelayWindow(HWND hwnd);
|
||||
HRESULT Advise(ifc_device *device);
|
||||
HRESULT Unadvise(ifc_device *device);
|
||||
|
||||
|
||||
protected:
|
||||
size_t ref;
|
||||
HWND relayWindow;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_DEVICE_HANDLER_HEADER
|
174
Src/Plugins/Library/ml_devices/deviceManagerHandler.cpp
Normal file
174
Src/Plugins/Library/ml_devices/deviceManagerHandler.cpp
Normal file
|
@ -0,0 +1,174 @@
|
|||
#include "main.h"
|
||||
#include "./deviceManagerHandler.h"
|
||||
|
||||
DeviceManagerHandler::DeviceManagerHandler()
|
||||
: ref(1), relayWindow(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceManagerHandler::~DeviceManagerHandler()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT DeviceManagerHandler::CreateInstance(DeviceManagerHandler **instance)
|
||||
{
|
||||
if (NULL == instance)
|
||||
return E_POINTER;
|
||||
|
||||
*instance = new DeviceManagerHandler();
|
||||
|
||||
if (NULL == *instance)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
size_t DeviceManagerHandler::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
size_t DeviceManagerHandler::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int DeviceManagerHandler::QueryInterface(GUID interface_guid, void **object)
|
||||
{
|
||||
if (NULL == object) return E_POINTER;
|
||||
|
||||
if (IsEqualIID(interface_guid, IFC_DeviceManagerEvent))
|
||||
*object = static_cast<ifc_devicemanagerevent*>(this);
|
||||
else
|
||||
{
|
||||
*object = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
if (NULL == *object)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void DeviceManagerHandler::TypeAdded(api_devicemanager *manager, ifc_devicetype *type)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_TYPE(relayWindow, type, Event_TypeRegistered);
|
||||
}
|
||||
|
||||
void DeviceManagerHandler::TypeRemoved(api_devicemanager *manager, ifc_devicetype *type)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_TYPE(relayWindow, type, Event_TypeUnregistered);
|
||||
}
|
||||
|
||||
void DeviceManagerHandler::ConnectionAdded(api_devicemanager *manager, ifc_deviceconnection *connection)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_CONNECTION(relayWindow, connection, Event_ConnectionRegistered);
|
||||
}
|
||||
|
||||
void DeviceManagerHandler::ConnectionRemoved(api_devicemanager *manager, ifc_deviceconnection *connection)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_CONNECTION(relayWindow, connection, Event_ConnectionUnregistered);
|
||||
}
|
||||
|
||||
void DeviceManagerHandler::CommandAdded(api_devicemanager *manager, ifc_devicecommand *command)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_COMMAND(relayWindow, command, Event_CommandRegistered);
|
||||
}
|
||||
|
||||
void DeviceManagerHandler::CommandRemoved(api_devicemanager *manager, ifc_devicecommand *command)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_COMMAND(relayWindow, command, Event_CommandUnregistered);
|
||||
}
|
||||
|
||||
void DeviceManagerHandler::DeviceAdded(api_devicemanager *manager, ifc_device *device)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceAdded);
|
||||
}
|
||||
|
||||
void DeviceManagerHandler::DeviceRemoved(api_devicemanager *manager, ifc_device *device)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DEVICE(relayWindow, device, Event_DeviceRemoved);
|
||||
}
|
||||
|
||||
void DeviceManagerHandler::DiscoveryStarted(api_devicemanager *manager)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DISCOVERY(relayWindow, manager, Event_DiscoveryStarted);
|
||||
}
|
||||
|
||||
void DeviceManagerHandler::DiscoveryFinished(api_devicemanager *manager)
|
||||
{
|
||||
if (NULL != relayWindow)
|
||||
EVENTRELAY_NOTIFY_DISCOVERY(relayWindow, manager, Event_DiscoveryFinished);
|
||||
}
|
||||
|
||||
HRESULT DeviceManagerHandler::SetRelayWindow(HWND hwnd)
|
||||
{
|
||||
relayWindow = hwnd;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeviceManagerHandler::Advise(api_devicemanager *manager)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == manager)
|
||||
return E_INVALIDARG;
|
||||
|
||||
hr = manager->Advise(this);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceManagerHandler::Unadvise(api_devicemanager *manager)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == manager)
|
||||
return E_INVALIDARG;
|
||||
|
||||
hr = manager->Unadvise(this);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
#define CBCLASS DeviceManagerHandler
|
||||
START_DISPATCH;
|
||||
CB(ADDREF, AddRef)
|
||||
CB(RELEASE, Release)
|
||||
CB(QUERYINTERFACE, QueryInterface)
|
||||
VCB(API_TYPEADDED, TypeAdded)
|
||||
VCB(API_TYPEREMOVED, TypeRemoved)
|
||||
VCB(API_CONNECTIONADDED, ConnectionAdded)
|
||||
VCB(API_CONNECTIONREMOVED, ConnectionRemoved)
|
||||
VCB(API_COMMANDADDED, CommandAdded)
|
||||
VCB(API_COMMANDREMOVED, CommandRemoved)
|
||||
VCB(API_DEVICEADDED, DeviceAdded)
|
||||
VCB(API_DEVICEREMOVED, DeviceRemoved)
|
||||
VCB(API_DISCOVERYSTARTED, DiscoveryStarted)
|
||||
VCB(API_DISCOVERYFINISHED, DiscoveryFinished)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
54
Src/Plugins/Library/ml_devices/deviceManagerHandler.h
Normal file
54
Src/Plugins/Library/ml_devices/deviceManagerHandler.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_MANAGER_HANDLER_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_DEVICE_MANAGER_HANDLER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../devices/api_devicemanager.h"
|
||||
//#include <ifc_devicemanagerevent.h>
|
||||
|
||||
class DeviceManagerHandler: public ifc_devicemanagerevent
|
||||
{
|
||||
protected:
|
||||
DeviceManagerHandler();
|
||||
~DeviceManagerHandler();
|
||||
|
||||
public:
|
||||
static HRESULT CreateInstance(DeviceManagerHandler **instance);
|
||||
|
||||
public:
|
||||
/* Dispatchable */
|
||||
size_t AddRef();
|
||||
size_t Release();
|
||||
int QueryInterface(GUID interface_guid, void **object);
|
||||
|
||||
/* ifc_devicemanagerevent */
|
||||
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:
|
||||
HRESULT SetRelayWindow(HWND hwnd);
|
||||
HRESULT Advise(api_devicemanager *manager);
|
||||
HRESULT Unadvise(api_devicemanager *manager);
|
||||
|
||||
|
||||
protected:
|
||||
size_t ref;
|
||||
HWND relayWindow;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_DEVICE_MANAGER_HANDLER_HEADER
|
1240
Src/Plugins/Library/ml_devices/embeddedEditor.cpp
Normal file
1240
Src/Plugins/Library/ml_devices/embeddedEditor.cpp
Normal file
File diff suppressed because it is too large
Load diff
79
Src/Plugins/Library/ml_devices/embeddedEditor.h
Normal file
79
Src/Plugins/Library/ml_devices/embeddedEditor.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_EMBEDED_EDITOR_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_EMBEDED_EDITOR_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
|
||||
typedef void (CALLBACK *EmbeddedEditorFinishCb)(HWND /*editorWindow*/, BOOL /*canceled*/,
|
||||
const wchar_t * /*text*/, void * /*user*/);
|
||||
|
||||
|
||||
BOOL
|
||||
EmbeddedEditor_Attach(HWND hwnd,
|
||||
EmbeddedEditorFinishCb callback,
|
||||
void *user);
|
||||
|
||||
BOOL
|
||||
EmbeddedEditor_AdjustWindowRectEx(RECT *rect,
|
||||
unsigned long styleEx,
|
||||
unsigned long style);
|
||||
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_FIRST (WM_USER + 10)
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_SET_TEXT_COLOR (EMBEDDEDEDITOR_WM_FIRST + 0)
|
||||
#define EMBEDDEDEDITOR_SET_TEXT_COLOR(/*HWND*/ _hwnd, /*COLORREF*/ _color)\
|
||||
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_TEXT_COLOR, 0, (LPARAM)(_color)))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_GET_TEXT_COLOR (EMBEDDEDEDITOR_WM_FIRST + 1)
|
||||
#define EMBEDDEDEDITOR_GET_TEXT_COLOR(/*HWND*/ _hwnd)\
|
||||
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_GET_TEXT_COLOR, 0, 0L))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_SET_BACK_COLOR (EMBEDDEDEDITOR_WM_FIRST + 2)
|
||||
#define EMBEDDEDEDITOR_SET_BACK_COLOR(/*HWND*/ _hwnd, /*COLORREF*/ _color)\
|
||||
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_BACK_COLOR, 0, (LPARAM)(_color)))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_GET_BACK_COLOR (EMBEDDEDEDITOR_WM_FIRST + 3)
|
||||
#define EMBEDDEDEDITOR_GET_BACK_COLOR(/*HWND*/ _hwnd)\
|
||||
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_GET_BACK_COLOR, 0, 0L))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_SET_BORDER_COLOR (EMBEDDEDEDITOR_WM_FIRST + 4)
|
||||
#define EMBEDDEDEDITOR_SET_BORDER_COLOR(/*HWND*/ _hwnd, /*COLORREF*/ _color)\
|
||||
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_BORDER_COLOR, 0, (LPARAM)(_color)))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_GET_BORDER_COLOR (EMBEDDEDEDITOR_WM_FIRST + 5)
|
||||
#define EMBEDDEDEDITOR_GET_BORDER_COLOR(/*HWND*/ _hwnd)\
|
||||
((COLORREF)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_GET_BORDER_COLOR, 0, 0L))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_SET_USER_DATA (EMBEDDEDEDITOR_WM_FIRST + 6)
|
||||
#define EMBEDDEDEDITOR_SET_USER_DATA(/*HWND*/ _hwnd, /*void* */ _user)\
|
||||
((void*)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_USER_DATA, 0, (LPARAM)(_user)))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_GET_USER_DATA (EMBEDDEDEDITOR_WM_FIRST + 7)
|
||||
#define EMBEDDEDEDITOR_GET_USER_DATA(/*HWND*/ _hwnd)\
|
||||
((void*)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_GET_USER_DATA, 0, 0L))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_SET_ANCHOR_POINT (EMBEDDEDEDITOR_WM_FIRST + 8)
|
||||
#define EMBEDDEDEDITOR_SET_ANCHOR_POINT(/*HWND*/ _hwnd, /*long*/ _x, /*long*/ _y)\
|
||||
((BOOL)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_ANCHOR_POINT, (WPARAM)(_x), (LPARAM)(_y)))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_GET_ANCHOR_POINT (EMBEDDEDEDITOR_WM_FIRST + 9)
|
||||
#define EMBEDDEDEDITOR_GET_ANCHOR_POINT(/*HWND*/ _hwnd, /*long* */ _x, /*long* */ _y)\
|
||||
((BOOL)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_GET_ANCHOR_POINT, (WPARAM)(_x), (LPARAM)(_y)))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_SET_MAX_SIZE (EMBEDDEDEDITOR_WM_FIRST + 10)
|
||||
#define EMBEDDEDEDITOR_SET_MAX_SIZE(/*HWND*/ _hwnd, /*long*/ _width, /*long*/ _height)\
|
||||
((BOOL)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_SET_MAX_SIZE, (WPARAM)(_width), (LPARAM)(_height)))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_GET_MAX_SIZE (EMBEDDEDEDITOR_WM_FIRST + 11)
|
||||
#define EMBEDDEDEDITOR_GET_MAX_SIZE(/*HWND*/ _hwnd, /*long* */ _width, /*long* */ _height)\
|
||||
((BOOL)SendMessageW((_hwnd), EMBEDDEDEDITOR_GET_MAX_SIZE, (WPARAM)(_width), (LPARAM)(_height)))
|
||||
|
||||
#define EMBEDDEDEDITOR_WM_END_EDITING (EMBEDDEDEDITOR_WM_FIRST + 12)
|
||||
#define EMBEDDEDEDITOR_END_EDITING(/*HWND*/ _hwnd, /*BOOL*/ _cancel)\
|
||||
((BOOL)SendMessageW((_hwnd), EMBEDDEDEDITOR_WM_END_EDITING, (WPARAM)(_cancel), 0L))
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_EMBEDED_EDITOR_HEADER
|
465
Src/Plugins/Library/ml_devices/eventRelay.cpp
Normal file
465
Src/Plugins/Library/ml_devices/eventRelay.cpp
Normal file
|
@ -0,0 +1,465 @@
|
|||
#include "main.h"
|
||||
#include "./eventRelay.h"
|
||||
#include <vector>
|
||||
|
||||
#define EVENT_RELAY_WINDOW_CLASS L"NullsoftEventRelay"
|
||||
|
||||
typedef struct EventHandler
|
||||
{
|
||||
size_t cookie;
|
||||
DeviceEventCallbacks callbacks;
|
||||
void *user;
|
||||
} EventHandler;
|
||||
|
||||
typedef std::vector<EventHandler*> EventHandlerList;
|
||||
|
||||
typedef struct EventRelay
|
||||
{
|
||||
EventHandlerList handlerList;
|
||||
DeviceManagerHandler *managerHandler;
|
||||
DeviceHandler *deviceHandler;
|
||||
} EventRelay;
|
||||
|
||||
#define EVENTRELAY(_hwnd) ((EventRelay*)(LONGX86)GetWindowLongPtrW((_hwnd), 0))
|
||||
#define EVENTRELAY_RET_VOID(_self, _hwnd) {(_self) = EVENTRELAY((_hwnd)); if (NULL == (_self)) return;}
|
||||
#define EVENTRELAY_RET_VAL(_self, _hwnd, _error) {(_self) = EVENTRELAY((_hwnd)); if (NULL == (_self)) return (_error);}
|
||||
|
||||
|
||||
static LRESULT CALLBACK
|
||||
EventRelay_WindowProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
|
||||
static ATOM
|
||||
EventRelay_GetClassAtom(HINSTANCE instance)
|
||||
{
|
||||
WNDCLASSEXW klass;
|
||||
ATOM klassAtom;
|
||||
|
||||
klassAtom = (ATOM)GetClassInfoExW(instance, EVENT_RELAY_WINDOW_CLASS, &klass);
|
||||
if (0 != klassAtom)
|
||||
return klassAtom;
|
||||
|
||||
memset(&klass, 0, sizeof(klass));
|
||||
klass.cbSize = sizeof(klass);
|
||||
klass.style = 0;
|
||||
klass.lpfnWndProc = EventRelay_WindowProc;
|
||||
klass.cbClsExtra = 0;
|
||||
klass.cbWndExtra = sizeof(EventRelay*);
|
||||
klass.hInstance = instance;
|
||||
klass.hIcon = NULL;
|
||||
klass.hCursor = NULL;
|
||||
klass.hbrBackground = NULL;
|
||||
klass.lpszMenuName = NULL;
|
||||
klass.lpszClassName = EVENT_RELAY_WINDOW_CLASS;
|
||||
klass.hIconSm = NULL;
|
||||
klassAtom = RegisterClassExW(&klass);
|
||||
|
||||
return klassAtom;
|
||||
}
|
||||
|
||||
HWND
|
||||
EventRelay_CreateWindow()
|
||||
{
|
||||
HINSTANCE instance;
|
||||
ATOM klassAtom;
|
||||
HWND hwnd;
|
||||
|
||||
instance = GetModuleHandleW(NULL);
|
||||
klassAtom = EventRelay_GetClassAtom(instance);
|
||||
if (0 == klassAtom)
|
||||
return NULL;
|
||||
|
||||
hwnd = CreateWindowEx(WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY,
|
||||
MAKEINTATOM(klassAtom),
|
||||
NULL,
|
||||
WS_OVERLAPPED,
|
||||
0, 0, 0, 0,
|
||||
HWND_MESSAGE,
|
||||
NULL,
|
||||
instance,
|
||||
NULL);
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
EventRelay_GenerateCookie(EventRelay *self)
|
||||
{
|
||||
size_t cookie;
|
||||
EventHandler *handler;
|
||||
|
||||
|
||||
if (NULL == self)
|
||||
return 0;
|
||||
|
||||
cookie = self->handlerList.size() + 1;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
size_t index = self->handlerList.size();
|
||||
while(index--)
|
||||
{
|
||||
handler = self->handlerList[index];
|
||||
if (cookie == handler->cookie)
|
||||
{
|
||||
cookie++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (((size_t)-1) == index)
|
||||
return cookie;
|
||||
}
|
||||
|
||||
return cookie;
|
||||
}
|
||||
|
||||
static EventHandler *
|
||||
EventRelay_CreateEventHandler(EventRelay *self, DeviceEventCallbacks *callbacks, void *user)
|
||||
{
|
||||
EventHandler *handler;
|
||||
size_t cookie;
|
||||
|
||||
if (NULL == self || NULL == callbacks)
|
||||
return NULL;
|
||||
|
||||
cookie = EventRelay_GenerateCookie(self);
|
||||
if (0 == cookie)
|
||||
return NULL;
|
||||
|
||||
handler = (EventHandler*)malloc(sizeof(EventHandler));
|
||||
if (NULL == handler)
|
||||
return NULL;
|
||||
|
||||
handler->user = user;
|
||||
handler->cookie = cookie;
|
||||
handler->callbacks.deviceCb = callbacks->deviceCb;
|
||||
handler->callbacks.typeCb = callbacks->typeCb;
|
||||
handler->callbacks.connectionCb = callbacks->connectionCb;
|
||||
handler->callbacks.commandCb = callbacks->commandCb;
|
||||
handler->callbacks.discoveryCb = callbacks->discoveryCb;
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
static void
|
||||
EventRelay_DestroyEventHandler(EventHandler *handler)
|
||||
{
|
||||
if (NULL == handler)
|
||||
return;
|
||||
|
||||
free(handler);
|
||||
}
|
||||
|
||||
static LRESULT
|
||||
EventRelay_OnCreate(HWND hwnd, CREATESTRUCT *createStruct)
|
||||
{
|
||||
EventRelay *self;
|
||||
ifc_deviceobjectenum *enumerator;
|
||||
ifc_deviceobject *object;
|
||||
ifc_device *device;
|
||||
|
||||
if (NULL == WASABI_API_DEVICES)
|
||||
return -1;
|
||||
|
||||
self = new EventRelay();
|
||||
if (NULL == self)
|
||||
return -1;
|
||||
|
||||
self->deviceHandler = NULL;
|
||||
self->managerHandler = NULL;
|
||||
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
if (!SetWindowLongPtr(hwnd, 0, (LONGX86)self) && ERROR_SUCCESS != GetLastError())
|
||||
return -1;
|
||||
|
||||
if (FAILED(DeviceHandler::CreateInstance(&self->deviceHandler)))
|
||||
return -1;
|
||||
|
||||
self->deviceHandler->SetRelayWindow(hwnd);
|
||||
|
||||
if (SUCCEEDED(WASABI_API_DEVICES->DeviceEnumerate(&enumerator)))
|
||||
{
|
||||
while(S_OK == enumerator->Next(&object, 1, NULL))
|
||||
{
|
||||
if (SUCCEEDED(object->QueryInterface(IFC_Device, (void**)&device)))
|
||||
{
|
||||
self->deviceHandler->Advise(device);
|
||||
device->Release();
|
||||
}
|
||||
object->Release();
|
||||
}
|
||||
enumerator->Release();
|
||||
}
|
||||
|
||||
if (FAILED(DeviceManagerHandler::CreateInstance(&self->managerHandler)))
|
||||
return -1;
|
||||
|
||||
self->managerHandler->SetRelayWindow(hwnd);
|
||||
if (FAILED(self->managerHandler->Advise(WASABI_API_DEVICES)))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
EventRelay_OnDestroy(HWND hwnd)
|
||||
{
|
||||
EventRelay *self;
|
||||
MSG msg;
|
||||
|
||||
self = EVENTRELAY(hwnd);
|
||||
SetWindowLongPtr(hwnd, 0, 0);
|
||||
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
size_t index = self->handlerList.size();
|
||||
while(index--)
|
||||
{
|
||||
EventHandler *handler = self->handlerList[index];
|
||||
EventRelay_DestroyEventHandler(handler);
|
||||
}
|
||||
|
||||
if (NULL != self->managerHandler)
|
||||
{
|
||||
self->managerHandler->SetRelayWindow(NULL);
|
||||
|
||||
if (NULL != WASABI_API_DEVICES)
|
||||
self->managerHandler->Unadvise(WASABI_API_DEVICES);
|
||||
|
||||
self->managerHandler->Release();
|
||||
}
|
||||
|
||||
if (NULL != self->deviceHandler)
|
||||
{
|
||||
self->deviceHandler->SetRelayWindow(NULL);
|
||||
|
||||
if (NULL != WASABI_API_DEVICES)
|
||||
{
|
||||
ifc_deviceobjectenum *enumerator;
|
||||
ifc_deviceobject *object;
|
||||
ifc_device *device;
|
||||
|
||||
if (SUCCEEDED(WASABI_API_DEVICES->DeviceEnumerate(&enumerator)))
|
||||
{
|
||||
while(S_OK == enumerator->Next(&object, 1, NULL))
|
||||
{
|
||||
if (SUCCEEDED(object->QueryInterface(IFC_Device, (void**)&device)))
|
||||
{
|
||||
self->deviceHandler->Unadvise(device);
|
||||
device->Release();
|
||||
}
|
||||
object->Release();
|
||||
}
|
||||
enumerator->Release();
|
||||
}
|
||||
}
|
||||
|
||||
self->deviceHandler->Release();
|
||||
}
|
||||
|
||||
delete self;
|
||||
|
||||
// finish pumping messages
|
||||
while(FALSE != PeekMessage(&msg, hwnd, EVENTRELAY_WM_FIRST, EVENTRELAY_WM_LAST, PM_REMOVE))
|
||||
{
|
||||
EventRelay_WindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT
|
||||
EventRelay_OnRegisterHandler(HWND hwnd, DeviceEventCallbacks *callbacks, void *user)
|
||||
{
|
||||
EventRelay *self;
|
||||
EventHandler *handler;
|
||||
|
||||
EVENTRELAY_RET_VAL(self, hwnd, 0);
|
||||
|
||||
handler = EventRelay_CreateEventHandler(self, callbacks, user);
|
||||
if(NULL == handler)
|
||||
return 0;
|
||||
|
||||
self->handlerList.push_back(handler);
|
||||
return (LRESULT)handler->cookie;
|
||||
}
|
||||
|
||||
static LRESULT
|
||||
EventRelay_OnUnregisterHandler(HWND hwnd, size_t cookie)
|
||||
{
|
||||
EventRelay *self;
|
||||
|
||||
EVENTRELAY_RET_VAL(self, hwnd, FALSE);
|
||||
|
||||
size_t index = self->handlerList.size();
|
||||
while(index--)
|
||||
{
|
||||
EventHandler *handler = self->handlerList[index];
|
||||
if (handler->cookie == cookie)
|
||||
{
|
||||
self->handlerList.erase(self->handlerList.begin() + index);
|
||||
EventRelay_DestroyEventHandler(handler);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
EventRelay_OnNotifyDevice(HWND hwnd, ifc_device *device, DeviceEvent eventId)
|
||||
{
|
||||
ReplyMessage(0);
|
||||
|
||||
if (NULL != device)
|
||||
{
|
||||
EventRelay *self;
|
||||
self = EVENTRELAY(hwnd);
|
||||
|
||||
if (NULL != self)
|
||||
{
|
||||
switch(eventId)
|
||||
{
|
||||
case Event_DeviceAdded:
|
||||
if (NULL != self->deviceHandler)
|
||||
self->deviceHandler->Advise(device);
|
||||
break;
|
||||
|
||||
case Event_DeviceRemoved:
|
||||
if (NULL != self->deviceHandler)
|
||||
self->deviceHandler->Unadvise(device);
|
||||
break;
|
||||
}
|
||||
|
||||
size_t index = self->handlerList.size();
|
||||
while(index--)
|
||||
{
|
||||
EventHandler *handler = self->handlerList[index];
|
||||
if (NULL != handler->callbacks.deviceCb)
|
||||
handler->callbacks.deviceCb(device, eventId, handler->user);
|
||||
}
|
||||
}
|
||||
|
||||
device->Release();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
EventRelay_OnNotifyDiscovery(HWND hwnd, api_devicemanager *manager, DeviceDiscoveryEvent eventId)
|
||||
{
|
||||
ReplyMessage(0);
|
||||
|
||||
if (NULL != manager)
|
||||
{
|
||||
EventRelay *self;
|
||||
self = EVENTRELAY(hwnd);
|
||||
|
||||
if (NULL != self)
|
||||
{
|
||||
size_t index = self->handlerList.size();
|
||||
while(index--)
|
||||
{
|
||||
EventHandler *handler = self->handlerList[index];
|
||||
if (NULL != handler->callbacks.discoveryCb)
|
||||
handler->callbacks.discoveryCb(manager, eventId, handler->user);
|
||||
}
|
||||
}
|
||||
|
||||
manager->Release();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
EventRelay_OnNotifyType(HWND hwnd, ifc_devicetype *type, DeviceTypeEvent eventId)
|
||||
{
|
||||
ReplyMessage(0);
|
||||
|
||||
if (NULL != type)
|
||||
{
|
||||
EventRelay *self;
|
||||
self = EVENTRELAY(hwnd);
|
||||
|
||||
if (NULL != self)
|
||||
{
|
||||
size_t index = self->handlerList.size();
|
||||
while(index--)
|
||||
{
|
||||
EventHandler *handler = self->handlerList[index];
|
||||
if (NULL != handler->callbacks.typeCb)
|
||||
handler->callbacks.typeCb(type, eventId, handler->user);
|
||||
}
|
||||
}
|
||||
|
||||
type->Release();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
EventRelay_OnNotifyConnection(HWND hwnd, ifc_deviceconnection *connection, DeviceConnectionEvent eventId)
|
||||
{
|
||||
ReplyMessage(0);
|
||||
|
||||
if (NULL != connection)
|
||||
{
|
||||
EventRelay *self;
|
||||
self = EVENTRELAY(hwnd);
|
||||
|
||||
if (NULL != self)
|
||||
{
|
||||
size_t index = self->handlerList.size();
|
||||
while(index--)
|
||||
{
|
||||
EventHandler *handler = self->handlerList[index];
|
||||
if (NULL != handler->callbacks.connectionCb)
|
||||
handler->callbacks.connectionCb(connection, eventId, handler->user);
|
||||
}
|
||||
}
|
||||
|
||||
connection->Release();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
EventRelay_OnNotifyCommand(HWND hwnd, ifc_devicecommand *command, DeviceCommandEvent eventId)
|
||||
{
|
||||
ReplyMessage(0);
|
||||
|
||||
if (NULL != command)
|
||||
{
|
||||
EventRelay *self;
|
||||
self = EVENTRELAY(hwnd);
|
||||
|
||||
if (NULL != self)
|
||||
{
|
||||
size_t index = self->handlerList.size();
|
||||
while(index--)
|
||||
{
|
||||
EventHandler *handler = self->handlerList[index];
|
||||
if (NULL != handler->callbacks.commandCb)
|
||||
handler->callbacks.commandCb(command, eventId, handler->user);
|
||||
}
|
||||
}
|
||||
|
||||
command->Release();
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
EventRelay_WindowProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_CREATE: return EventRelay_OnCreate(hwnd, (CREATESTRUCT*)lParam);
|
||||
case WM_DESTROY: EventRelay_OnDestroy(hwnd); return 0;
|
||||
|
||||
case EVENTRELAY_WM_REGISTER_HANDLER: return EventRelay_OnRegisterHandler(hwnd, (DeviceEventCallbacks*)lParam, (void*)wParam);
|
||||
case EVENTRELAY_WM_UNREGISTER_HANDLER: return EventRelay_OnUnregisterHandler(hwnd, (size_t)lParam);
|
||||
case EVENTRELAY_WM_NOTIFY_DEVICE: EventRelay_OnNotifyDevice(hwnd, (ifc_device*)lParam, (DeviceEvent)wParam); return 0;
|
||||
case EVENTRELAY_WM_NOTIFY_DISCOVERY: EventRelay_OnNotifyDiscovery(hwnd, (api_devicemanager*)lParam, (DeviceDiscoveryEvent)wParam); return 0;
|
||||
case EVENTRELAY_WM_NOTIFY_TYPE: EventRelay_OnNotifyType(hwnd, (ifc_devicetype*)lParam, (DeviceTypeEvent)wParam); return 0;
|
||||
case EVENTRELAY_WM_NOTIFY_CONNECTION: EventRelay_OnNotifyConnection(hwnd, (ifc_deviceconnection*)lParam, (DeviceConnectionEvent)wParam); return 0;
|
||||
case EVENTRELAY_WM_NOTIFY_COMMAND: EventRelay_OnNotifyCommand(hwnd, (ifc_devicecommand*)lParam, (DeviceCommandEvent)wParam); return 0;
|
||||
}
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
116
Src/Plugins/Library/ml_devices/eventRelay.h
Normal file
116
Src/Plugins/Library/ml_devices/eventRelay.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_EVENT_RELAY_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_EVENT_RELAY_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
typedef enum DeviceEvent
|
||||
{
|
||||
Event_DeviceAdded = 1,
|
||||
Event_DeviceRemoved = 2,
|
||||
Event_DeviceIconChanged = 3,
|
||||
Event_DeviceDisplayNameChanged = 4,
|
||||
Event_DeviceAttached = 5,
|
||||
Event_DeviceDetached = 6,
|
||||
Event_DeviceHidden = 7,
|
||||
Event_DeviceShown = 8,
|
||||
Event_DeviceTotalSpaceChanged = 9,
|
||||
Event_DeviceUsedSpaceChanged = 10,
|
||||
Event_DeviceCommandChanged = 11,
|
||||
Event_DeviceActivityStarted = 12,
|
||||
Event_DeviceActivityFinished = 13,
|
||||
Event_DeviceActivityChanged = 14,
|
||||
Event_DeviceModelChanged = 15,
|
||||
Event_DeviceStatusChanged = 16,
|
||||
} DeviceEvent;
|
||||
|
||||
typedef enum DeviceTypeEvent
|
||||
{
|
||||
Event_TypeRegistered = 1,
|
||||
Event_TypeUnregistered = 2,
|
||||
} DeviceTypeEvent;
|
||||
|
||||
typedef enum DeviceConnectionEvent
|
||||
{
|
||||
Event_ConnectionRegistered = 1,
|
||||
Event_ConnectionUnregistered = 2,
|
||||
} DeviceConnectionEvent;
|
||||
|
||||
typedef enum DeviceCommandEvent
|
||||
{
|
||||
Event_CommandRegistered = 1,
|
||||
Event_CommandUnregistered = 2,
|
||||
} DeviceCommandEvent;
|
||||
|
||||
typedef enum DeviceDiscoveryEvent
|
||||
{
|
||||
Event_DiscoveryStarted = 1,
|
||||
Event_DiscoveryFinished = 2,
|
||||
} DeviceDiscoveryEvent;
|
||||
|
||||
typedef void (*DeviceEventCb)(ifc_device *device, DeviceEvent eventId, void *user);
|
||||
typedef void (*DeviceTypeEventCb)(ifc_devicetype *type, DeviceTypeEvent eventId, void *user);
|
||||
typedef void (*DeviceConnectionEventCb)(ifc_deviceconnection *connection, DeviceConnectionEvent eventId, void *user);
|
||||
typedef void (*DeviceCommandEventCb)(ifc_devicecommand *command, DeviceCommandEvent eventId, void *user);
|
||||
typedef void (*DeviceDiscoveryEventCb)(api_devicemanager *manager, DeviceDiscoveryEvent eventId, void *user);
|
||||
|
||||
typedef struct DeviceEventCallbacks
|
||||
{
|
||||
DeviceEventCb deviceCb;
|
||||
DeviceTypeEventCb typeCb;
|
||||
DeviceConnectionEventCb connectionCb;
|
||||
DeviceCommandEventCb commandCb;
|
||||
DeviceDiscoveryEventCb discoveryCb;
|
||||
} DeviceEventCallbacks;
|
||||
|
||||
HWND
|
||||
EventRelay_CreateWindow();
|
||||
|
||||
|
||||
#define EVENTRELAY_WM_FIRST (WM_USER + 10)
|
||||
|
||||
#define EVENTRELAY_WM_REGISTER_HANDLER (EVENTRELAY_WM_FIRST + 0)
|
||||
#define EVENTRELAY_REGISTER_HANDLER(/*HWND*/ _hwnd, /*DeviceEventCallbacks*/ _handler, /*void* */ _user)\
|
||||
((size_t)SendMessageW((_hwnd), EVENTRELAY_WM_REGISTER_HANDLER, (WPARAM)(_user), (LPARAM)(_handler)))
|
||||
|
||||
#define EVENTRELAY_WM_UNREGISTER_HANDLER (EVENTRELAY_WM_FIRST + 1)
|
||||
#define EVENTRELAY_UNREGISTER_HANDLER(/*HWND*/ _hwnd, /*size_t*/ _handlerCookie)\
|
||||
((BOOL)SendMessageW((_hwnd), EVENTRELAY_WM_UNREGISTER_HANDLER, 0, (LPARAM)(_handlerCookie)))
|
||||
|
||||
|
||||
#define EVENTRELAY_WM_NOTIFY_DEVICE (EVENTRELAY_WM_FIRST + 2)
|
||||
#define EVENTRELAY_NOTIFY_DEVICE(/*HWND*/ _hwnd, /*ifc_device* */ _device, /*DeviceEvent*/ _eventId)\
|
||||
{ ifc_device *_d = (_device); if (NULL != _d && NULL != (_hwnd)) { _d->AddRef(); \
|
||||
if (FALSE == ((BOOL)PostMessageW((_hwnd), EVENTRELAY_WM_NOTIFY_DEVICE,\
|
||||
(WPARAM)(_eventId), (LPARAM)(_d)))) { _d->Release(); }}}
|
||||
|
||||
#define EVENTRELAY_WM_NOTIFY_DISCOVERY (EVENTRELAY_WM_FIRST + 3)
|
||||
#define EVENTRELAY_NOTIFY_DISCOVERY(/*HWND*/ _hwnd, /*api_devicemanager* */ _manager, /*DeviceDiscoveryEvent*/ _eventId)\
|
||||
{ api_devicemanager *_m = (_manager); if (NULL != _m && NULL != (_hwnd)) { _m->AddRef(); \
|
||||
if (FALSE == ((BOOL)PostMessageW((_hwnd), EVENTRELAY_WM_NOTIFY_DISCOVERY,\
|
||||
(WPARAM)(_eventId), (LPARAM)(_m)))) { _m->Release(); }}}
|
||||
|
||||
#define EVENTRELAY_WM_NOTIFY_TYPE (EVENTRELAY_WM_FIRST + 4)
|
||||
#define EVENTRELAY_NOTIFY_TYPE(/*HWND*/ _hwnd, /*ifc_devicetype* */ _type, /*DeviceTypeEvent*/ _eventId)\
|
||||
{ ifc_devicetype *_t = (_type); if (NULL != _t && NULL != (_hwnd)) { _t->AddRef(); \
|
||||
if (FALSE == ((BOOL)PostMessageW((_hwnd), EVENTRELAY_WM_NOTIFY_TYPE,\
|
||||
(WPARAM)(_eventId), (LPARAM)(_t)))) { _t->Release(); }}}
|
||||
|
||||
#define EVENTRELAY_WM_NOTIFY_CONNECTION (EVENTRELAY_WM_FIRST + 5)
|
||||
#define EVENTRELAY_NOTIFY_CONNECTION(/*HWND*/ _hwnd, /*ifc_deviceconnection* */ _connection, /*DeviceConnectionEvent*/ _eventId)\
|
||||
{ ifc_deviceconnection *_c = (_connection); if (NULL != _c && NULL != (_hwnd)) { _c->AddRef(); \
|
||||
if (FALSE == ((BOOL)PostMessageW((_hwnd), EVENTRELAY_WM_NOTIFY_CONNECTION,\
|
||||
(WPARAM)(_eventId), (LPARAM)(_c)))) { _c->Release(); }}}
|
||||
|
||||
#define EVENTRELAY_WM_NOTIFY_COMMAND (EVENTRELAY_WM_FIRST + 6)
|
||||
#define EVENTRELAY_NOTIFY_COMMAND(/*HWND*/ _hwnd, /*ifc_devicecommand* */ _command, /*DeviceCommandEvent*/ _eventId)\
|
||||
{ ifc_devicecommand *_c = (_command); if (NULL != _c && NULL != (_hwnd)) { _c->AddRef(); \
|
||||
if (FALSE == ((BOOL)PostMessageW((_hwnd), EVENTRELAY_WM_NOTIFY_COMMAND,\
|
||||
(WPARAM)(_eventId), (LPARAM)(_c)))) { _c->Release(); }}}
|
||||
|
||||
#define EVENTRELAY_WM_LAST EVENTRELAY_WM_NOTIFY_COMMAND
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_EVENT_RELAY_HEADER
|
134
Src/Plugins/Library/ml_devices/fillRegion.cpp
Normal file
134
Src/Plugins/Library/ml_devices/fillRegion.cpp
Normal file
|
@ -0,0 +1,134 @@
|
|||
#include "main.h"
|
||||
#include "./fillRegion.h"
|
||||
|
||||
static BOOL
|
||||
FillRegion_TempRegionFromRect(FillRegion *region, const RECT *rect)
|
||||
{
|
||||
if (NULL == region || NULL == rect)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == region->tmp)
|
||||
{
|
||||
region->tmp = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom);
|
||||
if (NULL == region->tmp)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FALSE == SetRectRgn(region->tmp, rect->left, rect->top, rect->right, rect->bottom))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FillRegion_Init(FillRegion *region, const RECT *rect)
|
||||
{
|
||||
if (NULL == region)
|
||||
return FALSE;
|
||||
|
||||
region->fill = (NULL != rect) ?
|
||||
CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom) :
|
||||
NULL;
|
||||
|
||||
region->tmp = NULL;
|
||||
|
||||
if (NULL == region->fill)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
FillRegion_Uninit(FillRegion *region)
|
||||
{
|
||||
if (NULL != region)
|
||||
{
|
||||
if (NULL != region->fill)
|
||||
{
|
||||
DeleteObject(region->fill);
|
||||
region->fill = NULL;
|
||||
}
|
||||
|
||||
if (NULL != region->tmp)
|
||||
{
|
||||
DeleteObject(region->tmp);
|
||||
region->tmp = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
FillRegion_ExcludeRect(FillRegion *region, const RECT *rect)
|
||||
{
|
||||
if (NULL == region || NULL == rect)
|
||||
return FALSE;
|
||||
|
||||
return (FALSE != FillRegion_TempRegionFromRect(region, rect) &&
|
||||
ERROR != CombineRgn(region->fill, region->fill, region->tmp, RGN_DIFF));
|
||||
}
|
||||
|
||||
BOOL
|
||||
FillRegion_ExcludeRgn(FillRegion *region, HRGN rgn)
|
||||
{
|
||||
if (NULL == region || NULL == rgn)
|
||||
return FALSE;
|
||||
|
||||
return (ERROR != CombineRgn(region->fill, region->fill, rgn, RGN_DIFF));
|
||||
}
|
||||
|
||||
BOOL
|
||||
FillRegion_AppendRect(FillRegion *region, const RECT *rect)
|
||||
{
|
||||
if (NULL == region || NULL == rect)
|
||||
return FALSE;
|
||||
|
||||
return (FALSE != FillRegion_TempRegionFromRect(region, rect) &&
|
||||
ERROR != CombineRgn(region->fill, region->fill, region->tmp, RGN_OR));
|
||||
}
|
||||
|
||||
BOOL
|
||||
FillRegion_AppendRgn(FillRegion *region, HRGN rgn)
|
||||
{
|
||||
if (NULL == region || NULL == rgn)
|
||||
return FALSE;
|
||||
|
||||
return (ERROR != CombineRgn(region->fill, region->fill, rgn, RGN_OR));
|
||||
}
|
||||
|
||||
BOOL
|
||||
FillRegion_BrushFill(FillRegion *region, HDC hdc, HBRUSH brush)
|
||||
{
|
||||
if (NULL == region)
|
||||
return FALSE;
|
||||
|
||||
return FillRgn(hdc, region->fill, brush);
|
||||
}
|
||||
|
||||
BOOL
|
||||
FillRegion_Offset(FillRegion *region, long x, long y)
|
||||
{
|
||||
if (NULL == region)
|
||||
return FALSE;
|
||||
|
||||
return (ERROR != OffsetRgn(region->fill, x, y));
|
||||
}
|
||||
|
||||
BOOL
|
||||
FillRegion_SetRect(FillRegion *region, const RECT *rect)
|
||||
{
|
||||
if (NULL == region || NULL == rect)
|
||||
return FALSE;
|
||||
|
||||
return SetRectRgn(region->fill, rect->left, rect->top, rect->right, rect->bottom);
|
||||
}
|
||||
|
||||
BOOL
|
||||
FillRegion_SetEmpty(FillRegion *region)
|
||||
{
|
||||
if (NULL == region)
|
||||
return FALSE;
|
||||
|
||||
return SetRectRgn(region->fill, 0, 0, 0, 0);
|
||||
}
|
51
Src/Plugins/Library/ml_devices/fillRegion.h
Normal file
51
Src/Plugins/Library/ml_devices/fillRegion.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_FILL_REGION_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_FILL_REGION_HEADER
|
||||
|
||||
|
||||
typedef struct FillRegion
|
||||
{
|
||||
HRGN fill;
|
||||
HRGN tmp;
|
||||
} FillRegion;
|
||||
|
||||
BOOL
|
||||
FillRegion_Init(FillRegion *region,
|
||||
const RECT *rect);
|
||||
|
||||
void
|
||||
FillRegion_Uninit(FillRegion *region);
|
||||
|
||||
BOOL
|
||||
FillRegion_ExcludeRect(FillRegion *region,
|
||||
const RECT *rect);
|
||||
|
||||
BOOL
|
||||
FillRegion_ExcludeRgn(FillRegion *region,
|
||||
HRGN rgn);
|
||||
|
||||
BOOL
|
||||
FillRegion_AppendRect(FillRegion *region,
|
||||
const RECT *rect);
|
||||
|
||||
BOOL
|
||||
FillRegion_AppendRgn(FillRegion *region,
|
||||
HRGN rgn);
|
||||
|
||||
BOOL
|
||||
FillRegion_BrushFill(FillRegion *region,
|
||||
HDC hdc,
|
||||
HBRUSH brush);
|
||||
|
||||
BOOL
|
||||
FillRegion_Offset(FillRegion *region,
|
||||
long x,
|
||||
long y);
|
||||
|
||||
BOOL
|
||||
FillRegion_SetRect(FillRegion *region,
|
||||
const RECT *rect);
|
||||
|
||||
BOOL
|
||||
FillRegion_SetEmpty(FillRegion *region);
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_FILL_REGION_HEADER
|
76
Src/Plugins/Library/ml_devices/gen_deviceprovider/common.h
Normal file
76
Src/Plugins/Library/ml_devices/gen_deviceprovider/common.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_COMMON_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_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_GEN_DEVICE_PROVIDER_COMMON_HEADER
|
871
Src/Plugins/Library/ml_devices/gen_deviceprovider/device.cpp
Normal file
871
Src/Plugins/Library/ml_devices/gen_deviceprovider/device.cpp
Normal file
|
@ -0,0 +1,871 @@
|
|||
#include "main.h"
|
||||
#include "./device.h"
|
||||
|
||||
#include <strsafe.h>
|
||||
|
||||
Device::Device()
|
||||
: ref(1), name(NULL), type(NULL), connection(NULL), displayName(NULL),
|
||||
totalSpace(0), usedSpace(0), attached(FALSE), hidden(FALSE),
|
||||
connected(FALSE), activity(NULL), model(NULL), status(NULL)
|
||||
{
|
||||
|
||||
InitializeCriticalSection(&lock);
|
||||
|
||||
if (NULL == WASABI_API_DEVICES ||
|
||||
FAILED(WASABI_API_DEVICES->CreateDeviceEventManager(&eventManager)))
|
||||
{
|
||||
eventManager = NULL;
|
||||
}
|
||||
|
||||
if (NULL == WASABI_API_DEVICES ||
|
||||
FAILED(WASABI_API_DEVICES->CreateIconStore(&iconStore)))
|
||||
{
|
||||
iconStore = NULL;
|
||||
}
|
||||
|
||||
if (NULL == WASABI_API_DEVICES ||
|
||||
FAILED(WASABI_API_DEVICES->CreateSupportedCommandStore(&commands)))
|
||||
{
|
||||
commands = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
DeviceActivity *activityCopy;
|
||||
|
||||
Lock();
|
||||
|
||||
if (NULL != activity)
|
||||
{
|
||||
activity->SetUser(NULL);
|
||||
activityCopy = activity;
|
||||
activityCopy->AddRef();
|
||||
}
|
||||
else
|
||||
activityCopy = NULL;
|
||||
|
||||
AnsiString_Free(name);
|
||||
AnsiString_Free(type);
|
||||
AnsiString_Free(connection);
|
||||
String_Free(displayName);
|
||||
String_Free(model);
|
||||
String_Free(status);
|
||||
|
||||
if (NULL != commands)
|
||||
commands->Release();
|
||||
|
||||
if (NULL != iconStore)
|
||||
iconStore->Release();
|
||||
|
||||
if (NULL != eventManager)
|
||||
eventManager->Release();
|
||||
|
||||
Unlock();
|
||||
|
||||
if (NULL != activityCopy)
|
||||
{
|
||||
|
||||
activityCopy->Stop();
|
||||
activityCopy->Release();
|
||||
}
|
||||
|
||||
DeleteCriticalSection(&lock);
|
||||
}
|
||||
|
||||
HRESULT Device::CreateInstance(const char *name, const char *type, const char *connection, Device**instance)
|
||||
{
|
||||
Device *self;
|
||||
|
||||
if (NULL == instance)
|
||||
return E_POINTER;
|
||||
|
||||
*instance = NULL;
|
||||
|
||||
self = new Device();
|
||||
if (NULL == self)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
self->name = AnsiString_Duplicate(name);
|
||||
self->type = AnsiString_Duplicate(type);
|
||||
self->connection = AnsiString_Duplicate(connection);
|
||||
|
||||
*instance = self;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
size_t Device::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
size_t Device::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int Device::QueryInterface(GUID interface_guid, void **object)
|
||||
{
|
||||
if (NULL == object)
|
||||
return E_POINTER;
|
||||
|
||||
if (IsEqualIID(interface_guid, IFC_Device))
|
||||
*object = static_cast<ifc_device*>(this);
|
||||
else
|
||||
{
|
||||
*object = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
if (NULL == *object)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void Device::Lock()
|
||||
{
|
||||
EnterCriticalSection(&lock);
|
||||
}
|
||||
|
||||
void Device::Unlock()
|
||||
{
|
||||
LeaveCriticalSection(&lock);
|
||||
}
|
||||
|
||||
const char *Device::GetName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
const char *Device::GetType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
const char *Device::GetConnection()
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
HRESULT Device::GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
|
||||
{
|
||||
if (NULL == buffer)
|
||||
return E_POINTER;
|
||||
|
||||
if (NULL == iconStore)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return iconStore->Get(buffer, bufferSize, width, height);
|
||||
}
|
||||
|
||||
HRESULT Device::GetDisplayName(wchar_t *buffer, size_t bufferSize)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == buffer)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
if (0 == String_CopyTo(buffer, displayName, bufferSize) &&
|
||||
FALSE == IS_STRING_EMPTY(displayName))
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
else
|
||||
hr = S_OK;
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
BOOL Device::GetHidden()
|
||||
{
|
||||
return hidden;
|
||||
}
|
||||
|
||||
HRESULT Device::GetTotalSpace(uint64_t *size)
|
||||
{
|
||||
if (NULL == size)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
*size = totalSpace;
|
||||
|
||||
Unlock();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Device::GetUsedSpace(uint64_t *size)
|
||||
{
|
||||
if (NULL == size)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
*size = usedSpace;
|
||||
|
||||
Unlock();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL Device::GetAttached()
|
||||
{
|
||||
return attached;
|
||||
}
|
||||
|
||||
HRESULT Device::Attach(HWND hostWindow)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (FALSE != attached)
|
||||
hr = S_FALSE;
|
||||
else
|
||||
{
|
||||
attached = TRUE;
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if (S_OK == hr && NULL != eventManager)
|
||||
eventManager->Notify_AttachmentChanged(this, attached);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::Detach(HWND hostWindow)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (FALSE == attached)
|
||||
hr = S_FALSE;
|
||||
else
|
||||
{
|
||||
attached = FALSE;
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if (S_OK == hr && NULL != eventManager)
|
||||
eventManager->Notify_AttachmentChanged(this, attached);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::EnumerateCommands(ifc_devicesupportedcommandenum **enumerator, DeviceCommandContext context)
|
||||
{
|
||||
if (NULL == commands)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return commands->Enumerate(enumerator);
|
||||
}
|
||||
|
||||
HRESULT Device::SendCommand(const char *command, HWND hostWindow, ULONG_PTR param)
|
||||
{
|
||||
const wchar_t *commandName;
|
||||
wchar_t message[1024];
|
||||
|
||||
if (NULL == command)
|
||||
return E_POINTER;
|
||||
|
||||
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "sync", -1))
|
||||
{
|
||||
StartSyncActivity(hostWindow);
|
||||
return S_OK;
|
||||
}
|
||||
else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "eject", -1))
|
||||
commandName = L"Eject";
|
||||
else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "detach", -1))
|
||||
{
|
||||
Detach(hostWindow);
|
||||
return S_OK;
|
||||
}
|
||||
else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "settings", -1))
|
||||
commandName = L"Settings";
|
||||
else
|
||||
return E_NOTIMPL;
|
||||
|
||||
StringCchPrintf(message, ARRAYSIZE(message), L"%s command received", commandName);
|
||||
MessageBox(hostWindow, message, L"Device command test", MB_OK | MB_ICONINFORMATION);
|
||||
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Device::GetCommandFlags(const char *command, DeviceCommandFlags *flags)
|
||||
{
|
||||
if (NULL == commands)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return commands->GetFlags(command, flags);
|
||||
}
|
||||
|
||||
HRESULT Device::GetActivity(ifc_deviceactivity **activityOut)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == activityOut)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
*activityOut = activity;
|
||||
|
||||
if (NULL != activity)
|
||||
{
|
||||
activity->AddRef();
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
hr = S_FALSE;
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::Advise(ifc_deviceevent *handler)
|
||||
{
|
||||
if (NULL == eventManager)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return eventManager->Advise(handler);
|
||||
}
|
||||
|
||||
HRESULT Device::Unadvise(ifc_deviceevent *handler)
|
||||
{
|
||||
if (NULL == eventManager)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return eventManager->Unadvise(handler);
|
||||
}
|
||||
|
||||
HWND Device::CreateView(HWND parentWindow)
|
||||
{
|
||||
return DeviceView_CreateWindow(parentWindow, this);
|
||||
}
|
||||
|
||||
void Device::SetNavigationItem(void *navigationItem)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT Device::GetModel(wchar_t *buffer, size_t bufferSize)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == buffer)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
if (0 == String_CopyTo(buffer, model, bufferSize) &&
|
||||
FALSE == IS_STRING_EMPTY(model))
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
else
|
||||
hr = S_OK;
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
HRESULT Device::GetStatus(wchar_t *buffer, size_t bufferSize)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == buffer)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
if (0 == String_CopyTo(buffer, status, bufferSize) &&
|
||||
FALSE == IS_STRING_EMPTY(status))
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
else
|
||||
hr = S_OK;
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
HRESULT Device::SetConnection(const char *con)
|
||||
{
|
||||
Lock();
|
||||
|
||||
AnsiString_Free(connection);
|
||||
connection = AnsiString_Duplicate(con);
|
||||
|
||||
Unlock();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Device::SetDisplayName(const wchar_t *name)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (NULL == name && NULL == displayName)
|
||||
hr = S_FALSE;
|
||||
else
|
||||
{
|
||||
if (NULL != displayName &&
|
||||
CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, name, -1, displayName, -1))
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *string;
|
||||
|
||||
string = String_Duplicate(name);
|
||||
if (NULL == string && NULL != name)
|
||||
hr = E_FAIL;
|
||||
else
|
||||
{
|
||||
String_Free(displayName);
|
||||
displayName = string;
|
||||
|
||||
if (NULL != eventManager)
|
||||
eventManager->Notify_DisplayNameChanged(this, displayName);
|
||||
|
||||
hr = S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::SetTotalSpace(uint64_t size)
|
||||
{
|
||||
Lock();
|
||||
|
||||
totalSpace = size;
|
||||
|
||||
if (NULL != eventManager)
|
||||
eventManager->Notify_TotalSpaceChanged(this, totalSpace);
|
||||
|
||||
Unlock();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Device::SetUsedSpace(uint64_t size)
|
||||
{
|
||||
Lock();
|
||||
|
||||
usedSpace = size;
|
||||
|
||||
if (NULL != eventManager)
|
||||
eventManager->Notify_UsedSpaceChanged(this, usedSpace);
|
||||
|
||||
Unlock();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Device::SetModel(const wchar_t *deviceModel)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (NULL == deviceModel && NULL == model)
|
||||
hr = S_FALSE;
|
||||
else
|
||||
{
|
||||
if (NULL != model &&
|
||||
CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, deviceModel, -1, model, -1))
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *string;
|
||||
|
||||
string = String_Duplicate(deviceModel);
|
||||
if (NULL == string && NULL != deviceModel)
|
||||
hr = E_FAIL;
|
||||
else
|
||||
{
|
||||
String_Free(model);
|
||||
model = string;
|
||||
|
||||
if (NULL != eventManager)
|
||||
eventManager->Notify_ModelChanged(this, model);
|
||||
|
||||
hr = S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::SetStatus(const wchar_t *deviceStatus)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (NULL == deviceStatus && NULL == status)
|
||||
hr = S_FALSE;
|
||||
else
|
||||
{
|
||||
if (NULL != status &&
|
||||
CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, deviceStatus, -1, status, -1))
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *string;
|
||||
|
||||
string = String_Duplicate(deviceStatus);
|
||||
if (NULL == string && NULL != deviceStatus)
|
||||
hr = E_FAIL;
|
||||
else
|
||||
{
|
||||
String_Free(status);
|
||||
status = string;
|
||||
|
||||
if (NULL != eventManager)
|
||||
eventManager->Notify_StatusChanged(this, status);
|
||||
|
||||
hr = S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::AddIcon(const wchar_t *path, unsigned int width, unsigned int height)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == iconStore)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
hr = iconStore->Add(path, width, height, TRUE);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (NULL != eventManager)
|
||||
eventManager->Notify_IconChanged(this);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::EnumerateIcons(ifc_deviceiconstore::EnumeratorCallback callback, void *user)
|
||||
{
|
||||
if (NULL == iconStore)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return iconStore->Enumerate(callback, user);
|
||||
}
|
||||
|
||||
|
||||
HRESULT Device::RemoveIcon(unsigned int width, unsigned int height)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == iconStore)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
hr = iconStore->Remove(width, height);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (NULL != eventManager)
|
||||
eventManager->Notify_IconChanged(this);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
HRESULT Device::SetHidden(BOOL hiddenState)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (hidden == (FALSE != hiddenState))
|
||||
hr = S_FALSE;
|
||||
else
|
||||
{
|
||||
hidden = (FALSE != hiddenState);
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if (S_OK == hr && NULL != eventManager)
|
||||
eventManager->Notify_VisibilityChanged(this, TRUE);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::IsConnected()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
hr = (FALSE != connected) ? S_OK : S_FALSE;
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::Connect()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (FALSE != connected)
|
||||
hr = S_FALSE;
|
||||
else
|
||||
{
|
||||
connected = TRUE;
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::Disconnect()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (FALSE == connected)
|
||||
hr = S_FALSE;
|
||||
else
|
||||
{
|
||||
connected = FALSE;
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Device::CopyTo(Device *target)
|
||||
{
|
||||
if (NULL == target)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
target->SetDisplayName(displayName);
|
||||
|
||||
if (NULL != target->iconStore)
|
||||
target->iconStore->Release();
|
||||
|
||||
if (NULL == iconStore || FAILED(iconStore->Clone(&target->iconStore)))
|
||||
target->iconStore = NULL;
|
||||
|
||||
target->usedSpace = usedSpace;
|
||||
target->totalSpace = totalSpace;
|
||||
target->hidden = hidden;
|
||||
target->attached = attached;
|
||||
target->connected = connected;
|
||||
|
||||
if (NULL != target->commands)
|
||||
target->commands->Release();
|
||||
|
||||
if (NULL == commands || FAILED(commands->Clone(&target->commands, TRUE)))
|
||||
target->commands = NULL;
|
||||
|
||||
Unlock();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Device::SetIconBase(const wchar_t *path)
|
||||
{
|
||||
if (NULL == iconStore)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return iconStore->SetBasePath(path);
|
||||
}
|
||||
|
||||
HRESULT Device::AddCommand(const char *command, DeviceCommandFlags flags)
|
||||
{
|
||||
if (NULL == commands)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return commands->Add(command, flags);
|
||||
}
|
||||
|
||||
HRESULT Device::RemoveCommand(const char *command)
|
||||
{
|
||||
if (NULL == commands)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return commands->Remove(command);
|
||||
|
||||
}
|
||||
|
||||
HRESULT Device::SetCommandFlags(const char *command, DeviceCommandFlags mask, DeviceCommandFlags flags)
|
||||
{
|
||||
if (NULL == commands)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
return commands->SetFlags(command, mask, flags);
|
||||
}
|
||||
|
||||
void Device::ActivityStartedCb(DeviceActivity *activity)
|
||||
{
|
||||
Device *device;
|
||||
|
||||
if(FAILED(activity->GetUser((void**)&device)) || NULL == device)
|
||||
return;
|
||||
|
||||
if (NULL != device->eventManager)
|
||||
device->eventManager->Notify_ActivityStarted(device, activity);
|
||||
}
|
||||
|
||||
void Device::ActivityFinishedCb(DeviceActivity *activity)
|
||||
{
|
||||
Device *device;
|
||||
|
||||
if(FAILED(activity->GetUser((void**)&device)) || NULL == device)
|
||||
return;
|
||||
|
||||
device->Lock();
|
||||
|
||||
if (activity == device->activity)
|
||||
device->activity = NULL;
|
||||
|
||||
|
||||
device->Unlock();
|
||||
|
||||
if (NULL != device->eventManager)
|
||||
device->eventManager->Notify_ActivityFinished(device, activity);
|
||||
|
||||
activity->Release();
|
||||
}
|
||||
|
||||
void Device::ActivityProgressCb(DeviceActivity *activity, unsigned int progress, unsigned int duration)
|
||||
{
|
||||
Device *device;
|
||||
uint64_t space;
|
||||
|
||||
if(FAILED(activity->GetUser((void**)&device)) || NULL == device)
|
||||
return;
|
||||
|
||||
device->Lock();
|
||||
|
||||
space = device->usedSpace;
|
||||
space++;
|
||||
if (space > device->totalSpace)
|
||||
space = 0;
|
||||
|
||||
device->Unlock();
|
||||
|
||||
device->SetUsedSpace(space);
|
||||
|
||||
if (NULL != device->eventManager)
|
||||
device->eventManager->Notify_ActivityChanged(device, activity);
|
||||
|
||||
}
|
||||
|
||||
HRESULT Device::StartSyncActivity(HWND hostWindow)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (NULL != activity)
|
||||
hr = E_PENDING;
|
||||
else
|
||||
{
|
||||
hr = DeviceActivity::CreateInstance(DeviceActivityFlag_Cancelable | DeviceActivityFlag_SupportProgress,
|
||||
ActivityStartedCb, ActivityFinishedCb, ActivityProgressCb,
|
||||
this, &activity);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
activity->SetDisplayName(L"Synchronizing...");
|
||||
|
||||
activity->SetStatus(L"Performing synchronization...");
|
||||
hr = activity->Start(60000, 20);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
activity->Release();
|
||||
activity = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#define CBCLASS Device
|
||||
START_DISPATCH;
|
||||
CB(ADDREF, AddRef)
|
||||
CB(RELEASE, Release)
|
||||
CB(QUERYINTERFACE, QueryInterface)
|
||||
CB(API_GETNAME, GetName)
|
||||
CB(API_GETTYPE, GetType)
|
||||
CB(API_GETCONNECTION, GetConnection)
|
||||
CB(API_GETICON, GetIcon)
|
||||
CB(API_GETDISPLAYNAME, GetDisplayName)
|
||||
CB(API_GETHIDDEN, GetHidden)
|
||||
CB(API_GETTOTALSPACE, GetTotalSpace)
|
||||
CB(API_GETUSEDSPACE, GetUsedSpace)
|
||||
CB(API_GETATTACHED, GetAttached)
|
||||
CB(API_ATTACH, Attach)
|
||||
CB(API_DETACH, Detach)
|
||||
CB(API_ENUMERATECOMMANDS, EnumerateCommands)
|
||||
CB(API_SENDCOMMAND, SendCommand)
|
||||
CB(API_GETCOMMANDFLAGS, GetCommandFlags)
|
||||
CB(API_GETACTIVITY, GetActivity)
|
||||
CB(API_ADVISE, Advise)
|
||||
CB(API_UNADVISE, Unadvise)
|
||||
CB(API_CREATEVIEW, CreateView)
|
||||
VCB(API_SETNAVIGATIONITEM, SetNavigationItem)
|
||||
CB(API_SETDISPLAYNAME, SetDisplayName)
|
||||
CB(API_GETMODEL, GetModel)
|
||||
CB(API_GETSTATUS, GetStatus)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
114
Src/Plugins/Library/ml_devices/gen_deviceprovider/device.h
Normal file
114
Src/Plugins/Library/ml_devices/gen_deviceprovider/device.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
class DeviceActivity;
|
||||
|
||||
class Device: public ifc_device
|
||||
{
|
||||
|
||||
protected:
|
||||
Device();
|
||||
~Device();
|
||||
public:
|
||||
static HRESULT CreateInstance(const char *name,
|
||||
const char *type,
|
||||
const char *connection,
|
||||
Device**instance);
|
||||
|
||||
public:
|
||||
/* Dispatchable */
|
||||
size_t AddRef();
|
||||
size_t Release();
|
||||
int QueryInterface(GUID interface_guid, void **object);
|
||||
|
||||
/* ifc_device */
|
||||
const char *GetName();
|
||||
const char *GetType();
|
||||
const char *GetConnection();
|
||||
HRESULT GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height);
|
||||
HRESULT GetDisplayName(wchar_t *buffer, size_t bufferSize);
|
||||
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 GetModel(wchar_t *buffer, size_t bufferSize);
|
||||
HRESULT GetStatus(wchar_t *buffer, size_t bufferSize);
|
||||
|
||||
public:
|
||||
HRESULT SetConnection(const char *connection);
|
||||
HRESULT SetDisplayName(const wchar_t *name);
|
||||
HRESULT SetTotalSpace(uint64_t size);
|
||||
HRESULT SetUsedSpace(uint64_t size);
|
||||
HRESULT SetHidden(BOOL hiddenState);
|
||||
HRESULT SetModel(const wchar_t *deviceModel);
|
||||
HRESULT SetStatus(const wchar_t *deviceStatus);
|
||||
|
||||
HRESULT AddIcon(const wchar_t *path, unsigned int width, unsigned int height);
|
||||
HRESULT EnumerateIcons(ifc_deviceiconstore::EnumeratorCallback callback, void *user);
|
||||
HRESULT RemoveIcon(unsigned int width, unsigned int height);
|
||||
|
||||
HRESULT AddCommand(const char *command, DeviceCommandFlags flags);
|
||||
HRESULT RemoveCommand(const char *command);
|
||||
HRESULT SetCommandFlags(const char *command, DeviceCommandFlags mask, DeviceCommandFlags flags);
|
||||
|
||||
HRESULT IsConnected();
|
||||
HRESULT Connect();
|
||||
HRESULT Disconnect();
|
||||
|
||||
HRESULT CopyTo(Device *target);
|
||||
HRESULT SetIconBase(const wchar_t *path);
|
||||
|
||||
HRESULT StartSyncActivity(HWND hostWindow);
|
||||
|
||||
|
||||
protected:
|
||||
void Lock();
|
||||
void Unlock();
|
||||
|
||||
static void ActivityStartedCb(DeviceActivity *activity);
|
||||
static void ActivityFinishedCb(DeviceActivity *activity);
|
||||
static void ActivityProgressCb(DeviceActivity *activity, unsigned int progress, unsigned int duration);
|
||||
|
||||
|
||||
protected:
|
||||
size_t ref;
|
||||
char *name;
|
||||
char *type;
|
||||
char *connection;
|
||||
wchar_t *displayName;
|
||||
wchar_t *model;
|
||||
wchar_t *status;
|
||||
uint64_t totalSpace;
|
||||
uint64_t usedSpace;
|
||||
BOOL attached;
|
||||
BOOL hidden;
|
||||
BOOL connected;
|
||||
ifc_deviceiconstore *iconStore;
|
||||
ifc_deviceeventmanager *eventManager;
|
||||
ifc_devicesupportedcommandstore *commands;
|
||||
DeviceActivity *activity;
|
||||
CRITICAL_SECTION lock;
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_HEADER
|
|
@ -0,0 +1,519 @@
|
|||
#include "main.h"
|
||||
#include "./deviceActivity.h"
|
||||
|
||||
#include <strsafe.h>
|
||||
|
||||
typedef struct DeviceActivityThreadParam
|
||||
{
|
||||
DeviceActivity *activity;
|
||||
unsigned int duration;
|
||||
unsigned int interval;
|
||||
HANDLE readyEvent;
|
||||
}DeviceActivityThreadParam;
|
||||
|
||||
DeviceActivity::DeviceActivity(DeviceActivityFlags flags,
|
||||
DeviceActivityCallback startCb, DeviceActivityCallback finishCb,
|
||||
DeviceActivityProgressCallback progressCb, void *user)
|
||||
: ref(1), displayName(NULL), status(NULL), activityThread(FALSE), cancelEvent(NULL), progress(0)
|
||||
{
|
||||
InitializeCriticalSection(&lock);
|
||||
|
||||
this->flags = flags;
|
||||
callbackStart = startCb;
|
||||
callbackFinish = finishCb;
|
||||
callbackProgress = progressCb;
|
||||
this->user = user;
|
||||
}
|
||||
|
||||
DeviceActivity::~DeviceActivity()
|
||||
{
|
||||
Stop();
|
||||
|
||||
String_Free(displayName);
|
||||
String_Free(status);
|
||||
|
||||
DeleteCriticalSection(&lock);
|
||||
}
|
||||
|
||||
|
||||
HRESULT DeviceActivity::CreateInstance(DeviceActivityFlags flags,
|
||||
DeviceActivityCallback startCb, DeviceActivityCallback finishCb,
|
||||
DeviceActivityProgressCallback progressCb, void *user,
|
||||
DeviceActivity **instance)
|
||||
{
|
||||
DeviceActivity *self;
|
||||
|
||||
if (NULL == instance)
|
||||
return E_POINTER;
|
||||
|
||||
*instance = NULL;
|
||||
|
||||
self = new DeviceActivity(flags, startCb, finishCb, progressCb, user);
|
||||
if (NULL == self)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
*instance = self;
|
||||
return S_OK;
|
||||
|
||||
}
|
||||
|
||||
size_t DeviceActivity::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
size_t DeviceActivity::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int DeviceActivity::QueryInterface(GUID interface_guid, void **object)
|
||||
{
|
||||
if (NULL == object)
|
||||
return E_POINTER;
|
||||
|
||||
if (IsEqualIID(interface_guid, IFC_DeviceActivity))
|
||||
*object = static_cast<ifc_deviceactivity*>(this);
|
||||
else
|
||||
{
|
||||
*object = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
if (NULL == *object)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void DeviceActivity::Lock()
|
||||
{
|
||||
EnterCriticalSection(&lock);
|
||||
}
|
||||
|
||||
void DeviceActivity::Unlock()
|
||||
{
|
||||
LeaveCriticalSection(&lock);
|
||||
}
|
||||
|
||||
BOOL DeviceActivity::GetActive()
|
||||
{
|
||||
BOOL running;
|
||||
|
||||
Lock();
|
||||
running = (NULL != activityThread);
|
||||
Unlock();
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
BOOL DeviceActivity::GetCancelable()
|
||||
{
|
||||
BOOL cancelable;
|
||||
|
||||
Lock();
|
||||
cancelable = (0 != (DeviceActivityFlag_Cancelable & flags));
|
||||
Unlock();
|
||||
|
||||
return cancelable;
|
||||
}
|
||||
|
||||
HRESULT DeviceActivity::GetProgress(unsigned int *percentCompleted)
|
||||
{
|
||||
|
||||
if (NULL == percentCompleted)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
*percentCompleted = progress;
|
||||
|
||||
Unlock();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeviceActivity::GetDisplayName(wchar_t *buffer, size_t bufferMax)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == buffer)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
if (0 == String_CopyTo(buffer, displayName, bufferMax) &&
|
||||
FALSE == IS_STRING_EMPTY(displayName))
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
else
|
||||
hr = S_OK;
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceActivity::GetStatus(wchar_t *buffer, size_t bufferMax)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == buffer)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
if (0 == String_CopyTo(buffer, status, bufferMax) &&
|
||||
FALSE == IS_STRING_EMPTY(status))
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
else
|
||||
hr = S_OK;
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceActivity::Cancel(HWND hostWindow)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (0 == (DeviceActivityFlag_Cancelable & flags))
|
||||
hr = E_NOTIMPL;
|
||||
else
|
||||
hr = E_FAIL;
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DeviceActivity::Start(unsigned int duration, unsigned int interval)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (NULL != activityThread)
|
||||
hr = E_PENDING;
|
||||
else
|
||||
{
|
||||
hr = S_OK;
|
||||
|
||||
if (NULL == cancelEvent)
|
||||
{
|
||||
cancelEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (NULL == cancelEvent)
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DeviceActivityThreadParam param;
|
||||
|
||||
param.activity = this;
|
||||
param.duration = duration;
|
||||
param.interval = interval;
|
||||
param.readyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
if (NULL == param.readyEvent)
|
||||
hr = E_FAIL;
|
||||
else
|
||||
{
|
||||
DWORD threadId;
|
||||
|
||||
activityThread = CreateThread(NULL, 0, DeviceActivity_ActivityThreadStarter,
|
||||
¶m, 0, &threadId);
|
||||
if (NULL == activityThread)
|
||||
hr = E_FAIL;
|
||||
else
|
||||
WaitForSingleObject(param.readyEvent, INFINITE);
|
||||
|
||||
CloseHandle(param.readyEvent);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
Stop();
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceActivity::Stop()
|
||||
{
|
||||
HRESULT hr;
|
||||
HANDLE threadHandle, eventHandle;
|
||||
|
||||
Lock();
|
||||
|
||||
threadHandle = activityThread;
|
||||
eventHandle = cancelEvent;
|
||||
|
||||
activityThread = NULL;
|
||||
cancelEvent = NULL;
|
||||
|
||||
Unlock();
|
||||
|
||||
if (NULL != threadHandle)
|
||||
{
|
||||
if (NULL != eventHandle)
|
||||
SetEvent(eventHandle);
|
||||
|
||||
WaitForSingleObject(threadHandle, INFINITE);
|
||||
CloseHandle(threadHandle);
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
hr = S_FALSE;
|
||||
|
||||
if (NULL != eventHandle)
|
||||
CloseHandle(eventHandle);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceActivity::SetDisplayName(const wchar_t *name)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
Lock();
|
||||
|
||||
if (NULL == name && NULL == displayName)
|
||||
hr = S_FALSE;
|
||||
else
|
||||
{
|
||||
if (NULL != displayName &&
|
||||
CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, name, -1, displayName, -1))
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *string;
|
||||
|
||||
string = String_Duplicate(name);
|
||||
if (NULL == string && NULL != name)
|
||||
hr = E_FAIL;
|
||||
else
|
||||
{
|
||||
String_Free(displayName);
|
||||
displayName = string;
|
||||
hr = S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceActivity::SetStatus(const wchar_t *newStatus)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == newStatus && NULL == status)
|
||||
return S_FALSE;
|
||||
|
||||
Lock();
|
||||
|
||||
if (NULL != status &&
|
||||
CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, newStatus, -1, status, -1))
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *string;
|
||||
|
||||
string = String_Duplicate(newStatus);
|
||||
if (NULL == string && NULL != newStatus)
|
||||
hr = E_FAIL;
|
||||
else
|
||||
{
|
||||
String_Free(status);
|
||||
status = string;
|
||||
hr = S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceActivity::SetUser(void *data)
|
||||
{
|
||||
Lock();
|
||||
user = data;
|
||||
Unlock();
|
||||
|
||||
return S_OK;
|
||||
|
||||
}
|
||||
HRESULT DeviceActivity::GetUser(void **data)
|
||||
{
|
||||
if (NULL == data)
|
||||
return E_POINTER;
|
||||
|
||||
Lock();
|
||||
|
||||
*data = user;
|
||||
|
||||
Unlock();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DWORD DeviceActivity::ActivityThread(unsigned int duration, unsigned int interval)
|
||||
{
|
||||
DWORD waitResult, waitTime;
|
||||
HANDLE cancelEventCopy;
|
||||
unsigned int position;
|
||||
|
||||
if (interval > duration)
|
||||
interval = duration;
|
||||
|
||||
|
||||
position = 0;
|
||||
|
||||
Lock();
|
||||
|
||||
progress = 0;
|
||||
|
||||
if (NULL == cancelEvent ||
|
||||
0 == DuplicateHandle(GetCurrentProcess(), cancelEvent, GetCurrentProcess(),
|
||||
&cancelEventCopy, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
cancelEventCopy = NULL;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if(NULL == cancelEventCopy)
|
||||
return -3;
|
||||
|
||||
Lock();
|
||||
|
||||
if (NULL != callbackStart)
|
||||
callbackStart(this);
|
||||
|
||||
if (NULL != callbackProgress)
|
||||
callbackProgress(this, position, duration);
|
||||
|
||||
Unlock();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
waitTime = interval;
|
||||
if ((position + waitTime) > duration)
|
||||
waitTime = duration - position;
|
||||
|
||||
waitResult = WaitForSingleObject(cancelEventCopy, waitTime);
|
||||
if (WAIT_TIMEOUT == waitResult)
|
||||
{
|
||||
position += waitTime;
|
||||
|
||||
Lock();
|
||||
|
||||
if (duration != 0)
|
||||
{
|
||||
progress = 100 * position / duration;
|
||||
if (progress > 100)
|
||||
progress = 100;
|
||||
}
|
||||
else
|
||||
progress = 100;
|
||||
|
||||
|
||||
if (NULL != callbackProgress)
|
||||
callbackProgress(this, position, duration);
|
||||
Unlock();
|
||||
|
||||
if (position >= duration)
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
|
||||
Lock();
|
||||
|
||||
if (NULL != activityThread)
|
||||
{
|
||||
CloseHandle(activityThread);
|
||||
activityThread = NULL;
|
||||
}
|
||||
|
||||
if (NULL != cancelEvent)
|
||||
{
|
||||
CloseHandle(cancelEvent);
|
||||
cancelEvent = NULL;
|
||||
}
|
||||
|
||||
if (NULL != callbackFinish)
|
||||
callbackFinish(this);
|
||||
|
||||
Unlock();
|
||||
|
||||
Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD CALLBACK
|
||||
DeviceActivity_ActivityThreadStarter(void *user)
|
||||
{
|
||||
DeviceActivityThreadParam *param;
|
||||
DeviceActivity *activity;
|
||||
unsigned int duration, interval;
|
||||
DWORD result;
|
||||
|
||||
param = (DeviceActivityThreadParam*)user;
|
||||
activity = param->activity;
|
||||
duration = param->duration;
|
||||
interval = param->interval;
|
||||
|
||||
if (NULL != param->readyEvent)
|
||||
SetEvent(param->readyEvent);
|
||||
|
||||
if (NULL != activity)
|
||||
result = activity->ActivityThread(duration, interval);
|
||||
else
|
||||
result = -2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceActivity
|
||||
START_DISPATCH;
|
||||
CB(ADDREF, AddRef)
|
||||
CB(RELEASE, Release)
|
||||
CB(QUERYINTERFACE, QueryInterface)
|
||||
CB(API_GETACTIVE, GetActive)
|
||||
CB(API_GETCANCELABLE, GetCancelable)
|
||||
CB(API_GETPROGRESS, GetProgress)
|
||||
CB(API_GETDISPLAYNAME, GetDisplayName)
|
||||
CB(API_GETSTATUS, GetStatus)
|
||||
CB(API_CANCEL, Cancel)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
|
@ -0,0 +1,91 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ACTIVITY_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ACTIVITY_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
typedef enum DeviceActivityFlags
|
||||
{
|
||||
DeviceActivityFlag_Cancelable = (1 << 0),
|
||||
DeviceActivityFlag_SupportProgress = (1 << 0),
|
||||
} DeviceActivityFlags;
|
||||
DEFINE_ENUM_FLAG_OPERATORS(DeviceActivityFlags);
|
||||
|
||||
typedef void (*DeviceActivityCallback)(DeviceActivity * /*activity*/);
|
||||
typedef void (*DeviceActivityProgressCallback)(DeviceActivity * /*activity*/, unsigned int /*position*/, unsigned int /*total*/);
|
||||
|
||||
|
||||
class DeviceActivity: public ifc_deviceactivity
|
||||
{
|
||||
|
||||
protected:
|
||||
DeviceActivity(DeviceActivityFlags flags,
|
||||
DeviceActivityCallback startCb,
|
||||
DeviceActivityCallback finishCb,
|
||||
DeviceActivityProgressCallback progressCb,
|
||||
void *user);
|
||||
|
||||
~DeviceActivity();
|
||||
public:
|
||||
static HRESULT CreateInstance(DeviceActivityFlags flags,
|
||||
DeviceActivityCallback startCb,
|
||||
DeviceActivityCallback finishCb,
|
||||
DeviceActivityProgressCallback progressCb,
|
||||
void *user,
|
||||
DeviceActivity **instance);
|
||||
|
||||
public:
|
||||
/* Dispatchable */
|
||||
size_t AddRef();
|
||||
size_t Release();
|
||||
int QueryInterface(GUID interface_guid, void **object);
|
||||
|
||||
/* ifc_deviceactivity */
|
||||
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:
|
||||
void Lock();
|
||||
void Unlock();
|
||||
|
||||
HRESULT Start(unsigned int duration, unsigned int interval);
|
||||
HRESULT Stop();
|
||||
|
||||
HRESULT SetDisplayName(const wchar_t *displayName);
|
||||
HRESULT SetStatus(const wchar_t *status);
|
||||
|
||||
HRESULT SetUser(void *data);
|
||||
HRESULT GetUser(void **data);
|
||||
|
||||
protected:
|
||||
DWORD ActivityThread(unsigned int duration, unsigned int interval);
|
||||
friend static DWORD CALLBACK DeviceActivity_ActivityThreadStarter(void *param);
|
||||
|
||||
protected:
|
||||
size_t ref;
|
||||
DeviceActivityFlags flags;
|
||||
DeviceActivityCallback callbackStart;
|
||||
DeviceActivityCallback callbackFinish;
|
||||
DeviceActivityProgressCallback callbackProgress;
|
||||
void *user;
|
||||
wchar_t *displayName;
|
||||
wchar_t *status;
|
||||
HANDLE activityThread;
|
||||
HANDLE cancelEvent;
|
||||
unsigned int progress;
|
||||
CRITICAL_SECTION lock;
|
||||
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ACTIVITY_HEADER
|
|
@ -0,0 +1,75 @@
|
|||
#include "main.h"
|
||||
#include "./DeviceCommandNodeParser.h"
|
||||
#include "../../xml/obj_xml.h"
|
||||
|
||||
DeviceCommandNodeParser::DeviceCommandNodeParser()
|
||||
: reader(NULL), test(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceCommandNodeParser::~DeviceCommandNodeParser()
|
||||
{
|
||||
End();
|
||||
}
|
||||
|
||||
|
||||
BOOL DeviceCommandNodeParser::Begin(obj_xml *xmlReader, TestSuite *testSuite)
|
||||
{
|
||||
if (NULL != reader || NULL != test)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == xmlReader || NULL == testSuite)
|
||||
return FALSE;
|
||||
|
||||
reader = xmlReader;
|
||||
reader->AddRef();
|
||||
|
||||
test = testSuite;
|
||||
|
||||
reader->xmlreader_registerCallback(L"testprovider\fcommands\fcommand", this);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void DeviceCommandNodeParser::End()
|
||||
{
|
||||
if (NULL != reader)
|
||||
{
|
||||
reader->xmlreader_unregisterCallback(this);
|
||||
reader->Release();
|
||||
reader = NULL;
|
||||
}
|
||||
|
||||
if (NULL != test)
|
||||
test = NULL;
|
||||
}
|
||||
|
||||
|
||||
void DeviceCommandNodeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
|
||||
{
|
||||
elementParser.Begin(reader, params);
|
||||
}
|
||||
|
||||
void DeviceCommandNodeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
|
||||
{
|
||||
ifc_devicecommand *result;
|
||||
if (FALSE != elementParser.End(reader, &result))
|
||||
{
|
||||
if (NULL != test)
|
||||
test->AddCommand(result);
|
||||
|
||||
result->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceCommandNodeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
|
||||
{
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceCommandNodeParser
|
||||
START_DISPATCH;
|
||||
VCB(ONSTARTELEMENT, Event_XmlStartElement)
|
||||
VCB(ONENDELEMENT, Event_XmlEndElement)
|
||||
VCB(ONERROR, Event_XmlError)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_NODE_PARSER_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_NODE_PARSER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../../xml/ifc_xmlreadercallback.h"
|
||||
#include "./deviceCommandParser.h"
|
||||
|
||||
class obj_xml;
|
||||
|
||||
class DeviceCommandNodeParser : public ifc_xmlreadercallback
|
||||
{
|
||||
|
||||
public:
|
||||
DeviceCommandNodeParser();
|
||||
~DeviceCommandNodeParser();
|
||||
|
||||
public:
|
||||
BOOL Begin(obj_xml *xmlReader, TestSuite *testSuite);
|
||||
void End();
|
||||
|
||||
protected:
|
||||
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
|
||||
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
|
||||
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
|
||||
|
||||
protected:
|
||||
obj_xml *reader;
|
||||
DeviceCommandParser elementParser;
|
||||
TestSuite *test;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_NODE_PARSER_HEADER
|
|
@ -0,0 +1,192 @@
|
|||
#include "main.h"
|
||||
#include "./deviceCommandParser.h"
|
||||
|
||||
#include "../../xml/obj_xml.h"
|
||||
|
||||
typedef void (*COMMANDTAGCALLBACK)(DeviceCommandParser* /*self*/, ifc_devicecommandeditor* /*editor*/, const wchar_t* /*value*/);
|
||||
|
||||
typedef struct COMMANDTAG
|
||||
{
|
||||
const wchar_t *name;
|
||||
BOOL multiEntry;
|
||||
COMMANDTAGCALLBACK callback;
|
||||
} COMMANDTAG;
|
||||
|
||||
static void
|
||||
DeviceCommandParser_DisplayNameCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value)
|
||||
{
|
||||
editor->SetDisplayName(value);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceCommandParser_IconCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value)
|
||||
{
|
||||
ifc_deviceiconstore *iconStore;
|
||||
if (SUCCEEDED(editor->GetIconStore(&iconStore)))
|
||||
{
|
||||
iconStore->Add(value, self->iconSize.cx, self->iconSize.cy, TRUE);
|
||||
iconStore->Release();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceCommandParser_DescirptionCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value)
|
||||
{
|
||||
editor->SetDescription(value);
|
||||
}
|
||||
|
||||
static const COMMANDTAG knownTags[COMMAND_TAG_MAX] =
|
||||
{
|
||||
{L"displayName", FALSE, DeviceCommandParser_DisplayNameCb},
|
||||
{L"icon", TRUE, DeviceCommandParser_IconCb},
|
||||
{L"description", FALSE, DeviceCommandParser_DescirptionCb},
|
||||
};
|
||||
|
||||
DeviceCommandParser::DeviceCommandParser()
|
||||
: editor(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceCommandParser::~DeviceCommandParser()
|
||||
{
|
||||
if (NULL != editor)
|
||||
editor->Release();
|
||||
}
|
||||
|
||||
BOOL DeviceCommandParser::Begin(obj_xml *reader, ifc_xmlreaderparams *params)
|
||||
{
|
||||
const wchar_t *name;
|
||||
ifc_devicecommand *command;
|
||||
char *nameAnsi;
|
||||
|
||||
if (NULL != editor)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == reader || NULL == params)
|
||||
return FALSE;
|
||||
|
||||
name = params->getItemValue(L"name");
|
||||
if (NULL == name)
|
||||
return FALSE;
|
||||
|
||||
nameAnsi = String_ToAnsi(CP_UTF8, 0, name, -1, NULL, NULL);
|
||||
if (NULL == nameAnsi)
|
||||
return FALSE;
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
SUCCEEDED(WASABI_API_DEVICES->CreateCommand(nameAnsi, &command)))
|
||||
{
|
||||
if(FAILED(command->QueryInterface(IFC_DeviceCommandEditor, (void**)&editor)))
|
||||
editor = NULL;
|
||||
|
||||
command->Release();
|
||||
}
|
||||
|
||||
AnsiString_Free(nameAnsi);
|
||||
|
||||
if (NULL == editor)
|
||||
return FALSE;
|
||||
|
||||
reader->xmlreader_registerCallback(L"testprovider\fcommands\fcommand\fdisplayName", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fcommands\fcommand\fdescription", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fcommands\fcommand\ficon", this);
|
||||
ZeroMemory(hitList, sizeof(hitList));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DeviceCommandParser::End(obj_xml *reader, ifc_devicecommand **command)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
if (NULL != reader)
|
||||
reader->xmlreader_unregisterCallback(this);
|
||||
|
||||
if (NULL == command)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == editor)
|
||||
return FALSE;
|
||||
|
||||
if (NULL != command)
|
||||
{
|
||||
if (FAILED(editor->QueryInterface(IFC_DeviceCommand, (void**)command)))
|
||||
result = FALSE;
|
||||
else
|
||||
result = TRUE;
|
||||
}
|
||||
else
|
||||
result = TRUE;
|
||||
|
||||
editor->Release();
|
||||
editor = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DeviceCommandParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
|
||||
{
|
||||
elementString.Clear();
|
||||
|
||||
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, L"icon", -1, xmltag, -1))
|
||||
{
|
||||
const wchar_t *sVal;
|
||||
int iVal;
|
||||
|
||||
sVal = params->getItemValue(L"width");
|
||||
if (NULL == sVal ||
|
||||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
|
||||
{
|
||||
iVal = 0;
|
||||
}
|
||||
|
||||
iconSize.cx = iVal;
|
||||
|
||||
sVal = params->getItemValue(L"height");
|
||||
if (NULL == sVal ||
|
||||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
|
||||
{
|
||||
iVal = 0;
|
||||
}
|
||||
|
||||
iconSize.cy = iVal;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceCommandParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
|
||||
{
|
||||
if (NULL == editor)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < COMMAND_TAG_MAX; i++)
|
||||
{
|
||||
if (FALSE == hitList[i] &&
|
||||
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, knownTags[i].name, -1, xmltag, -1))
|
||||
{
|
||||
knownTags[i].callback(this, editor, elementString.Get());
|
||||
|
||||
if (FALSE == knownTags[i].multiEntry)
|
||||
hitList[i] = TRUE;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceCommandParser::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
|
||||
{
|
||||
elementString.Append(value);
|
||||
}
|
||||
|
||||
void DeviceCommandParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
|
||||
{
|
||||
elementString.Clear();
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceCommandParser
|
||||
START_DISPATCH;
|
||||
VCB(ONSTARTELEMENT, Event_XmlStartElement)
|
||||
VCB(ONENDELEMENT, Event_XmlEndElement)
|
||||
VCB(ONCHARDATA, Event_XmlCharData)
|
||||
VCB(ONERROR, Event_XmlError)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_PARSER_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_PARSER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../../xml/ifc_xmlreadercallback.h"
|
||||
|
||||
class obj_xml;
|
||||
|
||||
#define COMMAND_TAG_MAX 3
|
||||
|
||||
class DeviceCommandParser : public ifc_xmlreadercallback
|
||||
{
|
||||
public:
|
||||
DeviceCommandParser();
|
||||
~DeviceCommandParser();
|
||||
public:
|
||||
BOOL Begin(obj_xml *reader, ifc_xmlreaderparams *params);
|
||||
BOOL End(obj_xml *reader, ifc_devicecommand **command);
|
||||
|
||||
protected:
|
||||
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
|
||||
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
|
||||
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
|
||||
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
|
||||
|
||||
protected:
|
||||
friend static void DeviceCommandParser_DisplayNameCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value);
|
||||
friend static void DeviceCommandParser_IconCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value);
|
||||
friend static void DeviceCommandParser_DescirptionCb(DeviceCommandParser *self, ifc_devicecommandeditor *editor, const wchar_t *value);
|
||||
|
||||
protected:
|
||||
StringBuilder elementString;
|
||||
ifc_devicecommandeditor *editor;
|
||||
BOOL hitList[COMMAND_TAG_MAX];
|
||||
SIZE iconSize;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_COMMAND_PARSER_HEADER
|
|
@ -0,0 +1,75 @@
|
|||
#include "main.h"
|
||||
#include "./DeviceConnectionNodeParser.h"
|
||||
#include "../../xml/obj_xml.h"
|
||||
|
||||
DeviceConnectionNodeParser::DeviceConnectionNodeParser()
|
||||
: reader(NULL), test(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceConnectionNodeParser::~DeviceConnectionNodeParser()
|
||||
{
|
||||
End();
|
||||
}
|
||||
|
||||
|
||||
BOOL DeviceConnectionNodeParser::Begin(obj_xml *xmlReader, TestSuite *testSuite)
|
||||
{
|
||||
if (NULL != reader || NULL != test)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == xmlReader || NULL == testSuite)
|
||||
return FALSE;
|
||||
|
||||
reader = xmlReader;
|
||||
reader->AddRef();
|
||||
|
||||
test = testSuite;
|
||||
|
||||
reader->xmlreader_registerCallback(L"testprovider\fconnections\fconnection", this);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void DeviceConnectionNodeParser::End()
|
||||
{
|
||||
if (NULL != reader)
|
||||
{
|
||||
reader->xmlreader_unregisterCallback(this);
|
||||
reader->Release();
|
||||
reader = NULL;
|
||||
}
|
||||
|
||||
if (NULL != test)
|
||||
test = NULL;
|
||||
}
|
||||
|
||||
|
||||
void DeviceConnectionNodeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
|
||||
{
|
||||
elementParser.Begin(reader, params);
|
||||
}
|
||||
|
||||
void DeviceConnectionNodeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
|
||||
{
|
||||
ifc_deviceconnection *result;
|
||||
if (FALSE != elementParser.End(reader, &result))
|
||||
{
|
||||
if (NULL != test)
|
||||
test->AddConnection(result);
|
||||
|
||||
result->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceConnectionNodeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
|
||||
{
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceConnectionNodeParser
|
||||
START_DISPATCH;
|
||||
VCB(ONSTARTELEMENT, Event_XmlStartElement)
|
||||
VCB(ONENDELEMENT, Event_XmlEndElement)
|
||||
VCB(ONERROR, Event_XmlError)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_NODE_PARSER_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_NODE_PARSER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../../xml/ifc_xmlreadercallback.h"
|
||||
#include "./deviceConnectionParser.h"
|
||||
|
||||
class obj_xml;
|
||||
|
||||
class DeviceConnectionNodeParser : public ifc_xmlreadercallback
|
||||
{
|
||||
|
||||
public:
|
||||
DeviceConnectionNodeParser();
|
||||
~DeviceConnectionNodeParser();
|
||||
|
||||
public:
|
||||
BOOL Begin(obj_xml *xmlReader, TestSuite *testSuite);
|
||||
void End();
|
||||
|
||||
protected:
|
||||
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
|
||||
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
|
||||
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
|
||||
|
||||
protected:
|
||||
obj_xml *reader;
|
||||
DeviceConnectionParser elementParser;
|
||||
TestSuite *test;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_NODE_PARSER_HEADER
|
|
@ -0,0 +1,181 @@
|
|||
#include "main.h"
|
||||
#include "./deviceConnectionParser.h"
|
||||
|
||||
#include "../../xml/obj_xml.h"
|
||||
|
||||
typedef void (*CONNECTIONTAGCALLBACK)(DeviceConnectionParser* /*self*/, ifc_deviceconnectioneditor * /*editor*/, const wchar_t* /*value*/);
|
||||
|
||||
typedef struct CONNECTIONTAG
|
||||
{
|
||||
const wchar_t *name;
|
||||
BOOL multiEntry;
|
||||
CONNECTIONTAGCALLBACK callback;
|
||||
} CONNECTIONTAG;
|
||||
|
||||
static void
|
||||
DeviceConnectionParser_DisplayNameCb(DeviceConnectionParser *self, ifc_deviceconnectioneditor *editor, const wchar_t *value)
|
||||
{
|
||||
editor->SetDisplayName(value);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceConnectionParser_IconCb(DeviceConnectionParser *self, ifc_deviceconnectioneditor *editor, const wchar_t *value)
|
||||
{
|
||||
ifc_deviceiconstore *iconStore;
|
||||
if (SUCCEEDED(editor->GetIconStore(&iconStore)))
|
||||
{
|
||||
iconStore->Add(value, self->iconSize.cx, self->iconSize.cy, TRUE);
|
||||
iconStore->Release();
|
||||
}
|
||||
}
|
||||
|
||||
static const CONNECTIONTAG knownTags[CONNECTION_TAG_MAX] =
|
||||
{
|
||||
{L"displayName", FALSE, DeviceConnectionParser_DisplayNameCb},
|
||||
{L"icon", TRUE, DeviceConnectionParser_IconCb},
|
||||
};
|
||||
|
||||
DeviceConnectionParser::DeviceConnectionParser()
|
||||
: editor(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceConnectionParser::~DeviceConnectionParser()
|
||||
{
|
||||
if (NULL != editor)
|
||||
editor->Release();
|
||||
}
|
||||
|
||||
BOOL DeviceConnectionParser::Begin(obj_xml *reader, ifc_xmlreaderparams *params)
|
||||
{
|
||||
const wchar_t *name;
|
||||
ifc_deviceconnection *connection;
|
||||
char *nameAnsi;
|
||||
|
||||
if (NULL != editor)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == reader || NULL == params)
|
||||
return FALSE;
|
||||
|
||||
|
||||
name = params->getItemValue(L"name");
|
||||
if (NULL == name)
|
||||
return FALSE;
|
||||
|
||||
nameAnsi = String_ToAnsi(CP_UTF8, 0, name, -1, NULL, NULL);
|
||||
if (NULL == nameAnsi)
|
||||
return FALSE;
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
SUCCEEDED(WASABI_API_DEVICES->CreateConnection(nameAnsi, &connection)))
|
||||
{
|
||||
if(FAILED(connection->QueryInterface(IFC_DeviceConnectionEditor, (void**)&editor)))
|
||||
editor = NULL;
|
||||
|
||||
connection->Release();
|
||||
}
|
||||
AnsiString_Free(nameAnsi);
|
||||
|
||||
if (NULL == editor)
|
||||
return FALSE;
|
||||
|
||||
reader->xmlreader_registerCallback(L"testprovider\fconnections\fconnection\fdisplayName", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fconnections\fconnection\ficon", this);
|
||||
ZeroMemory(hitList, sizeof(hitList));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DeviceConnectionParser::End(obj_xml *reader, ifc_deviceconnection **connection)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
if (NULL != reader)
|
||||
reader->xmlreader_unregisterCallback(this);
|
||||
|
||||
if (NULL == editor)
|
||||
return FALSE;
|
||||
|
||||
if (NULL != connection)
|
||||
{
|
||||
if (FAILED(editor->QueryInterface(IFC_DeviceConnection, (void**)connection)))
|
||||
result = FALSE;
|
||||
else
|
||||
result = TRUE;
|
||||
}
|
||||
else
|
||||
result = TRUE;
|
||||
|
||||
editor->Release();
|
||||
editor = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DeviceConnectionParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
|
||||
{
|
||||
elementString.Clear();
|
||||
|
||||
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, L"icon", -1, xmltag, -1))
|
||||
{
|
||||
const wchar_t *sVal;
|
||||
int iVal;
|
||||
|
||||
sVal = params->getItemValue(L"width");
|
||||
if (NULL == sVal ||
|
||||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
|
||||
{
|
||||
iVal = 0;
|
||||
}
|
||||
|
||||
iconSize.cx = iVal;
|
||||
|
||||
sVal = params->getItemValue(L"height");
|
||||
if (NULL == sVal ||
|
||||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
|
||||
{
|
||||
iVal = 0;
|
||||
}
|
||||
|
||||
iconSize.cy = iVal;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceConnectionParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
|
||||
{
|
||||
if (NULL == editor)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < CONNECTION_TAG_MAX; i++)
|
||||
{
|
||||
if (FALSE == hitList[i] &&
|
||||
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, knownTags[i].name, -1, xmltag, -1))
|
||||
{
|
||||
knownTags[i].callback(this, editor, elementString.Get());
|
||||
|
||||
if (FALSE == knownTags[i].multiEntry)
|
||||
hitList[i] = TRUE;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceConnectionParser::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
|
||||
{
|
||||
elementString.Append(value);
|
||||
}
|
||||
|
||||
void DeviceConnectionParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
|
||||
{
|
||||
elementString.Clear();
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceConnectionParser
|
||||
START_DISPATCH;
|
||||
VCB(ONSTARTELEMENT, Event_XmlStartElement)
|
||||
VCB(ONENDELEMENT, Event_XmlEndElement)
|
||||
VCB(ONCHARDATA, Event_XmlCharData)
|
||||
VCB(ONERROR, Event_XmlError)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_PARSER_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_PARSER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../../xml/ifc_xmlreadercallback.h"
|
||||
|
||||
class obj_xml;
|
||||
|
||||
#define CONNECTION_TAG_MAX 2
|
||||
|
||||
class DeviceConnectionParser : public ifc_xmlreadercallback
|
||||
{
|
||||
public:
|
||||
DeviceConnectionParser();
|
||||
~DeviceConnectionParser();
|
||||
public:
|
||||
BOOL Begin(obj_xml *reader, ifc_xmlreaderparams *params);
|
||||
BOOL End(obj_xml *reader, ifc_deviceconnection **connection);
|
||||
|
||||
protected:
|
||||
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
|
||||
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
|
||||
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
|
||||
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
|
||||
|
||||
protected:
|
||||
friend static void DeviceConnectionParser_DisplayNameCb(DeviceConnectionParser *self, ifc_deviceconnectioneditor *editor, const wchar_t *value);
|
||||
friend static void DeviceConnectionParser_IconCb(DeviceConnectionParser *self, ifc_deviceconnectioneditor *editor, const wchar_t *value);
|
||||
|
||||
protected:
|
||||
StringBuilder elementString;
|
||||
ifc_deviceconnectioneditor *editor;
|
||||
BOOL hitList[CONNECTION_TAG_MAX];
|
||||
SIZE iconSize;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_CONNECTION_PARSER_HEADER
|
|
@ -0,0 +1,178 @@
|
|||
#include "main.h"
|
||||
#include "./deviceIconEditor.h"
|
||||
|
||||
|
||||
#define DEVICEICONEDITOR_PROP L"NullsoftDevicesIconEditorProp"
|
||||
|
||||
|
||||
static INT_PTR
|
||||
DeviceIconEditor_DialogProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
INT_PTR
|
||||
DeviceIconEditor_Show(HWND parentWindow, DeviceIconInfo *iconInfo)
|
||||
{
|
||||
if (NULL == iconInfo)
|
||||
return -1;
|
||||
|
||||
return WASABI_API_DIALOGBOXPARAMW((INT_PTR)IDD_ICON_EDITOR, parentWindow,
|
||||
DeviceIconEditor_DialogProc, (LPARAM)iconInfo);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceIconEditor_UpdateInfo(HWND hwnd)
|
||||
{
|
||||
DeviceIconInfo *iconInfo;
|
||||
HWND controlWindow;
|
||||
wchar_t *string;
|
||||
|
||||
iconInfo = (DeviceIconInfo*)GetProp(hwnd, DEVICEICONEDITOR_PROP);
|
||||
if (NULL == iconInfo)
|
||||
return;
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_PATH);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
String_Free(iconInfo->path);
|
||||
iconInfo->path = String_FromWindow(controlWindow);
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_WIDTH);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
string = String_FromWindow(controlWindow);
|
||||
if (NULL == string ||
|
||||
FALSE == StrToIntEx(string, STIF_DEFAULT, &iconInfo->width))
|
||||
{
|
||||
iconInfo->width = 0;
|
||||
}
|
||||
String_Free(string);
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_HEIGHT);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
string = String_FromWindow(controlWindow);
|
||||
if (NULL == string ||
|
||||
FALSE == StrToIntEx(string, STIF_DEFAULT, &iconInfo->height))
|
||||
{
|
||||
iconInfo->height = 0;
|
||||
}
|
||||
String_Free(string);
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR
|
||||
DeviceIconEditor_OnInitDialog(HWND hwnd, HWND focusWindow, LPARAM param)
|
||||
{
|
||||
DeviceIconInfo *iconInfo;
|
||||
HWND controlWindow;
|
||||
|
||||
iconInfo = (DeviceIconInfo*)param;
|
||||
SetProp(hwnd, DEVICEICONEDITOR_PROP, iconInfo);
|
||||
|
||||
if (NULL != iconInfo)
|
||||
{
|
||||
wchar_t buffer[64];
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_PATH);
|
||||
if (NULL != controlWindow)
|
||||
SetWindowText(controlWindow, iconInfo->path);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_WIDTH);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
_itow_s(iconInfo->width, buffer, 10);
|
||||
SetWindowText(controlWindow, buffer);
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_HEIGHT);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
_itow_s(iconInfo->height, buffer, 10);
|
||||
SetWindowText(controlWindow, buffer);
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceIconEditor_DisplayFileOpen(HWND hwnd)
|
||||
{
|
||||
wchar_t buffer[MAX_PATH * 2];
|
||||
OPENFILENAME ofn;
|
||||
HWND controlWindow;
|
||||
|
||||
buffer[0] = L'\0';
|
||||
|
||||
ZeroMemory(&ofn, sizeof(ofn));
|
||||
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = hwnd;
|
||||
ofn.lpstrFilter = L"Portable Network Graphics\0" L"*.png\0"
|
||||
L"\0";
|
||||
ofn.lpstrFile = buffer;
|
||||
ofn.nMaxFile = ARRAYSIZE(buffer);
|
||||
ofn.lpstrTitle = L"Load Icon";
|
||||
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
|
||||
|
||||
if (FALSE == GetOpenFileName(&ofn))
|
||||
return;
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_PATH);
|
||||
if (NULL != controlWindow)
|
||||
SetWindowText(controlWindow, buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceIconEditor_OnDestroy(HWND hwnd)
|
||||
{
|
||||
RemoveProp(hwnd, DEVICEICONEDITOR_PROP);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceIconEditor_OnCommand(HWND hwnd, INT commandId, INT eventId, HWND controlWindow)
|
||||
{
|
||||
switch(commandId)
|
||||
{
|
||||
case IDOK:
|
||||
switch(eventId)
|
||||
{
|
||||
case BN_CLICKED:
|
||||
DeviceIconEditor_UpdateInfo(hwnd);
|
||||
EndDialog(hwnd, IDOK);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IDCANCEL:
|
||||
switch(eventId)
|
||||
{
|
||||
case BN_CLICKED:
|
||||
EndDialog(hwnd, IDCANCEL);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IDC_BUTTON_BROWSE:
|
||||
switch(eventId)
|
||||
{
|
||||
case BN_CLICKED:
|
||||
DeviceIconEditor_DisplayFileOpen(hwnd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR
|
||||
DeviceIconEditor_DialogProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG: return DeviceIconEditor_OnInitDialog(hwnd, (HWND)wParam, lParam);
|
||||
case WM_DESTROY: DeviceIconEditor_OnDestroy(hwnd); return TRUE;
|
||||
case WM_COMMAND: DeviceIconEditor_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return TRUE;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ICON_EDITOR_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ICON_EDITOR_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
typedef struct DeviceIconInfo
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
wchar_t *path;
|
||||
} DeviceIconInfo;
|
||||
|
||||
INT_PTR
|
||||
DeviceIconEditor_Show(HWND parentWindow,
|
||||
DeviceIconInfo *iconInfo);
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_ICON_EDITOR_HEADER
|
|
@ -0,0 +1,75 @@
|
|||
#include "main.h"
|
||||
#include "./DeviceNodeParser.h"
|
||||
#include "../../xml/obj_xml.h"
|
||||
|
||||
DeviceNodeParser::DeviceNodeParser()
|
||||
: reader(NULL), test(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceNodeParser::~DeviceNodeParser()
|
||||
{
|
||||
End();
|
||||
}
|
||||
|
||||
|
||||
BOOL DeviceNodeParser::Begin(obj_xml *xmlReader, TestSuite *testSuite)
|
||||
{
|
||||
if (NULL != reader || NULL != test)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == xmlReader || NULL == testSuite)
|
||||
return FALSE;
|
||||
|
||||
reader = xmlReader;
|
||||
reader->AddRef();
|
||||
|
||||
test = testSuite;
|
||||
|
||||
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice", this);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void DeviceNodeParser::End()
|
||||
{
|
||||
if (NULL != reader)
|
||||
{
|
||||
reader->xmlreader_unregisterCallback(this);
|
||||
reader->Release();
|
||||
reader = NULL;
|
||||
}
|
||||
|
||||
if (NULL != test)
|
||||
test = NULL;
|
||||
}
|
||||
|
||||
|
||||
void DeviceNodeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
|
||||
{
|
||||
elementParser.Begin(reader, params);
|
||||
}
|
||||
|
||||
void DeviceNodeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
|
||||
{
|
||||
Device *result;
|
||||
if (FALSE != elementParser.End(reader, &result))
|
||||
{
|
||||
if (NULL != test)
|
||||
test->AddDevice(result);
|
||||
|
||||
result->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceNodeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
|
||||
{
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceNodeParser
|
||||
START_DISPATCH;
|
||||
VCB(ONSTARTELEMENT, Event_XmlStartElement)
|
||||
VCB(ONENDELEMENT, Event_XmlEndElement)
|
||||
VCB(ONERROR, Event_XmlError)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_NODE_PARSER_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_NODE_PARSER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../../xml/ifc_xmlreadercallback.h"
|
||||
#include "./deviceParser.h"
|
||||
|
||||
class obj_xml;
|
||||
|
||||
class DeviceNodeParser : public ifc_xmlreadercallback
|
||||
{
|
||||
|
||||
public:
|
||||
DeviceNodeParser();
|
||||
~DeviceNodeParser();
|
||||
|
||||
public:
|
||||
BOOL Begin(obj_xml *xmlReader, TestSuite *testSuite);
|
||||
void End();
|
||||
|
||||
protected:
|
||||
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
|
||||
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
|
||||
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
|
||||
|
||||
protected:
|
||||
obj_xml *reader;
|
||||
DeviceParser elementParser;
|
||||
TestSuite *test;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_NODE_PARSER_HEADER
|
|
@ -0,0 +1,306 @@
|
|||
#include "main.h"
|
||||
#include "./deviceParser.h"
|
||||
|
||||
#include "../../xml/obj_xml.h"
|
||||
|
||||
typedef void (*DEVICETAGCALLBACK)(DeviceParser* /*self*/, Device* /*device*/, const wchar_t* /*value*/);
|
||||
|
||||
typedef struct DEVICETAG
|
||||
{
|
||||
const wchar_t *name;
|
||||
BOOL multiEntry;
|
||||
DEVICETAGCALLBACK callback;
|
||||
} DEVICETAG;
|
||||
|
||||
|
||||
static void
|
||||
DeviceParser_ConnectionCb(DeviceParser *self, Device *device, const wchar_t *value)
|
||||
{
|
||||
char *connectionAnsi;
|
||||
|
||||
connectionAnsi = (NULL != value) ?
|
||||
String_ToAnsi(CP_UTF8, 0, value, -1, NULL, NULL) :
|
||||
NULL;
|
||||
|
||||
device->SetConnection(connectionAnsi);
|
||||
AnsiString_Free(connectionAnsi);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DeviceParser_DisplayNameCb(DeviceParser *self, Device *device, const wchar_t *value)
|
||||
{
|
||||
device->SetDisplayName(value);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceParser_IconCb(DeviceParser *self, Device *device, const wchar_t *value)
|
||||
{
|
||||
device->AddIcon(value, self->iconSize.cx, self->iconSize.cy);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceParser_TotalSpaceCb(DeviceParser *self, Device *device, const wchar_t *value)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
if (NULL == value)
|
||||
size = -1;
|
||||
else
|
||||
{
|
||||
LONGLONG lval;
|
||||
if (FALSE == StrToInt64Ex(value, STIF_DEFAULT, &lval))
|
||||
return;
|
||||
|
||||
size = (size_t)lval;
|
||||
}
|
||||
device->SetTotalSpace(size);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceParser_UsedSpaceCb(DeviceParser *self, Device *device, const wchar_t *value)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
if (NULL == value)
|
||||
size = -1;
|
||||
else
|
||||
{
|
||||
LONGLONG lval;
|
||||
if (FALSE == StrToInt64Ex(value, STIF_DEFAULT, &lval))
|
||||
return;
|
||||
|
||||
size = (size_t)lval;
|
||||
}
|
||||
device->SetUsedSpace(size);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceParser_HiddenCb(DeviceParser *self, Device *device, const wchar_t *value)
|
||||
{
|
||||
int hidden;
|
||||
if (FALSE != StrToIntEx(value, STIF_DEFAULT, &hidden))
|
||||
device->SetHidden(0 != hidden);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceParser_CommandCb(DeviceParser *self, Device *device, const wchar_t *value)
|
||||
{
|
||||
char *command;
|
||||
|
||||
if (FALSE != IS_STRING_EMPTY(value))
|
||||
return;
|
||||
command = String_ToAnsi(CP_UTF8, 0, value, -1, NULL, NULL);
|
||||
if (NULL != command)
|
||||
{
|
||||
device->AddCommand(command, self->commandFlags);
|
||||
AnsiString_Free(command);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DeviceParser_ModelCb(DeviceParser *self, Device *device, const wchar_t *value)
|
||||
{
|
||||
device->SetModel(value);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceParser_StatusCb(DeviceParser *self, Device *device, const wchar_t *value)
|
||||
{
|
||||
device->SetStatus(value);
|
||||
}
|
||||
|
||||
static const DEVICETAG knownTags[DEVICE_TAG_MAX] =
|
||||
{
|
||||
{L"connection", FALSE, DeviceParser_ConnectionCb},
|
||||
{L"displayName", FALSE, DeviceParser_DisplayNameCb},
|
||||
{L"icon", TRUE, DeviceParser_IconCb},
|
||||
{L"totalSpace", FALSE, DeviceParser_TotalSpaceCb},
|
||||
{L"usedSpace", FALSE, DeviceParser_UsedSpaceCb},
|
||||
{L"hidden", FALSE, DeviceParser_HiddenCb},
|
||||
{L"command", TRUE, DeviceParser_CommandCb},
|
||||
{L"model", FALSE, DeviceParser_ModelCb},
|
||||
{L"status", FALSE, DeviceParser_StatusCb},
|
||||
|
||||
};
|
||||
|
||||
DeviceParser::DeviceParser()
|
||||
: device(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceParser::~DeviceParser()
|
||||
{
|
||||
if (NULL != device)
|
||||
device->Release();
|
||||
}
|
||||
|
||||
BOOL DeviceParser::Begin(obj_xml *reader, ifc_xmlreaderparams *params)
|
||||
{
|
||||
const wchar_t *value;
|
||||
char *nameAnsi, *typeAnsi;
|
||||
if (NULL != device)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == reader || NULL == params)
|
||||
return FALSE;
|
||||
|
||||
value = params->getItemValue(L"name");
|
||||
nameAnsi = (NULL != value) ? String_ToAnsi(CP_UTF8, 0, value, -1, NULL, NULL) : NULL;
|
||||
|
||||
value = params->getItemValue(L"type");
|
||||
typeAnsi = (NULL != value) ? String_ToAnsi(CP_UTF8, 0, value, -1, NULL, NULL) : NULL;
|
||||
|
||||
if (NULL == nameAnsi ||
|
||||
NULL == typeAnsi ||
|
||||
FAILED(Device::CreateInstance(nameAnsi, typeAnsi, NULL, &device)))
|
||||
{
|
||||
device = NULL;
|
||||
}
|
||||
|
||||
AnsiString_Free(nameAnsi);
|
||||
AnsiString_Free(typeAnsi);
|
||||
|
||||
if (NULL == device)
|
||||
return FALSE;
|
||||
|
||||
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fconnection", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fdisplayName", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\ficon", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\ftotalSpace", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fusedSpace", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fhidden", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fcommand", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fmodel", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fdevices\fdevice\fstatus", this);
|
||||
ZeroMemory(hitList, sizeof(hitList));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DeviceParser::End(obj_xml *reader, Device **result)
|
||||
{
|
||||
if (NULL != reader)
|
||||
reader->xmlreader_unregisterCallback(this);
|
||||
|
||||
if (NULL == device)
|
||||
return FALSE;
|
||||
|
||||
if (NULL != result)
|
||||
{
|
||||
*result = device;
|
||||
device->AddRef();
|
||||
}
|
||||
|
||||
device->Release();
|
||||
device = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void DeviceParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
|
||||
{
|
||||
elementString.Clear();
|
||||
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, L"icon", -1, xmltag, -1))
|
||||
{
|
||||
const wchar_t *sVal;
|
||||
int iVal;
|
||||
|
||||
sVal = params->getItemValue(L"width");
|
||||
if (NULL == sVal ||
|
||||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
|
||||
{
|
||||
iVal = 0;
|
||||
}
|
||||
|
||||
iconSize.cx = iVal;
|
||||
|
||||
sVal = params->getItemValue(L"height");
|
||||
if (NULL == sVal ||
|
||||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
|
||||
{
|
||||
iVal = 0;
|
||||
}
|
||||
|
||||
iconSize.cy = iVal;
|
||||
}
|
||||
else if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, L"command", -1, xmltag, -1))
|
||||
{
|
||||
const wchar_t *sVal;
|
||||
int iVal;
|
||||
|
||||
commandFlags = DeviceCommandFlag_None;
|
||||
|
||||
sVal = params->getItemValue(L"primary");
|
||||
if (FALSE == IS_STRING_EMPTY(sVal) &&
|
||||
FALSE != StrToIntEx(sVal, STIF_DEFAULT, &iVal) &&
|
||||
0 != iVal)
|
||||
{
|
||||
commandFlags |= DeviceCommandFlag_Primary;
|
||||
}
|
||||
|
||||
sVal = params->getItemValue(L"group");
|
||||
if (FALSE == IS_STRING_EMPTY(sVal) &&
|
||||
FALSE != StrToIntEx(sVal, STIF_DEFAULT, &iVal) &&
|
||||
0 != iVal)
|
||||
{
|
||||
commandFlags |= DeviceCommandFlag_Group;
|
||||
}
|
||||
|
||||
sVal = params->getItemValue(L"disabled");
|
||||
if (FALSE == IS_STRING_EMPTY(sVal) &&
|
||||
FALSE != StrToIntEx(sVal, STIF_DEFAULT, &iVal) &&
|
||||
0 != iVal)
|
||||
{
|
||||
commandFlags |= DeviceCommandFlag_Disabled;
|
||||
}
|
||||
|
||||
sVal = params->getItemValue(L"hidden");
|
||||
if (FALSE == IS_STRING_EMPTY(sVal) &&
|
||||
FALSE != StrToIntEx(sVal, STIF_DEFAULT, &iVal) &&
|
||||
0 != iVal)
|
||||
{
|
||||
commandFlags |= DeviceCommandFlag_Hidden;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DeviceParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
|
||||
{
|
||||
if (NULL == device)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < DEVICE_TAG_MAX; i++)
|
||||
{
|
||||
if (FALSE == hitList[i] &&
|
||||
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, knownTags[i].name, -1, xmltag, -1))
|
||||
{
|
||||
knownTags[i].callback(this, device, elementString.Get());
|
||||
|
||||
if (FALSE == knownTags[i].multiEntry)
|
||||
hitList[i] = TRUE;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceParser::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
|
||||
{
|
||||
elementString.Append(value);
|
||||
}
|
||||
|
||||
void DeviceParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
|
||||
{
|
||||
elementString.Clear();
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceParser
|
||||
START_DISPATCH;
|
||||
VCB(ONSTARTELEMENT, Event_XmlStartElement)
|
||||
VCB(ONENDELEMENT, Event_XmlEndElement)
|
||||
VCB(ONCHARDATA, Event_XmlCharData)
|
||||
VCB(ONERROR, Event_XmlError)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_PARSER_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_PARSER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../../xml/ifc_xmlreadercallback.h"
|
||||
#include "./device.h"
|
||||
|
||||
class obj_xml;
|
||||
|
||||
#define DEVICE_TAG_MAX 9
|
||||
|
||||
class DeviceParser : public ifc_xmlreadercallback
|
||||
{
|
||||
public:
|
||||
DeviceParser();
|
||||
~DeviceParser();
|
||||
public:
|
||||
BOOL Begin(obj_xml *reader, ifc_xmlreaderparams *params);
|
||||
BOOL End(obj_xml *reader, Device **result);
|
||||
|
||||
protected:
|
||||
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
|
||||
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
|
||||
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
|
||||
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
|
||||
protected:
|
||||
friend static void DeviceParser_IconCb(DeviceParser *self, Device *device, const wchar_t *value);
|
||||
friend static void DeviceParser_ConnectionCb(DeviceParser *self, Device *device, const wchar_t *value);
|
||||
friend static void DeviceParser_DisplayNameCb(DeviceParser *self, Device *device, const wchar_t *value);
|
||||
friend static void DeviceParser_TotalSpaceCb(DeviceParser *self, Device *device, const wchar_t *value);
|
||||
friend static void DeviceParser_UsedSpaceCb(DeviceParser *self, Device *device, const wchar_t *value);
|
||||
friend static void DeviceParser_HiddenCb(DeviceParser *self, Device *device, const wchar_t *value);
|
||||
friend static void DeviceParser_CommandCb(DeviceParser *self, Device *device, const wchar_t *value);
|
||||
friend static void DeviceParser_ModelCb(DeviceParser *self, Device *device, const wchar_t *value);
|
||||
friend static void DeviceParser_StatusCb(DeviceParser *self, Device *device, const wchar_t *value);
|
||||
|
||||
protected:
|
||||
StringBuilder elementString;
|
||||
Device *device;
|
||||
BOOL hitList[DEVICE_TAG_MAX];
|
||||
SIZE iconSize;
|
||||
DeviceCommandFlags commandFlags;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_PARSER_HEADER
|
|
@ -0,0 +1,75 @@
|
|||
#include "main.h"
|
||||
#include "./DeviceTypeNodeParser.h"
|
||||
#include "../../xml/obj_xml.h"
|
||||
|
||||
DeviceTypeNodeParser::DeviceTypeNodeParser()
|
||||
: reader(NULL), test(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceTypeNodeParser::~DeviceTypeNodeParser()
|
||||
{
|
||||
End();
|
||||
}
|
||||
|
||||
|
||||
BOOL DeviceTypeNodeParser::Begin(obj_xml *xmlReader, TestSuite *testSuite)
|
||||
{
|
||||
if (NULL != reader || NULL != test)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == xmlReader || NULL == testSuite)
|
||||
return FALSE;
|
||||
|
||||
reader = xmlReader;
|
||||
reader->AddRef();
|
||||
|
||||
test = testSuite;
|
||||
|
||||
reader->xmlreader_registerCallback(L"testprovider\ftypes\ftype", this);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void DeviceTypeNodeParser::End()
|
||||
{
|
||||
if (NULL != reader)
|
||||
{
|
||||
reader->xmlreader_unregisterCallback(this);
|
||||
reader->Release();
|
||||
reader = NULL;
|
||||
}
|
||||
|
||||
if (NULL != test)
|
||||
test = NULL;
|
||||
}
|
||||
|
||||
|
||||
void DeviceTypeNodeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
|
||||
{
|
||||
elementParser.Begin(reader, params);
|
||||
}
|
||||
|
||||
void DeviceTypeNodeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
|
||||
{
|
||||
ifc_devicetype *result;
|
||||
if (FALSE != elementParser.End(reader, &result))
|
||||
{
|
||||
if (NULL != test)
|
||||
test->AddType(result);
|
||||
|
||||
result->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceTypeNodeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
|
||||
{
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceTypeNodeParser
|
||||
START_DISPATCH;
|
||||
VCB(ONSTARTELEMENT, Event_XmlStartElement)
|
||||
VCB(ONENDELEMENT, Event_XmlEndElement)
|
||||
VCB(ONERROR, Event_XmlError)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_NODE_PARSER_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_NODE_PARSER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../../xml/ifc_xmlreadercallback.h"
|
||||
#include "./deviceTypeParser.h"
|
||||
|
||||
class obj_xml;
|
||||
|
||||
class DeviceTypeNodeParser : public ifc_xmlreadercallback
|
||||
{
|
||||
|
||||
public:
|
||||
DeviceTypeNodeParser();
|
||||
~DeviceTypeNodeParser();
|
||||
|
||||
public:
|
||||
BOOL Begin(obj_xml *xmlReader, TestSuite *testSuite);
|
||||
void End();
|
||||
|
||||
protected:
|
||||
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
|
||||
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
|
||||
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
|
||||
|
||||
protected:
|
||||
obj_xml *reader;
|
||||
DeviceTypeParser elementParser;
|
||||
TestSuite *test;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_NODE_PARSER_HEADER
|
|
@ -0,0 +1,182 @@
|
|||
#include "main.h"
|
||||
#include "./deviceTypeParser.h"
|
||||
|
||||
#include "../../xml/obj_xml.h"
|
||||
|
||||
typedef void (*TYPETAGCALLBACK)(DeviceTypeParser* /*self*/, ifc_devicetypeeditor* /*editor*/, const wchar_t* /*value*/);
|
||||
|
||||
typedef struct TYPETAG
|
||||
{
|
||||
const wchar_t *name;
|
||||
BOOL multiEntry;
|
||||
TYPETAGCALLBACK callback;
|
||||
} TYPETAG;
|
||||
|
||||
static void
|
||||
DeviceTypeParser_DisplayNameCb(DeviceTypeParser *self, ifc_devicetypeeditor *editor, const wchar_t *value)
|
||||
{
|
||||
editor->SetDisplayName(value);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceTypeParser_IconCb(DeviceTypeParser *self, ifc_devicetypeeditor *editor, const wchar_t *value)
|
||||
{
|
||||
ifc_deviceiconstore *iconStore;
|
||||
if (SUCCEEDED(editor->GetIconStore(&iconStore)))
|
||||
{
|
||||
iconStore->Add(value, self->iconSize.cx, self->iconSize.cy, TRUE);
|
||||
iconStore->Release();
|
||||
}
|
||||
}
|
||||
|
||||
static const TYPETAG knownTags[TYPE_TAG_MAX] =
|
||||
{
|
||||
{L"displayName", FALSE, DeviceTypeParser_DisplayNameCb},
|
||||
{L"icon", TRUE, DeviceTypeParser_IconCb},
|
||||
};
|
||||
|
||||
DeviceTypeParser::DeviceTypeParser()
|
||||
: editor(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceTypeParser::~DeviceTypeParser()
|
||||
{
|
||||
if (NULL != editor)
|
||||
editor->Release();
|
||||
}
|
||||
|
||||
BOOL DeviceTypeParser::Begin(obj_xml *reader, ifc_xmlreaderparams *params)
|
||||
{
|
||||
const wchar_t *name;
|
||||
ifc_devicetype *type;
|
||||
char *nameAnsi;
|
||||
|
||||
if (NULL != editor)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == reader || NULL == params)
|
||||
return FALSE;
|
||||
|
||||
|
||||
name = params->getItemValue(L"name");
|
||||
if (NULL == name)
|
||||
return FALSE;
|
||||
|
||||
nameAnsi = String_ToAnsi(CP_UTF8, 0, name, -1, NULL, NULL);
|
||||
if (NULL == nameAnsi)
|
||||
return FALSE;
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
SUCCEEDED(WASABI_API_DEVICES->CreateType(nameAnsi, &type)))
|
||||
{
|
||||
if(FAILED(type->QueryInterface(IFC_DeviceTypeEditor, (void**)&editor)))
|
||||
editor = NULL;
|
||||
|
||||
type->Release();
|
||||
}
|
||||
|
||||
AnsiString_Free(nameAnsi);
|
||||
|
||||
if (NULL == editor)
|
||||
return FALSE;
|
||||
|
||||
reader->xmlreader_registerCallback(L"testprovider\ftypes\ftype\fdisplayName", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\ftypes\ftype\ficon", this);
|
||||
ZeroMemory(hitList, sizeof(hitList));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DeviceTypeParser::End(obj_xml *reader, ifc_devicetype **deviceType)
|
||||
{
|
||||
BOOL result;
|
||||
|
||||
if (NULL != reader)
|
||||
reader->xmlreader_unregisterCallback(this);
|
||||
|
||||
if (NULL == editor)
|
||||
return FALSE;
|
||||
|
||||
if (NULL != deviceType)
|
||||
{
|
||||
if (FAILED(editor->QueryInterface(IFC_DeviceType, (void**)deviceType)))
|
||||
result = FALSE;
|
||||
else
|
||||
result = TRUE;
|
||||
}
|
||||
else
|
||||
result = TRUE;
|
||||
|
||||
editor->Release();
|
||||
editor = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DeviceTypeParser::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
|
||||
{
|
||||
elementString.Clear();
|
||||
|
||||
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, L"icon", -1, xmltag, -1))
|
||||
{
|
||||
const wchar_t *sVal;
|
||||
int iVal;
|
||||
|
||||
sVal = params->getItemValue(L"width");
|
||||
if (NULL == sVal ||
|
||||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
|
||||
{
|
||||
iVal = 0;
|
||||
}
|
||||
|
||||
iconSize.cx = iVal;
|
||||
|
||||
sVal = params->getItemValue(L"height");
|
||||
if (NULL == sVal ||
|
||||
FALSE == StrToIntEx(sVal, STIF_DEFAULT, &iVal))
|
||||
{
|
||||
iVal = 0;
|
||||
}
|
||||
|
||||
iconSize.cy = iVal;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceTypeParser::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
|
||||
{
|
||||
if (NULL == editor)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < TYPE_TAG_MAX; i++)
|
||||
{
|
||||
if (FALSE == hitList[i] &&
|
||||
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, knownTags[i].name, -1, xmltag, -1))
|
||||
{
|
||||
knownTags[i].callback(this, editor, elementString.Get());
|
||||
|
||||
if (FALSE == knownTags[i].multiEntry)
|
||||
hitList[i] = TRUE;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceTypeParser::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
|
||||
{
|
||||
elementString.Append(value);
|
||||
}
|
||||
|
||||
void DeviceTypeParser::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
|
||||
{
|
||||
elementString.Clear();
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceTypeParser
|
||||
START_DISPATCH;
|
||||
VCB(ONSTARTELEMENT, Event_XmlStartElement)
|
||||
VCB(ONENDELEMENT, Event_XmlEndElement)
|
||||
VCB(ONCHARDATA, Event_XmlCharData)
|
||||
VCB(ONERROR, Event_XmlError)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_PARSER_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_PARSER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../../xml/ifc_xmlreadercallback.h"
|
||||
|
||||
class obj_xml;
|
||||
|
||||
#define TYPE_TAG_MAX 2
|
||||
|
||||
class DeviceTypeParser : public ifc_xmlreadercallback
|
||||
{
|
||||
public:
|
||||
DeviceTypeParser();
|
||||
~DeviceTypeParser();
|
||||
public:
|
||||
BOOL Begin(obj_xml *reader, ifc_xmlreaderparams *params);
|
||||
BOOL End(obj_xml *reader, ifc_devicetype **deviceType);
|
||||
|
||||
protected:
|
||||
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
|
||||
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
|
||||
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
|
||||
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
|
||||
|
||||
protected:
|
||||
friend static void DeviceTypeParser_DisplayNameCb(DeviceTypeParser *self, ifc_devicetypeeditor *editor, const wchar_t *value);
|
||||
friend static void DeviceTypeParser_IconCb(DeviceTypeParser *self, ifc_devicetypeeditor *editor, const wchar_t *value);
|
||||
|
||||
protected:
|
||||
StringBuilder elementString;
|
||||
ifc_devicetypeeditor *editor;
|
||||
BOOL hitList[TYPE_TAG_MAX];
|
||||
SIZE iconSize;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_TYPE_PARSER_HEADER
|
994
Src/Plugins/Library/ml_devices/gen_deviceprovider/deviceView.cpp
Normal file
994
Src/Plugins/Library/ml_devices/gen_deviceprovider/deviceView.cpp
Normal file
|
@ -0,0 +1,994 @@
|
|||
#include "main.h"
|
||||
#include "./deviceView.h"
|
||||
#include <wincodec.h>
|
||||
|
||||
#include <commctrl.h>
|
||||
#include <strsafe.h>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#define DEVICEVIEW_PROP L"NullsoftDevicesViewProp"
|
||||
static ATOM DEVICEVIEW_ATOM = 0;
|
||||
|
||||
typedef struct DeviceView
|
||||
{
|
||||
Device *device;
|
||||
} DeviceView;
|
||||
|
||||
|
||||
typedef std::vector<DeviceIconInfo*> DeviceIconInfoList;
|
||||
|
||||
static INT_PTR
|
||||
DeviceView_DialogProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
|
||||
#define DEVICEVIEW(_hwnd) ((DeviceView*)GetPropW((_hwnd), MAKEINTATOM(DEVICEVIEW_ATOM)))
|
||||
#define DEVICEVIEW_RET_VOID(_view, _hwnd) { (_view) = DEVICEVIEW((_hwnd)); if (NULL == (_view)) return; }
|
||||
#define DEVICEVIEW_RET_VAL(_view, _hwnd, _error) { (_view) = DEVICEVIEW((_hwnd)); if (NULL == (_view)) return (_error); }
|
||||
|
||||
|
||||
|
||||
static HBITMAP
|
||||
DeviceView_HBitmapFromWicSource(IWICBitmapSource *wicSource)
|
||||
{
|
||||
HRESULT hr;
|
||||
HBITMAP bitmap;
|
||||
BITMAPINFO bitmapInfo;
|
||||
unsigned int width, height;
|
||||
void *pixelData = NULL;
|
||||
HDC windowDC;
|
||||
unsigned int strideSize, imageSize;
|
||||
|
||||
if (NULL == wicSource)
|
||||
return NULL;
|
||||
|
||||
hr = wicSource->GetSize(&width, &height);
|
||||
if (FAILED(hr))
|
||||
return NULL;
|
||||
|
||||
ZeroMemory(&bitmapInfo, sizeof(bitmapInfo));
|
||||
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfo.bmiHeader.biWidth = width;
|
||||
bitmapInfo.bmiHeader.biHeight = -(LONG)height;
|
||||
bitmapInfo.bmiHeader.biPlanes = 1;
|
||||
bitmapInfo.bmiHeader.biBitCount = 32;
|
||||
bitmapInfo.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
windowDC = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE);
|
||||
|
||||
bitmap = CreateDIBSection(windowDC, &bitmapInfo, DIB_RGB_COLORS, &pixelData, NULL, 0);
|
||||
|
||||
if (NULL != windowDC)
|
||||
ReleaseDC(NULL, windowDC);
|
||||
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
hr = UIntMult(width, sizeof(DWORD), &strideSize);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = UIntMult(strideSize, height, &imageSize);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = wicSource->CopyPixels(NULL, strideSize, imageSize, (BYTE*)pixelData);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DeleteObject(bitmap);
|
||||
bitmap = NULL;
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static HBITMAP
|
||||
DeviceView_LoadIcon(const wchar_t *path)
|
||||
{
|
||||
IWICImagingFactory *wicFactory;
|
||||
IWICBitmapDecoder *wicDecoder;
|
||||
|
||||
HRESULT hr;
|
||||
HBITMAP bitmap;
|
||||
|
||||
hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
|
||||
IID_PPV_ARGS(&wicFactory));
|
||||
|
||||
if (FAILED(hr))
|
||||
return NULL;
|
||||
|
||||
bitmap = NULL;
|
||||
|
||||
hr = wicFactory->CreateDecoderFromFilename(path, NULL, GENERIC_READ,
|
||||
WICDecodeMetadataCacheOnDemand, &wicDecoder);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IWICBitmapFrameDecode *wicFrame;
|
||||
hr = wicDecoder->GetFrame(0, &wicFrame);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
IWICBitmapSource *wicSource;
|
||||
hr = wicFrame->QueryInterface(IID_IWICBitmapSource,
|
||||
reinterpret_cast<void **>(&wicSource));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
WICPixelFormatGUID pixelFormat;
|
||||
hr = wicSource->GetPixelFormat(&pixelFormat);
|
||||
if (FAILED(hr) ||
|
||||
(GUID_WICPixelFormat32bppPBGRA != pixelFormat &&
|
||||
GUID_WICPixelFormat32bppBGR != pixelFormat &&
|
||||
GUID_WICPixelFormat32bppBGRA != pixelFormat &&
|
||||
GUID_WICPixelFormat32bppRGBA != pixelFormat &&
|
||||
GUID_WICPixelFormat32bppPRGBA != pixelFormat))
|
||||
{
|
||||
// try to convert
|
||||
IWICFormatConverter *wicConverter;
|
||||
hr = wicFactory->CreateFormatConverter(&wicConverter);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = wicConverter->Initialize(wicSource, GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeCustom);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IWICBitmapSource *wicConvertedSource;
|
||||
hr = wicConverter->QueryInterface(IID_IWICBitmapSource,
|
||||
reinterpret_cast<void **>(&wicConvertedSource));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
wicSource->Release();
|
||||
wicSource = wicConvertedSource;
|
||||
}
|
||||
}
|
||||
wicConverter->Release();
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
bitmap = DeviceView_HBitmapFromWicSource(wicSource);
|
||||
|
||||
wicSource->Release();
|
||||
}
|
||||
wicFrame->Release();
|
||||
}
|
||||
wicDecoder->Release();
|
||||
}
|
||||
|
||||
|
||||
wicFactory->Release();
|
||||
return bitmap;
|
||||
|
||||
}
|
||||
|
||||
HWND
|
||||
DeviceView_CreateWindow(HWND parentWindow, Device *device)
|
||||
{
|
||||
HWND hwnd;
|
||||
|
||||
if (NULL == device)
|
||||
return NULL;
|
||||
|
||||
if (0 == DEVICEVIEW_ATOM)
|
||||
{
|
||||
DEVICEVIEW_ATOM = GlobalAddAtom(DEVICEVIEW_PROP);
|
||||
if (0 == DEVICEVIEW_ATOM)
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
hwnd = WASABI_API_CREATEDIALOGPARAMW((INT_PTR)IDD_DEVICE_VIEW, parentWindow,
|
||||
DeviceView_DialogProc, (LPARAM)device);
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_InitCapacity(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
HWND controlWindow;
|
||||
uint64_t totalSpace, usedSpace;
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
if (NULL != self->device)
|
||||
{
|
||||
if (FAILED(self->device->GetTotalSpace(&totalSpace)))
|
||||
totalSpace = 0;
|
||||
|
||||
if (FAILED(self->device->GetUsedSpace(&usedSpace)))
|
||||
usedSpace = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
totalSpace = 0;
|
||||
usedSpace = 0;
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_SPIN_TOTALSPACE);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
SendMessage(controlWindow, UDM_SETRANGE32, (WPARAM)0, (LPARAM)0xFFFFFF);
|
||||
SendMessage(controlWindow, UDM_SETPOS32, (WPARAM)0, (LPARAM)totalSpace);
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_SPIN_USEDSPACE);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
SendMessage(controlWindow, UDM_SETRANGE32, (WPARAM)0, (LPARAM)totalSpace);
|
||||
SendMessage(controlWindow, UDM_SETPOS32, (WPARAM)0, (LPARAM)usedSpace);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
DeviceView_CompareDeviceIconInfo(const void *elem1, const void *elem2)
|
||||
{
|
||||
DeviceIconInfo *info1;
|
||||
DeviceIconInfo *info2;
|
||||
|
||||
info1 = *((DeviceIconInfo**)elem1);
|
||||
info2 = *((DeviceIconInfo**)elem2);
|
||||
|
||||
if (NULL == info1 || NULL == info2)
|
||||
return (int)(info1 - info2);
|
||||
if (info1->width != info2->width)
|
||||
return (int)(info1->width - info2->width);
|
||||
|
||||
if (info1->height != info2->height)
|
||||
return (int)(info1->height - info2->height);
|
||||
|
||||
if (NULL == info1->path || NULL == info2->path)
|
||||
return (int)(info1->path - info2->path);
|
||||
|
||||
return CompareString(CSTR_INVARIANT, NORM_IGNORECASE, info1->path, -1, info2->path, -1) - 2;
|
||||
}
|
||||
|
||||
static int
|
||||
DeviceView_CompareDeviceIconInfo_V2(const void* elem1, const void* elem2)
|
||||
{
|
||||
return DeviceView_CompareDeviceIconInfo(elem1, elem2) < 0;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
DeviceView_EnumerateIcons(const wchar_t *path, unsigned int width, unsigned int height, void *user)
|
||||
{
|
||||
DeviceIconInfo *info;
|
||||
|
||||
DeviceIconInfoList *list = (DeviceIconInfoList*)user;
|
||||
if( NULL == list)
|
||||
return FALSE;
|
||||
|
||||
info = (DeviceIconInfo*)malloc(sizeof(DeviceIconInfo));
|
||||
if (NULL != info)
|
||||
{
|
||||
info->height = height;
|
||||
info->width = width;
|
||||
info->path = String_Duplicate(path);
|
||||
|
||||
list->push_back(info);
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_DestroyIcons(HWND hwnd)
|
||||
{
|
||||
HWND controlWindow;
|
||||
int count, index;
|
||||
DeviceIconInfo *info;
|
||||
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ICONS);
|
||||
if (NULL == controlWindow)
|
||||
return;
|
||||
|
||||
count = (int)SendMessage(controlWindow, CB_GETCOUNT, 0, 0L);
|
||||
for(index = 0; index < count; index++)
|
||||
{
|
||||
info = (DeviceIconInfo*)SendMessage(controlWindow, CB_GETITEMDATA, index, 0L);
|
||||
if (CB_ERR != (INT_PTR)info)
|
||||
{
|
||||
String_Free(info->path);
|
||||
free(info);
|
||||
}
|
||||
}
|
||||
|
||||
SendMessage(controlWindow, CB_RESETCONTENT, 0, 0L);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_STATIC_PREVIEWICON);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
bitmap = (HBITMAP)SendMessage(controlWindow, STM_GETIMAGE, IMAGE_BITMAP, 0L);
|
||||
if(NULL != bitmap)
|
||||
DeleteObject(bitmap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_InitIcons(HWND hwnd, const wchar_t *selectPath)
|
||||
{
|
||||
DeviceView *self;
|
||||
DeviceIconInfoList list;
|
||||
HWND controlWindow;
|
||||
wchar_t buffer[2048];
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
DeviceView_DestroyIcons(hwnd);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ICONS);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
size_t index, count;
|
||||
int iItem, iSelect;
|
||||
DeviceIconInfo *info;
|
||||
|
||||
if (NULL != self->device)
|
||||
{
|
||||
self->device->EnumerateIcons(DeviceView_EnumerateIcons, &list);
|
||||
}
|
||||
|
||||
count = list.size();
|
||||
//qsort(list.begin(), count, sizeof(DeviceIconInfo**), DeviceView_CompareDeviceIconInfo);
|
||||
std::sort(list.begin(), list.end(), DeviceView_CompareDeviceIconInfo_V2);
|
||||
|
||||
iSelect = 0;
|
||||
|
||||
for(index = 0; index < count; index++)
|
||||
{
|
||||
info = list[index];
|
||||
if (1 == info->width && 1 == info->height)
|
||||
{
|
||||
StringCchPrintf(buffer, ARRAYSIZE(buffer), L"%s",
|
||||
info->path);
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCchPrintf(buffer, ARRAYSIZE(buffer), L"[%dx%d] - %s",
|
||||
info->width, info->height, info->path);
|
||||
}
|
||||
|
||||
iItem = (int)SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)buffer);
|
||||
if (CB_ERR != iItem)
|
||||
{
|
||||
if (CB_ERR == (int)SendMessage(controlWindow, CB_SETITEMDATA, index, (LPARAM)info))
|
||||
{
|
||||
SendMessage(controlWindow, CB_DELETESTRING, index, 0L);
|
||||
iItem = CB_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (CB_ERR == iItem)
|
||||
{
|
||||
free(info);
|
||||
}
|
||||
else if (NULL != selectPath &&
|
||||
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE,
|
||||
info->path, -1, selectPath, -1))
|
||||
{
|
||||
iSelect = iItem;
|
||||
}
|
||||
}
|
||||
|
||||
iItem = (int)SendMessage(controlWindow, CB_GETCOUNT, 0, 0L);
|
||||
if (CB_ERR == iItem)
|
||||
iItem = 0;
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_EDITICON), (0 != iItem));
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_REMOVEICON),(0 != iItem));
|
||||
|
||||
|
||||
SendMessage(controlWindow, CB_SETCURSEL, iSelect, 0L);
|
||||
PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_COMBO_ICONS, CBN_SELENDOK), (LPARAM)controlWindow);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_NewIcon(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
DeviceIconInfo info;
|
||||
INT_PTR result;
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
ZeroMemory(&info, sizeof(info));
|
||||
|
||||
result = DeviceIconEditor_Show(hwnd, &info);
|
||||
if (IDOK == result)
|
||||
{
|
||||
if (NULL != self->device &&
|
||||
SUCCEEDED(self->device->AddIcon(info.path, info.width, info.height)))
|
||||
{
|
||||
DeviceView_InitIcons(hwnd, info.path);
|
||||
}
|
||||
|
||||
String_Free(info.path);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_RemoveIcon(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
DeviceIconInfo *info;
|
||||
int index, count;
|
||||
HWND controlWindow;
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ICONS);
|
||||
if (NULL == controlWindow)
|
||||
return;
|
||||
|
||||
index = (int)SendMessage(controlWindow, CB_GETCURSEL, 0, 0L);
|
||||
if (CB_ERR == index)
|
||||
return;
|
||||
|
||||
info = (DeviceIconInfo*)SendMessage(controlWindow, CB_GETITEMDATA, index, 0L);
|
||||
if (CB_ERR != (INT_PTR)info)
|
||||
{
|
||||
if (NULL != self->device)
|
||||
self->device->RemoveIcon(info->width, info->height);
|
||||
|
||||
String_Free(info->path);
|
||||
free(info);
|
||||
}
|
||||
|
||||
SendMessage(controlWindow, CB_DELETESTRING, index, 0L);
|
||||
|
||||
count = (int)SendMessage(controlWindow, CB_GETCOUNT, 0, 0L);
|
||||
if (count > 0)
|
||||
{
|
||||
if (index > count)
|
||||
index = count - 1;
|
||||
SendMessage(controlWindow, CB_SETCURSEL, index, 0L);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessage(controlWindow, CB_SETCURSEL, -1, 0L);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_EDITICON),FALSE);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_REMOVEICON),FALSE);
|
||||
}
|
||||
|
||||
PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_COMBO_ICONS, CBN_SELENDOK), (LPARAM)controlWindow);
|
||||
|
||||
UpdateWindow(controlWindow);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_EditIcon(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
DeviceIconInfo *info;
|
||||
int index;
|
||||
unsigned int width, height;
|
||||
HWND controlWindow;
|
||||
INT_PTR result;
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ICONS);
|
||||
if (NULL == controlWindow)
|
||||
return;
|
||||
|
||||
index = (int)SendMessage(controlWindow, CB_GETCURSEL, 0, 0L);
|
||||
if (CB_ERR == index)
|
||||
return;
|
||||
|
||||
info = (DeviceIconInfo*)SendMessage(controlWindow, CB_GETITEMDATA, index, 0L);
|
||||
if (CB_ERR == (INT_PTR)info)
|
||||
return;
|
||||
width = info->width;
|
||||
height = info->height;
|
||||
|
||||
result = DeviceIconEditor_Show(hwnd, info);
|
||||
if (IDOK == result)
|
||||
{
|
||||
if (NULL != self->device)
|
||||
{
|
||||
self->device->RemoveIcon(width, height);
|
||||
self->device->AddIcon(info->path, info->width, info->height);
|
||||
DeviceView_InitIcons(hwnd, info->path);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateWindow(controlWindow);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_InitView(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
HWND controlWindow;
|
||||
wchar_t buffer[1024];
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_NAME);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
if (NULL == self->device ||
|
||||
0 == MultiByteToWideChar(CP_UTF8, 0, self->device->GetName(), -1, buffer, ARRAYSIZE(buffer)))
|
||||
{
|
||||
StringCchCopy(buffer, ARRAYSIZE(buffer), L"<unknown>");
|
||||
}
|
||||
SetWindowText(controlWindow, buffer);
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_TITLE);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
if (NULL == self->device ||
|
||||
FAILED(self->device->GetDisplayName(buffer, ARRAYSIZE(buffer))))
|
||||
{
|
||||
StringCchCopy(buffer, ARRAYSIZE(buffer), L"<unknown>");
|
||||
}
|
||||
SetWindowText(controlWindow, buffer);
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_TYPE);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
buffer[0] = L'\0';
|
||||
|
||||
if (NULL != self->device)
|
||||
{
|
||||
const char *typeName;
|
||||
ifc_devicetype *type;
|
||||
|
||||
typeName = self->device->GetType();
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
S_OK == WASABI_API_DEVICES->TypeFind(typeName, &type))
|
||||
{
|
||||
if (FAILED(type->GetDisplayName(buffer, ARRAYSIZE(buffer))))
|
||||
buffer[0] = L'\0';
|
||||
|
||||
type->Release();
|
||||
}
|
||||
|
||||
if (L'\0' == *buffer)
|
||||
MultiByteToWideChar(CP_UTF8, 0, typeName, -1, buffer, ARRAYSIZE(buffer));
|
||||
}
|
||||
|
||||
if (L'\0' == *buffer)
|
||||
StringCchCopy(buffer, ARRAYSIZE(buffer), L"<unknown>");
|
||||
|
||||
SetWindowText(controlWindow, buffer);
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_CONNECTION);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
buffer[0] = L'\0';
|
||||
|
||||
if (NULL != self->device)
|
||||
{
|
||||
const char *connectionName;
|
||||
ifc_deviceconnection *connection;
|
||||
|
||||
connectionName = self->device->GetConnection();
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
S_OK == WASABI_API_DEVICES->ConnectionFind(connectionName, &connection))
|
||||
{
|
||||
if (FAILED(connection->GetDisplayName(buffer, ARRAYSIZE(buffer))))
|
||||
buffer[0] = L'\0';
|
||||
|
||||
connection->Release();
|
||||
}
|
||||
|
||||
if (L'\0' == *buffer)
|
||||
MultiByteToWideChar(CP_UTF8, 0, connectionName, -1, buffer, ARRAYSIZE(buffer));
|
||||
}
|
||||
|
||||
if (L'\0' == *buffer)
|
||||
StringCchCopy(buffer, ARRAYSIZE(buffer), L"<unknown>");
|
||||
|
||||
SetWindowText(controlWindow, buffer);
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ATTACHED);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
SendMessage(controlWindow, CB_RESETCONTENT, 0, 0L);
|
||||
|
||||
if (NULL != self->device)
|
||||
{
|
||||
const wchar_t *searchString;
|
||||
|
||||
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"Yes");
|
||||
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"No");
|
||||
|
||||
if (FALSE == self->device->GetAttached())
|
||||
searchString = L"No";
|
||||
else
|
||||
searchString = L"Yes";
|
||||
|
||||
SendMessage(controlWindow, CB_SELECTSTRING, -1, (LPARAM)searchString);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"<unknown>");
|
||||
SendMessage(controlWindow, CB_SETCURSEL, 0, 0L);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_COMBO_VISIBLE);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
SendMessage(controlWindow, CB_RESETCONTENT, 0, 0L);
|
||||
|
||||
if (NULL != self->device)
|
||||
{
|
||||
const wchar_t *searchString;
|
||||
|
||||
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"Yes");
|
||||
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"No");
|
||||
|
||||
if (FALSE != self->device->GetHidden())
|
||||
searchString = L"No";
|
||||
else
|
||||
searchString = L"Yes";
|
||||
|
||||
SendMessage(controlWindow, CB_SELECTSTRING, -1, (LPARAM)searchString);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessage(controlWindow, CB_ADDSTRING, 0, (LPARAM)L"<unknown>");
|
||||
SendMessage(controlWindow, CB_SETCURSEL, 0, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
DeviceView_InitCapacity(hwnd);
|
||||
DeviceView_InitIcons(hwnd, NULL);
|
||||
|
||||
}
|
||||
|
||||
static INT_PTR
|
||||
DeviceView_OnInitDialog(HWND hwnd, HWND focusWindow, LPARAM param)
|
||||
{
|
||||
DeviceView *self;
|
||||
|
||||
self = (DeviceView*)malloc(sizeof(DeviceView));
|
||||
if (NULL != self)
|
||||
{
|
||||
ZeroMemory(self, sizeof(DeviceView));
|
||||
if (FALSE == SetProp(hwnd, MAKEINTATOM(DEVICEVIEW_ATOM), self))
|
||||
{
|
||||
free(self);
|
||||
self = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == self)
|
||||
{
|
||||
DestroyWindow(hwnd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
self->device = (Device*)param;
|
||||
if (NULL != self->device)
|
||||
self->device->AddRef();
|
||||
|
||||
DeviceView_InitView(hwnd);
|
||||
|
||||
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_OnDestroy(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
|
||||
DeviceView_DestroyIcons(hwnd);
|
||||
|
||||
self = DEVICEVIEW(hwnd);
|
||||
RemoveProp(hwnd, MAKEINTATOM(DEVICEVIEW_ATOM));
|
||||
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
if (NULL != self->device)
|
||||
self->device->Release();
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_OnTitleEditChanged(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
HWND controlWindow;
|
||||
wchar_t buffer[1024];
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_EDIT_TITLE);
|
||||
if (NULL == controlWindow)
|
||||
return;
|
||||
|
||||
if (NULL == self->device)
|
||||
return;
|
||||
|
||||
GetWindowText(controlWindow, buffer, ARRAYSIZE(buffer));
|
||||
|
||||
self->device->SetDisplayName(buffer);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_OnAttachedComboChanged(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
HWND controlWindow;
|
||||
wchar_t buffer[1024];
|
||||
int index;
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ATTACHED);
|
||||
if (NULL == controlWindow)
|
||||
return;
|
||||
|
||||
if (NULL == self->device)
|
||||
return;
|
||||
|
||||
index = (int)SendMessage(controlWindow, CB_GETCURSEL, 0, 0);
|
||||
if (CB_ERR != index &&
|
||||
CB_ERR != SendMessage(controlWindow, CB_GETLBTEXT, index, (LPARAM)buffer))
|
||||
{
|
||||
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, buffer, -1, L"Yes", -1))
|
||||
{
|
||||
self->device->Attach(NULL);
|
||||
}
|
||||
else if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, buffer, -1, L"No", -1))
|
||||
{
|
||||
self->device->Detach(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_OnVisibleComboChanged(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
HWND controlWindow;
|
||||
wchar_t buffer[1024];
|
||||
int index;
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_COMBO_VISIBLE);
|
||||
if (NULL == controlWindow)
|
||||
return;
|
||||
|
||||
if (NULL == self->device)
|
||||
return;
|
||||
|
||||
index = (int)SendMessage(controlWindow, CB_GETCURSEL, 0, 0);
|
||||
if (-1 != index &&
|
||||
CB_ERR != SendMessage(controlWindow, CB_GETLBTEXT, index, (LPARAM)buffer))
|
||||
{
|
||||
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, buffer, -1, L"Yes", -1))
|
||||
{
|
||||
self->device->SetHidden(FALSE);
|
||||
}
|
||||
else if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, buffer, -1, L"No", -1))
|
||||
{
|
||||
self->device->SetHidden(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_OnIconsComboChanged(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
HWND controlWindow, pictureWindow;
|
||||
int index;
|
||||
HBITMAP bitmap, previousBitmap;
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_COMBO_ICONS);
|
||||
if (NULL == controlWindow)
|
||||
return;
|
||||
|
||||
if (NULL == self->device)
|
||||
return;
|
||||
|
||||
pictureWindow = GetDlgItem(hwnd, IDC_STATIC_PREVIEWICON);
|
||||
if (NULL == pictureWindow)
|
||||
return;
|
||||
|
||||
bitmap = NULL;
|
||||
index = (int)SendMessage(controlWindow, CB_GETCURSEL, 0, 0);\
|
||||
if (CB_ERR != index)
|
||||
{
|
||||
DeviceIconInfo *info;
|
||||
info = (DeviceIconInfo*)SendMessage(controlWindow, CB_GETITEMDATA, index, 0L);
|
||||
if (CB_ERR != (INT_PTR)info && NULL != info->path)
|
||||
{
|
||||
bitmap = DeviceView_LoadIcon(info->path);
|
||||
}
|
||||
}
|
||||
|
||||
previousBitmap = (HBITMAP)SendMessage(pictureWindow, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bitmap);
|
||||
if (NULL != previousBitmap)
|
||||
DeleteObject(previousBitmap);
|
||||
|
||||
previousBitmap = (HBITMAP)SendMessage(pictureWindow, STM_GETIMAGE, IMAGE_BITMAP, 0L);
|
||||
if(previousBitmap != bitmap)
|
||||
{
|
||||
if (NULL != bitmap)
|
||||
DeleteObject(bitmap);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_OnTotalSpaceEditChanged(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
HWND controlWindow;
|
||||
uint64_t totalSpace;
|
||||
BOOL error;
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_SPIN_TOTALSPACE);
|
||||
if (NULL == controlWindow)
|
||||
return;
|
||||
|
||||
if (NULL == self->device)
|
||||
return;
|
||||
|
||||
totalSpace = (size_t)SendMessage(controlWindow, UDM_GETPOS32, 0, (LPARAM)&error);
|
||||
if (FALSE != error)
|
||||
return;
|
||||
|
||||
if (FAILED(self->device->SetTotalSpace(totalSpace)))
|
||||
{
|
||||
if (FAILED(self->device->GetTotalSpace(&totalSpace)))
|
||||
totalSpace = 0;
|
||||
}
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_SPIN_USEDSPACE);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
SendMessage(controlWindow, UDM_SETRANGE32, (WPARAM)0, (LPARAM)totalSpace);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_OnUsedSpaceEditChanged(HWND hwnd)
|
||||
{
|
||||
DeviceView *self;
|
||||
HWND controlWindow;
|
||||
uint64_t usedSpace;
|
||||
BOOL error;
|
||||
|
||||
DEVICEVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
controlWindow = GetDlgItem(hwnd, IDC_SPIN_USEDSPACE);
|
||||
if (NULL == controlWindow)
|
||||
return;
|
||||
|
||||
if (NULL == self->device)
|
||||
return;
|
||||
|
||||
usedSpace = (size_t)SendMessage(controlWindow, UDM_GETPOS32, 0, (LPARAM)&error);
|
||||
if (FALSE != error)
|
||||
return;
|
||||
|
||||
if (FAILED(self->device->SetUsedSpace(usedSpace)))
|
||||
{
|
||||
if (FAILED(self->device->GetTotalSpace(&usedSpace)))
|
||||
usedSpace = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceView_OnCommand(HWND hwnd, INT commandId, INT eventId, HWND controlWindow)
|
||||
{
|
||||
switch(commandId)
|
||||
{
|
||||
case IDC_EDIT_TITLE:
|
||||
switch(eventId)
|
||||
{
|
||||
case EN_CHANGE:
|
||||
DeviceView_OnTitleEditChanged(hwnd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IDC_COMBO_ATTACHED:
|
||||
switch(eventId)
|
||||
{
|
||||
case CBN_SELENDOK:
|
||||
DeviceView_OnAttachedComboChanged(hwnd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_COMBO_VISIBLE:
|
||||
switch(eventId)
|
||||
{
|
||||
case CBN_SELENDOK:
|
||||
DeviceView_OnVisibleComboChanged(hwnd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IDC_COMBO_ICONS:
|
||||
switch(eventId)
|
||||
{
|
||||
case CBN_SELENDOK:
|
||||
DeviceView_OnIconsComboChanged(hwnd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IDC_EDIT_TOTALSPACE:
|
||||
switch(eventId)
|
||||
{
|
||||
case EN_CHANGE:
|
||||
DeviceView_OnTotalSpaceEditChanged(hwnd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IDC_EDIT_USEDSPACE:
|
||||
switch(eventId)
|
||||
{
|
||||
case EN_CHANGE:
|
||||
DeviceView_OnUsedSpaceEditChanged(hwnd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IDC_BUTTON_NEWICON:
|
||||
switch(eventId)
|
||||
{
|
||||
case BN_CLICKED:
|
||||
DeviceView_NewIcon(hwnd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IDC_BUTTON_REMOVEICON:
|
||||
switch(eventId)
|
||||
{
|
||||
case BN_CLICKED:
|
||||
DeviceView_RemoveIcon(hwnd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IDC_BUTTON_EDITICON:
|
||||
switch(eventId)
|
||||
{
|
||||
case BN_CLICKED:
|
||||
DeviceView_EditIcon(hwnd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static INT_PTR
|
||||
DeviceView_DialogProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG: return DeviceView_OnInitDialog(hwnd, (HWND)wParam, lParam);
|
||||
case WM_DESTROY: DeviceView_OnDestroy(hwnd); return TRUE;
|
||||
case WM_COMMAND: DeviceView_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return TRUE;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_VIEW_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_VIEW_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
HWND
|
||||
DeviceView_CreateWindow(HWND parentWindow,
|
||||
Device *device);
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_DEVICE_VIEW_HEADER
|
Binary file not shown.
|
@ -0,0 +1,415 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="gen_deviceprovider"
|
||||
ProjectGUID="{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}"
|
||||
RootNamespace="gen_deviceprovider"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../..;../../wasabi;../../agave"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderThrough=""
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
EnablePREfast="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="comctl32.lib shlwapi.lib windowscodecs.lib"
|
||||
OutputFile="$(ProgramFiles)\winamp\plugins\gen_deviceprovider.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="msvcprt.lib"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
SupportUnloadOfDelayLoadedDLL="true"
|
||||
ImportLibrary="$(OutDir)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
Profile="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
OutputDocumentFile="$(OutDir)\$(TargetName).xml"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories="../..;../../wasabi;../../agave"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="main.h"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="comctl32.lib shlwapi.lib windowscodecs.lib"
|
||||
OutputFile="$(ProgramFiles)\winamp\plugins\gen_deviceprovider.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="msvcprt.lib"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
SupportUnloadOfDelayLoadedDLL="true"
|
||||
ImportLibrary="$(OutDir)\$(TargetName).lib"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
OutputDocumentFile="$(OutDir)\$(TargetName).xml"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="nu"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\nu\PtrList.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\nu\PtrList.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\nu\trace.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\nu\trace.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\common.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\device.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\device.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceActivity.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceActivity.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceCommandNodeParser.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceCommandNodeParser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceCommandParser.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceCommandParser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceConnectionNodeParser.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceConnectionNodeParser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceConnectionParser.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceConnectionParser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceIconEditor.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceIconEditor.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceNodeParser.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceNodeParser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceParser.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceParser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceTypeNodeParser.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceTypeNodeParser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceTypeParser.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceTypeParser.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceView.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\deviceView.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\iconStore.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\iconStore.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\main.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\main.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\provider.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\provider.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resources.rc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stringBuilder.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stringBuilder.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\strings.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\strings.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\testSuite.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\testSuite.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\testSuiteLoader.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\testSuiteLoader.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wasabi.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wasabi.h"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
|
@ -0,0 +1,335 @@
|
|||
<?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="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}</ProjectGuid>
|
||||
<RootNamespace>gen_deviceprovider</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)'=='Release|x64'" 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>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</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)'=='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|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>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
<EmbedManifest>true</EmbedManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg">
|
||||
<VcpkgEnableManifest>false</VcpkgEnableManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgConfiguration>Debug</VcpkgConfiguration>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
<VcpkgConfiguration>Debug</VcpkgConfiguration>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>../..;..\..\..\;..\..\..\..\wasabi;..\..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;_DEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<Profile>false</Profile>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Xdcmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
|
||||
</Xdcmake>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
|
||||
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>../..;..\..\..\..\;..\..\..\..\wasabi;..\..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;_DEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;windowscodecs.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<Profile>false</Profile>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Xdcmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
|
||||
</Xdcmake>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
|
||||
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>../..;..\..\..\..\;..\..\..\..\wasabi;..\..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;NDEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<StringPooling>true</StringPooling>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;windowscodecs.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>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Xdcmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
|
||||
</Xdcmake>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>../..;..\..\..\..\;..\..\..\..\wasabi;..\..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;NDEBUG;_WINDOWS;_USRDLL;GEN_DEVICEPROVIDER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<StringPooling>true</StringPooling>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;windowscodecs.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>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Xdcmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
|
||||
</Xdcmake>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\..\nu\PtrList.cpp" />
|
||||
<ClCompile Include="..\..\..\..\nu\trace.cpp" />
|
||||
<ClCompile Include="device.cpp" />
|
||||
<ClCompile Include="deviceActivity.cpp" />
|
||||
<ClCompile Include="deviceCommandNodeParser.cpp" />
|
||||
<ClCompile Include="deviceCommandParser.cpp" />
|
||||
<ClCompile Include="deviceConnectionNodeParser.cpp" />
|
||||
<ClCompile Include="deviceConnectionParser.cpp" />
|
||||
<ClCompile Include="deviceIconEditor.cpp" />
|
||||
<ClCompile Include="deviceNodeParser.cpp" />
|
||||
<ClCompile Include="deviceParser.cpp" />
|
||||
<ClCompile Include="deviceTypeNodeParser.cpp" />
|
||||
<ClCompile Include="deviceTypeParser.cpp" />
|
||||
<ClCompile Include="deviceView.cpp" />
|
||||
<ClCompile Include="iconStore.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="plugin.cpp" />
|
||||
<ClCompile Include="provider.cpp" />
|
||||
<ClCompile Include="stringBuilder.cpp" />
|
||||
<ClCompile Include="strings.cpp" />
|
||||
<ClCompile Include="testSuite.cpp" />
|
||||
<ClCompile Include="testSuiteLoader.cpp" />
|
||||
<ClCompile Include="wasabi.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\..\nu\trace.h" />
|
||||
<ClInclude Include="common.h" />
|
||||
<ClInclude Include="device.h" />
|
||||
<ClInclude Include="deviceActivity.h" />
|
||||
<ClInclude Include="deviceCommandNodeParser.h" />
|
||||
<ClInclude Include="deviceCommandParser.h" />
|
||||
<ClInclude Include="deviceConnectionNodeParser.h" />
|
||||
<ClInclude Include="deviceConnectionParser.h" />
|
||||
<ClInclude Include="deviceIconEditor.h" />
|
||||
<ClInclude Include="deviceNodeParser.h" />
|
||||
<ClInclude Include="deviceParser.h" />
|
||||
<ClInclude Include="deviceTypeNodeParser.h" />
|
||||
<ClInclude Include="deviceTypeParser.h" />
|
||||
<ClInclude Include="deviceView.h" />
|
||||
<ClInclude Include="iconStore.h" />
|
||||
<ClInclude Include="main.h" />
|
||||
<ClInclude Include="plugin.h" />
|
||||
<ClInclude Include="provider.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="stringBuilder.h" />
|
||||
<ClInclude Include="strings.h" />
|
||||
<ClInclude Include="testSuite.h" />
|
||||
<ClInclude Include="testSuiteLoader.h" />
|
||||
<ClInclude Include="wasabi.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="resources.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>
|
|
@ -0,0 +1,164 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="device.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceActivity.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceCommandNodeParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceCommandParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceConnectionNodeParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceConnectionParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceIconEditor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceNodeParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceTypeNodeParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceTypeParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceView.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="iconStore.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="provider.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stringBuilder.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="strings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testSuite.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testSuiteLoader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wasabi.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\nu\trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\..\nu\PtrList.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="common.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="device.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceActivity.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceCommandNodeParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceCommandParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceConnectionNodeParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceConnectionParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceIconEditor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceNodeParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceTypeNodeParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceTypeParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceView.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="iconStore.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="provider.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stringBuilder.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="strings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="testSuite.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="testSuiteLoader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wasabi.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\nu\trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{e264ea99-159e-4062-a78a-a85da3815f37}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Ressource Files">
|
||||
<UniqueIdentifier>{f5beaf0a-f21d-4ae9-8221-adde13e2b65d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{207087f5-3450-4826-bae5-39064e9da43f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="resources.rc">
|
||||
<Filter>Ressource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
289
Src/Plugins/Library/ml_devices/gen_deviceprovider/iconStore.cpp
Normal file
289
Src/Plugins/Library/ml_devices/gen_deviceprovider/iconStore.cpp
Normal file
|
@ -0,0 +1,289 @@
|
|||
#include "main.h"
|
||||
#include "./iconStore.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
typedef struct IconStoreRecord
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
wchar_t *path;
|
||||
} IconStoreRecord;
|
||||
|
||||
typedef std::vector<IconStoreRecord> RecodList;
|
||||
|
||||
struct IconStore
|
||||
{
|
||||
RecodList list;
|
||||
wchar_t *basePath;
|
||||
};
|
||||
|
||||
IconStore *
|
||||
IconStore_Create()
|
||||
{
|
||||
IconStore *self;
|
||||
|
||||
self = new IconStore();
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
self->basePath = NULL;
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
IconStore_Destroy(IconStore *self)
|
||||
{
|
||||
size_t index;
|
||||
IconStoreRecord *record;
|
||||
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
index = self->list.size();
|
||||
while(index--)
|
||||
{
|
||||
record = &self->list[index];
|
||||
String_Free(record->path);
|
||||
}
|
||||
|
||||
String_Free(self->basePath);
|
||||
}
|
||||
|
||||
BOOL
|
||||
IconStore_Add(IconStore *self, const wchar_t *path, unsigned int width, unsigned int height)
|
||||
{
|
||||
IconStoreRecord record, *prec;
|
||||
size_t index;
|
||||
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
if(width < 1)
|
||||
width = 1;
|
||||
|
||||
if(height < 1)
|
||||
height = 1;
|
||||
|
||||
index = self->list.size();
|
||||
while(index--)
|
||||
{
|
||||
prec = &self->list[index];
|
||||
if (width == prec->width &&
|
||||
height == prec->height)
|
||||
{
|
||||
String_Free(prec->path);
|
||||
prec->path = String_Duplicate(path);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
record.path = String_Duplicate(path);
|
||||
record.width = width;
|
||||
record.height = height;
|
||||
|
||||
self->list.push_back(record);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
IconStore_RemovePath(IconStore *self, const wchar_t *path)
|
||||
{
|
||||
size_t index;
|
||||
IconStoreRecord *record;
|
||||
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
index = self->list.size();
|
||||
while(index--)
|
||||
{
|
||||
record = &self->list[index];
|
||||
if(CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, record->path, -1, path, -1))
|
||||
{
|
||||
self->list.eraseAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
IconStore_Remove(IconStore *self, unsigned int width, unsigned int height)
|
||||
{
|
||||
size_t index;
|
||||
IconStoreRecord *record;
|
||||
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
index = self->list.size();
|
||||
while(index--)
|
||||
{
|
||||
record = &self->list[index];
|
||||
if(record->width == width &&
|
||||
record->height == height)
|
||||
{
|
||||
self->list.eraseAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
IconStore_GetFullPath(IconStore *self, const wchar_t *path, wchar_t *buffer, size_t bufferMax)
|
||||
{
|
||||
if (NULL == buffer)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
if (FALSE != IS_STRING_EMPTY(path))
|
||||
{
|
||||
*buffer = L'\0';
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (FALSE == PathIsRelative(path) ||
|
||||
IS_STRING_EMPTY(self->basePath))
|
||||
{
|
||||
if (0 == String_CopyTo(buffer, path, bufferMax) &&
|
||||
FALSE == IS_STRING_EMPTY(path))
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (NULL == PathCombine(buffer, self->basePath, path))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
IconStore_Get(IconStore *self, wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height)
|
||||
{
|
||||
const wchar_t *icon;
|
||||
IconStoreRecord *record;
|
||||
size_t index;
|
||||
double widthDbl, heightDbl;
|
||||
double scaleMin, scaleHorz, scaleVert;
|
||||
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == buffer)
|
||||
return FALSE;
|
||||
|
||||
icon = NULL;
|
||||
|
||||
widthDbl = width;
|
||||
heightDbl = height;
|
||||
|
||||
index = self->list.size();
|
||||
if (index > 0)
|
||||
{
|
||||
record = &self->list[--index];
|
||||
scaleHorz = widthDbl/record->width;
|
||||
scaleVert = heightDbl/record->height;
|
||||
scaleMin = (scaleHorz < scaleVert) ? scaleHorz : scaleVert;
|
||||
icon = record->path;
|
||||
if (1.0 != scaleMin)
|
||||
{
|
||||
scaleMin = fabs(1.0 - scaleMin);
|
||||
while(index--)
|
||||
{
|
||||
record = &self->list[index];
|
||||
scaleHorz = widthDbl/record->width;
|
||||
scaleVert = heightDbl/record->height;
|
||||
if (scaleHorz > scaleVert)
|
||||
scaleHorz = scaleVert;
|
||||
|
||||
if (1.0 == scaleHorz)
|
||||
{
|
||||
icon = record->path;
|
||||
break;
|
||||
}
|
||||
|
||||
scaleHorz = fabs(1.0 - scaleHorz);
|
||||
if (scaleHorz < scaleMin)
|
||||
{
|
||||
scaleMin = scaleHorz;
|
||||
icon = record->path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IconStore_GetFullPath(self, icon, buffer, bufferMax);
|
||||
}
|
||||
|
||||
BOOL
|
||||
IconStore_SetBasePath(IconStore *self, const wchar_t *path)
|
||||
{
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
String_Free(self->basePath);
|
||||
self->basePath = String_Duplicate(path);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
IconStore *
|
||||
IconStore_Clone(IconStore *self)
|
||||
{
|
||||
size_t index;
|
||||
IconStore *clone;
|
||||
IconStoreRecord targetRec;
|
||||
const IconStoreRecord *sourceRec;
|
||||
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
clone = IconStore_Create();
|
||||
if (NULL == clone)
|
||||
return NULL;
|
||||
|
||||
clone->basePath = String_Duplicate(self->basePath);
|
||||
for(index = 0; index < self->list.size(); index++)
|
||||
{
|
||||
sourceRec = &self->list[index];
|
||||
targetRec.path = String_Duplicate(sourceRec->path);
|
||||
targetRec.width = sourceRec->width;
|
||||
targetRec.height = sourceRec->height;
|
||||
clone->list.push_back(targetRec);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
IconStore_Enumerate(IconStore *self, IconEnumerator callback, void *user)
|
||||
{
|
||||
size_t index;
|
||||
wchar_t buffer[MAX_PATH*2];
|
||||
IconStoreRecord *record;
|
||||
|
||||
if (NULL == self || NULL == callback)
|
||||
return FALSE;
|
||||
|
||||
index = self->list.size();
|
||||
while(index--)
|
||||
{
|
||||
record = &self->list[index];
|
||||
if (FALSE != IconStore_GetFullPath(self, record->path, buffer, ARRAYSIZE(buffer)))
|
||||
{
|
||||
if (FALSE == callback(buffer, record->width, record->height, user))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_ICON_STORE_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_ICON_STORE_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
typedef struct IconStore IconStore;
|
||||
typedef BOOL (*IconEnumerator)(const wchar_t *path, unsigned int width, unsigned int height, void *user);
|
||||
|
||||
IconStore *
|
||||
IconStore_Create();
|
||||
|
||||
void
|
||||
IconStore_Destroy(IconStore *self);
|
||||
|
||||
BOOL
|
||||
IconStore_Add(IconStore *self,
|
||||
const wchar_t *path,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
BOOL
|
||||
IconStore_RemovePath(IconStore *self,
|
||||
const wchar_t *path);
|
||||
|
||||
BOOL
|
||||
IconStore_Remove(IconStore *self,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
BOOL
|
||||
IconStore_Get(IconStore *self,
|
||||
wchar_t *buffer,
|
||||
size_t bufferMax,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
BOOL
|
||||
IconStore_SetBasePath(IconStore *self,
|
||||
const wchar_t *path);
|
||||
|
||||
IconStore *
|
||||
IconStore_Clone(IconStore *self);
|
||||
|
||||
BOOL
|
||||
IconStore_Enumerate(IconStore *self,
|
||||
IconEnumerator callback,
|
||||
void *user);
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_ICON_STORE_HEADER
|
|
@ -0,0 +1,2 @@
|
|||
#include <initguid.h>
|
||||
#include "main.h"
|
31
Src/Plugins/Library/ml_devices/gen_deviceprovider/main.h
Normal file
31
Src/Plugins/Library/ml_devices/gen_deviceprovider/main.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_MAIN_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_MAIN_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
#include "./common.h"
|
||||
#include "./plugin.h"
|
||||
#include "./strings.h"
|
||||
#include "./stringBuilder.h"
|
||||
#include "./wasabi.h"
|
||||
#include "./provider.h"
|
||||
#include "./resource.h"
|
||||
#include "./device.h"
|
||||
#include "./deviceActivity.h"
|
||||
#include "./deviceView.h"
|
||||
#include "./deviceIconEditor.h"
|
||||
#include "./testSuite.h"
|
||||
#include "./testSuiteLoader.h"
|
||||
#include "./iconStore.h"
|
||||
|
||||
#include "../../winamp/wa_ipc.h"
|
||||
#include "../../nu/trace.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_MAIN_HEADER
|
114
Src/Plugins/Library/ml_devices/gen_deviceprovider/plugin.cpp
Normal file
114
Src/Plugins/Library/ml_devices/gen_deviceprovider/plugin.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
#include "main.h"
|
||||
#include "../../winamp/gen.h"
|
||||
#include <strsafe.h>
|
||||
|
||||
static INT
|
||||
Plugin_Init(void);
|
||||
|
||||
static void
|
||||
Plugin_Quit(void);
|
||||
|
||||
static void
|
||||
Plugin_Config(void);
|
||||
|
||||
|
||||
extern "C" winampGeneralPurposePlugin plugin =
|
||||
{
|
||||
GPPHDR_VER,
|
||||
0,
|
||||
Plugin_Init,
|
||||
Plugin_Config,
|
||||
Plugin_Quit,
|
||||
};
|
||||
|
||||
static DeviceProvider *deviceProvider = NULL;
|
||||
|
||||
HINSTANCE
|
||||
Plugin_GetInstance(void)
|
||||
{
|
||||
return plugin.hDllInstance;
|
||||
}
|
||||
|
||||
HWND
|
||||
Plugin_GetWinampWindow(void)
|
||||
{
|
||||
return plugin.hwndParent;
|
||||
}
|
||||
|
||||
static void
|
||||
Plugin_SetDescription()
|
||||
{
|
||||
WCHAR szBuffer[256], szTemplate[256];
|
||||
|
||||
if (0 != plugin.description)
|
||||
AnsiString_Free(plugin.description);
|
||||
|
||||
if (NULL != WASABI_API_LNG)
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_PLUGIN_NAME, szTemplate, ARRAYSIZE(szTemplate));
|
||||
else
|
||||
szTemplate[0] = L'\0';
|
||||
|
||||
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer),
|
||||
((L'\0' != szTemplate[0]) ? szTemplate : L"Nullsoft Test Device Provider v%d.%d"),
|
||||
PLUGIN_VERSION_MAJOR, PLUGIN_VERSION_MINOR);
|
||||
|
||||
plugin.description = String_ToAnsi(CP_ACP, 0, szBuffer, -1, NULL, NULL);
|
||||
}
|
||||
|
||||
static INT
|
||||
Plugin_Init(void)
|
||||
{
|
||||
|
||||
if (FALSE == Wasabi_InitializeFromWinamp(plugin.hDllInstance, plugin.hwndParent))
|
||||
return 1;
|
||||
|
||||
Wasabi_LoadDefaultServices();
|
||||
|
||||
Plugin_SetDescription();
|
||||
|
||||
if (NULL == deviceProvider)
|
||||
{
|
||||
if (FAILED(DeviceProvider::CreateInstance(&deviceProvider)))
|
||||
{
|
||||
Wasabi_Release();
|
||||
return 2;
|
||||
}
|
||||
|
||||
deviceProvider->Register(WASABI_API_DEVICES);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
Plugin_Quit(void)
|
||||
{
|
||||
if (0 != plugin.description)
|
||||
{
|
||||
AnsiString_Free(plugin.description);
|
||||
plugin.description = 0;
|
||||
}
|
||||
|
||||
if (NULL != deviceProvider)
|
||||
{
|
||||
deviceProvider->Unregister(WASABI_API_DEVICES);
|
||||
deviceProvider->Release();
|
||||
}
|
||||
|
||||
Wasabi_Release();
|
||||
}
|
||||
|
||||
static void
|
||||
Plugin_Config(void)
|
||||
{
|
||||
}
|
||||
|
||||
EXTERN_C __declspec(dllexport) winampGeneralPurposePlugin *
|
||||
winampGetGeneralPurposePlugin()
|
||||
{
|
||||
if (0 == plugin.description)
|
||||
{
|
||||
Plugin_SetDescription();
|
||||
}
|
||||
return &plugin;
|
||||
}
|
21
Src/Plugins/Library/ml_devices/gen_deviceprovider/plugin.h
Normal file
21
Src/Plugins/Library/ml_devices/gen_deviceprovider/plugin.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_PLUGIN_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_PLUGIN_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
#define PLUGIN_VERSION_MAJOR 1
|
||||
#define PLUGIN_VERSION_MINOR 1
|
||||
|
||||
// {51B54A05-B711-4509-80AE-5A0AAA502FA5}
|
||||
DEFINE_GUID(PLUGIN_LANGUAGE_ID,
|
||||
0x51b54a05, 0xb711, 0x4509, 0x80, 0xae, 0x5a, 0xa, 0xaa, 0x50, 0x2f, 0xa5);
|
||||
|
||||
|
||||
HINSTANCE Plugin_GetInstance(void);
|
||||
HWND Plugin_GetWinampWindow(void);
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_PLUGIN_HEADER
|
336
Src/Plugins/Library/ml_devices/gen_deviceprovider/provider.cpp
Normal file
336
Src/Plugins/Library/ml_devices/gen_deviceprovider/provider.cpp
Normal file
|
@ -0,0 +1,336 @@
|
|||
#include "main.h"
|
||||
#include "./provider.h"
|
||||
|
||||
typedef struct DeviceProviderThreadParam
|
||||
{
|
||||
api_devicemanager *manager;
|
||||
DeviceProvider *provider;
|
||||
HANDLE readyEvent;
|
||||
|
||||
}DeviceProviderThreadParam;
|
||||
|
||||
DeviceProvider::DeviceProvider()
|
||||
: ref(1), discoveryThread(NULL), cancelEvent(NULL)
|
||||
{
|
||||
wchar_t buffer[MAX_PATH * 2];
|
||||
HINSTANCE module;
|
||||
|
||||
TestSuiteLoader loader;
|
||||
|
||||
InitializeCriticalSection(&lock);
|
||||
|
||||
module = Plugin_GetInstance();
|
||||
if (0 == GetModuleFileName(module, buffer, ARRAYSIZE(buffer)) ||
|
||||
FALSE == PathRemoveFileSpec(buffer))
|
||||
{
|
||||
buffer[0] = L'\0';
|
||||
}
|
||||
PathAppend(buffer, L"testprovider.xml");
|
||||
loader.Load(buffer, &testSuite);
|
||||
}
|
||||
|
||||
DeviceProvider::~DeviceProvider()
|
||||
{
|
||||
CancelDiscovery();
|
||||
DeleteCriticalSection(&lock);
|
||||
}
|
||||
|
||||
HRESULT DeviceProvider::CreateInstance(DeviceProvider **instance)
|
||||
{
|
||||
if (NULL == instance)
|
||||
return E_POINTER;
|
||||
|
||||
*instance = new DeviceProvider();
|
||||
|
||||
if (NULL == *instance)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
size_t DeviceProvider::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
size_t DeviceProvider::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int DeviceProvider::QueryInterface(GUID interface_guid, void **object)
|
||||
{
|
||||
if (NULL == object)
|
||||
return E_POINTER;
|
||||
|
||||
if (IsEqualIID(interface_guid, IFC_DeviceProvider))
|
||||
*object = static_cast<ifc_deviceprovider*>(this);
|
||||
else
|
||||
{
|
||||
*object = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
if (NULL == *object)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DWORD DeviceProvider::DiscoveryThread(api_devicemanager *manager)
|
||||
{
|
||||
DWORD waitResult;
|
||||
DWORD deviceCount;
|
||||
DWORD threadId;
|
||||
DWORD sleepTime;
|
||||
LARGE_INTEGER perfCounter;
|
||||
|
||||
deviceCount = 0;
|
||||
|
||||
threadId = GetCurrentThreadId();
|
||||
// aTRACE_FMT("[test provider] device discovery started (0x%X).\r\n", threadId);
|
||||
|
||||
manager->SetProviderActive(this, TRUE);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if (FALSE != QueryPerformanceCounter(&perfCounter))
|
||||
srand(perfCounter.LowPart);
|
||||
else
|
||||
srand(GetTickCount());
|
||||
|
||||
sleepTime = (DWORD)((double)rand()/(RAND_MAX) * 0);
|
||||
|
||||
waitResult = WaitForSingleObject(cancelEvent, sleepTime);
|
||||
if (WAIT_OBJECT_0 == waitResult)
|
||||
break;
|
||||
else if (WAIT_TIMEOUT == waitResult)
|
||||
{
|
||||
Device *device;
|
||||
|
||||
deviceCount++;
|
||||
// aTRACE_FMT("[test provider] creating new device[%d] (0x%X).\r\n", deviceCount, threadId);
|
||||
|
||||
device = testSuite.GetRandomDevice();
|
||||
if (NULL != device)
|
||||
{
|
||||
device->Connect();
|
||||
if (0 == manager->DeviceRegister((ifc_device**)&device, 1))
|
||||
device->Disconnect();
|
||||
}
|
||||
|
||||
if (4 == deviceCount)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// aTRACE_FMT("[test provider] error (0x%X).\r\n", threadId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
if (NULL != discoveryThread)
|
||||
{
|
||||
CloseHandle(discoveryThread);
|
||||
discoveryThread = NULL;
|
||||
}
|
||||
|
||||
if (NULL != cancelEvent)
|
||||
{
|
||||
CloseHandle(cancelEvent);
|
||||
cancelEvent = NULL;
|
||||
}
|
||||
|
||||
// aTRACE_FMT("[test provider] device discovery finished (0x%X).\r\n", threadId);
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
manager->SetProviderActive(this, FALSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD CALLBACK DeviceProvider_DiscoveryThreadStarter(void *user)
|
||||
{
|
||||
DeviceProviderThreadParam *param;
|
||||
DeviceProvider *provider;
|
||||
api_devicemanager *manager;
|
||||
DWORD result;
|
||||
|
||||
param = (DeviceProviderThreadParam*)user;
|
||||
manager = param->manager;
|
||||
provider = param->provider;
|
||||
|
||||
if (NULL != manager)
|
||||
manager->AddRef();
|
||||
|
||||
if (NULL != param->readyEvent)
|
||||
SetEvent(param->readyEvent);
|
||||
|
||||
if (NULL == manager)
|
||||
return -1;
|
||||
|
||||
if (NULL != provider)
|
||||
result = provider->DiscoveryThread(manager);
|
||||
else
|
||||
result = -2;
|
||||
|
||||
manager->Release();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT DeviceProvider::BeginDiscovery(api_devicemanager *manager)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == manager)
|
||||
return E_INVALIDARG;
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
if (NULL != discoveryThread)
|
||||
hr = E_PENDING;
|
||||
else
|
||||
{
|
||||
hr = S_OK;
|
||||
if (NULL == cancelEvent)
|
||||
{
|
||||
cancelEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (NULL == cancelEvent)
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DeviceProviderThreadParam param;
|
||||
|
||||
param.provider = this;
|
||||
param.manager = manager;
|
||||
param.readyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
if (NULL == param.readyEvent)
|
||||
hr = E_FAIL;
|
||||
else
|
||||
{
|
||||
DWORD threadId;
|
||||
|
||||
discoveryThread = CreateThread(NULL, 0, DeviceProvider_DiscoveryThreadStarter, ¶m, 0, &threadId);
|
||||
if (NULL == discoveryThread)
|
||||
hr = E_FAIL;
|
||||
else
|
||||
WaitForSingleObject(param.readyEvent, INFINITE);
|
||||
|
||||
CloseHandle(param.readyEvent);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
CancelDiscovery();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceProvider::CancelDiscovery()
|
||||
{
|
||||
HRESULT hr;
|
||||
HANDLE threadHandle, eventHandle;
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
threadHandle = discoveryThread;
|
||||
eventHandle = cancelEvent;
|
||||
|
||||
discoveryThread = NULL;
|
||||
cancelEvent = NULL;
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
if (NULL != threadHandle)
|
||||
{
|
||||
if (NULL != eventHandle)
|
||||
SetEvent(eventHandle);
|
||||
|
||||
WaitForSingleObject(threadHandle, INFINITE);
|
||||
CloseHandle(threadHandle);
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
hr = S_FALSE;
|
||||
|
||||
if (NULL != eventHandle)
|
||||
CloseHandle(eventHandle);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceProvider::GetActive()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
hr = (NULL != discoveryThread) ? S_OK : S_FALSE;
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceProvider::Register(api_devicemanager *manager)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == manager)
|
||||
return E_POINTER;
|
||||
|
||||
hr = manager->RegisterProvider(this);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
testSuite.RegisterCommands(manager);
|
||||
testSuite.RegisterTypes(manager);
|
||||
testSuite.RegisterConnections(manager);
|
||||
testSuite.RegisterDevices(manager);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DeviceProvider::Unregister(api_devicemanager *manager)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == manager)
|
||||
return E_POINTER;
|
||||
|
||||
hr = manager->UnregisterProvider(this);
|
||||
testSuite.UnregisterTypes(manager);
|
||||
testSuite.UnregisterConnections(manager);
|
||||
testSuite.UnregisterCommands(manager);
|
||||
testSuite.UnregisterDevices(manager);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
#define CBCLASS DeviceProvider
|
||||
START_DISPATCH;
|
||||
CB(ADDREF, AddRef)
|
||||
CB(RELEASE, Release)
|
||||
CB(QUERYINTERFACE, QueryInterface)
|
||||
CB(API_BEGINDISCOVERY, BeginDiscovery)
|
||||
CB(API_CANCELDISCOVERY, CancelDiscovery)
|
||||
CB(API_GETACTIVE, GetActive)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
50
Src/Plugins/Library/ml_devices/gen_deviceprovider/provider.h
Normal file
50
Src/Plugins/Library/ml_devices/gen_deviceprovider/provider.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_IMPLEMENTATION_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_IMPLEMENTATION_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../../devices/ifc_deviceprovider.h"
|
||||
#include "./testSuite.h"
|
||||
|
||||
class DeviceProvider : public ifc_deviceprovider
|
||||
{
|
||||
protected:
|
||||
DeviceProvider();
|
||||
~DeviceProvider();
|
||||
public:
|
||||
static HRESULT CreateInstance(DeviceProvider **instance);
|
||||
|
||||
public:
|
||||
/* Dispatchable */
|
||||
size_t AddRef();
|
||||
size_t Release();
|
||||
int QueryInterface(GUID interface_guid, void **object);
|
||||
|
||||
/* ifc_deviceprovider */
|
||||
HRESULT BeginDiscovery(api_devicemanager *manager);
|
||||
HRESULT CancelDiscovery();
|
||||
HRESULT GetActive();
|
||||
public:
|
||||
HRESULT Register(api_devicemanager *manager);
|
||||
HRESULT Unregister(api_devicemanager *manager);
|
||||
|
||||
private:
|
||||
DWORD DiscoveryThread(api_devicemanager *manager);
|
||||
friend static DWORD CALLBACK DeviceProvider_DiscoveryThreadStarter(void *param);
|
||||
|
||||
protected:
|
||||
size_t ref;
|
||||
HANDLE discoveryThread;
|
||||
HANDLE cancelEvent;
|
||||
TestSuite testSuite;
|
||||
CRITICAL_SECTION lock;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_IMPLEMENTATION_HEADER
|
39
Src/Plugins/Library/ml_devices/gen_deviceprovider/resource.h
Normal file
39
Src/Plugins/Library/ml_devices/gen_deviceprovider/resource.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by resources.rc
|
||||
//
|
||||
#define IDS_PLUGIN_NAME 101
|
||||
#define IDD_DEVICE_VIEW 102
|
||||
#define IDD_ICON_EDITOR 104
|
||||
#define IDC_EDIT_NAME 1001
|
||||
#define IDC_EDIT_TITLE 1002
|
||||
#define IDC_EDIT_TYPE 1003
|
||||
#define IDC_EDIT_CONNECTION 1004
|
||||
#define IDC_COMBO_ATTACHED 1005
|
||||
#define IDC_COMBO_VISIBLE 1006
|
||||
#define IDC_EDIT_TOTALSPACE 1007
|
||||
#define IDC_SPIN_TOTALSPACE 1008
|
||||
#define IDC_EDIT_USEDSPACE 1009
|
||||
#define IDC_SPIN_USEDSPACE 1010
|
||||
#define IDC_COMBO_ICONS 1011
|
||||
#define IDC_BUTTON_NEWICON 1012
|
||||
#define IDC_BUTTON_REMOVEICON 1013
|
||||
#define IDC_STATIC_PREVIEWICON 1014
|
||||
#define IDC_EDIT_WIDTH 1015
|
||||
#define IDC_EDIT_HEIGHT 1016
|
||||
#define IDC_EDIT_PATH 1017
|
||||
#define IDC_BUTTON_BROWSE 1018
|
||||
#define IDC_BUTTON1 1019
|
||||
#define IDC_BUTTON_EDITICON 1019
|
||||
#define IDS_STRING102 65535
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 105
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1020
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
186
Src/Plugins/Library/ml_devices/gen_deviceprovider/resources.rc
Normal file
186
Src/Plugins/Library/ml_devices/gen_deviceprovider/resources.rc
Normal file
|
@ -0,0 +1,186 @@
|
|||
// 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
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_DEVICE_VIEW DIALOGEX 0, 0, 397, 282
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
|
||||
EXSTYLE WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
EDITTEXT IDC_EDIT_NAME,57,23,101,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
EDITTEXT IDC_EDIT_TYPE,57,36,101,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
EDITTEXT IDC_EDIT_CONNECTION,57,50,101,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
EDITTEXT IDC_EDIT_TITLE,57,70,101,12,ES_AUTOHSCROLL
|
||||
COMBOBOX IDC_COMBO_ATTACHED,57,85,101,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
|
||||
COMBOBOX IDC_COMBO_VISIBLE,57,101,101,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
|
||||
EDITTEXT IDC_EDIT_TOTALSPACE,57,117,101,16,ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "",IDC_SPIN_TOTALSPACE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,149,118,9,12,WS_EX_TRANSPARENT
|
||||
EDITTEXT IDC_EDIT_USEDSPACE,57,134,101,16,ES_AUTOHSCROLL | ES_NUMBER
|
||||
CONTROL "",IDC_SPIN_USEDSPACE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,149,136,9,12,WS_EX_TRANSPARENT
|
||||
COMBOBOX IDC_COMBO_ICONS,169,34,221,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
PUSHBUTTON "New",IDC_BUTTON_NEWICON,264,49,40,14
|
||||
PUSHBUTTON "Edit",IDC_BUTTON_EDITICON,307,49,40,14
|
||||
PUSHBUTTON "Remove",IDC_BUTTON_REMOVEICON,350,49,40,14
|
||||
CONTROL "",IDC_STATIC_PREVIEWICON,"Static",SS_BITMAP | SS_CENTERIMAGE,169,70,221,170,WS_EX_STATICEDGE
|
||||
LTEXT "Device View",IDC_STATIC,7,7,39,8
|
||||
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,16,383,1
|
||||
LTEXT "Name:",IDC_STATIC,15,24,22,8
|
||||
LTEXT "Title:",IDC_STATIC,15,71,17,8
|
||||
LTEXT "Type:",IDC_STATIC,15,37,20,8
|
||||
LTEXT "Connection:",IDC_STATIC,15,51,40,8
|
||||
LTEXT "Attached:",IDC_STATIC,15,87,33,8
|
||||
LTEXT "Visible:",IDC_STATIC,15,103,23,8
|
||||
LTEXT "Capacity:",IDC_STATIC,15,119,32,8
|
||||
LTEXT "Used Space:",IDC_STATIC,15,136,41,8
|
||||
LTEXT "Icons:",IDC_STATIC,169,22,21,8
|
||||
END
|
||||
|
||||
IDD_ICON_EDITOR DIALOGEX 0, 0, 290, 79
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Device Icon"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,180,58,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,233,58,50,14
|
||||
LTEXT "Width:",IDC_STATIC,8,34,35,8
|
||||
LTEXT "Height:",IDC_STATIC,47,33,29,8
|
||||
EDITTEXT IDC_EDIT_WIDTH,7,44,35,14,ES_AUTOHSCROLL | ES_NUMBER
|
||||
EDITTEXT IDC_EDIT_HEIGHT,46,44,35,14,ES_AUTOHSCROLL | ES_NUMBER
|
||||
EDITTEXT IDC_EDIT_PATH,7,18,250,14,ES_AUTOHSCROLL
|
||||
LTEXT "Path:",IDC_STATIC,7,7,18,8
|
||||
PUSHBUTTON "...",IDC_BUTTON_BROWSE,261,18,22,14
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_DEVICE_VIEW, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 390
|
||||
VERTGUIDE, 15
|
||||
VERTGUIDE, 57
|
||||
VERTGUIDE, 158
|
||||
VERTGUIDE, 169
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 275
|
||||
END
|
||||
|
||||
IDD_ICON_EDITOR, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 283
|
||||
VERTGUIDE, 42
|
||||
VERTGUIDE, 46
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 72
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog Info
|
||||
//
|
||||
|
||||
IDD_DEVICE_VIEW DLGINIT
|
||||
BEGIN
|
||||
IDC_COMBO_ATTACHED, 0x403, 4, 0
|
||||
0x6559, 0x0073,
|
||||
IDC_COMBO_ATTACHED, 0x403, 3, 0
|
||||
0x6f4e, "\000"
|
||||
IDC_COMBO_VISIBLE, 0x403, 4, 0
|
||||
0x6559, 0x0073,
|
||||
IDC_COMBO_VISIBLE, 0x403, 3, 0
|
||||
0x6f4e, "\000"
|
||||
0
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_PLUGIN_NAME "Nullsoft Test Device Provider v%d.%d"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
65535 "{51B54A05-B711-4509-80AE-5A0AAA502FA5}"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
#include "main.h"
|
||||
#include "./stringBuilder.h"
|
||||
#include <strsafe.h>
|
||||
|
||||
StringBuilder::StringBuilder()
|
||||
: buffer(NULL), cursor(NULL), allocated(0), remaining(0)
|
||||
{
|
||||
}
|
||||
|
||||
StringBuilder::~StringBuilder()
|
||||
{
|
||||
String_Free(buffer);
|
||||
}
|
||||
|
||||
HRESULT StringBuilder::Allocate(size_t newSize)
|
||||
{
|
||||
if (newSize <= allocated)
|
||||
return S_FALSE;
|
||||
|
||||
LPWSTR t = String_ReAlloc(buffer, newSize);
|
||||
if (NULL == t) return E_OUTOFMEMORY;
|
||||
|
||||
cursor = t + (cursor - buffer);
|
||||
buffer = t;
|
||||
|
||||
remaining += newSize - allocated;
|
||||
allocated = newSize;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void StringBuilder::Clear(void)
|
||||
{
|
||||
if (NULL != buffer)
|
||||
{
|
||||
buffer[0] = L'\0';
|
||||
}
|
||||
cursor = buffer;
|
||||
remaining = allocated;
|
||||
}
|
||||
|
||||
LPCWSTR StringBuilder::Get(void)
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
HRESULT StringBuilder::Set(size_t index, WCHAR value)
|
||||
{
|
||||
if (NULL == buffer)
|
||||
return E_POINTER;
|
||||
|
||||
if (index >= allocated)
|
||||
return E_INVALIDARG;
|
||||
|
||||
buffer[index] = value;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT StringBuilder::Append(LPCWSTR pszString)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (NULL == buffer)
|
||||
{
|
||||
hr = Allocate(1024);
|
||||
if (FAILED(hr)) return hr;
|
||||
}
|
||||
|
||||
size_t cchCursor = remaining;
|
||||
hr = StringCchCopyEx(cursor, cchCursor, pszString, &cursor, &remaining, STRSAFE_IGNORE_NULLS);
|
||||
if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
|
||||
{
|
||||
size_t offset = cchCursor - remaining;
|
||||
size_t requested = lstrlen(pszString) + (allocated - remaining) + 1;
|
||||
size_t newsize = allocated * 2;
|
||||
while (newsize < requested) newsize = newsize * 2;
|
||||
|
||||
hr = Allocate(newsize);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
hr = StringCchCopyEx(cursor, remaining, pszString + offset, &cursor, &remaining, STRSAFE_IGNORE_NULLS);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef NULLSOFT_WINAMP_STRING_BUILDER_HEADER
|
||||
#define NULLSOFT_WINAMP_STRING_BUILDER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
class StringBuilder
|
||||
{
|
||||
public:
|
||||
StringBuilder();
|
||||
~StringBuilder();
|
||||
|
||||
public:
|
||||
HRESULT Allocate(size_t newSize);
|
||||
void Clear(void);
|
||||
LPCWSTR Get(void);
|
||||
HRESULT Set(size_t index, WCHAR value);
|
||||
HRESULT Append(LPCWSTR pszString);
|
||||
|
||||
|
||||
protected:
|
||||
LPWSTR buffer;
|
||||
LPWSTR cursor;
|
||||
size_t allocated;
|
||||
size_t remaining;
|
||||
};
|
||||
|
||||
#endif //NULLSOFT_WINAMP_STRING_BUILDER_HEADER
|
243
Src/Plugins/Library/ml_devices/gen_deviceprovider/strings.cpp
Normal file
243
Src/Plugins/Library/ml_devices/gen_deviceprovider/strings.cpp
Normal file
|
@ -0,0 +1,243 @@
|
|||
#include "main.h"
|
||||
#include "./strings.h"
|
||||
#include <strsafe.h>
|
||||
|
||||
|
||||
wchar_t *
|
||||
String_Malloc(size_t size)
|
||||
{
|
||||
return (wchar_t *)malloc(sizeof(wchar_t) * size);
|
||||
}
|
||||
|
||||
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, STRSAFE_IGNORE_NULLS)))
|
||||
return 0;
|
||||
|
||||
return (size - remaining);
|
||||
}
|
||||
|
||||
wchar_t *
|
||||
String_FromWindowEx(HWND hwnd, size_t *lengthOut, BOOL *errorOut)
|
||||
{
|
||||
BOOL error;
|
||||
size_t length;
|
||||
wchar_t *string;
|
||||
|
||||
error = TRUE;
|
||||
string = NULL;
|
||||
length = 0;
|
||||
|
||||
if (NULL != hwnd)
|
||||
{
|
||||
length = GetWindowTextLength(hwnd);
|
||||
if (0 != length ||
|
||||
ERROR_SUCCESS == GetLastError())
|
||||
{
|
||||
string = String_Malloc(length + 1);
|
||||
if(NULL != string)
|
||||
{
|
||||
if (0 == length)
|
||||
{
|
||||
string[0] = L'\0';
|
||||
error = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = GetWindowText(hwnd, string, (int)length + 1);
|
||||
if (0 == length && ERROR_SUCCESS != GetLastError())
|
||||
{
|
||||
String_Free(string);
|
||||
string = NULL;
|
||||
}
|
||||
else
|
||||
error = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != lengthOut)
|
||||
*lengthOut = length;
|
||||
|
||||
if (NULL != errorOut)
|
||||
*errorOut = error;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
char *
|
||||
AnsiString_Malloc(size_t size)
|
||||
{
|
||||
return (char*)malloc(sizeof(char) * size);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
wchar_t*
|
||||
ResourceString_Duplicate(const wchar_t *source)
|
||||
{
|
||||
return (FALSE != IS_INTRESOURCE(source)) ?
|
||||
(LPWSTR)source :
|
||||
String_Duplicate(source);
|
||||
}
|
||||
|
||||
void
|
||||
ResourceString_Free(wchar_t *string)
|
||||
{
|
||||
if (FALSE == IS_INTRESOURCE(string))
|
||||
String_Free(string);
|
||||
}
|
||||
|
||||
size_t
|
||||
ResourceString_CopyTo(wchar_t *destination, const wchar_t *source, size_t size)
|
||||
{
|
||||
if (NULL == destination)
|
||||
return 0;
|
||||
|
||||
if (NULL == source)
|
||||
{
|
||||
destination[0] = L'\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FALSE != IS_INTRESOURCE(source))
|
||||
{
|
||||
if (NULL == WASABI_API_LNG)
|
||||
{
|
||||
destination[0] = L'\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)source, destination, size);
|
||||
return lstrlenW(destination);
|
||||
}
|
||||
|
||||
return String_CopyTo(destination, source, size);
|
||||
}
|
82
Src/Plugins/Library/ml_devices/gen_deviceprovider/strings.h
Normal file
82
Src/Plugins/Library/ml_devices/gen_deviceprovider/strings.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_STRINGS_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_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);
|
||||
|
||||
wchar_t *
|
||||
String_FromWindowEx(HWND hwnd,
|
||||
size_t *lengthOut,
|
||||
BOOL *errorOut);
|
||||
|
||||
#define String_FromWindow(/*HWND*/ _hwnd)\
|
||||
String_FromWindowEx((_hwnd), NULL, NULL)
|
||||
|
||||
/*
|
||||
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);
|
||||
|
||||
/*
|
||||
Resource String
|
||||
*/
|
||||
|
||||
wchar_t*
|
||||
ResourceString_Duplicate(const wchar_t *source);
|
||||
|
||||
void
|
||||
ResourceString_Free(wchar_t *string);
|
||||
|
||||
size_t
|
||||
ResourceString_CopyTo(wchar_t *destination,
|
||||
const wchar_t *source,
|
||||
size_t size);
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_STRINGS_HEADER
|
|
@ -0,0 +1,108 @@
|
|||
#include "main.h"
|
||||
#include "./supportedCommand.h"
|
||||
|
||||
#include <strsafe.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;
|
||||
}
|
||||
|
||||
#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
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_SUPPORTED_COMMAND_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_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);
|
||||
|
||||
protected:
|
||||
size_t ref;
|
||||
char *name;
|
||||
DeviceCommandFlags flags;
|
||||
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_SUPPORTED_COMMAND_HEADER
|
555
Src/Plugins/Library/ml_devices/gen_deviceprovider/testSuite.cpp
Normal file
555
Src/Plugins/Library/ml_devices/gen_deviceprovider/testSuite.cpp
Normal file
|
@ -0,0 +1,555 @@
|
|||
#include "main.h"
|
||||
#include "./testSuite.h"
|
||||
|
||||
#include <strsafe.h>
|
||||
|
||||
TestSuite::TestSuite()
|
||||
{
|
||||
}
|
||||
|
||||
TestSuite::~TestSuite()
|
||||
{
|
||||
size_t index;
|
||||
|
||||
index = deviceList.size();
|
||||
while(index--)
|
||||
{
|
||||
deviceList[index]->Release();
|
||||
}
|
||||
|
||||
index = typeList.size();
|
||||
while(index--)
|
||||
{
|
||||
typeList[index]->Release();
|
||||
}
|
||||
|
||||
index = connectionList.size();
|
||||
while(index--)
|
||||
{
|
||||
connectionList[index]->Release();
|
||||
}
|
||||
|
||||
index = commandList.size();
|
||||
while(index--)
|
||||
{
|
||||
commandList[index]->Release();
|
||||
}
|
||||
|
||||
index = insertList.size();
|
||||
while(index--)
|
||||
{
|
||||
AnsiString_Free(insertList[index]);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL TestSuite::AddDevice(Device *device)
|
||||
{
|
||||
if (NULL == device)
|
||||
return FALSE;
|
||||
|
||||
deviceList.push_back(device);
|
||||
device->AddRef();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
size_t TestSuite::GetDeviceCount()
|
||||
{
|
||||
return deviceList.size();
|
||||
}
|
||||
|
||||
Device *TestSuite::GetDevice(size_t index)
|
||||
{
|
||||
return deviceList[index];
|
||||
}
|
||||
|
||||
static int
|
||||
String_RemoveCounter(wchar_t *string)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = lstrlenW(string);
|
||||
if (len > 3)
|
||||
{
|
||||
int cutoff = 0;
|
||||
if (string[len-1] == L')')
|
||||
{
|
||||
WORD charType;
|
||||
cutoff = 1;
|
||||
while(len > cutoff &&
|
||||
FALSE != GetStringTypeW(CT_CTYPE1, string + (len - 1) - cutoff, 1, &charType) &&
|
||||
0 != (C1_DIGIT & charType))
|
||||
{
|
||||
cutoff++;
|
||||
}
|
||||
|
||||
if (len > cutoff &&
|
||||
cutoff > 1 &&
|
||||
L'(' == string[len - 1 - cutoff])
|
||||
{
|
||||
cutoff++;
|
||||
if (len > cutoff &&
|
||||
L' ' == string[len - 1 - cutoff])
|
||||
{
|
||||
string[len - 1 - cutoff] = L'\0';
|
||||
len -= (cutoff + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
AnsiString_RemoveCounter(char *string)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = lstrlenA(string);
|
||||
if (len > 3)
|
||||
{
|
||||
int cutoff = 0;
|
||||
if (string[len-1] == ')')
|
||||
{
|
||||
WORD charType;
|
||||
cutoff = 1;
|
||||
while(len > cutoff &&
|
||||
FALSE != GetStringTypeA(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, string + (len - 1) - cutoff, 1, &charType) &&
|
||||
0 != (C1_DIGIT & charType))
|
||||
{
|
||||
cutoff++;
|
||||
}
|
||||
|
||||
if (len > cutoff &&
|
||||
cutoff > 1 &&
|
||||
'(' == string[len - 1 - cutoff])
|
||||
{
|
||||
cutoff++;
|
||||
if (len > cutoff &&
|
||||
' ' == string[len - 1 - cutoff])
|
||||
{
|
||||
string[len - 1 - cutoff] = '\0';
|
||||
len -= (cutoff + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
Device *TestSuite::CreateDeviceCopy(Device *source)
|
||||
{
|
||||
const char *name;
|
||||
size_t index, counter;
|
||||
char buffer[1024];
|
||||
wchar_t *displayName;
|
||||
BOOL found;
|
||||
Device *destination;
|
||||
int length;
|
||||
|
||||
if (NULL == source)
|
||||
return NULL;
|
||||
|
||||
found = FALSE;
|
||||
counter = 0;
|
||||
|
||||
name = source->GetName();
|
||||
StringCbCopyA(buffer, sizeof(buffer), name);
|
||||
length = AnsiString_RemoveCounter(buffer);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
||||
if (0 != counter)
|
||||
StringCbPrintfA(buffer + length, sizeof(buffer) - length, " (%d)", counter);
|
||||
|
||||
found = TRUE;
|
||||
|
||||
index = deviceList.size();
|
||||
while(index--)
|
||||
{
|
||||
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, deviceList[index]->GetName(), -1, buffer, -1))
|
||||
{
|
||||
found = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (FALSE != found)
|
||||
break;
|
||||
else
|
||||
counter++;
|
||||
}
|
||||
|
||||
if (FAILED(Device::CreateInstance(buffer, source->GetType(), source->GetConnection(), &destination)))
|
||||
return NULL;
|
||||
|
||||
source->CopyTo(destination);
|
||||
|
||||
source->GetDisplayName((wchar_t*)buffer, sizeof(buffer)/sizeof(wchar_t));
|
||||
displayName = (wchar_t*)buffer;
|
||||
length = String_RemoveCounter(displayName);
|
||||
|
||||
if (0 != counter)
|
||||
StringCchPrintf(displayName + length, sizeof(buffer)/sizeof(wchar_t) - length, L" (%d)", counter);
|
||||
|
||||
destination->SetDisplayName(displayName);
|
||||
|
||||
|
||||
return destination;
|
||||
|
||||
}
|
||||
Device *TestSuite::GetRandomDevice()
|
||||
{
|
||||
size_t index;
|
||||
Device *device;
|
||||
LARGE_INTEGER perfCounter;
|
||||
|
||||
if (0 == deviceList.size())
|
||||
return NULL;
|
||||
|
||||
if (FALSE != QueryPerformanceCounter(&perfCounter))
|
||||
srand(perfCounter.LowPart);
|
||||
else
|
||||
srand(GetTickCount());
|
||||
|
||||
index = (size_t)((double)rand()/(RAND_MAX + 1) * deviceList.size());
|
||||
device = deviceList[index];
|
||||
|
||||
if (S_OK == device->IsConnected())
|
||||
{
|
||||
size_t search;
|
||||
|
||||
for(search = index + 1; search < deviceList.size(); search++)
|
||||
{
|
||||
device = deviceList[search];
|
||||
if (S_FALSE == device->IsConnected())
|
||||
return device;
|
||||
}
|
||||
|
||||
search = index;
|
||||
while(search--)
|
||||
{
|
||||
device = deviceList[search];
|
||||
if (S_FALSE == device->IsConnected())
|
||||
return device;
|
||||
}
|
||||
|
||||
device = CreateDeviceCopy(deviceList[index]);
|
||||
if (NULL != device)
|
||||
{
|
||||
size_t totalSpace, usedSpace;
|
||||
totalSpace = (size_t)((double)rand()/(RAND_MAX + 1) * 1000);
|
||||
usedSpace = (size_t)((double)rand()/(RAND_MAX + 1) * totalSpace);
|
||||
|
||||
device->SetTotalSpace(totalSpace);
|
||||
device->SetUsedSpace(usedSpace);
|
||||
|
||||
device->Disconnect();
|
||||
device->Detach(NULL);
|
||||
AddDevice(device);
|
||||
}
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
BOOL TestSuite::AddType(ifc_devicetype *type)
|
||||
{
|
||||
if (NULL == type)
|
||||
return FALSE;
|
||||
|
||||
typeList.push_back(type);
|
||||
type->AddRef();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
size_t TestSuite::GetTypeCount()
|
||||
{
|
||||
return typeList.size();
|
||||
}
|
||||
|
||||
ifc_devicetype *TestSuite::GetType(size_t index)
|
||||
{
|
||||
return typeList[index];
|
||||
}
|
||||
|
||||
|
||||
BOOL TestSuite::RegisterTypes(api_devicemanager *manager)
|
||||
{
|
||||
if (NULL == manager)
|
||||
return FALSE;
|
||||
|
||||
if (0 != typeList.size())
|
||||
manager->TypeRegister((ifc_devicetype**)typeList.begin(), typeList.size());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL TestSuite::UnregisterTypes(api_devicemanager *manager)
|
||||
{
|
||||
size_t index;
|
||||
if (NULL == manager)
|
||||
return FALSE;
|
||||
|
||||
index = typeList.size();
|
||||
while(index--)
|
||||
{
|
||||
manager->TypeUnregister(typeList[index]->GetName());
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL TestSuite::SetIconBase(const wchar_t *path)
|
||||
{
|
||||
size_t index;
|
||||
Device *device;
|
||||
ifc_devicetype *type;
|
||||
ifc_devicetypeeditor *typeEditor;
|
||||
ifc_deviceiconstore *iconStore;
|
||||
ifc_deviceconnection *connection;
|
||||
ifc_deviceconnectioneditor *connectionEditor;
|
||||
ifc_devicecommand *command;
|
||||
ifc_devicecommandeditor *commandEditor;
|
||||
|
||||
index = deviceList.size();
|
||||
while(index--)
|
||||
{
|
||||
device = deviceList[index];
|
||||
device->SetIconBase(path);
|
||||
}
|
||||
|
||||
index = typeList.size();
|
||||
while(index--)
|
||||
{
|
||||
type = typeList[index];
|
||||
if (SUCCEEDED(type->QueryInterface(IFC_DeviceTypeEditor, (void**)&typeEditor)))
|
||||
{
|
||||
if(SUCCEEDED(typeEditor->GetIconStore(&iconStore)))
|
||||
{
|
||||
iconStore->SetBasePath(path);
|
||||
iconStore->Release();
|
||||
}
|
||||
typeEditor->Release();
|
||||
}
|
||||
}
|
||||
|
||||
index = commandList.size();
|
||||
while(index--)
|
||||
{
|
||||
command = commandList[index];
|
||||
if (SUCCEEDED(command->QueryInterface(IFC_DeviceCommandEditor, (void**)&commandEditor)))
|
||||
{
|
||||
if(SUCCEEDED(commandEditor->GetIconStore(&iconStore)))
|
||||
{
|
||||
iconStore->SetBasePath(path);
|
||||
iconStore->Release();
|
||||
}
|
||||
commandEditor->Release();
|
||||
}
|
||||
}
|
||||
|
||||
index = connectionList.size();
|
||||
while(index--)
|
||||
{
|
||||
connection = connectionList[index];
|
||||
if (SUCCEEDED(connection->QueryInterface(IFC_DeviceConnectionEditor, (void**)&connectionEditor)))
|
||||
{
|
||||
if(SUCCEEDED(connectionEditor->GetIconStore(&iconStore)))
|
||||
{
|
||||
iconStore->SetBasePath(path);
|
||||
iconStore->Release();
|
||||
}
|
||||
connectionEditor->Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL TestSuite::SetConnectList(char **devices, size_t count)
|
||||
{
|
||||
size_t index;
|
||||
char *name;
|
||||
|
||||
index = insertList.size();
|
||||
if (index > 0)
|
||||
{
|
||||
while(index--)
|
||||
{
|
||||
name = insertList[index];
|
||||
AnsiString_Free(name);
|
||||
}
|
||||
insertList.clear();
|
||||
}
|
||||
|
||||
for(index = 0; index < count; index++)
|
||||
{
|
||||
name = AnsiString_Duplicate(devices[index]);
|
||||
if (NULL != name)
|
||||
insertList.push_back(name);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Device *TestSuite::GetDeviceByName(const char *name)
|
||||
{
|
||||
size_t index;
|
||||
Device *device;
|
||||
|
||||
for (index = 0; index < deviceList.size(); index++)
|
||||
{
|
||||
device = deviceList[index];
|
||||
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, name, -1, device->GetName(), -1))
|
||||
return device;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL TestSuite::RegisterDevices(api_devicemanager *manager)
|
||||
{
|
||||
size_t index;
|
||||
const char *name;
|
||||
Device *device;
|
||||
|
||||
if (NULL == manager)
|
||||
return FALSE;
|
||||
|
||||
for (index = 0; index < insertList.size(); index++)
|
||||
{
|
||||
name = insertList[index];
|
||||
device = GetDeviceByName(name);
|
||||
if (NULL != device)
|
||||
{
|
||||
manager->DeviceRegister((ifc_device**)&device, 1);
|
||||
device->Connect();
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL TestSuite::UnregisterDevices(api_devicemanager *manager)
|
||||
{
|
||||
size_t index;
|
||||
Device *device;
|
||||
|
||||
if (NULL == manager)
|
||||
return FALSE;
|
||||
|
||||
index = deviceList.size();
|
||||
while(index--)
|
||||
{
|
||||
device = deviceList[index];
|
||||
if (S_OK == device->IsConnected())
|
||||
{
|
||||
device->Disconnect();
|
||||
manager->DeviceUnregister(device->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL TestSuite::AddConnection(ifc_deviceconnection *connection)
|
||||
{
|
||||
if (NULL == connection)
|
||||
return FALSE;
|
||||
|
||||
connectionList.push_back(connection);
|
||||
connection->AddRef();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
size_t TestSuite::GetConnectionCount()
|
||||
{
|
||||
return connectionList.size();
|
||||
}
|
||||
|
||||
ifc_deviceconnection *TestSuite::GetConnection(size_t index)
|
||||
{
|
||||
return connectionList[index];
|
||||
}
|
||||
|
||||
BOOL TestSuite::RegisterConnections(api_devicemanager *manager)
|
||||
{
|
||||
if (NULL == manager)
|
||||
return FALSE;
|
||||
|
||||
if (0 != connectionList.size())
|
||||
manager->ConnectionRegister((ifc_deviceconnection**)connectionList.begin(), connectionList.size());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL TestSuite::UnregisterConnections(api_devicemanager *manager)
|
||||
{
|
||||
size_t index;
|
||||
if (NULL == manager)
|
||||
return FALSE;
|
||||
|
||||
index = connectionList.size();
|
||||
while(index--)
|
||||
{
|
||||
manager->ConnectionUnregister(connectionList[index]->GetName());
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL TestSuite::AddCommand(ifc_devicecommand *command)
|
||||
{
|
||||
if (NULL == command)
|
||||
return FALSE;
|
||||
|
||||
commandList.push_back(command);
|
||||
command->AddRef();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
size_t TestSuite::GetCommandCount()
|
||||
{
|
||||
return commandList.size();
|
||||
}
|
||||
|
||||
ifc_devicecommand *TestSuite::GetCommand(size_t index)
|
||||
{
|
||||
return commandList[index];
|
||||
}
|
||||
|
||||
BOOL TestSuite::RegisterCommands(api_devicemanager *manager)
|
||||
{
|
||||
if (NULL == manager)
|
||||
return FALSE;
|
||||
|
||||
if (0 != commandList.size())
|
||||
manager->CommandRegister((ifc_devicecommand**)commandList.begin(), commandList.size());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL TestSuite::UnregisterCommands(api_devicemanager *manager)
|
||||
{
|
||||
size_t index;
|
||||
if (NULL == manager)
|
||||
return FALSE;
|
||||
|
||||
index = commandList.size();
|
||||
while(index--)
|
||||
{
|
||||
manager->CommandUnregister(commandList[index]->GetName());
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include <vector>
|
||||
#include "./device.h"
|
||||
|
||||
class TestSuite
|
||||
{
|
||||
public:
|
||||
TestSuite();
|
||||
~TestSuite();
|
||||
|
||||
public:
|
||||
BOOL AddDevice(Device *device);
|
||||
size_t GetDeviceCount();
|
||||
Device *GetDevice(size_t index);
|
||||
Device *GetRandomDevice();
|
||||
Device *CreateDeviceCopy(Device *source);
|
||||
Device *GetDeviceByName(const char *name);
|
||||
BOOL RegisterDevices(api_devicemanager *manager);
|
||||
BOOL UnregisterDevices(api_devicemanager *manager);
|
||||
|
||||
BOOL AddType(ifc_devicetype *type);
|
||||
size_t GetTypeCount();
|
||||
ifc_devicetype *GetType(size_t index);
|
||||
BOOL RegisterTypes(api_devicemanager *manager);
|
||||
BOOL UnregisterTypes(api_devicemanager *manager);
|
||||
|
||||
BOOL AddConnection(ifc_deviceconnection *connection);
|
||||
size_t GetConnectionCount();
|
||||
ifc_deviceconnection *GetConnection(size_t index);
|
||||
BOOL RegisterConnections(api_devicemanager *manager);
|
||||
BOOL UnregisterConnections(api_devicemanager *manager);
|
||||
|
||||
BOOL AddCommand(ifc_devicecommand *command);
|
||||
size_t GetCommandCount();
|
||||
ifc_devicecommand *GetCommand(size_t index);
|
||||
BOOL RegisterCommands(api_devicemanager *manager);
|
||||
BOOL UnregisterCommands(api_devicemanager *manager);
|
||||
|
||||
BOOL SetIconBase(const wchar_t *path);
|
||||
BOOL SetConnectList(char **devices, size_t count);
|
||||
|
||||
private:
|
||||
typedef std::vector<Device*> DeviceList;
|
||||
typedef std::vector<ifc_devicetype*> TypeList;
|
||||
typedef std::vector<ifc_deviceconnection*> ConnectionList;
|
||||
typedef std::vector<ifc_devicecommand*> CommandList;
|
||||
|
||||
typedef std::vector<char*> NameList;
|
||||
|
||||
private:
|
||||
DeviceList deviceList;
|
||||
TypeList typeList;
|
||||
ConnectionList connectionList;
|
||||
CommandList commandList;
|
||||
NameList insertList;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_HEADER
|
|
@ -0,0 +1,226 @@
|
|||
#include "main.h"
|
||||
#include "./testSuiteLoader.h"
|
||||
|
||||
#include "../../xml/obj_xml.h"
|
||||
#include <api/service/waservicefactory.h>
|
||||
|
||||
#include <strsafe.h>
|
||||
|
||||
|
||||
typedef void (CALLBACK *LOADERTAGCALLBACK)(TestSuiteLoader* /*loader*/, const wchar_t* /*value*/);
|
||||
|
||||
typedef struct LOADERTAG
|
||||
{
|
||||
const wchar_t *name;
|
||||
LOADERTAGCALLBACK callback;
|
||||
} LOADERTAG;
|
||||
|
||||
static void CALLBACK
|
||||
LoaderTag_ImageBase(TestSuiteLoader *loader, const wchar_t *value)
|
||||
{
|
||||
String_Free(loader->imageBase);
|
||||
loader->imageBase = String_Duplicate(value);
|
||||
}
|
||||
|
||||
static void CALLBACK
|
||||
LoaderTag_Connect(TestSuiteLoader *loader, const wchar_t *value)
|
||||
{
|
||||
if (IS_STRING_EMPTY(value))
|
||||
return;
|
||||
|
||||
const wchar_t *block, *cursor;
|
||||
char *name;
|
||||
size_t length;
|
||||
|
||||
block = value;
|
||||
cursor = block;
|
||||
for(;;)
|
||||
{
|
||||
if (L'\0' == *cursor ||
|
||||
L';' == *cursor ||
|
||||
L',' == *cursor)
|
||||
{
|
||||
|
||||
if (block < cursor)
|
||||
{
|
||||
length = cursor - block;
|
||||
name = String_ToAnsi(CP_UTF8, 0, block, (int)length, NULL, NULL);
|
||||
if (NULL != name)
|
||||
loader->connectList.push_back(name);
|
||||
}
|
||||
|
||||
if (L'\0' == *cursor)
|
||||
break;
|
||||
|
||||
block = cursor + 1;
|
||||
}
|
||||
cursor++;
|
||||
}
|
||||
//loader->SetImageBase(value);
|
||||
}
|
||||
|
||||
|
||||
static const LOADERTAG knownTags[LOADER_TAG_MAX] =
|
||||
{
|
||||
{L"imageBase", LoaderTag_ImageBase},
|
||||
{L"connect", LoaderTag_Connect},
|
||||
};
|
||||
|
||||
TestSuiteLoader::TestSuiteLoader()
|
||||
: imageBase(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
TestSuiteLoader::~TestSuiteLoader()
|
||||
{
|
||||
size_t index;
|
||||
|
||||
index = connectList.size();
|
||||
while(index--)
|
||||
{
|
||||
AnsiString_Free(connectList[index]);
|
||||
}
|
||||
|
||||
String_Free(imageBase);
|
||||
|
||||
}
|
||||
|
||||
BOOL TestSuiteLoader::Load(const wchar_t *path, TestSuite *testSuite)
|
||||
{
|
||||
BOOL result;
|
||||
HANDLE fileHandle;
|
||||
obj_xml *reader;
|
||||
|
||||
if (NULL == testSuite)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == path || L'\0' == *path)
|
||||
return FALSE;
|
||||
|
||||
fileHandle = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||
if (INVALID_HANDLE_VALUE == fileHandle)
|
||||
return FALSE;
|
||||
|
||||
result = FALSE;
|
||||
if (NULL != WASABI_API_SVC)
|
||||
{
|
||||
waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID);
|
||||
reader = (NULL != sf) ? (obj_xml*)sf->getInterface() : NULL;
|
||||
if (NULL != reader)
|
||||
{
|
||||
if (OBJ_XML_SUCCESS == reader->xmlreader_open())
|
||||
{
|
||||
reader->xmlreader_registerCallback(L"testprovider\fimageBase", this);
|
||||
reader->xmlreader_registerCallback(L"testprovider\fconnect", this);
|
||||
ZeroMemory(hitList, sizeof(hitList));
|
||||
|
||||
deviceParser.Begin(reader, testSuite);
|
||||
typeParser.Begin(reader, testSuite);
|
||||
connectionParser.Begin(reader, testSuite);
|
||||
commandParser.Begin(reader, testSuite);
|
||||
|
||||
result = FeedFile(reader, fileHandle, 8192);
|
||||
|
||||
deviceParser.End();
|
||||
typeParser.End();
|
||||
connectionParser.End();
|
||||
commandParser.End();
|
||||
|
||||
reader->xmlreader_close();
|
||||
|
||||
testSuite->SetIconBase(imageBase);
|
||||
testSuite->SetConnectList(connectList.begin(), connectList.size());
|
||||
|
||||
}
|
||||
sf->releaseInterface(reader);
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(fileHandle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL TestSuiteLoader::FeedFile(obj_xml *reader, HANDLE fileHandle, DWORD bufferSize)
|
||||
{
|
||||
BOOL result;
|
||||
DWORD read;
|
||||
BYTE *buffer;
|
||||
int readerCode;
|
||||
|
||||
if (NULL == reader ||
|
||||
INVALID_HANDLE_VALUE == fileHandle ||
|
||||
0 == bufferSize)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
buffer = (BYTE*)malloc(bufferSize);
|
||||
if (NULL == buffer)
|
||||
return FALSE;
|
||||
|
||||
|
||||
readerCode = OBJ_XML_SUCCESS;
|
||||
result = TRUE;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if (FALSE == ReadFile(fileHandle, buffer, bufferSize, &read, NULL) || 0 == read)
|
||||
{
|
||||
result = FALSE;
|
||||
|
||||
if (0 == read && OBJ_XML_SUCCESS == readerCode)
|
||||
reader->xmlreader_feed(0, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
readerCode = reader->xmlreader_feed(buffer, read);
|
||||
if (OBJ_XML_SUCCESS != readerCode)
|
||||
{
|
||||
result = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TestSuiteLoader::Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
|
||||
{
|
||||
elementString.Clear();
|
||||
}
|
||||
|
||||
void TestSuiteLoader::Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag)
|
||||
{
|
||||
for (size_t i = 0; i < LOADER_TAG_MAX; i++)
|
||||
{
|
||||
if (FALSE == hitList[i] &&
|
||||
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, knownTags[i].name, -1, xmltag, -1))
|
||||
{
|
||||
knownTags[i].callback(this, elementString.Get());
|
||||
hitList[i] = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestSuiteLoader::Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value)
|
||||
{
|
||||
elementString.Append(value);
|
||||
}
|
||||
|
||||
void TestSuiteLoader::Event_XmlError(int linenum, int errcode, const wchar_t *errstr)
|
||||
{
|
||||
elementString.Clear();
|
||||
}
|
||||
|
||||
#define CBCLASS TestSuiteLoader
|
||||
START_DISPATCH;
|
||||
VCB(ONSTARTELEMENT, Event_XmlStartElement)
|
||||
VCB(ONENDELEMENT, Event_XmlEndElement)
|
||||
VCB(ONCHARDATA, Event_XmlCharData)
|
||||
VCB(ONERROR, Event_XmlError)
|
||||
END_DISPATCH;
|
||||
#undef CBCLASS
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_LOADER_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_LOADER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "../../xml/ifc_xmlreadercallback.h"
|
||||
#include <vector>
|
||||
#include "./DeviceNodeParser.h"
|
||||
#include "./DeviceTypeNodeParser.h"
|
||||
#include "./DeviceConnectionNodeParser.h"
|
||||
#include "./DeviceCommandNodeParser.h"
|
||||
|
||||
class obj_xml;
|
||||
|
||||
#define LOADER_TAG_MAX 2
|
||||
|
||||
class TestSuiteLoader : public ifc_xmlreadercallback
|
||||
{
|
||||
|
||||
public:
|
||||
TestSuiteLoader();
|
||||
~TestSuiteLoader();
|
||||
|
||||
public:
|
||||
BOOL Load(const wchar_t *path, TestSuite *testSuite);
|
||||
|
||||
private:
|
||||
BOOL FeedFile(obj_xml *reader, HANDLE hFile, DWORD bufferSize);
|
||||
|
||||
void Event_XmlStartElement(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
|
||||
void Event_XmlEndElement(const wchar_t *xmlpath, const wchar_t *xmltag);
|
||||
void Event_XmlCharData(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *value);
|
||||
void Event_XmlError(int linenum, int errcode, const wchar_t *errstr);
|
||||
|
||||
protected:
|
||||
friend static void CALLBACK LoaderTag_ImageBase(TestSuiteLoader *loader, const wchar_t *value);
|
||||
friend static void CALLBACK LoaderTag_Connect(TestSuiteLoader *loader, const wchar_t *value);
|
||||
protected:
|
||||
typedef std::vector<char*> NameList;
|
||||
|
||||
protected:
|
||||
StringBuilder elementString;
|
||||
DeviceNodeParser deviceParser;
|
||||
DeviceTypeNodeParser typeParser;
|
||||
DeviceConnectionNodeParser connectionParser;
|
||||
DeviceCommandNodeParser commandParser;
|
||||
BOOL hitList[LOADER_TAG_MAX];
|
||||
|
||||
wchar_t *imageBase;
|
||||
|
||||
NameList connectList;
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
};
|
||||
|
||||
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_TEST_SUITE_LOADER_HEADER
|
|
@ -0,0 +1,244 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testprovider>
|
||||
<imageBase>c:\winamp\ml_devices\resources\food</imageBase>
|
||||
<connect>iconTest;apple;banana;grape;pear;pepper;eggplant;cucumber;carrot</connect>
|
||||
<connections>
|
||||
<connection name="usb">
|
||||
<displayName>USB</displayName>
|
||||
<icon>..\connections\usb.png</icon>
|
||||
</connection>
|
||||
<connection name="wifi">
|
||||
<displayName>Wi-Fi</displayName>
|
||||
<icon>..\connections\wifi.png</icon>
|
||||
</connection>
|
||||
<connection name="bluetooth">
|
||||
<displayName>Bluetooth</displayName>
|
||||
<icon>..\connections\bluetooth.png</icon>
|
||||
</connection>
|
||||
</connections>
|
||||
<types>
|
||||
<type name="vegetables">
|
||||
<displayName>Vegetables</displayName>
|
||||
<icon>vegetables.png</icon>
|
||||
</type>
|
||||
<type name="fruits">
|
||||
<displayName>Fruits</displayName>
|
||||
<icon>fruits.png</icon>
|
||||
</type>
|
||||
<type name="grains">
|
||||
<displayName>Grains</displayName>
|
||||
<icon>grains.png</icon>
|
||||
</type>
|
||||
</types>
|
||||
<commands>
|
||||
<command name="sync">
|
||||
<displayName>&Sync</displayName>
|
||||
<description>Sync things</description>
|
||||
<icon>..\commands\sync.png</icon>
|
||||
</command>
|
||||
<command name="settings">
|
||||
<displayName>Se&ttings</displayName>
|
||||
<description>Open settings page</description>
|
||||
<icon>..\commands\settings.png</icon>
|
||||
</command>
|
||||
<command name="detach">
|
||||
<displayName>&Detach</displayName>
|
||||
<description>Detach device</description>
|
||||
<icon>..\commands\detach.png</icon>
|
||||
</command>
|
||||
<command name="eject">
|
||||
<displayName>&Eject</displayName>
|
||||
<description>Eject device</description>
|
||||
<icon>..\commands\eject.png</icon>
|
||||
</command>
|
||||
</commands>
|
||||
<devices>
|
||||
<device name="iconTest" type="test">
|
||||
<connection></connection>
|
||||
<displayName>Icon Test</displayName>
|
||||
<icon width="24" height="32">..\zoom\24x32.png</icon>
|
||||
<icon width="48" height="64">..\zoom\48x64.png</icon>
|
||||
<icon width="96" height="128">..\zoom\96x128.png</icon>
|
||||
<icon width="192" height="256">..\zoom\192x256.png</icon>
|
||||
<command primary="1" disabled="0">sync</command>
|
||||
<command primary="0" disabled="0" hidden="0" group="1">settings</command>
|
||||
<command primary="0">detach</command>
|
||||
<command disabled="1" hidden="0">eject</command>
|
||||
<totalSpace>909242</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<model>Icon Test v1.0</model>
|
||||
<status>Icon Test status string</status>
|
||||
</device>
|
||||
<device name="apple" type="fruits">
|
||||
<connection>wifi</connection>
|
||||
<displayName>Dilicious Apple</displayName>
|
||||
<icon>apple.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<model>iApple 2</model>
|
||||
<command primary="1">sync</command>
|
||||
<command group="1">eject</command>
|
||||
</device>
|
||||
<device name="banana" type="fruits">
|
||||
<connection>usb</connection>
|
||||
<displayName>Banana</displayName>
|
||||
<icon>banana.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<model>iBanana 2</model>
|
||||
<command primary="1">sync</command>
|
||||
<command group="1">eject</command>
|
||||
</device>
|
||||
<device name="peach" type="fruits">
|
||||
<connection>bluetooth</connection>
|
||||
<displayName>Peach</displayName>
|
||||
<icon>peach.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<model>iPeach 2</model>
|
||||
<command primary="1">sync</command>
|
||||
<command group="1">eject</command>
|
||||
</device>
|
||||
<device name="orange" type="fruits">
|
||||
<connection>usb</connection>
|
||||
<displayName>Orange</displayName>
|
||||
<icon>orange.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<model>iOrange 2</model>
|
||||
<command primary="1">sync</command>
|
||||
<command group="1">eject</command>
|
||||
</device>
|
||||
<device name="pear" type="fruits">
|
||||
<connection>wifi</connection>
|
||||
<displayName>Pear</displayName>
|
||||
<icon>pear.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<model>iPear 2</model>
|
||||
<command primary="1">sync</command>
|
||||
<command group="1">eject</command>
|
||||
</device>
|
||||
<device name="grape" type="fruits">
|
||||
<connection>bluetooth</connection>
|
||||
<displayName>Grape</displayName>
|
||||
<icon>grape.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<model>iGrape 2</model>
|
||||
<command primary="1">sync</command>
|
||||
<command group="1">eject</command>
|
||||
</device>
|
||||
<device name="lemon" type="fruits">
|
||||
<connection>usb</connection>
|
||||
<displayName>Lemon</displayName>
|
||||
<icon>lemon.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<model>iLemon 2</model>
|
||||
<command primary="1">sync</command>
|
||||
<command group="1">eject</command>
|
||||
</device>
|
||||
<device name="carrot" type="vegetables">
|
||||
<connection>wifi</connection>
|
||||
<displayName>Carrot</displayName>
|
||||
<icon>carrot.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<command primary="1">sync</command>
|
||||
</device>
|
||||
<device name="broccoli" type="vegetables">
|
||||
<connection>bluetooth</connection>
|
||||
<displayName>Broccoli</displayName>
|
||||
<icon>broccoli.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<command primary="1">sync</command>
|
||||
</device>
|
||||
<device name="eggplant" type="vegetables">
|
||||
<connection>usb</connection>
|
||||
<displayName>Eggplant</displayName>
|
||||
<icon>eggplant.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<command primary="1">sync</command>
|
||||
</device>
|
||||
<device name="cucumber" type="vegetables">
|
||||
<connection>wifi</connection>
|
||||
<displayName>Cucumber</displayName>
|
||||
<icon>cucumber.png</icon>
|
||||
<totalSpace>0</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<command primary="1">sync</command>
|
||||
</device>
|
||||
<device name="pepper" type="vegetables">
|
||||
<connection>bluetooth</connection>
|
||||
<displayName>Pepper</displayName>
|
||||
<icon>pepper.png</icon>
|
||||
<totalSpace>0</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
<command primary="1">sync</command>
|
||||
</device>
|
||||
<device name="bread" type="grains">
|
||||
<connection>usb</connection>
|
||||
<displayName>Bread</displayName>
|
||||
<icon>bread.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
</device>
|
||||
<device name="pasta" type="grains">
|
||||
<connection>wifi</connection>
|
||||
<displayName>Pasta</displayName>
|
||||
<icon>pasta.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
</device>
|
||||
<device name="rice" type="grains">
|
||||
<connection>bluetooth</connection>
|
||||
<displayName>Rice</displayName>
|
||||
<icon>rice.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
</device>
|
||||
<device name="cereal" type="grains">
|
||||
<connection>usb</connection>
|
||||
<displayName>Cereal</displayName>
|
||||
<icon>cereal.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
</device>
|
||||
<device name="muffin" type="grains">
|
||||
<connection>wifi</connection>
|
||||
<displayName>Muffin</displayName>
|
||||
<icon>muffin.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
</device>
|
||||
<device name="pretzel" type="grains">
|
||||
<connection>bluetooth</connection>
|
||||
<displayName>Pretzel</displayName>
|
||||
<icon>pretzel.png</icon>
|
||||
<totalSpace>100</totalSpace>
|
||||
<usedSpace>0</usedSpace>
|
||||
<hidden>0</hidden>
|
||||
</device>
|
||||
</devices>
|
||||
</testprovider>
|
139
Src/Plugins/Library/ml_devices/gen_deviceprovider/wasabi.cpp
Normal file
139
Src/Plugins/Library/ml_devices/gen_deviceprovider/wasabi.cpp
Normal file
|
@ -0,0 +1,139 @@
|
|||
#include "main.h"
|
||||
#include "./wasabi.h"
|
||||
|
||||
#include <api/service/waservicefactory.h>
|
||||
|
||||
api_service *WASABI_API_SVC = NULL;
|
||||
api_application *WASABI_API_APP = NULL;
|
||||
api_language *WASABI_API_LNG = NULL;
|
||||
api_devicemanager *WASABI_API_DEVICES = NULL;
|
||||
|
||||
HINSTANCE WASABI_API_LNG_HINST = NULL;
|
||||
HINSTANCE WASABI_API_ORIG_HINST = NULL;
|
||||
|
||||
static unsigned long wasabiReference = 0;
|
||||
static BOOL defaultServicesLoaded = FALSE;
|
||||
|
||||
static void
|
||||
Wasabi_Uninitialize()
|
||||
{
|
||||
if (NULL != WASABI_API_SVC)
|
||||
{
|
||||
Wasabi_ReleaseInterface(applicationApiServiceGuid, WASABI_API_APP);
|
||||
Wasabi_ReleaseInterface(languageApiGUID, WASABI_API_LNG);
|
||||
Wasabi_ReleaseInterface(DeviceManagerGUID, WASABI_API_DEVICES);
|
||||
}
|
||||
|
||||
WASABI_API_SVC = NULL;
|
||||
WASABI_API_APP = NULL;
|
||||
WASABI_API_LNG = NULL;
|
||||
WASABI_API_DEVICES = NULL;
|
||||
defaultServicesLoaded = FALSE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Wasabi_Initialize(HINSTANCE instance, api_service *serviceMngr)
|
||||
{
|
||||
if (NULL != WASABI_API_SVC)
|
||||
return FALSE;
|
||||
|
||||
defaultServicesLoaded = FALSE;
|
||||
|
||||
WASABI_API_SVC = serviceMngr;
|
||||
if ((api_service*)1 == WASABI_API_SVC)
|
||||
WASABI_API_SVC = NULL;
|
||||
|
||||
if (NULL == WASABI_API_SVC)
|
||||
return FALSE;
|
||||
|
||||
WASABI_API_APP = NULL;
|
||||
WASABI_API_DEVICES = NULL;
|
||||
|
||||
WASABI_API_LNG = NULL;
|
||||
WASABI_API_ORIG_HINST = instance;
|
||||
WASABI_API_LNG_HINST = WASABI_API_ORIG_HINST;
|
||||
|
||||
Wasabi_AddRef();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Wasabi_InitializeFromWinamp(HINSTANCE instance, HWND winampWindow)
|
||||
{
|
||||
api_service *serviceMngr;
|
||||
serviceMngr = (api_service*)SENDWAIPC(winampWindow, IPC_GET_API_SERVICE, 0);
|
||||
return Wasabi_Initialize(instance, serviceMngr);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Wasabi_LoadDefaultServices(void)
|
||||
{
|
||||
if (NULL == WASABI_API_SVC)
|
||||
return FALSE;
|
||||
|
||||
if (FALSE != defaultServicesLoaded)
|
||||
return FALSE;
|
||||
|
||||
WASABI_API_APP = Wasabi_QueryInterface(api_application, applicationApiServiceGuid);
|
||||
WASABI_API_DEVICES = Wasabi_QueryInterface(api_devicemanager, DeviceManagerGUID);
|
||||
|
||||
WASABI_API_LNG = Wasabi_QueryInterface(api_language, languageApiGUID);
|
||||
if (NULL != WASABI_API_LNG)
|
||||
{
|
||||
WASABI_API_LNG_HINST = WASABI_API_LNG->StartLanguageSupport(WASABI_API_ORIG_HINST,
|
||||
PLUGIN_LANGUAGE_ID);
|
||||
}
|
||||
|
||||
defaultServicesLoaded = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
Wasabi_AddRef(void)
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&wasabiReference);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
Wasabi_Release(void)
|
||||
{
|
||||
if (0 == wasabiReference)
|
||||
return wasabiReference;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&wasabiReference);
|
||||
if (0 == r)
|
||||
{
|
||||
Wasabi_Uninitialize();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void *
|
||||
Wasabi_QueryInterface0(const GUID &interfaceGuid)
|
||||
{
|
||||
waServiceFactory *serviceFactory;
|
||||
|
||||
if (NULL == WASABI_API_SVC)
|
||||
return NULL;
|
||||
|
||||
serviceFactory = WASABI_API_SVC->service_getServiceByGuid(interfaceGuid);
|
||||
if (NULL == serviceFactory)
|
||||
return NULL;
|
||||
|
||||
return serviceFactory->getInterface();
|
||||
}
|
||||
|
||||
void
|
||||
Wasabi_ReleaseInterface0(const GUID &interfaceGuid, void *interfaceInstance)
|
||||
{
|
||||
waServiceFactory *serviceFactory;
|
||||
|
||||
if (NULL == WASABI_API_SVC)
|
||||
return;
|
||||
|
||||
serviceFactory = WASABI_API_SVC->service_getServiceByGuid(interfaceGuid);
|
||||
if (NULL == serviceFactory)
|
||||
return;
|
||||
|
||||
serviceFactory->releaseInterface(interfaceInstance);
|
||||
}
|
57
Src/Plugins/Library/ml_devices/gen_deviceprovider/wasabi.h
Normal file
57
Src/Plugins/Library/ml_devices/gen_deviceprovider/wasabi.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
#ifndef _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_WASABI_HEADER
|
||||
#define _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_WASABI_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <api/service/api_service.h>
|
||||
extern api_service *wasabiManager;
|
||||
#define WASABI_API_SVC wasabiManager
|
||||
|
||||
#include <api/application/api_application.h>
|
||||
#define WASABI_API_APP applicationApi
|
||||
|
||||
#include "../Agave/Language/api_language.h"
|
||||
|
||||
#include "../../devices/api_devicemanager.h"
|
||||
extern api_devicemanager *deviceManagerApi;
|
||||
#define WASABI_API_DEVICES deviceManagerApi
|
||||
|
||||
BOOL
|
||||
Wasabi_Initialize(HINSTANCE instance,
|
||||
api_service *serviceMngr);
|
||||
|
||||
BOOL
|
||||
Wasabi_InitializeFromWinamp(HINSTANCE instance,
|
||||
HWND winampWindow);
|
||||
|
||||
BOOL
|
||||
Wasabi_LoadDefaultServices(void);
|
||||
|
||||
unsigned long
|
||||
Wasabi_AddRef(void);
|
||||
|
||||
unsigned long
|
||||
Wasabi_Release(void);
|
||||
|
||||
void *
|
||||
Wasabi_QueryInterface0(const GUID &interfaceGuid);
|
||||
|
||||
#define Wasabi_QueryInterface(_interfaceType, _interfaceGuid)\
|
||||
((##_interfaceType*)Wasabi_QueryInterface0(_interfaceGuid))
|
||||
|
||||
|
||||
void
|
||||
Wasabi_ReleaseInterface0(const GUID &interfaceGuid,
|
||||
void *interfaceInstance);
|
||||
|
||||
#define Wasabi_ReleaseInterface(_interfaceGuid, _interfaceInstance)\
|
||||
(Wasabi_ReleaseInterface0((_interfaceGuid), (_interfaceInstance)))
|
||||
|
||||
|
||||
#define Wasabi_ReleaseObject(_object)\
|
||||
{if (NULL != (_object)) {((Dispatchable*)(_object))->Release();}}
|
||||
|
||||
|
||||
#endif // _NULLSOFT_WINAMP_GEN_DEVICE_PROVIDER_WASABI_HEADER
|
313
Src/Plugins/Library/ml_devices/graphics.cpp
Normal file
313
Src/Plugins/Library/ml_devices/graphics.cpp
Normal file
|
@ -0,0 +1,313 @@
|
|||
#include "main.h"
|
||||
#include "./graphics.h"
|
||||
|
||||
BYTE
|
||||
Graphics_GetSysFontQuality()
|
||||
{
|
||||
BOOL smoothingEnabled;
|
||||
if (FALSE == SystemParametersInfoW(SPI_GETFONTSMOOTHING, 0, &smoothingEnabled, 0) ||
|
||||
FALSE == smoothingEnabled)
|
||||
{
|
||||
return DEFAULT_QUALITY;
|
||||
}
|
||||
|
||||
OSVERSIONINFOW vi;
|
||||
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||
if (FALSE == GetVersionExW(&vi))
|
||||
return DEFAULT_QUALITY;
|
||||
|
||||
if (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion >= 1))
|
||||
{
|
||||
UINT smootingType;
|
||||
if (FALSE == SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &smootingType, 0))
|
||||
return DEFAULT_QUALITY;
|
||||
|
||||
if (FE_FONTSMOOTHINGCLEARTYPE == smootingType)
|
||||
return CLEARTYPE_NATURAL_QUALITY/*CLEARTYPE_QUALITY*/;
|
||||
}
|
||||
|
||||
return ANTIALIASED_QUALITY;
|
||||
}
|
||||
|
||||
HFONT
|
||||
Graphics_CreateSysFont()
|
||||
{
|
||||
LOGFONTW lf = {0};
|
||||
HFONT font = NULL;
|
||||
|
||||
if (FALSE == SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
|
||||
return NULL;
|
||||
|
||||
lf.lfQuality = Graphics_GetSysFontQuality();
|
||||
font = CreateFontIndirectW(&lf);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
HFONT
|
||||
Graphics_DuplicateFont(HFONT sourceFont, INT heightDeltaPt, BOOL forceBold, BOOL systemQuality)
|
||||
{
|
||||
LOGFONTW lf = {0};
|
||||
|
||||
if (NULL == sourceFont)
|
||||
return NULL;
|
||||
|
||||
|
||||
if (sizeof(lf) != GetObjectW(sourceFont, sizeof(lf), &lf))
|
||||
return NULL;
|
||||
|
||||
if (0 != heightDeltaPt)
|
||||
{
|
||||
HDC hdcTmp = NULL, hdc = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE | DCX_NORESETATTRS);
|
||||
|
||||
if (NULL != hdc)
|
||||
{
|
||||
hdcTmp = CreateCompatibleDC(hdc);
|
||||
ReleaseDC(NULL, hdc);
|
||||
}
|
||||
|
||||
if (NULL == hdcTmp)
|
||||
return NULL;
|
||||
|
||||
LONG pixelsY = GetDeviceCaps(hdcTmp, LOGPIXELSY);
|
||||
HFONT prevFont = SelectFont(hdcTmp, sourceFont);
|
||||
|
||||
TEXTMETRICW tm = {0};
|
||||
if (FALSE != GetTextMetricsW(hdcTmp, &tm))
|
||||
{
|
||||
INT basePt = MulDiv(tm.tmHeight - tm.tmInternalLeading, 96, pixelsY);
|
||||
lf.lfHeight = -MulDiv((basePt + heightDeltaPt), pixelsY, 96);
|
||||
|
||||
}
|
||||
|
||||
SelectObject(hdcTmp, prevFont);
|
||||
DeleteDC(hdcTmp);
|
||||
}
|
||||
|
||||
if (FALSE != systemQuality)
|
||||
lf.lfQuality = Graphics_GetSysFontQuality();
|
||||
if (FALSE != forceBold && lf.lfWeight < FW_BOLD)
|
||||
lf.lfWeight = FW_BOLD;
|
||||
|
||||
return CreateFontIndirectW(&lf);
|
||||
}
|
||||
|
||||
long
|
||||
Graphics_GetFontHeight(HDC hdc)
|
||||
{
|
||||
TEXTMETRICW tm;
|
||||
if (FALSE == GetTextMetricsW(hdc, &tm))
|
||||
return 0;
|
||||
|
||||
return tm.tmHeight;
|
||||
}
|
||||
|
||||
long
|
||||
Graphics_GetAveStrWidth(HDC hdc, UINT cchLen)
|
||||
{
|
||||
const char szTest[] =
|
||||
{
|
||||
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z',
|
||||
'a','b','c','d','e','f','g','h','i','j','k','l', 'm','n','o','p','q','r','s','t','u','v','w','x','y','z'
|
||||
};
|
||||
|
||||
SIZE textSize;
|
||||
if (FALSE == GetTextExtentPointA(hdc, szTest, ARRAYSIZE(szTest) -1, &textSize))
|
||||
return 0;
|
||||
|
||||
LONG result;
|
||||
if (1 == cchLen)
|
||||
{
|
||||
result = (textSize.cx + ARRAYSIZE(szTest)/2)/ARRAYSIZE(szTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = MulDiv(cchLen, textSize.cx + ARRAYSIZE(szTest)/2, ARRAYSIZE(szTest));
|
||||
if (0 != result)
|
||||
{
|
||||
TEXTMETRICW tm;
|
||||
if (FALSE != GetTextMetricsW(hdc, &tm))
|
||||
result += tm.tmOverhang;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Graphics_GetWindowBaseUnits(HWND hwnd, LONG *baseUnitX, LONG *baseUnitY)
|
||||
{
|
||||
BOOL result;
|
||||
result = FALSE;
|
||||
|
||||
if (NULL != hwnd)
|
||||
{
|
||||
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL != hdc)
|
||||
{
|
||||
TEXTMETRICW tm;
|
||||
HFONT font, prevFont;
|
||||
|
||||
font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
|
||||
prevFont = SelectFont(hdc, font);
|
||||
|
||||
if (FALSE != GetTextMetricsW(hdc, &tm))
|
||||
{
|
||||
if (NULL != baseUnitX)
|
||||
*baseUnitX = Graphics_GetAveStrWidth(hdc, 1);
|
||||
|
||||
if (NULL != baseUnitY)
|
||||
*baseUnitY = tm.tmHeight;
|
||||
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
SelectFont(hdc, prevFont);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
typedef int (*SkinColorFunc)(int idx);
|
||||
|
||||
COLORREF Graphics_GetSkinColor(unsigned int colorIndex)
|
||||
{
|
||||
static SkinColorFunc GetSkinColor = NULL;
|
||||
|
||||
if (NULL == GetSkinColor)
|
||||
{
|
||||
GetSkinColor = (SkinColorFunc)SENDMLIPC(Plugin_GetLibraryWindow(), ML_IPC_SKIN_WADLG_GETFUNC, 1);
|
||||
if (NULL == GetSkinColor)
|
||||
return RGB(255, 0, 255);
|
||||
}
|
||||
|
||||
return GetSkinColor(colorIndex);
|
||||
}
|
||||
|
||||
COLORREF
|
||||
Graphics_BlendColors(COLORREF rgbTop, COLORREF rgbBottom, INT alpha)
|
||||
{
|
||||
if (alpha > 254) return rgbTop;
|
||||
if (alpha < 0) return rgbBottom;
|
||||
|
||||
WORD k = (WORD)(((255 - alpha)*255 + 127)/255);
|
||||
|
||||
return RGB( (GetRValue(rgbTop)*alpha + k*GetRValue(rgbBottom) + 127)/255,
|
||||
(GetGValue(rgbTop)*alpha + k*GetGValue(rgbBottom) + 127)/255,
|
||||
(GetBValue(rgbTop)*alpha + k*GetBValue(rgbBottom) + 127)/255);
|
||||
}
|
||||
|
||||
INT
|
||||
Graphics_GetColorDistance(COLORREF rgb1, COLORREF rgb2)
|
||||
{
|
||||
return (1000 * ((GetRValue(rgb1) - GetRValue(rgb2)) +
|
||||
(GetGValue(rgb1) - GetGValue(rgb2)) +
|
||||
(GetBValue(rgb1) - GetBValue(rgb2))))/ (3 * 255);
|
||||
}
|
||||
|
||||
void
|
||||
Graphics_ClampRect(RECT *rect, const RECT *boxRect)
|
||||
{
|
||||
if (rect->left < boxRect->left)
|
||||
rect->left = boxRect->left;
|
||||
|
||||
if (rect->top < boxRect->top)
|
||||
rect->top = boxRect->top;
|
||||
|
||||
if (rect->right > boxRect->right)
|
||||
rect->right = boxRect->right;
|
||||
|
||||
if (rect->bottom > boxRect->bottom)
|
||||
rect->bottom = boxRect->bottom;
|
||||
}
|
||||
|
||||
void
|
||||
Graphics_NormalizeRect(RECT *rect)
|
||||
{
|
||||
if (rect->top > rect->bottom)
|
||||
rect->bottom = rect->top;
|
||||
|
||||
if (rect->left > rect->right)
|
||||
rect->right = rect->left;
|
||||
}
|
||||
|
||||
void
|
||||
Graphics_GetRectSizeNormalized(const RECT *rect, SIZE *size)
|
||||
{
|
||||
size->cx = rect->right - rect->left;
|
||||
if (size->cx < 0)
|
||||
size->cx = 0;
|
||||
|
||||
size->cy = rect->bottom - rect->top;
|
||||
if (size->cy < 0)
|
||||
size->cy = 0;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Graphics_IsRectFit(const RECT *rect, const RECT *boxRect)
|
||||
{
|
||||
if (rect->left < boxRect->left ||
|
||||
rect->top < boxRect->top ||
|
||||
rect->right > boxRect->right ||
|
||||
rect->bottom > boxRect->bottom)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL SetSizeEmpty(SIZE *size)
|
||||
{
|
||||
if (NULL == size)
|
||||
return FALSE;
|
||||
|
||||
ZeroMemory(size, sizeof(SIZE));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL IsSizeEmpty(SIZE *size)
|
||||
{
|
||||
return (NULL == size || 0 == size->cx || 0 == size->cy);
|
||||
}
|
||||
|
||||
BOOL SetSize(SIZE *size, long width, long height)
|
||||
{
|
||||
if (NULL == size)
|
||||
return FALSE;
|
||||
|
||||
size->cx = width;
|
||||
size->cy = height;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetPoint(POINT *pt, long x, long y)
|
||||
{
|
||||
if (NULL == pt)
|
||||
return FALSE;
|
||||
|
||||
pt->x = x;
|
||||
pt->y = y;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL MakeRectPolygon(POINT vertices[4], long left, long top, long right, long bottom)
|
||||
{
|
||||
if (NULL == vertices)
|
||||
return FALSE;
|
||||
|
||||
vertices[0].x = left;
|
||||
vertices[0].y = top;
|
||||
vertices[1].x = right;
|
||||
vertices[1].y = top;
|
||||
vertices[2].x = right;
|
||||
vertices[2].y = bottom;
|
||||
vertices[3].x = left;
|
||||
vertices[3].y = bottom;
|
||||
|
||||
return TRUE;
|
||||
}
|
72
Src/Plugins/Library/ml_devices/graphics.h
Normal file
72
Src/Plugins/Library/ml_devices/graphics.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_GRAPHICS_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_GRAPHICS_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef SelectBitmap
|
||||
#define SelectBitmap(_hdc, _bitmap) ((HBITMAP)SelectObject(_hdc, _bitmap))
|
||||
#endif
|
||||
|
||||
#ifndef SelectFont
|
||||
#define SelectFont(_hdc, _font) ((HFONT)SelectObject(_hdc, _font))
|
||||
#endif
|
||||
|
||||
#ifndef SelectBrush
|
||||
#define SelectBrush(_hdc, _brush) ((HBRUSH)SelectObject(_hdc, _brush))
|
||||
#endif
|
||||
|
||||
#ifndef GetCurrentBitmap
|
||||
#define GetCurrentBitmap(_hdc) ((HBITMAP)GetCurrentObject(_hdc, OBJ_BITMAP))
|
||||
#endif
|
||||
|
||||
#ifndef GetCurrentFont
|
||||
#define GetCurrentFont(_hdc) ((HFONT)GetCurrentObject(_hdc, OBJ_FONT))
|
||||
#endif
|
||||
|
||||
#ifndef GetCurrentBrush
|
||||
#define GetCurrentBrush(_hdc) ((HBRUSH)GetCurrentObject(_hdc, OBJ_BRUSH))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef SET_GRADIENT_VERTEX
|
||||
#define SET_GRADIENT_VERTEX(_vertex, _x, _y, _rgb)\
|
||||
{(_vertex).x = (_x); (_vertex).y = (_y);\
|
||||
(_vertex).Red = GetRValue(_rgb) << 8; (_vertex).Green = GetGValue(_rgb) << 8;\
|
||||
(_vertex).Blue = GetBValue(_rgb) << 8; (_vertex).Alpha = 0x0000;}
|
||||
#endif
|
||||
|
||||
#ifndef SET_GRADIENT_RECT_MESH
|
||||
#define SET_GRADIENT_RECT_MESH(_mesh, _upperLeft, _bottomRight)\
|
||||
{(_mesh).UpperLeft = (_upperLeft); (_mesh).LowerRight = (_bottomRight);}
|
||||
#endif
|
||||
|
||||
|
||||
BYTE Graphics_GetSysFontQuality();
|
||||
HFONT Graphics_CreateSysFont();
|
||||
HFONT Graphics_DuplicateFont(HFONT sourceFont, INT heightDeltaPt, BOOL forceBold, BOOL systemQuality);
|
||||
|
||||
long Graphics_GetFontHeight(HDC hdc);
|
||||
long Graphics_GetAveStrWidth(HDC hdc, UINT cchLen);
|
||||
BOOL Graphics_GetWindowBaseUnits(HWND hwnd, LONG *baseUnitX, LONG *baseUnitY);
|
||||
|
||||
COLORREF Graphics_GetSkinColor(unsigned int colorIndex);
|
||||
COLORREF Graphics_BlendColors(COLORREF rgbTop, COLORREF rgbBottom, INT alpha);
|
||||
INT Graphics_GetColorDistance(COLORREF rgb1, COLORREF rgb2);
|
||||
|
||||
void Graphics_ClampRect(RECT *rect, const RECT *boxRect);
|
||||
void Graphics_NormalizeRect(RECT *rect);
|
||||
void Graphics_GetRectSizeNormalized(const RECT *rect, SIZE *size);
|
||||
BOOL Graphics_IsRectFit(const RECT *rect, const RECT *boxRect);
|
||||
|
||||
BOOL SetSizeEmpty(SIZE *size);
|
||||
BOOL IsSizeEmpty(SIZE *size);
|
||||
BOOL SetSize(SIZE *size, long width, long height);
|
||||
|
||||
BOOL SetPoint(POINT *pt, long x, long y);
|
||||
BOOL MakeRectPolygon(POINT vertices[4], long left, long top, long right, long bottom);
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_GRAPHICS_HEADER
|
978
Src/Plugins/Library/ml_devices/image.cpp
Normal file
978
Src/Plugins/Library/ml_devices/image.cpp
Normal file
|
@ -0,0 +1,978 @@
|
|||
#include "main.h"
|
||||
#include "./image.h"
|
||||
|
||||
|
||||
HBITMAP
|
||||
Image_Load(const wchar_t *path, unsigned int type,
|
||||
unsigned int flags, int width, int height)
|
||||
{
|
||||
MLIMAGESOURCE source;
|
||||
HWND libraryWindow = Plugin_GetLibraryWindow();
|
||||
if (NULL == libraryWindow)
|
||||
return NULL;
|
||||
|
||||
source.cbSize = sizeof(source);
|
||||
source.lpszName = path;
|
||||
source.type = type;
|
||||
source.flags = (flags & ~IMAGE_FILTER_MASK);
|
||||
source.cxDst = width;
|
||||
source.cyDst = height;
|
||||
|
||||
if (0 == (ISF_LOADFROMFILE & source.flags))
|
||||
{
|
||||
source.hInst = WASABI_API_LNG_HINST;
|
||||
if (NULL != source.hInst)
|
||||
{
|
||||
HBITMAP bitmap = MLImageLoader_LoadDib(libraryWindow, &source);
|
||||
if (NULL != bitmap)
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
if (WASABI_API_ORIG_HINST == source.hInst)
|
||||
return NULL;
|
||||
|
||||
source.hInst = WASABI_API_ORIG_HINST;
|
||||
return (NULL != source.hInst) ?
|
||||
MLImageLoader_LoadDib(libraryWindow, &source) :
|
||||
NULL;
|
||||
}
|
||||
|
||||
return MLImageLoader_LoadDib(Plugin_GetLibraryWindow(), &source);
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
Image_LoadEx(HINSTANCE instance, const wchar_t *path, unsigned int type,
|
||||
unsigned int flags, int width, int height)
|
||||
{
|
||||
MLIMAGESOURCE source = {0};
|
||||
|
||||
source.cbSize = sizeof(source);
|
||||
source.hInst = instance;
|
||||
source.lpszName = path;
|
||||
source.type = type;
|
||||
source.flags = (flags & ~IMAGE_FILTER_MASK);
|
||||
source.cxDst = width;
|
||||
source.cyDst = height;
|
||||
|
||||
return MLImageLoader_LoadDib(Plugin_GetLibraryWindow(), &source);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_FilterEx(void *pixelData, long width, long height, unsigned short bpp,
|
||||
unsigned int flags, COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
|
||||
{
|
||||
MLIMAGEFILTERAPPLYEX filter;
|
||||
HWND libraryWindow;
|
||||
BOOL result;
|
||||
|
||||
if (NULL == pixelData)
|
||||
return FALSE;
|
||||
|
||||
libraryWindow = Plugin_GetLibraryWindow();
|
||||
if (NULL == libraryWindow)
|
||||
return FALSE;
|
||||
|
||||
filter.cbSize = sizeof(filter);
|
||||
filter.pData = (BYTE*)pixelData;
|
||||
filter.cx = width;
|
||||
filter.cy = height;
|
||||
filter.bpp = bpp;
|
||||
filter.imageTag = NULL;
|
||||
|
||||
result = FALSE;
|
||||
|
||||
if (0 != (IMAGE_FILTER_GRAYSCALE & flags))
|
||||
{
|
||||
filter.filterUID = MLIF_GRAYSCALE_UID;
|
||||
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
|
||||
}
|
||||
|
||||
filter.rgbBk = backColor;
|
||||
filter.rgbFg = frontColor;
|
||||
|
||||
if (32 == bpp)
|
||||
{
|
||||
filter.filterUID = MLIF_FILTER1_PRESERVE_ALPHA_UID;
|
||||
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
|
||||
|
||||
if (0 != (IMAGE_FILTER_BLEND & flags))
|
||||
{
|
||||
filter.filterUID = MLIF_BLENDONBK_UID;
|
||||
filter.rgbBk = blendColor;
|
||||
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
filter.filterUID = MLIF_FILTER1_UID;
|
||||
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_Filter(HBITMAP bitmap, unsigned int flags,
|
||||
COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
|
||||
{
|
||||
DIBSECTION bitmapData;
|
||||
BITMAP *bi;
|
||||
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
if (sizeof(bitmapData) != GetObjectW(bitmap, sizeof(bitmapData), &bitmapData))
|
||||
return FALSE;
|
||||
|
||||
bi = &bitmapData.dsBm;
|
||||
|
||||
return Image_FilterEx(bi->bmBits, bi->bmWidth, bi->bmHeight, bi->bmBitsPixel,
|
||||
flags, backColor, frontColor, blendColor);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_BlendEx(void *pixelData, long width, long height, unsigned short bpp, COLORREF blendColor)
|
||||
{
|
||||
MLIMAGEFILTERAPPLYEX filter;
|
||||
HWND libraryWindow;
|
||||
|
||||
if (NULL == pixelData || 32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
libraryWindow = Plugin_GetLibraryWindow();
|
||||
if (NULL == libraryWindow)
|
||||
return FALSE;
|
||||
|
||||
filter.cbSize = sizeof(filter);
|
||||
filter.pData = (BYTE*)pixelData;
|
||||
filter.cx = width;
|
||||
filter.cy = height;
|
||||
filter.bpp = bpp;
|
||||
filter.imageTag = NULL;
|
||||
|
||||
|
||||
filter.filterUID = MLIF_BLENDONBK_UID;
|
||||
filter.rgbBk = blendColor;
|
||||
return MLImageFilter_ApplyEx(libraryWindow, &filter);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_Blend(HBITMAP bitmap, COLORREF blendColor)
|
||||
{
|
||||
DIBSECTION bitmapData;
|
||||
BITMAP *bi;
|
||||
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
if (sizeof(bitmapData) != GetObjectW(bitmap, sizeof(bitmapData), &bitmapData))
|
||||
return FALSE;
|
||||
|
||||
bi = &bitmapData.dsBm;
|
||||
|
||||
return Image_BlendEx(bi->bmBits, bi->bmWidth, bi->bmHeight, bi->bmBitsPixel, blendColor);
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
Image_LoadSkinnedEx(HINSTANCE instance, const wchar_t *path, unsigned int type,
|
||||
unsigned int flags, int width, int height,
|
||||
COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
|
||||
bitmap = Image_LoadEx(instance, path, type, flags, width, height);
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
Image_Filter(bitmap, flags, backColor, frontColor, blendColor);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
Image_LoadSkinned(const wchar_t *path, unsigned int type,
|
||||
unsigned int flags, int width, int height,
|
||||
COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
|
||||
bitmap = Image_Load(path, type, flags, width, height);
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
Image_Filter(bitmap, flags, backColor, frontColor, blendColor);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
Image_DuplicateDib(HBITMAP source)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
DIBSECTION sourceDib;
|
||||
HDC windowDC;
|
||||
void *pixelData;
|
||||
|
||||
if (NULL == source)
|
||||
return NULL;
|
||||
|
||||
if (sizeof(sourceDib) != GetObjectW(source, sizeof(sourceDib), &sourceDib))
|
||||
return FALSE;
|
||||
|
||||
|
||||
sourceDib.dsBmih.biSize = sizeof(BITMAPINFOHEADER);
|
||||
if (sourceDib.dsBmih.biHeight > 0)
|
||||
sourceDib.dsBmih.biHeight = -sourceDib.dsBmih.biHeight;
|
||||
|
||||
windowDC = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE);
|
||||
|
||||
bitmap = CreateDIBSection(windowDC, (BITMAPINFO*)&sourceDib.dsBmih, DIB_RGB_COLORS, &pixelData, NULL, 0);
|
||||
|
||||
if (NULL != windowDC)
|
||||
ReleaseDC(NULL, windowDC);
|
||||
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
CopyMemory(pixelData, sourceDib.dsBm.bmBits, sourceDib.dsBm.bmWidthBytes * sourceDib.dsBm.bmHeight);
|
||||
|
||||
return bitmap;
|
||||
|
||||
}
|
||||
BOOL
|
||||
Image_ColorOver(HBITMAP bitmap, const RECT *prcPart, BOOL premult, COLORREF rgb)
|
||||
{
|
||||
DIBSECTION bitmapData;
|
||||
BITMAP *bi;
|
||||
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
if (sizeof(bitmapData) != GetObjectW(bitmap, sizeof(bitmapData), &bitmapData))
|
||||
return FALSE;
|
||||
|
||||
if (BI_RGB != bitmapData.dsBmih.biCompression ||
|
||||
1 != bitmapData.dsBmih.biPlanes ||
|
||||
32 != bitmapData.dsBm.bmBitsPixel)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bi = &bitmapData.dsBm;
|
||||
|
||||
return (NULL == prcPart) ?
|
||||
Image_ColorOverEx((BYTE*)bi->bmBits, bi->bmWidth, bi->bmHeight,
|
||||
0, 0, bi->bmWidth, bi->bmHeight,
|
||||
bi->bmBitsPixel, premult, rgb) :
|
||||
Image_ColorOverEx((BYTE*)bi->bmBits, bi->bmWidth, bi->bmHeight,
|
||||
prcPart->left, prcPart->top,
|
||||
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
|
||||
bi->bmBitsPixel, premult, rgb);
|
||||
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_ColorOverEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy, unsigned short bpp,
|
||||
BOOL premult, COLORREF rgb)
|
||||
{
|
||||
LONG pitch;
|
||||
UINT a, r, g, b, ma, mr, mg, mb;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (step < 3)
|
||||
return TRUE;
|
||||
|
||||
if (cy < 0) cy -= cy;
|
||||
|
||||
a = (LOBYTE((rgb)>>24)); r = GetRValue(rgb); g = GetGValue(rgb); b = GetBValue(rgb);
|
||||
ma = 255 - a; mr = r * 255; mg = g * 255; mb = b * 255;
|
||||
|
||||
if (0 == a)
|
||||
return TRUE;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
if (0xFF == a)
|
||||
{
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
cursor[0] = (BYTE)b;
|
||||
cursor[1] = (BYTE)g;
|
||||
cursor[2] = (BYTE)r;
|
||||
// cursor[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
if (premult)
|
||||
{
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
int t = (mb + ma * cursor[0] + 127) / 255;
|
||||
cursor[0] = (t > 0xFF) ? 0xFF : t;
|
||||
t = (mg + ma * cursor[1] + 127) / 255;
|
||||
cursor[1] = (t > 0xFF) ? 0xFF : t;
|
||||
t = (mr+ ma * cursor[2] + 127) / 255;
|
||||
cursor[2] = (t > 0xFF) ? 0xFF : t;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WORD k = (((255 - a)*255 + 127)/255);
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
cursor[0] = (b*a + k*cursor[0] + 127)/255;
|
||||
cursor[1] = (g*a + k*cursor[1] + 127)/255;
|
||||
cursor[2] = (r*a + k*cursor[2] + 127)/255;
|
||||
// cursor[3] = (a*a + k*cursor[3] + 127)/255;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_Premultiply(HBITMAP hbmp, const RECT *prcPart)
|
||||
{
|
||||
DIBSECTION dibsec;
|
||||
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
|
||||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
|
||||
return FALSE;
|
||||
|
||||
return (NULL == prcPart) ?
|
||||
Image_PremultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
0, 0, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
dibsec.dsBm.bmBitsPixel) :
|
||||
Image_PremultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
prcPart->left, prcPart->top, RECTWIDTH(*prcPart), RECTHEIGHT(*prcPart),
|
||||
dibsec.dsBm.bmBitsPixel);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_PremultiplyEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy, unsigned short bpp)
|
||||
{
|
||||
if (32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
LONG pitch;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (cy < 0)
|
||||
cy = -cy;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
UINT a;
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
a = cursor[3];
|
||||
if (0 == a)
|
||||
{
|
||||
cursor[0] = 0;
|
||||
cursor[1] = 0;
|
||||
cursor[2] = 0;
|
||||
}
|
||||
else if (255 != a)
|
||||
{
|
||||
cursor[0] = (BYTE)MulDiv(cursor[0], a, 255);
|
||||
cursor[1] = (BYTE)MulDiv(cursor[1], a, 255);
|
||||
cursor[2] = (BYTE)MulDiv(cursor[2], a, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_Demultiply(HBITMAP hbmp, const RECT *prcPart)
|
||||
{
|
||||
DIBSECTION dibsec;
|
||||
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
|
||||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
|
||||
return FALSE;
|
||||
|
||||
return (NULL == prcPart) ?
|
||||
Image_DemultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
0, 0, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
dibsec.dsBm.bmBitsPixel) :
|
||||
Image_DemultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
prcPart->left, prcPart->top, RECTWIDTH(*prcPart), RECTHEIGHT(*prcPart),
|
||||
dibsec.dsBm.bmBitsPixel);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_DemultiplyEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy, unsigned short bpp)
|
||||
{
|
||||
if (32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
LONG pitch;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (cy < 0)
|
||||
cy = -cy;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
UINT a;
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
a = cursor[3];
|
||||
if (0 == a)
|
||||
{
|
||||
cursor[0] = 0;
|
||||
cursor[1] = 0;
|
||||
cursor[2] = 0;
|
||||
}
|
||||
else if (255 != a)
|
||||
{
|
||||
cursor[0] = (BYTE)MulDiv(cursor[0], 255, a);
|
||||
cursor[1] = (BYTE)MulDiv(cursor[1], 255, a);
|
||||
cursor[2] = (BYTE)MulDiv(cursor[2], 255, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
BOOL
|
||||
Image_Saturate(HBITMAP hbmp, const RECT *prcPart, int n, BOOL fScale)
|
||||
{
|
||||
DIBSECTION dibsec;
|
||||
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
|
||||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
|
||||
return FALSE;
|
||||
|
||||
return Image_SaturateEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
prcPart->left, prcPart->top,
|
||||
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
|
||||
dibsec.dsBm.bmBitsPixel, n, fScale);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_SaturateEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy, unsigned short bpp,
|
||||
int n, BOOL fScale)
|
||||
{
|
||||
if (32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
LONG pitch;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (FALSE == fScale)
|
||||
{
|
||||
if (n < 0) n = 0;
|
||||
else if (n > 1000) n = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n < -1000) n = -1000;
|
||||
else if (n > 1000) n = 1000;
|
||||
}
|
||||
|
||||
if (cy < 0)
|
||||
cy = -cy;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
COLORREF rgb;
|
||||
INT k;
|
||||
WORD h, l, s;
|
||||
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
rgb = RGB(cursor[2], cursor[1], cursor[0]);
|
||||
ColorRGBToHLS(rgb, &h, &l, &s);
|
||||
if(FALSE == fScale)
|
||||
s = ((WORD)((240 * n)/1000));
|
||||
else
|
||||
{
|
||||
k = s;
|
||||
s = (WORD)(k + (k * n) /1000);
|
||||
}
|
||||
|
||||
rgb = ColorHLSToRGB(h, l, s);
|
||||
|
||||
cursor[0] = GetBValue(rgb);
|
||||
cursor[1] = GetGValue(rgb);
|
||||
cursor[2] = GetRValue(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_AdjustAlpha(HBITMAP hbmp, const RECT *prcPart, int n, BOOL fScale)
|
||||
{
|
||||
DIBSECTION dibsec;
|
||||
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
|
||||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
|
||||
return FALSE;
|
||||
|
||||
return Image_AdjustAlphaEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
prcPart->left, prcPart->top,
|
||||
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
|
||||
dibsec.dsBm.bmBitsPixel, n, fScale);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_AdjustAlphaEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy, unsigned short bpp,
|
||||
int n, BOOL fScale)
|
||||
{
|
||||
if (32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
LONG pitch;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (FALSE == fScale)
|
||||
{
|
||||
if (n < 0) n = 0;
|
||||
else if (n > 1000) n = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n < -1000) n = -1000;
|
||||
else if (n > 1000) n = 1000;
|
||||
}
|
||||
|
||||
if (cy < 0)
|
||||
cy = -cy;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
INT k;
|
||||
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
if(FALSE == fScale)
|
||||
cursor[3] = ((BYTE)((255 * n)/1000));
|
||||
else
|
||||
{
|
||||
k = cursor[3];
|
||||
k = k + MulDiv(k, n, 1000);
|
||||
if (k > 255) k = 255;
|
||||
cursor[3] = (BYTE)k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_AdjustSaturationAlpha(HBITMAP hbmp, const RECT *prcPart, int nSaturation, int nAlpha)
|
||||
{
|
||||
DIBSECTION dibsec;
|
||||
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
|
||||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
|
||||
return FALSE;
|
||||
|
||||
return Image_AdjustSaturationAlphaEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
prcPart->left, prcPart->top,
|
||||
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
|
||||
dibsec.dsBm.bmBitsPixel, nSaturation, nAlpha);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_AdjustSaturationAlphaEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy,
|
||||
unsigned short bpp, int nSaturation, int nAlpha)
|
||||
{
|
||||
if (32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
LONG pitch;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (nSaturation < -1000) nSaturation = -1000;
|
||||
else if (nSaturation > 1000) nSaturation = 1000;
|
||||
|
||||
if (nAlpha < -1000) nAlpha = -1000;
|
||||
else if (nAlpha > 1000) nAlpha = 1000;
|
||||
|
||||
if (cy < 0)
|
||||
cy = -cy;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
INT k;
|
||||
COLORREF rgb;
|
||||
WORD h, l, s;
|
||||
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
k = cursor[3];
|
||||
k = k + MulDiv(k, nAlpha, 1000);
|
||||
if (k > 255) k = 255;
|
||||
cursor[3] = (BYTE)k;
|
||||
|
||||
rgb = RGB(cursor[2], cursor[1], cursor[0]);
|
||||
ColorRGBToHLS(rgb, &h, &l, &s);
|
||||
|
||||
k = s;
|
||||
k = k + MulDiv(k, nSaturation, 1000);
|
||||
if (k > 240) k = 240;
|
||||
s = (WORD)k;
|
||||
|
||||
rgb = ColorHLSToRGB(h, l, s);
|
||||
cursor[0] = GetBValue(rgb);
|
||||
cursor[1] = GetGValue(rgb);
|
||||
cursor[2] = GetRValue(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_FillBorder(HDC targetDC, const RECT *targetRect,
|
||||
HDC sourceDC, const RECT *sourceRect,
|
||||
BOOL fillCenter, BYTE alphaConstant)
|
||||
{
|
||||
INT prevStretchMode;
|
||||
long centerWidth, centerHeight;
|
||||
long sliceWidth, sliceHeight;
|
||||
|
||||
const BLENDFUNCTION blendFunction = { AC_SRC_OVER, 0, alphaConstant, AC_SRC_ALPHA };
|
||||
const long targetWidth = RECTWIDTH(*targetRect);
|
||||
const long targetHeight = RECTHEIGHT(*targetRect);
|
||||
const long sourceWidth = RECTWIDTH(*sourceRect);
|
||||
const long sourceHeight = RECTHEIGHT(*sourceRect);
|
||||
|
||||
if (NULL == targetDC || NULL == sourceDC)
|
||||
return FALSE;
|
||||
|
||||
sliceWidth = sourceWidth/2;
|
||||
sliceHeight = sourceHeight/2;
|
||||
|
||||
if (sliceWidth*2 > targetWidth)
|
||||
sliceWidth = targetWidth/2;
|
||||
|
||||
if (sliceHeight*2 > targetHeight)
|
||||
sliceHeight = targetHeight/2;
|
||||
|
||||
if (0 == sliceWidth || 0 == sliceHeight)
|
||||
return FALSE;
|
||||
|
||||
prevStretchMode = SetStretchBltMode(targetDC, COLORONCOLOR);
|
||||
SetViewportOrgEx(sourceDC, 0, 0, NULL);
|
||||
|
||||
GdiAlphaBlend(targetDC, targetRect->left, targetRect->top, sliceWidth, sliceHeight,
|
||||
sourceDC, sourceRect->left, sourceRect->top, sliceWidth, sliceHeight, blendFunction);
|
||||
GdiAlphaBlend(targetDC, targetRect->right - sliceWidth, targetRect->top, sliceWidth, sliceHeight,
|
||||
sourceDC, sourceRect->right - sliceWidth, sourceRect->top, sliceWidth, sliceHeight, blendFunction);
|
||||
GdiAlphaBlend(targetDC, targetRect->left, targetRect->bottom - sliceHeight, sliceWidth, sliceHeight,
|
||||
sourceDC, sourceRect->left, sourceRect->bottom - sliceHeight, sliceWidth, sliceHeight, blendFunction);
|
||||
GdiAlphaBlend(targetDC, targetRect->right - sliceWidth, targetRect->bottom - sliceHeight, sliceWidth, sliceHeight,
|
||||
sourceDC, sourceRect->right - sliceWidth, sourceRect->bottom - sliceHeight, sliceWidth, sliceHeight, blendFunction);
|
||||
|
||||
if (targetWidth > 2*sliceWidth)
|
||||
{
|
||||
centerWidth = sourceWidth - 2*sliceWidth;
|
||||
if(centerWidth < 1)
|
||||
centerWidth = 1;
|
||||
|
||||
GdiAlphaBlend(targetDC, targetRect->left + sliceWidth, targetRect->top, targetWidth - (sliceWidth * 2), sliceHeight,
|
||||
sourceDC, sourceRect->left + sliceWidth, sourceRect->top, centerWidth, sliceHeight, blendFunction);
|
||||
|
||||
GdiAlphaBlend(targetDC, targetRect->left + sliceWidth, targetRect->bottom - sliceHeight, targetWidth - (sliceWidth * 2), sliceHeight,
|
||||
sourceDC, sourceRect->left + sliceWidth, sourceRect->bottom - sliceHeight, centerWidth, sliceHeight, blendFunction);
|
||||
}
|
||||
else
|
||||
centerWidth = 0;
|
||||
|
||||
if (targetHeight > 2*sliceHeight)
|
||||
{
|
||||
centerHeight = sourceHeight - 2*sliceHeight;
|
||||
if(centerHeight < 1)
|
||||
centerHeight = 1;
|
||||
|
||||
GdiAlphaBlend(targetDC, targetRect->left, targetRect->top + sliceHeight, sliceWidth, targetHeight - (sliceHeight* 2),
|
||||
sourceDC, sourceRect->left, sourceRect->top + sliceHeight, sliceWidth, centerHeight, blendFunction);
|
||||
|
||||
GdiAlphaBlend(targetDC, targetRect->right - sliceWidth, targetRect->top + sliceHeight, sliceWidth, targetHeight - (sliceHeight* 2),
|
||||
sourceDC, sourceRect->right - sliceWidth, sourceRect->top + sliceHeight, sliceWidth, centerHeight, blendFunction);
|
||||
}
|
||||
else
|
||||
centerHeight = 0;
|
||||
|
||||
if (FALSE != fillCenter &&
|
||||
0 != centerWidth && 0 != centerHeight)
|
||||
{
|
||||
GdiAlphaBlend(targetDC, targetRect->left + sliceWidth, targetRect->top + sliceHeight, targetWidth - (sliceWidth * 2), targetHeight - (sliceHeight* 2),
|
||||
sourceDC, sourceRect->left + sliceWidth, sourceRect->top + sliceHeight, centerWidth, centerHeight, blendFunction);
|
||||
|
||||
}
|
||||
|
||||
SetStretchBltMode(targetDC, prevStretchMode);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const ImageInfo *
|
||||
Image_GetBestFit(const ImageInfo *images, size_t count, unsigned int width, unsigned int height)
|
||||
{
|
||||
const ImageInfo *image, *bestFit;
|
||||
double widthDbl, heightDbl;
|
||||
double scaleMin, scaleHorz, scaleVert;
|
||||
|
||||
if (NULL == images || count < 1)
|
||||
return NULL;
|
||||
|
||||
if (width < 1)
|
||||
width = 1;
|
||||
|
||||
if (height < 1)
|
||||
height = 1;
|
||||
|
||||
widthDbl = width;
|
||||
heightDbl = height;
|
||||
|
||||
image = &images[--count];
|
||||
scaleHorz = widthDbl/image->width;
|
||||
scaleVert = heightDbl/image->height;
|
||||
scaleMin = (scaleHorz < scaleVert) ? scaleHorz : scaleVert;
|
||||
bestFit = image;
|
||||
|
||||
if (1.0 != scaleMin)
|
||||
{
|
||||
scaleMin = fabs(1.0 - scaleMin);
|
||||
while(count--)
|
||||
{
|
||||
image = &images[count];
|
||||
scaleHorz = widthDbl/image->width;
|
||||
scaleVert = heightDbl/image->height;
|
||||
if (scaleHorz > scaleVert)
|
||||
scaleHorz = scaleVert;
|
||||
|
||||
if (1.0 == scaleHorz)
|
||||
{
|
||||
bestFit = image;
|
||||
break;
|
||||
}
|
||||
|
||||
scaleHorz = fabs(1.0 - scaleHorz);
|
||||
if (scaleHorz < scaleMin)
|
||||
{
|
||||
scaleMin = scaleHorz;
|
||||
bestFit = image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestFit;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_AlphaBlend(HDC targetDC, const RECT *targetRect,
|
||||
HDC sourceDC, const RECT *sourceRect, BYTE sourceAlpha,
|
||||
HBITMAP sourceBitmap, const RECT *paintRect, AlphaBlendFlags flags,
|
||||
RECT *rectOut)
|
||||
{
|
||||
BOOL result, clipSource;
|
||||
RECT fillRect;
|
||||
int sourceX, sourceY, sourceWidth, sourceHeight;
|
||||
const BLENDFUNCTION blendFunction =
|
||||
{
|
||||
AC_SRC_OVER,
|
||||
0,
|
||||
sourceAlpha,
|
||||
AC_SRC_ALPHA
|
||||
};
|
||||
|
||||
if (NULL != paintRect)
|
||||
{
|
||||
if (FALSE == IntersectRect(&fillRect, targetRect, paintRect))
|
||||
return TRUE;
|
||||
|
||||
clipSource = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyRect(&fillRect, targetRect);
|
||||
clipSource = FALSE;
|
||||
}
|
||||
|
||||
if (NULL != sourceRect)
|
||||
{
|
||||
sourceX = sourceRect->left;
|
||||
sourceY = sourceRect->top;
|
||||
sourceWidth = RECTWIDTH(*sourceRect);
|
||||
sourceHeight = RECTHEIGHT(*sourceRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
BITMAP bitmapInfo;
|
||||
if (sizeof(bitmapInfo) != GetObject(sourceBitmap, sizeof(bitmapInfo), &bitmapInfo))
|
||||
return FALSE;
|
||||
|
||||
sourceX = 0;
|
||||
sourceY = 0;
|
||||
sourceWidth = bitmapInfo.bmWidth;
|
||||
sourceHeight = bitmapInfo.bmHeight;
|
||||
if (sourceHeight < 0)
|
||||
sourceHeight = -sourceHeight;
|
||||
}
|
||||
|
||||
if (0 != (AlphaBlend_ScaleSource & flags))
|
||||
{
|
||||
RECT rect;
|
||||
double scaleHorz, scaleVert;
|
||||
|
||||
scaleHorz = (double)RECTWIDTH(*targetRect) / sourceWidth;
|
||||
scaleVert = (double)RECTHEIGHT(*targetRect) / sourceHeight;
|
||||
if (scaleHorz > scaleVert)
|
||||
scaleHorz = scaleVert;
|
||||
|
||||
SetRect(&rect, 0, 0, (int)(sourceWidth * scaleHorz), (int)(sourceHeight * scaleHorz));
|
||||
|
||||
if (0 != (AlphaBlend_AlignLeft & flags))
|
||||
rect.left = targetRect->left;
|
||||
else if (0 != (AlphaBlend_AlignRight & flags))
|
||||
rect.left = targetRect->right - rect.right;
|
||||
else
|
||||
rect.left = targetRect->left + (RECTWIDTH(*targetRect) - rect.right)/2;
|
||||
|
||||
if (0 != (AlphaBlend_AlignTop & flags))
|
||||
rect.top = targetRect->top;
|
||||
else if (0 != (AlphaBlend_AlignBottom & flags))
|
||||
rect.top = targetRect->bottom - rect.bottom;
|
||||
else
|
||||
rect.top = targetRect->top + (RECTHEIGHT(*targetRect) - rect.bottom)/2;
|
||||
|
||||
rect.right += rect.left;
|
||||
rect.bottom += rect.top;
|
||||
|
||||
if (NULL != rectOut)
|
||||
CopyRect(rectOut, &rect);
|
||||
|
||||
if (NULL != paintRect)
|
||||
{
|
||||
if (FALSE == IntersectRect(&fillRect, &rect, paintRect))
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
CopyRect(&fillRect, &rect);
|
||||
|
||||
sourceX += (int)((fillRect.left - rect.left)/scaleHorz);
|
||||
sourceY += (int)((fillRect.top - rect.top)/ scaleHorz);
|
||||
sourceWidth -= (int)((RECTWIDTH(rect) - RECTWIDTH(fillRect))/scaleHorz);
|
||||
sourceHeight -= (int)((RECTHEIGHT(rect) - RECTHEIGHT(fillRect))/scaleHorz);
|
||||
clipSource = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sourceWidth < RECTWIDTH(*targetRect) ||
|
||||
sourceHeight < RECTHEIGHT(*targetRect))
|
||||
{
|
||||
RECT rect;
|
||||
|
||||
if (0 != (AlphaBlend_AlignLeft & flags))
|
||||
rect.left = targetRect->left;
|
||||
else if (0 != (AlphaBlend_AlignRight & flags))
|
||||
rect.left = targetRect->right - sourceWidth;
|
||||
else
|
||||
rect.left = targetRect->left + (RECTWIDTH(*targetRect) - sourceWidth)/2;
|
||||
|
||||
if (0 != (AlphaBlend_AlignTop & flags))
|
||||
rect.top = targetRect->top;
|
||||
else if (0 != (AlphaBlend_AlignBottom & flags))
|
||||
rect.top = targetRect->bottom - sourceHeight;
|
||||
else
|
||||
rect.top = targetRect->top + (RECTHEIGHT(*targetRect) - sourceHeight)/2;
|
||||
|
||||
rect.right = rect.left + sourceWidth;
|
||||
rect.bottom = rect.top + sourceHeight;
|
||||
|
||||
if (NULL != paintRect)
|
||||
{
|
||||
if (FALSE == IntersectRect(&fillRect, &rect, paintRect))
|
||||
return TRUE;
|
||||
|
||||
sourceX += (fillRect.left - rect.left);
|
||||
sourceY += (fillRect.top - rect.top);
|
||||
sourceWidth -= (RECTWIDTH(rect) - RECTWIDTH(fillRect));
|
||||
sourceHeight -= (RECTHEIGHT(rect) - RECTHEIGHT(fillRect));
|
||||
}
|
||||
else
|
||||
CopyRect(&fillRect, &rect);
|
||||
|
||||
if (NULL != rectOut)
|
||||
CopyRect(rectOut, &rect);
|
||||
|
||||
clipSource = FALSE;
|
||||
}
|
||||
else if (NULL != rectOut)
|
||||
CopyRect(rectOut, targetRect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (FALSE != clipSource)
|
||||
{
|
||||
sourceX += (fillRect.left - targetRect->left);
|
||||
sourceY += (fillRect.top - targetRect->top);
|
||||
sourceWidth -= (RECTWIDTH(*targetRect) - RECTWIDTH(fillRect));
|
||||
sourceHeight -= (RECTHEIGHT(*targetRect) - RECTHEIGHT(fillRect));
|
||||
}
|
||||
|
||||
if (NULL != sourceBitmap)
|
||||
SelectBitmap(sourceDC, sourceBitmap);
|
||||
|
||||
result = GdiAlphaBlend(targetDC, fillRect.left, fillRect.top, RECTWIDTH(fillRect), RECTHEIGHT(fillRect),
|
||||
sourceDC, sourceX, sourceY, sourceWidth, sourceHeight, blendFunction);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
227
Src/Plugins/Library/ml_devices/image.h
Normal file
227
Src/Plugins/Library/ml_devices/image.h
Normal file
|
@ -0,0 +1,227 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_IMAGE_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_IMAGE_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#define IMAGE_FILTER_NORMAL 0x00000000
|
||||
#define IMAGE_FILTER_GRAYSCALE 0x00010000
|
||||
#define IMAGE_FILTER_BLEND 0x00020000
|
||||
#define IMAGE_FILTER_MASK 0xFFFF0000
|
||||
|
||||
|
||||
typedef struct ImageInfo
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
const wchar_t *path;
|
||||
} ImageInfo;
|
||||
|
||||
|
||||
HBITMAP
|
||||
Image_Load(const wchar_t *path,
|
||||
unsigned int type,
|
||||
unsigned int flags,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
HBITMAP
|
||||
Image_LoadEx(HINSTANCE instance,
|
||||
const wchar_t *path,
|
||||
unsigned int type,
|
||||
unsigned int flags,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
HBITMAP
|
||||
Image_LoadSkinned(const wchar_t *path,
|
||||
unsigned int type,
|
||||
unsigned int flags, //ISF_XXX + IMAGE_FILTER_XXX
|
||||
int width,
|
||||
int height,
|
||||
COLORREF backColor,
|
||||
COLORREF frontColor,
|
||||
COLORREF blendColor); // only valid if IMAGE_FILTER_BLEND set
|
||||
|
||||
HBITMAP
|
||||
Image_LoadSkinnedEx(HINSTANCE instance,
|
||||
const wchar_t *path,
|
||||
unsigned int type,
|
||||
unsigned int flags, //ISF_XXX + IMAGE_FILTER_XXX
|
||||
int width,
|
||||
int height,
|
||||
COLORREF backColor,
|
||||
COLORREF frontColor,
|
||||
COLORREF blendColor); // only valid if IMAGE_FILTER_BLEND set
|
||||
|
||||
BOOL
|
||||
Image_FilterEx(void *pixelData,
|
||||
long width,
|
||||
long height,
|
||||
unsigned short bpp,
|
||||
unsigned int flags,
|
||||
COLORREF backColor,
|
||||
COLORREF frontColor,
|
||||
COLORREF blendColor);
|
||||
|
||||
BOOL
|
||||
Image_Filter(HBITMAP bitmap,
|
||||
unsigned int flags,
|
||||
COLORREF backColor,
|
||||
COLORREF frontColor,
|
||||
COLORREF blendColor);
|
||||
|
||||
BOOL
|
||||
Image_BlendEx(void *pixelData,
|
||||
long width,
|
||||
long height,
|
||||
unsigned short bpp,
|
||||
COLORREF blendColor);
|
||||
BOOL
|
||||
Image_Blend(HBITMAP bitmap,
|
||||
COLORREF blendColor);
|
||||
|
||||
HBITMAP
|
||||
Image_DuplicateDib(HBITMAP source);
|
||||
|
||||
BOOL
|
||||
Image_ColorOver(HBITMAP hbmp,
|
||||
const RECT *prcPart,
|
||||
BOOL premult,
|
||||
COLORREF rgb);
|
||||
|
||||
BOOL
|
||||
Image_ColorOverEx(unsigned char *pPixels,
|
||||
int bitmapCX,
|
||||
int bitmapCY,
|
||||
long x,
|
||||
long y,
|
||||
long cx,
|
||||
long cy,
|
||||
unsigned short bpp,
|
||||
BOOL premult,
|
||||
COLORREF rgb);
|
||||
|
||||
BOOL
|
||||
Image_Premultiply(HBITMAP hbmp,
|
||||
const RECT *prcPart);
|
||||
|
||||
BOOL
|
||||
Image_PremultiplyEx(unsigned char *pPixels,
|
||||
int bitmapCX,
|
||||
int bitmapCY,
|
||||
long x,
|
||||
long y,
|
||||
long cx,
|
||||
long cy,
|
||||
unsigned short bpp);
|
||||
|
||||
BOOL
|
||||
Image_Demultiply(HBITMAP hbmp,
|
||||
const RECT *prcPart);
|
||||
|
||||
BOOL
|
||||
Image_DemultiplyEx(unsigned char *pPixels,
|
||||
int bitmapCX,
|
||||
int bitmapCY,
|
||||
long x,
|
||||
long y,
|
||||
long cx,
|
||||
long cy,
|
||||
unsigned short bpp);
|
||||
|
||||
BOOL
|
||||
Image_Saturate(HBITMAP hbmp,
|
||||
const RECT *prcPart,
|
||||
int n,
|
||||
BOOL fScale);
|
||||
|
||||
BOOL
|
||||
Image_SaturateEx(unsigned char *pPixels,
|
||||
int bitmapCX,
|
||||
int bitmapCY,
|
||||
long x,
|
||||
long y,
|
||||
long cx,
|
||||
long cy,
|
||||
unsigned short bpp,
|
||||
int n,
|
||||
BOOL fScale);
|
||||
|
||||
BOOL
|
||||
Image_AdjustAlpha(HBITMAP hbmp,
|
||||
const RECT *prcPart,
|
||||
int n,
|
||||
BOOL fScale);
|
||||
|
||||
BOOL
|
||||
Image_AdjustAlphaEx(unsigned char *pPixels,
|
||||
int bitmapCX,
|
||||
int bitmapCY,
|
||||
long x,
|
||||
long y,
|
||||
long cx,
|
||||
long cy,
|
||||
unsigned short bpp,
|
||||
int n,
|
||||
BOOL fScale);
|
||||
|
||||
BOOL
|
||||
Image_AdjustSaturationAlpha(HBITMAP hbmp,
|
||||
const RECT *prcPart,
|
||||
int nSaturation,
|
||||
int nAlpha);
|
||||
|
||||
BOOL
|
||||
Image_AdjustSaturationAlphaEx(unsigned char *pPixels,
|
||||
int bitmapCX,
|
||||
int bitmapCY,
|
||||
long x,
|
||||
long y,
|
||||
long cx,
|
||||
long cy,
|
||||
unsigned short bpp,
|
||||
int nSaturation,
|
||||
int nAlpha);
|
||||
|
||||
BOOL
|
||||
Image_FillBorder(HDC targetDC,
|
||||
const RECT *targetRect,
|
||||
HDC sourceDC,
|
||||
const RECT *sourceRect,
|
||||
BOOL fillCenter,
|
||||
BYTE alphaConstant);
|
||||
|
||||
|
||||
const ImageInfo *
|
||||
Image_GetBestFit(const ImageInfo *images,
|
||||
size_t count,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
typedef enum AlphaBlendFlags
|
||||
{
|
||||
AlphaBlend_Normal = 0,
|
||||
AlphaBlend_ScaleSource = (1 << 0),
|
||||
AlphaBlend_AlignLeft = (1 << 1),
|
||||
AlphaBlend_AlignRight = (1 << 2),
|
||||
AlphaBlend_AlignCenter = 0,
|
||||
AlphaBlend_AlignTop = (1 << 3),
|
||||
AlphaBlend_AlignBottom = (1 << 4),
|
||||
AlphaBlend_AlignVCenter = 0,
|
||||
}AlphaBlendFlags;
|
||||
DEFINE_ENUM_FLAG_OPERATORS(AlphaBlendFlags);
|
||||
|
||||
BOOL
|
||||
Image_AlphaBlend(HDC targetDC,
|
||||
const RECT *targetRect,
|
||||
HDC sourceDC,
|
||||
const RECT *sourceRect,
|
||||
BYTE sourceAlpha,
|
||||
HBITMAP sourceBitmap,
|
||||
const RECT *paintRect,
|
||||
AlphaBlendFlags flags,
|
||||
RECT *rectOut);
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_IMAGE_HEADER
|
902
Src/Plugins/Library/ml_devices/imageCache.cpp
Normal file
902
Src/Plugins/Library/ml_devices/imageCache.cpp
Normal file
|
@ -0,0 +1,902 @@
|
|||
#include "main.h"
|
||||
#include "./imageCache.h"
|
||||
#include <wincodec.h>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
struct DeviceColoredImage
|
||||
{
|
||||
size_t ref;
|
||||
DeviceImage *base;
|
||||
HBITMAP bitmap;
|
||||
COLORREF color1;
|
||||
COLORREF color2;
|
||||
DeviceImageFilter filter;
|
||||
void *filterParam;
|
||||
};
|
||||
|
||||
typedef std::vector<DeviceColoredImage*> DeviceColoredImageList;
|
||||
|
||||
struct DeviceImage
|
||||
{
|
||||
size_t ref;
|
||||
DeviceImageCache *cache;
|
||||
wchar_t *source;
|
||||
HBITMAP bitmap;
|
||||
HBITMAP exactBitmap;
|
||||
int width;
|
||||
int height;
|
||||
DeviceImageLoader loader;
|
||||
void *loaderParam;
|
||||
DeviceColoredImageList list;
|
||||
};
|
||||
typedef std::vector<DeviceImage*> DeviceImageList;
|
||||
|
||||
struct DeviceImageCache
|
||||
{
|
||||
DeviceImageList list;
|
||||
IWICImagingFactory *wicFactory;
|
||||
};
|
||||
|
||||
typedef struct DeviceImageSeachParam
|
||||
{
|
||||
const wchar_t *path;
|
||||
int width;
|
||||
int height;
|
||||
} DeviceImageSeachParam;
|
||||
|
||||
typedef struct DeviceColoredImageSeachParam
|
||||
{
|
||||
COLORREF color1;
|
||||
COLORREF color2;
|
||||
} DeviceColoredImageSeachParam;
|
||||
|
||||
|
||||
DeviceImageCache *
|
||||
DeviceImageCache_Create()
|
||||
{
|
||||
DeviceImageCache *self;
|
||||
|
||||
self = new DeviceImageCache();
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
self->wicFactory = NULL;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DeviceImageCache_Free(DeviceImageCache *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
size_t index = self->list.size();
|
||||
while(index--)
|
||||
{
|
||||
DeviceImage *image = self->list[index];
|
||||
image->cache = NULL;
|
||||
}
|
||||
|
||||
if (NULL != self->wicFactory)
|
||||
self->wicFactory->Release();
|
||||
|
||||
delete(self);
|
||||
}
|
||||
|
||||
|
||||
static DeviceImage *
|
||||
DeviceImage_Create(DeviceImageCache *cache, const wchar_t *path, int width, int height,
|
||||
DeviceImageLoader loader, void *loaderParam)
|
||||
{
|
||||
DeviceImage *self;
|
||||
|
||||
if (NULL == loader)
|
||||
return NULL;
|
||||
|
||||
self = new DeviceImage();
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
self->ref = 1;
|
||||
self->cache = cache;
|
||||
self->source = ResourceString_Duplicate(path);
|
||||
self->loader = loader;
|
||||
self->loaderParam = loaderParam;
|
||||
self->bitmap = NULL;
|
||||
self->exactBitmap = NULL;
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceImage_Free(DeviceImage *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
if (NULL != self->source)
|
||||
ResourceString_Free(self->source);
|
||||
|
||||
if (NULL != self->bitmap)
|
||||
DeleteObject(self->bitmap);
|
||||
|
||||
if (NULL != self->exactBitmap &&
|
||||
self->exactBitmap != self->bitmap)
|
||||
{
|
||||
DeleteObject(self->exactBitmap);
|
||||
}
|
||||
|
||||
delete(self);
|
||||
}
|
||||
|
||||
static int
|
||||
DeviceImageCache_SearchCb(const void *key, const void *element)
|
||||
{
|
||||
DeviceImageSeachParam *search;
|
||||
DeviceImage *image;
|
||||
int result;
|
||||
|
||||
search = (DeviceImageSeachParam*)key;
|
||||
image = (DeviceImage*)element;
|
||||
|
||||
result = search->height - image->height;
|
||||
if (0 != result)
|
||||
return result;
|
||||
|
||||
result = search->width - image->width;
|
||||
if (0 != result)
|
||||
return result;
|
||||
|
||||
if (FALSE != IS_INTRESOURCE(search->path) ||
|
||||
FALSE != IS_INTRESOURCE(image->source))
|
||||
{
|
||||
return (int)(INT_PTR)(search->path - image->source);
|
||||
}
|
||||
|
||||
return CompareString(CSTR_INVARIANT, 0, search->path, -1, image->source, -1) - 2;
|
||||
}
|
||||
|
||||
static int
|
||||
DeviceImageCache_SortCb(const void *element1, const void *element2)
|
||||
{
|
||||
DeviceImage *image1;
|
||||
DeviceImage *image2;
|
||||
int result;
|
||||
|
||||
image1 = (DeviceImage*)element1;
|
||||
image2 = (DeviceImage*)element2;
|
||||
|
||||
result = image1->height - image2->height;
|
||||
if (0 != result)
|
||||
return result;
|
||||
|
||||
result = image1->width - image2->width;
|
||||
if (0 != result)
|
||||
return result;
|
||||
|
||||
if (FALSE != IS_INTRESOURCE(image1->source) ||
|
||||
FALSE != IS_INTRESOURCE(image2->source))
|
||||
{
|
||||
return (int)(INT_PTR)(image1->source - image2->source);
|
||||
}
|
||||
|
||||
return CompareString(CSTR_INVARIANT, 0, image1->source, -1, image2->source, -1) - 2;
|
||||
}
|
||||
static int
|
||||
DeviceImageCache_SortCb_V2(const void* element1, const void* element2)
|
||||
{
|
||||
return DeviceImageCache_SortCb(element1, element2) < 0;
|
||||
}
|
||||
|
||||
|
||||
static HBITMAP
|
||||
DeviceImage_DefaultImageLoader(const wchar_t *path, int width, int height, void *param)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
unsigned int flags;
|
||||
|
||||
flags = ISF_PREMULTIPLY;
|
||||
if (FALSE == IS_INTRESOURCE(path))
|
||||
flags |= ISF_LOADFROMFILE;
|
||||
|
||||
bitmap = Image_Load(path, SRC_TYPE_PNG, flags, 0, 0);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
DeviceImage *
|
||||
DeviceImageCache_GetImage(DeviceImageCache *self, const wchar_t *path, int width, int height, DeviceImageLoader loader, void *user)
|
||||
{
|
||||
DeviceImage *image, *image_ptr = 0;
|
||||
DeviceImageSeachParam searchParam;
|
||||
|
||||
if (width < 1)
|
||||
width = 0;
|
||||
|
||||
if (height < 1)
|
||||
height = 0;
|
||||
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
if (NULL == path ||
|
||||
(FALSE == IS_INTRESOURCE(path) && L'\0' == *path))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
searchParam.height = height;
|
||||
searchParam.width = width;
|
||||
searchParam.path = path;
|
||||
|
||||
//image_ptr = (DeviceImage**)bsearch(&searchParam, &self->list[0], self->list.size(),
|
||||
// sizeof(DeviceImage**),
|
||||
// DeviceImageCache_SearchCb);
|
||||
auto it = std::find_if(self->list.begin(), self->list.end(),
|
||||
[&](DeviceImage* upT) -> bool
|
||||
{
|
||||
return DeviceImageCache_SearchCb(&searchParam, upT) == 0;
|
||||
}
|
||||
);
|
||||
if (it != self->list.end())
|
||||
{
|
||||
image_ptr = *it;
|
||||
}
|
||||
|
||||
|
||||
if (NULL != image_ptr)
|
||||
{
|
||||
image = image_ptr;
|
||||
DeviceImage_AddRef(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
if (NULL == loader)
|
||||
loader = DeviceImage_DefaultImageLoader;
|
||||
|
||||
image = DeviceImage_Create(self, path, width, height, loader, user);
|
||||
if (NULL != image)
|
||||
{
|
||||
self->list.push_back(image);
|
||||
//qsort(&self->list[0], self->list.size(), sizeof(DeviceImage**), DeviceImageCache_SortCb);
|
||||
std::sort(self->list.begin(), self->list.end(), DeviceImageCache_SortCb_V2);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
DeviceImageCache_RemoveImage(DeviceImageCache *self, DeviceImage *image)
|
||||
{
|
||||
size_t index;
|
||||
|
||||
if (NULL == self || NULL == image)
|
||||
return FALSE;
|
||||
|
||||
index = self->list.size();
|
||||
while(index--)
|
||||
{
|
||||
if (self->list[index] == image)
|
||||
{
|
||||
self->list.erase(self->list.begin() + index);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
size_t
|
||||
DeviceImage_AddRef(DeviceImage *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return 0;
|
||||
return InterlockedIncrement((LONG*)&self->ref);
|
||||
}
|
||||
|
||||
size_t
|
||||
DeviceImage_Release(DeviceImage *self)
|
||||
{
|
||||
size_t r;
|
||||
if (NULL == self || 0 == self->ref)
|
||||
return 0;
|
||||
|
||||
r = InterlockedDecrement((LONG*)&self->ref);
|
||||
if (0 == r)
|
||||
{
|
||||
if (NULL != self->cache)
|
||||
DeviceImageCache_RemoveImage(self->cache, self);
|
||||
DeviceImage_Free(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
BOOL
|
||||
DeviceImage_GetSize(DeviceImage *self, int *width, int *height)
|
||||
{
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
if (NULL != width)
|
||||
*width = self->width;
|
||||
|
||||
if (NULL != height)
|
||||
*height = self->height;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static IWICImagingFactory*
|
||||
DeviceImage_GetWicFactory(DeviceImageCache *cache)
|
||||
{
|
||||
IWICImagingFactory *wicFactory;
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL != cache &&
|
||||
NULL != cache->wicFactory)
|
||||
{
|
||||
cache->wicFactory->AddRef();
|
||||
return cache->wicFactory;
|
||||
}
|
||||
|
||||
hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
|
||||
IID_PPV_ARGS(&wicFactory));
|
||||
|
||||
if (FAILED(hr))
|
||||
return NULL;
|
||||
|
||||
if (NULL != cache)
|
||||
{
|
||||
wicFactory->AddRef();
|
||||
cache->wicFactory = wicFactory;
|
||||
}
|
||||
|
||||
return wicFactory;
|
||||
}
|
||||
|
||||
|
||||
static HBITMAP
|
||||
DeviceImage_HBitmapFromWicSource(IWICBitmapSource *wicSource, unsigned int targetWidth,
|
||||
unsigned int targetHeight, DeviceImageFlags flags)
|
||||
{
|
||||
HRESULT hr;
|
||||
HBITMAP bitmap;
|
||||
BITMAPINFO bitmapInfo;
|
||||
unsigned int width, height, bitmapWidth, bitmapHeight;
|
||||
void *pixelData = NULL;
|
||||
WICPixelFormatGUID pixelFormat;
|
||||
HDC windowDC;
|
||||
unsigned int strideSize, imageSize;
|
||||
|
||||
if (NULL == wicSource)
|
||||
return NULL;
|
||||
|
||||
hr = wicSource->GetPixelFormat(&pixelFormat);
|
||||
if (FAILED(hr) ||
|
||||
(GUID_WICPixelFormat32bppPBGRA != pixelFormat &&
|
||||
GUID_WICPixelFormat32bppBGR != pixelFormat &&
|
||||
GUID_WICPixelFormat32bppBGRA != pixelFormat &&
|
||||
GUID_WICPixelFormat32bppRGBA != pixelFormat &&
|
||||
GUID_WICPixelFormat32bppPRGBA != pixelFormat))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hr = wicSource->GetSize(&width, &height);
|
||||
if (FAILED(hr))
|
||||
return NULL;
|
||||
|
||||
if (0 != (DeviceImage_ExactSize & flags))
|
||||
{
|
||||
bitmapWidth = (targetWidth > width) ? targetWidth : width;
|
||||
bitmapHeight = (targetHeight > height) ? targetHeight : height;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmapWidth = width;
|
||||
bitmapHeight = height;
|
||||
}
|
||||
|
||||
ZeroMemory(&bitmapInfo, sizeof(bitmapInfo));
|
||||
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfo.bmiHeader.biWidth = bitmapWidth;
|
||||
bitmapInfo.bmiHeader.biHeight = -(LONG)bitmapHeight;
|
||||
bitmapInfo.bmiHeader.biPlanes = 1;
|
||||
bitmapInfo.bmiHeader.biBitCount = 32;
|
||||
bitmapInfo.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
windowDC = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE);
|
||||
|
||||
bitmap = CreateDIBSection(windowDC, &bitmapInfo, DIB_RGB_COLORS, &pixelData, NULL, 0);
|
||||
|
||||
if (NULL != windowDC)
|
||||
ReleaseDC(NULL, windowDC);
|
||||
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
hr = UIntMult(bitmapWidth, sizeof(DWORD), &strideSize);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (0 != (DeviceImage_ExactSize & flags) &&
|
||||
(bitmapWidth > width || bitmapHeight > height))
|
||||
{
|
||||
if (SUCCEEDED(UIntMult(strideSize, bitmapHeight, &imageSize)))
|
||||
ZeroMemory(pixelData, imageSize);
|
||||
}
|
||||
|
||||
hr = UIntMult(strideSize, height, &imageSize);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
unsigned int offset, delta;
|
||||
|
||||
offset = 0;
|
||||
|
||||
if (0 != (DeviceImage_AlignVCenter & flags))
|
||||
{
|
||||
delta = bitmapHeight - height;
|
||||
delta = delta/2 + delta%2;
|
||||
}
|
||||
else if (0 != (DeviceImage_AlignBottom & flags))
|
||||
delta = bitmapHeight - height;
|
||||
else
|
||||
delta = 0;
|
||||
|
||||
if (0 != delta && SUCCEEDED(UIntMult(delta, strideSize, &delta)))
|
||||
offset += delta;
|
||||
|
||||
if (0 != (DeviceImage_AlignHCenter & flags))
|
||||
{
|
||||
delta = bitmapWidth - width;
|
||||
delta = delta/2;
|
||||
}
|
||||
else if (0 != (DeviceImage_AlignRight & flags))
|
||||
delta = bitmapWidth - width;
|
||||
else
|
||||
delta = 0;
|
||||
|
||||
if (0 != delta && SUCCEEDED(UIntMult(delta, sizeof(DWORD), &delta)))
|
||||
offset += delta;
|
||||
|
||||
hr = wicSource->CopyPixels(NULL, strideSize, imageSize, ((BYTE*)pixelData) + offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DeleteObject(bitmap);
|
||||
bitmap = NULL;
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
DeviceImage_ScaleBitmap(HBITMAP sourceBitmap, int width, int height, DeviceImageCache *cache,
|
||||
DeviceImageFlags flags, HBITMAP *scalledBitmap)
|
||||
{
|
||||
HBITMAP resultBitmap;
|
||||
BITMAP sourceInfo;
|
||||
IWICImagingFactory *wicFactory;
|
||||
unsigned int requestedWidth, requestedHeight;
|
||||
double scale, scaleH;
|
||||
int t;
|
||||
|
||||
if (NULL == sourceBitmap || NULL == scalledBitmap)
|
||||
return FALSE;
|
||||
|
||||
if (sizeof(sourceInfo) != GetObject(sourceBitmap, sizeof(sourceInfo), &sourceInfo))
|
||||
return FALSE;
|
||||
|
||||
if (sourceInfo.bmHeight < 0)
|
||||
sourceInfo.bmHeight = -sourceInfo.bmHeight;
|
||||
|
||||
scale = (double)width / sourceInfo.bmWidth;
|
||||
scaleH = (double)height / sourceInfo.bmHeight;
|
||||
|
||||
if (scale > scaleH)
|
||||
scale = scaleH;
|
||||
|
||||
if (1.0 == scale)
|
||||
{
|
||||
*scalledBitmap = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
requestedWidth = width;
|
||||
requestedHeight = height;
|
||||
|
||||
t = (int)((sourceInfo.bmWidth * scale) + 0.5);
|
||||
if (t < width)
|
||||
width = t;
|
||||
|
||||
t = (int)((sourceInfo.bmHeight * scale) + 0.5);
|
||||
if (t < height)
|
||||
height = t;
|
||||
|
||||
|
||||
resultBitmap = NULL;
|
||||
|
||||
wicFactory = DeviceImage_GetWicFactory(cache);
|
||||
if (NULL != wicFactory)
|
||||
{
|
||||
HRESULT hr;
|
||||
IWICBitmap *wicBitmap;
|
||||
|
||||
hr = wicFactory->CreateBitmapFromHBITMAP(sourceBitmap, NULL,
|
||||
WICBitmapUsePremultipliedAlpha, &wicBitmap);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IWICBitmapScaler *wicScaler;
|
||||
hr = wicFactory->CreateBitmapScaler(&wicScaler);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = wicScaler->Initialize(wicBitmap, width, height, WICBitmapInterpolationModeFant);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
resultBitmap = DeviceImage_HBitmapFromWicSource(wicScaler,
|
||||
requestedWidth, requestedHeight, flags);
|
||||
}
|
||||
wicScaler->Release();
|
||||
|
||||
}
|
||||
wicBitmap->Release();
|
||||
}
|
||||
|
||||
wicFactory->Release();
|
||||
}
|
||||
|
||||
*scalledBitmap = resultBitmap;
|
||||
return (NULL != resultBitmap);
|
||||
}
|
||||
|
||||
static HBITMAP
|
||||
DeviceImage_GetExactBitmap(DeviceImage *self, DeviceImageFlags flags)
|
||||
{
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
if (NULL == self->exactBitmap)
|
||||
{
|
||||
if (NULL != self->bitmap)
|
||||
{
|
||||
BITMAP bi;
|
||||
if (sizeof(bi) == GetObject(self->bitmap, sizeof(bi), &bi) &&
|
||||
bi.bmWidth == self->width && bi.bmHeight == self->height)
|
||||
{
|
||||
self->exactBitmap = self->bitmap;
|
||||
return self->exactBitmap;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != self->loader)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
bitmap = self->loader(self->source, self->width, self->height, self->loaderParam);
|
||||
if (NULL != bitmap)
|
||||
{
|
||||
if (FALSE != DeviceImage_ScaleBitmap(bitmap, self->width, self->height,
|
||||
self->cache, flags, &self->exactBitmap))
|
||||
{
|
||||
|
||||
if (NULL == self->exactBitmap)
|
||||
{
|
||||
self->exactBitmap = bitmap;
|
||||
bitmap = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != bitmap)
|
||||
DeleteObject(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self->exactBitmap;
|
||||
}
|
||||
|
||||
|
||||
HBITMAP
|
||||
DeviceImage_GetBitmap(DeviceImage *self, DeviceImageFlags flags)
|
||||
{
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
if (0 != (DeviceImage_ExactSize & flags))
|
||||
return DeviceImage_GetExactBitmap(self, flags);
|
||||
|
||||
if (NULL == self->bitmap)
|
||||
{
|
||||
if (NULL != self->loader)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
bitmap = self->loader(self->source, self->width, self->height, self->loaderParam);
|
||||
if (NULL != bitmap)
|
||||
{
|
||||
if (FALSE == DeviceImage_ScaleBitmap(bitmap, self->width, self->height,
|
||||
self->cache, flags, &self->bitmap))
|
||||
{
|
||||
self->bitmap = NULL;
|
||||
}
|
||||
|
||||
if (NULL != self->bitmap)
|
||||
DeleteObject(bitmap);
|
||||
else
|
||||
self->bitmap = bitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self->bitmap;
|
||||
}
|
||||
|
||||
|
||||
static DeviceColoredImage *
|
||||
DeveiceColoredImage_Create(DeviceImage *base, COLORREF color1, COLORREF color2,
|
||||
DeviceImageFilter filter, void *user)
|
||||
{
|
||||
DeviceColoredImage *coloredImage;
|
||||
|
||||
if (NULL == base)
|
||||
return NULL;
|
||||
|
||||
coloredImage = (DeviceColoredImage*)malloc(sizeof(DeviceColoredImage));
|
||||
if (NULL == coloredImage)
|
||||
return NULL;
|
||||
|
||||
ZeroMemory(coloredImage, sizeof(DeviceColoredImage));
|
||||
|
||||
coloredImage->ref = 1;
|
||||
coloredImage->base = base;
|
||||
coloredImage->color1 = color1;
|
||||
coloredImage->color2 = color2;
|
||||
coloredImage->filter = filter;
|
||||
coloredImage->filterParam = user;
|
||||
|
||||
DeviceImage_AddRef(base);
|
||||
|
||||
return coloredImage;
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceColoredImage_Free(DeviceColoredImage *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
if (NULL != self->bitmap)
|
||||
DeleteObject(self->bitmap);
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
static int
|
||||
DeviceColoredImage_SearchCb(const void *key, const void *element)
|
||||
{
|
||||
DeviceColoredImageSeachParam *search;
|
||||
DeviceColoredImage *image;
|
||||
int result;
|
||||
|
||||
search = (DeviceColoredImageSeachParam*)key;
|
||||
image = (DeviceColoredImage*)element;
|
||||
|
||||
result = search->color1 - image->color1;
|
||||
if (0 != result)
|
||||
return result;
|
||||
|
||||
return search->color2- image->color2;
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
DeviceColoredImage_SortCb(const void *element1, const void *element2)
|
||||
{
|
||||
DeviceColoredImage *image1;
|
||||
DeviceColoredImage *image2;
|
||||
int result;
|
||||
|
||||
image1 = (DeviceColoredImage*)element1;
|
||||
image2 = (DeviceColoredImage*)element2;
|
||||
|
||||
result = image1->color1 - image2->color1;
|
||||
if (0 != result)
|
||||
return result;
|
||||
|
||||
return image1->color2- image2->color2;
|
||||
}
|
||||
|
||||
static int
|
||||
DeviceColoredImage_SortCb_V2(const void* element1, const void* element2)
|
||||
{
|
||||
return DeviceColoredImage_SortCb(element1, element2) < 0;
|
||||
}
|
||||
|
||||
DeviceColoredImage *
|
||||
DeviceImage_GetColoredImage(DeviceImage *self, COLORREF color1, COLORREF color2,
|
||||
DeviceImageFilter filter, void *user)
|
||||
{
|
||||
size_t listSize;
|
||||
DeviceColoredImage *image;
|
||||
DeviceColoredImageSeachParam searchParam;
|
||||
|
||||
searchParam.color1 = color1;
|
||||
searchParam.color2 = color2;
|
||||
|
||||
listSize = self->list.size();
|
||||
if (listSize > 0)
|
||||
{
|
||||
DeviceColoredImage* image_ptr = NULL;
|
||||
//DeviceColoredImage **image_ptr = (DeviceColoredImage**)bsearch(&searchParam, &self->list[0], listSize,
|
||||
// sizeof(DeviceColoredImage**),
|
||||
// DeviceColoredImage_SearchCb);
|
||||
|
||||
auto it = std::find_if(self->list.begin(), self->list.end(),
|
||||
[&](DeviceColoredImage* upT) -> bool
|
||||
{
|
||||
return DeviceColoredImage_SearchCb(&searchParam, upT) == 0;
|
||||
}
|
||||
);
|
||||
if (it != self->list.end())
|
||||
{
|
||||
image_ptr = *it;
|
||||
}
|
||||
|
||||
if (NULL != image_ptr)
|
||||
{
|
||||
image = image_ptr;
|
||||
DeviceColoredImage_AddRef(image);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
image = DeveiceColoredImage_Create(self, color1, color2, filter, user);
|
||||
if (NULL == image)
|
||||
return NULL;
|
||||
|
||||
self->list.push_back(image);
|
||||
listSize++;
|
||||
|
||||
if (listSize > 1)
|
||||
{
|
||||
//qsort(&self->list[0], self->list.size(), sizeof(DeviceColoredImage**),
|
||||
// DeviceColoredImage_SortCb);
|
||||
std::sort(self->list.begin(), self->list.end(), DeviceColoredImage_SortCb_V2);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static void
|
||||
DeviceImage_RemoveColored(DeviceImage *self, DeviceColoredImage *coloredImage)
|
||||
{
|
||||
size_t index;
|
||||
|
||||
if (NULL == self || NULL == coloredImage)
|
||||
return;
|
||||
|
||||
index = self->list.size();
|
||||
while(index--)
|
||||
{
|
||||
if (coloredImage == self->list[index])
|
||||
{
|
||||
self->list.erase(self->list.begin() + index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
DeviceColoredImage_AddRef(DeviceColoredImage *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return 0;
|
||||
return InterlockedIncrement((LONG*)&self->ref);
|
||||
}
|
||||
|
||||
size_t
|
||||
DeviceColoredImage_Release(DeviceColoredImage *self)
|
||||
{
|
||||
size_t r;
|
||||
if (NULL == self || 0 == self->ref)
|
||||
return 0;
|
||||
|
||||
r = InterlockedDecrement((LONG*)&self->ref);
|
||||
if (0 == r)
|
||||
{
|
||||
if (NULL != self->base)
|
||||
{
|
||||
DeviceImage_RemoveColored(self->base, self);
|
||||
DeviceImage_Release(self->base);
|
||||
}
|
||||
DeviceColoredImage_Free(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
DeviceColoredImage_DefaultFilter(HBITMAP bitmap, COLORREF color1, COLORREF color2, void *user)
|
||||
{
|
||||
DIBSECTION bitmapDib;
|
||||
BITMAP *bitmapInfo;
|
||||
MLIMAGEFILTERAPPLYEX filter;
|
||||
|
||||
if (sizeof(bitmapDib) != GetObjectW(bitmap, sizeof(bitmapDib), &bitmapDib))
|
||||
return FALSE;
|
||||
|
||||
bitmapInfo = &bitmapDib.dsBm;
|
||||
|
||||
filter.cbSize = sizeof(filter);
|
||||
filter.pData = (BYTE*)bitmapInfo->bmBits;
|
||||
filter.cx = bitmapInfo->bmWidth;
|
||||
filter.cy = bitmapInfo->bmHeight;
|
||||
filter.bpp = bitmapInfo->bmBitsPixel;
|
||||
filter.imageTag = NULL;
|
||||
|
||||
filter.filterUID = MLIF_GRAYSCALE_UID;
|
||||
MLImageFilter_ApplyEx(Plugin_GetLibraryWindow(), &filter);
|
||||
|
||||
filter.rgbBk = color1;
|
||||
filter.rgbFg = color2;
|
||||
|
||||
if (32 == bitmapInfo->bmBitsPixel)
|
||||
{
|
||||
filter.filterUID = MLIF_FILTER1_PRESERVE_ALPHA_UID;
|
||||
MLImageFilter_ApplyEx(Plugin_GetLibraryWindow(), &filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
filter.filterUID = MLIF_FILTER1_UID;
|
||||
MLImageFilter_ApplyEx(Plugin_GetLibraryWindow(), &filter);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
DeviceColoredImage_GetBitmap(DeviceColoredImage *self, DeviceImageFlags flags)
|
||||
{
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
if (NULL == self->bitmap)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
bitmap = DeviceImage_GetBitmap(self->base, flags);
|
||||
if (NULL != bitmap)
|
||||
{
|
||||
self->bitmap = Image_DuplicateDib(bitmap);
|
||||
if (NULL != self->bitmap)
|
||||
{
|
||||
DeviceImageFilter filter;
|
||||
if (NULL == self->filter)
|
||||
filter = DeviceColoredImage_DefaultFilter;
|
||||
else
|
||||
filter = self->filter;
|
||||
|
||||
Image_Demultiply(self->bitmap, NULL);
|
||||
filter(self->bitmap, self->color1, self->color2, self->filterParam);
|
||||
Image_Premultiply(self->bitmap, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self->bitmap;
|
||||
}
|
||||
|
||||
DeviceImage*
|
||||
DeviceColoredImage_GetBaseImage(DeviceColoredImage *self)
|
||||
{
|
||||
if (NULL == self || NULL == self->base)
|
||||
return NULL;
|
||||
|
||||
DeviceImage_AddRef(self->base);
|
||||
return self->base;
|
||||
}
|
76
Src/Plugins/Library/ml_devices/imageCache.h
Normal file
76
Src/Plugins/Library/ml_devices/imageCache.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_IMAGE_CACHE_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_IMAGE_CACHE_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
typedef struct DeviceColoredImage DeviceColoredImage;
|
||||
typedef struct DeviceImage DeviceImage;
|
||||
typedef struct DeviceImageCache DeviceImageCache;
|
||||
|
||||
typedef HBITMAP (*DeviceImageLoader)(const wchar_t* /*path*/, int /*width*/, int /*height*/, void* /*user*/);
|
||||
typedef BOOL (*DeviceImageFilter)(HBITMAP /*bitmap*/, COLORREF /*color1*/, COLORREF /*color2*/, void* /*user*/);
|
||||
|
||||
DeviceImageCache *
|
||||
DeviceImageCache_Create();
|
||||
|
||||
void
|
||||
DeviceImageCache_Free(DeviceImageCache *self);
|
||||
|
||||
DeviceImage *
|
||||
DeviceImageCache_GetImage(DeviceImageCache *self,
|
||||
const wchar_t *path,
|
||||
int width,
|
||||
int height,
|
||||
DeviceImageLoader loader,
|
||||
void *user);
|
||||
|
||||
size_t
|
||||
DeviceImage_AddRef(DeviceImage *self);
|
||||
|
||||
size_t
|
||||
DeviceImage_Release(DeviceImage *self);
|
||||
|
||||
BOOL
|
||||
DeviceImage_GetSize(DeviceImage *self,
|
||||
int *width,
|
||||
int *height);
|
||||
|
||||
typedef enum DeviceImageFlags
|
||||
{
|
||||
|
||||
DeviceImage_ExactSize = (1 << 0),
|
||||
DeviceImage_AlignLeft = 0,
|
||||
DeviceImage_AlignRight = (1 << 1),
|
||||
DeviceImage_AlignHCenter = (1 << 2),
|
||||
DeviceImage_AlignTop = 0,
|
||||
DeviceImage_AlignBottom = (1 << 3),
|
||||
DeviceImage_AlignVCenter = (1 << 4),
|
||||
DeviceImage_Normal = (DeviceImage_AlignLeft | DeviceImage_AlignTop),
|
||||
} DeviceImageFlags;
|
||||
DEFINE_ENUM_FLAG_OPERATORS(DeviceImageFlags);
|
||||
|
||||
HBITMAP
|
||||
DeviceImage_GetBitmap(DeviceImage *self, DeviceImageFlags flags);
|
||||
|
||||
DeviceColoredImage *
|
||||
DeviceImage_GetColoredImage(DeviceImage *self,
|
||||
COLORREF color1,
|
||||
COLORREF color2,
|
||||
DeviceImageFilter filter,
|
||||
void *user);
|
||||
|
||||
size_t
|
||||
DeviceColoredImage_AddRef(DeviceColoredImage *self);
|
||||
|
||||
size_t
|
||||
DeviceColoredImage_Release(DeviceColoredImage *self);
|
||||
|
||||
HBITMAP
|
||||
DeviceColoredImage_GetBitmap(DeviceColoredImage *self, DeviceImageFlags flags);
|
||||
|
||||
DeviceImage*
|
||||
DeviceColoredImage_GetBaseImage(DeviceColoredImage *self);
|
||||
|
||||
#endif // _NULLSOFT_WINAMP_ML_DEVICES_IMAGE_CACHE_HEADER
|
399
Src/Plugins/Library/ml_devices/infoWidget.cpp
Normal file
399
Src/Plugins/Library/ml_devices/infoWidget.cpp
Normal file
|
@ -0,0 +1,399 @@
|
|||
#include "main.h"
|
||||
#include "./infoWidget.h"
|
||||
|
||||
#define INFOWIDGET_OFFSET_LEFT_DLU 4
|
||||
#define INFOWIDGET_OFFSET_TOP_DLU 2
|
||||
#define INFOWIDGET_OFFSET_RIGHT_DLU 4
|
||||
#define INFOWIDGET_OFFSET_BOTTOM_DLU 2
|
||||
|
||||
#define INFOWIDGET_MIN_WIDTH_DLU (8*4)
|
||||
#define INFOWIDGET_MAX_WIDTH_DLU (48*4)
|
||||
|
||||
#define INFOWIDGET_TITLE_OFFSET_BOTTOM_DLU 24
|
||||
#define INFOWIDGET_IMAGE_OFFSET_BOTTOM_DLU 24
|
||||
|
||||
|
||||
typedef struct InfoWidget
|
||||
{
|
||||
wchar_t *title;
|
||||
wchar_t *text;
|
||||
wchar_t *imagePath;
|
||||
HBITMAP image;
|
||||
RECT titleRect;
|
||||
RECT textRect;
|
||||
RECT imageRect;
|
||||
BackBuffer backBuffer;
|
||||
} InfoWidget;
|
||||
|
||||
typedef struct InfoWidgetParam
|
||||
{
|
||||
const wchar_t *title;
|
||||
const wchar_t *text;
|
||||
const wchar_t *imagePath;
|
||||
} InfoWidgetParam;
|
||||
|
||||
static BOOL
|
||||
InfoWidget_InitCb(HWND hwnd, void **object, void *param)
|
||||
{
|
||||
InfoWidget *self;
|
||||
const InfoWidgetParam *createParam;
|
||||
|
||||
self = (InfoWidget*)malloc(sizeof(InfoWidget));
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
ZeroMemory(self, sizeof(InfoWidget));
|
||||
|
||||
|
||||
createParam = (InfoWidgetParam*)param;
|
||||
|
||||
if (NULL != createParam)
|
||||
{
|
||||
wchar_t buffer[4096] = {0};
|
||||
|
||||
if (FALSE != IS_INTRESOURCE(createParam->title))
|
||||
{
|
||||
if (NULL != WASABI_API_LNG)
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF((int)(INT_PTR)createParam->title, buffer, ARRAYSIZE(buffer));
|
||||
self->title = String_Duplicate(buffer);
|
||||
}
|
||||
else
|
||||
self->title = NULL;
|
||||
}
|
||||
else
|
||||
self->title = String_Duplicate(createParam->title);
|
||||
|
||||
if (FALSE != IS_INTRESOURCE(createParam->text))
|
||||
{
|
||||
if (NULL != WASABI_API_LNG)
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF((int)(INT_PTR)createParam->text, buffer, ARRAYSIZE(buffer));
|
||||
self->text = String_Duplicate(buffer);
|
||||
}
|
||||
else
|
||||
self->text = NULL;
|
||||
}
|
||||
else
|
||||
self->text = String_Duplicate(createParam->text);
|
||||
|
||||
self->imagePath = ResourceString_Duplicate(createParam->imagePath);
|
||||
}
|
||||
|
||||
BackBuffer_Initialize(&self->backBuffer, hwnd);
|
||||
|
||||
*object = self;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
InfoWidget_DestroyCb(InfoWidget *self, HWND hwnd)
|
||||
{
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
String_Free(self->title);
|
||||
String_Free(self->text);
|
||||
ResourceString_Free(self->imagePath);
|
||||
|
||||
if (NULL != self->image)
|
||||
DeleteObject(self->image);
|
||||
|
||||
BackBuffer_Uninitialize(&self->backBuffer);
|
||||
free(self);
|
||||
}
|
||||
|
||||
|
||||
static HBITMAP
|
||||
InfoWidget_GetImage(InfoWidget *self, WidgetStyle *style)
|
||||
{
|
||||
if (NULL == self->image)
|
||||
{
|
||||
unsigned int flags;
|
||||
|
||||
flags = IMAGE_FILTER_BLEND;
|
||||
|
||||
if (FALSE == IS_INTRESOURCE(self->imagePath))
|
||||
flags |= ISF_LOADFROMFILE;
|
||||
|
||||
self->image = Image_LoadSkinned(self->imagePath, SRC_TYPE_PNG, flags,
|
||||
0, 0,
|
||||
WIDGETSTYLE_IMAGE_BACK_COLOR(style),
|
||||
WIDGETSTYLE_IMAGE_FRONT_COLOR(style),
|
||||
WIDGETSTYLE_BACK_COLOR(style));
|
||||
|
||||
}
|
||||
|
||||
return self->image;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
InfoWidget_GetImageSize(InfoWidget *self, WidgetStyle *style, SIZE *size)
|
||||
{
|
||||
HBITMAP image;
|
||||
BITMAP imageInfo;
|
||||
|
||||
image = InfoWidget_GetImage(self, style);
|
||||
if (NULL == image)
|
||||
return FALSE;
|
||||
|
||||
if (sizeof(imageInfo) != GetObject(image, sizeof(imageInfo), &imageInfo))
|
||||
return FALSE;
|
||||
|
||||
size->cx = imageInfo.bmWidth;
|
||||
size->cy = imageInfo.bmHeight;
|
||||
if (size->cy < 0)
|
||||
size->cy = -size->cy;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
InfoWidget_GetTextSize(HDC hdc, HFONT font, const wchar_t *text, long width,
|
||||
unsigned int format, SIZE *size)
|
||||
{
|
||||
RECT rect;
|
||||
BOOL result;
|
||||
HFONT prevFont;
|
||||
|
||||
if (FALSE != IS_STRING_EMPTY(text))
|
||||
{
|
||||
size->cx = 0;
|
||||
size->cy = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
prevFont = SelectFont(hdc, font);
|
||||
|
||||
SetRect(&rect, 0, 0, width, 0);
|
||||
result = DrawText(hdc, text, -1, &rect, DT_CALCRECT | format);
|
||||
if (FALSE != result)
|
||||
{
|
||||
size->cx = RECTWIDTH(rect);
|
||||
size->cy = RECTHEIGHT(rect);
|
||||
}
|
||||
|
||||
SelectFont(hdc, prevFont);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static long
|
||||
InfoWidget_GetClientWidth(WidgetStyle *style, long viewWidth)
|
||||
{
|
||||
long test;
|
||||
|
||||
viewWidth -= (WIDGETSTYLE_DLU_TO_HORZ_PX(style, INFOWIDGET_OFFSET_LEFT_DLU) +
|
||||
WIDGETSTYLE_DLU_TO_HORZ_PX(style, INFOWIDGET_OFFSET_RIGHT_DLU));
|
||||
|
||||
test = WIDGETSTYLE_DLU_TO_HORZ_PX(style, INFOWIDGET_MIN_WIDTH_DLU);
|
||||
if (viewWidth < test)
|
||||
return test;
|
||||
|
||||
test = WIDGETSTYLE_DLU_TO_HORZ_PX(style, INFOWIDGET_MAX_WIDTH_DLU);
|
||||
if (viewWidth > test)
|
||||
return test;
|
||||
|
||||
return viewWidth;
|
||||
}
|
||||
|
||||
static void
|
||||
InfoWidget_LayoutCb(InfoWidget *self, HWND hwnd, WidgetStyle *style,
|
||||
const RECT *clientRect, SIZE *viewSize, BOOL redraw)
|
||||
{
|
||||
HDC windowDC;
|
||||
LONG offsetX, offsetY;
|
||||
SIZE widgetSize;
|
||||
RECT offsetRect;
|
||||
|
||||
if (NULL == self || NULL == style)
|
||||
return;
|
||||
|
||||
windowDC = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL == windowDC)
|
||||
return;
|
||||
|
||||
offsetRect.left = WIDGETSTYLE_DLU_TO_HORZ_PX(style, INFOWIDGET_OFFSET_LEFT_DLU);
|
||||
offsetRect.top = WIDGETSTYLE_DLU_TO_VERT_PX(style, INFOWIDGET_OFFSET_TOP_DLU);
|
||||
offsetRect.right = WIDGETSTYLE_DLU_TO_HORZ_PX(style, INFOWIDGET_OFFSET_RIGHT_DLU);
|
||||
offsetRect.bottom = WIDGETSTYLE_DLU_TO_VERT_PX(style, INFOWIDGET_OFFSET_BOTTOM_DLU);
|
||||
|
||||
widgetSize.cx = InfoWidget_GetClientWidth(style, RECTWIDTH(*clientRect));
|
||||
widgetSize.cy = 0;
|
||||
|
||||
SetRectEmpty(&self->imageRect);
|
||||
if (FALSE != InfoWidget_GetImageSize(self, style, ((SIZE*)&self->imageRect) + 1))
|
||||
{
|
||||
if (widgetSize.cx < self->imageRect.right)
|
||||
widgetSize.cx = self->imageRect.right;
|
||||
|
||||
widgetSize.cy += self->imageRect.bottom;
|
||||
if (0 != self->imageRect.bottom)
|
||||
widgetSize.cy += WIDGETSTYLE_DLU_TO_VERT_PX(style, INFOWIDGET_IMAGE_OFFSET_BOTTOM_DLU);
|
||||
}
|
||||
|
||||
SetRectEmpty(&self->titleRect);
|
||||
if (FALSE != InfoWidget_GetTextSize(windowDC, style->titleFont, self->title, widgetSize.cx,
|
||||
DT_LEFT | DT_TOP | DT_NOPREFIX | DT_WORDBREAK, ((SIZE*)&self->titleRect) + 1))
|
||||
{
|
||||
widgetSize.cy += self->titleRect.bottom;
|
||||
if (0 != self->titleRect.bottom)
|
||||
widgetSize.cy += WIDGETSTYLE_DLU_TO_VERT_PX(style, INFOWIDGET_TITLE_OFFSET_BOTTOM_DLU);
|
||||
}
|
||||
|
||||
SetRectEmpty(&self->textRect);
|
||||
if (FALSE != InfoWidget_GetTextSize(windowDC, style->textFont, self->text, widgetSize.cx,
|
||||
DT_LEFT | DT_TOP | DT_NOPREFIX | DT_WORDBREAK, ((SIZE*)&self->textRect) + 1))
|
||||
{
|
||||
widgetSize.cy += self->textRect.bottom;
|
||||
}
|
||||
|
||||
|
||||
if ((widgetSize.cx + (offsetRect.left + offsetRect.right)) < RECTWIDTH(*clientRect))
|
||||
offsetX = clientRect->left + (RECTWIDTH(*clientRect) - widgetSize.cx)/2;
|
||||
else
|
||||
offsetX = clientRect->left + offsetRect.left;
|
||||
|
||||
if ((widgetSize.cy + (offsetRect.top + offsetRect.bottom)) < RECTHEIGHT(*clientRect))
|
||||
offsetY = clientRect->top + (RECTHEIGHT(*clientRect) - widgetSize.cy)/2;
|
||||
else
|
||||
offsetY = clientRect->top + offsetRect.top;
|
||||
|
||||
|
||||
if (FALSE == IsRectEmpty(&self->titleRect))
|
||||
{
|
||||
OffsetRect(&self->titleRect, offsetX + (widgetSize.cx - self->titleRect.right)/2, offsetY);
|
||||
offsetY = self->titleRect.bottom;
|
||||
offsetY += WIDGETSTYLE_DLU_TO_VERT_PX(style, INFOWIDGET_TITLE_OFFSET_BOTTOM_DLU);
|
||||
}
|
||||
|
||||
if (FALSE == IsRectEmpty(&self->imageRect))
|
||||
{
|
||||
OffsetRect(&self->imageRect, offsetX + (widgetSize.cx - self->imageRect.right)/2, offsetY);
|
||||
offsetY = self->imageRect.bottom;
|
||||
offsetY += WIDGETSTYLE_DLU_TO_VERT_PX(style, INFOWIDGET_IMAGE_OFFSET_BOTTOM_DLU);
|
||||
}
|
||||
|
||||
if (FALSE == IsRectEmpty(&self->textRect))
|
||||
{
|
||||
OffsetRect(&self->textRect, offsetX + (widgetSize.cx - self->textRect.right)/2, offsetY);
|
||||
}
|
||||
|
||||
ReleaseDC(hwnd, windowDC);
|
||||
|
||||
viewSize->cx = widgetSize.cx + offsetRect.left + offsetRect.right;
|
||||
viewSize->cy = widgetSize.cy + offsetRect.top + offsetRect.bottom;
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
InfoWidget_PaintCb(InfoWidget *self, HWND hwnd, WidgetStyle *style, HDC hdc, const RECT *paintRect, BOOL erase)
|
||||
{
|
||||
RECT intersectRect;
|
||||
FillRegion fillRegion;
|
||||
|
||||
FillRegion_Init(&fillRegion, paintRect);
|
||||
|
||||
if (FALSE == IS_STRING_EMPTY(self->title) &&
|
||||
FALSE != IntersectRect(&intersectRect, &self->titleRect, paintRect))
|
||||
{
|
||||
if (FALSE != BackBuffer_DrawTextEx(&self->backBuffer, hdc, self->title, -1, &self->titleRect,
|
||||
DT_CENTER | DT_NOPREFIX | DT_WORDBREAK,
|
||||
style->titleFont, style->backColor, style->titleColor, OPAQUE))
|
||||
{
|
||||
FillRegion_ExcludeRect(&fillRegion, &intersectRect);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != self->image &&
|
||||
FALSE != IntersectRect(&intersectRect, &self->imageRect, paintRect))
|
||||
{
|
||||
HDC windowDC = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL != windowDC)
|
||||
{
|
||||
HDC sourceDC = CreateCompatibleDC(windowDC);
|
||||
if (NULL != sourceDC)
|
||||
{
|
||||
HBITMAP prevBitmap = SelectBitmap(sourceDC, self->image);
|
||||
if (FALSE != BitBlt(hdc, intersectRect.left, intersectRect.top,
|
||||
RECTWIDTH(intersectRect), RECTHEIGHT(intersectRect),
|
||||
sourceDC,
|
||||
intersectRect.left - self->imageRect.left,
|
||||
intersectRect.top - self->imageRect.top,
|
||||
SRCCOPY))
|
||||
{
|
||||
FillRegion_ExcludeRect(&fillRegion, &intersectRect);
|
||||
}
|
||||
|
||||
SelectBitmap(sourceDC, prevBitmap);
|
||||
DeleteDC(sourceDC);
|
||||
}
|
||||
ReleaseDC(hwnd, windowDC);
|
||||
}
|
||||
}
|
||||
|
||||
if (FALSE == IS_STRING_EMPTY(self->text) &&
|
||||
FALSE != IntersectRect(&intersectRect, &self->textRect, paintRect))
|
||||
{
|
||||
if (FALSE != BackBuffer_DrawTextEx(&self->backBuffer, hdc, self->text, -1, &self->textRect,
|
||||
DT_CENTER | DT_NOPREFIX | DT_WORDBREAK,
|
||||
style->textFont, style->backColor, style->textColor, OPAQUE))
|
||||
{
|
||||
FillRegion_ExcludeRect(&fillRegion, &intersectRect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (FALSE != erase)
|
||||
FillRegion_BrushFill(&fillRegion, hdc, style->backBrush);
|
||||
|
||||
FillRegion_Uninit(&fillRegion);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
InfoWidget_StyleColorChangedCb(InfoWidget *self, HWND hwnd, WidgetStyle *style)
|
||||
{
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
if (NULL != self->image)
|
||||
{
|
||||
if (NULL != self->image)
|
||||
DeleteObject(self->image);
|
||||
|
||||
self->image = NULL;
|
||||
InfoWidget_GetImage(self, style);
|
||||
}
|
||||
}
|
||||
|
||||
HWND InfoWidget_CreateWindow(unsigned int type, const wchar_t *title, const wchar_t *text,
|
||||
const wchar_t *imagePath, HWND parentWindow,
|
||||
int x, int y, int width, int height, BOOL border, unsigned int controlId)
|
||||
{
|
||||
const static WidgetInterface infoWidgetInterface =
|
||||
{
|
||||
(WidgetInitCallback)InfoWidget_InitCb,
|
||||
(WidgetDestroyCallback)InfoWidget_DestroyCb,
|
||||
(WidgetLayoutCallback)InfoWidget_LayoutCb,
|
||||
(WidgetPaintCallback)InfoWidget_PaintCb,
|
||||
(WidgetStyleCallback)InfoWidget_StyleColorChangedCb,
|
||||
};
|
||||
|
||||
InfoWidgetParam param;
|
||||
|
||||
param.title = title;
|
||||
param.text = text;
|
||||
param.imagePath = imagePath;
|
||||
|
||||
return Widget_CreateWindow(type,
|
||||
&infoWidgetInterface,
|
||||
NULL,
|
||||
(FALSE != border) ? WS_EX_CLIENTEDGE : 0,
|
||||
0,
|
||||
x, y, width, height,
|
||||
parentWindow,
|
||||
controlId, ¶m);
|
||||
}
|
27
Src/Plugins/Library/ml_devices/infoWidget.h
Normal file
27
Src/Plugins/Library/ml_devices/infoWidget.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_INFO_WIDGET_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_INFO_WIDGET_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
#define WIDGET_TYPE_UNKNOWN 0
|
||||
#define WIDGET_TYPE_WELCOME 1
|
||||
#define WIDGET_TYPE_SERVICE_ERROR 2
|
||||
#define WIDGET_TYPE_VIEW_ERROR 3
|
||||
|
||||
HWND InfoWidget_CreateWindow(unsigned int type,
|
||||
const wchar_t *title,
|
||||
const wchar_t *text,
|
||||
const wchar_t *imagePath,
|
||||
HWND parentWindow,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
BOOL border,
|
||||
unsigned int controlId);
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_INFO_WIDGET_HEADER
|
4096
Src/Plugins/Library/ml_devices/listWidget.cpp
Normal file
4096
Src/Plugins/Library/ml_devices/listWidget.cpp
Normal file
File diff suppressed because it is too large
Load diff
23
Src/Plugins/Library/ml_devices/listWidget.h
Normal file
23
Src/Plugins/Library/ml_devices/listWidget.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_LIST_WIDGET_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_LIST_WIDGET_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
#define WIDGET_TYPE_LIST 3
|
||||
|
||||
HWND
|
||||
ListWidget_CreateWindow(HWND parentWindow,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
BOOL border,
|
||||
unsigned int controlId);
|
||||
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_LIST_WIDGET_HEADER
|
202
Src/Plugins/Library/ml_devices/listWidgetCategory.cpp
Normal file
202
Src/Plugins/Library/ml_devices/listWidgetCategory.cpp
Normal file
|
@ -0,0 +1,202 @@
|
|||
#include "main.h"
|
||||
#include "./listWidgetInternal.h"
|
||||
#include <algorithm>
|
||||
|
||||
#define LISTWIDGETCATEGORY_OFFSET_LEFT_DLU 3
|
||||
#define LISTWIDGETCATEGORY_OFFSET_TOP_DLU 0
|
||||
#define LISTWIDGETCATEGORY_OFFSET_RIGHT_DLU 4
|
||||
#define LISTWIDGETCATEGORY_OFFSET_BOTTOM_DLU 0
|
||||
#define LISTWIDGETCATEGORY_LINE_OFFSET_TOP_DLU 0
|
||||
#define LISTWIDGETCATEGORY_LINE_HEIGHT_DLU 1
|
||||
#define LISTWIDGETCATEGORY_TITLE_OFFSET_LEFT_DLU 4
|
||||
#define LISTWIDGETCATEGORY_MIN_HEIGHT_DLU 9
|
||||
#define LISTWIDGETCATEGORY_ARROW_WIDTH_PX 8
|
||||
#define LISTWIDGETCATEGORY_ARROW_HEIGHT_PX 8
|
||||
|
||||
|
||||
ListWidgetCategory *
|
||||
ListWidget_CreateCategory(const char *name, const wchar_t *title, BOOL collapsed)
|
||||
{
|
||||
ListWidgetCategory *category;
|
||||
|
||||
if (NULL == name)
|
||||
return NULL;
|
||||
|
||||
category = new ListWidgetCategory();
|
||||
if(NULL == category)
|
||||
return NULL;
|
||||
|
||||
category->name = AnsiString_Duplicate(name);
|
||||
category->title = String_Duplicate(title);
|
||||
category->collapsed = collapsed;
|
||||
category->countString = NULL;
|
||||
category->countWidth = -1;
|
||||
category->titleWidth = -1;
|
||||
category->emptyText = NULL;
|
||||
SetRect(&category->emptyTextRect, -1, -1, -1, -1);
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_DestroyCategory(ListWidgetCategory *category)
|
||||
{
|
||||
size_t index;
|
||||
if (NULL == category)
|
||||
return;
|
||||
|
||||
index = category->groups.size();
|
||||
while(index--)
|
||||
{
|
||||
ListWidget_DestroyGroup(category->groups[index]);
|
||||
}
|
||||
|
||||
AnsiString_Free(category->name);
|
||||
String_Free(category->title);
|
||||
String_Free(category->countString);
|
||||
String_Free(category->emptyText);
|
||||
|
||||
delete category;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_GetCategoryMetrics(WidgetStyle *style, ListWidgetCategoryMetric *metrics)
|
||||
{
|
||||
long test;
|
||||
|
||||
if (NULL == metrics || NULL == style)
|
||||
return FALSE;
|
||||
|
||||
WIDGETSTYLE_DLU_TO_HORZ_PX_MIN(metrics->offsetLeft, style, LISTWIDGETCATEGORY_OFFSET_LEFT_DLU, 1);
|
||||
WIDGETSTYLE_DLU_TO_VERT_PX_MIN(metrics->offsetTop, style, LISTWIDGETCATEGORY_OFFSET_TOP_DLU, 1);
|
||||
WIDGETSTYLE_DLU_TO_HORZ_PX_MIN(metrics->offsetRight, style, LISTWIDGETCATEGORY_OFFSET_RIGHT_DLU, 1);
|
||||
WIDGETSTYLE_DLU_TO_VERT_PX_MIN(metrics->offsetBottom, style, LISTWIDGETCATEGORY_OFFSET_BOTTOM_DLU, 1);
|
||||
|
||||
WIDGETSTYLE_DLU_TO_HORZ_PX_MIN(metrics->titleOffsetLeft, style, LISTWIDGETCATEGORY_TITLE_OFFSET_LEFT_DLU, 2);
|
||||
|
||||
WIDGETSTYLE_DLU_TO_VERT_PX_MIN(metrics->lineOffsetTop, style, LISTWIDGETCATEGORY_LINE_OFFSET_TOP_DLU, 1);
|
||||
WIDGETSTYLE_DLU_TO_VERT_PX_MIN(metrics->minHeight, style, LISTWIDGETCATEGORY_MIN_HEIGHT_DLU, 1);
|
||||
|
||||
#if (0 != LISTWIDGETCATEGORY_LINE_HEIGHT_DLU)
|
||||
{
|
||||
metrics->lineHeight = WIDGETSTYLE_DLU_TO_VERT_PX(style, LISTWIDGETCATEGORY_LINE_HEIGHT_DLU);
|
||||
metrics->lineHeight = metrics->lineHeight /2;
|
||||
if (0 == metrics->lineHeight)
|
||||
metrics->lineHeight = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
metrics->iconWidth = LISTWIDGETCATEGORY_ARROW_WIDTH_PX;
|
||||
metrics->iconHeight = LISTWIDGETCATEGORY_ARROW_HEIGHT_PX;
|
||||
|
||||
test = metrics->iconHeight +
|
||||
metrics->offsetTop + metrics->offsetBottom +
|
||||
metrics->lineHeight + metrics->lineOffsetTop;
|
||||
|
||||
if (metrics->minHeight < test)
|
||||
metrics->minHeight = test;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ListWidgetCategory *
|
||||
ListWidget_FindCategory(ListWidget *self, const char *name)
|
||||
{
|
||||
if (NULL == self || NULL == name)
|
||||
return NULL;
|
||||
|
||||
for (size_t iCategory = 0; iCategory < self->categories.size(); iCategory++)
|
||||
{
|
||||
ListWidgetCategory *category = self->categories[iCategory];
|
||||
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, name, -1, category->name, -1))
|
||||
return category;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ListWidgetCategory *
|
||||
ListWidget_GetCategoryFromPoint(ListWidget *self, POINT point)
|
||||
{
|
||||
size_t iCategory;
|
||||
ListWidgetCategory *category;
|
||||
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
for (iCategory = 0; iCategory < self->categories.size(); iCategory++)
|
||||
{
|
||||
category = self->categories[iCategory];
|
||||
if (FALSE != PtInRect(&category->rect, point))
|
||||
return category;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_ToggleCategory(ListWidgetCategory *category, HWND hwnd)
|
||||
{
|
||||
if (NULL == category)
|
||||
return FALSE;
|
||||
|
||||
category->collapsed = !category->collapsed;
|
||||
|
||||
if (NULL != hwnd)
|
||||
ListWidget_UpdateLayout(hwnd, ListWidgetLayout_UpdateNow);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_ResetCategoryCounter(ListWidgetCategory *category)
|
||||
{
|
||||
if (NULL != category)
|
||||
{
|
||||
String_Free(category->countString);
|
||||
category->countString = NULL;
|
||||
category->countWidth = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ListWidget_GroupSortCb(const void *element1, const void *element2)
|
||||
{
|
||||
ListWidgetGroup *group1;
|
||||
ListWidgetGroup *group2;
|
||||
int result;
|
||||
|
||||
group1 = *(ListWidgetGroup**)element1;
|
||||
group2 = *(ListWidgetGroup**)element2;
|
||||
|
||||
result = CompareString(LOCALE_USER_DEFAULT, 0, group1->title, -1, group2->title, -1);
|
||||
if (CSTR_EQUAL == result || 0 == result)
|
||||
result = CompareStringA(CSTR_INVARIANT, 0, group1->name, -1, group2->name, -1);
|
||||
|
||||
return (result == CSTR_LESS_THAN);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ListWidget_SortCategory(ListWidgetCategory *category)
|
||||
{
|
||||
if (category->groups.size())
|
||||
{
|
||||
//qsort(category->groups.first(), category->groups.size(), sizeof(ListWidgetGroup**), ListWidget_GroupSortCb);
|
||||
std::sort(category->groups.begin(), category->groups.end(), ListWidget_GroupSortCb);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_SetCategoryEmptyText(ListWidgetCategory *category, const wchar_t *text)
|
||||
{
|
||||
if (NULL == category)
|
||||
return FALSE;
|
||||
|
||||
String_Free(category->emptyText);
|
||||
category->emptyText = String_Duplicate(text);
|
||||
|
||||
SetRect(&category->emptyTextRect, -1, -1, -1, -1);
|
||||
|
||||
return TRUE;
|
||||
}
|
392
Src/Plugins/Library/ml_devices/listWidgetCommand.cpp
Normal file
392
Src/Plugins/Library/ml_devices/listWidgetCommand.cpp
Normal file
|
@ -0,0 +1,392 @@
|
|||
#include "main.h"
|
||||
#include "./listWidgetInternal.h"
|
||||
|
||||
#define REQUEST_STRING ((wchar_t*)1)
|
||||
#define REQUEST_IMAGE ((DeviceImage*)1)
|
||||
|
||||
typedef struct ListWidgetCommand
|
||||
{
|
||||
char *name;
|
||||
ListWidgetCommandState state;
|
||||
wchar_t *title;
|
||||
wchar_t *description;
|
||||
DeviceImage *imageLarge;
|
||||
DeviceImage *imageSmall;
|
||||
RECT rect;
|
||||
} ListWidgetCommand;
|
||||
|
||||
ListWidgetCommand *
|
||||
ListWidget_CreateCommand(const char *name, BOOL primary, BOOL disabled)
|
||||
{
|
||||
ListWidgetCommand *self;
|
||||
|
||||
if (NULL == name)
|
||||
return NULL;
|
||||
|
||||
self = (ListWidgetCommand*)malloc(sizeof(ListWidgetCommand));
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
ZeroMemory(self, sizeof(ListWidgetCommand));
|
||||
|
||||
self->name = AnsiString_Duplicate(name);
|
||||
self->state = ListWidgetCommandState_Normal;
|
||||
|
||||
if (NULL != self->name)
|
||||
{
|
||||
if (FALSE != primary)
|
||||
self->state |= ListWidgetCommandState_Primary;
|
||||
|
||||
if (FALSE != disabled)
|
||||
self->state |= ListWidgetCommandState_Disabled;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ListWidget_DestroyCommand(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->title = REQUEST_STRING;
|
||||
self->description = REQUEST_STRING;
|
||||
self->imageLarge = REQUEST_IMAGE;
|
||||
self->imageSmall = REQUEST_IMAGE;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_DestroyCommand(ListWidgetCommand *command)
|
||||
{
|
||||
if (NULL == command)
|
||||
return;
|
||||
|
||||
AnsiString_Free(command->name);
|
||||
|
||||
if (NULL != command->imageLarge && REQUEST_IMAGE != command->imageLarge)
|
||||
DeviceImage_Release(command->imageLarge);
|
||||
|
||||
if (NULL != command->imageSmall && REQUEST_IMAGE != command->imageSmall)
|
||||
DeviceImage_Release(command->imageSmall);
|
||||
|
||||
if (REQUEST_STRING != command->title)
|
||||
String_Free(command->title);
|
||||
|
||||
if (REQUEST_STRING != command->description)
|
||||
String_Free(command->description);
|
||||
|
||||
free(command);
|
||||
}
|
||||
|
||||
size_t
|
||||
ListWigdet_GetDeviceCommands(ListWidgetCommand **buffer, size_t bufferMax, ifc_device *device)
|
||||
{
|
||||
size_t count;
|
||||
ifc_devicesupportedcommandenum *enumerator;
|
||||
ifc_devicesupportedcommand *command;
|
||||
DeviceCommandFlags flags;
|
||||
ListWidgetCommand *widgetCommand;
|
||||
BOOL primaryFound;
|
||||
|
||||
if (NULL == buffer || bufferMax < 1 || NULL == device)
|
||||
return 0;
|
||||
|
||||
if (FAILED(device->EnumerateCommands(&enumerator, DeviceCommandContext_View)))
|
||||
return 0;
|
||||
|
||||
count = 0;
|
||||
primaryFound = FALSE;
|
||||
|
||||
while(S_OK == enumerator->Next(&command, 1, NULL))
|
||||
{
|
||||
if(FAILED(command->GetFlags(&flags)))
|
||||
flags = DeviceCommandFlag_None;
|
||||
|
||||
if (0 == (DeviceCommandFlag_Hidden & flags))
|
||||
{
|
||||
widgetCommand = ListWidget_CreateCommand(command->GetName(),
|
||||
(0 != (DeviceCommandFlag_Primary & flags)),
|
||||
(0 != (DeviceCommandFlag_Disabled & flags)));
|
||||
if (NULL != widgetCommand)
|
||||
{
|
||||
if (0 != (DeviceCommandFlag_Primary & flags))
|
||||
{
|
||||
if (count == bufferMax)
|
||||
{
|
||||
ListWidget_DestroyCommand(buffer[count-1]);
|
||||
count--;
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
MoveMemory(&buffer[1], buffer, sizeof(ListWidgetCommand*) * count);
|
||||
|
||||
buffer[0] = widgetCommand;
|
||||
primaryFound = TRUE;
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count < bufferMax)
|
||||
{
|
||||
buffer[count] = widgetCommand;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
command->Release();
|
||||
|
||||
if (count == bufferMax && FALSE != primaryFound)
|
||||
break;
|
||||
}
|
||||
|
||||
enumerator->Release();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_DestroyAllCommands(ListWidgetCommand **buffer, size_t bufferMax)
|
||||
{
|
||||
if (NULL == buffer)
|
||||
return;
|
||||
|
||||
while(bufferMax--)
|
||||
ListWidget_DestroyCommand(buffer[bufferMax]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
ListWidget_GetCommandName(ListWidgetCommand *command)
|
||||
{
|
||||
return (NULL != command) ? command->name : NULL;
|
||||
}
|
||||
|
||||
const wchar_t *
|
||||
ListWidget_GetCommandTitle(ListWidgetCommand *command)
|
||||
{
|
||||
if (NULL == command || NULL == command->title)
|
||||
return NULL;
|
||||
|
||||
if (REQUEST_STRING == command->title)
|
||||
{
|
||||
ifc_devicecommand *info;
|
||||
|
||||
command->title = NULL;
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
S_OK == WASABI_API_DEVICES->CommandFind(command->name, &info))
|
||||
{
|
||||
wchar_t buffer[512] = {0};
|
||||
|
||||
if (SUCCEEDED(info->GetDisplayName(buffer, ARRAYSIZE(buffer))))
|
||||
command->title = String_Duplicate(buffer);
|
||||
|
||||
info->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return command->title;
|
||||
}
|
||||
|
||||
const wchar_t *
|
||||
ListWidget_GetCommandDescription(ListWidgetCommand *command)
|
||||
{
|
||||
if (NULL == command || NULL == command->description)
|
||||
return NULL;
|
||||
|
||||
if (REQUEST_STRING == command->description)
|
||||
{
|
||||
ifc_devicecommand *info;
|
||||
|
||||
command->description = NULL;
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
S_OK == WASABI_API_DEVICES->CommandFind(command->name, &info))
|
||||
{
|
||||
wchar_t buffer[1024] = {0};
|
||||
|
||||
if (SUCCEEDED(info->GetDescription(buffer, ARRAYSIZE(buffer))))
|
||||
command->description = String_Duplicate(buffer);
|
||||
|
||||
info->Release();
|
||||
}
|
||||
}
|
||||
return command->description;
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
ListWidget_GetCommandLargeBitmap(WidgetStyle *style, ListWidgetCommand *command, int width, int height)
|
||||
{
|
||||
if (NULL == style || NULL == command || NULL == command->imageLarge)
|
||||
return NULL;
|
||||
|
||||
if (REQUEST_IMAGE == command->imageLarge)
|
||||
{
|
||||
ifc_devicecommand *info;
|
||||
|
||||
command->imageLarge = NULL;
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
S_OK == WASABI_API_DEVICES->CommandFind(command->name, &info))
|
||||
{
|
||||
wchar_t buffer[MAX_PATH * 2] = {0};
|
||||
|
||||
if (FAILED(info->GetIcon(buffer, ARRAYSIZE(buffer), width, height)))
|
||||
buffer[0] = L'\0';
|
||||
|
||||
info->Release();
|
||||
|
||||
if (L'\0' != buffer[0])
|
||||
{
|
||||
command->imageLarge = DeviceImageCache_GetImage(Plugin_GetImageCache(), buffer,
|
||||
width, height, NULL, NULL);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DeviceImage_GetBitmap(command->imageLarge, DeviceImage_Normal);
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
ListWidget_GetCommandSmallBitmap(WidgetStyle *style, ListWidgetCommand *command, int width, int height)
|
||||
{
|
||||
if (NULL == style || NULL == command || NULL == command->imageSmall)
|
||||
return NULL;
|
||||
|
||||
if (REQUEST_IMAGE == command->imageSmall)
|
||||
{
|
||||
ifc_devicecommand *info;
|
||||
|
||||
command->imageSmall = NULL;
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
S_OK == WASABI_API_DEVICES->CommandFind(command->name, &info))
|
||||
{
|
||||
wchar_t buffer[MAX_PATH * 2] = {0};
|
||||
|
||||
if (FAILED(info->GetIcon(buffer, ARRAYSIZE(buffer), width, height)))
|
||||
buffer[0] = L'\0';
|
||||
|
||||
info->Release();
|
||||
|
||||
if (L'\0' != buffer[0])
|
||||
{
|
||||
command->imageSmall = DeviceImageCache_GetImage(Plugin_GetImageCache(), buffer,
|
||||
width, height, NULL, NULL);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DeviceImage_GetBitmap(command->imageSmall, DeviceImage_Normal);
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_ResetCommandImages(ListWidgetCommand *command)
|
||||
{
|
||||
if (NULL == command)
|
||||
return FALSE;
|
||||
|
||||
if (REQUEST_IMAGE != command->imageLarge)
|
||||
{
|
||||
if (NULL != command->imageLarge)
|
||||
DeviceImage_Release(command->imageLarge);
|
||||
command->imageLarge = REQUEST_IMAGE;
|
||||
}
|
||||
|
||||
if (REQUEST_IMAGE != command->imageSmall)
|
||||
{
|
||||
if (NULL != command->imageSmall)
|
||||
DeviceImage_Release(command->imageSmall);
|
||||
command->imageSmall = REQUEST_IMAGE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_GetCommandRect(ListWidgetCommand *command, RECT *rect)
|
||||
{
|
||||
if (NULL == command || NULL == rect)
|
||||
return FALSE;
|
||||
|
||||
return CopyRect(rect, &command->rect);
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_SetCommandRect(ListWidgetCommand *command, const RECT *rect)
|
||||
{
|
||||
if (NULL == command || NULL == rect)
|
||||
return FALSE;
|
||||
|
||||
return CopyRect(&command->rect, rect);
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_GetCommandRectEqual(ListWidgetCommand *command, const RECT *rect)
|
||||
{
|
||||
if (NULL == command || NULL == rect)
|
||||
return FALSE;
|
||||
|
||||
return EqualRect(&command->rect, rect);
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_GetCommandPrimary(ListWidgetCommand *command)
|
||||
{
|
||||
return (NULL == command ||
|
||||
(0 != (ListWidgetCommandState_Primary & command->state)));
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
ListWidget_GetCommandDisabled(ListWidgetCommand *command)
|
||||
{
|
||||
return (NULL == command ||
|
||||
(0 != (ListWidgetCommandState_Disabled & command->state)));
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
ListWidget_GetCommandPressed(ListWidgetCommand *command)
|
||||
{
|
||||
return (NULL == command ||
|
||||
(0 != (ListWidgetCommandState_Pressed & command->state)));
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_EnableCommand(ListWidgetCommand *command, BOOL enable)
|
||||
{
|
||||
if (NULL == command)
|
||||
return FALSE;
|
||||
|
||||
if ((FALSE == enable) == (0 != (ListWidgetCommandState_Disabled & command->state)))
|
||||
return FALSE;
|
||||
|
||||
if (FALSE == enable)
|
||||
command->state |= ListWidgetCommandState_Disabled;
|
||||
else
|
||||
command->state &= ~ListWidgetCommandState_Disabled;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_SetCommandPressed(ListWidgetCommand *command, BOOL pressed)
|
||||
{
|
||||
if (NULL == command)
|
||||
return FALSE;
|
||||
|
||||
if ((FALSE == pressed) == (0 == (ListWidgetCommandState_Pressed & command->state)))
|
||||
return FALSE;
|
||||
|
||||
if (FALSE == pressed)
|
||||
command->state &= ~ListWidgetCommandState_Pressed;
|
||||
else
|
||||
command->state |= ListWidgetCommandState_Pressed;
|
||||
|
||||
return TRUE;
|
||||
}
|
262
Src/Plugins/Library/ml_devices/listWidgetConnection.cpp
Normal file
262
Src/Plugins/Library/ml_devices/listWidgetConnection.cpp
Normal file
|
@ -0,0 +1,262 @@
|
|||
#include "main.h"
|
||||
#include "./listWidgetInternal.h"
|
||||
|
||||
#define LISTWIDGETCONNECTION_IMAGE_WIDTH 16
|
||||
#define LISTWIDGETCONNECTION_IMAGE_HEIGHT 16
|
||||
|
||||
#define REQUEST_STRING ((wchar_t*)1)
|
||||
#define REQUEST_IMAGE ((DeviceImage*)1)
|
||||
|
||||
|
||||
typedef struct ListWidgetConnection
|
||||
{
|
||||
char *name;
|
||||
wchar_t *title;
|
||||
DeviceImage *image;
|
||||
} ListWidgetConnection;
|
||||
|
||||
|
||||
ListWidgetConnection *
|
||||
ListWidget_CreateConnection(const char *name)
|
||||
{
|
||||
ListWidgetConnection *self;
|
||||
|
||||
if (NULL == name)
|
||||
return NULL;
|
||||
|
||||
self = (ListWidgetConnection*)malloc(sizeof(ListWidgetConnection));
|
||||
if (NULL == self)
|
||||
return NULL;
|
||||
|
||||
ZeroMemory(self, sizeof(ListWidgetConnection));
|
||||
|
||||
self->name = AnsiString_Duplicate(name);
|
||||
|
||||
if (NULL == self->name)
|
||||
{
|
||||
ListWidget_DestroyConnection(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->title = REQUEST_STRING;
|
||||
self->image = REQUEST_IMAGE;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_DestroyConnection(ListWidgetConnection *connection)
|
||||
{
|
||||
if (NULL == connection)
|
||||
return;
|
||||
|
||||
AnsiString_Free(connection->name);
|
||||
|
||||
if (NULL != connection->image && REQUEST_IMAGE != connection->image)
|
||||
DeviceImage_Release(connection->image);
|
||||
|
||||
if (REQUEST_STRING != connection->title)
|
||||
String_Free(connection->title);
|
||||
|
||||
free(connection);
|
||||
}
|
||||
|
||||
const wchar_t *
|
||||
ListWidget_GetConnectionTitle(ListWidgetConnection *connection)
|
||||
{
|
||||
if (NULL == connection || NULL == connection->title)
|
||||
return NULL;
|
||||
|
||||
if (REQUEST_STRING == connection->title)
|
||||
{
|
||||
ifc_deviceconnection *info;
|
||||
|
||||
connection->title = NULL;
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
S_OK == WASABI_API_DEVICES->ConnectionFind(connection->name, &info))
|
||||
{
|
||||
wchar_t buffer[512] = {0};
|
||||
|
||||
if (SUCCEEDED(info->GetDisplayName(buffer, ARRAYSIZE(buffer))))
|
||||
connection->title = String_Duplicate(buffer);
|
||||
|
||||
info->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return connection->title;
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
ListWidget_GetConnectionImage(WidgetStyle *style, ListWidgetConnection *connection, int width, int height)
|
||||
{
|
||||
if (NULL == style || NULL == connection || NULL == connection->image)
|
||||
return NULL;
|
||||
|
||||
if (REQUEST_IMAGE == connection->image)
|
||||
{
|
||||
ifc_deviceconnection *info;
|
||||
|
||||
connection->image = NULL;
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
S_OK == WASABI_API_DEVICES->ConnectionFind(connection->name, &info))
|
||||
{
|
||||
wchar_t buffer[MAX_PATH * 2] = {0};
|
||||
|
||||
if (FAILED(info->GetIcon(buffer, ARRAYSIZE(buffer), width, height)))
|
||||
buffer[0] = L'\0';
|
||||
|
||||
info->Release();
|
||||
|
||||
if (L'\0' != buffer[0])
|
||||
{
|
||||
connection->image = DeviceImageCache_GetImage(Plugin_GetImageCache(), buffer,
|
||||
width, height, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == connection->image)
|
||||
return NULL;
|
||||
|
||||
return DeviceImage_GetBitmap(connection->image, DeviceImage_Normal);
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_ConnectionResetColors(WidgetStyle *style, ListWidgetConnection *connection)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_ResetConnnectionsColors(ListWidget *self, WidgetStyle *style)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
ListWidget_UpdateConnectionImageSize(ListWidgetConnection *connection, int width, int height)
|
||||
{
|
||||
if (NULL == connection)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == connection->image || REQUEST_IMAGE == connection->image)
|
||||
return TRUE;
|
||||
|
||||
DeviceImage_Release(connection->image);
|
||||
connection->image = REQUEST_IMAGE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ListWidgetConnection *
|
||||
ListWidget_FindConnection(ListWidget *self, const char *name)
|
||||
{
|
||||
if (NULL == self || FALSE != IS_STRING_EMPTY(name))
|
||||
return NULL;
|
||||
|
||||
size_t index = self->connections.size();
|
||||
while(index--)
|
||||
{
|
||||
ListWidgetConnection *connection = self->connections[index];
|
||||
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, name, -1, connection->name, -1))
|
||||
return connection;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_AddConnection(ListWidget *self, ListWidgetConnection *connection)
|
||||
{
|
||||
if (NULL == self || NULL == connection)
|
||||
return FALSE;
|
||||
|
||||
self->connections.push_back(connection);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_RemoveConnection(ListWidget *self, const char *name)
|
||||
{
|
||||
size_t iCategory, iGroup, iItem;
|
||||
ListWidgetCategory *category;
|
||||
ListWidgetGroup *group;
|
||||
ListWidgetItem *item;
|
||||
|
||||
|
||||
if (NULL == self || FALSE != IS_STRING_EMPTY(name))
|
||||
return;
|
||||
|
||||
size_t index = self->connections.size();
|
||||
while(index--)
|
||||
{
|
||||
ListWidgetConnection *connection = self->connections[index];
|
||||
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, name, -1, connection->name, -1))
|
||||
{
|
||||
for (iCategory = 0; iCategory < self->categories.size(); iCategory++)
|
||||
{
|
||||
category = self->categories[iCategory];
|
||||
for(iGroup = 0; iGroup < category->groups.size(); iGroup++)
|
||||
{
|
||||
group = category->groups[iGroup];
|
||||
for(iItem = 0; iItem < group->items.size(); iItem++)
|
||||
{
|
||||
item = group->items[iItem];
|
||||
if(item->connection == connection)
|
||||
item->connection = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->connections.erase(self->connections.begin() + index);
|
||||
ListWidget_DestroyConnection(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_RemoveAllConnections(ListWidget *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
size_t index = self->connections.size();
|
||||
if (index > 0)
|
||||
{
|
||||
size_t iCategory, iGroup, iItem;
|
||||
ListWidgetCategory *category;
|
||||
ListWidgetGroup *group;
|
||||
ListWidgetItem *item;
|
||||
|
||||
for (iCategory = 0; iCategory < self->categories.size(); iCategory++)
|
||||
{
|
||||
category = self->categories[iCategory];
|
||||
for(iGroup = 0; iGroup < category->groups.size(); iGroup++)
|
||||
{
|
||||
group = category->groups[iGroup];
|
||||
for(iItem = 0; iItem < group->items.size(); iItem++)
|
||||
{
|
||||
item = group->items[iItem];
|
||||
if(NULL != item->connection)
|
||||
{
|
||||
item->connection = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(index--)
|
||||
{
|
||||
ListWidgetConnection *connection = self->connections[index];
|
||||
ListWidget_DestroyConnection(connection);
|
||||
}
|
||||
|
||||
self->connections.clear();
|
||||
}
|
||||
|
||||
|
||||
}
|
135
Src/Plugins/Library/ml_devices/listWidgetGroup.cpp
Normal file
135
Src/Plugins/Library/ml_devices/listWidgetGroup.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
#include "main.h"
|
||||
#include "./listWidgetInternal.h"
|
||||
#include <algorithm>
|
||||
|
||||
ListWidgetGroup *
|
||||
ListWidget_CreateGroup(const char *name)
|
||||
{
|
||||
ifc_devicetype *deviceType;
|
||||
wchar_t buffer[1024] = {0};
|
||||
|
||||
if (NULL == name)
|
||||
return NULL;
|
||||
|
||||
if (NULL != WASABI_API_DEVICES &&
|
||||
S_OK == WASABI_API_DEVICES->TypeFind(name, &deviceType))
|
||||
{
|
||||
if (FAILED(deviceType->GetDisplayName(buffer, ARRAYSIZE(buffer))))
|
||||
buffer[0] = L'\0';
|
||||
|
||||
deviceType->Release();
|
||||
}
|
||||
else
|
||||
buffer[0] = L'\0';
|
||||
|
||||
return ListWidget_CreateGroupEx(name, buffer);
|
||||
}
|
||||
|
||||
ListWidgetGroup *
|
||||
ListWidget_CreateGroupEx(const char *name, const wchar_t *title)
|
||||
{
|
||||
ListWidgetGroup *group;
|
||||
|
||||
if (NULL == name)
|
||||
return NULL;
|
||||
|
||||
group = new ListWidgetGroup();
|
||||
if (NULL == group)
|
||||
return NULL;
|
||||
|
||||
group->name = AnsiString_Duplicate(name);
|
||||
group->title = String_Duplicate(title);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ListWidget_DestroyGroup(ListWidgetGroup *group)
|
||||
{
|
||||
size_t index;
|
||||
if (NULL == group)
|
||||
return;
|
||||
|
||||
index = group->items.size();
|
||||
while(index--)
|
||||
{
|
||||
ListWidget_DestroyItem(group->items[index]);
|
||||
}
|
||||
|
||||
AnsiString_Free(group->name);
|
||||
String_Free(group->title);
|
||||
|
||||
delete group;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_AddGroup( ListWidgetCategory *category, ListWidgetGroup *group)
|
||||
{
|
||||
if (NULL == category || NULL == group)
|
||||
return FALSE;
|
||||
|
||||
category->groups.push_back(group);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ListWidgetGroup *
|
||||
ListWidget_FindGroupEx(ListWidgetCategory *category, const char *name, size_t max)
|
||||
{
|
||||
size_t index, count;
|
||||
|
||||
if (NULL == category || NULL == name)
|
||||
return NULL;
|
||||
|
||||
count = category->groups.size();
|
||||
if (max < count)
|
||||
count = max;
|
||||
|
||||
for(index = 0; index < count; index++)
|
||||
{
|
||||
ListWidgetGroup *group = category->groups[index];
|
||||
if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, name, -1, group->name, -1))
|
||||
return group;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ListWidgetGroup *
|
||||
ListWidget_FindGroup(ListWidgetCategory *category, const char *name)
|
||||
{
|
||||
return ListWidget_FindGroupEx(category, name, -1);
|
||||
}
|
||||
|
||||
static int
|
||||
ListWidget_ItemSortCb(const void *element1, const void *element2)
|
||||
{
|
||||
ListWidgetItem *item1;
|
||||
ListWidgetItem *item2;
|
||||
int result;
|
||||
|
||||
item1 = (ListWidgetItem*)element1;
|
||||
item2 = (ListWidgetItem*)element2;
|
||||
|
||||
result = CompareString(LOCALE_USER_DEFAULT, 0, item1->title, -1, item2->title, -1);
|
||||
if (CSTR_EQUAL == result || 0 == result)
|
||||
result = CompareStringA(CSTR_INVARIANT, 0, item1->name, -1, item2->name, -1);
|
||||
|
||||
return (result - 2);
|
||||
|
||||
}
|
||||
static bool
|
||||
ListWidget_ItemSortCb_V2(const void* element1, const void* element2)
|
||||
{
|
||||
return ListWidget_ItemSortCb(element1, element2) < 0;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_SortGroup(ListWidgetGroup *group)
|
||||
{
|
||||
if (group->items.size())
|
||||
{
|
||||
//qsort(group->items.first(), group->items.size(), sizeof(ListWidgetItem**), ListWidget_ItemSortCb);
|
||||
std::sort(group->items.begin(), group->items.end(), ListWidget_ItemSortCb_V2);
|
||||
}
|
||||
}
|
1020
Src/Plugins/Library/ml_devices/listWidgetInternal.h
Normal file
1020
Src/Plugins/Library/ml_devices/listWidgetInternal.h
Normal file
File diff suppressed because it is too large
Load diff
2854
Src/Plugins/Library/ml_devices/listWidgetItem.cpp
Normal file
2854
Src/Plugins/Library/ml_devices/listWidgetItem.cpp
Normal file
File diff suppressed because it is too large
Load diff
725
Src/Plugins/Library/ml_devices/listWidgetPaint.cpp
Normal file
725
Src/Plugins/Library/ml_devices/listWidgetPaint.cpp
Normal file
|
@ -0,0 +1,725 @@
|
|||
#include "main.h"
|
||||
#include "./listWidgetInternal.h"
|
||||
|
||||
#include <strsafe.h>
|
||||
|
||||
static BOOL
|
||||
ListWidgetPaintSpacebar_Initialize(ListWidgetPaintSpacebar *self, ListWidget *widget,
|
||||
WidgetStyle *style, HWND hwnd, long width, long height)
|
||||
{
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
self->bitmap = ListWidget_GetSpacebarBitmap(widget, style, hwnd, width, height);
|
||||
if (NULL == self->bitmap)
|
||||
{
|
||||
self->width = 0;
|
||||
self->height = 0;
|
||||
self->emptyBarOffset = 0;
|
||||
self->filledBarOffset = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
self->emptyBarOffset = 0;
|
||||
self->filledBarOffset = height;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ListWidgetPaintSpacebar_Uninitialize(ListWidgetPaintSpacebar *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
ListWidgetPaintArrow_Initialize(ListWidgetPaintArrow *self, ListWidget *widget,
|
||||
WidgetStyle *style, HWND hwnd)
|
||||
{
|
||||
BITMAP bitmapInfo;
|
||||
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
self->bitmap = ListWidget_GetArrowsBitmap(widget, style, hwnd);
|
||||
if (NULL == self->bitmap ||
|
||||
sizeof(bitmapInfo) != GetObject(self->bitmap, sizeof(bitmapInfo), &bitmapInfo))
|
||||
{
|
||||
ZeroMemory(self, sizeof(ListWidgetPaintArrow));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->width = bitmapInfo.bmWidth;
|
||||
self->height = bitmapInfo.bmHeight/2;
|
||||
if (self->height < 0)
|
||||
self->height = -self->height;
|
||||
|
||||
self->collapsedOffset = 0;
|
||||
self->expandedOffset = self->height;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ListWidgetPaintArrow_Uninitialize(ListWidgetPaintArrow *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidgetPaint_Initialize(ListWidgetPaint *self, ListWidget *widget, WidgetStyle *style,
|
||||
HWND hwnd, HDC hdc, const RECT *paintRect, BOOL erase)
|
||||
{
|
||||
HDC windowDC;
|
||||
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
if (NULL == widget || NULL == style)
|
||||
return FALSE;
|
||||
|
||||
self->widget = widget;
|
||||
self->style = style;
|
||||
self->hwnd = hwnd;
|
||||
self->hdc = hdc;
|
||||
self->erase = erase;
|
||||
self->paintRect = paintRect;
|
||||
|
||||
windowDC = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL != windowDC)
|
||||
{
|
||||
self->sourceDC = CreateCompatibleDC(windowDC);
|
||||
ReleaseDC(hwnd, windowDC);
|
||||
}
|
||||
|
||||
if (NULL == self->sourceDC)
|
||||
return FALSE;
|
||||
|
||||
if (FALSE == ListWidget_GetItemMetrics(style, &self->itemMetrics))
|
||||
return FALSE;
|
||||
|
||||
if (FALSE == ListWidget_GetCategoryMetrics(style, &self->categoryMetrics))
|
||||
return FALSE;
|
||||
|
||||
if (FALSE == ListWidgetPaintSpacebar_Initialize(&self->spacebar, widget, style, hwnd,
|
||||
widget->itemWidth - (self->itemMetrics.offsetLeft + self->itemMetrics.offsetRight),
|
||||
self->itemMetrics.spacebarHeight))
|
||||
{
|
||||
// ListWidgetPaint_Uninitialize(self);
|
||||
// return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (FALSE == ListWidgetPaintArrow_Initialize(&self->arrow, widget, style, hwnd))
|
||||
{
|
||||
// ListWidgetPaint_Uninitialize(self);
|
||||
// return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidgetPaint_Uninitialize(ListWidgetPaint *self)
|
||||
{
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
if (NULL != self->sourceDC)
|
||||
DeleteDC(self->sourceDC);
|
||||
|
||||
ListWidgetPaintSpacebar_Uninitialize(&self->spacebar);
|
||||
ListWidgetPaintArrow_Uninitialize(&self->arrow);
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
ListWidgetPaint_DrawSpacebar(ListWidgetPaint *self, HDC hdc, int x, int y,
|
||||
uint64_t totalSpace, uint64_t usedSpace)
|
||||
{
|
||||
RECT *partRect, sourceRect;
|
||||
BOOL succeeded;
|
||||
long usedWidth;
|
||||
ListWidgetPaintSpacebar *spacebar;
|
||||
|
||||
if (NULL == self)
|
||||
return FALSE;
|
||||
|
||||
partRect = &self->partRect;
|
||||
spacebar = &self->spacebar;
|
||||
if (NULL == spacebar->bitmap)
|
||||
return FALSE;
|
||||
|
||||
succeeded = TRUE;
|
||||
|
||||
if (usedSpace > totalSpace)
|
||||
usedSpace = totalSpace;
|
||||
|
||||
if (0 == totalSpace)
|
||||
usedWidth = 0;
|
||||
else
|
||||
usedWidth = (long)(spacebar->width * (double)usedSpace/totalSpace);
|
||||
|
||||
|
||||
SetRect(partRect, x, y, x + spacebar->width, y + spacebar->height);
|
||||
SetRect(&sourceRect, 0, 0, spacebar->width, spacebar->height);
|
||||
OffsetRect(&sourceRect, 0, spacebar->emptyBarOffset);
|
||||
|
||||
if (FALSE == Image_AlphaBlend(hdc, partRect, self->sourceDC, &sourceRect, 255,
|
||||
spacebar->bitmap, self->paintRect, AlphaBlend_Normal, NULL))
|
||||
{
|
||||
succeeded = FALSE;
|
||||
}
|
||||
|
||||
if (0 != usedWidth)
|
||||
{
|
||||
SetRect(partRect, x, y, x + usedWidth, y + spacebar->height);
|
||||
SetRect(&sourceRect, 0, 0, usedWidth, spacebar->height);
|
||||
OffsetRect(&sourceRect, 0, spacebar->filledBarOffset);
|
||||
|
||||
if (FALSE == Image_AlphaBlend(hdc, partRect, self->sourceDC, &sourceRect, 255,
|
||||
spacebar->bitmap, self->paintRect, AlphaBlend_Normal, NULL))
|
||||
{
|
||||
succeeded = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidgetPaint_DrawItemAction(ListWidgetPaint *self, HDC hdc, ListWidgetItem *item, ListWidgetActivity *activity)
|
||||
{
|
||||
HDC sourceDC;
|
||||
WidgetStyle *style;
|
||||
ListWidget *widget;
|
||||
ListWidgetItemMetric *metrics;
|
||||
RECT *partRect, sourceRect;
|
||||
HBITMAP bitmap, prevSourceBitmap;
|
||||
COLORREF prevTextColor;
|
||||
HFONT prevFont;
|
||||
int stringLength;
|
||||
|
||||
if (NULL == activity ||
|
||||
FALSE == ListWidget_GetItemActivityRect(self->widget, item, &self->itemMetrics, &self->partRect) ||
|
||||
FALSE == IntersectRect(&sourceRect, &self->partRect, self->paintRect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
style = self->style;
|
||||
widget = self->widget;
|
||||
metrics = &self->itemMetrics;
|
||||
sourceDC = self->sourceDC;
|
||||
partRect = &self->partRect;
|
||||
prevSourceBitmap = GetCurrentBitmap(sourceDC);
|
||||
prevTextColor = GetTextColor(hdc);
|
||||
prevFont = GetCurrentFont(hdc);
|
||||
|
||||
if (NULL != widget->activityFont)
|
||||
SelectFont(hdc, widget->activityFont);
|
||||
|
||||
bitmap = ListWidget_GetActivityBadgeBitmap(widget, style, self->hwnd,
|
||||
RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
|
||||
if (NULL != bitmap)
|
||||
{
|
||||
Image_AlphaBlend(hdc, partRect, sourceDC, NULL, 255, bitmap, self->paintRect,
|
||||
AlphaBlend_Normal, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (FALSE == IS_STRING_EMPTY(activity->title) &&
|
||||
FALSE != ListWidget_GetItemActivityTitleRect(widget, hdc, item, metrics, partRect) &&
|
||||
FALSE != IntersectRect(&sourceRect, partRect, self->paintRect))
|
||||
{
|
||||
stringLength = lstrlen(activity->title);
|
||||
|
||||
OffsetRect(partRect, 0, 1);
|
||||
SetTextColor(hdc, 0x000000);
|
||||
DrawText(hdc, activity->title, stringLength, partRect,
|
||||
DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_EDITCONTROL | DT_WORD_ELLIPSIS);
|
||||
|
||||
OffsetRect(partRect, 0, -1);
|
||||
SetTextColor(hdc, 0xFFFFFF);
|
||||
DrawText(hdc, activity->title, stringLength, partRect,
|
||||
DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_EDITCONTROL | DT_WORD_ELLIPSIS);
|
||||
|
||||
}
|
||||
|
||||
if (FALSE != ListWidget_GetItemActivityProgressRect(widget, hdc, item, metrics, partRect) &&
|
||||
FALSE != IntersectRect(&sourceRect, partRect, self->paintRect))
|
||||
{
|
||||
bitmap = ListWidget_GetActivityProgressBitmap(widget, style);
|
||||
if (NULL != bitmap)
|
||||
{
|
||||
SetRect(&sourceRect, 0, 0,
|
||||
widget->activityMetrics.progressWidth, widget->activityMetrics.progressHeight);
|
||||
OffsetRect(&sourceRect, 0, widget->activityMetrics.progressHeight * activity->step);
|
||||
|
||||
Image_AlphaBlend(hdc, partRect, sourceDC, &sourceRect, 255, bitmap, self->paintRect,
|
||||
AlphaBlend_Normal, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if ((unsigned int)-1 != activity->percent &&
|
||||
FALSE != ListWidget_GetItemActivityPercentRect(widget, hdc, item, metrics, partRect) &&
|
||||
FALSE != IntersectRect(&sourceRect, partRect, self->paintRect))
|
||||
{
|
||||
wchar_t buffer[6] = {0};
|
||||
|
||||
if (FAILED(StringCchPrintf(buffer, ARRAYSIZE(buffer), L"%d%%", activity->percent)))
|
||||
stringLength = 0;
|
||||
else
|
||||
stringLength = lstrlen(buffer);
|
||||
|
||||
OffsetRect(partRect, 0, 1);
|
||||
SetTextColor(hdc, 0x000000);
|
||||
DrawText(hdc, buffer, stringLength, partRect,
|
||||
DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE);
|
||||
|
||||
OffsetRect(partRect, 0, -1);
|
||||
SetTextColor(hdc, 0xFFFFFF);
|
||||
DrawText(hdc, buffer, stringLength, partRect,
|
||||
DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE);
|
||||
}
|
||||
|
||||
SetTextColor(hdc, prevTextColor);
|
||||
SelectFont(hdc, prevFont);
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidgetPaint_DrawItem(ListWidgetPaint *self, ListWidgetItem *item)
|
||||
{
|
||||
RECT frameRect;
|
||||
long frameHeight, frameWidth;
|
||||
HDC hdc, sourceDC, bufferDC, targetDC;
|
||||
WidgetStyle *style;
|
||||
ListWidget *widget;
|
||||
ListWidgetItemMetric *metrics;
|
||||
RECT *partRect, paintRect;
|
||||
HBITMAP bitmap, prevSourceBitmap;
|
||||
|
||||
if (NULL == self || NULL == item)
|
||||
return FALSE;
|
||||
|
||||
hdc = self->hdc;
|
||||
style = self->style;
|
||||
widget = self->widget;
|
||||
metrics = &self->itemMetrics;
|
||||
sourceDC = self->sourceDC;
|
||||
partRect = &self->partRect;
|
||||
prevSourceBitmap = GetCurrentBitmap(sourceDC);
|
||||
|
||||
|
||||
|
||||
if (FALSE == ListWidget_GetItemFrameRect(widget, item, metrics, &frameRect))
|
||||
return FALSE;
|
||||
|
||||
frameWidth = RECTWIDTH(frameRect);
|
||||
frameHeight = RECTHEIGHT(frameRect);
|
||||
|
||||
if (FALSE == IntersectRect(&paintRect, &item->rect, self->paintRect))
|
||||
return TRUE;
|
||||
|
||||
CopyRect(partRect, &paintRect);
|
||||
|
||||
if (FALSE != BackBuffer_EnsureSizeEx(&widget->backBuffer,
|
||||
RECTWIDTH(paintRect), RECTHEIGHT(paintRect),
|
||||
RECTWIDTH(item->rect), RECTHEIGHT(item->rect)))
|
||||
{
|
||||
|
||||
bufferDC = BackBuffer_GetDC(&widget->backBuffer);
|
||||
if (NULL != bufferDC)
|
||||
{
|
||||
SetViewportOrgEx(bufferDC, -paintRect.left, -paintRect.top, NULL);
|
||||
SetTextColor(bufferDC, GetTextColor(hdc));
|
||||
SetBkColor(bufferDC, GetBkColor(hdc));
|
||||
SetBkMode(bufferDC, GetBkMode(hdc));
|
||||
SelectFont(bufferDC, GetCurrentFont(hdc));
|
||||
|
||||
targetDC = hdc;
|
||||
hdc = bufferDC;
|
||||
}
|
||||
}
|
||||
else
|
||||
bufferDC = NULL;
|
||||
|
||||
|
||||
if (FALSE != self->erase)
|
||||
{
|
||||
FillRect(hdc, partRect, style->backBrush);
|
||||
}
|
||||
|
||||
|
||||
if (FALSE != ListWidgetItem_IsHovered(item))
|
||||
{
|
||||
bitmap = ListWidget_GetHoverBitmap(widget, style, self->hwnd,
|
||||
frameWidth, frameHeight);
|
||||
|
||||
Image_AlphaBlend(hdc, &frameRect, sourceDC, NULL, 255, bitmap, &paintRect,
|
||||
AlphaBlend_Normal, NULL);
|
||||
}
|
||||
|
||||
if (FALSE != ListWidgetItem_IsSelected(item))
|
||||
{
|
||||
bitmap = (GetFocus() == self->hwnd) ?
|
||||
ListWidget_GetSelectBitmap(widget, style, self->hwnd, frameWidth, frameHeight) :
|
||||
ListWidget_GetInactiveSelectBitmap(widget, style, self->hwnd, frameWidth, frameHeight);
|
||||
|
||||
Image_AlphaBlend(hdc, &frameRect, sourceDC, NULL, 255, bitmap, &paintRect,
|
||||
AlphaBlend_Normal, NULL);
|
||||
}
|
||||
|
||||
|
||||
bitmap = ListWidget_GetItemImage(widget, style, item);
|
||||
if (NULL != bitmap)
|
||||
{
|
||||
partRect->left = frameRect.left + metrics->offsetLeft + metrics->imageOffsetLeft;
|
||||
partRect->top = frameRect.top + metrics->offsetTop + metrics->imageOffsetTop;
|
||||
partRect->right = frameRect.right - (metrics->offsetRight + metrics->imageOffsetRight);
|
||||
partRect->bottom = frameRect.bottom - metrics->imageOffsetBottom;
|
||||
|
||||
Image_AlphaBlend(hdc, partRect, sourceDC, NULL, 255, bitmap, &paintRect,
|
||||
AlphaBlend_ScaleSource | AlphaBlend_AlignBottom, NULL);
|
||||
}
|
||||
|
||||
bitmap = ListWidget_GetConnectionImage(style, item->connection,
|
||||
widget->connectionSize.cx, widget->connectionSize.cy);
|
||||
if (NULL != bitmap &&
|
||||
FALSE != ListWidget_GetItemConnectionRect(widget, item, metrics, partRect))
|
||||
{
|
||||
|
||||
Image_AlphaBlend(hdc, partRect, sourceDC, NULL, 255, bitmap, &paintRect,
|
||||
AlphaBlend_AlignCenter | AlphaBlend_AlignBottom, NULL);
|
||||
}
|
||||
|
||||
ListWidgetPaint_DrawItemAction(self, hdc, item, item->activity);
|
||||
|
||||
if (FALSE != ListWidgetItem_IsInteractive(item) && 0 != widget->commandsCount)
|
||||
{
|
||||
|
||||
HBITMAP commandBitmap;
|
||||
size_t index;
|
||||
RECT commandPaintRect;
|
||||
|
||||
bitmap = NULL;
|
||||
for(index = 0; index < widget->commandsCount; index++)
|
||||
{
|
||||
long offset;
|
||||
BYTE sourceAlpha;
|
||||
ListWidget_GetCommandRect(widget->commands[index], partRect);
|
||||
OffsetRect(partRect, frameRect.left, frameRect.top);
|
||||
|
||||
if (FALSE == IntersectRect(&commandPaintRect, partRect, &paintRect))
|
||||
continue;
|
||||
|
||||
if (FALSE != ListWidget_GetCommandPressed(widget->commands[index]))
|
||||
sourceAlpha = 200;
|
||||
else if (FALSE != ListWidget_GetCommandDisabled(widget->commands[index]))
|
||||
sourceAlpha = 32;
|
||||
else
|
||||
sourceAlpha = 255;
|
||||
|
||||
if (NULL == item->activity &&
|
||||
FALSE != ListWidget_GetCommandPrimary(widget->commands[index]))
|
||||
{
|
||||
bitmap = ListWidget_GetLargeBadgeBitmap(widget, style, self->hwnd,
|
||||
RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
|
||||
|
||||
Image_AlphaBlend(hdc, partRect, sourceDC, NULL, 255, bitmap, &commandPaintRect,
|
||||
AlphaBlend_AlignCenter, NULL);
|
||||
|
||||
bitmap = NULL;
|
||||
|
||||
offset = widget->primaryCommandSize.cy/6;
|
||||
if (offset < 3)
|
||||
offset = 3;
|
||||
|
||||
InflateRect(partRect, -offset, -offset);
|
||||
commandBitmap = ListWidget_GetCommandLargeBitmap(style, widget->commands[index],
|
||||
RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
|
||||
if (NULL == commandBitmap)
|
||||
commandBitmap = ListWidget_GetUnknownCommandLargeBitmap(widget, style,
|
||||
RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NULL == bitmap)
|
||||
{
|
||||
bitmap = ListWidget_GetSmallBadgeBitmap(widget, style, self->hwnd,
|
||||
RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
|
||||
}
|
||||
|
||||
Image_AlphaBlend(hdc, partRect, sourceDC, NULL, 255, bitmap, &commandPaintRect,
|
||||
AlphaBlend_AlignCenter, NULL);
|
||||
|
||||
offset = widget->secondaryCommandSize.cy/6;
|
||||
if (offset < 3)
|
||||
offset = 3;
|
||||
|
||||
InflateRect(partRect, -offset, -offset);
|
||||
commandBitmap = ListWidget_GetCommandSmallBitmap(style, widget->commands[index],
|
||||
RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
|
||||
|
||||
if (NULL == commandBitmap)
|
||||
commandBitmap = ListWidget_GetUnknownCommandSmallBitmap(widget, style,
|
||||
RECTWIDTH(*partRect), RECTHEIGHT(*partRect));
|
||||
}
|
||||
|
||||
if (NULL != commandBitmap)
|
||||
{
|
||||
Image_AlphaBlend(hdc, partRect, sourceDC, NULL, sourceAlpha, commandBitmap, &commandPaintRect,
|
||||
AlphaBlend_Normal, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (FALSE != ListWidget_GetItemSpacebarRect(widget, item, metrics, partRect))
|
||||
{
|
||||
ListWidgetPaint_DrawSpacebar(self, hdc,
|
||||
partRect->left,
|
||||
partRect->top,
|
||||
item->spaceTotal, item->spaceUsed);
|
||||
}
|
||||
|
||||
|
||||
if (FALSE == ListWidgetItem_IsTextEdited(item) &&
|
||||
FALSE == IS_STRING_EMPTY(item->title) &&
|
||||
FALSE != ListWidget_GetItemTitleRect(widget, item, metrics, TRUE, partRect))
|
||||
{
|
||||
DrawText(hdc, item->title, -1, partRect,
|
||||
DT_CENTER | DT_NOPREFIX | DT_WORDBREAK | DT_EDITCONTROL | DT_END_ELLIPSIS);
|
||||
}
|
||||
|
||||
SelectBitmap(sourceDC, prevSourceBitmap);
|
||||
|
||||
if (NULL != bufferDC)
|
||||
{
|
||||
hdc = targetDC;
|
||||
|
||||
SetViewportOrgEx(bufferDC, 0, 0, NULL);
|
||||
|
||||
BackBuffer_Copy(&widget->backBuffer, hdc,
|
||||
paintRect.left, paintRect.top, RECTWIDTH(paintRect), RECTHEIGHT(paintRect));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidgetPaint_DrawCategory(ListWidgetPaint *self, ListWidgetCategory *category)
|
||||
{
|
||||
HDC hdc;
|
||||
RECT elementRect, *partRect;
|
||||
WidgetStyle *style;
|
||||
ListWidgetCategoryMetric *metrics;
|
||||
|
||||
if (NULL == self || NULL == category)
|
||||
return FALSE;
|
||||
|
||||
hdc = self->hdc;
|
||||
style = self->style;
|
||||
partRect = &self->partRect;
|
||||
metrics = &self->categoryMetrics;
|
||||
|
||||
if (FALSE == IntersectRect(partRect, &category->rect, self->paintRect))
|
||||
return TRUE;
|
||||
|
||||
CopyRect(partRect, &category->rect);
|
||||
partRect->right -= metrics->offsetRight;
|
||||
if (FALSE != IntersectRect(partRect, partRect, self->paintRect))
|
||||
FillRect(hdc, partRect, WIDGETSTYLE_CATEGORY_BRUSH(style));
|
||||
|
||||
partRect->left = category->rect.right - metrics->offsetRight;
|
||||
partRect->right = category->rect.right;
|
||||
if (FALSE != IntersectRect(partRect, partRect, self->paintRect))
|
||||
FillRect(hdc, partRect, WIDGETSTYLE_BACK_BRUSH(style));
|
||||
|
||||
if (NULL != self->arrow.bitmap)
|
||||
{
|
||||
long limit;
|
||||
SetRect(&elementRect, 0, 0, self->arrow.width, self->arrow.height);
|
||||
OffsetRect(&elementRect,
|
||||
0,
|
||||
(FALSE == category->collapsed) ?
|
||||
self->arrow.expandedOffset :
|
||||
self->arrow.collapsedOffset);
|
||||
|
||||
|
||||
CopyRect(partRect, &category->rect);
|
||||
partRect->left += metrics->offsetLeft;
|
||||
partRect->right = partRect->left + self->arrow.width;
|
||||
|
||||
limit = (RECTHEIGHT(category->rect) - self->arrow.height - metrics->offsetTop);
|
||||
partRect->top += metrics->offsetTop + limit/2 + limit%2;
|
||||
partRect->bottom = partRect->top + self->arrow.height;
|
||||
|
||||
limit = category->rect.bottom - metrics->offsetBottom - metrics->lineHeight;
|
||||
if (partRect->bottom > limit)
|
||||
OffsetRect(partRect, 0, (limit - partRect->bottom));
|
||||
|
||||
limit = category->rect.top + metrics->offsetTop;
|
||||
if (partRect->top < limit)
|
||||
OffsetRect(partRect, 0, (limit - partRect->top));
|
||||
|
||||
Image_AlphaBlend(hdc, partRect, self->sourceDC, &elementRect,
|
||||
255, self->arrow.bitmap, self->paintRect,
|
||||
AlphaBlend_Normal, NULL);
|
||||
}
|
||||
|
||||
CopyRect(&elementRect, &category->rect);
|
||||
elementRect.left += metrics->offsetLeft + metrics->iconWidth + metrics->titleOffsetLeft;
|
||||
elementRect.top += metrics->offsetTop;
|
||||
elementRect.right -= metrics->offsetRight;
|
||||
elementRect.bottom -= (metrics->offsetBottom + metrics->lineHeight + metrics->lineOffsetTop);
|
||||
|
||||
if (FALSE != IntersectRect(partRect, &elementRect, self->paintRect))
|
||||
{
|
||||
COLORREF prevTextColor = SetTextColor(hdc, WIDGETSTYLE_CATEGORY_TEXT_COLOR(style));
|
||||
HFONT prevFont = SelectFont(hdc, WIDGETSTYLE_CATEGORY_FONT(style));
|
||||
|
||||
if (NULL == category->countString)
|
||||
{
|
||||
size_t count, index;
|
||||
wchar_t buffer[64] = {0};
|
||||
|
||||
count = 0;
|
||||
index = category->groups.size();
|
||||
while(index--)
|
||||
{
|
||||
count += category->groups[index]->items.size();
|
||||
}
|
||||
|
||||
if (SUCCEEDED(StringCchPrintf(buffer, ARRAYSIZE(buffer), L" (%u)", count)))
|
||||
category->countString = String_Duplicate(buffer);
|
||||
}
|
||||
|
||||
if (-1 == category->titleWidth)
|
||||
{
|
||||
category->titleWidth = 0;
|
||||
|
||||
if (FALSE == IS_STRING_EMPTY(category->title))
|
||||
{
|
||||
SetRect(partRect, 0, 0, 0, RECTHEIGHT(elementRect));
|
||||
if (FALSE != DrawText(hdc, category->title, -1, partRect,
|
||||
DT_CALCRECT | DT_LEFT | DT_TOP | DT_NOPREFIX | DT_SINGLELINE))
|
||||
{
|
||||
category->titleWidth = RECTWIDTH(*partRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 == category->countWidth)
|
||||
{
|
||||
category->countWidth = 0;
|
||||
if (FALSE == IS_STRING_EMPTY(category->countString))
|
||||
{
|
||||
SetRect(partRect, 0, 0, 0, RECTHEIGHT(elementRect));
|
||||
if (FALSE != DrawText(hdc, category->countString, -1, partRect,
|
||||
DT_CALCRECT | DT_LEFT | DT_TOP | DT_NOPREFIX | DT_SINGLELINE))
|
||||
{
|
||||
category->countWidth = RECTWIDTH(*partRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != category->titleWidth)
|
||||
{
|
||||
CopyRect(partRect, &elementRect);
|
||||
|
||||
if (partRect->right < (partRect->left + category->titleWidth + category->countWidth))
|
||||
partRect->right = partRect->right - category->countWidth;
|
||||
|
||||
if (partRect->right > partRect->left)
|
||||
{
|
||||
DrawText(hdc, category->title, -1, partRect,
|
||||
DT_LEFT | DT_BOTTOM | DT_NOPREFIX | DT_SINGLELINE | DT_END_ELLIPSIS);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != category->countWidth)
|
||||
{
|
||||
CopyRect(partRect, &elementRect);
|
||||
partRect->left += category->titleWidth;
|
||||
|
||||
if (partRect->left > (partRect->right - category->countWidth))
|
||||
{
|
||||
partRect->left = partRect->right - category->countWidth;
|
||||
if (partRect->left < elementRect.left)
|
||||
partRect->left = elementRect.left;
|
||||
}
|
||||
|
||||
if (partRect->right > partRect->left)
|
||||
{
|
||||
DrawText(hdc, category->countString, -1, partRect,
|
||||
DT_LEFT | DT_BOTTOM | DT_NOPREFIX | DT_SINGLELINE);
|
||||
}
|
||||
}
|
||||
|
||||
SetTextColor(hdc, prevTextColor);
|
||||
SelectFont(hdc, prevFont);
|
||||
}
|
||||
|
||||
if (0 != metrics->lineHeight)
|
||||
{
|
||||
CopyRect(partRect, &category->rect);
|
||||
partRect->right -= metrics->offsetRight;
|
||||
partRect->bottom -= metrics->offsetBottom;
|
||||
partRect->top = partRect->bottom - metrics->lineHeight;
|
||||
|
||||
if (FALSE != IntersectRect(partRect, partRect, self->paintRect))
|
||||
{
|
||||
COLORREF prevBackColor;
|
||||
|
||||
prevBackColor = SetBkColor(hdc, WIDGETSTYLE_CATEGORY_LINE_COLOR(style));
|
||||
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, partRect, NULL, 0, NULL);
|
||||
|
||||
SetBkColor(hdc, prevBackColor);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidgetPaint_DrawEmptyCategoryText(ListWidgetPaint *self, ListWidgetCategory *category)
|
||||
{
|
||||
HDC hdc;
|
||||
WidgetStyle *style;
|
||||
RECT *partRect;
|
||||
BOOL result;
|
||||
COLORREF prevTextColor;
|
||||
|
||||
if (NULL == self || NULL == category)
|
||||
return FALSE;
|
||||
|
||||
hdc = self->hdc;
|
||||
style = self->style;
|
||||
partRect = &self->partRect;
|
||||
|
||||
|
||||
if (FALSE == IntersectRect(partRect, self->paintRect, &category->emptyTextRect))
|
||||
return TRUE;
|
||||
|
||||
if (FALSE != self->erase)
|
||||
{
|
||||
FillRect(hdc, partRect, style->backBrush);
|
||||
}
|
||||
|
||||
if (FALSE != IS_STRING_EMPTY(category->emptyText))
|
||||
return TRUE;
|
||||
|
||||
prevTextColor = SetTextColor(hdc, WIDGETSTYLE_CATEGORY_EMPTY_TEXT_COLOR(style));
|
||||
|
||||
result = DrawText(hdc, category->emptyText, -1, &category->emptyTextRect,
|
||||
DT_CENTER | DT_TOP | DT_NOPREFIX | DT_WORDBREAK | DT_EDITCONTROL);
|
||||
|
||||
SetTextColor(hdc, prevTextColor);
|
||||
return result;
|
||||
}
|
592
Src/Plugins/Library/ml_devices/listWidgetTooltip.cpp
Normal file
592
Src/Plugins/Library/ml_devices/listWidgetTooltip.cpp
Normal file
|
@ -0,0 +1,592 @@
|
|||
#include "main.h"
|
||||
#include "./listWidgetInternal.h"
|
||||
|
||||
#include <strsafe.h>
|
||||
|
||||
#define TOOLTIP_MARGIN_LEFT_DLU 3
|
||||
#define TOOLTIP_MARGIN_TOP_DLU 1
|
||||
#define TOOLTIP_MARGIN_RIGHT_DLU 3
|
||||
#define TOOLTIP_MARGIN_BOTTOM_DLU 1
|
||||
|
||||
#define TOOLTIP_DELAY_INITIAL 1000
|
||||
#define TOOLTIP_DELAY_RESHOW 400
|
||||
|
||||
static ATOM LISTWIDGETTOOLTIP_PROP = 0;
|
||||
|
||||
static LRESULT WINAPI
|
||||
ListWidgetTooltip_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
typedef struct ListWidgetTooltip
|
||||
{
|
||||
HWND window;
|
||||
HWND owner;
|
||||
BOOL active;
|
||||
POINT position;
|
||||
wchar_t *buffer;
|
||||
ListWidgetItem *item;
|
||||
ListWidgetItemPart part;
|
||||
RECT partRect;
|
||||
BOOL blockLocationChange;
|
||||
WNDPROC originalProc;
|
||||
DWORD showTime;
|
||||
} ListWidgetTooltip;
|
||||
|
||||
|
||||
static HWND
|
||||
ListWidget_TooltipCreateWindow(HWND owner, WNDPROC *originalProc, HANDLE windowProperty)
|
||||
{
|
||||
HWND hwnd;
|
||||
TOOLINFO ti;
|
||||
|
||||
hwnd = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_NOPARENTNOTIFY | WS_EX_TRANSPARENT | WS_EX_LAYERED,
|
||||
TOOLTIPS_CLASS, NULL, WS_CLIPSIBLINGS | WS_POPUP | TTS_NOANIMATE | TTS_ALWAYSTIP,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
owner, NULL, NULL, NULL);
|
||||
|
||||
if ( hwnd == NULL )
|
||||
return NULL;
|
||||
|
||||
MLSkinWindow2(Plugin_GetLibraryWindow(), hwnd, SKINNEDWND_TYPE_TOOLTIP,
|
||||
SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS);
|
||||
|
||||
if (NULL != originalProc)
|
||||
{
|
||||
if (0 == LISTWIDGETTOOLTIP_PROP)
|
||||
LISTWIDGETTOOLTIP_PROP = GlobalAddAtom(TEXT("ListWidgetTooltipProp"));
|
||||
|
||||
if (0 != LISTWIDGETTOOLTIP_PROP)
|
||||
{
|
||||
*originalProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hwnd, GWLP_WNDPROC,
|
||||
(LONGX86)(LONG_PTR)ListWidgetTooltip_WindowProc);
|
||||
if (NULL != *originalProc &&
|
||||
FALSE == SetProp(hwnd, MAKEINTATOM(LISTWIDGETTOOLTIP_PROP), windowProperty))
|
||||
{
|
||||
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)*originalProc);
|
||||
*originalProc = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
*originalProc = NULL;
|
||||
}
|
||||
|
||||
SendMessage(hwnd, CCM_SETVERSION, 6, 0L);
|
||||
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
|
||||
|
||||
ZeroMemory(&ti, sizeof(ti));
|
||||
ti.cbSize = sizeof(ti);
|
||||
ti.hwnd = owner;
|
||||
ti.lpszText = LPSTR_TEXTCALLBACK;
|
||||
ti.uFlags = 0/*TTF_TRACK | TTF_ABSOLUTE*/;
|
||||
|
||||
SendMessage(hwnd, TTM_ADDTOOL, 0, (LPARAM)&ti);
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
ListWidgetTooltip*
|
||||
ListWidget_TooltipCreate(HWND hwnd)
|
||||
{
|
||||
ListWidgetTooltip *tooltip;
|
||||
|
||||
tooltip = (ListWidgetTooltip*)malloc(sizeof(ListWidgetTooltip));
|
||||
if (NULL == tooltip)
|
||||
return FALSE;
|
||||
|
||||
ZeroMemory(tooltip, sizeof(ListWidgetTooltip));
|
||||
|
||||
tooltip->window = ListWidget_TooltipCreateWindow(hwnd, &tooltip->originalProc, tooltip);
|
||||
if (NULL == tooltip->window)
|
||||
{
|
||||
ListWidget_TooltipDestroy(tooltip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tooltip->owner = hwnd;
|
||||
ListWidget_TooltipFontChanged(tooltip);
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_TooltipDestroy(ListWidgetTooltip *tooltip)
|
||||
{
|
||||
if (NULL != tooltip)
|
||||
{
|
||||
if (NULL != tooltip->window)
|
||||
DestroyWindow(tooltip->window);
|
||||
|
||||
String_Free(tooltip->buffer);
|
||||
|
||||
free(tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_TooltipFontChanged(ListWidgetTooltip *tooltip)
|
||||
{
|
||||
WidgetStyle *style;
|
||||
RECT marginsRect;
|
||||
HDC hdc;
|
||||
long maxWidth;
|
||||
|
||||
if (NULL == tooltip)
|
||||
return;
|
||||
|
||||
if (NULL == tooltip->window)
|
||||
{
|
||||
// attempt to recover...
|
||||
tooltip->window = ListWidget_TooltipCreateWindow(tooltip->owner, &tooltip->originalProc, tooltip);
|
||||
if (NULL == tooltip->window)
|
||||
return;
|
||||
|
||||
tooltip->active = FALSE;
|
||||
tooltip->part = ListWidgetItemPart_None;
|
||||
SetRectEmpty(&tooltip->partRect);
|
||||
}
|
||||
|
||||
|
||||
style = WIDGET_GET_STYLE(tooltip->owner);
|
||||
if (NULL == style)
|
||||
return;
|
||||
|
||||
hdc = GetDCEx(tooltip->window, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL != hdc)
|
||||
{
|
||||
HFONT font = (HFONT)SendMessage(tooltip->window, WM_GETFONT, 0, 0L);
|
||||
HFONT prevFont = SelectFont(hdc, font);
|
||||
|
||||
maxWidth = Graphics_GetAveStrWidth(hdc, 36);
|
||||
|
||||
SelectFont(hdc, prevFont);
|
||||
ReleaseDC(tooltip->window, hdc);
|
||||
}
|
||||
else
|
||||
maxWidth = 100;
|
||||
|
||||
|
||||
SendMessage(tooltip->window, TTM_SETMAXTIPWIDTH, 0, (LPARAM)maxWidth);
|
||||
|
||||
WIDGETSTYLE_DLU_TO_HORZ_PX_MIN(marginsRect.left, style, TOOLTIP_MARGIN_LEFT_DLU, 3);
|
||||
WIDGETSTYLE_DLU_TO_VERT_PX_MIN(marginsRect.top, style, TOOLTIP_MARGIN_TOP_DLU, 2);
|
||||
WIDGETSTYLE_DLU_TO_HORZ_PX_MIN(marginsRect.right, style, TOOLTIP_MARGIN_RIGHT_DLU, 3);
|
||||
WIDGETSTYLE_DLU_TO_VERT_PX_MIN(marginsRect.bottom, style, TOOLTIP_MARGIN_BOTTOM_DLU, 2);
|
||||
|
||||
SendMessage(tooltip->window, TTM_SETMARGIN, 0, (LPARAM)&marginsRect);
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_TooltipRelayMouseMessage(ListWidgetTooltip *tooltip, unsigned int message, unsigned int vKeys, const POINT *cursor)
|
||||
{
|
||||
if (NULL != tooltip &&
|
||||
NULL != tooltip->window &&
|
||||
FALSE != tooltip->active)
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
msg.hwnd = tooltip->owner;
|
||||
msg.message = message;
|
||||
msg.wParam = (WPARAM)vKeys;
|
||||
msg.lParam = MAKELPARAM(cursor->x, cursor->y);
|
||||
|
||||
SendMessage(tooltip->window, TTM_RELAYEVENT, 0, (LPARAM)&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ListWidget_TooltipHide(ListWidgetTooltip *tooltip)
|
||||
{
|
||||
if (NULL == tooltip ||
|
||||
NULL == tooltip->window ||
|
||||
FALSE == tooltip->active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tooltip->active = FALSE;
|
||||
tooltip->part = ListWidgetItemPart_None;
|
||||
SetRectEmpty(&tooltip->partRect);
|
||||
|
||||
SendMessage(tooltip->window, TTM_ACTIVATE, FALSE, 0);
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_TooltipActivate(ListWidgetTooltip *tooltip, const RECT *rect)
|
||||
{
|
||||
TOOLINFO ti;
|
||||
POINT origin;
|
||||
|
||||
if (NULL == tooltip ||
|
||||
NULL == tooltip->window)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(&ti, sizeof(ti));
|
||||
ti.cbSize = sizeof(ti);
|
||||
ti.hwnd = tooltip->owner;
|
||||
ti.uId = 0;
|
||||
|
||||
|
||||
if (FALSE == SendMessage(tooltip->window, TTM_GETTOOLINFO, 0, (LPARAM)&ti))
|
||||
return FALSE;
|
||||
|
||||
if (FALSE != tooltip->active)
|
||||
{
|
||||
tooltip->active = FALSE;
|
||||
SendMessage(tooltip->window, TTM_ACTIVATE, FALSE, 0);
|
||||
}
|
||||
else
|
||||
SendMessage(tooltip->window, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(TOOLTIP_DELAY_INITIAL, 0));
|
||||
|
||||
|
||||
CopyRect(&ti.rect, rect);
|
||||
if (FALSE != ListWidget_GetViewOrigin(tooltip->owner, &origin))
|
||||
OffsetRect(&ti.rect, origin.x, origin.y);
|
||||
|
||||
ti.lParam = NULL;
|
||||
ti.lpszText = LPSTR_TEXTCALLBACK;
|
||||
|
||||
SendMessage(tooltip->window, TTM_SETTOOLINFO, 0, (LPARAM)&ti);
|
||||
|
||||
|
||||
if (FALSE == tooltip->active)
|
||||
{
|
||||
KillTimer(tooltip->window, 4);
|
||||
SendMessage(tooltip->window, TTM_ACTIVATE, TRUE, 0);
|
||||
tooltip->active = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
ListWidget_TooltipUpdate(ListWidgetTooltip *tooltip, ListWidgetItem *item,
|
||||
ListWidgetItemPart part, const RECT *partRect)
|
||||
{
|
||||
BOOL tooltipValid;
|
||||
|
||||
if (NULL == tooltip)
|
||||
return FALSE;
|
||||
|
||||
if(FALSE == tooltip->active && NULL == item)
|
||||
return FALSE;
|
||||
|
||||
if (0 != (ListWidgetItemPart_Activity & part))
|
||||
{
|
||||
part &= ~ListWidgetItemPart_Activity;
|
||||
part |= ListWidgetItemPart_Frame;
|
||||
}
|
||||
|
||||
tooltipValid = (NULL != item && ListWidgetItemPart_None != part);
|
||||
if (tooltip->item == item &&
|
||||
tooltip->part == part &&
|
||||
(FALSE != (FALSE != tooltipValid) ?
|
||||
EqualRect(&tooltip->partRect, partRect) :
|
||||
IsRectEmpty(&tooltip->partRect)))
|
||||
{
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tooltip->item = item;
|
||||
tooltip->part = part;
|
||||
|
||||
if (FALSE != tooltipValid)
|
||||
CopyRect(&tooltip->partRect, partRect);
|
||||
else
|
||||
SetRectEmpty(&tooltip->partRect);
|
||||
|
||||
if (FALSE == tooltipValid)
|
||||
{
|
||||
ListWidget_TooltipHide(tooltip);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return ListWidget_TooltipActivate(tooltip, &tooltip->partRect);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
ListWidget_TooltipFormatTip(ListWidget *self, HWND hwnd,
|
||||
const RECT *rect, wchar_t *buffer, size_t bufferMax)
|
||||
{
|
||||
WidgetStyle *style;
|
||||
ListWidgetItem *item;
|
||||
ListWidgetItemPart part;
|
||||
ListWidgetItemMetric metrics;
|
||||
RECT partRect;
|
||||
POINT pt, origin;
|
||||
|
||||
if (NULL == self || NULL == rect)
|
||||
return FALSE;
|
||||
|
||||
style = WIDGET_GET_STYLE(hwnd);
|
||||
if (NULL == style)
|
||||
return FALSE;
|
||||
|
||||
if (FALSE == ListWidget_GetItemMetrics(style, &metrics))
|
||||
return FALSE;
|
||||
|
||||
if (FALSE == ListWidget_GetViewOrigin(hwnd, &origin))
|
||||
{
|
||||
origin.x = 0;
|
||||
origin.y = 0;
|
||||
}
|
||||
|
||||
pt.x = (rect->left + (rect->right - rect->left)/2) - origin.x;
|
||||
pt.y = (rect->top + (rect->bottom - rect->top)/2) - origin.y;
|
||||
|
||||
|
||||
item = ListWidget_GetItemFromPoint(self, pt);
|
||||
if (NULL == item)
|
||||
return FALSE;
|
||||
|
||||
|
||||
part = ListWidgetItemPart_Frame |
|
||||
ListWidgetItemPart_Command |
|
||||
ListWidgetItemPart_Spacebar |
|
||||
ListWidgetItemPart_Title;
|
||||
|
||||
part = ListWidget_GetItemPartFromPoint(self, item, &metrics, pt, part, &partRect);
|
||||
switch(part)
|
||||
{
|
||||
case ListWidgetItemPart_Command:
|
||||
CopyRect(&partRect, rect);
|
||||
OffsetRect(&partRect, -origin.x - item->rect.left, -origin.y - item->rect.top);
|
||||
return ListWidget_FormatItemCommandTip(self, item, &partRect, buffer, bufferMax);
|
||||
|
||||
case ListWidgetItemPart_Activity:
|
||||
case ListWidgetItemPart_Frame:
|
||||
return ListWidget_FormatItemTip(self, item, buffer, bufferMax);
|
||||
|
||||
case ListWidgetItemPart_Spacebar:
|
||||
return ListWidget_FormatItemSpaceTip(self, item, buffer, bufferMax);
|
||||
|
||||
case ListWidgetItemPart_Title:
|
||||
return ListWidget_FormatItemTitleTip(self, item, buffer, bufferMax);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
ListWidget_TooltipGetDispInfo(ListWidget *self, ListWidgetTooltip *tooltip, NMTTDISPINFO *dispInfo)
|
||||
{
|
||||
TOOLINFO ti;
|
||||
|
||||
if (NULL == dispInfo)
|
||||
return;
|
||||
|
||||
ZeroMemory(&ti, sizeof(ti));
|
||||
ti.cbSize = sizeof(ti);
|
||||
ti.hwnd = tooltip->owner;
|
||||
ti.uId = dispInfo->hdr.idFrom;
|
||||
|
||||
String_Free(tooltip->buffer);
|
||||
tooltip->buffer = NULL;
|
||||
|
||||
if (FALSE != SendMessage(dispInfo->hdr.hwndFrom, TTM_GETTOOLINFO, 0, (LPARAM)&ti))
|
||||
{
|
||||
wchar_t buffer[4096] = {0};
|
||||
if (FALSE != ListWidget_TooltipFormatTip(self, tooltip->owner, &ti.rect, buffer, ARRAYSIZE(buffer)))
|
||||
tooltip->buffer = String_Duplicate(buffer);
|
||||
}
|
||||
|
||||
dispInfo->lpszText = tooltip->buffer;
|
||||
dispInfo->szText[0] = L'\0';
|
||||
dispInfo->hinst = NULL;
|
||||
dispInfo->uFlags = TTF_DI_SETITEM;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_TooltipProcessNotification(ListWidget *self, ListWidgetTooltip *tooltip, NMHDR *pnmh, LRESULT *result)
|
||||
{
|
||||
if (NULL == tooltip ||
|
||||
NULL == pnmh ||
|
||||
pnmh->hwndFrom != tooltip->window)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch(pnmh->code)
|
||||
{
|
||||
case TTN_GETDISPINFO:
|
||||
ListWidget_TooltipGetDispInfo(self, tooltip, (NMTTDISPINFO*)pnmh);
|
||||
break;
|
||||
|
||||
case TTN_SHOW:
|
||||
if (0 == (WS_VISIBLE & GetWindowStyle(tooltip->window)))
|
||||
tooltip->showTime = GetTickCount();
|
||||
|
||||
if (FALSE != tooltip->active)
|
||||
{
|
||||
SendMessage(tooltip->window, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(TOOLTIP_DELAY_RESHOW, 0));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ListWidgetItem *
|
||||
ListWidget_TooltipGetCurrent(ListWidgetTooltip *tooltip, ListWidgetItemPart *part, RECT *partRect)
|
||||
{
|
||||
if (NULL == tooltip ||
|
||||
FALSE == tooltip->active ||
|
||||
NULL == tooltip->item)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (NULL != part)
|
||||
*part = tooltip->part;
|
||||
|
||||
if (NULL != partRect)
|
||||
CopyRect(partRect, &tooltip->partRect);
|
||||
|
||||
return tooltip->item;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_TooltipGetChanged(ListWidgetTooltip *tooltip, ListWidgetItem *item,
|
||||
ListWidgetItemPart part, const RECT *partRect)
|
||||
{
|
||||
if (NULL == tooltip)
|
||||
return FALSE;
|
||||
|
||||
if (tooltip->item != item)
|
||||
return TRUE;
|
||||
|
||||
if (NULL == item)
|
||||
return FALSE;
|
||||
|
||||
if (tooltip->part != part)
|
||||
return TRUE;
|
||||
|
||||
if (FALSE == EqualRect(&tooltip->partRect, partRect))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ListWidget_TooltipUpdateText(ListWidget *self, ListWidgetTooltip *tooltip, ListWidgetItem *item, TooltipUpdateReason reason)
|
||||
{
|
||||
TOOLINFO ti;
|
||||
ListWidgetItemPart mask;
|
||||
unsigned int windowStyle;
|
||||
unsigned long showTimeout, currentTime;
|
||||
|
||||
if (NULL == self ||
|
||||
NULL == tooltip ||
|
||||
NULL == tooltip->active ||
|
||||
NULL == tooltip->window)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (NULL != item && tooltip->item != item)
|
||||
return FALSE;
|
||||
|
||||
windowStyle = GetWindowStyle(tooltip->window);
|
||||
if (0 == (WS_VISIBLE & windowStyle))
|
||||
return FALSE;
|
||||
|
||||
showTimeout = (unsigned long)SendMessage(tooltip->window, TTM_GETDELAYTIME, (WPARAM)TTDT_AUTOPOP, 0L);
|
||||
currentTime = GetTickCount();
|
||||
if (currentTime < tooltip->showTime)
|
||||
return FALSE;
|
||||
|
||||
currentTime -= tooltip->showTime;
|
||||
if (showTimeout > (currentTime + 10))
|
||||
showTimeout -= currentTime;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
KillTimer(tooltip->window, 4);
|
||||
|
||||
switch(reason)
|
||||
{
|
||||
case Tooltip_DeviceTitleChanged:
|
||||
case Tooltip_DeviceModelChanged:
|
||||
case Tooltip_DeviceStatusChanged:
|
||||
mask = ListWidgetItemPart_Frame |
|
||||
ListWidgetItemPart_Activity |
|
||||
ListWidgetItemPart_Title;
|
||||
|
||||
if (0 == (mask & tooltip->part))
|
||||
return FALSE;
|
||||
|
||||
break;
|
||||
|
||||
case Tooltip_DeviceSpaceChanged:
|
||||
mask = ListWidgetItemPart_Frame |
|
||||
ListWidgetItemPart_Activity |
|
||||
ListWidgetItemPart_Spacebar;
|
||||
|
||||
if (0 == (mask & tooltip->part))
|
||||
return FALSE;
|
||||
|
||||
break;
|
||||
|
||||
/*case Tooltip_DeviceActivityChanged:
|
||||
mask = ListWidgetItemPart_Frame |
|
||||
ListWidgetItemPart_Activity;
|
||||
|
||||
if (0 == (mask & tooltip->part))
|
||||
return FALSE;
|
||||
|
||||
break;*/
|
||||
}
|
||||
|
||||
|
||||
ZeroMemory(&ti, sizeof(ti));
|
||||
ti.cbSize = sizeof(ti);
|
||||
ti.hwnd = tooltip->owner;
|
||||
ti.uId = 0;
|
||||
ti.lpszText = LPSTR_TEXTCALLBACK;
|
||||
|
||||
tooltip->blockLocationChange = TRUE;
|
||||
SendMessage(tooltip->window, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
|
||||
tooltip->blockLocationChange = FALSE;
|
||||
|
||||
SetTimer(tooltip->window, 4, showTimeout, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static LRESULT WINAPI
|
||||
ListWidgetTooltip_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
ListWidgetTooltip *tooltip;
|
||||
|
||||
tooltip = (ListWidgetTooltip*)GetProp(hwnd, MAKEINTATOM(LISTWIDGETTOOLTIP_PROP));
|
||||
if (NULL == tooltip ||
|
||||
NULL == tooltip->originalProc)
|
||||
{
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
RemoveProp(hwnd, MAKEINTATOM(LISTWIDGETTOOLTIP_PROP));
|
||||
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)tooltip->originalProc);
|
||||
CallWindowProc(tooltip->originalProc, hwnd, uMsg, wParam, lParam);
|
||||
tooltip->originalProc = NULL;
|
||||
tooltip->window = NULL;
|
||||
break;
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
if (FALSE != tooltip->blockLocationChange)
|
||||
{
|
||||
WINDOWPOS *pwp;
|
||||
pwp = (WINDOWPOS*)lParam;
|
||||
if (NULL != pwp)
|
||||
{
|
||||
pwp->flags |= SWP_NOMOVE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CallWindowProc(tooltip->originalProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
183
Src/Plugins/Library/ml_devices/local_menu.cpp
Normal file
183
Src/Plugins/Library/ml_devices/local_menu.cpp
Normal file
|
@ -0,0 +1,183 @@
|
|||
#include "main.h"
|
||||
#include "./local_menu.h"
|
||||
|
||||
unsigned int
|
||||
Menu_InsertDeviceItems(HMENU menu, int position, unsigned int baseId,
|
||||
ifc_device *device, DeviceCommandContext context)
|
||||
{
|
||||
unsigned int count, separator;
|
||||
MENUITEMINFO itemInfo = {0};
|
||||
wchar_t itemName[512] = {0};
|
||||
|
||||
ifc_devicecommand *commandInfo;
|
||||
ifc_devicesupportedcommandenum *enumerator;
|
||||
ifc_devicesupportedcommand *command;
|
||||
DeviceCommandFlags commandFlags;
|
||||
|
||||
if (NULL == device || NULL == menu)
|
||||
return 0;
|
||||
|
||||
if (FAILED(device->EnumerateCommands(&enumerator, context)))
|
||||
return 0;
|
||||
|
||||
itemInfo.cbSize = sizeof(itemInfo);
|
||||
itemInfo.fMask = MIIM_DATA | MIIM_ID | MIIM_FTYPE | MIIM_STATE | MIIM_STRING;
|
||||
|
||||
count = 0;
|
||||
separator = 0;
|
||||
|
||||
while(S_OK == enumerator->Next(&command, 1, NULL))
|
||||
{
|
||||
if(SUCCEEDED(command->GetFlags(&commandFlags)))
|
||||
{
|
||||
if (0 != (DeviceCommandFlag_Group & commandFlags) &&
|
||||
separator != count)
|
||||
{
|
||||
itemInfo.fType = MFT_SEPARATOR;
|
||||
itemInfo.fState = MFS_ENABLED;
|
||||
itemInfo.wID = 0xFFFE;
|
||||
itemInfo.dwItemData = NULL;
|
||||
if (0 != InsertMenuItem(menu, position + count, TRUE, &itemInfo))
|
||||
{
|
||||
count++;
|
||||
separator = count;
|
||||
}
|
||||
}
|
||||
if (0 == (DeviceCommandFlag_Hidden & commandFlags))
|
||||
{
|
||||
if (S_OK == WASABI_API_DEVICES->CommandFind(command->GetName(), &commandInfo))
|
||||
{
|
||||
if (SUCCEEDED(commandInfo->GetDisplayName(itemName, ARRAYSIZE(itemName))))
|
||||
{
|
||||
itemInfo.dwItemData = (ULONG_PTR)AnsiString_Duplicate(command->GetName());
|
||||
if (NULL != itemInfo.dwItemData)
|
||||
{
|
||||
itemInfo.fType = MFT_STRING;
|
||||
itemInfo.dwTypeData = itemName;
|
||||
itemInfo.fState = 0;
|
||||
itemInfo.wID = baseId + count;
|
||||
|
||||
if (0 == (DeviceCommandFlag_Disabled & commandFlags))
|
||||
itemInfo.fState |= MFS_ENABLED;
|
||||
else
|
||||
itemInfo.fState |= (MFS_DISABLED | MFS_GRAYED);
|
||||
|
||||
if (0 != (DeviceCommandFlag_Primary & commandFlags))
|
||||
itemInfo.fState |= MFS_DEFAULT;
|
||||
|
||||
if (0 != InsertMenuItem(menu, position + count, TRUE, &itemInfo))
|
||||
count++;
|
||||
else
|
||||
AnsiString_Free((char*)itemInfo.dwItemData);
|
||||
}
|
||||
|
||||
}
|
||||
commandInfo->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
command->Release();
|
||||
}
|
||||
|
||||
|
||||
enumerator->Release();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
Menu_FreeItemData(HMENU menu, unsigned int start, int count)
|
||||
{
|
||||
unsigned int processed;
|
||||
MENUITEMINFO itemInfo;
|
||||
|
||||
if (NULL == menu)
|
||||
return 0;
|
||||
|
||||
if (count < 0 )
|
||||
count = GetMenuItemCount(menu);
|
||||
|
||||
if (start > (unsigned int)count)
|
||||
return 0;
|
||||
|
||||
count -= start;
|
||||
processed = 0;
|
||||
|
||||
itemInfo.cbSize = sizeof(itemInfo);
|
||||
itemInfo.fMask = MIIM_DATA;
|
||||
|
||||
while(count-- &&
|
||||
FALSE != GetMenuItemInfo(menu, start + processed, TRUE, &itemInfo))
|
||||
{
|
||||
AnsiString_Free((char*)itemInfo.dwItemData);
|
||||
processed++;
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
ULONG_PTR
|
||||
Menu_GetItemData(HMENU menu, unsigned int item, BOOL byPosition)
|
||||
{
|
||||
MENUITEMINFO itemInfo;
|
||||
|
||||
if (NULL == menu)
|
||||
return 0;
|
||||
|
||||
itemInfo.cbSize = sizeof(itemInfo);
|
||||
itemInfo.fMask = MIIM_DATA;
|
||||
|
||||
if (FALSE != GetMenuItemInfo(menu, item, byPosition, &itemInfo))
|
||||
return itemInfo.dwItemData;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
Menu_FindItemByData(HMENU menu, Menu_FindItemByDataCb callback, void *user)
|
||||
{
|
||||
int index, count;
|
||||
MENUITEMINFO itemInfo;
|
||||
|
||||
if (NULL == menu || NULL == callback)
|
||||
return -1;
|
||||
|
||||
count = GetMenuItemCount(menu);
|
||||
if (0 == count)
|
||||
return -1;
|
||||
|
||||
itemInfo.cbSize = sizeof(itemInfo);
|
||||
itemInfo.fMask = MIIM_DATA | MIIM_ID;
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
if (FALSE != GetMenuItemInfo(menu, index, TRUE, &itemInfo) &&
|
||||
FALSE != callback(itemInfo.dwItemData, user))
|
||||
{
|
||||
return itemInfo.wID;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
static BOOL
|
||||
Menu_FindItemByAnsiStringDataCb(ULONG_PTR param, void *user)
|
||||
{
|
||||
const char *string1, *string2;
|
||||
|
||||
string1 = (const char*)param;
|
||||
string2 = (const char*)user;
|
||||
|
||||
if (NULL == string1 || NULL == string2)
|
||||
return (string1 == string2);
|
||||
|
||||
return (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, string1, -1, string2, -1));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
Menu_FindItemByAnsiStringData(HMENU menu, const char *string)
|
||||
{
|
||||
return Menu_FindItemByData(menu, Menu_FindItemByAnsiStringDataCb, (void*)string);
|
||||
}
|
48
Src/Plugins/Library/ml_devices/local_menu.h
Normal file
48
Src/Plugins/Library/ml_devices/local_menu.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_MENU_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_MENU_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
int
|
||||
Menu_TrackSkinnedPopup(HMENU menu,
|
||||
unsigned int flags,
|
||||
int x,
|
||||
int y,
|
||||
HWND hwnd,
|
||||
LPTPMPARAMS lptpm);
|
||||
|
||||
unsigned int
|
||||
Menu_InsertDeviceItems(HMENU menu,
|
||||
int position,
|
||||
unsigned int baseId,
|
||||
ifc_device *device,
|
||||
DeviceCommandContext context);
|
||||
|
||||
unsigned int
|
||||
Menu_FreeItemData(HMENU menu,
|
||||
unsigned int start,
|
||||
int count);
|
||||
|
||||
ULONG_PTR
|
||||
Menu_GetItemData(HMENU menu,
|
||||
unsigned int item,
|
||||
BOOL byPosition);
|
||||
|
||||
|
||||
typedef BOOL (*Menu_FindItemByDataCb)(ULONG_PTR param, void *user);
|
||||
|
||||
unsigned int
|
||||
Menu_FindItemByData(HMENU menu,
|
||||
Menu_FindItemByDataCb callback,
|
||||
void *user);
|
||||
|
||||
unsigned int
|
||||
Menu_FindItemByAnsiStringData(HMENU menu,
|
||||
const char *string);
|
||||
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_MENU_HEADER
|
5
Src/Plugins/Library/ml_devices/main.cpp
Normal file
5
Src/Plugins/Library/ml_devices/main.cpp
Normal file
|
@ -0,0 +1,5 @@
|
|||
#include <initguid.h>
|
||||
#include "main.h"
|
||||
#define _ML_HEADER_IMPMLEMENT
|
||||
#include "../../General/gen_ml/ml_ipc_0313.h"
|
||||
#undef _ML_HEADER_IMPMLEMENT
|
50
Src/Plugins/Library/ml_devices/main.h
Normal file
50
Src/Plugins/Library/ml_devices/main.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_MAIN_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_MAIN_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// #define _CRTDBG_MAP_ALLOC
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
#include "./common.h"
|
||||
#include "./strings.h"
|
||||
#include "./plugin.h"
|
||||
#include "./local_menu.h"
|
||||
#include "./graphics.h"
|
||||
#include "./image.h"
|
||||
#include "./imageCache.h"
|
||||
#include "./fillRegion.h"
|
||||
#include "./backBuffer.h"
|
||||
#include "./wasabi.h"
|
||||
#include "./config.h"
|
||||
#include "./navigation.h"
|
||||
#include "./navigationIcons.h"
|
||||
#include "./managerView.h"
|
||||
#include "./statusBar.h"
|
||||
#include "./widgetHost.h"
|
||||
#include "./widgetStyle.h"
|
||||
#include "./widget.h"
|
||||
#include "./infoWidget.h"
|
||||
#include "./welcomeWidget.h"
|
||||
#include "./listWidget.h"
|
||||
#include "./deviceManagerHandler.h"
|
||||
#include "./deviceHandler.h"
|
||||
#include "./eventRelay.h"
|
||||
#include "./deviceCommands.h"
|
||||
#include "./resource.h"
|
||||
#include "./embeddedEditor.h"
|
||||
|
||||
#include "../../General/gen_ml/ml.h"
|
||||
#include "../../General/gen_ml/menu.h"
|
||||
#include "../../General/gen_ml/ml_ipc_0313.h"
|
||||
#include "../winamp/wa_ipc.h"
|
||||
#include "../winamp/wa_dlg.h"
|
||||
#include "../nu/trace.h"
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <math.h>
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_MAIN_HEADER
|
994
Src/Plugins/Library/ml_devices/managerView.cpp
Normal file
994
Src/Plugins/Library/ml_devices/managerView.cpp
Normal file
|
@ -0,0 +1,994 @@
|
|||
#include "main.h"
|
||||
#include "./managerView.h"
|
||||
|
||||
#define MANAGERVIEW_PROP L"NullsoftDevicesManagerViewProp"
|
||||
|
||||
#define VIEW_OFFSET_LEFT_PX 0
|
||||
#define VIEW_OFFSET_TOP_PX 0
|
||||
#define VIEW_OFFSET_RIGHT_PX 2
|
||||
#define VIEW_OFFSET_BOTTOM_PX -1
|
||||
|
||||
#define DISCOVER_BUTTON_MIN_HEIGHT_PX 18
|
||||
#define DISCOVER_BUTTON_MIN_WIDTH_PX 72
|
||||
#define DISCOVER_BUTTON_EXTRA_SPACE_DLU 8
|
||||
#define DISCOVER_BUTTON_SPACING_RIGHT_DLU 6
|
||||
|
||||
#define ZOOM_SLIDER_SPACING_LEFT_DLU 6
|
||||
|
||||
#define BOTTOM_BAR_OFFSET_TOP_DLU 2
|
||||
|
||||
|
||||
#define MANAGERVIEW_WIDGET_ID 10000
|
||||
#define MANAGERVIEW_STATUSBAR_ID 10001
|
||||
|
||||
static ATOM MANAGERVIEW_ATOM = 0;
|
||||
|
||||
|
||||
typedef
|
||||
enum ManagerViewState
|
||||
{
|
||||
MANAGERVIEW_STATE_FROZEN_UI = (1 << 0),
|
||||
} WelcomeViewState;
|
||||
DEFINE_ENUM_FLAG_OPERATORS(ManagerViewState);
|
||||
|
||||
#define MANAGERVIEW_IS_FROZEN(_view) (0 != (MANAGERVIEW_STATE_FROZEN_UI & (_view)->state))
|
||||
#define MANAGERVIEW_FREEZE(_view) (((_view)->state) |= MANAGERVIEW_STATE_FROZEN_UI)
|
||||
#define MANAGERVIEW_THAW(_view) (((_view)->state) &= ~MANAGERVIEW_STATE_FROZEN_UI)
|
||||
|
||||
#define MANAGERVIEW_DLU_TO_HORZ_PX(_view, _dlu) MulDiv((_dlu), (_view)->unitSize.cx, 4)
|
||||
#define MANAGERVIEW_DLU_TO_VERT_PX(_view, _dlu) MulDiv((_dlu), (_view)->unitSize.cy, 8)
|
||||
|
||||
#define MANAGERVIEW_REGISTER_WIDGET(_widgetWindow) (SetWindowLongPtrW((_widgetWindow), GWLP_ID, MANAGERVIEW_WIDGET_ID))
|
||||
#define MANAGERVIEW_WIDGET(_viewWindow) (GetDlgItem((_viewWindow), MANAGERVIEW_WIDGET_ID))
|
||||
#define MANAGERVIEW_STATUS_BAR(_viewWindow) (GetDlgItem((_viewWindow), MANAGERVIEW_STATUSBAR_ID))
|
||||
#define MANAGERVIEW_DISCOVER_BUTTON(_viewWindow) (GetDlgItem((_viewWindow), IDC_BUTTON_DISCOVER))
|
||||
#define MANAGERVIEW_ZOOM_SLIDER(_viewWindow) (GetDlgItem((_viewWindow), IDC_SLIDER_ZOOM))
|
||||
|
||||
typedef struct ManagerView
|
||||
{
|
||||
ManagerViewState state;
|
||||
WidgetStyle widgetStyle;
|
||||
HFONT font;
|
||||
HFONT systemFont;
|
||||
COLORREF backColor;
|
||||
COLORREF textColor;
|
||||
COLORREF borderColor;
|
||||
HBRUSH backBrush;
|
||||
SIZE unitSize;
|
||||
BOOL devicesPresent;
|
||||
size_t deviceHandler;
|
||||
HRGN updateRegion;
|
||||
POINT updateOffset;
|
||||
unsigned int discoveryStatus;
|
||||
} ManagerView;
|
||||
|
||||
#define MANAGERVIEW(_hwnd) ((ManagerView*)GetPropW((_hwnd), MAKEINTATOM(MANAGERVIEW_ATOM)))
|
||||
#define MANAGERVIEW_RET_VOID(_view, _hwnd) { (_view) = MANAGERVIEW((_hwnd)); if (NULL == (_view)) return; }
|
||||
#define MANAGERVIEW_RET_VAL(_view, _hwnd, _error) { (_view) = MANAGERVIEW((_hwnd)); if (NULL == (_view)) return (_error); }
|
||||
|
||||
static INT_PTR CALLBACK
|
||||
ManagerView_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static void CALLBACK
|
||||
ManagerView_PluginUnloadCb()
|
||||
{
|
||||
if (0 != MANAGERVIEW_ATOM)
|
||||
{
|
||||
GlobalDeleteAtom(MANAGERVIEW_ATOM);
|
||||
MANAGERVIEW_ATOM = 0;
|
||||
}
|
||||
}
|
||||
|
||||
HWND ManagerView_CreateWindow(HWND parentWindow)
|
||||
{
|
||||
if (0 == MANAGERVIEW_ATOM)
|
||||
{
|
||||
MANAGERVIEW_ATOM = GlobalAddAtom(MANAGERVIEW_PROP);
|
||||
if (0 == MANAGERVIEW_ATOM)
|
||||
return NULL;
|
||||
|
||||
Plugin_RegisterUnloadCallback(ManagerView_PluginUnloadCb);
|
||||
}
|
||||
|
||||
HWND hwnd = WASABI_API_CREATEDIALOGPARAMW((INT_PTR)IDD_MANAGER_VIEW, parentWindow,
|
||||
ManagerView_DialogProc, (LPARAM)0L);
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_Layout(HWND hwnd, BOOL redraw)
|
||||
{
|
||||
ManagerView *self = NULL;
|
||||
RECT clientRect, elementRect;
|
||||
LONG bottomBarHeight = 0, buttonWidth = 0, sliderWidth = 0;
|
||||
|
||||
MANAGERVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
GetClientRect(hwnd, &clientRect);
|
||||
clientRect.left += VIEW_OFFSET_LEFT_PX;
|
||||
clientRect.top += VIEW_OFFSET_TOP_PX;
|
||||
clientRect.right -= VIEW_OFFSET_RIGHT_PX;
|
||||
clientRect.bottom -= VIEW_OFFSET_BOTTOM_PX;
|
||||
|
||||
HDWP hdwp = BeginDeferWindowPos(4);
|
||||
if (NULL == hdwp)
|
||||
return;
|
||||
|
||||
UINT swpFlags = SWP_NOACTIVATE | SWP_NOZORDER;
|
||||
if (FALSE == redraw)
|
||||
swpFlags |= SWP_NOREDRAW;
|
||||
|
||||
HWND buttonWindow = MANAGERVIEW_DISCOVER_BUTTON(hwnd);
|
||||
if (NULL != buttonWindow)
|
||||
{
|
||||
if (FALSE != GetWindowRect(buttonWindow, &elementRect))
|
||||
{
|
||||
wchar_t buffer[128] = {0};
|
||||
GetWindowText(buttonWindow, buffer, ARRAYSIZE(buffer));
|
||||
LRESULT idealSize = MLSkinnedButton_GetIdealSize(buttonWindow, buffer);
|
||||
|
||||
hdwp = DeferWindowPos(hdwp, buttonWindow, NULL, clientRect.left + 1,
|
||||
clientRect.bottom - WASABI_API_APP->getScaleY(HIWORD(idealSize)) - WASABI_API_APP->getScaleY(1),
|
||||
RECTWIDTH(elementRect), WASABI_API_APP->getScaleY(HIWORD(idealSize)), swpFlags);
|
||||
|
||||
bottomBarHeight = WASABI_API_APP->getScaleY(HIWORD(idealSize));
|
||||
buttonWidth = RECTWIDTH(elementRect);
|
||||
}
|
||||
}
|
||||
|
||||
HWND sliderWindow = MANAGERVIEW_ZOOM_SLIDER(hwnd);
|
||||
if (NULL != sliderWindow)
|
||||
{
|
||||
if (0 != (WS_VISIBLE & GetWindowStyle(sliderWindow)) &&
|
||||
FALSE != GetWindowRect(sliderWindow, &elementRect))
|
||||
{
|
||||
hdwp = DeferWindowPos(hdwp, sliderWindow, NULL, clientRect.right - RECTWIDTH(elementRect),
|
||||
clientRect.bottom - RECTHEIGHT(elementRect),
|
||||
RECTWIDTH(elementRect), RECTHEIGHT(elementRect), swpFlags);
|
||||
sliderWidth = RECTWIDTH(elementRect);
|
||||
}
|
||||
}
|
||||
|
||||
HWND statusBar = MANAGERVIEW_STATUS_BAR(hwnd);
|
||||
if (NULL != statusBar)
|
||||
{
|
||||
long statusBarHeight = 0;
|
||||
CopyRect(&elementRect, &clientRect);
|
||||
|
||||
if (0 != buttonWidth)
|
||||
{
|
||||
elementRect.left += buttonWidth;
|
||||
elementRect.left += MANAGERVIEW_DLU_TO_HORZ_PX(self, DISCOVER_BUTTON_SPACING_RIGHT_DLU);
|
||||
if (elementRect.left > clientRect.right)
|
||||
elementRect.left = clientRect.right;
|
||||
}
|
||||
|
||||
if (0 != sliderWidth)
|
||||
{
|
||||
elementRect.right -= sliderWidth;
|
||||
elementRect.right -= MANAGERVIEW_DLU_TO_HORZ_PX(self, ZOOM_SLIDER_SPACING_LEFT_DLU);
|
||||
if (elementRect.left > elementRect.right)
|
||||
elementRect.right = elementRect.left;
|
||||
}
|
||||
|
||||
statusBarHeight = STATUSBAR_GET_IDEAL_HEIGHT(statusBar);
|
||||
if (statusBarHeight > bottomBarHeight)
|
||||
statusBarHeight = 0;
|
||||
|
||||
elementRect.top = elementRect.bottom - statusBarHeight - WASABI_API_APP->getScaleY(3);
|
||||
elementRect.bottom = elementRect.top + statusBarHeight;
|
||||
|
||||
hdwp = DeferWindowPos(hdwp, statusBar, NULL, elementRect.left, elementRect.top,
|
||||
RECTWIDTH(elementRect), RECTHEIGHT(elementRect), swpFlags);
|
||||
}
|
||||
|
||||
HWND widgetWindow = MANAGERVIEW_WIDGET(hwnd);
|
||||
if (NULL != widgetWindow)
|
||||
{
|
||||
CopyRect(&elementRect, &clientRect);
|
||||
if (0 != bottomBarHeight)
|
||||
{
|
||||
elementRect.bottom -= (bottomBarHeight + WASABI_API_APP->getScaleY(4));
|
||||
}
|
||||
|
||||
Graphics_ClampRect(&elementRect, &clientRect);
|
||||
|
||||
if (NULL != hdwp)
|
||||
{
|
||||
hdwp = DeferWindowPos(hdwp, widgetWindow, NULL, elementRect.left, elementRect.top,
|
||||
RECTWIDTH(elementRect), RECTHEIGHT(elementRect), swpFlags);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != hdwp)
|
||||
EndDeferWindowPos(hdwp);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
ManagerView_Paint(HWND hwnd, HDC hdc, const RECT *paintRect, BOOL erase)
|
||||
{
|
||||
ManagerView *self;
|
||||
MANAGERVIEW_RET_VAL(self, hwnd, FALSE);
|
||||
|
||||
if (FALSE != erase)
|
||||
{
|
||||
HRGN fillRegion;
|
||||
fillRegion = CreateRectRgnIndirect(paintRect);
|
||||
FillRgn(hdc, fillRegion, self->backBrush);
|
||||
DeleteObject(fillRegion);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_UpdateSkin(HWND hwnd)
|
||||
{
|
||||
ManagerView *self;
|
||||
MANAGERVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
BOOL styleChanged = FALSE;
|
||||
COLORREF color = Graphics_GetSkinColor(WADLG_WNDBG);
|
||||
if (color != self->backColor || NULL == self->backBrush)
|
||||
{
|
||||
self->backColor = color;
|
||||
self->backBrush = CreateSolidBrush(self->backColor);
|
||||
styleChanged = TRUE;
|
||||
}
|
||||
|
||||
color = Graphics_GetSkinColor(WADLG_WNDFG);
|
||||
if (self->textColor != color)
|
||||
{
|
||||
self->textColor = color;
|
||||
styleChanged = TRUE;
|
||||
}
|
||||
|
||||
color = Graphics_GetSkinColor(WADLG_HILITE);
|
||||
if (self->borderColor != color)
|
||||
{
|
||||
self->borderColor = color;
|
||||
styleChanged = TRUE;
|
||||
}
|
||||
|
||||
if (FALSE != WidgetStyle_UpdateDefaultColors(&self->widgetStyle))
|
||||
styleChanged = TRUE;
|
||||
|
||||
if (FALSE != styleChanged)
|
||||
{
|
||||
HWND controlWindow = MANAGERVIEW_WIDGET(hwnd);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
WIDGET_STYLE_COLOR_CHANGED(controlWindow);
|
||||
InvalidateRect(controlWindow, NULL, TRUE);
|
||||
}
|
||||
|
||||
controlWindow = MANAGERVIEW_STATUS_BAR(hwnd);
|
||||
if (NULL != controlWindow)
|
||||
{
|
||||
STATUSBAR_SET_TEXT_COLOR(controlWindow, self->textColor, FALSE);
|
||||
STATUSBAR_SET_BACK_COLOR(controlWindow, self->backColor, FALSE);
|
||||
STATUSBAR_SET_BACK_BRUSH(controlWindow, self->backBrush, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL
|
||||
ManagerView_GetIdealButtonSize(HWND buttonWindow, SIZE *buttonSize)
|
||||
{
|
||||
if (NULL == buttonWindow || NULL == buttonSize)
|
||||
return FALSE;
|
||||
|
||||
LRESULT skinSize = MLSkinnedButton_GetIdealSize(buttonWindow, NULL);
|
||||
if (0 != skinSize)
|
||||
{
|
||||
buttonSize->cx = LOWORD(skinSize);
|
||||
buttonSize->cy = HIWORD(skinSize);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
buttonSize->cx = 0;
|
||||
buttonSize->cy = 0;
|
||||
if (FALSE != SendMessageW(buttonWindow, BCM_GETIDEALSIZE, 0, (LPARAM)buttonSize))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
ManagerView_UpdateDiscoverButtonFont(HWND hwnd, HFONT font, SIZE *size)
|
||||
{
|
||||
ManagerView *self;
|
||||
SIZE buttonSize;
|
||||
|
||||
MANAGERVIEW_RET_VAL(self, hwnd, FALSE);
|
||||
|
||||
HWND buttonWindow = MANAGERVIEW_DISCOVER_BUTTON(hwnd);
|
||||
if (NULL == buttonWindow)
|
||||
return FALSE;
|
||||
|
||||
SendMessage(buttonWindow, WM_SETFONT, (WPARAM)font, MAKELPARAM(0,0));
|
||||
|
||||
if (FALSE == ManagerView_GetIdealButtonSize(buttonWindow, &buttonSize))
|
||||
{
|
||||
RECT buttonRect;
|
||||
if (FALSE == GetWindowRect(buttonWindow, &buttonRect))
|
||||
return FALSE;
|
||||
|
||||
buttonSize.cx = RECTWIDTH(buttonRect);
|
||||
buttonSize.cy = RECTHEIGHT(buttonRect);
|
||||
}
|
||||
|
||||
buttonSize.cx += MANAGERVIEW_DLU_TO_HORZ_PX(self, DISCOVER_BUTTON_EXTRA_SPACE_DLU);
|
||||
|
||||
if (buttonSize.cx < DISCOVER_BUTTON_MIN_WIDTH_PX)
|
||||
buttonSize.cx = DISCOVER_BUTTON_MIN_WIDTH_PX;
|
||||
|
||||
if (buttonSize.cy < DISCOVER_BUTTON_MIN_HEIGHT_PX)
|
||||
buttonSize.cy = DISCOVER_BUTTON_MIN_HEIGHT_PX;
|
||||
|
||||
BOOL result = SetWindowPos(buttonWindow, NULL, 0, 0, buttonSize.cx, buttonSize.cy,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
|
||||
if (FALSE == result)
|
||||
return FALSE;
|
||||
|
||||
if (NULL != size)
|
||||
*size = buttonSize;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_UpdateFont(HWND hwnd, BOOL redraw)
|
||||
{
|
||||
HWND controlWindow = NULL;
|
||||
ManagerView *self = NULL;
|
||||
MANAGERVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
if (FALSE == Graphics_GetWindowBaseUnits(hwnd, &self->unitSize.cx, &self->unitSize.cy))
|
||||
{
|
||||
self->unitSize.cx = 6;
|
||||
self->unitSize.cy = 13;
|
||||
}
|
||||
|
||||
if (FALSE != WidgetStyle_UpdateDefaultFonts(&self->widgetStyle, self->font, self->unitSize.cx, self->unitSize.cy))
|
||||
{
|
||||
controlWindow = MANAGERVIEW_WIDGET(hwnd);
|
||||
if (NULL != controlWindow)
|
||||
WIDGET_STYLE_FONT_CHANGED(controlWindow);
|
||||
}
|
||||
|
||||
ManagerView_UpdateDiscoverButtonFont(hwnd, self->font, NULL);
|
||||
|
||||
controlWindow = MANAGERVIEW_STATUS_BAR(hwnd);
|
||||
if (NULL != controlWindow)
|
||||
SendMessage(controlWindow, WM_SETFONT, (WPARAM)self->font, 0L);
|
||||
|
||||
if (NULL != redraw)
|
||||
{
|
||||
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE |SWP_NOMOVE |SWP_FRAMECHANGED | SWP_NOREDRAW);
|
||||
|
||||
RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_UpdateDiscoveryStatus(HWND hwnd, BOOL discoveryActive)
|
||||
{
|
||||
ManagerView *self;
|
||||
MANAGERVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
HWND statusBar = MANAGERVIEW_STATUS_BAR(hwnd);
|
||||
if (NULL == statusBar)
|
||||
return;
|
||||
|
||||
if (FALSE != discoveryActive)
|
||||
{
|
||||
wchar_t buffer[512] = {0};
|
||||
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_STATUS_DISCOVERY_ACTIVE, buffer, ARRAYSIZE(buffer));
|
||||
|
||||
if (STATUS_ERROR == self->discoveryStatus)
|
||||
self->discoveryStatus = STATUSBAR_ADD_STATUS(statusBar, buffer);
|
||||
else
|
||||
{
|
||||
STATUSBAR_SET_STATUS_TEXT(statusBar, self->discoveryStatus, buffer);
|
||||
STATUSBAR_MOVE_STATUS(statusBar, self->discoveryStatus, STATUS_MOVE_TOP);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (STATUS_ERROR != self->discoveryStatus)
|
||||
{
|
||||
STATUSBAR_REMOVE_STATUS(statusBar, self->discoveryStatus);
|
||||
self->discoveryStatus = STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static HWND
|
||||
ManagerView_CreateServiceErrorWidget(HWND hwnd)
|
||||
{
|
||||
return InfoWidget_CreateWindow(WIDGET_TYPE_SERVICE_ERROR,
|
||||
MAKEINTRESOURCE(IDS_INFOWIDGET_TITLE),
|
||||
MAKEINTRESOURCE(IDS_DEVICE_SERVICE_NOT_FOUND),
|
||||
NULL,
|
||||
hwnd, 0, 0, 0, 0, TRUE, 0);
|
||||
}
|
||||
|
||||
static HWND
|
||||
ManagerView_CreateViewErrorWidget(HWND hwnd)
|
||||
{
|
||||
return InfoWidget_CreateWindow(WIDGET_TYPE_VIEW_ERROR,
|
||||
MAKEINTRESOURCE(IDS_INFOWIDGET_TITLE),
|
||||
MAKEINTRESOURCE(IDS_CREATE_MANAGER_VIEW_FAILED),
|
||||
NULL,
|
||||
hwnd, 0, 0, 0, 0, TRUE, 0);
|
||||
}
|
||||
|
||||
static HWND
|
||||
ManagerView_UpdateWidget(HWND hwnd)
|
||||
{
|
||||
ManagerView *self;
|
||||
unsigned int widgetType, requiredType;
|
||||
unsigned int windowStyle;
|
||||
|
||||
MANAGERVIEW_RET_VAL(self, hwnd, NULL);
|
||||
|
||||
HWND widgetWindow = MANAGERVIEW_WIDGET(hwnd);
|
||||
if (NULL == widgetWindow)
|
||||
widgetType = WIDGET_TYPE_UNKNOWN;
|
||||
else
|
||||
widgetType = WIDGET_GET_TYPE(widgetWindow);
|
||||
|
||||
if (FALSE != self->devicesPresent)
|
||||
requiredType = WIDGET_TYPE_LIST;
|
||||
else
|
||||
{
|
||||
requiredType = (NULL != WASABI_API_DEVICES) ?
|
||||
WIDGET_TYPE_WELCOME :
|
||||
WIDGET_TYPE_SERVICE_ERROR;
|
||||
}
|
||||
|
||||
if (widgetType == requiredType)
|
||||
return widgetWindow;
|
||||
|
||||
windowStyle = GetWindowStyle(hwnd);
|
||||
if (0 != (WS_VISIBLE & windowStyle))
|
||||
SetWindowStyle(hwnd, windowStyle & ~WS_VISIBLE);
|
||||
|
||||
if (NULL != widgetWindow)
|
||||
{
|
||||
SetWindowLongPtr(widgetWindow, GWLP_ID, 0);
|
||||
WIDGET_FREEZE(widgetWindow);
|
||||
DestroyWindow(widgetWindow);
|
||||
}
|
||||
|
||||
switch(requiredType)
|
||||
{
|
||||
case WIDGET_TYPE_SERVICE_ERROR:
|
||||
widgetWindow = ManagerView_CreateServiceErrorWidget(hwnd);
|
||||
break;
|
||||
case WIDGET_TYPE_WELCOME:
|
||||
widgetWindow = WelcomeWidget_CreateWindow(hwnd, 0, 0, 0, 0, TRUE, 0);
|
||||
break;
|
||||
case WIDGET_TYPE_LIST:
|
||||
widgetWindow = ListWidget_CreateWindow(hwnd, 0, 0, 0, 0, TRUE, 0);
|
||||
break;
|
||||
default:
|
||||
widgetWindow = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULL == widgetWindow)
|
||||
widgetWindow = ManagerView_CreateViewErrorWidget(hwnd);
|
||||
|
||||
if (NULL != widgetWindow)
|
||||
{
|
||||
if (FALSE != MANAGERVIEW_IS_FROZEN(self))
|
||||
WIDGET_FREEZE(widgetWindow);
|
||||
|
||||
MANAGERVIEW_REGISTER_WIDGET(widgetWindow);
|
||||
|
||||
WIDGET_SET_STYLE(widgetWindow, &self->widgetStyle);
|
||||
}
|
||||
|
||||
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW | SWP_FRAMECHANGED);
|
||||
|
||||
if (NULL != widgetWindow)
|
||||
{
|
||||
ShowWindow(widgetWindow, SW_SHOWNA);
|
||||
|
||||
SetWindowPos(widgetWindow, HWND_TOP, 0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
if (0 != (WS_VISIBLE & windowStyle))
|
||||
{
|
||||
windowStyle = GetWindowStyle(hwnd);
|
||||
if (0 == (WS_VISIBLE & windowStyle))
|
||||
{
|
||||
windowStyle |= WS_VISIBLE;
|
||||
SetWindowStyle(hwnd, windowStyle);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != (WS_VISIBLE & windowStyle))
|
||||
{
|
||||
RECT rect;
|
||||
GetClientRect(hwnd, &rect);
|
||||
|
||||
RedrawWindow(hwnd, &rect, NULL,
|
||||
RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN);
|
||||
}
|
||||
|
||||
return widgetWindow;
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_StartDiscovery(HWND hwnd, BOOL silent)
|
||||
{
|
||||
Plugin_BeginDiscovery();
|
||||
}
|
||||
|
||||
static BOOL
|
||||
ManagerView_CheckDevicesPresent()
|
||||
{
|
||||
ifc_deviceobjectenum *enumerator = 0;
|
||||
ifc_deviceobject *object = 0;
|
||||
ifc_device *device = 0;
|
||||
|
||||
BOOL devicesPresent = FALSE;
|
||||
|
||||
if (NULL == WASABI_API_DEVICES ||
|
||||
FAILED(WASABI_API_DEVICES->DeviceEnumerate(&enumerator)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while(S_OK == enumerator->Next(&object, 1, NULL))
|
||||
{
|
||||
if (SUCCEEDED(object->QueryInterface(IFC_Device, (void**)&device)))
|
||||
{
|
||||
if(FALSE == device->GetHidden() &&
|
||||
// excludes 'cloud' devices from appearing
|
||||
lstrcmpiA(device->GetConnection(), "cloud"))
|
||||
devicesPresent = TRUE;
|
||||
|
||||
device->Release();
|
||||
}
|
||||
object->Release();
|
||||
|
||||
if (FALSE != devicesPresent)
|
||||
break;
|
||||
}
|
||||
enumerator->Release();
|
||||
|
||||
return devicesPresent;
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_AddDevice(HWND hwnd, ifc_device *device)
|
||||
{
|
||||
ManagerView *self;
|
||||
|
||||
MANAGERVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
if (FALSE != self->devicesPresent)
|
||||
return;
|
||||
|
||||
self->devicesPresent = ManagerView_CheckDevicesPresent();
|
||||
if (FALSE != self->devicesPresent)
|
||||
ManagerView_UpdateWidget(hwnd);
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_RemoveDevice(HWND hwnd, ifc_device *device)
|
||||
{
|
||||
ManagerView *self;
|
||||
MANAGERVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
if (FALSE == self->devicesPresent)
|
||||
return;
|
||||
|
||||
self->devicesPresent = ManagerView_CheckDevicesPresent();
|
||||
if (FALSE == self->devicesPresent)
|
||||
ManagerView_UpdateWidget(hwnd);
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_DeviceCb(ifc_device *device, DeviceEvent eventId, void *user)
|
||||
{
|
||||
HWND hwnd = (HWND)user;
|
||||
|
||||
switch(eventId)
|
||||
{
|
||||
case Event_DeviceAdded:
|
||||
ManagerView_AddDevice(hwnd, device);
|
||||
break;
|
||||
|
||||
case Event_DeviceRemoved:
|
||||
ManagerView_RemoveDevice(hwnd, device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_DiscoveryCb(api_devicemanager *manager, DeviceDiscoveryEvent eventId, void *user)
|
||||
{
|
||||
HWND hwnd = (HWND)user;
|
||||
|
||||
switch(eventId)
|
||||
{
|
||||
case Event_DiscoveryStarted:
|
||||
ManagerView_UpdateDiscoveryStatus(hwnd, TRUE);
|
||||
break;
|
||||
|
||||
case Event_DiscoveryFinished:
|
||||
ManagerView_UpdateDiscoveryStatus(hwnd, FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL
|
||||
ManagerView_RegisterDeviceHandler(HWND hwnd)
|
||||
{
|
||||
ManagerView *self;
|
||||
DeviceEventCallbacks callbacks;
|
||||
|
||||
MANAGERVIEW_RET_VAL(self, hwnd, FALSE);
|
||||
|
||||
if (0 != self->deviceHandler)
|
||||
return FALSE;
|
||||
|
||||
HWND eventRelay = Plugin_GetEventRelayWindow();
|
||||
if (NULL == eventRelay)
|
||||
return FALSE;
|
||||
|
||||
ZeroMemory(&callbacks, sizeof(callbacks));
|
||||
callbacks.deviceCb = ManagerView_DeviceCb;
|
||||
callbacks.discoveryCb = ManagerView_DiscoveryCb;
|
||||
|
||||
self->deviceHandler = EVENTRELAY_REGISTER_HANDLER(eventRelay, &callbacks, hwnd);
|
||||
return (0 != self->deviceHandler);
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_OnDisplayChanged(HWND hwnd, INT bpp, INT dpi_x, INT dpi_y)
|
||||
{
|
||||
ManagerView *self = NULL;
|
||||
MANAGERVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
if (FALSE != MANAGERVIEW_IS_FROZEN(self))
|
||||
return;
|
||||
|
||||
ManagerView_UpdateSkin(hwnd);
|
||||
|
||||
RECT rc;
|
||||
GetClientRect(hwnd, &rc);
|
||||
RedrawWindow(hwnd, &rc, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN | RDW_ERASENOW | RDW_UPDATENOW);
|
||||
|
||||
ManagerView_Layout(hwnd, TRUE);
|
||||
}
|
||||
|
||||
static INT_PTR
|
||||
ManagerView_OnInitDialog(HWND hwnd, HWND focusWindow, LPARAM param)
|
||||
{
|
||||
ManagerView *self = (ManagerView*)malloc(sizeof(ManagerView));
|
||||
if (NULL != self)
|
||||
{
|
||||
ZeroMemory(self, sizeof(ManagerView));
|
||||
if (FALSE == SetProp(hwnd, MAKEINTATOM(MANAGERVIEW_ATOM), self))
|
||||
{
|
||||
free(self);
|
||||
self = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == self)
|
||||
{
|
||||
DestroyWindow(hwnd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MANAGERVIEW_FREEZE(self);
|
||||
|
||||
ManagerView_RegisterDeviceHandler(hwnd);
|
||||
|
||||
self->devicesPresent = ManagerView_CheckDevicesPresent();
|
||||
|
||||
MLSkinWindow2(Plugin_GetLibraryWindow(), hwnd, SKINNEDWND_TYPE_DIALOG,
|
||||
SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS);
|
||||
|
||||
HWND discoverButton = MANAGERVIEW_DISCOVER_BUTTON(hwnd);
|
||||
if (NULL != discoverButton)
|
||||
{
|
||||
MLSkinWindow2(Plugin_GetLibraryWindow(), discoverButton, SKINNEDWND_TYPE_BUTTON,
|
||||
SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS);
|
||||
|
||||
ShowWindow(discoverButton, SW_SHOW);
|
||||
EnableWindow(discoverButton, TRUE);
|
||||
}
|
||||
|
||||
HWND statusBar = StatusBar_CreateWindow(0, NULL, WS_VISIBLE, 0, 0, 0, 0, hwnd, MANAGERVIEW_STATUSBAR_ID);
|
||||
if (NULL != statusBar)
|
||||
{
|
||||
MLSkinWindow2(Plugin_GetLibraryWindow(), statusBar, SKINNEDWND_TYPE_AUTO,
|
||||
SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS);
|
||||
}
|
||||
|
||||
self->discoveryStatus = STATUS_ERROR;
|
||||
|
||||
if (S_OK == WASABI_API_DEVICES->IsDiscoveryActive())
|
||||
ManagerView_UpdateDiscoveryStatus(hwnd, TRUE);
|
||||
|
||||
ManagerView_UpdateFont(hwnd, FALSE);
|
||||
ManagerView_UpdateSkin(hwnd);
|
||||
|
||||
HWND widgetWindow = ManagerView_UpdateWidget(hwnd);
|
||||
MANAGERVIEW_THAW(self);
|
||||
|
||||
if (NULL != widgetWindow)
|
||||
WIDGET_THAW(widgetWindow);
|
||||
|
||||
PostMessage(hwnd, WM_DISPLAYCHANGE, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_OnDestroy(HWND hwnd)
|
||||
{
|
||||
ManagerView *self = MANAGERVIEW(hwnd);
|
||||
RemoveProp(hwnd, MAKEINTATOM(MANAGERVIEW_ATOM));
|
||||
|
||||
if (NULL == self)
|
||||
return;
|
||||
|
||||
MANAGERVIEW_FREEZE(self);
|
||||
|
||||
if (0 != self->deviceHandler)
|
||||
{
|
||||
HWND eventRelay = Plugin_GetEventRelayWindow();
|
||||
if (NULL != eventRelay)
|
||||
{
|
||||
EVENTRELAY_UNREGISTER_HANDLER(eventRelay, self->deviceHandler);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != self->systemFont)
|
||||
DeleteObject(self->systemFont);
|
||||
|
||||
if (NULL != self->backBrush)
|
||||
DeleteObject(self->backBrush);
|
||||
|
||||
WidgetStyle_Free(&self->widgetStyle);
|
||||
free(self);
|
||||
}
|
||||
|
||||
static LRESULT
|
||||
ManagerView_OnColorDialog(HWND hwnd, HDC hdc)
|
||||
{
|
||||
ManagerView *self;
|
||||
self = MANAGERVIEW(hwnd);
|
||||
|
||||
if (NULL == self)
|
||||
return DefWindowProcW(hwnd, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hwnd);
|
||||
|
||||
if (NULL != hdc)
|
||||
{
|
||||
SetTextColor(hdc, self->textColor);
|
||||
SetBkColor(hdc, self->backColor);
|
||||
}
|
||||
|
||||
return (LRESULT)self->backBrush;
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_OnWindowPosChanged(HWND hwnd, WINDOWPOS *windowPos)
|
||||
{
|
||||
if ((SWP_NOSIZE | SWP_NOMOVE) != ((SWP_NOSIZE | SWP_NOMOVE) & windowPos->flags) ||
|
||||
(SWP_FRAMECHANGED & windowPos->flags))
|
||||
{
|
||||
ManagerView *self;
|
||||
MANAGERVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
if (FALSE != MANAGERVIEW_IS_FROZEN(self))
|
||||
return;
|
||||
|
||||
ManagerView_Layout(hwnd, !(SWP_NOREDRAW & windowPos->flags));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_OnPaint(HWND hwnd)
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
if (NULL != BeginPaint(hwnd, &ps))
|
||||
{
|
||||
ManagerView_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase);
|
||||
EndPaint(hwnd, &ps);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_OnPrintClient(HWND hwnd, HDC hdc, UINT options)
|
||||
{
|
||||
RECT clientRect;
|
||||
if (GetClientRect(hwnd, &clientRect))
|
||||
{
|
||||
ManagerView_Paint(hwnd, hdc, &clientRect, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_OnSetFont(HWND hwnd, HFONT font, BOOL redraw)
|
||||
{
|
||||
ManagerView *self = NULL;
|
||||
LOGFONTW prevFont = {0}, newFont = {0};
|
||||
|
||||
MANAGERVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
if (NULL == self->font ||
|
||||
sizeof(LOGFONTW) != GetObjectW(self->font, sizeof(prevFont), &prevFont))
|
||||
{
|
||||
ZeroMemory(&prevFont, sizeof(prevFont));
|
||||
}
|
||||
|
||||
self->font = font;
|
||||
if (NULL == self->font)
|
||||
{
|
||||
if (NULL == self->systemFont)
|
||||
self->systemFont = Graphics_CreateSysFont();
|
||||
}
|
||||
|
||||
if (NULL == self->font ||
|
||||
sizeof(newFont) != GetObjectW(self->font, sizeof(newFont), &newFont))
|
||||
{
|
||||
ZeroMemory(&newFont, sizeof(newFont));
|
||||
}
|
||||
|
||||
if (0 == memcmp(&prevFont, &newFont, sizeof(prevFont)) ||
|
||||
FALSE != MANAGERVIEW_IS_FROZEN(self))
|
||||
{
|
||||
redraw = FALSE;
|
||||
}
|
||||
|
||||
ManagerView_UpdateFont(hwnd, redraw);
|
||||
}
|
||||
|
||||
static HFONT
|
||||
ManagerView_OnGetFont(HWND hwnd)
|
||||
{
|
||||
ManagerView *self;
|
||||
MANAGERVIEW_RET_VAL(self, hwnd, NULL);
|
||||
|
||||
return self->font;
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_OnCommand(HWND hwnd, INT commandId, INT eventId, HWND controlWindow)
|
||||
{
|
||||
switch(commandId)
|
||||
{
|
||||
case IDC_BUTTON_DISCOVER:
|
||||
switch(eventId)
|
||||
{
|
||||
case BN_CLICKED:
|
||||
ManagerView_StartDiscovery(hwnd, FALSE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_OnZoomSliderPosChanging(HWND hwnd, NMTRBTHUMBPOSCHANGING *sliderInfo)
|
||||
{
|
||||
HWND widgetWindow = MANAGERVIEW_WIDGET(hwnd);
|
||||
if (NULL != widgetWindow)
|
||||
WIDGET_ZOOM_SLIDER_POS_CHANGING(widgetWindow, sliderInfo);
|
||||
}
|
||||
|
||||
static LRESULT
|
||||
ManagerView_OnNotify(HWND hwnd, NMHDR *pnmh)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_OnHorzScroll(HWND hwnd, INT action, INT trackPosition, HWND senderWindow)
|
||||
{
|
||||
HWND sliderWindow = MANAGERVIEW_ZOOM_SLIDER(hwnd);
|
||||
if (NULL != sliderWindow && senderWindow == sliderWindow)
|
||||
{
|
||||
NMTRBTHUMBPOSCHANGING zoomInfo;
|
||||
zoomInfo.hdr.code = TRBN_THUMBPOSCHANGING;
|
||||
zoomInfo.hdr.hwndFrom = senderWindow;
|
||||
zoomInfo.hdr.idFrom = IDC_SLIDER_ZOOM;
|
||||
zoomInfo.nReason = action;
|
||||
if (TB_THUMBPOSITION == action ||
|
||||
TB_THUMBTRACK == action)
|
||||
{
|
||||
zoomInfo.dwPos = trackPosition;
|
||||
}
|
||||
else
|
||||
zoomInfo.dwPos = (DWORD)SendMessage(sliderWindow, TBM_GETPOS, 0, 0L);
|
||||
|
||||
ManagerView_OnZoomSliderPosChanging(hwnd, &zoomInfo);
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL
|
||||
ManagerView_OnHelp(HWND hwnd, HELPINFO *helpInfo)
|
||||
{
|
||||
HWND widgetWindow = MANAGERVIEW_WIDGET(hwnd);
|
||||
if (NULL != widgetWindow)
|
||||
{
|
||||
wchar_t buffer[4096] = {0};
|
||||
|
||||
if (FALSE != WIDGET_GET_HELP_URL(widgetWindow, buffer, ARRAYSIZE(buffer)) &&
|
||||
MediaLibrary_ShowHelp(Plugin_GetLibraryWindow(), buffer))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return Plugin_ShowHelp();
|
||||
}
|
||||
|
||||
static void
|
||||
ManagerView_OnSetUpdateRegion(HWND hwnd, HRGN updateRegion, POINTS regionOffset)
|
||||
{
|
||||
ManagerView *self;
|
||||
MANAGERVIEW_RET_VOID(self, hwnd);
|
||||
|
||||
self->updateRegion = updateRegion;
|
||||
self->updateOffset.x = regionOffset.x;
|
||||
self->updateOffset.y = regionOffset.y;
|
||||
}
|
||||
|
||||
static HWND
|
||||
ManagerView_OnGetZoomSlider(HWND hwnd)
|
||||
{
|
||||
return MANAGERVIEW_ZOOM_SLIDER(hwnd);
|
||||
}
|
||||
|
||||
static HWND
|
||||
ManagerView_OnGetStatusBar(HWND hwnd)
|
||||
{
|
||||
return MANAGERVIEW_STATUS_BAR(hwnd);
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK
|
||||
ManagerView_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG: return ManagerView_OnInitDialog(hwnd, (HWND)wParam, lParam);
|
||||
case WM_DESTROY: ManagerView_OnDestroy(hwnd); return TRUE;
|
||||
case WM_CTLCOLORDLG: return ManagerView_OnColorDialog(hwnd, (HDC)wParam);
|
||||
case WM_PAINT: ManagerView_OnPaint(hwnd); return TRUE;
|
||||
case WM_PRINTCLIENT: ManagerView_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); return TRUE;
|
||||
case WM_ERASEBKGND: DIALOG_RESULT(hwnd, 0);
|
||||
case WM_WINDOWPOSCHANGED: ManagerView_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return TRUE;
|
||||
case WM_DISPLAYCHANGE: ManagerView_OnDisplayChanged(hwnd, (INT)wParam, LOWORD(lParam), HIWORD(lParam)); return TRUE;
|
||||
case WM_SETFONT: ManagerView_OnSetFont(hwnd, (HFONT)wParam, LOWORD(lParam)); return TRUE;
|
||||
case WM_GETFONT: DIALOG_RESULT(hwnd, ManagerView_OnGetFont(hwnd));
|
||||
case WM_COMMAND: ManagerView_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); return TRUE;
|
||||
case WM_NOTIFY: DIALOG_RESULT(hwnd, ManagerView_OnNotify(hwnd, (NMHDR*)lParam));
|
||||
case WM_HSCROLL: ManagerView_OnHorzScroll(hwnd, LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); return TRUE;
|
||||
case WM_HELP: DIALOG_RESULT(hwnd, ManagerView_OnHelp(hwnd, (HELPINFO*)lParam));
|
||||
|
||||
// gen_ml flickerless drawing
|
||||
case WM_USER + 0x200: DIALOG_RESULT(hwnd, 1);
|
||||
case WM_USER + 0x201: ManagerView_OnSetUpdateRegion(hwnd, (HRGN)lParam, MAKEPOINTS(wParam)); return TRUE;
|
||||
|
||||
case MANAGERVIEW_WM_ZOOMSLIDER: DIALOG_RESULT(hwnd, ManagerView_OnGetZoomSlider(hwnd));
|
||||
case MANAGERVIEW_WM_STATUSBAR: DIALOG_RESULT(hwnd, ManagerView_OnGetStatusBar(hwnd));
|
||||
}
|
||||
return 0;
|
||||
}
|
22
Src/Plugins/Library/ml_devices/managerView.h
Normal file
22
Src/Plugins/Library/ml_devices/managerView.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_MANAGER_VIEW_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_MANAGER_VIEW_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
HWND ManagerView_CreateWindow(HWND parentWindow);
|
||||
|
||||
#define MANAGERVIEW_WM_FIRST (WM_USER + 10)
|
||||
|
||||
#define MANAGERVIEW_WM_ZOOMSLIDER (MANAGERVIEW_WM_FIRST + 0)
|
||||
#define MANAGERVIEW_GET_ZOOM_SLIDER(/*HWND*/ _hwnd)\
|
||||
((HWND)SendMessageW((_hwnd), MANAGERVIEW_WM_ZOOMSLIDER, 0, 0L))
|
||||
|
||||
#define MANAGERVIEW_WM_STATUSBAR (MANAGERVIEW_WM_FIRST + 1)
|
||||
#define MANAGERVIEW_GET_STATUS_BAR(/*HWND*/ _hwnd)\
|
||||
((HWND)SendMessageW((_hwnd), MANAGERVIEW_WM_STATUSBAR, 0, 0L))
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_MANAGER_VIEW_HEADER
|
172
Src/Plugins/Library/ml_devices/ml_devices.rc
Normal file
172
Src/Plugins/Library/ml_devices/ml_devices.rc
Normal file
|
@ -0,0 +1,172 @@
|
|||
// 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
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_MANAGER_VIEW DIALOGEX 0, 0, 317, 186
|
||||
STYLE DS_SETFONT | DS_NOIDLEMSG | DS_FIXEDSYS | DS_NOFAILCREATE | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
|
||||
EXSTYLE WS_EX_CONTROLPARENT | WS_EX_NOACTIVATE
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
PUSHBUTTON "Discover",IDC_BUTTON_DISCOVER,0,172,50,14
|
||||
CONTROL "",IDC_SLIDER_ZOOM,"msctls_trackbar32",TBS_NOTICKS | TBS_ENABLESELRANGE | NOT WS_VISIBLE | WS_TABSTOP,244,174,73,12
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
//
|
||||
|
||||
IDR_PLUGIN_MENU MENU
|
||||
BEGIN
|
||||
POPUP "NavigationRootContext"
|
||||
BEGIN
|
||||
MENUITEM "&Open", ID_VIEW_OPEN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Start &Discovery", ID_DISCOVERY_BEGIN
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&Help", ID_PLUGIN_HELP
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_WELCOMEWIDGET_TITLE "WINAMP DEVICE MANAGER"
|
||||
IDS_WELCOMEWIDGET_TEXT "Manage the media on your devices by connecting them to Winamp. To get started, connect a device or click Discover to find already connected devices. To manage Android devices over Wi-Fi, ensure wireless sync is enabled in the Winamp App settings."
|
||||
IDS_DEVICES_NAVIGATION_NODE "Devices"
|
||||
IDS_CATEGORY_ATTACHED "Attached"
|
||||
IDS_CATEGORY_DISCOVERED "Discovered"
|
||||
IDS_INFOWIDGET_TITLE "Winamp Device Manager"
|
||||
IDS_DEVICE_SERVICE_NOT_FOUND
|
||||
"Winamp Device Manager unable to communicate with device service. Try reinstalling application."
|
||||
IDS_CREATE_DEVICE_VIEW_FAILED
|
||||
"Error creating device view. Verify that you have latest version of portable media plug-in."
|
||||
IDS_SYNC_COMMAND_TITLE "&Sync"
|
||||
IDS_SYNC_COMMAND_DESC "Transfer media to device"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_PLUGIN_NAME "Nullsoft Device Manager v%d.%02d"
|
||||
65535 "{CA4D071B-4E9B-44fd-862A-783FC763B63D}"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CANCEL_SYNC_COMMAND_TITLE "C&ancel Sync"
|
||||
IDS_CANCEL_SYNC_COMMAND_DESC "Cancel synchronization"
|
||||
IDS_CREATE_MANAGER_VIEW_FAILED "Unable to create device manager view."
|
||||
IDS_ATTACH_COMMAND_TITLE "&Attach"
|
||||
IDS_ATTACH_COMMAND_DESC "Connect device to Winamp"
|
||||
IDS_DETACH_COMMAND_TITLE "&Detach"
|
||||
IDS_DETACH_COMMAND_DESC "Detach device from Winamp"
|
||||
IDS_EJECT_COMMAND_TITLE "&Eject"
|
||||
IDS_EJECT_COMMAND_DESC "Eject device"
|
||||
IDS_DEVICE_TYPE_SHORT "Type"
|
||||
IDS_DEVICE_CONNECTION_SHORT "Connection"
|
||||
IDS_TOTAL_SPACE "Total"
|
||||
IDS_FREE_SPACE "Free"
|
||||
IDS_USED_SPACE "Used"
|
||||
IDS_FRACTION_SEPARATOR "."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_DEVICE_ACTIVITY_SHORT "Status"
|
||||
IDS_PLUGIN_HELP_URL "https://help.winamp.com/hc/articles/8106455294612-Winamp-Portables-Guide"
|
||||
IDS_RENAME_COMMAND_TITLE "&Rename\tF2"
|
||||
IDS_RENAME_COMMAND_DESC "Change the name of this device."
|
||||
IDS_VIEW_OPEN_COMMAND_TITLE "&Open"
|
||||
IDS_VIEW_OPEN_COMMAND_DESC "Show contents of this device."
|
||||
IDS_PREFERENCES_COMMAND_TITLE "&Preferences"
|
||||
IDS_PREFERENCES_COMMAND_DESC "Change settings for this device."
|
||||
IDS_PLAYLIST_CREATE_COMMAND_TITLE "&New Playlist"
|
||||
IDS_PLAYLIST_CREATE_COMMAND_DESC "Make a new playlist on this device."
|
||||
IDS_MESSAGEBOX_TITLE "Winamp Device Manager"
|
||||
IDS_MESSAGE_UNABLE_TO_RENAME "Unable to change device name."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_DEVICE_MODEL_SHORT "Model"
|
||||
IDS_DEVICE_STATUS_SHORT "Status"
|
||||
IDS_STATUS_DISCOVERY_ACTIVE "Discovering devices..."
|
||||
IDS_STATUS_SPACE_TEMPLATE "%s free of %s"
|
||||
IDS_CATEGORY_ATTACHED_EMPTY_TEXT
|
||||
"No devices are attached, select a discovered device to attach."
|
||||
IDS_WELCOMEWIDGET_HELP_URL
|
||||
"https://help.winamp.com/hc/articles/8106455294612-Winamp-Portables-Guide"
|
||||
IDS_HELP_LINK "Help"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
#include "version.rc2"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
51
Src/Plugins/Library/ml_devices/ml_devices.sln
Normal file
51
Src/Plugins/Library/ml_devices/ml_devices.sln
Normal file
|
@ -0,0 +1,51 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29613.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ml_devices", "ml_devices.vcxproj", "{07D24820-5624-4EC3-AAC6-288D20E039DE}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "devices", "..\devices\devices.vcxproj", "{06F6E796-653F-48A9-BA2F-46B679D35F9E}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_deviceprovider", "gen_deviceprovider\gen_deviceprovider.vcxproj", "{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}"
|
||||
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
|
||||
{07D24820-5624-4EC3-AAC6-288D20E039DE}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{07D24820-5624-4EC3-AAC6-288D20E039DE}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{07D24820-5624-4EC3-AAC6-288D20E039DE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{07D24820-5624-4EC3-AAC6-288D20E039DE}.Debug|x64.Build.0 = Debug|x64
|
||||
{07D24820-5624-4EC3-AAC6-288D20E039DE}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{07D24820-5624-4EC3-AAC6-288D20E039DE}.Release|Win32.Build.0 = Release|Win32
|
||||
{07D24820-5624-4EC3-AAC6-288D20E039DE}.Release|x64.ActiveCfg = Release|x64
|
||||
{07D24820-5624-4EC3-AAC6-288D20E039DE}.Release|x64.Build.0 = Release|x64
|
||||
{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}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{06F6E796-653F-48A9-BA2F-46B679D35F9E}.Debug|x64.Build.0 = Debug|x64
|
||||
{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}.Release|x64.ActiveCfg = Release|x64
|
||||
{06F6E796-653F-48A9-BA2F-46B679D35F9E}.Release|x64.Build.0 = Release|x64
|
||||
{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}.Debug|Win32.ABuild = Debug|Win32
|
||||
{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}.Debug|x64.ABuild = Debug|x64
|
||||
{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}.Release|Win32.Build = Release|Win32
|
||||
{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}.Release|x64.ActiveCfg = Release|x64
|
||||
{A3C7D830-CD01-4C2B-9E1A-FB62B5236BA9}.Release|x64.Build = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {6DCE600E-002D-459F-9DDB-A21A22F89EF7}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
412
Src/Plugins/Library/ml_devices/ml_devices.vcxproj
Normal file
412
Src/Plugins/Library/ml_devices/ml_devices.vcxproj
Normal file
|
@ -0,0 +1,412 @@
|
|||
<?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="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{07D24820-5624-4EC3-AAC6-288D20E039DE}</ProjectGuid>
|
||||
<RootNamespace>ml_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)'=='Release|x64'" 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>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</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)'=='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|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>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
<EmbedManifest>true</EmbedManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
||||
<EmbedManifest>true</EmbedManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
<EmbedManifest>true</EmbedManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
|
||||
<EmbedManifest>true</EmbedManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg">
|
||||
<VcpkgEnableManifest>false</VcpkgEnableManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgConfiguration>Debug</VcpkgConfiguration>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
<VcpkgConfiguration>Debug</VcpkgConfiguration>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<VcpkgInstalledDir>
|
||||
</VcpkgInstalledDir>
|
||||
<VcpkgUseStatic>false</VcpkgUseStatic>
|
||||
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;..\..\..\;..\..\..\wasabi;..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;_DEBUG;_WINDOWS;_USRDLL;ML_DEVICES_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<Profile>false</Profile>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
</Link>
|
||||
<Xdcmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
|
||||
</Xdcmake>
|
||||
<Bscmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).bsc</OutputFile>
|
||||
</Bscmake>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
|
||||
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Manifest>
|
||||
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;../wasabi;../agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;_DEBUG;_WINDOWS;_USRDLL;ML_DEVICES_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<Profile>false</Profile>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
</Link>
|
||||
<Xdcmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
|
||||
</Xdcmake>
|
||||
<Bscmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).bsc</OutputFile>
|
||||
</Bscmake>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
|
||||
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Manifest>
|
||||
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>..;..\..\..\;..\..\..\wasabi;..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;NDEBUG;_WINDOWS;_USRDLL;ML_DEVICES_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>comctl32.lib;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>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<Xdcmake>
|
||||
<OutputFile>$(IntDir)$(ProjectName).xml</OutputFile>
|
||||
</Xdcmake>
|
||||
<Bscmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).bsc</OutputFile>
|
||||
</Bscmake>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Manifest>
|
||||
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>..;..\..\..\;..\..\..\wasabi;..\..\..\agave;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;NDEBUG;_WINDOWS;_USRDLL;ML_DEVICES_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4312;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>comctl32.lib;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>
|
||||
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ModuleDefinitionFile>
|
||||
</ModuleDefinitionFile>
|
||||
</Link>
|
||||
<Xdcmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
|
||||
</Xdcmake>
|
||||
<Bscmake>
|
||||
<OutputFile>$(IntDir)$(TargetName).bsc</OutputFile>
|
||||
</Bscmake>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
|
||||
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
|
||||
</PostBuildEvent>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Manifest>
|
||||
<OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\General\gen_ml\menu.cpp" />
|
||||
<ClCompile Include="..\..\..\nu\trace.cpp" />
|
||||
<ClCompile Include="backBuffer.cpp" />
|
||||
<ClCompile Include="config.cpp" />
|
||||
<ClCompile Include="deviceCommands.cpp" />
|
||||
<ClCompile Include="deviceHandler.cpp" />
|
||||
<ClCompile Include="deviceManagerHandler.cpp" />
|
||||
<ClCompile Include="embeddedEditor.cpp" />
|
||||
<ClCompile Include="eventRelay.cpp" />
|
||||
<ClCompile Include="fillRegion.cpp" />
|
||||
<ClCompile Include="graphics.cpp" />
|
||||
<ClCompile Include="image.cpp" />
|
||||
<ClCompile Include="imageCache.cpp" />
|
||||
<ClCompile Include="infoWidget.cpp" />
|
||||
<ClCompile Include="listWidget.cpp" />
|
||||
<ClCompile Include="listWidgetCategory.cpp" />
|
||||
<ClCompile Include="listWidgetCommand.cpp" />
|
||||
<ClCompile Include="listWidgetConnection.cpp" />
|
||||
<ClCompile Include="listWidgetGroup.cpp" />
|
||||
<ClCompile Include="listWidgetItem.cpp" />
|
||||
<ClCompile Include="listWidgetPaint.cpp" />
|
||||
<ClCompile Include="listWidgetTooltip.cpp" />
|
||||
<ClCompile Include="local_menu.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="managerView.cpp" />
|
||||
<ClCompile Include="navigation.cpp" />
|
||||
<ClCompile Include="navigationIcons.cpp" />
|
||||
<ClCompile Include="plugin.cpp" />
|
||||
<ClCompile Include="statusBar.cpp" />
|
||||
<ClCompile Include="strings.cpp" />
|
||||
<ClCompile Include="wasabi.cpp" />
|
||||
<ClCompile Include="welcomeWidget.cpp" />
|
||||
<ClCompile Include="widget.cpp" />
|
||||
<ClCompile Include="widgetHost.cpp" />
|
||||
<ClCompile Include="widgetStyle.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\General\gen_ml\menu.h" />
|
||||
<ClInclude Include="..\..\..\nu\trace.h" />
|
||||
<ClInclude Include="backBuffer.h" />
|
||||
<ClInclude Include="common.h" />
|
||||
<ClInclude Include="config.h" />
|
||||
<ClInclude Include="deviceCommands.h" />
|
||||
<ClInclude Include="deviceHandler.h" />
|
||||
<ClInclude Include="deviceManagerHandler.h" />
|
||||
<ClInclude Include="embeddedEditor.h" />
|
||||
<ClInclude Include="eventRelay.h" />
|
||||
<ClInclude Include="fillRegion.h" />
|
||||
<ClInclude Include="graphics.h" />
|
||||
<ClInclude Include="image.h" />
|
||||
<ClInclude Include="imageCache.h" />
|
||||
<ClInclude Include="infoWidget.h" />
|
||||
<ClInclude Include="listWidget.h" />
|
||||
<ClInclude Include="listWidgetInternal.h" />
|
||||
<ClInclude Include="local_menu.h" />
|
||||
<ClInclude Include="main.h" />
|
||||
<ClInclude Include="managerView.h" />
|
||||
<ClInclude Include="navigation.h" />
|
||||
<ClInclude Include="navigationIcons.h" />
|
||||
<ClInclude Include="plugin.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="statusBar.h" />
|
||||
<ClInclude Include="strings.h" />
|
||||
<ClInclude Include="wasabi.h" />
|
||||
<ClInclude Include="welcomeWidget.h" />
|
||||
<ClInclude Include="widget.h" />
|
||||
<ClInclude Include="widgetHost.h" />
|
||||
<ClInclude Include="widgetStyle.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="resources\action-bg.png" />
|
||||
<Image Include="resources\arrows.png" />
|
||||
<Image Include="resources\attach-command-large.png" />
|
||||
<Image Include="resources\attach-command-small.png" />
|
||||
<Image Include="resources\cancel-sync-command-small.png" />
|
||||
<Image Include="resources\command-bg.png" />
|
||||
<Image Include="resources\command-secondary-bg.png" />
|
||||
<Image Include="resources\detach-command-large.png" />
|
||||
<Image Include="resources\detach-command-small.png" />
|
||||
<Image Include="resources\devices-title-en.png" />
|
||||
<Image Include="resources\devices.png" />
|
||||
<Image Include="resources\eject-command-small.png" />
|
||||
<Image Include="resources\generic-device-160x160.png" />
|
||||
<Image Include="resources\generic-device-16x16.png" />
|
||||
<Image Include="resources\item-hover.png" />
|
||||
<Image Include="resources\item-select.png" />
|
||||
<Image Include="resources\progress-large.png" />
|
||||
<Image Include="resources\progress-small.png" />
|
||||
<Image Include="resources\spacebar.png" />
|
||||
<Image Include="resources\sync-command-large.png" />
|
||||
<Image Include="resources\sync-command-small.png" />
|
||||
<Image Include="resources\unknown-command-large.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="ml_devices.rc" />
|
||||
<ResourceCompile Include="png.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>
|
310
Src/Plugins/Library/ml_devices/ml_devices.vcxproj.filters
Normal file
310
Src/Plugins/Library/ml_devices/ml_devices.vcxproj.filters
Normal file
|
@ -0,0 +1,310 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="backBuffer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="config.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceCommands.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deviceManagerHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="embeddedEditor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="eventRelay.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="fillRegion.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="graphics.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="image.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="imageCache.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="infoWidget.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="listWidget.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="listWidgetCategory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="listWidgetCommand.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="listWidgetConnection.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="listWidgetGroup.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="listWidgetItem.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="listWidgetPaint.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="listWidgetTooltip.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="local_menu.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="managerView.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="navigation.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="navigationIcons.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="plugin.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="statusBar.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="strings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wasabi.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="welcomeWidget.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="widgetStyle.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="widget.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="widgetHost.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\General\gen_ml\menu.cpp">
|
||||
<Filter>Source Files\gen_ml</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\nu\PtrList.cpp">
|
||||
<Filter>Source Files\nu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\nu\trace.cpp">
|
||||
<Filter>Source Files\nu</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="backBuffer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="common.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="config.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceCommands.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deviceManagerHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="embeddedEditor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="eventRelay.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="fillRegion.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="graphics.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="image.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="imageCache.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="infoWidget.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="listWidget.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="listWidgetInternal.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="local_menu.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="main.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="managerView.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="navigation.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="navigationIcons.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="plugin.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="statusBar.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="wasabi.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="welcomeWidget.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="widget.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="widgetHost.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="widgetStyle.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\General\gen_ml\menu.h">
|
||||
<Filter>Header Files\gen_ml</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\nu\trace.h">
|
||||
<Filter>Header Files\nu</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="ml_devices.rc">
|
||||
<Filter>Ressource Files</Filter>
|
||||
</ResourceCompile>
|
||||
<ResourceCompile Include="png.rc">
|
||||
<Filter>Ressource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="resources\attach-command-small.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\attach-command-large.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\cancel-sync-command-small.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\command-secondary-bg.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\detach-command-large.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\detach-command-small.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\generic-device-16x16.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\devices-title-en.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\devices.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\eject-command-small.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\command-bg.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\generic-device-160x160.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\action-bg.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\arrows.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\item-select.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\item-hover.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\progress-small.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\progress-large.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\sync-command-large.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\sync-command-small.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\spacebar.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
<Image Include="resources\unknown-command-large.png">
|
||||
<Filter>Image Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{e0dd5a27-571d-4f70-a2d4-d5752e61b4c9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Ressource Files">
|
||||
<UniqueIdentifier>{517e7a4b-9342-4d4c-8b09-cc9cd316f8d2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{b0bc738e-6b68-4e58-9192-30fd269eb5b3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Image Files">
|
||||
<UniqueIdentifier>{9918fa42-7a6e-4012-93e5-82c60aac295f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\gen_ml">
|
||||
<UniqueIdentifier>{f48e1848-fef5-4f67-a582-5621c5ca6e47}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\nu">
|
||||
<UniqueIdentifier>{4b166e51-c75c-4c33-81ff-81af63bdcbfe}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\gen_ml">
|
||||
<UniqueIdentifier>{1a9a3d9f-f9f0-4c01-b873-2f961be3f40f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\nu">
|
||||
<UniqueIdentifier>{5960b4c7-3d94-4269-9755-8cabb8309b36}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
1073
Src/Plugins/Library/ml_devices/navigation.cpp
Normal file
1073
Src/Plugins/Library/ml_devices/navigation.cpp
Normal file
File diff suppressed because it is too large
Load diff
29
Src/Plugins/Library/ml_devices/navigation.h
Normal file
29
Src/Plugins/Library/ml_devices/navigation.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef _NULLSOFT_WINAMP_ML_DEVICES_NAVIGATION_HEADER
|
||||
#define _NULLSOFT_WINAMP_ML_DEVICES_NAVIGATION_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
BOOL
|
||||
Navigation_Initialize(void);
|
||||
|
||||
void
|
||||
Navigation_Uninitialize(void);
|
||||
|
||||
BOOL
|
||||
Navigation_SelectDevice(const char *name);
|
||||
|
||||
BOOL
|
||||
Navigation_EditDeviceTitle(const char *name);
|
||||
|
||||
BOOL
|
||||
Navigation_ProcessMessage(INT msg,
|
||||
INT_PTR param1,
|
||||
INT_PTR param2,
|
||||
INT_PTR param3,
|
||||
INT_PTR *result);
|
||||
|
||||
#endif //_NULLSOFT_WINAMP_ML_DEVICES_NAVIGATION_HEADER
|
343
Src/Plugins/Library/ml_devices/navigationIcons.cpp
Normal file
343
Src/Plugins/Library/ml_devices/navigationIcons.cpp
Normal file
|
@ -0,0 +1,343 @@
|
|||
#include "main.h"
|
||||
#include "navigationIcons.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef struct IconCacheRecord
|
||||
{
|
||||
size_t ref;
|
||||
int index;
|
||||
DeviceImage *image;
|
||||
} IconCacheRecord;
|
||||
|
||||
typedef std::vector<IconCacheRecord> 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;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue