#include "main.h" #include "./service.h" #include "./wasabi.h" #include "./resource.h" #include "../replicant/nu/Autowide.h" #include "../winamp/wa_ipc.h" #include #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(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