Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions

View File

@ -0,0 +1,147 @@
#include "./common.h"
#include "./wasabi.h"
#include <strsafe.h>
LPWSTR Plugin_MallocString(size_t cchLen)
{
return (LPWSTR)calloc(cchLen, sizeof(WCHAR));
}
void Plugin_FreeString(LPWSTR pszString)
{
if (NULL != pszString)
{
free(pszString);
}
}
LPWSTR Plugin_ReAllocString(LPWSTR pszString, size_t cchLen)
{
return (LPWSTR)realloc(pszString, sizeof(WCHAR) * cchLen);
}
LPWSTR Plugin_CopyString(LPCWSTR pszSource)
{
if (NULL == pszSource)
return NULL;
INT cchSource = lstrlenW(pszSource) + 1;
LPWSTR copy = Plugin_MallocString(cchSource);
if (NULL != copy)
{
CopyMemory(copy, pszSource, sizeof(WCHAR) * cchSource);
}
return copy;
}
LPSTR Plugin_MallocAnsiString(size_t cchLen)
{
return (LPSTR)calloc(cchLen, sizeof(CHAR));
}
LPSTR Plugin_CopyAnsiString(LPCSTR pszSource)
{
if (NULL == pszSource)
return NULL;
INT cchSource = lstrlenA(pszSource) + 1;
LPSTR copy = Plugin_MallocAnsiString(cchSource);
if (NULL != copy)
{
CopyMemory(copy, pszSource, sizeof(CHAR) * cchSource);
}
return copy;
}
void Plugin_FreeAnsiString(LPSTR pszString)
{
Plugin_FreeString((LPWSTR)pszString);
}
LPSTR Plugin_WideCharToMultiByte(UINT codePage, DWORD dwFlags, LPCWSTR lpWideCharStr, INT cchWideChar, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
{
INT cchBuffer = WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
if (0 == cchBuffer) return NULL;
LPSTR buffer = Plugin_MallocAnsiString(cchBuffer);
if (NULL == buffer) return NULL;
if (0 == WideCharToMultiByte(codePage, dwFlags, lpWideCharStr, cchWideChar, buffer, cchBuffer, lpDefaultChar, lpUsedDefaultChar))
{
Plugin_FreeAnsiString(buffer);
return NULL;
}
return buffer;
}
LPWSTR Plugin_MultiByteToWideChar(UINT codePage, DWORD dwFlags, LPCSTR lpMultiByteStr, INT cbMultiByte)
{
if (NULL == lpMultiByteStr) return NULL;
INT cchBuffer = MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
if (NULL == cchBuffer) return NULL;
if (cbMultiByte > 0) cchBuffer++;
LPWSTR buffer = Plugin_MallocString(cchBuffer);
if (NULL == buffer) return NULL;
if (0 == MultiByteToWideChar(codePage, dwFlags, lpMultiByteStr, cbMultiByte, buffer, cchBuffer))
{
Plugin_FreeString(buffer);
return NULL;
}
if (cbMultiByte > 0)
{
buffer[cchBuffer - 1] = L'\0';
}
return buffer;
}
LPWSTR Plugin_DuplicateResString(LPCWSTR pszResource)
{
return (IS_INTRESOURCE(pszResource)) ?
(LPWSTR)pszResource :
Plugin_CopyString(pszResource);
}
void Plugin_FreeResString(LPWSTR pszResource)
{
if (!IS_INTRESOURCE(pszResource))
Plugin_FreeString(pszResource);
}
HRESULT Plugin_CopyResString(LPWSTR pszBuffer, INT cchBufferMax, LPCWSTR pszString)
{
if (NULL == pszBuffer)
return E_INVALIDARG;
HRESULT hr = S_OK;
if (NULL == pszString)
{
pszBuffer[0] = L'\0';
}
else if (IS_INTRESOURCE(pszString))
{
if (NULL == WASABI_API_LNG)
hr = E_FAIL;
else
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)pszString, pszBuffer, cchBufferMax);
}
else
{
hr = StringCchCopy(pszBuffer, cchBufferMax, pszString);
}
return hr;
}
void Plugin_SafeRelease(IUnknown *pUnk)
{
if (NULL != pUnk)
pUnk->Release();
}

View File

@ -0,0 +1,58 @@
#ifndef NULLSOFT_NOWPLAYING_PLUGIN_COMMON_HEADER
#define NULLSOFT_NOWPLAYING_PLUGIN_COMMON_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../nu/trace.h"
#define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
#ifndef ARRAYSIZE
#define ARRAYSIZE(blah) (sizeof(blah)/sizeof(*blah))
#endif
#ifndef LONGX86
#ifdef _WIN64
#define LONGX86 LONG_PTR
#else /*_WIN64*/
#define LONGX86 LONG
#endif /*_WIN64*/
#endif // LONGX86
#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 MSGRESULT(__hwnd, __result) { SetWindowLongPtrW((__hwnd), DWL_MSGRESULT, ((LONGX86)(LONG_PTR)(__result))); return TRUE; }
#define SENDCMD(__hwnd, __ctrlId, __eventId, __hctrl) (SENDMSG((__hwnd), WM_COMMAND, MAKEWPARAM(__ctrlId, __eventId), (LPARAM)(__hctrl)))
LPWSTR Plugin_MallocString(size_t cchLen);
LPWSTR Plugin_ReAllocString(LPWSTR pszString, size_t cchLen);
void Plugin_FreeString(LPWSTR pszString);
LPWSTR Plugin_CopyString(LPCWSTR pszSource);
LPSTR Plugin_MallocAnsiString(size_t cchLen);
LPSTR Plugin_CopyAnsiString(LPCSTR pszSource);
void Plugin_FreeAnsiString(LPSTR pszString);
LPWSTR Plugin_DuplicateResString(LPCWSTR pszResource);
void Plugin_FreeResString(LPWSTR pszResource);
HRESULT Plugin_CopyResString(LPWSTR pszBuffer, INT cchBufferMax, LPCWSTR pszString);
LPSTR Plugin_WideCharToMultiByte(UINT codePage, DWORD dwFlags, LPCWSTR lpWideCharStr, INT cchWideChar, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);
LPWSTR Plugin_MultiByteToWideChar(UINT codePage, DWORD dwFlags, LPCSTR lpMultiByteStr, INT cbMultiByte);
void Plugin_SafeRelease(IUnknown *pUnk);
#endif //NULLSOFT_NOWPLAYING_PLUGIN_COMMON_HEADER

