123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684 |
- #include "main.h"
- #include "./navigation.h"
- #include "./resource.h"
- #include "./wasabi.h"
- #include "./service.h"
- #include "../omBrowser/browserView.h"
- #include "../winamp/wa_ipc.h"
- #include "../replicant/nu/Autowide.h"
- #include "../gen_ml/ml_ipc_0313.h"
- #include "./local_menu.h"
- #include "../gen_ml/menu.h"
- #include <strsafe.h>
- #define NAVITEM_PREFIX L"nowplaying_svc_"
- #define E_NAVITEM_UNKNOWN E_NOINTERFACE
- typedef struct __NAVENUMRESULT
- {
- HNAVITEM hItem;
- OmService *service;
- UINT serviceId;
- LPCWSTR pszPrefix;
- INT cchPrefix;
- HWND hLibrary;
- NAVITEM itemInfo;
- WCHAR szBuffer[256];
- } NAVENUMRESULT;
- typedef struct __FORCEURLDATA
- {
- UINT serviceId;
- LPWSTR url;
- } FORCEURLDATA;
- #define FORCEURLPROP L"MLNOWPLAYING_FORCEURL"
- static void Navigation_RemoveForceUrl()
- {
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary) return;
- FORCEURLDATA *data = (FORCEURLDATA*)GetProp(hLibrary, FORCEURLPROP);
- RemoveProp(hLibrary, FORCEURLPROP);
- if (NULL != data)
- {
- Plugin_FreeString(data->url);
- free(data);
- }
- }
- static HRESULT Navigation_SetForceUrl(UINT serviceId, LPCWSTR pszUrl)
- {
- if (NULL == pszUrl) return E_INVALIDARG;
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary) return E_FAIL;
- FORCEURLDATA *data = (FORCEURLDATA*)GetProp(hLibrary, FORCEURLPROP);
- if (NULL != data)
- {
- Plugin_FreeString(data->url);
- if (data->serviceId != serviceId)
- {
- free(data);
- data = NULL;
- }
- }
- if (NULL == data)
- {
- data = (FORCEURLDATA*)calloc(1, sizeof(FORCEURLDATA));
- if (NULL == data) return E_OUTOFMEMORY;
- data->serviceId = serviceId;
- }
-
- data->url = Plugin_CopyString(pszUrl);
- if (NULL == data->url || FALSE == SetProp(hLibrary, FORCEURLPROP, data))
- {
- Navigation_RemoveForceUrl();
- return E_FAIL;
- }
- return S_OK;
- }
- static HRESULT Navigation_GetForceUrl(UINT serviceId, const wchar_t **ppszUrl)
- {
- if (NULL == ppszUrl) return E_POINTER;
- *ppszUrl = NULL;
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary) return E_FAIL;
- FORCEURLDATA *data = (FORCEURLDATA*)GetProp(hLibrary, FORCEURLPROP);
- if (NULL == data || data->serviceId != serviceId)
- return E_NOINTERFACE;
- *ppszUrl = data->url;
- return S_OK;
- }
- static INT Navigation_GetIconIndex(LPCWSTR pszImage)
- {
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary) return -1;
- HMLIMGLST hmlilNavigation = MLNavCtrl_GetImageList(hLibrary);
- if (NULL == hmlilNavigation) return -1;
-
- MLIMAGESOURCE mlis;
- ZeroMemory(&mlis, sizeof(mlis));
- mlis.cbSize = sizeof(mlis);
- mlis.hInst = NULL;
- mlis.bpp = 24;
- mlis.lpszName = pszImage;
- mlis.type = SRC_TYPE_PNG;
- mlis.flags = ISF_FORCE_BPP | ISF_PREMULTIPLY | ISF_LOADFROMFILE;
-
- MLIMAGELISTITEM item;
- ZeroMemory(&item, sizeof(item));
- item.cbSize = sizeof(item);
- item.hmlil = hmlilNavigation;
- item.filterUID = MLIF_FILTER3_UID;
- item.pmlImgSource = &mlis;
-
- return MLImageList_Add(hLibrary, &item);
- }
- static HNAVITEM Navigation_CreateItem(HWND hLibrary, HNAVITEM hParent, OmService *service)
- {
- if (NULL == hLibrary || NULL == service)
- return NULL;
- WCHAR szName[256] = {0}, szInvariant[64] = {0};
- if (FAILED(service->GetName(szName, ARRAYSIZE(szName))))
- return NULL;
- if (FAILED(StringCchPrintf(szInvariant, ARRAYSIZE(szInvariant), NAVITEM_PREFIX L"%u", service->GetId())))
- return NULL;
- NAVINSERTSTRUCT nis = {0};
- nis.hInsertAfter = NULL;
- nis.hParent = hParent;
-
- WCHAR szIcon[512] = {0};
- INT iIcon = (SUCCEEDED(service->GetIcon(szIcon, ARRAYSIZE(szIcon)))) ?
- Navigation_GetIconIndex(szIcon) : -1;
-
- nis.item.cbSize = sizeof(NAVITEM);
- nis.item.mask = NIMF_TEXT | NIMF_STYLE | NIMF_TEXTINVARIANT | NIMF_PARAM;
- if (-1 != iIcon)
- nis.item.mask |= (NIMF_IMAGE | NIMF_IMAGESEL);
-
- nis.item.id = 0;
- nis.item.pszText = szName;
- nis.item.pszInvariant = szInvariant;
- nis.item.style = NIS_ALLOWCHILDMOVE;
- nis.item.styleMask = nis.item.style;
- nis.item.lParam = (LPARAM)service;
- nis.item.iImage = iIcon;
- nis.item.iSelectedImage = iIcon;
-
- HNAVITEM hItem = MLNavCtrl_InsertItem(hLibrary, &nis);
- if (NULL != hItem)
- service->AddRef();
-
- return hItem;
- }
- static HNAVITEM Navigation_GetMessageItem(INT msg, INT_PTR param1)
- {
- HWND hLibrary = Plugin_GetLibrary();
- HNAVITEM hItem = (msg < ML_MSG_NAVIGATION_FIRST) ? MLNavCtrl_FindItemById(hLibrary, param1) : (HNAVITEM)param1;
- return hItem;
- }
- static HRESULT Navigation_GetService(HWND hLibrary, HNAVITEM hItem, OmService **service)
- {
- WCHAR szBuffer[64] = {0};
-
- if (NULL == service) return E_POINTER;
- *service = NULL;
- if (NULL == hLibrary || NULL == hItem) return E_INVALIDARG;
- NAVITEM itemInfo = {0};
- itemInfo.cbSize = sizeof(NAVITEM);
- itemInfo.hItem = hItem;
- itemInfo.pszInvariant = szBuffer;
- itemInfo.cchInvariantMax = ARRAYSIZE(szBuffer);
- itemInfo.mask = NIMF_PARAM | NIMF_TEXTINVARIANT;
- if (FALSE == MLNavItem_GetInfo(hLibrary, &itemInfo))
- return E_FAIL;
- INT cchInvariant = lstrlen(szBuffer);
- INT cchPrefix = ARRAYSIZE(NAVITEM_PREFIX) - 1;
- if (cchInvariant <= cchPrefix ||
- CSTR_EQUAL != CompareString(CSTR_INVARIANT, 0, NAVITEM_PREFIX, cchPrefix, szBuffer, cchPrefix))
- {
- return E_NAVITEM_UNKNOWN;
- }
- *service = (OmService*)itemInfo.lParam;
- (*service)->AddRef();
- return S_OK;
- }
- static BOOL CALLBACK Navigation_ItemEnumerator(HNAVITEM hItem, LPARAM param)
- {
- if (NULL == hItem) return TRUE;
- NAVENUMRESULT *result = (NAVENUMRESULT*)param;
- if (NULL == result) return FALSE;
- result->itemInfo .hItem = hItem;
- if (FALSE != MLNavItem_GetInfo(result->hLibrary, &result->itemInfo) &&
- CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, result->itemInfo.pszInvariant, result->cchPrefix,
- result->pszPrefix, result->cchPrefix))
- {
- OmService *service = (OmService*)result->itemInfo.lParam;
- if (NULL != service && service->GetId() == result->serviceId)
- {
- result->hItem = hItem;
- result->service = service;
- service->AddRef();
- return FALSE;
- }
- }
-
- return TRUE;
- }
- static HRESULT Navigation_CreateView(HNAVITEM hItem, HWND hParent, HWND *hView)
- {
- if (NULL == hView) return E_POINTER;
- *hView = NULL;
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary) return E_UNEXPECTED;
- if (NULL == hItem || NULL == hParent) return E_INVALIDARG;
- HRESULT hr;
- OmService *service = NULL;
- hr = Navigation_GetService(hLibrary, hItem, &service);
- if (SUCCEEDED(hr))
- {
- if (NULL == OMBROWSERMNGR)
- hr = E_UNEXPECTED;
- if (SUCCEEDED(hr))
- {
- hr = OMBROWSERMNGR->Initialize(NULL, Plugin_GetWinamp());
- if (SUCCEEDED(hr))
- {
- LPCWSTR forceUrl;
- if (FAILED(Navigation_GetForceUrl(service->GetId(), &forceUrl)))
- forceUrl = NULL;
- hr = OMBROWSERMNGR->CreateView(service, hParent, forceUrl, 0, hView);
- Navigation_RemoveForceUrl();
- }
- }
- wchar_t nowplayingurl[1024] = {0};
- // May 2022 - this service url is dead and would need either fixing up or replacing
- lstrcpynW(nowplayingurl, AutoWide(g_config->ReadString("nowplayingurl", "http://client.winamp.com/nowplaying")), ARRAYSIZE(nowplayingurl));
- service->SetUrl(nowplayingurl[0] ? nowplayingurl : SERVICE_HOMEURL);
- service->Release();
- }
- return hr;
- }
- static BOOL Navigation_GetViewRect(RECT *rect)
- {
- if (NULL == rect) return FALSE;
-
- HWND hWinamp = Plugin_GetWinamp();
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hWinamp || NULL == hLibrary)
- return FALSE;
- HWND hFrame = (HWND)SENDMLIPC(hLibrary, ML_IPC_GETCURRENTVIEW, 0);
- if (NULL == hFrame)
- hFrame = hLibrary;
-
- return GetWindowRect(hFrame, rect);
- }
- static HRESULT Navigation_CreatePopup(HNAVITEM hItem, HWND *hWindow)
- {
- if (NULL == hWindow) return E_POINTER;
- *hWindow = NULL;
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary) return E_UNEXPECTED;
- if (NULL == hItem) return E_INVALIDARG;
- HRESULT hr;
- OmService *service;
- hr = Navigation_GetService(hLibrary, hItem, &service);
- if (SUCCEEDED(hr))
- {
- HWND hWinamp = Plugin_GetWinamp();
- if (NULL == OMBROWSERMNGR)
- hr = E_UNEXPECTED;
- if (SUCCEEDED(hr))
- {
- hr = OMBROWSERMNGR->Initialize(NULL, hWinamp);
- if (SUCCEEDED(hr))
- {
- RECT rect;
- if (FALSE == Navigation_GetViewRect(&rect))
- hr = E_FAIL;
-
- if (SUCCEEDED(hr))
- {
- rect.left += 16;
- rect.top += 16;
-
- hr = OMBROWSERMNGR->CreatePopup(service, rect.left, rect.top,
- rect.right - rect.left, rect.bottom - rect.top, hWinamp, NULL, 0, hWindow);
- }
- }
- }
-
- service->Release();
- }
- return hr;
- }
- static void Navigation_OnDestroy()
- {
- Navigation_RemoveForceUrl();
- if (NULL != OMBROWSERMNGR)
- {
- OMBROWSERMNGR->Finish();
- }
- }
- static void Navigation_OpenPreferences()
- {
- winampMediaLibraryPlugin *(*gp)();
- gp = (winampMediaLibraryPlugin * (__cdecl *)(void))GetProcAddress(GetModuleHandle(L"ml_online.dll"), "winampGetMediaLibraryPlugin");
- if (gp)
- {
- winampMediaLibraryPlugin *mlplugin = gp();
- if (mlplugin && (mlplugin->version >= MLHDR_VER_OLD && mlplugin->version <= MLHDR_VER))
- {
- mlplugin->MessageProc(ML_MSG_CONFIG, 0, 0, 0);
- }
- else
- SendMessage(Plugin_GetWinamp(), WM_WA_IPC, (WPARAM)-1, IPC_OPENPREFSTOPAGE);
- }
- else
- SendMessage(Plugin_GetWinamp(), WM_WA_IPC, (WPARAM)-1, IPC_OPENPREFSTOPAGE);
- }
- static HRESULT Navigation_ShowContextMenu(HNAVITEM hItem, HWND hHost, POINTS pts)
- {
- if (NULL == hItem || NULL == hHost)
- return E_INVALIDARG;
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary) return E_UNEXPECTED;
- HRESULT hr;
- OmService *service;
- hr = Navigation_GetService(hLibrary, hItem, &service);
- if (FAILED(hr)) return hr;
-
- POINT pt;
- POINTSTOPOINT(pt, pts);
- if (-1 == pt.x || -1 == pt.y)
- {
- NAVITEMGETRECT itemRect;
- itemRect.fItem = FALSE;
- itemRect.hItem = hItem;
- if (MLNavItem_GetRect(hLibrary, &itemRect))
- {
- MapWindowPoints(hHost, HWND_DESKTOP, (POINT*)&itemRect.rc, 2);
- pt.x = itemRect.rc.left + 2;
- pt.y = itemRect.rc.top + 2;
- }
- }
-
- HMENU hMenu = Menu_GetMenu(MENU_NAVIGATIONCONTEXT);
- if (NULL != hMenu)
- {
- INT commandId = Menu_TrackPopup(hLibrary, hMenu,
- TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
- pt.x, pt.y, hHost, NULL);
-
- Menu_ReleaseMenu(hMenu, MENU_NAVIGATIONCONTEXT);
- switch(commandId)
- {
- case ID_NAVIGATION_OPEN:
- MLNavItem_Select(hLibrary, hItem);
- break;
-
- case ID_NAVIGATION_OPENNEWWINDOW:
- {
- HWND hWindow;
- if (SUCCEEDED(Navigation_CreatePopup(hItem, &hWindow)))
- {
- ShowWindow(hWindow, SW_SHOWNORMAL);
- }
- }
- break;
- case ID_NAVIGATION_HELP:
- SENDWAIPC(Plugin_GetWinamp(), IPC_OPEN_URL, L"https://help.winamp.com/hc/articles/8105304048660-The-Winamp-Media-Library");
- break;
- case ID_PLUGIN_PREFERENCES:
- Navigation_OpenPreferences();
- break;
- }
- }
- service->Release();
-
- return hr;
- }
- BOOL Navigation_Initialize(void)
- {
- OmService *service;
- HWND hLibrary = Plugin_GetLibrary();
- MLNavCtrl_BeginUpdate(hLibrary, NUF_LOCK_TOP);
- if (SUCCEEDED(OmService::CreateInstance(&service)))
- {
- HNAVITEM hParent = NULL;
- Navigation_CreateItem(hLibrary, hParent, service);
- service->Release();
- }
-
- MLNavCtrl_EndUpdate(hLibrary);
- return TRUE;
- }
- static void Navigation_OnDeleteItem(HNAVITEM hItem)
- {
- if (NULL == hItem) return;
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary) return;
- OmService *service;
- if (SUCCEEDED(Navigation_GetService(hLibrary, hItem, &service)))
- {
-
- NAVITEM itemInfo;
- itemInfo.cbSize = sizeof(NAVITEM);
- itemInfo.hItem = hItem;
- itemInfo.mask = NIMF_PARAM;
- itemInfo.lParam = 0L;
- MLNavItem_SetInfo(hLibrary, &itemInfo);
- service->Release(); // create
- service->Release(); // Navigation_GetService
- }
- }
- BOOL Navigation_ProcessMessage(INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3, INT_PTR *result)
- {
- if (msg == ML_MSG_NO_CONFIG)
- {
- if (!GetModuleHandle(L"ml_online.dll"))
- {
- *result = TRUE;
- return TRUE;
- }
- }
- else if (msg == ML_MSG_CONFIG)
- {
- Navigation_OpenPreferences();
- *result = TRUE;
- return TRUE;
- }
- if (msg < ML_MSG_TREE_BEGIN || msg > ML_MSG_TREE_END)
- return FALSE;
- switch(msg)
- {
- case ML_MSG_TREE_ONCREATEVIEW:
- {
- HWND hView;
- HNAVITEM hItem = Navigation_GetMessageItem(msg, param1);
- HRESULT hr = Navigation_CreateView(hItem, (HWND)param2, &hView);
- if (SUCCEEDED(hr))
- {
- *result = (INT_PTR)hView;
- return TRUE;
- }
- }
- break;
-
- case ML_MSG_NAVIGATION_ONDESTROY:
- Navigation_OnDestroy();
- break;
- case ML_MSG_NAVIGATION_CONTEXTMENU:
- {
- HNAVITEM hItem = Navigation_GetMessageItem(msg, param1);
- HRESULT hr = Navigation_ShowContextMenu(hItem, (HWND)param2, MAKEPOINTS(param3));
- if (SUCCEEDED(hr))
- {
- *result = TRUE;
- return TRUE;
- }
- }
- break;
- case ML_MSG_NAVIGATION_ONDELETE:
- {
- HNAVITEM hItem = Navigation_GetMessageItem(msg, param1);
- Navigation_OnDeleteItem(hItem);
- break;
- }
- }
- return FALSE;
- }
- HNAVITEM Navigation_FindService(UINT serviceId, OmService **serviceOut)
- {
- NAVENUMRESULT result;
- result.hItem = NULL;
- result.service = NULL;
- result.serviceId = serviceId;
- result.pszPrefix = NAVITEM_PREFIX;
- result.cchPrefix = lstrlen(result.pszPrefix);
- result.hLibrary = Plugin_GetLibrary();
- result.itemInfo.cbSize = sizeof(result.itemInfo);
- result.itemInfo.mask = NIMF_TEXTINVARIANT | NIMF_PARAM;
- result.itemInfo.cchInvariantMax = ARRAYSIZE(result.szBuffer);
- result.itemInfo.pszInvariant = result.szBuffer;
- NAVCTRLENUMPARAMS param;
- param.enumProc = Navigation_ItemEnumerator;
- param.hItemStart = NULL;
- param.lParam = (LPARAM)&result;
-
- if (NULL != result.hLibrary)
- MLNavCtrl_EnumItems(result.hLibrary, ¶m);
-
- if (NULL != serviceOut)
- *serviceOut = result.service;
- else if (NULL != result.service)
- result.service->Release();
-
- return result.hItem;
- }
- HRESULT Navigation_ShowService(UINT serviceId, LPCWSTR pszUrl, UINT navFlags)
- {
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary)
- return E_FAIL;
- OmService *service;
- HNAVITEM hItem = Navigation_FindService(serviceId, &service);
- if (NULL == hItem)
- return E_FAIL;
-
- OmService *activeService;
- HWND hView = Navigation_GetActiveView(&activeService);
- if (NULL == hView || activeService->GetId() != service->GetId())
- {
- hView = NULL;
- activeService = NULL;
- }
-
- HRESULT hr = S_OK;
-
- if (NULL != hView)
- {
- if (NULL == pszUrl && 0 != (NAVFLAG_FORCEACTIVE & navFlags))
- pszUrl = NAVIGATE_HOME;
- if (NULL != pszUrl && FALSE == BrowserView_Navigate(hView, pszUrl, TRUE))
- hr = E_FAIL;
- }
- else
- {
- if (NULL != pszUrl)
- hr = Navigation_SetForceUrl(serviceId, pszUrl);
- else
- Navigation_RemoveForceUrl();
-
- if (SUCCEEDED(hr) && FALSE == MLNavItem_Select(hLibrary, hItem))
- {
- Navigation_RemoveForceUrl();
- hr = E_FAIL;
- }
- }
- if (SUCCEEDED(hr))
- {
- if (0 != (NAVFLAG_ENSUREITEMVISIBLE & navFlags))
- MLNavItem_EnsureVisible(hLibrary, hItem);
-
- if (0 != (NAVFLAG_ENSUREMLVISIBLE & navFlags))
- SENDMLIPC(hLibrary, ML_IPC_ENSURE_VISIBLE, 0L);
- }
-
- service->Release();
- if (NULL != activeService)
- activeService->Release();
-
- return hr;
-
- }
- HNAVITEM Navigation_GetActive(OmService **serviceOut)
- {
- HWND hLibrary = Plugin_GetLibrary();
-
- OmService *service;
- HNAVITEM hActive = (NULL != hLibrary) ? MLNavCtrl_GetSelection(hLibrary) : NULL;
- if (NULL == hActive || FAILED(Navigation_GetService(hLibrary, hActive, &service)))
- {
- hActive = NULL;
- service = NULL;
- }
-
- if (NULL != serviceOut)
- *serviceOut = service;
- return hActive;
- }
- HWND Navigation_GetActiveView(OmService **serviceOut)
- {
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary)
- {
- if (NULL != serviceOut) *serviceOut = NULL;
- return NULL;
- }
-
- HWND hView =((HWND)SENDMLIPC(hLibrary, ML_IPC_GETCURRENTVIEW, 0));
- if (NULL != hView)
- {
- WCHAR szBuffer[128] = {0};
- if (!GetClassName(hView, szBuffer, ARRAYSIZE(szBuffer)) || CSTR_EQUAL != CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, szBuffer, -1, L"Nullsoft_omBrowserView", -1))
- hView = NULL;
- }
- OmService *service;
- HNAVITEM hActive = (NULL != hLibrary) ? MLNavCtrl_GetSelection(hLibrary) : NULL;
- if (NULL == hView || FALSE == BrowserView_GetService(hView, &service))
- {
- hView = NULL;
- service = NULL;
- }
- if (NULL != serviceOut)
- *serviceOut = service;
- else if (NULL != service)
- service->Release();
-
- return hView;
- }
|