diff options
Diffstat (limited to 'Src/Plugins/Library/ml_devices/plugin.cpp')
-rw-r--r-- | Src/Plugins/Library/ml_devices/plugin.cpp | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/Src/Plugins/Library/ml_devices/plugin.cpp b/Src/Plugins/Library/ml_devices/plugin.cpp new file mode 100644 index 00000000..e8396373 --- /dev/null +++ b/Src/Plugins/Library/ml_devices/plugin.cpp @@ -0,0 +1,357 @@ +#include "main.h" +#include <vector> + +//#include <crtdbg.h> +#include <strsafe.h> + +typedef std::vector<PluginUnloadCallback> UnloadCallbackList; + +static int Plugin_Init(); +static void Plugin_Quit(); + +static INT_PTR +Plugin_MessageProc(INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3); + +extern "C" winampMediaLibraryPlugin plugin = +{ + MLHDR_VER, + "nullsoft(ml_devices.dll)", + Plugin_Init, + Plugin_Quit, + Plugin_MessageProc, + 0, + 0, + 0, +}; + +static UnloadCallbackList *unloadCallbacks = NULL; +static DeviceImageCache *imageCache = NULL; +static HWND eventRelayWindow = NULL; + +HINSTANCE +Plugin_GetInstance(void) +{ + return plugin.hDllInstance; +} + +HWND +Plugin_GetWinampWindow(void) +{ + return plugin.hwndWinampParent; +} + +HWND +Plugin_GetLibraryWindow(void) +{ + return plugin.hwndLibraryParent; +} + +static void +Plugin_SetDescription() +{ + static wchar_t szDescription[256]; + StringCchPrintf(szDescription, ARRAYSIZE(szDescription), + WASABI_API_LNGSTRINGW(IDS_PLUGIN_NAME), + PLUGIN_VERSION_MAJOR, PLUGIN_VERSION_MINOR); + plugin.description = (char*)szDescription; +} + +static int Plugin_Init() +{ + unloadCallbacks = NULL; + +// _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | +// _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_CHECK_CRT_DF); + + if (FALSE == Wasabi_InitializeFromWinamp(plugin.hDllInstance, plugin.hwndWinampParent)) + return ML_INIT_FAILURE; + + Wasabi_LoadDefaultServices(); + + Plugin_SetDescription(); + + imageCache = DeviceImageCache_Create(); + + if (NULL == eventRelayWindow) + { + eventRelayWindow = EventRelay_CreateWindow(); + if (NULL == eventRelayWindow) + return 2; + } + + if (FALSE == Navigation_Initialize()) + { + if (NULL != eventRelayWindow) + { + DestroyWindow(eventRelayWindow); + eventRelayWindow = NULL; + } + + Wasabi_Release(); + return 3; + } + + DeviceCommands_Register(); + + return ML_INIT_SUCCESS; +} + +static void Plugin_Quit() +{ + if (NULL != unloadCallbacks) + { + size_t index = unloadCallbacks->size(); + while(index--) + unloadCallbacks->at(index)(); + delete(unloadCallbacks); + } + + if (NULL != eventRelayWindow) + { + DestroyWindow(eventRelayWindow); + eventRelayWindow = NULL; + } + + Navigation_Uninitialize(); + + if (NULL != imageCache) + { + DeviceImageCache_Free(imageCache); + imageCache = NULL; + } + + Wasabi_Release(); +} + +static INT_PTR +Plugin_MessageProc(INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3) +{ + INT_PTR result = 0; + + if (FALSE != Navigation_ProcessMessage(msg, param1, param2, param3, &result)) + return result; + + return FALSE; +} + +BOOL +Plugin_RegisterUnloadCallback(PluginUnloadCallback callback) +{ + if (NULL == callback) + return FALSE; + + if (NULL == unloadCallbacks) + { + unloadCallbacks = new UnloadCallbackList(); + if (NULL == unloadCallbacks) + return FALSE; + } + + unloadCallbacks->push_back(callback); + return TRUE; +} + +DeviceImageCache * +Plugin_GetImageCache() +{ + return imageCache; +} + +HWND +Plugin_GetEventRelayWindow() +{ + return eventRelayWindow; +} + +const wchar_t * +Plugin_GetDefaultDeviceImage(unsigned int width, unsigned int height) +{ + const ImageInfo *image; + const ImageInfo deviceImages[] = + { + {16, 16, MAKEINTRESOURCE(IDR_GENERIC_DEVICE_16x16_IMAGE)}, + {160, 160, MAKEINTRESOURCE(IDR_GENERIC_DEVICE_160x160_IMAGE)}, + }; + + image = Image_GetBestFit(deviceImages, ARRAYSIZE(deviceImages), width, height); + if (NULL == image) + return NULL; + + return image->path; +} + +HRESULT +Plugin_EnsurePathExist(const wchar_t *path) +{ + unsigned long errorCode; + unsigned int errorMode; + + errorCode = ERROR_SUCCESS; + errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); + + if (0 == CreateDirectory(path, NULL)) + { + errorCode = GetLastError(); + if (ERROR_PATH_NOT_FOUND == errorCode) + { + const wchar_t *block, *cursor; + wchar_t buffer[MAX_PATH] = {0}; + + block = path; + cursor = PathFindNextComponent(block); + + errorCode = (cursor == block || + S_OK != StringCchCopyN(buffer, ARRAYSIZE(buffer), block, (cursor - block))) ? + ERROR_INVALID_NAME : ERROR_SUCCESS; + + block = cursor; + + while(ERROR_SUCCESS == errorCode && + NULL != (cursor = PathFindNextComponent(block))) + { + if (cursor == block || + S_OK != StringCchCatN(buffer, ARRAYSIZE(buffer), block, (cursor - block))) + { + errorCode = ERROR_INVALID_NAME; + } + + if (ERROR_SUCCESS == errorCode && + FALSE == CreateDirectory(buffer, NULL)) + { + errorCode = GetLastError(); + if (ERROR_ALREADY_EXISTS == errorCode) + errorCode = ERROR_SUCCESS; + } + block = cursor; + } + } + + if (ERROR_ALREADY_EXISTS == errorCode) + errorCode = ERROR_SUCCESS; + } + + SetErrorMode(errorMode); + SetLastError(errorCode); + return HRESULT_FROM_WIN32(errorCode); +} + +BOOL +Plugin_GetResourceString(const wchar_t *resourceName, const wchar_t *resourceType, wchar_t *buffer, size_t bufferMax) +{ + unsigned long filenameLength; + + if (NULL == resourceName) + return FALSE; + + if (FAILED(StringCchCopyEx(buffer, bufferMax, L"res://", &buffer, &bufferMax, 0))) + return FALSE; + + filenameLength = GetModuleFileName(Plugin_GetInstance(), buffer, (DWORD)bufferMax); + if (0 == filenameLength || bufferMax == filenameLength) + return FALSE; + + buffer += filenameLength; + bufferMax -= filenameLength; + + if (NULL != resourceType) + { + if (FALSE != IS_INTRESOURCE(resourceType)) + { + if (FAILED(StringCchPrintfEx(buffer, bufferMax, &buffer, &bufferMax, 0, L"/#%d", (int)(INT_PTR)resourceType))) + return FALSE; + } + else + { + if (FAILED(StringCchPrintfEx(buffer, bufferMax, &buffer, &bufferMax, 0, L"/%s", resourceType))) + return FALSE; + } + } + + if (FALSE != IS_INTRESOURCE(resourceName)) + { + if (FAILED(StringCchPrintfEx(buffer, bufferMax, &buffer, &bufferMax, 0, L"/#%d", (int)(INT_PTR)resourceName))) + return FALSE; + } + else + { + if (FAILED(StringCchPrintfEx(buffer, bufferMax, &buffer, &bufferMax, 0, L"/%s", resourceName))) + return FALSE; + } + + return TRUE; +} + +HMENU +Plugin_LoadMenu() +{ + return WASABI_API_LOADMENUW(IDR_PLUGIN_MENU); +} + +BOOL +Plugin_ShowHelp() +{ + BOOL result; + wchar_t buffer[8192] = {0}; + + WASABI_API_LNGSTRINGW_BUF(IDS_PLUGIN_HELP_URL, buffer, ARRAYSIZE(buffer)); + if (L'\0' == buffer[0]) + { + if (FAILED(StringCchCopy(buffer, ARRAYSIZE(buffer), + L"https://help.winamp.com/hc/articles/8106455294612-Winamp-Portables-Guide"))) + { + return FALSE; + } + } + + result = MediaLibrary_ShowHelp(plugin.hwndLibraryParent, buffer); + + return result; +} + +BOOL +Plugin_BeginDiscovery() +{ + if (NULL == WASABI_API_DEVICES || + FAILED(WASABI_API_DEVICES->BeginDiscovery())) + { + return FALSE; + } + + return TRUE; +} + +BOOL +Plugin_OpenUrl(HWND ownerWindow, const wchar_t *url, BOOL forceExternal) +{ + BOOL result; + HCURSOR cursor; + + if (NULL == WASABI_API_WINAMP) + return FALSE; + + cursor = LoadCursor(NULL, IDC_APPSTARTING); + if (NULL != cursor) + cursor = SetCursor(cursor); + + if (FALSE != forceExternal) + { + HINSTANCE instance = ShellExecute(ownerWindow, L"open", url, NULL, NULL, SW_SHOWNORMAL); + result = ((INT_PTR)instance > 32) ? TRUE: FALSE; + } + else + { + HRESULT hr = WASABI_API_WINAMP->OpenUrl(ownerWindow, url); + result = SUCCEEDED(hr); + } + + if (NULL != cursor) + SetCursor(cursor); + + return result; +} + +EXTERN_C __declspec(dllexport) winampMediaLibraryPlugin * +winampGetMediaLibraryPlugin() +{ + return &plugin; +}
\ No newline at end of file |