View File

@ -0,0 +1,110 @@
#include "main.h"
#include "./resource.h"
#include "./external.h"
ExternalDispatch::ExternalDispatch()
: ref(1)
{
}
ExternalDispatch::~ExternalDispatch()
{
}
HRESULT ExternalDispatch::CreateInstance(ExternalDispatch **instance)
{
if (NULL == instance) return E_POINTER;
*instance = new ExternalDispatch();
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
LPCWSTR ExternalDispatch::GetName()
{
return L"NowPlaying";
}
ULONG ExternalDispatch::AddRef(void)
{
return InterlockedIncrement((LONG*)&ref);
}
ULONG ExternalDispatch::Release(void)
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
STDMETHODIMP ExternalDispatch::QueryInterface(REFIID riid, void **ppvObject)
{
if (NULL == ppvObject) return E_POINTER;
if (IsEqualIID(riid, IID_IDispatch))
*ppvObject = static_cast<IDispatch*>(this);
else if (IsEqualIID(riid, IID_IUnknown))
*ppvObject = static_cast<IUnknown*>(this);
else
{
*ppvObject = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
HRESULT ExternalDispatch::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
{
bool unknowns = false;
for (unsigned int i = 0;i != cNames;i++)
{
if (_wcsicmp(rgszNames[i], L"hidden") == 0)
rgdispid[i] = DISPATCH_HIDDEN;
else
{
rgdispid[i] = DISPID_UNKNOWN;
unknowns = true;
}
}
if (unknowns)
return DISP_E_UNKNOWNNAME;
else
return S_OK;
}
HRESULT ExternalDispatch::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
{
return E_NOTIMPL;
}
HRESULT ExternalDispatch::GetTypeInfoCount(unsigned int FAR * pctinfo)
{
return E_NOTIMPL;
}
HRESULT ExternalDispatch::Invoke(DISPID dispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
{
switch(dispId)
{
case DISPATCH_HIDDEN:
if (NULL != pvarResult)
{
HWND hLibrary = Plugin_GetLibrary();
VariantInit(pvarResult);
V_VT(pvarResult) = VT_BOOL;
V_BOOL(pvarResult) = (NULL == hLibrary || FALSE == SENDMLIPC(hLibrary, ML_IPC_IS_VISIBLE, 0));
}
return S_OK;
}
return DISP_E_MEMBERNOTFOUND;
}

View File

@ -0,0 +1,44 @@
#ifndef NULLSOFT_NOWPLAYING_PLUGIN_EXTERNAL_HEADER
#define NULLSOFT_NOWPLAYING_PLUGIN_EXTERNAL_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
class ExternalDispatch : public IDispatch
{
public:
typedef enum
{
DISPATCH_HIDDEN = 777,
} DispatchCodes;
protected:
ExternalDispatch();
~ExternalDispatch();
public:
static HRESULT CreateInstance(ExternalDispatch **instance);
static LPCWSTR GetName();
public:
STDMETHOD(QueryInterface)(REFIID riid, PVOID *ppvObject);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
// *** IDispatch Methods ***
STDMETHOD (GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid);
STDMETHOD (GetTypeInfo)(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo);
STDMETHOD (GetTypeInfoCount)(unsigned int FAR * pctinfo);
STDMETHOD (Invoke)(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr);
protected:
ULONG ref;
};
#endif //NULLSOFT_NOWPLAYING_PLUGIN_EXTERNAL_HEADER

View File

@ -0,0 +1,47 @@
#include "main.h"
#include "service.h"
#include "navigation.h"
#include "handler.h"
#include "../Agave/URIHandler/svc_urihandler.h"
#include <api/service/waservicefactory.h>
#include "api.h"
#include "../ml_online/config.h"
#include "../replicant/nu/Autowide.h"
int NowPlayingURIHandler::ProcessFilename(const wchar_t *filename)
{
if (!_wcsnicmp(filename, L"winamp://Now Playing", 20) || !_wcsnicmp(filename, L"winamp://Now%20Playing", 22))
{
size_t index = 0;
if (filename[12] == L' ')
index = 20;
else
index = 22;
wchar_t fullUrl[1024] = L"http://client.winamp.com/nowplaying";
lstrcpynW(fullUrl, AutoWide(g_config->ReadString("nowplayingurl", "http://client.winamp.com/nowplaying")), ARRAYSIZE(fullUrl));
if (filename[index] != 0)
{
StringCchCatW(fullUrl, 1024, filename + index);
}
Navigation_ShowService(SERVICE_ID, fullUrl, NAVFLAG_FORCEACTIVE | NAVFLAG_ENSUREMLVISIBLE | NAVFLAG_ENSUREITEMVISIBLE);
return HANDLED_EXCLUSIVE;
}
return NOT_HANDLED;
}
int NowPlayingURIHandler::IsMine(const wchar_t *filename)
{
if (!_wcsnicmp(filename, L"winamp://Now Playing", 20 ) || !_wcsnicmp(filename, L"winamp://Now%20Playing", 22))
return HANDLED;
else
return NOT_HANDLED;
}
#define CBCLASS NowPlayingURIHandler
START_DISPATCH;
CB(PROCESSFILENAME, ProcessFilename);
CB(ISMINE, IsMine);
END_DISPATCH;
#undef CBCLASS

View File

@ -0,0 +1,19 @@
#pragma once
#include "../Agave/URIHandler/svc_urihandler.h"
// {7A8BAF83-3995-4550-B15B-12D297A9220E}
static const GUID ml_nowplaying_uri_handler =
{ 0x7a8baf83, 0x3995, 0x4550, { 0xb1, 0x5b, 0x12, 0xd2, 0x97, 0xa9, 0x22, 0xe } };
class NowPlayingURIHandler : public svc_urihandler
{
public:
static const char *getServiceName() { return "Now Playing URI Handler"; }
static GUID getServiceGuid() { return ml_nowplaying_uri_handler; }
int ProcessFilename(const wchar_t *filename);
int IsMine(const wchar_t *filename); // just like ProcessFilename but don't actually process
protected:
RECVS_DISPATCH;
};

View File

@ -0,0 +1,68 @@
#include "main.h"
#include "./local_menu.h"
#include "./wasabi.h"
#include "./resource.h"
#include "./navigation.h"
#include "../gen_ml/ml_ipc_0313.h"
#include "../nu/menuHelpers.h"
#define SUBMENU_NAVIGATIONCONTEXT 0
static HMENU Menu_GetNavigationContext(HMENU baseMenu)
{
HMENU hMenu = GetSubMenu(baseMenu, SUBMENU_NAVIGATIONCONTEXT);
if (NULL == hMenu) return NULL;
hMenu = MenuHelper_DuplcateMenu(hMenu);
if (NULL == hMenu) return NULL;
HNAVITEM hActive = Navigation_GetActive(NULL);
if (NULL != hActive)
{
EnableMenuItem(hMenu, ID_NAVIGATION_OPEN, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED);
}
else
{
EnableMenuItem(hMenu, ID_NAVIGATION_OPEN, MF_BYCOMMAND | MF_ENABLED);
SetMenuDefaultItem(hMenu, ID_NAVIGATION_OPEN, FALSE);
}
return hMenu;
}
HMENU Menu_GetMenu(UINT menuKind)
{
HMENU baseMenu = WASABI_API_LOADMENUW(IDR_CONTEXTMENU);
if (NULL == baseMenu)
return NULL;
switch(menuKind)
{
case MENU_NAVIGATIONCONTEXT:
{
HMENU menu = Menu_GetNavigationContext(baseMenu);
if (!GetModuleHandle(L"ml_online.dll"))
{
if (DeleteMenu(menu, ID_PLUGIN_PREFERENCES, MF_BYCOMMAND))
{
DeleteMenu(menu, 2, MF_BYPOSITION);
}
}
return menu;
}
}
return NULL;
}
BOOL Menu_ReleaseMenu(HMENU hMenu, UINT menuKind)
{
if (NULL == hMenu) return FALSE;
switch(menuKind)
{
case MENU_NAVIGATIONCONTEXT:
return DestroyMenu(hMenu);
}
return FALSE;
}

View File

@ -0,0 +1,15 @@
#ifndef NULLSOFT_NOWPLAYING_PLUGIN_MENU_HEADER
#define NULLSOFT_NOWPLAYING_PLUGIN_MENU_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#define MENU_NAVIGATIONCONTEXT 0
HMENU Menu_GetMenu(UINT menuKind);
BOOL Menu_ReleaseMenu(HMENU hMenu, UINT menuKind);
#endif //NULLSOFT_NOWPLAYING_PLUGIN_MENU_HEADER

View File

@ -0,0 +1,160 @@
#include "main.h"
#include "./navigation.h"
#include "./wasabi.h"
#include "./resource.h"
#include "./external.h"
#include "./wasabiCallback.h"
#include "../nu/MediaLibraryInterface.h"
#include "../replicant/nu/AutoChar.h"
#include "../winamp/wa_ipc.h"
#include "handler.h"
#include "../nu/Singleton.h"
#include "../ml_online/config.h"
#include <strsafe.h>
static NowPlayingURIHandler uri_handler;
static SingletonServiceFactory<svc_urihandler, NowPlayingURIHandler> uri_handler_factory;
static DWORD externalCookie = 0;
static SysCallback *wasabiCallback = NULL;
C_Config *g_config = NULL;
static INT Plugin_Init(void);
static void Plugin_Quit(void);
static INT_PTR Plugin_MessageProc(INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3);
EXTERN_C winampMediaLibraryPlugin plugin =
{
MLHDR_VER,
"nullsoft(ml_nowplaying.dll)",
Plugin_Init,
Plugin_Quit,
Plugin_MessageProc,
0,
0,
0,
};
HINSTANCE Plugin_GetInstance(void)
{
return plugin.hDllInstance;
}
HWND Plugin_GetWinamp(void)
{
return plugin.hwndWinampParent;
}
HWND Plugin_GetLibrary(void)
{
return plugin.hwndLibraryParent;
}
void initConfigCache()
{
wchar_t iniFileName[2048] = {0};
mediaLibrary.BuildPath(L"Plugins\\ml", iniFileName, 2048);
CreateDirectory(iniFileName, NULL);
mediaLibrary.BuildPath(L"Plugins\\ml\\ml_online.ini", iniFileName, 2048);
AutoChar charFn(iniFileName);
g_config = new C_Config(AutoChar(iniFileName));
}
static INT Plugin_Init(void)
{
if (!WasabiApi_Initialize(Plugin_GetInstance()))
return 1;
if (NULL == OMBROWSERMNGR)
{
WasabiApi_Release();
return 2;
}
mediaLibrary.library = plugin.hwndLibraryParent;
mediaLibrary.winamp = plugin.hwndWinampParent;
mediaLibrary.instance = plugin.hDllInstance;
initConfigCache();
if (NULL != WASABI_API_LNG)
{
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;
}
ExternalDispatch *externalDispatch;
if (SUCCEEDED(ExternalDispatch::CreateInstance(&externalDispatch)))
{
DispatchInfo dispatchInfo;
dispatchInfo.id = 0;
dispatchInfo.name =(LPWSTR)externalDispatch->GetName();
dispatchInfo.dispatch = externalDispatch;
if (0 == SENDWAIPC(Plugin_GetWinamp(), IPC_ADD_DISPATCH_OBJECT, (WPARAM)&dispatchInfo))
externalCookie = dispatchInfo.id;
externalDispatch->Release();
}
if(NULL != WASABI_API_SYSCB && NULL == wasabiCallback &&
SUCCEEDED(WasabiCallback::CreateInstance((WasabiCallback**)&wasabiCallback)))
{
WASABI_API_SYSCB->syscb_registerCallback(wasabiCallback, 0);
for (;;)
{
SysCallback *callback = WASABI_API_SYSCB->syscb_enum(SysCallback::BROWSER, 0);
if (NULL == callback || callback == wasabiCallback)
{
if (NULL != callback)
callback->Release();
break;
}
WASABI_API_SYSCB->syscb_deregisterCallback(callback);
WASABI_API_SYSCB->syscb_registerCallback(callback, 0);
callback->Release();
}
}
uri_handler_factory.Register(plugin.service, &uri_handler);
Navigation_Initialize();
return 0;
}
static void Plugin_Quit(void)
{
if (NULL != wasabiCallback)
{
if (NULL != WASABI_API_SYSCB)
WASABI_API_SYSCB->syscb_deregisterCallback(wasabiCallback);
wasabiCallback->Release();
wasabiCallback = NULL;
}
if (0 != externalCookie)
{
HWND hWinamp = Plugin_GetWinamp();
SENDWAIPC(hWinamp, IPC_REMOVE_DISPATCH_OBJECT, (WPARAM)externalCookie);
externalCookie = 0;
}
uri_handler_factory.Deregister(plugin.service);
WasabiApi_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;
}
EXTERN_C __declspec(dllexport) winampMediaLibraryPlugin *winampGetMediaLibraryPlugin()
{
return &plugin;
}

View File

@ -0,0 +1,22 @@
#ifndef NULLSOFT_NOWPLAYING_PLUGIN_MAIN_HEADER
#define NULLSOFT_NOWPLAYING_PLUGIN_MAIN_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include "../gen_ml/ml.h"
#include "./common.h"
#define PLUGIN_VERSION_MAJOR 4
#define PLUGIN_VERSION_MINOR 1
HINSTANCE Plugin_GetInstance(void);
HWND Plugin_GetWinamp(void);
HWND Plugin_GetLibrary(void);
#include "../ml_online/config.h"
extern C_Config *g_config;
#endif //NULLSOFT_NOWPLAYING_PLUGIN_MAIN_HEADER

View File

@ -0,0 +1,99 @@
// 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
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_CONTEXTMENU MENU
BEGIN
POPUP "Navigation"
BEGIN
MENUITEM "&Open", ID_NAVIGATION_OPEN
MENUITEM "Open in &New Window", ID_NAVIGATION_OPENNEWWINDOW
MENUITEM SEPARATOR
MENUITEM "&Preferences", 40006
MENUITEM SEPARATOR
MENUITEM "Help", ID_NAVIGATION_HELP
END
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_PLUGIN_NAME "Nullsoft Now Playing v%d.%02d"
65535 "{7F31F590-6602-45c9-B3F8-F61AE05BD1D3}"
END
STRINGTABLE
BEGIN
IDS_SERVICE_NAME "Now Playing"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,30 @@
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_nowplaying", "ml_nowplaying.vcxproj", "{CB59733D-8D69-4DC4-AB67-C831DAE5A80F}"
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
{CB59733D-8D69-4DC4-AB67-C831DAE5A80F}.Debug|Win32.ActiveCfg = Debug|Win32
{CB59733D-8D69-4DC4-AB67-C831DAE5A80F}.Debug|Win32.Build.0 = Debug|Win32
{CB59733D-8D69-4DC4-AB67-C831DAE5A80F}.Debug|x64.ActiveCfg = Debug|x64
{CB59733D-8D69-4DC4-AB67-C831DAE5A80F}.Debug|x64.Build.0 = Debug|x64
{CB59733D-8D69-4DC4-AB67-C831DAE5A80F}.Release|Win32.ActiveCfg = Release|Win32
{CB59733D-8D69-4DC4-AB67-C831DAE5A80F}.Release|Win32.Build.0 = Release|Win32
{CB59733D-8D69-4DC4-AB67-C831DAE5A80F}.Release|x64.ActiveCfg = Release|x64
{CB59733D-8D69-4DC4-AB67-C831DAE5A80F}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0DF91B23-5CCB-4CD1-8A07-03B96BB9324E}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,280 @@
<?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>{CB59733D-8D69-4DC4-AB67-C831DAE5A80F}</ProjectGuid>
<RootNamespace>ml_nowplaying</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|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>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|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>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>true</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>..\..\..\external_dependencies\vcpkg</VcpkgInstalledDir>
<VcpkgUseStatic>true</VcpkgUseStatic>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>..\..\..\external_dependencies\vcpkg</VcpkgInstalledDir>
<VcpkgUseStatic>true</VcpkgUseStatic>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>..\..\..\external_dependencies\vcpkg</VcpkgInstalledDir>
<VcpkgUseStatic>true</VcpkgUseStatic>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>..\..\..\external_dependencies\vcpkg</VcpkgInstalledDir>
<VcpkgUseStatic>true</VcpkgUseStatic>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..;..\..\..\;..\..\..\wasabi;..\..\..\agave;..\..\..\ombrowser;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TEST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;comctl32.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName).dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)*.dll ..\..\..\..\..\Winamp_$(PlatformShortName)_$(Configuration)\plugins\
xcopy /Y /D $(OutDir)*.pdb ..\..\..\..\..\Winamp_$(PlatformShortName)_$(Configuration)\plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)*.dll ..\..\..\..\..\Winamp_$(PlatformShortName)_$(Configuration)\plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..;..\..\..\;..\..\..\wasabi;..\..\..\agave;..\..\..\ombrowser;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;TEST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;comctl32.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName).dll</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)*.dll ..\..\..\..\..\Winamp_$(PlatformShortName)_$(Configuration)\plugins\
xcopy /Y /D $(OutDir)*.pdb ..\..\..\..\..\Winamp_$(PlatformShortName)_$(Configuration)\plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)*.dll ..\..\..\..\..\Winamp_$(PlatformShortName)_$(Configuration)\plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..;..\..\..\;..\..\..\wasabi;..\..\..\agave;..\..\..\ombrowser;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x601;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;comctl32.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName).dll</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>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)*.dll ..\..\..\..\..\Winamp_$(PlatformShortName)_$(Configuration)\plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)*.dll ..\..\..\..\..\Winamp_$(PlatformShortName)_$(Configuration)\plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..;..\..\..\;..\..\..\wasabi;..\..\..\agave;..\..\..\ombrowser;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_WIN32_WINNT=0x601;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;comctl32.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName).dll</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>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)*.dll ..\..\..\..\..\Winamp_$(PlatformShortName)_$(Configuration)\plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)*.dll ..\..\..\..\..\Winamp_$(PlatformShortName)_$(Configuration)\plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\General\gen_ml\menu.cpp" />
<ClCompile Include="..\ml_online\config.cpp" />
<ClCompile Include="..\..\..\nu\MediaLibraryInterface.cpp" />
<ClCompile Include="..\..\..\nu\menuHelpers.cpp" />
<ClCompile Include="..\..\..\nu\trace.cpp" />
<ClCompile Include="common.cpp" />
<ClCompile Include="external.cpp" />
<ClCompile Include="handler.cpp" />
<ClCompile Include="local_menu.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="navigation.cpp" />
<ClCompile Include="service.cpp" />
<ClCompile Include="wasabi.cpp" />
<ClCompile Include="wasabiCallback.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\General\gen_ml\menu.h" />
<ClInclude Include="..\ml_online\config.h" />
<ClInclude Include="..\..\..\nu\MediaLibraryInterface.h" />
<ClInclude Include="common.h" />
<ClInclude Include="external.h" />
<ClInclude Include="handler.h" />
<ClInclude Include="local_menu.h" />
<ClInclude Include="main.h" />
<ClInclude Include="navigation.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="service.h" />
<ClInclude Include="wasabi.h" />
<ClInclude Include="wasabiCallback.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ml_nowplaying.rc" />
<ResourceCompile Include="png.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\omBrowser\omBrowser.vcxproj">
<Project>{fc74db95-5008-4d22-9147-1c052f43cdd3}</Project>
</ProjectReference>
<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>

