1173 lines
34 KiB
C++
1173 lines
34 KiB
C++
#include "main.h"
|
|
#include <windowsx.h>
|
|
#include <time.h>
|
|
#include <rpc.h>
|
|
#include "../winamp/gen.h"
|
|
#include "resource.h"
|
|
#include "childwnd.h"
|
|
#include "config.h"
|
|
#include "../winamp/ipc_pe.h"
|
|
#include "../winamp/wa_dlg.h"
|
|
#include "../winamp/strutil.h"
|
|
#include "ml.h"
|
|
#include "ml_ipc.h"
|
|
#include "./folderbrowser.h"
|
|
#include "./mldwm.h"
|
|
|
|
#ifndef _ML_HEADER_IMPMLEMENT
|
|
#define _ML_HEADER_IMPMLEMENT
|
|
#endif // _ML_HEADER_IMPMLEMENT
|
|
#include "ml_ipc_0313.h"
|
|
#undef _ML_HEADER_IMPMLEMENT
|
|
|
|
#include "sendto.h"
|
|
#include "../gen_hotkeys/wa_hotkeys.h"
|
|
#include "MediaLibraryCOM.h"
|
|
#include "../nu/CCVersion.h"
|
|
#include "../nu/AutoWideFn.h"
|
|
#include "../nu/htmlcontainer2.h"
|
|
#include <shlwapi.h>
|
|
|
|
#include "api__gen_ml.h"
|
|
#include <api/service/waServiceFactory.h>
|
|
#include "./navigation.h"
|
|
//#include "./skinnedwnd.h"
|
|
#include "./skinning.h"
|
|
#include "../nu/ServiceWatcher.h"
|
|
#include "MusicID.h"
|
|
#include <tataki/export.h>
|
|
#include <strsafe.h>
|
|
#include "../Winamp/wasabicfg.h"
|
|
|
|
// {6B0EDF80-C9A5-11d3-9F26-00C04F39FFC6}
|
|
static const GUID library_guid =
|
|
{ 0x6b0edf80, 0xc9a5, 0x11d3, { 0x9f, 0x26, 0x0, 0xc0, 0x4f, 0x39, 0xff, 0xc6 } };
|
|
|
|
int m_calling_getfileinfo;
|
|
int IPC_GETMLWINDOW, IPC_LIBRARY_SENDTOMENU, IPC_GET_ML_HMENU;
|
|
int config_use_ff_scrollbars=1, config_use_alternate_colors=0;
|
|
LARGE_INTEGER freq;
|
|
C_Config *g_config;
|
|
|
|
embedWindowState myWindowState;
|
|
prefsDlgRecW myPrefsItem, myPrefsItemPlug;
|
|
|
|
DEFINE_EXTERNAL_SERVICE(api_service, WASABI_API_SVC);
|
|
DEFINE_EXTERNAL_SERVICE(api_application, WASABI_API_APP);
|
|
DEFINE_EXTERNAL_SERVICE(api_language, WASABI_API_LNG);
|
|
DEFINE_EXTERNAL_SERVICE(obj_ombrowser, AGAVE_OBJ_BROWSER);
|
|
DEFINE_EXTERNAL_SERVICE(api_mldb, AGAVE_API_MLDB);
|
|
DEFINE_EXTERNAL_SERVICE(api_syscb, WASABI_API_SYSCB);
|
|
DEFINE_EXTERNAL_SERVICE(api_threadpool, AGAVE_API_THREADPOOL);
|
|
DEFINE_EXTERNAL_SERVICE(api_decodefile, AGAVE_API_DECODE);
|
|
DEFINE_EXTERNAL_SERVICE(wnd_api, WASABI_API_WND);
|
|
DEFINE_EXTERNAL_SERVICE(api_skin, WASABI_API_SKIN);
|
|
DEFINE_EXTERNAL_SERVICE(api_config, AGAVE_API_CONFIG);
|
|
DEFINE_EXTERNAL_SERVICE(api_palette, WASABI_API_PALETTE);
|
|
#ifndef IGNORE_API_GRACENOTE
|
|
DEFINE_EXTERNAL_SERVICE(api_gracenote, AGAVE_API_GRACENOTE);
|
|
#endif
|
|
DEFINE_EXTERNAL_SERVICE(JSAPI2::api_security, AGAVE_API_JSAPI2_SECURITY);
|
|
|
|
ifc_configitem *ieDisableSEH = 0;
|
|
|
|
// wasabi based services for localisation support
|
|
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
|
|
|
|
static ServiceWatcher serviceWatcher;
|
|
#ifndef IGNORE_API_GRACENOTE
|
|
MusicIDCOM musicIDCOM;
|
|
#endif
|
|
|
|
void config();
|
|
void quit();
|
|
int init();
|
|
|
|
BOOL init2(void);
|
|
|
|
extern "C"
|
|
{
|
|
HWND g_hwnd, g_ownerwnd;
|
|
|
|
extern winampGeneralPurposePlugin plugin =
|
|
{
|
|
GPPHDR_VER_U,
|
|
"nullsoft(gen_ml.dll)",
|
|
init,
|
|
config,
|
|
quit,
|
|
};
|
|
};
|
|
HWND g_PEWindow;
|
|
|
|
HMENU wa_main_menu = NULL;
|
|
HMENU wa_windows_menu = NULL;
|
|
HMENU wa_playlists_cmdmenu = NULL;
|
|
HMENU last_playlistsmenu = NULL;
|
|
HMENU last_viewmenu = NULL;
|
|
int last_viewmenu_insert = 0;
|
|
int g_safeMode = 0, sneak = 0;
|
|
|
|
HCURSOR hDragNDropCursor;
|
|
int profile = 0;
|
|
|
|
wchar_t pluginPath[MAX_PATH] = {0};
|
|
static wchar_t preferencesName[128];
|
|
|
|
|
|
HMENU g_context_menus;
|
|
|
|
extern C_ItemList m_plugins;
|
|
extern HNAVCTRL hNavigation;
|
|
|
|
//xp theme disabling shit
|
|
static HMODULE m_uxdll;
|
|
HRESULT (__stdcall *SetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
|
|
BOOL (__stdcall *IsAppThemed)(void);
|
|
|
|
template <class api_T>
|
|
void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
|
|
{
|
|
if (WASABI_API_SVC)
|
|
{
|
|
waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);
|
|
if (factory)
|
|
api_t = reinterpret_cast<api_T *>( factory->getInterface() );
|
|
}
|
|
}
|
|
|
|
template <class api_T>
|
|
void ServiceRelease(api_T *api_t, GUID factoryGUID_t)
|
|
{
|
|
if (WASABI_API_SVC && api_t)
|
|
{
|
|
waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);
|
|
if (factory)
|
|
factory->releaseInterface(api_t);
|
|
}
|
|
api_t = NULL;
|
|
}
|
|
|
|
bool IsVisible()
|
|
{
|
|
return g_hwnd && IsWindowVisible(g_ownerwnd);
|
|
}
|
|
|
|
void MLVisibleChanged(BOOL fVisible)
|
|
{
|
|
static BOOL visible = FALSE;
|
|
if (fVisible != visible)
|
|
{
|
|
visible = fVisible;
|
|
plugin_SendMessage(ML_MSG_MLVISIBLE, visible, 0, 0);
|
|
}
|
|
}
|
|
|
|
BOOL MlWindow_SetMinimizedMode(BOOL fMinimized)
|
|
{
|
|
if (FALSE != fMinimized)
|
|
return SetPropW(g_ownerwnd, L"MLWindow_MinimizedMode", (HANDLE)1);
|
|
|
|
RemovePropW(g_ownerwnd, L"MLWindow_MinimizedMode");
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL MlWindow_IsMinimizedMode(void)
|
|
{
|
|
return (0 != GetPropW(g_ownerwnd, L"MLWindow_MinimizedMode"));
|
|
}
|
|
|
|
void toggleVisible(int closecb)
|
|
{
|
|
BOOL fVisible, fMinimized;
|
|
HWND rootWindow;
|
|
fVisible = (0 != (WS_VISIBLE & GetWindowLongPtrW(g_ownerwnd, GWL_STYLE)));//IsWindowVisible(g_ownerwnd);
|
|
|
|
rootWindow = GetAncestor(g_ownerwnd, GA_ROOT);
|
|
if (NULL == rootWindow || rootWindow == g_ownerwnd)
|
|
{
|
|
rootWindow = (HWND)(HWND)SENDWAIPC(plugin.hwndParent, IPC_GETDIALOGBOXPARENT, 0);
|
|
if (NULL == rootWindow)
|
|
rootWindow = plugin.hwndParent;
|
|
}
|
|
|
|
fMinimized = IsIconic(rootWindow);
|
|
|
|
if (FALSE != fVisible || 1 == closecb)
|
|
{
|
|
if (FALSE == fMinimized && FALSE != fVisible)
|
|
{
|
|
HWND hwndFocus = GetFocus();
|
|
|
|
if (hwndFocus == g_ownerwnd || IsChild(g_ownerwnd, hwndFocus))
|
|
SendMessageW(plugin.hwndParent, WM_COMMAND, WINAMP_NEXT_WINDOW, 0);
|
|
|
|
ShowWindow(g_ownerwnd, SW_HIDE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (init2() && FALSE == fMinimized && FALSE == fVisible)
|
|
{
|
|
ShowWindow(g_ownerwnd, SW_SHOWNORMAL);
|
|
// make sure that we focus the tree to work around some modern skin quirks
|
|
if(closecb != 2)
|
|
{
|
|
SetFocus(NavCtrlI_GetHWND(hNavigation));
|
|
}
|
|
else
|
|
{
|
|
// delay the focusing on loading as some machines are too fast and
|
|
// may cause the wrong view to the selected (root instead of child)
|
|
PostMessage(g_ownerwnd,WM_ML_IPC,0,ML_IPC_FOCUS_TREE);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FALSE != fMinimized && 1 != closecb)
|
|
{
|
|
MlWindow_SetMinimizedMode(TRUE);
|
|
|
|
if (NULL != g_config)
|
|
g_config->WriteInt(L"visible", (FALSE == fVisible));
|
|
|
|
UINT menuFlags = (FALSE == fVisible) ? MF_CHECKED : MF_UNCHECKED;
|
|
menuFlags |= MF_BYCOMMAND;
|
|
|
|
INT szMenu[] = { 0, 4, };
|
|
for (INT i = 0; i < ARRAYSIZE(szMenu); i++)
|
|
{
|
|
HMENU hMenu = (HMENU)SendMessage(plugin.hwndParent, WM_WA_IPC, szMenu[i], IPC_GET_HMENU);
|
|
if (NULL != hMenu)
|
|
CheckMenuItem(hMenu, WA_MENUITEM_ID, menuFlags);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static WNDPROC wa_oldWndProc;
|
|
|
|
static BOOL Winamp_OnIPC(HWND hwnd, UINT uMsg, INT_PTR param, LRESULT *pResult)
|
|
{
|
|
if (IPC_GETMLWINDOW == uMsg && IPC_GETMLWINDOW > 65536)
|
|
{
|
|
if (param == -1 && !g_hwnd) init2();
|
|
*pResult = (LRESULT)g_hwnd;
|
|
return TRUE;
|
|
}
|
|
else if (IPC_LIBRARY_SENDTOMENU == uMsg && IPC_LIBRARY_SENDTOMENU > 65536)
|
|
{
|
|
librarySendToMenuStruct *s = (librarySendToMenuStruct*)param;
|
|
if (!s || s->mode == 0)
|
|
{
|
|
*pResult = 0xFFFFFFFF;
|
|
return TRUE;
|
|
}
|
|
if (s->mode == 1)
|
|
{
|
|
if (!s->ctx[0])
|
|
{
|
|
if (!g_hwnd) init2();
|
|
SendToMenu *stm = new SendToMenu();
|
|
if (s->build_start_id && s->build_end_id)
|
|
{
|
|
stm->buildmenu(s->build_hMenu, s->data_type, s->ctx[1], s->ctx[2], s->build_start_id, s->build_end_id);
|
|
}
|
|
else
|
|
{
|
|
stm->buildmenu(s->build_hMenu, s->data_type, s->ctx[1], s->ctx[2]);
|
|
}
|
|
s->ctx[0] = (intptr_t)stm;
|
|
*pResult = 0xFFFFFFFF;
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if (s->mode == 2)
|
|
{
|
|
SendToMenu *stm = (SendToMenu *)s->ctx[0];
|
|
if (stm && stm->isourcmd(s->menu_id))
|
|
{
|
|
*pResult = 0xFFFFFFFF;
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if (s->mode == 3)
|
|
{
|
|
SendToMenu *stm = (SendToMenu *)s->ctx[0];
|
|
if (stm)
|
|
{
|
|
*pResult = stm->handlecmd(s->hwnd, s->menu_id, s->data_type, s->data);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if (s->mode == 4)
|
|
{
|
|
delete (SendToMenu *)s->ctx[0];
|
|
s->ctx[0] = 0;
|
|
}
|
|
*pResult = TRUE;
|
|
return TRUE;
|
|
}
|
|
else if (IPC_GET_ML_HMENU == uMsg && IPC_GET_ML_HMENU > 65536)
|
|
{
|
|
*pResult = (LRESULT)g_context_menus;
|
|
return TRUE;
|
|
}
|
|
|
|
switch(uMsg)
|
|
{
|
|
case IPC_CB_RESETFONT:
|
|
PostMessageW(g_hwnd, WM_DISPLAYCHANGE, 0, 0);
|
|
break;
|
|
|
|
case IPC_CB_GETTOOLTIPW:
|
|
if (param == 16 && g_config->ReadInt(L"attachlbolt", 0))
|
|
{
|
|
static wchar_t tlStr[64];
|
|
*pResult = (LRESULT)WASABI_API_LNGSTRINGW_BUF(IDS_TOGGLE_LIBRARY,tlStr,64);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case IPC_GET_EXTENDED_FILE_INFO_HOOKABLE:
|
|
if (!m_calling_getfileinfo)
|
|
{
|
|
extendedFileInfoStruct *extendedInfo;
|
|
extendedInfo = (extendedFileInfoStruct*)param;
|
|
if (NULL != extendedInfo &&
|
|
NULL != extendedInfo->filename &&
|
|
NULL != extendedInfo->metadata)
|
|
{
|
|
if (plugin_SendMessage(ML_IPC_HOOKEXTINFO, param, 0, 0))
|
|
{
|
|
*pResult = 1;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE:
|
|
if (!m_calling_getfileinfo)
|
|
{
|
|
extendedFileInfoStructW *extendedInfo;
|
|
extendedInfo = (extendedFileInfoStructW*)param;
|
|
if (NULL != extendedInfo &&
|
|
NULL != extendedInfo->filename &&
|
|
NULL != extendedInfo->metadata)
|
|
{
|
|
if (plugin_SendMessage(ML_IPC_HOOKEXTINFOW, param, 0, 0))
|
|
{
|
|
*pResult = 1;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IPC_HOOK_TITLES:
|
|
if (NULL != param)
|
|
{
|
|
waHookTitleStruct *hookTitle;
|
|
hookTitle = (waHookTitleStruct*)param;
|
|
if (NULL != hookTitle->filename &&
|
|
plugin_SendMessage(ML_IPC_HOOKTITLE, param, 0, 0))
|
|
{
|
|
*pResult = 1;
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IPC_HOOK_TITLESW:
|
|
if (NULL != param)
|
|
{
|
|
waHookTitleStructW *hookTitle;
|
|
hookTitle = (waHookTitleStructW*)param;
|
|
if (NULL != hookTitle->filename &&
|
|
plugin_SendMessage(ML_IPC_HOOKTITLEW, param, 0, 0))
|
|
{
|
|
*pResult = 1;
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IPC_ADD_PREFS_DLG:
|
|
case IPC_ADD_PREFS_DLGW:
|
|
if (param && !((prefsDlgRec*)param)->where)
|
|
{
|
|
prefsDlgRec *p = (prefsDlgRec *)param;
|
|
// we use the dialog proc for the preferences to determine the hinstance of the module and
|
|
// use that to then determine if we set it as a child of the media library preference node
|
|
// it also handles localised versions of the preference pages as the dialog proceedure is
|
|
// going to be in the true plug-in dll and so can be matched to the main ml plugins list!
|
|
MEMORY_BASIC_INFORMATION mbi = {0};
|
|
if(VirtualQuery(p->proc, &mbi, sizeof(mbi)))
|
|
{
|
|
int i = m_plugins.GetSize();
|
|
while (i-- > 0)
|
|
{
|
|
winampMediaLibraryPlugin *mlplugin = (winampMediaLibraryPlugin *)m_plugins.Get(i);
|
|
if (mlplugin->hDllInstance == (HINSTANCE)mbi.AllocationBase)
|
|
{
|
|
p->where = (intptr_t)(INT_PTR)&myPrefsItem;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IPC_CB_ONSHOWWND:
|
|
if ((HWND)param == g_ownerwnd) MLVisibleChanged(TRUE);
|
|
break;
|
|
|
|
case IPC_HOOK_OKTOQUIT:
|
|
{
|
|
if (plugin_SendMessage(ML_MSG_NOTOKTOQUIT, 0, 0, 0))
|
|
{
|
|
*pResult = 0;
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IPC_PLAYING_FILEW:
|
|
plugin_SendMessage(ML_MSG_PLAYING_FILE, param, 0, 0);
|
|
break;
|
|
|
|
case IPC_WRITECONFIG:
|
|
plugin_SendMessage(ML_MSG_WRITE_CONFIG, param, 0, 0);
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static LRESULT WINAPI wa_newWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(uMsg)
|
|
{
|
|
// far from ideal fix but deals with differing plugin load orders (mainly from FAT32 drives)
|
|
// and not being able to unload/clean up properly the scrollbar bitmaps used - DRO 29/09/07
|
|
case WM_CLOSE:
|
|
SkinnedScrollWnd_Quit();
|
|
break;
|
|
case WM_WA_IPC:
|
|
{
|
|
LRESULT result = 0;
|
|
if (Winamp_OnIPC(hwndDlg, (UINT)lParam, (INT_PTR)wParam, &result)) return result;
|
|
break;
|
|
}
|
|
case WM_SIZE:
|
|
if (wParam == SIZE_RESTORED)
|
|
{
|
|
if (FALSE != MlWindow_IsMinimizedMode())
|
|
{
|
|
MlWindow_SetMinimizedMode(FALSE);
|
|
int showCommand = (0 != g_config->ReadInt(L"visible", 1)) ? SW_SHOWNA : SW_HIDE;
|
|
ShowWindow(g_ownerwnd, showCommand);
|
|
}
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
case WM_SYSCOMMAND:
|
|
{
|
|
WORD lowP = LOWORD(wParam);
|
|
if (lowP == WA_MENUITEM_ID || lowP == WINAMP_LIGHTNING_CLICK)
|
|
{
|
|
if (lowP != WINAMP_LIGHTNING_CLICK || g_config->ReadInt(L"attachlbolt", 0))
|
|
{
|
|
toggleVisible();
|
|
return 0;
|
|
}
|
|
}
|
|
#if 0 // no radio - don't delete yet - tag will need to do this in ml_online
|
|
else if (lowP == WINAMP_VIDEO_TVBUTTON) // && g_config->ReadInt("attachtv",1))
|
|
{
|
|
if (!g_hwnd || !IsWindowVisible(g_ownerwnd)) toggleVisible();
|
|
PostMessage(g_ownerwnd, WM_NEXTDLGCTL, (WPARAM)g_hwnd, TRUE);
|
|
HWND hwndTree = GetTreeHWND(g_hwnd);
|
|
HTREEITEM hti = findByParam(hwndTree, TREE_INTERNET_VIDEO, TVI_ROOT);
|
|
if (hti)
|
|
{
|
|
TreeView_SelectItem(hwndTree, hti);
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
// done like this since ml_online can't really subclass winamp to get the notification
|
|
else if (lowP == WINAMP_VIDEO_TVBUTTON)
|
|
{
|
|
if (!g_hwnd || !IsWindowVisible(g_ownerwnd)) toggleVisible();
|
|
HNAVITEM hDefItem = NavCtrlI_FindItemByName(hNavigation, LOCALE_USER_DEFAULT, NICF_INVARIANT_I | NICF_DISPLAY_I | NICF_IGNORECASE_I, L"Shoutcast TV", -1);
|
|
|
|
if(!hDefItem)
|
|
{
|
|
// work with the localised version of the Online Services root (if there...)
|
|
wchar_t OSName[64] = {L"Online Services"};
|
|
WASABI_API_LNG->GetStringFromGUIDW(MlOnlineLangGUID,WASABI_API_ORIG_HINST,1,OSName,64);
|
|
|
|
// just incase the localised dll was there but the file was missing the translation
|
|
if(!lstrcmpiW(OSName,L"Error loading string"))
|
|
lstrcpynW(OSName,L"Online Services",64);
|
|
|
|
hDefItem = NavCtrlI_FindItemByName(hNavigation, LOCALE_USER_DEFAULT, NICF_INVARIANT_I | NICF_DISPLAY_I | NICF_IGNORECASE_I, OSName, -1);
|
|
}
|
|
if (hDefItem)
|
|
{
|
|
NavItemI_Select(hDefItem);
|
|
NavCtrlI_Show(hNavigation, SW_SHOWNA);
|
|
}
|
|
else
|
|
{
|
|
wchar_t titleStr[128] = {0};
|
|
MessageBoxW(hwndDlg,WASABI_API_LNGSTRINGW(IDS_ONLINE_SERVICES_NOT_PRESENT),
|
|
WASABI_API_LNGSTRINGW_BUF(IDS_ERROR_SWITCHING_TO_VIEW,titleStr,128),0);
|
|
}
|
|
return 0;
|
|
}
|
|
if (lowP == WINAMP_SHOWLIBRARY)
|
|
{
|
|
if (!g_hwnd || !IsWindowVisible(g_hwnd))
|
|
toggleVisible((2 == HIWORD(wParam) ? 2 : 0));
|
|
}
|
|
else if (lowP == WINAMP_CLOSELIBRARY)
|
|
{
|
|
if (g_hwnd && IsWindowVisible(g_ownerwnd)) toggleVisible();
|
|
}
|
|
}
|
|
break;
|
|
case WM_DWMCOMPOSITIONCHANGED:
|
|
if (IsWindow(g_hwnd)) PostMessageW(g_hwnd, WM_DWMCOMPOSITIONCHANGED, 0, 0L);
|
|
break;
|
|
}
|
|
|
|
return CallWindowProcW(wa_oldWndProc, hwndDlg, uMsg, wParam, lParam);
|
|
}
|
|
|
|
INT_PTR CALLBACK dialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
BOOL init2(void)
|
|
{
|
|
if (!g_hwnd)
|
|
{
|
|
WADlg_init(plugin.hwndParent);
|
|
|
|
//xp theme disabling shit
|
|
m_uxdll = LoadLibraryA("uxtheme.dll");
|
|
if (m_uxdll)
|
|
{
|
|
IsAppThemed = (BOOL (__stdcall *)(void))GetProcAddress(m_uxdll, "IsAppThemed");
|
|
SetWindowTheme = (HRESULT (__stdcall *)(struct HWND__ *, LPCWSTR , LPCWSTR ))GetProcAddress(m_uxdll, "SetWindowTheme");
|
|
}
|
|
else
|
|
{
|
|
IsAppThemed = NULL;
|
|
SetWindowTheme = NULL;
|
|
}
|
|
|
|
g_context_menus = WASABI_API_LOADMENU(IDR_CONTEXTMENUS);
|
|
|
|
// 02/11/08 DrO
|
|
// defaults were 100,100,500,400 and not visible but these now make it align when opened under
|
|
// a clean install starting with a classic skin and is also visible on start now as with modern
|
|
myWindowState.r.left = g_config->ReadInt(L"mw_xpos", 301);
|
|
myWindowState.r.top = g_config->ReadInt(L"mw_ypos", 29);
|
|
myWindowState.r.right = myWindowState.r.left + g_config->ReadInt(L"mw_width", 500);
|
|
myWindowState.r.bottom = myWindowState.r.top + g_config->ReadInt(L"mw_height", 348);
|
|
SET_EMBED_GUID((&myWindowState), library_guid);
|
|
|
|
g_ownerwnd = (HWND)SendMessage(plugin.hwndParent, WM_WA_IPC, (LPARAM) & myWindowState, IPC_GET_EMBEDIF);
|
|
if (!g_ownerwnd) return FALSE;
|
|
|
|
if (NULL != WASABI_API_APP) WASABI_API_APP->app_registerGlobalWindow(g_ownerwnd);
|
|
|
|
SetWindowTextW(g_ownerwnd, WASABI_API_LNGSTRINGW(IDS_WINAMP_LIBRARY));
|
|
g_hwnd = WASABI_API_CREATEDIALOGW(IDD_MAIN, g_ownerwnd, dialogProc);
|
|
if (!g_hwnd)
|
|
{
|
|
DestroyWindow(g_ownerwnd);
|
|
g_ownerwnd = NULL;
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
wchar_t WINAMP_INI[MAX_PATH] = {0}, WINAMP_INI_DIR[MAX_PATH] = {0};
|
|
MediaLibraryCOM mediaLibraryCOM;
|
|
IDispatch *winampExternal = 0;
|
|
|
|
void TAG_FMT_EXT(const wchar_t *filename, void *f, void *ff, void *p, wchar_t *out, int out_len, int extended)
|
|
{
|
|
waFormatTitleExtended fmt;
|
|
fmt.filename=filename;
|
|
fmt.useExtendedInfo=extended;
|
|
fmt.out = out;
|
|
fmt.out_len = out_len;
|
|
fmt.p = p;
|
|
fmt.spec = 0;
|
|
*(void **)&fmt.TAGFUNC = f;
|
|
*(void **)&fmt.TAGFREEFUNC = ff;
|
|
*out = 0;
|
|
|
|
int oldCallingGetFileInfo=m_calling_getfileinfo;
|
|
m_calling_getfileinfo=1;
|
|
SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&fmt, IPC_FORMAT_TITLE_EXTENDED);
|
|
m_calling_getfileinfo=oldCallingGetFileInfo;
|
|
}
|
|
|
|
wchar_t *itemrecordTagFunc(wchar_t *tag, void * p) //return 0 if not found
|
|
{
|
|
itemRecord *t = (itemRecord *)p;
|
|
char buf[128] = {0};
|
|
char *value = NULL;
|
|
|
|
if (!_wcsicmp(tag, L"artist")) value = t->artist;
|
|
else if (!_wcsicmp(tag, L"album")) value = t->album;
|
|
else if (!_wcsicmp(tag, L"filename")) value = t->filename;
|
|
else if (!_wcsicmp(tag, L"title")) value = t->title;
|
|
else if ( !_wcsicmp( tag, L"ext" ) ) value = t->ext;
|
|
else if (!_wcsicmp(tag, L"year"))
|
|
{
|
|
if (t->year > 0)
|
|
{
|
|
StringCchPrintfA(buf, 128, "%04d", t->year);
|
|
value = buf;
|
|
}
|
|
}
|
|
else if (!_wcsicmp(tag, L"genre")) value = t->genre;
|
|
else if (!_wcsicmp(tag, L"comment")) value = t->comment;
|
|
else if (!_wcsicmp(tag, L"tracknumber") || !_wcsicmp(tag, L"track"))
|
|
{
|
|
if (t->track > 0)
|
|
{
|
|
StringCchPrintfA(buf, 128, "%02d", t->track);
|
|
value = buf;
|
|
}
|
|
}
|
|
else if (!_wcsicmp(tag, L"rating")) value = getRecordExtendedItem(t, "RATING");
|
|
else if (!_wcsicmp(tag, L"playcount")) value = getRecordExtendedItem(t, "PLAYCOUNT");
|
|
else if (!_wcsicmp(tag, L"bitrate")) value = getRecordExtendedItem(t, "BITRATE");
|
|
else
|
|
return 0;
|
|
|
|
if (!value) return reinterpret_cast<wchar_t *>(-1);
|
|
else return AutoWideDup(value);
|
|
}
|
|
|
|
wchar_t *itemrecordWTagFunc(wchar_t *tag, void * p) //return 0 if not found
|
|
{
|
|
itemRecordW *t = (itemRecordW *)p;
|
|
wchar_t buf[128] = {0};
|
|
wchar_t *value = NULL;
|
|
|
|
// TODO: more fields
|
|
if (!_wcsicmp(tag, L"artist")) value = t->artist;
|
|
else if (!_wcsicmp(tag, L"album")) value = t->album;
|
|
else if (!_wcsicmp(tag, L"albumartist")) value = t->albumartist;
|
|
else if (!_wcsicmp(tag, L"category")) value = t->category;
|
|
else if (!_wcsicmp(tag, L"comment")) value = t->comment;
|
|
else if (!_wcsicmp(tag, L"composer")) value = t->composer;
|
|
else if (!_wcsicmp(tag, L"publisher")) value = t->publisher;
|
|
else if (!_wcsicmp(tag, L"filename")) value = t->filename;
|
|
else if (!_wcsicmp(tag, L"title")) value = t->title;
|
|
else if (!_wcsicmp(tag, L"year"))
|
|
{
|
|
if (t->year > 0)
|
|
{
|
|
StringCchPrintfW(buf, 128, L"%04d", t->year);
|
|
value = buf;
|
|
}
|
|
}
|
|
else if (!_wcsicmp(tag, L"genre")) value = t->genre;
|
|
else if (!_wcsicmp(tag, L"comment")) value = t->comment;
|
|
else if (!_wcsicmp(tag, L"tracknumber") || !_wcsicmp(tag, L"track"))
|
|
{
|
|
if (t->track > 0)
|
|
{
|
|
StringCchPrintfW(buf, 128, L"%02d", t->track);
|
|
value = buf;
|
|
}
|
|
}
|
|
else if (!_wcsicmp(tag, L"rating"))
|
|
{
|
|
if (t->rating > 0)
|
|
{
|
|
StringCchPrintfW(buf, 128, L"%d", t->rating);
|
|
value = buf;
|
|
}
|
|
}
|
|
else if (!_wcsicmp(tag, L"playcount"))
|
|
{
|
|
if (t->playcount > 0)
|
|
{
|
|
StringCchPrintfW(buf, 128, L"%d", t->playcount);
|
|
value = buf;
|
|
}
|
|
}
|
|
else if (!_wcsicmp(tag, L"bitrate"))
|
|
{
|
|
if (t->bitrate > 0)
|
|
{
|
|
StringCchPrintfW(buf, 128, L"%d", t->bitrate);
|
|
value = buf;
|
|
}
|
|
}
|
|
else
|
|
return 0;
|
|
|
|
if (!value) return reinterpret_cast<wchar_t *>(-1);
|
|
else return _wcsdup(value);
|
|
}
|
|
|
|
|
|
void fieldTagFuncFree(wchar_t * tag, void * p)
|
|
{
|
|
free(tag);
|
|
}
|
|
|
|
void main_playItemRecordList(itemRecordList *obj, int enqueue, int startplaying)
|
|
{
|
|
if (obj->Size && !enqueue) SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_DELETE);
|
|
|
|
int x;
|
|
wchar_t title[2048]=L"";
|
|
|
|
for (x = 0; x < obj->Size; x ++)
|
|
{
|
|
if (obj->Items[x].filename && *obj->Items[x].filename)
|
|
{
|
|
AutoWideFn wfn( obj->Items[ x ].filename );
|
|
|
|
TAG_FMT_EXT(wfn, itemrecordTagFunc, fieldTagFuncFree, (void*)&obj->Items[x], title, 2048, 1);
|
|
|
|
{
|
|
enqueueFileWithMetaStructW s;
|
|
s.filename = wfn;
|
|
s.title = title;
|
|
s.ext = NULL;
|
|
s.length = obj->Items[x].length;
|
|
SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&s, IPC_PLAYFILEW);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (obj->Size && !enqueue && startplaying) SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_STARTPLAY);
|
|
}
|
|
|
|
void main_playItemRecordListW(itemRecordListW *obj, int enqueue, int startplaying)
|
|
{
|
|
if (obj->Size && !enqueue) SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_DELETE);
|
|
|
|
int x;
|
|
wchar_t title[2048]=L"";
|
|
|
|
for (x = 0; x < obj->Size; x ++)
|
|
{
|
|
if (obj->Items[x].filename && *obj->Items[x].filename)
|
|
{
|
|
TAG_FMT_EXT(obj->Items[x].filename, itemrecordWTagFunc, fieldTagFuncFree, (void*)&obj->Items[x], title, 2048, 1);
|
|
{
|
|
enqueueFileWithMetaStructW s;
|
|
s.filename = obj->Items[x].filename;
|
|
s.title = title;
|
|
s.ext = NULL;
|
|
s.length = obj->Items[x].length;
|
|
SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&s, IPC_PLAYFILEW);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (obj->Size && !enqueue && startplaying) SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_STARTPLAY);
|
|
}
|
|
|
|
void OpenMediaLibraryPreferences()
|
|
{
|
|
SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&myPrefsItem, IPC_OPENPREFSTOPAGE);
|
|
}
|
|
|
|
int AddTreeImageBmp(int resourceId)
|
|
{
|
|
HMLIMGLST hmlilNavigation = MLNavCtrl_GetImageList(g_hwnd);
|
|
MLIMAGESOURCE mlis = {sizeof(MLIMAGESOURCE),0};
|
|
MLIMAGELISTITEM item = {0};
|
|
item.cbSize = sizeof(MLIMAGELISTITEM);
|
|
item.hmlil = hmlilNavigation;
|
|
item.filterUID = MLIF_FILTER1_UID;
|
|
item.pmlImgSource = &mlis;
|
|
|
|
mlis.hInst = WASABI_API_ORIG_HINST;
|
|
mlis.bpp = 24;
|
|
mlis.lpszName = MAKEINTRESOURCEW(resourceId);
|
|
mlis.type = SRC_TYPE_BMP;
|
|
mlis.flags = ISF_FORCE_BPP;
|
|
return MLImageList_Add(g_hwnd, &item);
|
|
}
|
|
|
|
void SkinnedScrollWnd_Init();
|
|
void SkinnedScrollWnd_Quit();
|
|
int init()
|
|
{
|
|
wchar_t g_path[MAX_PATH] = {0};
|
|
QueryPerformanceFrequency(&freq);
|
|
|
|
WASABI_API_SVC = (api_service*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);
|
|
if (!WASABI_API_SVC || WASABI_API_SVC == (api_service *)1)
|
|
return GEN_INIT_FAILURE;
|
|
|
|
HTMLContainer2_Initialize();
|
|
Tataki::Init(WASABI_API_SVC);
|
|
|
|
// loader so that we can get the localisation service api for use
|
|
ServiceBuild(WASABI_API_LNG, languageApiGUID);
|
|
ServiceBuild(WASABI_API_SYSCB, syscbApiServiceGuid);
|
|
ServiceBuild(AGAVE_API_DECODE, decodeFileGUID);
|
|
ServiceBuild(AGAVE_API_JSAPI2_SECURITY, JSAPI2::api_securityGUID);
|
|
ServiceBuild(AGAVE_OBJ_BROWSER, OBJ_OmBrowser);
|
|
#ifndef IGNORE_API_GRACENOTE
|
|
ServiceBuild(AGAVE_API_GRACENOTE, gracenoteApiGUID);
|
|
#endif
|
|
ServiceBuild(WASABI_API_APP, applicationApiServiceGuid);
|
|
ServiceBuild(AGAVE_API_CONFIG, AgaveConfigGUID);
|
|
ServiceBuild(WASABI_API_PALETTE, PaletteManagerGUID);
|
|
ServiceBuild(AGAVE_API_THREADPOOL, ThreadPoolGUID);
|
|
// no guarantee that AGAVE_API_MLDB will be available yet, so we'll start a watcher for it
|
|
serviceWatcher.WatchWith(WASABI_API_SVC);
|
|
serviceWatcher.WatchFor(&AGAVE_API_MLDB, mldbApiGuid);
|
|
serviceWatcher.WatchFor(&WASABI_API_SKIN, skinApiServiceGuid);
|
|
serviceWatcher.WatchFor(&WASABI_API_WND,wndApiServiceGuid);
|
|
WASABI_API_SYSCB->syscb_registerCallback(&serviceWatcher);
|
|
SkinnedScrollWnd_Init();
|
|
|
|
// need to have this initialised before we try to do anything with localisation features
|
|
WASABI_API_START_LANG(plugin.hDllInstance,GenMlLangGUID);
|
|
|
|
// Build plugin description string...
|
|
static wchar_t szDescription[256];
|
|
StringCchPrintfW(szDescription, ARRAYSIZE(szDescription),
|
|
WASABI_API_LNGSTRINGW(IDS_NULLSOFT_ML_STR),
|
|
LOWORD(PLUGIN_VERSION) >> 8,
|
|
PLUGIN_VERSION & 0xFF);
|
|
plugin.description = (char*)szDescription;
|
|
|
|
DispatchInfo dispatchInfo;
|
|
dispatchInfo.name = L"MediaLibrary";
|
|
dispatchInfo.dispatch = &mediaLibraryCOM;
|
|
SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&dispatchInfo, IPC_ADD_DISPATCH_OBJECT);
|
|
|
|
#ifndef IGNORE_API_GRACENOTE
|
|
dispatchInfo.name = L"MusicID";
|
|
dispatchInfo.dispatch = &musicIDCOM;
|
|
SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&dispatchInfo, IPC_ADD_DISPATCH_OBJECT);
|
|
#endif
|
|
|
|
IPC_LIBRARY_SENDTOMENU = (INT)SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"LibrarySendToMenu", IPC_REGISTER_WINAMP_IPCMESSAGE);
|
|
IPC_GETMLWINDOW = (INT)SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"LibraryGetWnd", IPC_REGISTER_WINAMP_IPCMESSAGE);
|
|
IPC_GET_ML_HMENU = (INT)SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"LibraryGetHmenu", IPC_REGISTER_WINAMP_IPCMESSAGE);
|
|
|
|
lstrcpynW(WINAMP_INI, (wchar_t*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GETINIFILEW), MAX_PATH);
|
|
lstrcpynW(WINAMP_INI_DIR, (wchar_t*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GETINIDIRECTORYW), MAX_PATH);
|
|
|
|
PathCombineW(g_path, WINAMP_INI_DIR, L"Plugins");
|
|
CreateDirectoryW(g_path, NULL);
|
|
|
|
wchar_t *dir = (wchar_t*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GETPLUGINDIRECTORYW);
|
|
if (dir == (wchar_t *)1 || dir == 0)
|
|
lstrcpynW(pluginPath, g_path, MAX_PATH);
|
|
else
|
|
lstrcpynW(pluginPath, dir, MAX_PATH);
|
|
|
|
hDragNDropCursor = LoadCursor(plugin.hDllInstance, MAKEINTRESOURCE(ML_IDC_DRAGDROP));
|
|
profile = GetPrivateProfileIntW(L"winamp", L"profile", 0, WINAMP_INI);
|
|
|
|
wchar_t configName[1024 + 32] = {0};
|
|
StringCchPrintfW(configName, 1024 + 32, L"%s\\gen_ml.ini", g_path);
|
|
g_config = new C_Config(configName);
|
|
config_use_ff_scrollbars = g_config->ReadInt(L"ffsb", 1);
|
|
config_use_alternate_colors = g_config->ReadInt(L"alternate_items", 1);
|
|
|
|
int vis = g_config->ReadInt(L"visible", 1);
|
|
wa_main_menu = (HMENU)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_HMENU);
|
|
wa_windows_menu = (HMENU)SendMessage(plugin.hwndParent, WM_WA_IPC, 4, IPC_GET_HMENU);
|
|
wa_playlists_cmdmenu = NULL;
|
|
if (wa_main_menu || wa_windows_menu)
|
|
{
|
|
if (wa_main_menu)
|
|
{
|
|
MENUITEMINFOW i = {sizeof(i), MIIM_ID | MIIM_STATE | MIIM_TYPE, MFT_STRING, vis ? (UINT)MFS_CHECKED : 0, WA_MENUITEM_ID};
|
|
int prior_item = GetMenuItemID(wa_main_menu,9);
|
|
if(prior_item <= 0) prior_item = GetMenuItemID(wa_main_menu,8);
|
|
i.dwTypeData = WASABI_API_LNGSTRINGW(IDS_ML_ALT_L_SHORTCUT);
|
|
|
|
// append before the video menu entry (more reliable than inserting into position '9' in the menu
|
|
InsertMenuItemW(wa_main_menu, prior_item, FALSE, &i);
|
|
SendMessage(plugin.hwndParent, WM_WA_IPC, 1, IPC_ADJUST_OPTIONSMENUPOS);
|
|
}
|
|
|
|
if (wa_windows_menu)
|
|
{
|
|
MENUITEMINFOW i = {sizeof(i), MIIM_ID | MIIM_STATE | MIIM_TYPE, MFT_STRING, vis ? (UINT)MFS_CHECKED : 0, WA_MENUITEM_ID};
|
|
int prior_item = GetMenuItemID(wa_windows_menu,3);
|
|
if(prior_item <= 0) prior_item = GetMenuItemID(wa_windows_menu,2);
|
|
i.dwTypeData = WASABI_API_LNGSTRINGW(IDS_ML_ALT_L_SHORTCUT);
|
|
InsertMenuItemW(wa_windows_menu, prior_item, FALSE, &i);
|
|
SendMessage(plugin.hwndParent, WM_WA_IPC, 1, IPC_ADJUST_FFWINDOWSMENUPOS);
|
|
}
|
|
}
|
|
|
|
// subclass the winamp window to get our leet menu item to work
|
|
wa_oldWndProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(plugin.hwndParent, GWLP_WNDPROC, (LONGX86)(LONG_PTR)wa_newWndProc);
|
|
|
|
myPrefsItem.dlgID = IDD_PREFSFR;
|
|
myPrefsItem.name = WASABI_API_LNGSTRINGW_BUF(IDS_MEDIA_LIBRARY,preferencesName,128);
|
|
myPrefsItem.proc = (void*)PrefsProc;
|
|
myPrefsItem.hInst = WASABI_API_LNG_HINST;
|
|
myPrefsItem.where = -6; // to become root based item
|
|
SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&myPrefsItem, IPC_ADD_PREFS_DLGW);
|
|
|
|
myPrefsItemPlug.dlgID = IDD_MLPLUGINS;
|
|
myPrefsItemPlug.name = preferencesName;
|
|
myPrefsItemPlug.proc = (void*)PluginsProc;
|
|
myPrefsItemPlug.hInst = WASABI_API_LNG_HINST;
|
|
myPrefsItemPlug.where = 1;
|
|
SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&myPrefsItemPlug, IPC_ADD_PREFS_DLGW);
|
|
|
|
g_PEWindow = (HWND)SendMessage(plugin.hwndParent, WM_WA_IPC, IPC_GETWND_PE, IPC_GETWND);
|
|
g_safeMode = SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_IS_SAFEMODE);
|
|
|
|
// we're gonna go ahead and make this directory just to be safe.
|
|
// if a plugin tries to use it as an INI directory but it doesn't exist, things go wrong
|
|
wchar_t mldir[MAX_PATH] = {0};
|
|
PathCombineW(mldir, g_path, L"ml");
|
|
CreateDirectoryW(mldir, NULL);
|
|
PathCombineW(mldir, mldir, L"views");
|
|
CreateDirectoryW(mldir, NULL);
|
|
|
|
//add general hotkey
|
|
int m_genhotkeys_add_ipc = (INT)SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"GenHotkeysAdd", IPC_REGISTER_WINAMP_IPCMESSAGE);
|
|
|
|
static genHotkeysAddStruct ghas = {
|
|
(char*)_wcsdup(WASABI_API_LNGSTRINGW(IDS_ML_GHK_STR)),
|
|
HKF_BRING_TO_FRONT|HKF_UNICODE_NAME,
|
|
WM_COMMAND,
|
|
WA_MENUITEM_ID,
|
|
0,
|
|
// specifically set the id str now so that it'll work correctly with whatever lngpack is in use
|
|
"ML: Show/Hide Media Library"
|
|
};
|
|
if (m_genhotkeys_add_ipc > 65536) PostMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&ghas, m_genhotkeys_add_ipc); //post so gen_hotkeys will catch it if not inited yet
|
|
|
|
init2();
|
|
|
|
// register the art view window classes
|
|
{
|
|
extern void InitSmoothScrollList();
|
|
extern void InitHeaderIconList();
|
|
InitSmoothScrollList();
|
|
InitHeaderIconList();
|
|
RegisterFolderBrowserControl(plugin.hDllInstance);
|
|
}
|
|
|
|
NavCtrlI_BeginUpdate(hNavigation, NUF_LOCK_NONE_I);
|
|
loadMlPlugins();
|
|
|
|
#if 0
|
|
#ifdef _DEBUG
|
|
#define BETA
|
|
#endif
|
|
#ifdef BETA
|
|
sneak = GetPrivateProfileIntW(L"winamp", L"sneak", 0, WINAMP_INI);
|
|
if (!(sneak & 1))
|
|
{
|
|
NAVINSERTSTRUCT nis = {0};
|
|
nis.item.cbSize = sizeof(NAVITEM);
|
|
nis.item.pszText = L"Winamp Labs";
|
|
nis.item.pszInvariant = L"winamp_labs";
|
|
nis.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL | NIMF_STYLE;
|
|
nis.item.iImage = nis.item.iSelectedImage = AddTreeImageBmp(IDB_TREEITEM_LABS);
|
|
nis.item.style = NIS_BOLD;
|
|
nis.hInsertAfter = NCI_FIRST;
|
|
NAVITEM nvItem = {sizeof(NAVITEM),0,NIMF_ITEMID,};
|
|
nvItem.hItem = MLNavCtrl_InsertItem(g_hwnd, &nis);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
NavCtrlI_EndUpdate(hNavigation);
|
|
|
|
if (SW_SHOWMINIMIZED == SENDWAIPC(plugin.hwndParent, IPC_INITIAL_SHOW_STATE, 0))
|
|
{
|
|
MlWindow_SetMinimizedMode(TRUE);
|
|
}
|
|
else if (0 != vis)
|
|
{
|
|
PostMessageW(plugin.hwndParent, WM_COMMAND, MAKEWPARAM(WINAMP_SHOWLIBRARY, 2), 0L);
|
|
}
|
|
|
|
return GEN_INIT_SUCCESS;
|
|
}
|
|
|
|
|
|
void quit()
|
|
{
|
|
serviceWatcher.StopWatching();
|
|
serviceWatcher.Clear();
|
|
|
|
MlWindow_SetMinimizedMode(FALSE);
|
|
|
|
if (g_ownerwnd)
|
|
{
|
|
g_config->WriteInt(L"mw_xpos", myWindowState.r.left);
|
|
g_config->WriteInt(L"mw_ypos", myWindowState.r.top);
|
|
g_config->WriteInt(L"mw_width", myWindowState.r.right - myWindowState.r.left);
|
|
g_config->WriteInt(L"mw_height", myWindowState.r.bottom - myWindowState.r.top);
|
|
|
|
if (NULL != WASABI_API_APP) WASABI_API_APP->app_unregisterGlobalWindow(g_ownerwnd);
|
|
DestroyWindow(g_ownerwnd);
|
|
g_ownerwnd = NULL;
|
|
}
|
|
|
|
// unload any services from ml_ plugins before unloading the plugins
|
|
ServiceRelease(AGAVE_API_MLDB, mldbApiGuid);
|
|
|
|
#ifndef IGNORE_API_GRACENOTE
|
|
musicIDCOM.Quit();
|
|
#endif
|
|
|
|
unloadMlPlugins();
|
|
|
|
WADlg_close();
|
|
|
|
if (g_config)
|
|
{
|
|
delete g_config;
|
|
g_config = NULL;
|
|
}
|
|
|
|
if (m_uxdll)
|
|
{
|
|
FreeLibrary(m_uxdll);
|
|
m_uxdll = NULL;
|
|
}
|
|
SkinnedScrollWnd_Quit();
|
|
#ifndef IGNORE_API_GRACENOTE
|
|
ServiceRelease(AGAVE_API_GRACENOTE, gracenoteApiGUID);
|
|
#endif
|
|
ServiceRelease(WASABI_API_SYSCB, syscbApiServiceGuid);
|
|
ServiceRelease(AGAVE_API_DECODE, decodeFileGUID);
|
|
ServiceRelease(AGAVE_API_JSAPI2_SECURITY, JSAPI2::api_securityGUID);
|
|
ServiceRelease(AGAVE_OBJ_BROWSER, OBJ_OmBrowser);
|
|
ServiceRelease(WASABI_API_LNG, languageApiGUID);
|
|
ServiceRelease(WASABI_API_WND, wndApiServiceGuid);
|
|
ServiceRelease(WASABI_API_SKIN, skinApiServiceGuid);
|
|
ServiceRelease(WASABI_API_APP, applicationApiServiceGuid);
|
|
ServiceRelease(AGAVE_API_CONFIG, AgaveConfigGUID);
|
|
ServiceRelease(WASABI_API_PALETTE, PaletteManagerGUID);
|
|
|
|
Tataki::Quit();
|
|
|
|
HTMLContainer2_Uninitialize();
|
|
|
|
ServiceRelease(AGAVE_API_THREADPOOL, ThreadPoolGUID);
|
|
}
|
|
|
|
void config()
|
|
{
|
|
OpenMediaLibraryPreferences();
|
|
}
|
|
|
|
INT MediaLibrary_TrackPopupEx(HMENU hMenu, UINT fuFlags, INT x, INT y, HWND hwnd, LPTPMPARAMS lptpm, HMLIMGLST hmlil,
|
|
INT width, UINT skinStyle, MENUCUSTOMIZEPROC customProc, ULONG_PTR customParam)
|
|
{
|
|
if (NULL == hMenu)
|
|
return NULL;
|
|
|
|
return IsSkinnedPopupEnabled(FALSE) ?
|
|
TrackSkinnedPopupMenuEx(hMenu, fuFlags, x, y, hwnd, lptpm, hmlil, width, skinStyle, customProc, customParam) :
|
|
TrackPopupMenuEx(hMenu, fuFlags, x, y, hwnd, lptpm);
|
|
}
|
|
|
|
|
|
INT MediaLibrary_TrackPopup(HMENU hMenu, UINT fuFlags, INT x, INT y, HWND hwnd)
|
|
{
|
|
return MediaLibrary_TrackPopupEx(hMenu, fuFlags, x, y, hwnd, NULL, NULL, 0, SMS_USESKINFONT, NULL, NULL);
|
|
}
|
|
|
|
HANDLE MediaLibrary_InitSkinnedPopupHook(HWND hwnd, HMLIMGLST hmlil, INT width, UINT skinStyle, MENUCUSTOMIZEPROC customProc, ULONG_PTR customParam)
|
|
{
|
|
if (FALSE == IsSkinnedPopupEnabled(FALSE))
|
|
return FALSE;
|
|
|
|
return InitSkinnedPopupHook(hwnd, hmlil, width, skinStyle, customProc, customParam);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
MediaLibrary_OpenUrl(HWND ownerWindow, const wchar_t *url, BOOL forceExternal)
|
|
{
|
|
BOOL result;
|
|
HCURSOR cursor;
|
|
|
|
cursor = LoadCursor(NULL, IDC_APPSTARTING);
|
|
if (NULL != cursor)
|
|
cursor = SetCursor(cursor);
|
|
|
|
if (FALSE != forceExternal)
|
|
{
|
|
HINSTANCE instance;
|
|
|
|
if (NULL == ownerWindow)
|
|
ownerWindow = (HWND)SENDWAIPC(plugin.hwndParent, IPC_GETDIALOGBOXPARENT, 0);
|
|
|
|
instance = ShellExecuteW(ownerWindow, L"open", url, NULL, NULL, SW_SHOWNORMAL);
|
|
result = ((INT_PTR)instance > 32) ? TRUE: FALSE;
|
|
}
|
|
else
|
|
{
|
|
SENDWAIPC(plugin.hwndParent, IPC_OPEN_URL, url);
|
|
result = TRUE;
|
|
}
|
|
|
|
if (NULL != cursor)
|
|
SetCursor(cursor);
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
MediaLibrary_OpenHelpUrl(const wchar_t *helpUrl)
|
|
{
|
|
HWND ownerWindow;
|
|
|
|
ownerWindow = (HWND)SENDWAIPC(plugin.hwndParent, IPC_GETDIALOGBOXPARENT, 0);
|
|
|
|
return MediaLibrary_OpenUrl(ownerWindow, helpUrl, FALSE);
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
int getFileInfo(const char *filename, const char *metadata, char *dest, int len)
|
|
{
|
|
m_calling_getfileinfo = 1;
|
|
dest[0] = 0;
|
|
extendedFileInfoStruct efis = {
|
|
filename,
|
|
metadata,
|
|
dest,
|
|
(size_t)len,
|
|
};
|
|
int r = (INT)SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM) & efis, IPC_GET_EXTENDED_FILE_INFO); //will return 1 if wa2 supports this IPC call
|
|
m_calling_getfileinfo = 0;
|
|
return r;
|
|
}
|
|
|
|
__declspec(dllexport) winampGeneralPurposePlugin *winampGetGeneralPurposePlugin()
|
|
{
|
|
return &plugin;
|
|
}
|
|
};
|
|
|