View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="common.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\ml_online\config.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="external.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="handler.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="..\nu\MediaLibraryInterface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\gen_ml\menu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\nu\menuHelpers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="navigation.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="service.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\nu\trace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wasabi.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wasabiCallback.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\ml_online\config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="external.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="handler.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="..\nu\MediaLibraryInterface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\gen_ml\menu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="navigation.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="service.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wasabi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wasabiCallback.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="png.rc">
<Filter>Header Files</Filter>
</ResourceCompile>
<ResourceCompile Include="ml_nowplaying.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{a1f12bb1-c2c0-49d3-b74a-5f8bbac3dee6}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{8fef1ee3-d193-47aa-872e-843f5178bcc5}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{f17e7245-8101-4787-b60f-874085ddb8a7}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@ -0,0 +1,684 @@
#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, &param);
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;
}

View File

@ -0,0 +1,27 @@
#ifndef NULLSOFT_NOWPLAYING_PLUGIN_NAVIGATION_HEADER
#define NULLSOFT_NOWPLAYING_PLUGIN_NAVIGATION_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
typedef LPVOID HNAVITEM;
class OmService;
BOOL Navigation_Initialize(void);
BOOL Navigation_ProcessMessage(INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3, INT_PTR *result);
#define NAVFLAG_NORMAL 0x0000
#define NAVFLAG_ENSUREITEMVISIBLE 0x0001
#define NAVFLAG_ENSUREMLVISIBLE 0x0002
#define NAVFLAG_FORCEACTIVE 0x0004
HRESULT Navigation_ShowService(UINT serviceId, LPCWSTR pszUrl, UINT navFlags);
HNAVITEM Navigation_FindService(UINT serviceId, OmService **serviceOut);
HNAVITEM Navigation_GetActive(OmService **serviceOut);
HWND Navigation_GetActiveView(OmService **serviceOut);
#endif //NULLSOFT_NOWPLAYING_PLUGIN_NAVIGATION_HEADER

View File

@ -0,0 +1,7 @@
#include "resource.h"
/////////////////////////////////////////////////////////////////////////////
//
// Data
//
IDR_SERVICE_ICON RCDATA
".\\resources\\serviceIcon.png"

View File

@ -0,0 +1,23 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by ml_nowplaying.rc
//
#define IDS_SERVICE_NAME 1
#define IDR_CONTEXTMENU 101
#define IDR_SERVICE_ICON 20000
#define ID_NAVIGATION_OPENNEWWINDOW 40000
#define ID_NAVIGATION_OPEN 40001
#define ID_NAVIGATION_HELP 40005
#define ID_PLUGIN_PREFERENCES 40006
#define IDS_PLUGIN_NAME 65534
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40007
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

View File

@ -0,0 +1,171 @@
#include "main.h"
#include "./service.h"
#include "./wasabi.h"
#include "./resource.h"
#include "../replicant/nu/Autowide.h"
#include "../winamp/wa_ipc.h"
#include <strsafe.h>
#define IS_INVALIDISPATCH(__disp) (((IDispatch *)1) == (__disp) || NULL == (__disp))
OmService::OmService(UINT nId)
: ref(1), id(nId), name(NULL), url(NULL), icon(NULL)
{
}
OmService::~OmService()
{
Plugin_FreeResString(name);
Plugin_FreeString(url);
Plugin_FreeResString(icon);
}
HRESULT OmService::CreateInstance(OmService **instance)
{
if (NULL == instance) return E_POINTER;
*instance = NULL;
OmService *service = new OmService(SERVICE_ID);
if (NULL == service) return E_OUTOFMEMORY;
wchar_t nowplayingurl[1024] = {0};
lstrcpynW(nowplayingurl, AutoWide(g_config->ReadString("nowplayingurl","")), ARRAYSIZE(nowplayingurl));
service->SetName(MAKEINTRESOURCE(IDS_SERVICE_NAME));
service->SetUrl((nowplayingurl[0] ? nowplayingurl : SERVICE_HOMEURL));
service->SetIcon(MAKEINTRESOURCE(IDR_SERVICE_ICON));
*instance = service;
return S_OK;
}
size_t OmService::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t OmService::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int OmService::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object) return E_POINTER;
if (IsEqualIID(interface_guid, IFC_OmService))
*object = static_cast<ifc_omservice*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
unsigned int OmService::GetId()
{
return id;
}
HRESULT OmService::GetName(wchar_t *pszBuffer, int cchBufferMax)
{
return Plugin_CopyResString(pszBuffer, cchBufferMax, name);
}
HRESULT OmService::GetUrl(wchar_t *pszBuffer, int cchBufferMax)
{
return StringCchCopyEx(pszBuffer, cchBufferMax, url, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
HRESULT OmService::GetIcon(wchar_t *pszBuffer, int cchBufferMax)
{
if (NULL != icon && IS_INTRESOURCE(icon))
{
WCHAR szPath[2*MAX_PATH] = {0};
if (0 == GetModuleFileName(Plugin_GetInstance(), szPath, ARRAYSIZE(szPath)))
return E_FAIL;
return StringCchPrintf(pszBuffer, cchBufferMax, L"res://%s/#%d/#%d", szPath, RT_RCDATA, icon);
}
return StringCchCopyEx(pszBuffer, cchBufferMax, icon, NULL, NULL, STRSAFE_IGNORE_NULLS);
}
HRESULT OmService::GetExternal(IDispatch **ppDispatch)
{
if (NULL == ppDispatch)
return E_POINTER;
*ppDispatch = NULL;
HWND hWinamp = Plugin_GetWinamp();
if (NULL == hWinamp)
return E_UNEXPECTED;
// So far we do not use JSAPI2 in nowplaying
// // try JSAPI2 first
// WCHAR szBuffer[64] = {0};
// if (SUCCEEDED(StringCchPrintfW(szBuffer, ARRAYSIZE(szBuffer), L"%u", id)))
// *ppDispatch = (IDispatch*)SENDWAIPC(hWinamp, IPC_JSAPI2_GET_DISPATCH_OBJECT, (WPARAM)szBuffer);
if (IS_INVALIDISPATCH(*ppDispatch))
{ // try JSAPI1
*ppDispatch = (IDispatch*)SENDWAIPC(hWinamp, IPC_GET_DISPATCH_OBJECT, 0);
if (IS_INVALIDISPATCH(*ppDispatch))
{ // Fail
*ppDispatch = NULL;
return E_FAIL;
}
}
return S_OK;
}
HRESULT OmService::SetName(LPCWSTR pszName)
{
Plugin_FreeResString(name);
name = Plugin_DuplicateResString(pszName);
return S_OK;
}
HRESULT OmService::SetUrl(LPCWSTR pszUrl)
{
Plugin_FreeString(url);
url = Plugin_CopyString(pszUrl);
return S_OK;
}
HRESULT OmService::SetIcon(LPCWSTR pszIcon)
{
Plugin_FreeResString(icon);
icon = Plugin_DuplicateResString(pszIcon);
return S_OK;
}
#define CBCLASS OmService
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
CB(API_GETID, GetId)
CB(API_GETNAME, GetName)
CB(API_GETURL, GetUrl)
CB(API_GETICON, GetIcon)
CB(API_GETEXTERNAL, GetExternal)
END_DISPATCH;
#undef CBCLASS

View File

@ -0,0 +1,53 @@
#ifndef NULLSOFT_NOWPLAYING_PLUGIN_SERVICE_HEADER
#define NULLSOFT_NOWPLAYING_PLUGIN_SERVICE_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include <ifc_omservice.h>
#define SERVICE_ID 101
#define SERVICE_HOMEURL L"http://client.winamp.com/nowplaying?v=5.9&icid=navigationtree"
class OmService : public ifc_omservice
{
protected:
OmService(UINT nId);
~OmService();
public:
static HRESULT CreateInstance(OmService **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_omservice */
unsigned int GetId();
HRESULT GetName(wchar_t *pszBuffer, int cchBufferMax);
HRESULT GetUrl(wchar_t *pszBuffer, int cchBufferMax);
HRESULT GetExternal(IDispatch **ppDispatch);
HRESULT GetIcon(wchar_t *pszBuffer, int cchBufferMax);
public:
HRESULT SetName(LPCWSTR pszName);
HRESULT SetUrl(LPCWSTR pszUrl);
HRESULT SetIcon(LPCWSTR pszIcon);
protected:
RECVS_DISPATCH;
protected:
ULONG ref;
UINT id;
LPWSTR name;
LPWSTR url;
LPWSTR icon;
};
#endif //NULLSOFT_NOWPLAYING_PLUGIN_SERVICE_HEADER

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "../../../Winamp/buildType.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,0,1,0
PRODUCTVERSION WINAMP_PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Winamp SA"
VALUE "FileDescription", "Winamp Media Library Plug-in"
VALUE "FileVersion", "4,0,1,0"
VALUE "InternalName", "Nullsoft Nowplaying"
VALUE "LegalCopyright", "Copyright <20> 2003-2023 Winamp SA"
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
VALUE "OriginalFilename", "ml_nowplaying.dll"
VALUE "ProductName", "Winamp"
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@ -0,0 +1,82 @@
#include "main.h"
#include "./wasabi.h"
#include <api/service/waservicefactory.h>
static ULONG wasabiRef = 0;
api_application *WASABI_API_APP = NULL;
api_language *WASABI_API_LNG = NULL;
JSAPI2::api_security *AGAVE_API_JSAPI2_SECURITY = NULL;
obj_ombrowser *browserManager = NULL;
api_syscb *WASABI_API_SYSCB = NULL;
ifc_omutility *omUtility = NULL;
HINSTANCE WASABI_API_LNG_HINST = NULL;
HINSTANCE WASABI_API_ORIG_HINST = NULL;
EXTERN_C winampMediaLibraryPlugin plugin;
void *Wasabi_QueryInterface(REFGUID interfaceGuid)
{
waServiceFactory *serviceFactory = plugin.service->service_getServiceByGuid(interfaceGuid);
return (NULL != serviceFactory) ? serviceFactory->getInterface() : NULL;
}
void Wasabi_ReleaseInterface(REFGUID interfaceGuid, void *pInstance)
{
waServiceFactory *serviceFactory = plugin.service->service_getServiceByGuid(interfaceGuid);
if (NULL != serviceFactory) serviceFactory->releaseInterface(pInstance);
}
void Wasabi_SafeRelease(Dispatchable *pDisp)
{
if (NULL != pDisp)
pDisp->Release();
}
BOOL WasabiApi_Initialize(HINSTANCE hInstance)
{
WASABI_API_APP = QueryWasabiInterface(api_application, applicationApiServiceGuid);
WASABI_API_SYSCB = QueryWasabiInterface(api_syscb, syscbApiServiceGuid);
WASABI_API_LNG = QueryWasabiInterface(api_language, languageApiGUID);
AGAVE_API_JSAPI2_SECURITY = QueryWasabiInterface(JSAPI2::api_security, JSAPI2::api_securityGUID);
OMBROWSERMNGR = QueryWasabiInterface(obj_ombrowser, OBJ_OmBrowser);
OMUTILITY = QueryWasabiInterface(ifc_omutility, IFC_OmUtility);
if (NULL != WASABI_API_LNG)
WASABI_API_START_LANG(hInstance, MlNowPlayingLangGUID);
WasabiApi_AddRef();
return TRUE;
}
static void WasabiApi_Uninitialize()
{
ReleaseWasabiInterface(applicationApiServiceGuid, WASABI_API_APP);
ReleaseWasabiInterface(syscbApiServiceGuid, WASABI_API_SYSCB);
ReleaseWasabiInterface(languageApiGUID, WASABI_API_LNG);
ReleaseWasabiInterface(JSAPI2::api_securityGUID, AGAVE_API_JSAPI2_SECURITY);
ReleaseWasabiInterface(OBJ_OmBrowser, OMBROWSERMNGR);
ReleaseWasabiInterface(IFC_OmUtility, OMUTILITY);
WASABI_API_APP = NULL;
WASABI_API_LNG = NULL;
AGAVE_API_JSAPI2_SECURITY = NULL;
}
ULONG WasabiApi_AddRef()
{
return InterlockedIncrement((LONG*)&wasabiRef);
}
ULONG WasabiApi_Release()
{
if (0 == wasabiRef)
return wasabiRef;
LONG r = InterlockedDecrement((LONG*)&wasabiRef);
if (0 == r)
{
WasabiApi_Uninitialize();
}
return r;
}

View File

@ -0,0 +1,42 @@
#ifndef NULLSOFT_NOWPLAYING_PLUGIN_WASABI_HEADER
#define NULLSOFT_NOWPLAYING_PLUGIN_WASABI_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <wtypes.h>
#include <api/application/api_application.h>
#define WASABI_API_APP applicationApi
#include "../Agave/Language/api_language.h"
#include "../Winamp/JSAPI2_api_security.h"
extern JSAPI2::api_security *jsapi2_securityApi;
#define AGAVE_API_JSAPI2_SECURITY jsapi2_securityApi
#include <obj_ombrowser.h>
extern obj_ombrowser *browserManager;
#define OMBROWSERMNGR browserManager
#include <api/syscb/api_syscb.h>
#define WASABI_API_SYSCB sysCallbackApi
#include <ifc_omutility.h>
extern ifc_omutility *omUtility;
#define OMUTILITY omUtility
BOOL WasabiApi_Initialize(HINSTANCE hInstance);
ULONG WasabiApi_AddRef(void);
ULONG WasabiApi_Release(void);
void *Wasabi_QueryInterface(REFGUID interfaceGuid);
void Wasabi_ReleaseInterface(REFGUID interfaceGuid, void *pInstance);
#define QueryWasabiInterface(__interfaceType, __interfaceGuid) ((##__interfaceType*)Wasabi_QueryInterface(__interfaceGuid))
#define ReleaseWasabiInterface(__interfaceGuid, __interfaceInstance) (Wasabi_ReleaseInterface((__interfaceGuid), (__interfaceInstance)))
void Wasabi_SafeRelease(Dispatchable *pDisp);
#endif // NULLSOFT_NOWPLAYING_PLUGIN_WASABI_HEADER

View File

@ -0,0 +1,90 @@
#include "main.h"
#include "./wasabiCallback.h"
#include "./navigation.h"
#include "./service.h"
#include "../replicant/nu/Autowide.h"
WasabiCallback::WasabiCallback()
: ref(1)
{
}
WasabiCallback::~WasabiCallback()
{
}
HRESULT WasabiCallback::CreateInstance(WasabiCallback **instance)
{
if (NULL == instance) return E_POINTER;
*instance = new WasabiCallback();
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
size_t WasabiCallback::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t WasabiCallback::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int WasabiCallback::QueryInterface(GUID interface_guid, void **object)
{
return 0;
}
FOURCC WasabiCallback::GetEventType()
{
return SysCallback::BROWSER;
}
int WasabiCallback::Notify(int msg, intptr_t param1, intptr_t param2)
{
switch (msg)
{
case BrowserCallback::ONOPENURL:
return OpenURL(reinterpret_cast<const wchar_t*>(param1), reinterpret_cast<bool *>(param2));
}
return 0;
}
int WasabiCallback::OpenURL(const wchar_t *url, bool *override)
{
WCHAR szTemplate[1024] = L"http://client.winamp.com/nowplaying";
INT cchTemplate = ARRAYSIZE(szTemplate) - 1;
lstrcpynW(szTemplate, AutoWide(g_config->ReadString("nowplayingurl", "http://client.winamp.com/nowplaying")), ARRAYSIZE(szTemplate));
if (NULL != url &&
CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, url, cchTemplate, szTemplate, cchTemplate))
{
if (SUCCEEDED(Navigation_ShowService(SERVICE_ID, url,
NAVFLAG_FORCEACTIVE | NAVFLAG_ENSUREMLVISIBLE | NAVFLAG_ENSUREITEMVISIBLE)))
{
*override = true;
return 1;
}
}
return 0;
}
#define CBCLASS WasabiCallback
START_DISPATCH;
CB(ADDREF, AddRef);
CB(RELEASE, Release);
CB(QUERYINTERFACE, QueryInterface);
CB(SYSCALLBACK_GETEVENTTYPE, GetEventType);
CB(SYSCALLBACK_NOTIFY, Notify);
END_DISPATCH;
#undef CBCLASS

View File

@ -0,0 +1,42 @@
#ifndef NULLSOFT_NOWPLAYING_PLUGIN_WASABI_CALLBACK_HEADER
#define NULLSOFT_NOWPLAYING_PLUGIN_WASABI_CALLBACK_HEADER
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include <api/syscb/callbacks/syscb.h>
#include <api/syscb/callbacks/browsercb.h>
class WasabiCallback : public SysCallback
{
protected:
WasabiCallback();
~WasabiCallback();
public:
static HRESULT CreateInstance(WasabiCallback **instance);
public:
/*** Dispatchable ***/
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/*** SysCallback ***/
FOURCC GetEventType();
int Notify(int msg, intptr_t param1 = 0, intptr_t param2 = 0);
protected:
// set *override = true to prevent the URL from being opened
// leave it alone otherwise (in case someone else wanted to override it)
int OpenURL(const wchar_t *url, bool *override);
protected:
RECVS_DISPATCH;
protected:
ULONG ref;
};
#endif //NULLSOFT_NOWPLAYING_PLUGIN_WASABI_CALLBACK_HEADER