mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-12-18 20:15:51 +01:00
3527 lines
108 KiB
C++
3527 lines
108 KiB
C++
#include "precomp__gen_ff.h"
|
||
#include <windows.h>
|
||
#include <commctrl.h>
|
||
|
||
#include "main.h"
|
||
#include "resource.h"
|
||
#include "prefs.h"
|
||
#include "wa2frontend.h"
|
||
#include "wa2groupdefs.h"
|
||
#include "wa2wndembed.h"
|
||
#include "wa2cfgitems.h"
|
||
#include "wa2coreactions.h"
|
||
#include "wa2pledit.h"
|
||
#include "embedwndguid.h"
|
||
#include "gen_ff_ipc.h"
|
||
#include "fsmonitor.h"
|
||
#include <api/wnd/wndclass/foreignwnd.h>
|
||
#include "../winamp/wa_ipc.h"
|
||
#include "../gen_hotkeys/wa_hotkeys.h"
|
||
#include <api/script/objects/c_script/c_group.h>
|
||
#include <api/script/objects/c_script/c_text.h>
|
||
|
||
#include <api/apiinit.h>
|
||
#include <api/wnd/rootwnd.h>
|
||
#include <api/script/objects/guiobject.h>
|
||
#include <api/core/coreactions.h>
|
||
#include "menuactions.h"
|
||
#include <api/wnd/wndclass/oswndhost.h>
|
||
#include <api/script/scriptobj.h>
|
||
#include <api/service/svcs/svc_wndcreate.h>
|
||
#include <bfc/reentryfilter.h>
|
||
#include <api/skin/skinparse.h>
|
||
#include <api/wndmgr/skinembed.h>
|
||
#include <api/skin/widgets/xuiwndholder.h>
|
||
#include <api/skin/widgets/text.h>
|
||
#include <api/script/scriptmgr.h>
|
||
#include <api/wac/compon.h>
|
||
#include <api/application/version.h>
|
||
#include <bfc/parse/pathparse.h>
|
||
#include <tataki/blending/blending.h>
|
||
#include "skininfo.h"
|
||
#include <api/skin/guitree.h>
|
||
|
||
#include <bfc/wasabi_std_wnd.h>
|
||
|
||
#include "wa2core.h"
|
||
#include <api/locales/xlatstr.h>
|
||
|
||
#include <api/wndmgr/gc.h>
|
||
#include <api/syscb/callbacks/gccb.h>
|
||
#include <api/script/vcpu.h>
|
||
#include <tataki/canvas/bltcanvas.h>
|
||
|
||
#include "../nu/AutoWide.h"
|
||
#include <shlwapi.h>
|
||
#include <windowsx.h>
|
||
//wtf?
|
||
#define _WAFE_H_
|
||
#define ___HOTAMP3_H___
|
||
#include "../gen_hotkeys/hotkey.h"
|
||
|
||
int embedCreateProc(embedWindowState *p, embedEnumStruct *parms);
|
||
|
||
DECLARE_MODULE_SVCMGR;
|
||
|
||
#define VERSION L"1.55"
|
||
//#define VIDDEBUG
|
||
//#define DEBUG_CAPTURES
|
||
|
||
#include "../gen_ml/ml_ipc.h"
|
||
librarySendToMenuStruct mainSendTo;
|
||
|
||
#include "../Agave/Language/api_language.h"
|
||
// wasabi based services for localisation support
|
||
api_language *WASABI_API_LNG = 0;
|
||
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST;
|
||
static wchar_t szDescription[256];
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
|
||
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
|
||
|
||
#define ID_FILE_SHOWLIBRARY 40379
|
||
#define WINAMP_OPTIONS_PREFS 40012
|
||
#define WINAMP_HELP_ABOUT 40041
|
||
#define WINAMP_LIGHTNING_CLICK 40339
|
||
#define WINAMP
|
||
#define UPDATE_EGG 0xC0DE+2
|
||
#define VIEWPORT 0xC0DE+3
|
||
static int DEFERREDCALLBACKMSG;
|
||
static int UPDATEDIALOGBOXPARENTMSG;
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void config();
|
||
void quit();
|
||
int init();
|
||
void quit_inst();
|
||
void init_inst();
|
||
void ToggleLayout(const wchar_t *containerName);
|
||
void RestoreClassicWinamp(int was_loaded);
|
||
extern "C" winampGeneralPurposePlugin plugin =
|
||
{
|
||
GPPHDR_VER_U,
|
||
"nullsoft(gen_ff.dll)",
|
||
init,
|
||
config,
|
||
quit,
|
||
};
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
|
||
int wantContainerInMenu(Container *cont)
|
||
{
|
||
wchar_t tmpBuf[96] = {0};
|
||
GUID g = cont->getGUID();
|
||
if (WCSCASEEQLSAFE(cont->getId(), L"main")) return 0;
|
||
if (cont->getNoMenu()) return 0;
|
||
if (g == pleditWndGuid) return 0;
|
||
if (g == videoWndGuid) return 0;
|
||
if (g == avs_guid) return 0;
|
||
if (g == library_guid) return 0;
|
||
if (WCSCASEEQLSAFE(cont->getName(), L":componenttitle")) return 0;
|
||
if (WCSCASEEQLSAFE(cont->getName(), L"Playlist Editor") || WCSCASEEQLSAFE(cont->getName(), L"Playlist") || WCSCASEEQLSAFE(cont->getId(), L"pledit")) return 0;
|
||
if (WCSCASEEQLSAFE(cont->getName(), L"Video Window") || WCSCASEEQLSAFE(cont->getName(), L"Video") || WCSCASEEQLSAFE(cont->getId(), L"Video")) return 0;
|
||
if (WCSCASEEQLSAFE(cont->getName(), WASABI_API_LNG->GetStringFromGUIDW(GenMlLangGUID,plugin.hDllInstance,18)) ||
|
||
WCSCASEEQLSAFE(cont->getName(), L"Media Library") ||
|
||
WCSCASEEQLSAFE(cont->getId(), L"Library") ||
|
||
WCSCASEEQLSAFE(cont->getName(),WASABI_API_LNGSTRINGW_BUF(IDS_MEDIA_LIBRARY,tmpBuf,96))) return 0;
|
||
if (WCSCASEEQLSAFE(cont->getName(), L"AVS") || WCSCASEEQLSAFE(cont->getName(), WASABI_API_LNGSTRINGW(IDS_VISUALIZATIONS)) || WCSCASEEQLSAFE(cont->getName(), L"Vis") || WCSCASEEQLSAFE(cont->getId(), L"Avs") || WCSCASEEQLSAFE(cont->getId(), L"Vis")) return 0;
|
||
return 1;
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
|
||
api_playlists *AGAVE_API_PLAYLISTS = 0;
|
||
api_playlistmanager *AGAVE_API_PLAYLISTMANAGER = 0;
|
||
api_albumart *AGAVE_API_ALBUMART = 0;
|
||
api_downloadManager *WAC_API_DOWNLOADMANAGER = 0;
|
||
api_colorthemes *WASABI_API_COLORTHEMES = 0;
|
||
api_palette *WASABI_API_PALETTE = 0;
|
||
api_threadpool *WASABI_API_THREADPOOL = 0;
|
||
|
||
StringW m_lastskin_nam, m_lastskin_dir;
|
||
|
||
inline int lumidiff(int a, int b) {
|
||
int r1 = (a & 0xFF0000) >> 16;
|
||
int r2 = (b & 0xFF0000) >> 16;
|
||
int g1 = (a & 0xFF00) >> 8;
|
||
int g2 = (b & 0xFF00) >> 8;
|
||
int b1 = a & 0xFF;
|
||
int b2 = b & 0xFF;
|
||
return MIN((ABS(r1 - r2), ABS(g1 - g2)), ABS(b1 - b2));
|
||
}
|
||
|
||
static void doplaylistcolors()
|
||
{
|
||
int interpolate = 0;
|
||
if (SkinParser::getSkinVersion()*10 < 10) interpolate = 1;
|
||
|
||
// update colors
|
||
int buf[6] = {0};
|
||
waSetPlColorsStruct s = {0, };
|
||
extern COLORREF getWindowBackground(COLORREF *);
|
||
COLORREF windowbackground;
|
||
buf[5] = getWindowBackground(&windowbackground); // auto inverted
|
||
|
||
int need_cols = 1, need_bms = 1;
|
||
|
||
if (!m_lastskin_dir.isempty())
|
||
{
|
||
StringPathCombine bitmapfilename(m_lastskin_dir, L"pledit.bmp");
|
||
HANDLE h = CreateFileW(bitmapfilename, 0, 0, 0, OPEN_EXISTING, 0, 0);
|
||
if (h != INVALID_HANDLE_VALUE)
|
||
{
|
||
CloseHandle(h);
|
||
need_bms = 0;
|
||
}
|
||
|
||
bitmapfilename = StringPathCombine(m_lastskin_dir, L"pledit.txt");
|
||
h = CreateFileW(bitmapfilename, 0, 0, 0, OPEN_EXISTING, 0, 0);
|
||
if (h != INVALID_HANDLE_VALUE)
|
||
{
|
||
CloseHandle(h);
|
||
need_cols = 0;
|
||
}
|
||
}
|
||
|
||
if (need_cols)
|
||
{
|
||
s.numElems = 6;
|
||
s.elems = buf;
|
||
|
||
// list background
|
||
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.background"))
|
||
buf[2] = SkinColor(L"wasabi.list.background") & 0xFFFFFF;
|
||
else
|
||
buf[2] = RGBTOBGR(WASABI_API_SKIN->skin_getBitmapColor(L"wasabi.list.background")) & 0xFFFFFF; // inverted coz coming from bitmap
|
||
|
||
// normal text
|
||
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text"))
|
||
buf[0] = SkinColor(L"wasabi.list.text") & 0xFFFFFF;
|
||
else
|
||
buf[0] = SkinColor(L"wasabi.edit.text") & 0xFFFFFF;
|
||
|
||
if (interpolate)
|
||
{
|
||
int c = buf[0];
|
||
c = lumidiff(c, buf[2]) < 0x1F ? Blenders::BLEND_AVG(buf[0], 0xFF7F7F7F) : c;
|
||
c = lumidiff(c, buf[2]) < 0x1F ? Blenders::BLEND_AVG(buf[0], 0xFF101010) : c;
|
||
buf[0] = c & 0xFFFFFF;
|
||
}
|
||
|
||
COLORREF selected;
|
||
|
||
// selected items background
|
||
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text.selected.background"))
|
||
{
|
||
selected = SkinColor(L"wasabi.list.text.selected.background");
|
||
buf[3] = selected;
|
||
}
|
||
else
|
||
{
|
||
// inverted twice, see bellow
|
||
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.item.selected"))
|
||
selected = RGBTOBGR(SkinColor(L"wasabi.list.item.selected"));
|
||
else
|
||
selected = RGBTOBGR(SkinColor(SKINCOLOR_TREE_SELITEMBKG));
|
||
|
||
COLORREF col = RGBTOBGR(SkinColor(SKINCOLOR_LIST_COLUMNBKG));
|
||
int a = MAX((col & 0xFF0000) >> 16, MAX((col & 0xFF00) >> 8, col & 0xFF));
|
||
col = a < 0x1F ? Blenders::BLEND_AVG(windowbackground, 0xFF000000) : col;
|
||
int listbkg = RGBTOBGR(buf[2]);
|
||
selected = lumidiff(selected, listbkg) < 0x2F ? Blenders::BLEND_AVG(windowbackground, 0xFF7F7F7F) : selected;
|
||
selected = lumidiff(selected, listbkg) < 0x2F ? Blenders::BLEND_AVG(listbkg, 0xFF7F7F7F) : selected;
|
||
selected = lumidiff(selected, listbkg) < 0x2F ? Blenders::BLEND_AVG(windowbackground, 0xFFF0F0F0) : selected;
|
||
selected = lumidiff(selected, listbkg) < 0x2F ? Blenders::BLEND_AVG(listbkg, 0xFFF0F0F0) : selected;
|
||
selected = lumidiff(selected, listbkg) < 0x2F ? Blenders::BLEND_AVG(col, 0xFFF0F0F0) : selected;
|
||
selected = lumidiff(selected, listbkg) < 0x2F ? Blenders::BLEND_AVG(col, 0xFF101010) : selected;
|
||
selected = lumidiff(selected, RGBTOBGR(buf[0])) < 0x1F ? Blenders::BLEND_AVG(selected, 0xFF101010) : selected;
|
||
selected = lumidiff(selected, RGBTOBGR(buf[0])) < 0x1F ? Blenders::BLEND_AVG(selected, 0xFFF0F0F0) : selected;
|
||
selected &= 0xFFFFFF;
|
||
buf[3] = RGBTOBGR(selected);
|
||
}
|
||
|
||
// active text
|
||
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text.current"))
|
||
buf[1] = SkinColor(L"wasabi.list.text.current");
|
||
else
|
||
{
|
||
COLORREF act = Blenders::BLEND_AVG(selected, buf[0]);
|
||
act = (lumidiff(act, buf[0]) < 0x3F || lumidiff(act, buf[2]) < 0x2F) ? Blenders::BLEND_AVG(buf[2], 0xFFFFFFFF) : act;
|
||
act = (lumidiff(act, buf[0]) < 0x3F || lumidiff(act, buf[2]) < 0x2F) ? Blenders::BLEND_AVG(buf[2], 0xFF101010) : act;
|
||
act = (lumidiff(act, buf[0]) < 0x3F || lumidiff(act, buf[2]) < 0x2F) ? Blenders::BLEND_AVG(selected, buf[0]) : act;
|
||
act = (lumidiff(act, buf[0]) < 0x3F || lumidiff(act, buf[2]) < 0x2F) ? Blenders::BLEND_AVG(selected, buf[2]) : act;
|
||
act = (lumidiff(act, buf[0]) < 0x3F || lumidiff(act, buf[2]) < 0x2F) ? Blenders::BLEND_AVG(buf[0], buf[2]) : act;
|
||
buf[1] = act & 0xFFFFFF;
|
||
}
|
||
}
|
||
|
||
if (need_bms)
|
||
{
|
||
BltCanvas c(280, 186);
|
||
|
||
c.fillBits(windowbackground); // already inverted
|
||
|
||
void blitButtonToCanvas(int w, int h, int state, const wchar_t *overlayelement, int xpos, int ypos, BltCanvas *c);
|
||
|
||
blitButtonToCanvas(8, 18, 0, L"wasabi.scrollbar.vertical.grip", 52, 53, &c);
|
||
blitButtonToCanvas(8, 18, 1, L"wasabi.scrollbar.vertical.grip", 61, 53, &c);
|
||
|
||
int xpos, ypos;
|
||
//w=8,h=29
|
||
int cols[2];
|
||
int *fb = (int*)c.getBits() + 280 * 42;
|
||
|
||
// inverted colors because going into bitmap
|
||
|
||
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.scrollbar.background.inverted"))
|
||
cols[0] = RGBTOBGR(SkinColor(L"wasabi.scrollbar.background.inverted"));
|
||
else
|
||
{
|
||
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.column.empty"))
|
||
cols[0] = RGBTOBGR(SkinColor(L"wasabi.list.column.empty"));
|
||
else
|
||
{
|
||
COLORREF col = SkinColor(SKINCOLOR_LIST_COLUMNBKG);
|
||
int a = MAX((col & 0xFF0000) >> 16, MAX((col & 0xFF00) >> 8, col & 0xFF));
|
||
col = a < 0x1F ? Blenders::BLEND_AVG(windowbackground, 0xFF000000) : col;
|
||
cols[0] = RGBTOBGR(Blenders::BLEND_AVG(col, 0xFF000000));
|
||
}
|
||
}
|
||
|
||
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.border.sunken"))
|
||
cols[1] = RGBTOBGR(SkinColor(L"wasabi.border.sunken"));
|
||
else
|
||
{
|
||
int a = MAX((windowbackground & 0xFF0000) >> 16, MAX((windowbackground & 0xFF00) >> 8, windowbackground & 0xFF));
|
||
cols[1] = Blenders::BLEND_AVG(windowbackground, a > 0xE0 ? 0xFF000000 : 0xFFFFFFFF);
|
||
}
|
||
|
||
for (ypos = 42;ypos < 42 + 29; ypos ++)
|
||
{
|
||
for (xpos = 36; xpos < 36 + 8; xpos ++)
|
||
{
|
||
fb[xpos] = cols[(xpos == 36 || xpos == 36 + 8 - 1)];
|
||
}
|
||
fb += 280;
|
||
}
|
||
|
||
extern HBITMAP CreateBitmapDIB(int w, int h, int planes, int bpp, void *data);
|
||
s.bm = CreateBitmapDIB(280, 186, 1, 32, c.getBits());
|
||
}
|
||
if (s.bm || s.elems) SendMessageW(wa2.getMainWindow(), WM_WA_IPC, (WPARAM)&s, IPC_SETPLEDITCOLORS);
|
||
}
|
||
|
||
static prefsDlgRecW ffPrefsItem;
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
|
||
// a guid for our app : {4BE592C7-6937-426a-A388-ACF0EBC88E93}
|
||
static const GUID GEN_FREEFORM =
|
||
{ 0x4be592c7, 0x6937, 0x426a, { 0xa3, 0x88, 0xac, 0xf0, 0xeb, 0xc8, 0x8e, 0x93 } };
|
||
|
||
Wa2Groupdefs *groups;
|
||
static WNDPROC wa_oldWndProc;
|
||
|
||
Wa2CfgItems *cfgitems=0;
|
||
|
||
HINSTANCE hInstance = NULL;
|
||
HWND last_dlg_parent = NULL;
|
||
void populateWindowsMenus();
|
||
void unpopulateWindowsMenus();
|
||
void addWindowOptionsToContextMenu(ifc_window *w);
|
||
void removeWindowOptionsFromContextMenu();
|
||
void controlOpacity(int v);
|
||
void controlScaling(double v);
|
||
void customScaling();
|
||
void customOpacity();
|
||
void autoOpacifyHover();
|
||
void autoOpacifyFocus();
|
||
ifc_window *g_controlMenuTarget = NULL;
|
||
HMENU controlmenu = NULL;
|
||
void lockScaling(int lock);
|
||
int ffwindowsitempos = -1;
|
||
int ffoptionstop = -1;
|
||
int ffwoptionstop = -1;
|
||
int ffwindowstop = -1;
|
||
int ffwindowsitempos2 = -1;
|
||
int eqremoved = 0;
|
||
void removeEq();
|
||
void restoreEq();
|
||
int g_timedisplaymode = 0;
|
||
ifc_window *lastFocused = NULL;
|
||
int before_startup_callback = 0;
|
||
void loadExtraColorThemes();
|
||
extern _int last_page;
|
||
int gothrueqmsg = 0;
|
||
void unhookOutputIPC();
|
||
int we_have_ml = 0;
|
||
void checkMlPresent();
|
||
char eggstr[9] = {0};
|
||
int eggstat = 0;
|
||
int eggfallout = 0;
|
||
void initEgg();
|
||
void toggleEgg();
|
||
Layout *lastlayoutegg = NULL;
|
||
int disable_send_visrandom = 0;
|
||
void registerGlobalHotkeys();
|
||
int processGenericHotkey(const char *hk);
|
||
const char *getSkinInfo();
|
||
const wchar_t *getSkinInfoW();
|
||
void controlAppBar(int side);
|
||
void controlAppBarAOT();
|
||
void controlAppBarAH();
|
||
void updateAppBarMenu(ifc_window *w);
|
||
void startFSMonitor();
|
||
void stopFSMonitor();
|
||
void onGoFullscreen();
|
||
void onCancelFullscreen();
|
||
FullScreenMonitor *g_fsmonitor = NULL;
|
||
class Wa5FSCallback : public FSCallback
|
||
{
|
||
public:
|
||
virtual void onGoFullscreen()
|
||
{
|
||
::onGoFullscreen();
|
||
}
|
||
virtual void onCancelFullscreen()
|
||
{
|
||
::onCancelFullscreen();
|
||
}
|
||
};
|
||
Wa5FSCallback *g_fscallback = NULL;
|
||
int getAOTTempDisable()
|
||
{
|
||
return g_fsmonitor->isFullScreen();
|
||
}
|
||
|
||
LRESULT CallWinampWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
return CallWindowProcW(wa_oldWndProc, hwnd, msg, wParam, lParam);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
BOOL WINAPI dll_main_raw_fn(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||
{
|
||
hInstance = hinstDLL;
|
||
Wasabi::Std::Initialize();
|
||
return TRUE;
|
||
}
|
||
|
||
extern "C"
|
||
{
|
||
void *_pRawDllMain = &dll_main_raw_fn;
|
||
};
|
||
|
||
__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||
{
|
||
hInstance = hinstDLL;
|
||
return TRUE;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// core actions implement "play", "stop", etc. wndEmbedded embed wa2 windows into GUID-based wnds
|
||
//-----------------------------------------------------------------------------------------------
|
||
BEGIN_SERVICES(Winamp2_Svcs);
|
||
DECLARE_SERVICETSINGLE(svc_action, CoreActions);
|
||
DECLARE_SERVICETSINGLE(svc_action, MenuActions);
|
||
DECLARE_SERVICETSINGLE(svc_windowCreate, Wa2WndEmbed);
|
||
END_SERVICES(Winamp2_Svcs, _Winamp2_Svcs);
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// functions called by the overriden windowproc to create and destroy wndembedders
|
||
//-----------------------------------------------------------------------------------------------
|
||
ifc_window *plWnd = NULL;
|
||
#ifdef MINIBROWSER_SUPPORT
|
||
ifc_window *mbWnd = NULL;
|
||
#endif
|
||
ifc_window *vidWnd = NULL;
|
||
TList<HWND> forcedoffwnds;
|
||
|
||
int going_freeform = 0;
|
||
int going_fixedform = 0;
|
||
|
||
wchar_t *INI_FILE = 0, *INI_DIR = 0;
|
||
|
||
void ToggleLayout(const wchar_t *containerName)
|
||
{
|
||
Container *c = SkinParser::getContainer(containerName);
|
||
if (c)
|
||
{
|
||
int numLayouts = c->getNumLayouts();
|
||
|
||
for (int i = 0;i < numLayouts;i++)
|
||
{
|
||
if (c->enumLayout(i) == c->getCurrentLayout())
|
||
{
|
||
int nextLayout = (i + 1) % numLayouts;
|
||
Layout *layout = c->enumLayout(nextLayout);
|
||
c->switchToLayout(layout->getId());
|
||
return ;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
int updatePl()
|
||
{
|
||
// find out if this GUID is already shown.
|
||
WindowHolder *wh = skinEmbedder->getSuitableWindowHolder(pleditWndGuid, NULL, NULL, NULL, 1, -1, 0, 1, -1);
|
||
if (wh != NULL)
|
||
{
|
||
wh->cancelDeferredRemove();
|
||
GuiObject *go = wh->getRootWndPtr()->getGuiObject();
|
||
if (go)
|
||
{
|
||
Layout *l = go->guiobject_getParentLayout();
|
||
if (l)
|
||
{
|
||
Container *c = l->getParentContainer();
|
||
if (c)
|
||
{
|
||
DebugStringW(L"Container is %s\n", c->getId());
|
||
SkinEmbedder::cancelDestroyContainer(c);
|
||
}
|
||
}
|
||
}
|
||
plWnd = wh->getRootWndPtr(); //->getDesktopParent();
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int createPl()
|
||
{
|
||
if (updatePl())
|
||
{
|
||
ShowWindow(wa2.getWnd(IPC_GETWND_PE), SW_SHOWNA);
|
||
return 1;
|
||
}
|
||
ReentryFilter f(&wndMsgFilter, IPC_GETWND_PE);
|
||
if (f.mustLeave()) return 1;
|
||
plWnd = WASABI_API_WNDMGR->skinwnd_createByGuid(pleditWndGuid, L"resizable_status");
|
||
if (plWnd != NULL)
|
||
{
|
||
plWnd->setVisible(1);
|
||
}
|
||
return plWnd != NULL;
|
||
}
|
||
|
||
static ifc_window *updateEmb(GUID thisguid, embedWindowState *ws)
|
||
{
|
||
WindowHolder *wh = skinEmbedder->getSuitableWindowHolder(thisguid, NULL, NULL, NULL, 1, -1, 0, 1, -1);
|
||
if (wh != NULL && !(ws->flags & EMBED_FLAGS_LEGACY_WND))
|
||
{
|
||
ifc_window *p = wh->getRootWndPtr(); //->getDesktopParent();
|
||
|
||
// p->getGuiScriptObject()->vcpu_setInterface(embeddedWndStateGuid, ws, INTERFACE_GENERICVOIDPTR);
|
||
ws->extra_data[EMBED_STATE_EXTRA_FFROOTWND] = (intptr_t)p;
|
||
return p;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static ifc_window *createEmb(embedWindowState *ws, bool startHidden)
|
||
{
|
||
GUID thisguid = EmbedWndGuid(ws).getGuid();
|
||
if (thisguid == INVALID_GUID || (ws->flags & EMBED_FLAGS_LEGACY_WND))
|
||
return 0;
|
||
|
||
//thisguid.Data1 = (int)ws->me;
|
||
ifc_window *update = updateEmb(thisguid, ws);
|
||
if (update)
|
||
return update;
|
||
|
||
ReentryFilter f(&wndMsgFilter, (intptr_t)ws);
|
||
if (f.mustLeave())
|
||
return 0;
|
||
|
||
RECT r;
|
||
if (!GetWindowRect(ws->me, &r))
|
||
SetRectEmpty(&r);
|
||
|
||
ifc_window *p = NULL;
|
||
if (ws->flags & EMBED_FLAGS_NORESIZE)
|
||
p = WASABI_API_WNDMGR->skinwnd_createByGuid(thisguid, L"static", 0, NULL, 0, startHidden, NULL);
|
||
else
|
||
p = WASABI_API_WNDMGR->skinwnd_createByGuid(thisguid, L"resizable_nostatus", 0, NULL, 0, startHidden, NULL);
|
||
|
||
ws->extra_data[EMBED_STATE_EXTRA_FFROOTWND] = (intptr_t) p;
|
||
if (p != NULL)
|
||
{
|
||
// p->getGuiScriptObject()->vcpu_setInterface(embeddedWndStateGuid, ws, INTERFACE_GENERICVOIDPTR);
|
||
if (NULL != WASABI_API_APP)
|
||
WASABI_API_APP->app_unregisterGlobalWindow(p->getDesktopParent()->gethWnd());
|
||
|
||
if (!startHidden)
|
||
p->setVisible(1);
|
||
|
||
GuiObject *go = p->getGuiObject();
|
||
if (go)
|
||
{
|
||
Layout *l = go->guiobject_getParentLayout();
|
||
if (l)
|
||
{
|
||
Container *c = l->getParentContainer();
|
||
if (c)
|
||
{
|
||
if (ws->flags & EMBED_FLAGS_NOWINDOWMENU)
|
||
c->setXmlParam(L"nomenu", L"1");
|
||
else
|
||
c->setXmlParam(L"nomenu", L"0");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (p == NULL)
|
||
{
|
||
RECT r;
|
||
GetWindowRect(ws->me, &r);
|
||
//////SetWindowPos( ws->me, NULL, r.left - 20000, r.top - 20000, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOCOPYBITS );
|
||
SetWindowPos( ws->me, NULL, r.left, r.top, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOCOPYBITS );
|
||
forcedoffwnds.addItem(ws->me);
|
||
//if (0 != (WS_VISIBLE & windowStyle))
|
||
//RedrawWindow(GetDesktopWindow(), &r, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW | RDW_NOERASE);
|
||
}
|
||
|
||
RedrawWindow(GetDesktopWindow(), &r, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW | RDW_NOERASE);
|
||
return p;
|
||
}
|
||
|
||
#ifdef MINIBROWSER_SUPPORT
|
||
int updateMb()
|
||
{
|
||
WindowHolder *wh = skinEmbedder->getSuitableWindowHolder(minibrowserWndGuid, NULL, NULL, NULL, 1, -1, 0, 1, -1);
|
||
if (wh != NULL)
|
||
{
|
||
mbWnd = wh->getRootWndPtr(); //->getDesktopParent();
|
||
ShowWindow(wa2.getWnd(IPC_GETWND_MB), SW_SHOWNA);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int createMb()
|
||
{
|
||
// see cratePl()
|
||
if (updateMb()) return 1;
|
||
ReentryFilter f(&wndMsgFilter, IPC_GETWND_MB);
|
||
if (f.mustLeave()) return 1;
|
||
mbWnd = WASABI_API_WNDMGR->skinwnd_createByGuid(minibrowserWndGuid, "resizable_status");
|
||
if (mbWnd != NULL) mbWnd->setVisible(1);
|
||
return mbWnd != NULL;
|
||
}
|
||
#endif
|
||
|
||
static HWND oldVideoWnd;
|
||
static WNDPROC oldVideoWndProc;
|
||
static DWORD WINAPI newVideoWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
if (uMsg == WM_USER + 0x100 && wParam == 1 && lParam)
|
||
return 0;
|
||
|
||
return CallWindowProc(oldVideoWndProc, hwnd, uMsg, wParam, lParam);
|
||
}
|
||
|
||
int updateVid()
|
||
{
|
||
WindowHolder *wh = skinEmbedder->getSuitableWindowHolder(videoWndGuid, NULL, NULL, NULL, 1, -1, 0, 1, -1);
|
||
if (wh != NULL)
|
||
{
|
||
#ifdef VIDDEBUG
|
||
DebugString("Video : Host already exists and window already shown in it\n");
|
||
#endif
|
||
wh->cancelDeferredRemove();
|
||
GuiObject *go = wh->getRootWndPtr()->getGuiObject();
|
||
if (go)
|
||
{
|
||
Layout *l = go->guiobject_getParentLayout();
|
||
if (l)
|
||
{
|
||
Container *c = l->getParentContainer();
|
||
if (c)
|
||
{
|
||
DebugStringW(L"Container is %s\n", c->getId());
|
||
SkinEmbedder::cancelDestroyContainer(c);
|
||
}
|
||
}
|
||
}
|
||
vidWnd = wh->getRootWndPtr(); //->getDesktopParent();
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int createVid()
|
||
{
|
||
ShowWindow(WASABI_API_WND->main_getRootWnd()->gethWnd(), SW_RESTORE);
|
||
SetForegroundWindow(WASABI_API_WND->main_getRootWnd()->gethWnd());
|
||
|
||
if (updateVid())
|
||
{
|
||
ShowWindow(wa2.getWnd(IPC_GETWND_VIDEO), SW_SHOWNA);
|
||
return 1;
|
||
}
|
||
|
||
if (vidWnd == NULL)
|
||
{
|
||
ReentryFilter f(&wndMsgFilter, IPC_GETWND_VIDEO);
|
||
if (f.mustLeave()) return 1;
|
||
#ifdef VIDDEBUG
|
||
DebugString("Video : Trying to find a host or creating it if needed\n");
|
||
#endif
|
||
vidWnd = WASABI_API_WNDMGR->skinwnd_createByGuid(videoWndGuid, L"resizable_status");
|
||
}
|
||
|
||
if (vidWnd != NULL)
|
||
{
|
||
vidWnd->setVisible(1);
|
||
}
|
||
return vidWnd != NULL;
|
||
}
|
||
|
||
int destroyPl(HWND hwndDlg, int uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
ReentryFilter f(&wndMsgFilter, IPC_GETWND_PE);
|
||
int r = CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
if (f.mustLeave()) return r;
|
||
if (plWnd != NULL && WASABI_API_WND->rootwndIsValid(plWnd))
|
||
{
|
||
WASABI_API_WNDMGR->skinwnd_destroy(plWnd);
|
||
r = !WASABI_API_WND->rootwndIsValid(plWnd);
|
||
}
|
||
else
|
||
r = !SOM::checkAbortShowHideWindow(pleditWndGuid, 0);
|
||
if (r)
|
||
plWnd = NULL;
|
||
return r;
|
||
}
|
||
|
||
int destroyEmb(HWND hwndDlg, int uMsg, WPARAM wParam, LPARAM lParam, embedWindowState *ws)
|
||
{
|
||
ReentryFilter f(&wndMsgFilter, (intptr_t)ws);
|
||
int r = CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
if (f.mustLeave() || (ws->flags & EMBED_FLAGS_LEGACY_WND)) return r;
|
||
if (ws->extra_data[EMBED_STATE_EXTRA_FFROOTWND] == NULL) return r;
|
||
if (ws->extra_data[EMBED_STATE_EXTRA_REPARENTING] == 1) return r;
|
||
ifc_window *w = (ifc_window*)ws->extra_data[EMBED_STATE_EXTRA_FFROOTWND];
|
||
#if 1
|
||
if (WASABI_API_WND->rootwndIsValid(w))
|
||
{
|
||
WASABI_API_WNDMGR->skinwnd_destroy(w);
|
||
r = !WASABI_API_WND->rootwndIsValid(w);
|
||
}
|
||
else
|
||
{
|
||
r = !SOM::checkAbortShowHideWindow(embedWndGuidMgr.getGuid(ws), 0);
|
||
}
|
||
if (r)
|
||
ws->extra_data[EMBED_STATE_EXTRA_FFROOTWND] = NULL;
|
||
#else
|
||
if (WASABI_API_WND->rootwndIsValid(w)) WASABI_API_WNDMGR->skinwnd_destroy(w);
|
||
else SOM::checkAbortShowHideWindow(embedWndGuidMgr.getGuid(ws), 0);
|
||
ws->extra_data[EMBED_STATE_EXTRA_FFROOTWND] = NULL;
|
||
#endif
|
||
return r;
|
||
}
|
||
|
||
#ifdef MINIBROWSER_SUPPORT
|
||
int destroyMb(HWND hwndDlg, int uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
ReentryFilter f(&wndMsgFilter, IPC_GETWND_MB);
|
||
int r = CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
if (f.mustLeave()) return r;
|
||
|
||
if (mbWnd != NULL && WASABI_API_WND->rootwndIsValid(mbWnd)) WASABI_API_WNDMGR->skinwnd_destroy(mbWnd);
|
||
else SOM::checkAbortShowHideWindow(minibrowserWndGuid, 0);
|
||
mbWnd = NULL;
|
||
return r;
|
||
}
|
||
#endif
|
||
|
||
int destroyVid(HWND hwndDlg, int uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
ReentryFilter f(&wndMsgFilter, IPC_GETWND_VIDEO);
|
||
int r = CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
|
||
if (f.mustLeave()) return r;
|
||
|
||
if (vidWnd != NULL && WASABI_API_WND->rootwndIsValid(vidWnd))
|
||
{
|
||
WASABI_API_WNDMGR->skinwnd_destroy(vidWnd);
|
||
r = !WASABI_API_WND->rootwndIsValid(vidWnd);
|
||
}
|
||
else
|
||
r = !SOM::checkAbortShowHideWindow(videoWndGuid, 0);
|
||
|
||
if (r)
|
||
vidWnd = NULL;
|
||
|
||
return r;
|
||
}
|
||
|
||
|
||
int m_loading_at_startup;
|
||
int m_are_we_loaded;
|
||
|
||
#define WINAMP_REFRESHSKIN 40291
|
||
#define WINAMP_OPTIONS_EQ 40036
|
||
#define WINAMP_OPTIONS_DSIZE 40165
|
||
#define WINAMP_OPTIONS_ELAPSED 40037
|
||
#define WINAMP_OPTIONS_REMAINING 40038
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
class MainLayoutMonitor : public H_Layout
|
||
{
|
||
public:
|
||
MainLayoutMonitor(HWND _w, ScriptObject *o) : H_Layout(o) { hwnd= _w; }
|
||
void hook_onResize(int x, int y, int w, int h);
|
||
HWND hwnd;
|
||
};
|
||
|
||
void MainLayoutMonitor::hook_onResize(int x, int y, int w, int h)
|
||
{
|
||
PostMessage(wa2.getMainWindow(), WM_WA_IPC, (WPARAM)hwnd, UPDATEDIALOGBOXPARENTMSG);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// must be called after switching to a new freeform skin
|
||
// should also be called when the main container changes its visible layout
|
||
//-----------------------------------------------------------------------------------------------
|
||
Layout *GetMainLayout()
|
||
{
|
||
Container *container = SkinParser::getContainer(L"main");
|
||
if (container != NULL)
|
||
{
|
||
return container->getCurrentLayout();
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
HWND GetMainContainerHWND()
|
||
{
|
||
Layout *l = GetMainLayout();
|
||
if (l != NULL)
|
||
return l->gethWnd();
|
||
|
||
return 0;
|
||
}
|
||
static MainLayoutMonitor *mainLayoutMonitor = 0;
|
||
void setDialogBoxesParent()
|
||
{
|
||
Layout *l = GetMainLayout();
|
||
if (l != NULL)
|
||
{
|
||
HWND hwnd = l->gethWnd();
|
||
delete mainLayoutMonitor;
|
||
mainLayoutMonitor = new MainLayoutMonitor(hwnd, l->getScriptObject());
|
||
wa2.setDialogBoxParent(hwnd);
|
||
PostMessage(wa2.getMainWindow(), WM_WA_IPC, (WPARAM)hwnd, UPDATEDIALOGBOXPARENTMSG);
|
||
lastFocused = l;
|
||
}
|
||
}
|
||
|
||
static void removeSkinExtension(StringW &skinname)
|
||
{
|
||
int x = skinname.len() - 4;
|
||
if (x > 0)
|
||
{
|
||
const wchar_t *p = ((const wchar_t *)skinname) + x;
|
||
if (!_wcsicmp(p, L".zip") || !_wcsicmp(p, L".wal") || !_wcsicmp(p, L".wsz"))
|
||
skinname.trunc(x);
|
||
}
|
||
}
|
||
|
||
extern HWND subWnd, tabwnd;
|
||
extern int subWndId;
|
||
extern int toggle_from_wa2;
|
||
int switching_skin = 0;
|
||
void shutdownFFApi();
|
||
|
||
|
||
/*-----------------------------------------------------------------------------------------------
|
||
* Winamp2 message processor
|
||
*/
|
||
|
||
static void RerouteMessage(MSG *pMsg, ifc_window *wnd)
|
||
{
|
||
if (NULL == wnd)
|
||
return;
|
||
|
||
HWND hReroute = NULL;
|
||
if (pMsg->hwnd == GetMainContainerHWND())
|
||
{
|
||
hReroute = WASABI_API_WND->main_getRootWnd()->gethWnd();
|
||
if (NULL != hReroute)
|
||
{
|
||
pMsg->hwnd = hReroute;
|
||
}
|
||
return;
|
||
}
|
||
if (wnd->gethWnd() != pMsg->hwnd)
|
||
return;
|
||
|
||
ifc_window *parent = wnd->getRootParent();
|
||
if (NULL == parent)
|
||
return;
|
||
|
||
Layout *l = static_cast<Layout *>(parent->getInterface(layoutGuid));
|
||
if (NULL == l)
|
||
return;
|
||
|
||
Container *c = l->getParentContainer();
|
||
if (NULL == c)
|
||
return;
|
||
|
||
GUID g = c->getDefaultContent();
|
||
if (INVALID_GUID == g)
|
||
return;
|
||
|
||
if (g == playerWndGuid)
|
||
hReroute = wa2.getMainWindow();
|
||
else if (g == pleditWndGuid)
|
||
hReroute = wa2.getWnd(IPC_GETWND_PE);
|
||
else if (g == videoWndGuid)
|
||
hReroute = wa2.getWnd(IPC_GETWND_VIDEO);
|
||
else
|
||
{
|
||
embedWindowState *ews = embedWndGuidMgr.getEmbedWindowState(g);
|
||
if (ews)
|
||
hReroute = ews->me;
|
||
}
|
||
|
||
if (NULL != hReroute)
|
||
pMsg->hwnd = hReroute;
|
||
}
|
||
|
||
class WaMessageProccessor : public ifc_messageprocessor
|
||
{
|
||
public:
|
||
WaMessageProccessor() {}
|
||
~WaMessageProccessor(void) {}
|
||
|
||
public:
|
||
bool ProcessMessage(MSG *pMsg)
|
||
{
|
||
if (WM_KEYDOWN == pMsg->message ||
|
||
WM_KEYUP == pMsg->message ||
|
||
WM_SYSKEYDOWN == pMsg->message ||
|
||
WM_SYSKEYUP == pMsg->message)
|
||
{
|
||
|
||
ifc_window *wnd;
|
||
HWND h = pMsg->hwnd;
|
||
do
|
||
{
|
||
wnd = WASABI_API_WND->rootWndFromOSHandle(h);
|
||
|
||
} while (!wnd && NULL!= (h = GetAncestor(h, GA_PARENT)));
|
||
|
||
if (wnd)
|
||
{
|
||
if (!wnd->isVirtual())
|
||
{
|
||
while (wnd)
|
||
{
|
||
const wchar_t *pid = wnd->getId();
|
||
if (pid && *pid) break;
|
||
wnd = wnd->getParent();
|
||
}
|
||
}
|
||
if (wnd && wnd->getCurVirtualChildFocus())
|
||
wnd = wnd->getCurVirtualChildFocus();
|
||
}
|
||
|
||
if (wnd)
|
||
DebugStringW(L"target wnd 0x%08X, id: %s", wnd, wnd->getId());
|
||
|
||
INT keyMsg = -1;
|
||
switch(pMsg->message)
|
||
{
|
||
case WM_KEYDOWN:
|
||
static int pos;
|
||
if (toupper((int)pMsg->wParam) == eggstr[pos])
|
||
{
|
||
if (!eggstr[++pos])
|
||
{
|
||
toggleEgg();
|
||
pos = 0;
|
||
}
|
||
}
|
||
else pos = 0;
|
||
keyMsg = (0 != WASABI_API_WND->forwardOnKeyDown(wnd, (int)pMsg->wParam, pMsg->lParam));
|
||
break;
|
||
case WM_KEYUP: keyMsg = (wnd && 0 != WASABI_API_WND->forwardOnKeyUp(wnd, (int)pMsg->wParam, pMsg->lParam)); break;
|
||
case WM_SYSKEYDOWN: keyMsg = ( 0 != WASABI_API_WND->forwardOnSysKeyDown(wnd, (int)pMsg->wParam, pMsg->lParam)); break;
|
||
case WM_SYSKEYUP: keyMsg = (wnd && 0 != WASABI_API_WND->forwardOnSysKeyUp(wnd, (int)pMsg->wParam, pMsg->lParam)); break;
|
||
|
||
}
|
||
if (-1 != keyMsg)
|
||
{
|
||
if (keyMsg > 0)
|
||
return true;
|
||
|
||
RerouteMessage(pMsg, wnd);
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
protected:
|
||
RECVS_DISPATCH;
|
||
};
|
||
|
||
#define CBCLASS WaMessageProccessor
|
||
START_DISPATCH;
|
||
CB(IFC_MESSAGEPROCESSOR_PROCESS_MESSAGE, ProcessMessage)
|
||
END_DISPATCH;
|
||
#undef CBCLASS
|
||
|
||
static WaMessageProccessor waMessageProcessor;
|
||
|
||
#define TabCtrl_InsertItemW(hwnd, iItem, pitem) \
|
||
(int)SNDMSG((hwnd), TCM_INSERTITEMW, (WPARAM)(int)(iItem), (LPARAM)(const TC_ITEMW *)(pitem))
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void onSkinSwitch()
|
||
{
|
||
switching_skin = 1;
|
||
int lastloaded = m_are_we_loaded;
|
||
|
||
Wa2WndEmbed::rememberVisibleWindows();
|
||
|
||
// get skin name
|
||
wchar_t buf[MAX_PATH] = {0};
|
||
wchar_t *p = (wchar_t *) SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)buf, IPC_GETSKINW);
|
||
{
|
||
m_lastskin_nam.setValue(p);
|
||
m_lastskin_dir.setValue(buf);
|
||
|
||
StringPathCombine t(m_lastskin_dir, L"skin.xml");
|
||
|
||
if (!m_lastskin_nam.isempty()
|
||
&& _waccess(t.getValue(), 0))
|
||
{
|
||
t.setValue(m_lastskin_dir);
|
||
StringW n = m_lastskin_nam;
|
||
removeSkinExtension(n);
|
||
t.AppendPath(n);
|
||
t.AppendPath(L"skin.xml");
|
||
if (!_waccess(t.getValue(), 0))
|
||
m_lastskin_dir.AppendPath(n);
|
||
}
|
||
|
||
if (!_waccess(t.getValue(), 0))
|
||
{
|
||
if (!m_are_we_loaded) init_inst();
|
||
else
|
||
{
|
||
// load new skin
|
||
StringW skinname = m_lastskin_nam;
|
||
|
||
removeSkinExtension(skinname);
|
||
|
||
before_startup_callback = 1;
|
||
WASABI_API_SKIN->skin_switchSkin(skinname, m_lastskin_dir);
|
||
|
||
if (DEFERREDCALLBACKMSG > 65536)
|
||
PostMessage(wa2.getMainWindow(), WM_WA_IPC, 2, DEFERREDCALLBACKMSG);
|
||
//embedEnumStruct cs = { embedCreateProc, 0 };
|
||
//SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&cs, IPC_EMBED_ENUM);
|
||
|
||
doplaylistcolors();
|
||
setDialogBoxesParent();
|
||
populateWindowsMenus();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
going_fixedform = 1;
|
||
quit_inst();
|
||
}
|
||
}
|
||
if (subWnd != NULL && IsWindow(subWnd)) SendMessageW(subWnd, WM_INITDIALOG, 0, 0);
|
||
|
||
if (IsWindow(tabwnd))
|
||
{
|
||
if (!m_are_we_loaded)
|
||
{
|
||
if (subWndId == 5)
|
||
{
|
||
DestroyWindow(subWnd);
|
||
TabCtrl_SetCurSel(tabwnd,0);
|
||
_dosetsel(GetParent(tabwnd));
|
||
}
|
||
|
||
if (TabCtrl_GetItemCount(tabwnd) == 5)
|
||
{
|
||
TabCtrl_DeleteItem(tabwnd,4);
|
||
TabCtrl_DeleteItem(tabwnd,3);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (TabCtrl_GetItemCount(tabwnd) == 3)
|
||
{
|
||
TCITEMW item = {0};
|
||
item.mask=TCIF_TEXT;
|
||
item.pszText=WASABI_API_LNGSTRINGW(IDS_COLOR_THEMES);
|
||
TabCtrl_InsertItemW(tabwnd,3,&item);
|
||
item.pszText=WASABI_API_LNGSTRINGW(IDS_CURRENT_SKIN);
|
||
TabCtrl_InsertItemW(tabwnd,4,&item);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (m_are_we_loaded || lastloaded) // dont call this if going from classic->classic
|
||
Wa2WndEmbed::restoreVisibleWindows();
|
||
|
||
if (m_are_we_loaded && WASABI_API_SYSCB)
|
||
WASABI_API_SYSCB->syscb_issueCallback(SysCallback::GC, GarbageCollectCallback::GARBAGECOLLECT);
|
||
|
||
if (WASABI_API_APP)
|
||
{
|
||
if (m_are_we_loaded) WASABI_API_APP->app_addMessageProcessor(&waMessageProcessor);
|
||
else WASABI_API_APP->app_removeMessageProcessor(&waMessageProcessor);
|
||
}
|
||
|
||
/* TODO: benski> want to add this, but it's causing a weird crash
|
||
if (going_fixedform)
|
||
shutdownFFApi();
|
||
*/
|
||
switching_skin = 0;
|
||
going_fixedform = 0;
|
||
before_startup_callback = 0;
|
||
}
|
||
|
||
static int embedUpdateColorProc(embedWindowState *p, embedEnumStruct *parms)
|
||
{
|
||
SendMessageW(p->me, WM_DISPLAYCHANGE, 0, 0);
|
||
return 0;
|
||
}
|
||
|
||
int embedCreateProc(embedWindowState *ws, embedEnumStruct *parms)
|
||
{
|
||
ifc_window *rw = reinterpret_cast<ifc_window*>(ws->extra_data[EMBED_STATE_EXTRA_FFROOTWND]);
|
||
|
||
if (!rw && IsWindow(ws->me) && IsWindowVisible(ws->me) && !(ws->flags & EMBED_FLAGS_LEGACY_WND))
|
||
{
|
||
ifc_window *windowParent = createEmb(ws, true);
|
||
if (NULL != windowParent)
|
||
{
|
||
GuiObject *uiObject = windowParent->getGuiObject();
|
||
if (NULL != uiObject)
|
||
{
|
||
if (0 != (EMBED_FLAGS_FFCALLBACK & ws->flags) &&
|
||
NULL != ws->callback)
|
||
{
|
||
ws->callback(ws, FFC_CREATEEMBED, (LPARAM)windowParent);
|
||
}
|
||
|
||
Layout *layout = uiObject->guiobject_getParentLayout();
|
||
if (NULL != layout)
|
||
{
|
||
Container *container = layout->getParentContainer();
|
||
if (NULL != container) container->setVisible(1);
|
||
else layout->setVisible(1);
|
||
windowParent->setVisible(1);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (NULL == windowParent)
|
||
ShowWindow(ws->me, SW_HIDE);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void syncDoubleSize(int loading = 0)
|
||
{
|
||
if (!cfg_uioptions_uselocks.getValueAsInt()) return ;
|
||
int isdsize = wa2.isDoubleSize();
|
||
int i;
|
||
for (i = 0;i < SkinParser::getNumContainers();i++)
|
||
{
|
||
Container *c = SkinParser::enumContainer(i);
|
||
if (c != NULL)
|
||
{
|
||
int j;
|
||
for (j = 0;j < c->getNumLayouts();j++)
|
||
{
|
||
Layout *l = c->enumLayout(j);
|
||
if (l != NULL)
|
||
{
|
||
if (l->isScaleLocked()) continue;
|
||
l->setRenderRatio(isdsize ? 2.0f : 1.0f);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
class syncDisplayModeEnumerator : public FindObjectCallbackI
|
||
{
|
||
public:
|
||
int findobjectcb_matchObject(ifc_window *object)
|
||
{
|
||
ScriptObject *s = NULL;
|
||
GuiObject *g = object->getGuiObject();
|
||
if (g)
|
||
{
|
||
ScriptObject *_s = g->guiobject_getScriptObject();
|
||
if (_s)
|
||
{
|
||
void *v = _s->vcpu_getInterfaceObject(textGuid, &s);
|
||
if (v && !s)
|
||
{
|
||
(static_cast<Text*>(v))->setTimeDisplayMode(g_timedisplaymode);
|
||
}
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
};
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void syncDisplayMode()
|
||
{
|
||
if (switching_skin) return ;
|
||
g_timedisplaymode = wa2.getTimeDisplayMode();
|
||
int i;
|
||
syncDisplayModeEnumerator enumerator;
|
||
for (i = 0;i < SkinParser::getNumContainers();i++)
|
||
{
|
||
Container *c = SkinParser::enumContainer(i);
|
||
if (c != NULL)
|
||
{
|
||
int j;
|
||
for (j = 0;j < c->getNumLayouts();j++)
|
||
{
|
||
Layout *l = c->enumLayout(j);
|
||
if (!WASABI_API_WND->rootwndIsValid(l)) continue;
|
||
l->findWindowByCallback(&enumerator);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
static POINT viewPort;
|
||
VOID CALLBACK ViewPortChanged(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
||
{
|
||
KillTimer(hwnd, idEvent);
|
||
if (viewPort.x && viewPort.y)
|
||
{
|
||
SystemObject::onViewPortChanged(viewPort.x, viewPort.y);
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// Winamp2 main window subclass
|
||
//-----------------------------------------------------------------------------------------------
|
||
static LRESULT WINAPI wa_newWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
static int m_in_skinrefresh;
|
||
|
||
if (uMsg == WM_COMMAND && LOWORD(wParam) == WINAMP_REFRESHSKIN)
|
||
{
|
||
HWND prefs = wa2.getPreferencesWindow();
|
||
RECT prefrect = {0};
|
||
if (prefs)
|
||
{
|
||
GetWindowRect(prefs, &prefrect);
|
||
HWND hOwner = (HWND)(LONG_PTR)GetWindowLongPtrW(prefs, GWLP_HWNDPARENT);
|
||
if (NULL != hOwner && hOwner != hwndDlg)
|
||
SetWindowLongPtrW(prefs, GWLP_HWNDPARENT, (LONG_PTR)hwndDlg);
|
||
}
|
||
m_in_skinrefresh++;
|
||
DWORD b = CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
onSkinSwitch();
|
||
if (m_are_we_loaded) doplaylistcolors();
|
||
m_in_skinrefresh--;
|
||
if (prefs && !wa2.getPreferencesWindow())
|
||
{
|
||
SendMessageW(wa2.getMainWindow(), WM_COMMAND, WINAMP_OPTIONS_PREFS, 0);
|
||
SetWindowPos(wa2.getPreferencesWindow(), NULL, prefrect.left, prefrect.top, prefrect.right - prefrect.left, prefrect.bottom - prefrect.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE);
|
||
}
|
||
|
||
return b;
|
||
}
|
||
if (g_Core)
|
||
{
|
||
if (uMsg == WM_WA_IPC && lParam == IPC_CB_MISC) g_Core->gotCallback(wParam);
|
||
#define WINAMP_FILE_REPEAT 40022
|
||
#define WINAMP_FILE_SHUFFLE 40023
|
||
#define WINAMP_FILE_MANUALPLADVANCE 40395
|
||
#define UPDATE_DISPLAY_TIMER 38
|
||
if (uMsg == WM_TIMER)
|
||
{
|
||
if (LOWORD(wParam) == UPDATE_EGG)
|
||
{
|
||
for (int i = 0;i < SkinParser::getNumContainers();i++)
|
||
{
|
||
Container *cont = SkinParser::enumContainer(i);
|
||
if (cont->isMainContainer())
|
||
{
|
||
Layout *l = cont->getCurrentLayout();
|
||
if (lastlayoutegg && l != lastlayoutegg)
|
||
{
|
||
if (WASABI_API_WND->rootwndIsValid(lastlayoutegg))
|
||
{
|
||
lastlayoutegg->updateTransparency();
|
||
lastlayoutegg->setTransparencyOverride(-1);
|
||
}
|
||
}
|
||
lastlayoutegg = l;
|
||
int v = (WASABI_API_MEDIACORE->core_getLeftVuMeter(0) + WASABI_API_MEDIACORE->core_getRightVuMeter(0)) / 4;
|
||
eggfallout -= 4;
|
||
if (v > eggfallout) eggfallout = v;
|
||
lastlayoutegg->setTransparencyOverride(255 - eggfallout);
|
||
break;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
if (LOWORD(wParam) == UPDATE_DISPLAY_TIMER + 4)
|
||
{
|
||
syncDisplayMode();
|
||
}
|
||
if (LOWORD(wParam) == 0xC0DE)
|
||
{
|
||
if (!wa2.isVisRunning())
|
||
{
|
||
KillTimer(wa2.getMainWindow(), 0xC0DE);
|
||
KillTimer(wa2.getMainWindow(), 0xC0DE + 1);
|
||
wa2.toggleVis();
|
||
}
|
||
}
|
||
if (LOWORD(wParam) == 0xC0DE + 1)
|
||
{
|
||
KillTimer(wa2.getMainWindow(), 0xC0DE);
|
||
KillTimer(wa2.getMainWindow(), 0xC0DE + 1);
|
||
}
|
||
}
|
||
if (!my_set && (uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND) && LOWORD(wParam) == WINAMP_FILE_SHUFFLE)
|
||
{
|
||
DWORD v = CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
int shuf = wa2.getShuffle();
|
||
if (!shuffle.getValueAsInt() != !shuf) shuffle.setValueAsInt(shuf);
|
||
return v;
|
||
}
|
||
if (!my_set && (uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND) &&
|
||
(LOWORD(wParam) == WINAMP_FILE_REPEAT) ||
|
||
(LOWORD(wParam) == WINAMP_FILE_MANUALPLADVANCE))
|
||
{
|
||
DWORD v = CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
int rep = wa2.getRepeat();
|
||
int manadv = wa2.getManualPlaylistAdvance();
|
||
int _v = (rep && manadv) ? -1 : rep;
|
||
if (repeat.getValueAsInt() != _v) repeat.setValueAsInt(_v);
|
||
return v;
|
||
}
|
||
if ((uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND) && LOWORD(wParam) == WINAMP_OPTIONS_DSIZE)
|
||
{
|
||
int v = CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
syncDoubleSize();
|
||
return v;
|
||
}
|
||
if ((uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND) && (LOWORD(wParam) == WINAMP_OPTIONS_ELAPSED || LOWORD(wParam) == WINAMP_OPTIONS_REMAINING))
|
||
{
|
||
int v = CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
syncDisplayMode();
|
||
return v;
|
||
}
|
||
}
|
||
if (m_are_we_loaded)
|
||
{
|
||
if (uMsg == WM_COMMAND && LOWORD(wParam) == 40266)
|
||
{
|
||
ToggleLayout(L"pledit");
|
||
return 0;
|
||
}
|
||
else if (uMsg == WM_COMMAND && LOWORD(wParam) == 40064)
|
||
{
|
||
ToggleLayout(L"main");
|
||
return 0;
|
||
}
|
||
else if (uMsg == WM_CLOSE && wParam == 0xDEADBEEF && lParam == 0xDEADF00D)
|
||
{
|
||
//if (/*todo: configurable */ 1)
|
||
{
|
||
uMsg = WM_COMMAND;
|
||
wParam = WINAMP_MAIN_WINDOW;
|
||
}
|
||
}
|
||
else if (uMsg == WM_SETTINGCHANGE)
|
||
{
|
||
// used to track viewport changes so we can update
|
||
// e.g. when removing Win8's side-by-side app mode
|
||
if (wParam == SPI_SETWORKAREA)
|
||
{
|
||
KillTimer(wa2.getMainWindow(), VIEWPORT);
|
||
viewPort.x = -1;
|
||
viewPort.y = -1;
|
||
SetTimer(wa2.getMainWindow(), VIEWPORT, 100, ViewPortChanged);
|
||
}
|
||
}
|
||
else if (uMsg == WM_DISPLAYCHANGE)
|
||
{
|
||
DWORD b = CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
if (!m_in_skinrefresh) doplaylistcolors();
|
||
|
||
// filter out our internal skin updates
|
||
if (wParam && lParam)
|
||
{
|
||
KillTimer(wa2.getMainWindow(), VIEWPORT);
|
||
viewPort.x = LOWORD(lParam);
|
||
viewPort.y = HIWORD(lParam);
|
||
SetTimer(wa2.getMainWindow(), VIEWPORT, 100, ViewPortChanged);
|
||
}
|
||
|
||
return b;
|
||
}
|
||
else if (uMsg == WM_INITMENUPOPUP)
|
||
{
|
||
HMENU hmenuPopup = (HMENU) wParam;
|
||
|
||
if (hmenuPopup && hmenuPopup == mainSendTo.build_hMenu && mainSendTo.mode == 1)
|
||
{
|
||
int IPC_LIBRARY_SENDTOMENU = SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"LibrarySendToMenu", IPC_REGISTER_WINAMP_IPCMESSAGE);
|
||
if (IPC_LIBRARY_SENDTOMENU > 65536 && SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&mainSendTo, IPC_LIBRARY_SENDTOMENU) == 0xffffffff)
|
||
mainSendTo.mode = 2;
|
||
}
|
||
|
||
if(hmenuPopup == wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_PLAY))
|
||
{
|
||
CheckMenuItem((HMENU)wParam, WINAMP_FILE_SHUFFLE, wa2.getShuffle() ? MF_CHECKED : MF_UNCHECKED);
|
||
CheckMenuItem((HMENU)wParam, WINAMP_FILE_REPEAT, wa2.getRepeat() ? MF_CHECKED : MF_UNCHECKED);
|
||
}
|
||
|
||
if (hmenuPopup == wa2.getPopupMenu() ||
|
||
hmenuPopup == wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_OPTIONS) ||
|
||
hmenuPopup == wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_WINDOWS))
|
||
{
|
||
if (hmenuPopup == wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_OPTIONS)) {
|
||
EnableMenuItem(hmenuPopup, WINAMP_OPTIONS_DSIZE,
|
||
MF_BYCOMMAND | (cfg_uioptions_uselocks.getValueAsInt() ? MF_ENABLED : MF_GRAYED));
|
||
}
|
||
if (hmenuPopup == wa2.getPopupMenu()){
|
||
EnableMenuItem(GetSubMenu(hmenuPopup, 11 + wa2.adjustOptionsPopupMenu(0)), WINAMP_OPTIONS_DSIZE,
|
||
MF_BYCOMMAND | (cfg_uioptions_uselocks.getValueAsInt() ? MF_ENABLED : MF_GRAYED));
|
||
}
|
||
|
||
populateWindowsMenus();
|
||
|
||
if ((HMENU)wParam == wa2.getPopupMenu())
|
||
{
|
||
for (int i = 0;i < SkinParser::getNumContainers();i++)
|
||
{
|
||
Container *cont = SkinParser::enumContainer(i);
|
||
if (!_wcsicmp(cont->getId(), L"main"))
|
||
{
|
||
CheckMenuItem((HMENU)wParam, WINAMP_MAIN_WINDOW, cont->isVisible() ? MF_CHECKED : MF_UNCHECKED);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (uMsg == WM_SETFOCUS)
|
||
{
|
||
if (m_are_we_loaded && !switching_skin)
|
||
{
|
||
Container *c = SkinParser::getContainer(L"main");
|
||
if (c)
|
||
{
|
||
Layout *l = c->enumLayout(0);
|
||
if (l) l->setFocus();
|
||
}
|
||
return 1;
|
||
}
|
||
}
|
||
else if (uMsg == WM_WA_IPC)
|
||
{
|
||
if (lParam == DEFERREDCALLBACKMSG && DEFERREDCALLBACKMSG > 65536)
|
||
{
|
||
if (wParam == 1)
|
||
{
|
||
setDialogBoxesParent();
|
||
return 1;
|
||
}
|
||
else if (wParam == 2)
|
||
{
|
||
// embed the windows that are currently visible because at the time the window were originally shown,
|
||
// we hadn't been loaded yet
|
||
// but then again, we might if it's only a switch skin and not a app load, so let's check anyway
|
||
|
||
populateWindowsMenus();
|
||
|
||
doplaylistcolors();
|
||
|
||
if (plWnd == NULL && wa2.isWindowVisible(IPC_GETWND_PE))
|
||
if (!createPl()) wa2.setWindowVisible(IPC_GETWND_PE, 0);
|
||
|
||
#ifdef MINIBROWSER_SUPPORT
|
||
if (mbWnd == NULL && wa2.isWindowVisible(IPC_GETWND_MB))
|
||
if (!createMb()) wa2.setWindowVisible(IPC_GETWND_MB, 0);
|
||
#endif
|
||
if (vidWnd == NULL && wa2.isWindowVisible(IPC_GETWND_VIDEO))
|
||
if (!createVid()) wa2.setWindowVisible(IPC_GETWND_VIDEO, 0);
|
||
|
||
embedEnumStruct cs = { embedCreateProc, 0 };
|
||
SendMessageW(hwndDlg, WM_WA_IPC, (WPARAM)&cs, IPC_EMBED_ENUM);
|
||
|
||
for (int i = 0;i < SkinParser::getNumContainers();i++)
|
||
{
|
||
Container *cont = SkinParser::enumContainer(i);
|
||
if (!_wcsicmp(cont->getId(), L"main"))
|
||
{
|
||
for (int j = 0;j < cont->getNumLayouts();j++)
|
||
{
|
||
Layout *l = cont->enumLayout(j);
|
||
if (l && l->isVisible())
|
||
{
|
||
SetFocus(l->gethWnd());
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Crossfader::onOutputChanged();
|
||
|
||
extern int make_sure_library_is_here_at_startup;
|
||
if (make_sure_library_is_here_at_startup)
|
||
SendMessageW(wa2.getMainWindow(), WM_COMMAND, ID_FILE_SHOWLIBRARY, 0);
|
||
make_sure_library_is_here_at_startup = 0;
|
||
|
||
before_startup_callback = 0;
|
||
|
||
registerGlobalHotkeys();
|
||
|
||
// force a title update since it's not always correct
|
||
// if gen_ml hasn't loaded fully when we're loading
|
||
if (wa2.isPlaying())
|
||
g_Core->gotCallback(IPC_CB_MISC_TITLE, 2);
|
||
return 1;
|
||
}
|
||
}
|
||
else if (lParam == UPDATEDIALOGBOXPARENTMSG && UPDATEDIALOGBOXPARENTMSG > 65536)
|
||
{
|
||
wa2.updateDialogBoxParent((HWND)wParam);
|
||
}
|
||
else switch (lParam)
|
||
{
|
||
case IPC_GETSKININFO:
|
||
return (LRESULT)getSkinInfo();
|
||
case IPC_GETSKININFOW:
|
||
return (LRESULT)getSkinInfoW();
|
||
case IPC_SHOW_NOTIFICATION:
|
||
return SystemObject::onShowNotification();
|
||
case IPC_CB_VISRANDOM:
|
||
{
|
||
int v = wParam;
|
||
extern _bool visrandom;
|
||
if (!!v == !!visrandom.getValueAsInt()) break;
|
||
disable_send_visrandom = 1;
|
||
visrandom.setValueAsInt(v);
|
||
disable_send_visrandom = 0;
|
||
break;
|
||
}
|
||
case IPC_CB_OUTPUTCHANGED:
|
||
Crossfader::onOutputChanged();
|
||
break;
|
||
|
||
case IPC_CB_ONTOGGLEAOT:
|
||
{
|
||
if ((WPARAM)cfg_options_alwaysontop.getValueAsInt() != wParam)
|
||
cfg_options_alwaysontop.setValueAsInt(wParam);
|
||
break;
|
||
}
|
||
|
||
case IPC_SETIDEALVIDEOSIZE:
|
||
{
|
||
wa2.setIdealVideoSize(HIWORD(wParam), LOWORD(wParam));
|
||
break;
|
||
}
|
||
// this is where we detect that wa2 wants to open one of its windows (thru popup menu, button, whatever)
|
||
// when this happens, we create a freeform wndembedder if one doesn't already exist. that embedder will
|
||
// reparent and resize the wa2 window on its own. when we return, winamp then shows the HWND inside our frame
|
||
// as it would show the HWND as a popup normally.
|
||
case IPC_CB_ONSHOWWND:
|
||
switch (wParam)
|
||
{
|
||
case IPC_CB_WND_PE:
|
||
if (!createPl()) return 0;
|
||
break;
|
||
#ifdef MINIBROWSER_SUPPORT
|
||
case IPC_CB_WND_MB:
|
||
if (!createMb()) return 0;
|
||
break;
|
||
#endif
|
||
case IPC_CB_WND_VIDEO:
|
||
#ifdef VIDDEBUG
|
||
DebugString("Video : Got IPC_ONSHOW\n");
|
||
#endif
|
||
if (!createVid())
|
||
{
|
||
#ifdef VIDDEBUG
|
||
DebugString("Video : SHOW was cancelled by script\n");
|
||
#endif
|
||
return 0;
|
||
}
|
||
break;
|
||
default:
|
||
DebugStringW(L"embedWnd : Got IPC_ONSHOW\n");
|
||
if (IsWindow((HWND)wParam))
|
||
{
|
||
HWND hTarget = (HWND)wParam;
|
||
embedWindowState *ws = (embedWindowState*)GetWindowLongPtrW(hTarget, GWLP_USERDATA);
|
||
if (ws && ws->me == hTarget)
|
||
{
|
||
GUID thisguid = EmbedWndGuid(ws).getGuid();
|
||
if (INVALID_GUID == thisguid || NULL == updateEmb(thisguid, ws))
|
||
{
|
||
ifc_window *windowParent = createEmb(ws, true);
|
||
if (NULL != windowParent)
|
||
{
|
||
GuiObject *uiObject = windowParent->getGuiObject();
|
||
if (NULL != uiObject)
|
||
{
|
||
if (0 != (EMBED_FLAGS_FFCALLBACK & ws->flags) &&
|
||
NULL != ws->callback)
|
||
{
|
||
ws->callback(ws, FFC_CREATEEMBED, (LPARAM)windowParent);
|
||
}
|
||
|
||
Layout *layout = uiObject->guiobject_getParentLayout();
|
||
if (NULL != layout)
|
||
{
|
||
Container *container = layout->getParentContainer();
|
||
if (NULL != container) container->setVisible(1);
|
||
else layout->setVisible(1);
|
||
windowParent->setVisible(1);
|
||
}
|
||
}
|
||
|
||
}
|
||
return (NULL != windowParent);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
// here we do the reverse, we detect that wa2 wants to close one of its windows, so we destroy our window
|
||
// embedder (it will reparent the wa2 window back to its former parent and resize it back to where it was
|
||
// on its own). when we return, winamp then hides the window.
|
||
|
||
// NOTE! because of this, there might be a split second where the window is seen on the screen as a popup
|
||
// after you closed the window (this won't happen for static containers [ie: pledit/video in mmd3] since
|
||
// they are hidden rather than destroyed). this can be fixed in the future
|
||
case IPC_CB_ONHIDEWND:
|
||
switch (wParam)
|
||
{
|
||
case IPC_CB_WND_PE:
|
||
destroyPl(hwndDlg, uMsg, wParam, lParam);
|
||
break;
|
||
#ifdef MINIBROWSER_SUPPORT
|
||
case IPC_CB_WND_MB:
|
||
return destroyMb(hwndDlg, uMsg, wParam, lParam);
|
||
#endif
|
||
case IPC_CB_WND_VIDEO:
|
||
#ifdef VIDDEBUG
|
||
DebugString("Video : Got IPC_ONHIDE\n");
|
||
#endif
|
||
return destroyVid(hwndDlg, uMsg, wParam, lParam);
|
||
default:
|
||
DebugStringW(L"embedWnd : Got IPC_ONHIDE\n");
|
||
if (IsWindow((HWND)wParam))
|
||
{
|
||
HWND h = (HWND)wParam;
|
||
embedWindowState *ws = (embedWindowState *)GetWindowLongPtrW(h, GWLP_USERDATA);
|
||
if (ws) return destroyEmb(hwndDlg, uMsg, wParam, lParam, ws);
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
case IPC_FF_ISMAINWND:
|
||
{
|
||
for (int i = 0;i < SkinParser::getNumContainers();i++)
|
||
{
|
||
Container *cont = SkinParser::enumContainer(i);
|
||
if (!_wcsicmp(cont->getId(), L"main"))
|
||
{
|
||
for (int j = 0;j < cont->getNumLayouts();j++)
|
||
{
|
||
if (cont->enumLayout(j)->gethWnd() == (HWND)wParam) return 1;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
case IPC_FF_GETCONTENTWND:
|
||
return (LRESULT)ff_ipc_getContentWnd((HWND)wParam);
|
||
case IPC_FF_GETSKINCOLOR:
|
||
ff_ipc_getSkinColor((ff_skincolor*)wParam);
|
||
return 1;
|
||
case IPC_FF_GENSKINBITMAP:
|
||
ff_ipc_genSkinBitmap((ff_skinbitmap*)wParam);
|
||
return 1;
|
||
case IPC_FF_NOTIFYHOTKEY:
|
||
if (processGenericHotkey((const char *)wParam)) return 0; // prevent gen_hotkey from processing the hotkey
|
||
return 1; // let gen_hotkey process the hotkey
|
||
case IPC_GET_GENSKINBITMAP:
|
||
if (m_are_we_loaded)
|
||
{
|
||
if (wParam == 0)
|
||
{
|
||
if (m_lastskin_dir[0])
|
||
{
|
||
HBITMAP bm;
|
||
wchar_t bitmapfilename[MAX_PATH] = {0};
|
||
PathCombineW(bitmapfilename, m_lastskin_dir, L"genex.bmp");
|
||
bm = (HBITMAP)LoadImageW(NULL, bitmapfilename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
|
||
if (bm) return (LRESULT)bm;
|
||
}
|
||
return (LRESULT)ff_genwa2skinbitmap();
|
||
}
|
||
else if (wParam == 4)
|
||
{
|
||
// TODO need to make sure we're covering everything needed for all of this!!
|
||
int buf[6] = {0};
|
||
// active text
|
||
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text.current"))
|
||
buf[1] = SkinColor(L"wasabi.list.text.current");
|
||
/*else
|
||
{
|
||
COLORREF act = Blenders::BLEND_AVG(selected, buf[0]);
|
||
act = (lumidiff(act, buf[0]) < 0x3F || lumidiff(act, buf[2]) < 0x2F) ? Blenders::BLEND_AVG(buf[2], 0xFFFFFFFF) : act;
|
||
act = (lumidiff(act, buf[0]) < 0x3F || lumidiff(act, buf[2]) < 0x2F) ? Blenders::BLEND_AVG(buf[2], 0xFF101010) : act;
|
||
act = (lumidiff(act, buf[0]) < 0x3F || lumidiff(act, buf[2]) < 0x2F) ? Blenders::BLEND_AVG(selected, buf[0]) : act;
|
||
act = (lumidiff(act, buf[0]) < 0x3F || lumidiff(act, buf[2]) < 0x2F) ? Blenders::BLEND_AVG(selected, buf[2]) : act;
|
||
act = (lumidiff(act, buf[0]) < 0x3F || lumidiff(act, buf[2]) < 0x2F) ? Blenders::BLEND_AVG(buf[0], buf[2]) : act;
|
||
buf[1] = act & 0xFFFFFF;
|
||
}*/
|
||
return buf[1];
|
||
}
|
||
}
|
||
break;
|
||
case IPC_FF_ONCOLORTHEMECHANGED:
|
||
{
|
||
embedEnumStruct cs = { embedUpdateColorProc, 0 };
|
||
SendMessageW(hwndDlg, WM_WA_IPC, (WPARAM)&cs, IPC_EMBED_ENUM);
|
||
if (wParam != 0xf00d) doplaylistcolors();
|
||
}
|
||
break;
|
||
case IPC_PLAYLIST_MODIFIED:
|
||
{
|
||
Wa2PlaylistEditor::_onPlaylistModified();
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
else if (uMsg == WM_COMMAND && (LOWORD(wParam) == 40144 || LOWORD(wParam) == 40148))
|
||
{
|
||
// seek left/right, we need to disable them if we are in a menu, because this is a
|
||
// plugin (ie: milkdrop) sending us the command manually as a forward rather than
|
||
// sending us the WM_KEY* directly
|
||
if (WASABI_API_WND->isKeyboardLocked()) return 0;
|
||
}
|
||
else if ((uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND) && LOWORD(wParam) >= 43000 && LOWORD(wParam) < ffwindowstop)
|
||
{
|
||
int id = LOWORD(wParam) - 43000;
|
||
|
||
int n = SkinParser::getNumContainers();
|
||
if (id < n)
|
||
{
|
||
Container *cont = SkinParser::enumContainer(id);
|
||
if (cont) cont->toggle();
|
||
return 1;
|
||
}
|
||
id -= n;
|
||
|
||
n = WASABI_API_WNDMGR->autopopup_getNumGuids();
|
||
if (id < n)
|
||
{
|
||
GUID guid = WASABI_API_WNDMGR->autopopup_enumGuid(id);
|
||
if (guid != INVALID_GUID)
|
||
WASABI_API_WNDMGR->skinwnd_toggleByGuid(guid);
|
||
return 1;
|
||
}
|
||
id -= n;
|
||
|
||
n = WASABI_API_WNDMGR->autopopup_getNumGroups();
|
||
if (id < n)
|
||
{
|
||
const wchar_t *gid = WASABI_API_WNDMGR->autopopup_enumGroup(id);
|
||
if (gid && *gid)
|
||
WASABI_API_WNDMGR->skinwnd_toggleByGroupId(gid);
|
||
return 1;
|
||
}
|
||
|
||
/* for (int c=0;c<SkinParser::getNumContainers();c++) {
|
||
Container *cont = SkinParser::enumContainer(c);
|
||
if (cont && wantContainerInMenu(cont)) {
|
||
if (cont->getName() == NULL) continue;
|
||
if (id == 0) {
|
||
if (cont)
|
||
cont->toggle();
|
||
return 1;
|
||
}
|
||
id--;
|
||
}
|
||
}
|
||
int n = WASABI_API_WNDMGR->autopopup_getNumGuids();
|
||
for (c=0;c<n;c++) {
|
||
GUID guid = WASABI_API_WNDMGR->autopopup_enumGuid(c);
|
||
const char *groupdesc = WASABI_API_WNDMGR->autopopup_enumGuidDescription(c);
|
||
if (guid != INVALID_GUID && groupdesc && *groupdesc) {
|
||
if (id == 0) {
|
||
WASABI_API_WNDMGR->skinwnd_toggleByGuid(guid);
|
||
return 1;
|
||
}
|
||
id--;
|
||
}
|
||
}
|
||
n = WASABI_API_WNDMGR->autopopup_getNumGroups();
|
||
for (c=0;c<n;c++) {
|
||
const char *gid = WASABI_API_WNDMGR->autopopup_enumGroup(c);
|
||
const char *groupdesc = WASABI_API_WNDMGR->autopopup_enumGroupDescription(c);
|
||
if (id && groupdesc && *gid && *groupdesc) {
|
||
if (id == 0) {
|
||
WASABI_API_WNDMGR->skinwnd_toggleByGroupId(gid);
|
||
return 1;
|
||
}
|
||
id--;
|
||
}
|
||
}*/
|
||
return 0;
|
||
}
|
||
else if ((uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND) && LOWORD(wParam) >= 44000 && LOWORD(wParam) < ffoptionstop)
|
||
{
|
||
int id = LOWORD(wParam);
|
||
MenuActions::toggleOption(id - 44000);
|
||
}
|
||
else if ((uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND) && LOWORD(wParam) >= 44500 && LOWORD(wParam) < 45000)
|
||
{
|
||
int id = LOWORD(wParam) - 44500;
|
||
WASABI_API_SKIN->colortheme_setColorSet(WASABI_API_SKIN->colortheme_enumColorSet(id));
|
||
}
|
||
else if ((uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND) && LOWORD(wParam) >= 42000 && LOWORD(wParam) < ffwoptionstop)
|
||
{
|
||
int id = LOWORD(wParam);
|
||
MenuActions::toggleWindowOption(id - 42000);
|
||
}
|
||
else if ((uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND) && LOWORD(wParam) == WINAMP_MAIN_WINDOW)
|
||
{
|
||
for (int i = 0;i < SkinParser::getNumContainers();i++)
|
||
{
|
||
Container *cont = SkinParser::enumContainer(i);
|
||
if (!_wcsicmp(cont->getId(), L"main"))
|
||
{
|
||
cont->toggle();
|
||
return 1;
|
||
}
|
||
}
|
||
}
|
||
else if ((uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND) && LOWORD(wParam) == WINAMP_OPTIONS_EQ)
|
||
{
|
||
if (!gothrueqmsg)
|
||
return 0;
|
||
}
|
||
else if ((uMsg == WM_COMMAND || uMsg == WM_SYSCOMMAND))
|
||
{
|
||
switch (LOWORD(wParam))
|
||
{
|
||
case ID_CONTROLMENU_OPACITY_10: controlOpacity(10); return 0;
|
||
case ID_CONTROLMENU_OPACITY_20: controlOpacity(20); return 0;
|
||
case ID_CONTROLMENU_OPACITY_30: controlOpacity(30); return 0;
|
||
case ID_CONTROLMENU_OPACITY_40: controlOpacity(40); return 0;
|
||
case ID_CONTROLMENU_OPACITY_50: controlOpacity(50); return 0;
|
||
case ID_CONTROLMENU_OPACITY_60: controlOpacity(60); return 0;
|
||
case ID_CONTROLMENU_OPACITY_70: controlOpacity(70); return 0;
|
||
case ID_CONTROLMENU_OPACITY_80: controlOpacity(80); return 0;
|
||
case ID_CONTROLMENU_OPACITY_90: controlOpacity(90); return 0;
|
||
case ID_CONTROLMENU_OPACITY_100: controlOpacity(100); return 0;
|
||
case ID_CONTROLMENU_SCALING_50: controlScaling(0.5); return 0;
|
||
case ID_CONTROLMENU_SCALING_75: controlScaling(0.75); return 0;
|
||
case ID_CONTROLMENU_SCALING_100: controlScaling(1.0); return 0;
|
||
case ID_CONTROLMENU_SCALING_125: controlScaling(1.25); return 0;
|
||
case ID_CONTROLMENU_SCALING_150: controlScaling(1.5); return 0;
|
||
case ID_CONTROLMENU_SCALING_200: controlScaling(2.0); return 0;
|
||
case ID_CONTROLMENU_SCALING_250: controlScaling(2.5); return 0;
|
||
case ID_CONTROLMENU_SCALING_300: controlScaling(3.0); return 0;
|
||
case ID_CONTROLMENU_SCALING_LOCKED: lockScaling(1); return 0;
|
||
case ID_CONTROLMENU_SCALING_FOLLOWDOUBLESIZE: lockScaling(0); return 0;
|
||
case ID_CONTROLMENU_SCALING_CUSTOM: customScaling(); return 0;
|
||
case ID_CONTROLMENU_OPACITY_CUSTOM: customOpacity(); return 0;
|
||
case ID_CONTROLMENU_OPACITY_AUTO100_HOVER: autoOpacifyHover(); return 0;
|
||
case ID_CONTROLMENU_OPACITY_AUTO100_FOCUS: autoOpacifyFocus(); return 0;
|
||
case SC_MOVE:
|
||
{
|
||
Layout *l = SkinParser::getMainLayout();
|
||
if (l != NULL)
|
||
{
|
||
Container *c = l->getParentContainer();
|
||
if (c)
|
||
{
|
||
Layout *ll = c->getCurrentLayout();
|
||
if (ll) l = ll;
|
||
if (l)
|
||
{
|
||
if (!l->isVisible()) l->setVisible(1);
|
||
return SendMessageW(l->gethWnd(), WM_SYSCOMMAND, wParam, lParam);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case ID_CONTROLMENU_TOOLBAR_DISABLED: controlAppBar(APPBAR_NOTDOCKED); break;
|
||
case ID_CONTROLMENU_TOOLBAR_TOP: controlAppBar(APPBAR_TOP); break;
|
||
case ID_CONTROLMENU_TOOLBAR_LEFT: controlAppBar(APPBAR_LEFT); break;
|
||
case ID_CONTROLMENU_TOOLBAR_RIGHT: controlAppBar(APPBAR_RIGHT); break;
|
||
case ID_CONTROLMENU_TOOLBAR_BOTTOM: controlAppBar(APPBAR_BOTTOM); break;
|
||
case ID_CONTROLMENU_TOOLBAR_ALWAYSONTOP: controlAppBarAOT(); break;
|
||
case ID_CONTROLMENU_TOOLBAR_AUTOHIDE: controlAppBarAH(); break;
|
||
case ID_CONTROLMENU_TOOLBAR_AUTODOCKONDRAG: cfg_options_appbarondrag = !cfg_options_appbarondrag; break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return CallWinampWndProc(hwndDlg, uMsg, wParam, lParam);
|
||
}
|
||
|
||
void onLayoutChanged()
|
||
{
|
||
if (DEFERREDCALLBACKMSG > 65536)
|
||
PostMessage(wa2.getMainWindow(), WM_WA_IPC, 1, DEFERREDCALLBACKMSG);
|
||
}
|
||
|
||
#ifdef DEBUG_CAPTURES
|
||
int tid = 0;
|
||
|
||
VOID TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD time)
|
||
{
|
||
DebugString("Capture belongs to %x (foregroundwnd = %x)\n", GetCapture(), GetForegroundWindow());
|
||
}
|
||
#endif
|
||
|
||
template <class api_T>
|
||
static 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>
|
||
static 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;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// initializes freeform library
|
||
//-----------------------------------------------------------------------------------------------
|
||
int m_loaded_at_all = 0;
|
||
StringW g_resourcepath;
|
||
|
||
void initFFApi()
|
||
{
|
||
if ( !m_loaded_at_all )
|
||
{
|
||
m_loaded_at_all = 1;
|
||
api_service *svc = (api_service *)SendMessageW( wa2.getMainWindow(), WM_WA_IPC, 0, IPC_GET_API_SERVICE );
|
||
|
||
ServiceBuild( AGAVE_API_PLAYLISTS, api_playlistsGUID );
|
||
ServiceBuild( AGAVE_API_ALBUMART, albumArtGUID );
|
||
ServiceBuild( AGAVE_API_PLAYLISTMANAGER, api_playlistmanagerGUID );
|
||
ServiceBuild( WAC_API_DOWNLOADMANAGER, DownloadManagerGUID );
|
||
ServiceBuild( WASABI_API_COLORTHEMES, ColorThemesAPIGUID );
|
||
ServiceBuild( WASABI_API_PALETTE, PaletteManagerGUID );
|
||
ServiceBuild( WASABI_API_THREADPOOL, ThreadPoolGUID );
|
||
|
||
ApiInit::init( hInstance, wa2.getMainWindow(), svc );
|
||
cfgitems = new Wa2CfgItems();
|
||
|
||
#ifdef DEBUG_CAPTURES
|
||
tid = SetTimer( NULL, 0x159, 50, (TIMERPROC)TimerProc );
|
||
#endif
|
||
|
||
wchar_t filename[ WA_MAX_PATH ] = { 0 };
|
||
GetModuleFileNameW( hInstance, filename, WA_MAX_PATH );
|
||
PathParserW pp( filename );
|
||
StringW path;
|
||
for ( int i = 0; i < pp.getNumStrings() - 1; i++ )
|
||
{
|
||
path.AppendPath( pp.enumString( i ) );
|
||
}
|
||
path.AppendPath( L"freeform" );
|
||
path.AppendFolder( L"wacs" );
|
||
|
||
// we can load a somewhat restricted version of the wac format
|
||
|
||
ComponentManager::loadAll( path );
|
||
ComponentManager::postLoad();
|
||
|
||
ApiInit::widgets->loadResources();
|
||
|
||
startFSMonitor();
|
||
}
|
||
cfg_options_alwaysontop.setValueAsInt( wa2.isOnTop() );
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// shutdown ff lib
|
||
//-----------------------------------------------------------------------------------------------
|
||
void shutdownFFApi()
|
||
{
|
||
if (m_loaded_at_all)
|
||
{
|
||
ServiceRelease( AGAVE_API_PLAYLISTS, api_playlistsGUID);
|
||
ServiceRelease( AGAVE_API_ALBUMART, albumArtGUID);
|
||
ServiceRelease( AGAVE_API_PLAYLISTMANAGER, api_playlistmanagerGUID);
|
||
ServiceRelease( WAC_API_DOWNLOADMANAGER, DownloadManagerGUID);
|
||
ServiceRelease( WASABI_API_COLORTHEMES, ColorThemesAPIGUID);
|
||
ServiceRelease( WASABI_API_PALETTE, PaletteManagerGUID);
|
||
ServiceRelease( WASABI_API_THREADPOOL, ThreadPoolGUID);
|
||
|
||
stopFSMonitor();
|
||
|
||
// shutdown the library
|
||
#ifdef DEBUG_CAPTURES
|
||
KillTimer(NULL, tid);
|
||
#endif
|
||
|
||
delete cfgitems; cfgitems = NULL;
|
||
ApiInit::shutdown();
|
||
ComponentManager::unloadAll();
|
||
|
||
m_loaded_at_all = 0;
|
||
}
|
||
}
|
||
|
||
static void MakeControlMenu()
|
||
{
|
||
if (controlmenu)
|
||
return ;
|
||
|
||
controlmenu = WASABI_API_LOADMENU(IDR_CONTROLMENU);
|
||
|
||
if (!Wasabi::Std::Wnd::isDesktopAlphaAvailable())
|
||
EnableMenuItem(controlmenu, 0, MF_BYPOSITION | MF_GRAYED);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// go freeform
|
||
//-----------------------------------------------------------------------------------------------
|
||
void init_inst()
|
||
{
|
||
if ( m_are_we_loaded )
|
||
return;
|
||
|
||
// set the classic main window to be transparent
|
||
// so we can move it around the screen to allow
|
||
// certain Windows 8 modes as well as improving
|
||
// where it is placed for some multi-mon setups
|
||
Wasabi::Std::Wnd::setLayeredWnd( wa2.getMainWindow(), 1 );
|
||
Wasabi::Std::Wnd::setLayeredAlpha( wa2.getMainWindow(), 0 );
|
||
|
||
initEgg();
|
||
|
||
wa2.setDrawBorders( 0 );
|
||
wa2.disableSkinnedCursors( 1 );
|
||
|
||
int wasminimized = IsIconic( wa2.getMainWindow() );
|
||
if ( wasminimized )
|
||
ShowWindow( wa2.getMainWindow(), SW_RESTORE );
|
||
|
||
MakeControlMenu();
|
||
|
||
going_freeform = 1;
|
||
|
||
Wa2WndEmbed::rememberVisibleWindows();
|
||
|
||
if ( wa2.isWindowVisible( IPC_GETWND_PE ) )
|
||
{
|
||
if ( !m_loading_at_startup ) WritePrivateProfileStringW( L"gen_ff", L"classicpe", L"1", INI_FILE );
|
||
}
|
||
else
|
||
if ( !m_loading_at_startup ) WritePrivateProfileStringW( L"gen_ff", L"classicpe", L"0", INI_FILE );
|
||
|
||
if ( wa2.isWindowVisible( IPC_GETWND_EQ ) )
|
||
{
|
||
gothrueqmsg = 1;
|
||
SendMessageW( plugin.hwndParent, WM_COMMAND, WINAMP_OPTIONS_EQ, 0 );
|
||
gothrueqmsg = 0;
|
||
if ( !m_loading_at_startup ) WritePrivateProfileStringW( L"gen_ff", L"classiceq", L"1", INI_FILE );
|
||
}
|
||
else
|
||
if ( !m_loading_at_startup ) WritePrivateProfileStringW( L"gen_ff", L"classiceq", L"0", INI_FILE );
|
||
|
||
removeEq();
|
||
|
||
if ( SendMessageW( plugin.hwndParent, WM_WA_IPC, 0, IPC_ISMAINWNDVISIBLE ) )
|
||
{
|
||
SendMessageW( plugin.hwndParent, WM_COMMAND, WINAMP_MAIN_WINDOW, 0 );
|
||
if ( !m_loading_at_startup ) WritePrivateProfileStringW( L"gen_ff", L"classicmw", L"1", INI_FILE );
|
||
}
|
||
else
|
||
if ( !m_loading_at_startup ) WritePrivateProfileStringW( L"gen_ff", L"classicmw", L"0", INI_FILE );
|
||
|
||
m_are_we_loaded = 1;
|
||
|
||
initFFApi();
|
||
|
||
// redirect drag and drop to winamp2 by default
|
||
WASABI_API_WND->setDefaultDropTarget( (void *)wa2.getDropTarget() );
|
||
|
||
// this installs a bunch of predefined groups to map wa3 to wa2 functionnality
|
||
groups = new Wa2Groupdefs();
|
||
|
||
// now load a skin ! the path to the skin is extracted and temporarilly becomes the official skins directory
|
||
|
||
StringW skinname = m_lastskin_nam;
|
||
|
||
removeSkinExtension( skinname );
|
||
|
||
before_startup_callback = 1;
|
||
WASABI_API_SKIN->skin_switchSkin( skinname, m_lastskin_dir );
|
||
|
||
/* // if we wanted to have drag&drop support for just the main window, we'd do it this way :-)
|
||
Container *maincontainer = SkinParser::getContainer("main");
|
||
if (maincontainer != NULL) {
|
||
for (int i=0;i<maincontainer->getNumLayouts();i++) {
|
||
Layout *layout = maincontainer->enumLayout(i);
|
||
if (layout != NULL) {
|
||
layout->setDropTarget((void *)wa2.getDropTarget());
|
||
}
|
||
}
|
||
}*/
|
||
|
||
// send event for dialog parent
|
||
onLayoutChanged();
|
||
|
||
if ( wa2.export_sa_setreq )
|
||
wa2.export_sa_setreq( 1 );
|
||
|
||
shuffle.setValueAsInt( wa2.getShuffle() );
|
||
|
||
int rep = wa2.getRepeat();
|
||
int manadv = wa2.getManualPlaylistAdvance();
|
||
|
||
disable_set_wa2_repeat = 1;
|
||
repeat.setValueAsInt( ( rep && manadv ) ? -1 : rep );
|
||
disable_set_wa2_repeat = 0;
|
||
|
||
if ( DEFERREDCALLBACKMSG > 65536 )
|
||
PostMessage( wa2.getMainWindow(), WM_WA_IPC, 2, DEFERREDCALLBACKMSG );
|
||
|
||
// so if some embedwindows are already visible, they update their look
|
||
PostMessage( wa2.getMainWindow(), WM_WA_IPC, 0xf00d, IPC_FF_ONCOLORTHEMECHANGED );
|
||
|
||
// monitor color theme
|
||
colorThemeMonitor = new ColorThemeMonitor();
|
||
|
||
syncDoubleSize( 1 );
|
||
syncDisplayMode();
|
||
|
||
going_freeform = 0;
|
||
|
||
if ( wa2.getWnd( IPC_GETWND_VIDEO ) )
|
||
{
|
||
oldVideoWnd = wa2.getWnd( IPC_GETWND_VIDEO );
|
||
if ( !oldVideoWndProc )
|
||
oldVideoWndProc = (WNDPROC)SetWindowLongPtrW( oldVideoWnd, GWLP_WNDPROC, (LONG_PTR)newVideoWndProc );
|
||
}
|
||
|
||
if ( wasminimized )
|
||
ShowWindow( wa2.getMainWindow(), SW_MINIMIZE );
|
||
|
||
if ( eggstat )
|
||
SetTimer( wa2.getMainWindow(), UPDATE_EGG, 25, NULL );
|
||
}
|
||
|
||
void quit_inst()
|
||
{
|
||
if (!m_are_we_loaded) return ;
|
||
|
||
KillTimer(wa2.getMainWindow(), UPDATE_EGG);
|
||
|
||
wa2.setDrawBorders(1);
|
||
wa2.disableSkinnedCursors(0);
|
||
|
||
KillTimer(wa2.getMainWindow(), 0xC0DE);
|
||
KillTimer(wa2.getMainWindow(), 0xC0DE + 1);
|
||
|
||
EnableMenuItem(wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_OPTIONS), WINAMP_OPTIONS_DSIZE, MF_ENABLED);
|
||
EnableMenuItem(GetSubMenu(wa2.getPopupMenu(), 11 + wa2.adjustOptionsPopupMenu(0)), WINAMP_OPTIONS_DSIZE, MF_ENABLED);
|
||
|
||
if (oldVideoWnd && oldVideoWndProc)
|
||
SetWindowLongPtrW(oldVideoWnd, GWLP_WNDPROC, (LONG_PTR)oldVideoWndProc);
|
||
oldVideoWndProc = 0;
|
||
oldVideoWnd = 0;
|
||
|
||
removeWindowOptionsFromContextMenu();
|
||
|
||
delete mainLayoutMonitor;
|
||
mainLayoutMonitor=0;
|
||
|
||
wa2.setDialogBoxParent(NULL);
|
||
unpopulateWindowsMenus();
|
||
restoreEq();
|
||
|
||
// unload the skin -- skinspath is restored to default
|
||
WASABI_API_SKIN->skin_unloadSkin();
|
||
|
||
// delete predefined groups service
|
||
delete groups; groups = NULL;
|
||
|
||
// delete options
|
||
delete ffoptions; ffoptions = NULL;
|
||
|
||
// stop monitoring color theme
|
||
delete colorThemeMonitor; colorThemeMonitor = NULL;
|
||
|
||
if (wa2.export_sa_setreq) wa2.export_sa_setreq(0);
|
||
|
||
m_are_we_loaded = 0;
|
||
|
||
int classicmw = GetPrivateProfileIntW(L"gen_ff", L"classicmw", 1, INI_FILE);
|
||
if (classicmw && !SendMessageW(plugin.hwndParent, WM_WA_IPC, 0, IPC_ISMAINWNDVISIBLE))
|
||
SendMessageW(plugin.hwndParent, WM_COMMAND, WINAMP_MAIN_WINDOW, 0);
|
||
|
||
CheckMenuItem(wa2.getPopupMenu(), WINAMP_MAIN_WINDOW, classicmw ? MF_CHECKED : MF_UNCHECKED);
|
||
|
||
if (GetPrivateProfileIntW(L"gen_ff", L"classiceq", 1, INI_FILE) && !wa2.isWindowVisible(IPC_GETWND_EQ))
|
||
{
|
||
gothrueqmsg = 1;
|
||
SendMessageW(plugin.hwndParent, WM_COMMAND, WINAMP_OPTIONS_EQ, 0);
|
||
gothrueqmsg = 0;
|
||
}
|
||
|
||
if (GetPrivateProfileIntW(L"gen_ff", L"classicpe", 1, INI_FILE) && !wa2.isWindowVisible(IPC_GETWND_PE))
|
||
{
|
||
SendMessageW(plugin.hwndParent, WM_COMMAND, WINAMP_OPTIONS_PLEDIT, 0);
|
||
}
|
||
|
||
// restore the classic main window to be solid
|
||
Wasabi::Std::Wnd::setLayeredWnd(wa2.getMainWindow(), 0);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// init (from Winamp2)
|
||
//-----------------------------------------------------------------------------------------------
|
||
int init()
|
||
{
|
||
// loader so that we can get the localisation service api for use
|
||
WASABI_API_SVC = (api_service*) SendMessageW(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);
|
||
if (WASABI_API_SVC == (api_service*)1) WASABI_API_SVC = NULL;
|
||
if (!WASABI_API_SVC || WASABI_API_SVC == (api_service *)1)
|
||
return GEN_INIT_FAILURE;
|
||
|
||
static wchar_t modskin[128];
|
||
INI_FILE = (wchar_t*) SendMessageW(plugin.hwndParent, WM_WA_IPC, 0, IPC_GETINIFILEW);
|
||
INI_DIR = (wchar_t*) SendMessageW(plugin.hwndParent, WM_WA_IPC, 0, IPC_GETINIDIRECTORYW);
|
||
|
||
waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(languageApiGUID);
|
||
if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
|
||
|
||
// need to have this initialised before we try to do anything with localisation features
|
||
WASABI_API_START_LANG(plugin.hDllInstance,GenFFLangGUID);
|
||
|
||
swprintf(szDescription, ARRAYSIZE(szDescription),
|
||
WASABI_API_LNGSTRINGW(IDS_NULLSOFT_MODERN_SKINS), VERSION);
|
||
plugin.description = (char*)szDescription;
|
||
|
||
wa2.init(plugin.hwndParent);
|
||
|
||
DEFERREDCALLBACKMSG = SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)"gen_ff_deferred", IPC_REGISTER_WINAMP_IPCMESSAGE);
|
||
UPDATEDIALOGBOXPARENTMSG = SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)"gen_ff_update", IPC_REGISTER_WINAMP_IPCMESSAGE);
|
||
|
||
// subclass the Winamp2 main window to receive our callbacks
|
||
wa_oldWndProc = (WNDPROC) SetWindowLongPtrW(wa2.getMainWindow(), GWLP_WNDPROC, (LONG_PTR)wa_newWndProc);
|
||
|
||
ffPrefsItem.dlgID = IDD_PREFS;
|
||
ffPrefsItem.name = WASABI_API_LNGSTRINGW_BUF(IDS_MODERN_SKINS,modskin,128);
|
||
ffPrefsItem.proc = (void*)ffPrefsProc;
|
||
ffPrefsItem.hInst = WASABI_API_LNG_HINST;
|
||
ffPrefsItem.where = 2; //skins subtreeitem
|
||
SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&ffPrefsItem, IPC_ADD_PREFS_DLGW);
|
||
|
||
checkMlPresent();
|
||
|
||
m_loading_at_startup = 1;
|
||
onSkinSwitch();
|
||
m_loading_at_startup = 0;
|
||
return 0;
|
||
}
|
||
|
||
void RestoreClassicWinamp(int was_loaded)
|
||
{
|
||
// JF> my proposed fix to the problems :)
|
||
// investigating doing this from winamp.exe on startup, gotta figure it out
|
||
if (INI_FILE && was_loaded) // restore winamp.ini to about what it shoulda been
|
||
{
|
||
int classicpews = GetPrivateProfileIntW(L"gen_ff", L"classicplws", 0, INI_FILE);
|
||
int classicwidth = GetPrivateProfileIntW(L"gen_ff", L"classicplwidth", 275, INI_FILE);
|
||
int classicheight = GetPrivateProfileIntW(L"gen_ff", L"classicplheight", 145, INI_FILE);
|
||
int classicmw = GetPrivateProfileIntW(L"gen_ff", L"classicmw", 1, INI_FILE);
|
||
int classiceq = GetPrivateProfileIntW(L"gen_ff", L"classiceq", 1, INI_FILE);
|
||
wchar_t buf[64] = {0};
|
||
|
||
wsprintfW(buf, L"%d", classicheight);
|
||
if (classicpews)
|
||
{
|
||
WritePrivateProfileStringW(L"winamp", L"pe_height", L"14", INI_FILE);
|
||
WritePrivateProfileStringW(L"winamp", L"pe_height_ws", buf, INI_FILE);
|
||
}
|
||
else
|
||
{
|
||
WritePrivateProfileStringW(L"winamp", L"pe_height", buf, INI_FILE);
|
||
WritePrivateProfileStringW(L"winamp", L"pe_height_ws", L"", INI_FILE);
|
||
}
|
||
wsprintfW(buf, L"%d", classicwidth);
|
||
WritePrivateProfileStringW(L"winamp", L"pe_width", buf, INI_FILE);
|
||
|
||
WritePrivateProfileStringW(L"winamp", L"eq_open", classiceq ? L"1" : L"0", INI_FILE);
|
||
WritePrivateProfileStringW(L"winamp", L"mw_open", classicmw ? L"1" : L"0", INI_FILE);
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// quit (from Winamp 2)
|
||
//-----------------------------------------------------------------------------------------------
|
||
void quit()
|
||
{
|
||
int was_loaded = m_are_we_loaded;
|
||
quit_inst();
|
||
|
||
RestoreClassicWinamp(was_loaded);
|
||
// restore wa2's windowproc
|
||
//SetWindowLong(wa2.getMainWindow(), GWL_WNDPROC, (LONG)wa_oldWndProc);
|
||
shutdownFFApi();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// About box wndproc
|
||
//-----------------------------------------------------------------------------------------------
|
||
ifc_window *about_group = NULL;
|
||
StringW oldrenderer;
|
||
BOOL CALLBACK aboutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
switch (uMsg)
|
||
{
|
||
case WM_INITDIALOG:
|
||
{
|
||
oldrenderer = cfg_options_fontrenderer.getValue();
|
||
if (!WCSCASEEQLSAFE(cfg_options_fontrenderer.getValue(), L"FreeType"))
|
||
cfg_options_fontrenderer.setValue(L"FreeType");
|
||
about_group = WASABI_API_SKIN->group_create(L"wasabi.gen_ff.about");
|
||
about_group->setVirtual(0);
|
||
HWND w = GetDlgItem(hwndDlg, IDC_STATIC_GROUP);
|
||
about_group->setStartHidden(1);
|
||
about_group->init(WASABI_API_WND->main_getRootWnd(), 1);
|
||
SetWindowLong(about_group->gethWnd(), GWL_STYLE, GetWindowLong(about_group->gethWnd(), GWL_STYLE) | WS_CHILD);
|
||
SetParent(about_group->gethWnd(), w);
|
||
SetWindowLong(w, GWL_STYLE, GetWindowLong(w, GWL_STYLE) | WS_CLIPCHILDREN);
|
||
RECT r;
|
||
GetClientRect(w, &r);
|
||
about_group->resize(r.left + 1, r.top + 1, r.right - r.left - 2, r.bottom - r.top - 2);
|
||
about_group->setVisible(1);
|
||
C_Group g(about_group->getGuiObject()->guiobject_getScriptObject());
|
||
ScriptObject *ver = g.findObject(L"version");
|
||
if (ver)
|
||
{
|
||
C_Text t(ver);
|
||
t.setText(StringPrintfW(L". <20> 2003-2023 Winamp SA %s", VERSION));
|
||
}
|
||
ShowWindow(about_group->gethWnd(), SW_NORMAL);
|
||
return 1;
|
||
}
|
||
case WM_DESTROY:
|
||
WASABI_API_SKIN->group_destroy(about_group);
|
||
about_group = NULL;
|
||
break;
|
||
case WM_COMMAND:
|
||
switch (LOWORD(wParam))
|
||
{
|
||
case IDOK: case IDCANCEL:
|
||
if (!WCSCASEEQLSAFE(cfg_options_fontrenderer.getValue(), oldrenderer))
|
||
cfg_options_fontrenderer.setValue(oldrenderer);
|
||
EndDialog(hwndDlg, 0);
|
||
return 0;
|
||
}
|
||
return 0;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// configure plugin (from Winamp 2)
|
||
//-----------------------------------------------------------------------------------------------
|
||
void config()
|
||
{
|
||
if (m_loaded_at_all)
|
||
{
|
||
StringW skin = WASABI_API_SKIN->getSkinName();
|
||
wchar_t _skName[64] = {0};
|
||
WASABI_API_LNGSTRINGW_BUF(IDS_NO_SKIN_LOADED_,_skName,64);
|
||
|
||
if ((!skin.iscaseequal(_skName)) || guiTree->getNumObject() > 0)
|
||
{
|
||
WASABI_API_DIALOGBOXW(IDD_ABOUT, wa2.getPreferencesWindow(), aboutProc);
|
||
return ;
|
||
}
|
||
}
|
||
|
||
MSGBOXPARAMSW msgbx = {sizeof(MSGBOXPARAMS),0};
|
||
msgbx.lpszText = WASABI_API_LNGSTRINGW(IDS_MODERN_SKIN_SUPPORT_CLASSIC);
|
||
msgbx.lpszCaption = szDescription;
|
||
msgbx.lpszIcon = MAKEINTRESOURCEW(102);
|
||
msgbx.hInstance = GetModuleHandle(0);
|
||
msgbx.dwStyle = MB_USERICON;
|
||
MessageBoxIndirectW(&msgbx);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// expose the genpurp plugin interface to dll
|
||
//-----------------------------------------------------------------------------------------------
|
||
extern "C" __declspec(dllexport) winampGeneralPurposePlugin * winampGetGeneralPurposePlugin() { return &plugin; }
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// a window was right clicked where there was no custom context menu available, spawn Wa2's menu
|
||
//-----------------------------------------------------------------------------------------------
|
||
void appContextMenu(ifc_window *w)
|
||
{
|
||
if (!WASABI_API_WND->rootwndIsValid(w)) return ;
|
||
WASABI_API_WND->appdeactivation_setbypass(1);
|
||
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||
w->setFocus();
|
||
DWORD p = GetMessagePos();
|
||
int x = GET_X_LPARAM(p);
|
||
int y = GET_Y_LPARAM(p);
|
||
addWindowOptionsToContextMenu(w);
|
||
wa2.triggerPopupMenu(x, y);
|
||
WASABI_API_WND->appdeactivation_setbypass(0);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void updateControlMenu(ifc_window *w)
|
||
{
|
||
int curalpha = 255;
|
||
double curratio = 1.;
|
||
int opacitysafe = 0;
|
||
int scalelocked = 0;
|
||
int auto100_hover = 0;
|
||
int auto100_focus = 0;
|
||
|
||
if (g_controlMenuTarget == NULL) return ;
|
||
|
||
if (w)
|
||
{
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (rootparent && rootparent->getInterface(layoutGuid))
|
||
{
|
||
Layout *l = static_cast<Layout*>(rootparent);
|
||
opacitysafe = l->isTransparencySafe();
|
||
scalelocked = l->isScaleLocked();
|
||
curratio = w->getRenderRatio();
|
||
if (!cfg_uioptions_linkallalpha.getValueAsInt())
|
||
{
|
||
auto100_hover = l->getAutoOpacify() == 1;
|
||
auto100_focus = l->getAutoOpacify() == 2;
|
||
curalpha = l->getAlpha();
|
||
}
|
||
else
|
||
{
|
||
auto100_hover = l->getAlphaMgr()->getAutoOpacify() == 1;
|
||
auto100_focus = l->getAlphaMgr()->getAutoOpacify() == 2;
|
||
curalpha = l->getAlphaMgr()->getGlobalAlpha();
|
||
}
|
||
}
|
||
}
|
||
|
||
HMENU ctrlmenu = GetSubMenu(controlmenu, 0);
|
||
EnableMenuItem(ctrlmenu, 0, MF_BYPOSITION | (opacitysafe ? MF_ENABLED : MF_GRAYED));
|
||
HMENU scalemenu = GetSubMenu(ctrlmenu, 1);
|
||
HMENU alphamenu = GetSubMenu(ctrlmenu, 0);
|
||
int uselocks = cfg_uioptions_uselocks.getValueAsInt();
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_LOCKED, MF_BYCOMMAND | ((scalelocked || !uselocks) ? MF_CHECKED : MF_UNCHECKED));
|
||
EnableMenuItem(scalemenu, ID_CONTROLMENU_SCALING_LOCKED, MF_BYCOMMAND | (uselocks ? MF_ENABLED : MF_GRAYED));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_FOLLOWDOUBLESIZE, MF_BYCOMMAND | (scalelocked || !uselocks ? MF_UNCHECKED : MF_CHECKED));
|
||
EnableMenuItem(scalemenu, ID_CONTROLMENU_SCALING_FOLLOWDOUBLESIZE, MF_BYCOMMAND | (uselocks ? MF_ENABLED : MF_GRAYED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_AUTO100_HOVER, MF_BYCOMMAND | (auto100_hover ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_AUTO100_FOCUS, MF_BYCOMMAND | (auto100_focus ? MF_CHECKED : MF_UNCHECKED));
|
||
|
||
int v = (int)((curalpha / 255.0f * 100.0f) + 0.5f);
|
||
int u = (int)((curratio * 100.0f) + 0.5f);
|
||
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_10, MF_BYCOMMAND | (v == 10 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_20, MF_BYCOMMAND | (v == 20 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_30, MF_BYCOMMAND | (v == 30 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_40, MF_BYCOMMAND | (v == 40 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_50, MF_BYCOMMAND | (v == 50 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_60, MF_BYCOMMAND | (v == 60 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_70, MF_BYCOMMAND | (v == 70 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_80, MF_BYCOMMAND | (v == 80 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_90, MF_BYCOMMAND | (v == 90 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_100, MF_BYCOMMAND | (v == 100 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_50, MF_BYCOMMAND | (u == 50 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_75, MF_BYCOMMAND | (u == 75 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_100, MF_BYCOMMAND | (u == 100 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_125, MF_BYCOMMAND | (u == 125 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_150, MF_BYCOMMAND | (u == 150 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_200, MF_BYCOMMAND | (u == 200 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_250, MF_BYCOMMAND | (u == 250 ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_300, MF_BYCOMMAND | (u == 300 ? MF_CHECKED : MF_UNCHECKED));
|
||
|
||
if (u != 50 && u != 75 && u != 100 && u != 125 && u != 150 && u != 200 && u != 250 && u != 300)
|
||
{
|
||
ModifyMenuW(scalemenu, ID_CONTROLMENU_SCALING_CUSTOM, MF_BYCOMMAND | MF_STRING, ID_CONTROLMENU_SCALING_CUSTOM, StringPrintfW(WASABI_API_LNGSTRINGW(IDS_CUSTOM_X_PERCENT), u));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_CUSTOM, MF_BYCOMMAND | MF_CHECKED);
|
||
}
|
||
else
|
||
{
|
||
ModifyMenuW(scalemenu, ID_CONTROLMENU_SCALING_CUSTOM, MF_BYCOMMAND | MF_STRING, ID_CONTROLMENU_SCALING_CUSTOM, WASABI_API_LNGSTRINGW(IDS_CUSTOM));
|
||
CheckMenuItem(scalemenu, ID_CONTROLMENU_SCALING_CUSTOM, MF_BYCOMMAND | MF_UNCHECKED);
|
||
}
|
||
if (((float)v / 10.0) - (v / 10) != 0.0)
|
||
{
|
||
ModifyMenuW(alphamenu, ID_CONTROLMENU_OPACITY_CUSTOM, MF_BYCOMMAND | MF_STRING, ID_CONTROLMENU_OPACITY_CUSTOM, StringPrintfW(WASABI_API_LNGSTRINGW(IDS_CUSTOM_X_PERCENT), v));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_CUSTOM, MF_BYCOMMAND | MF_CHECKED);
|
||
}
|
||
else
|
||
{
|
||
ModifyMenuW(alphamenu, ID_CONTROLMENU_OPACITY_CUSTOM, MF_BYCOMMAND | MF_STRING, ID_CONTROLMENU_OPACITY_CUSTOM, WASABI_API_LNGSTRINGW(IDS_CUSTOM));
|
||
CheckMenuItem(alphamenu, ID_CONTROLMENU_OPACITY_CUSTOM, MF_BYCOMMAND | MF_UNCHECKED);
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// a window has triggered the control menu (control scale & alpha)
|
||
//-----------------------------------------------------------------------------------------------
|
||
void appControlMenu(ifc_window *w)
|
||
{
|
||
WASABI_API_WND->appdeactivation_setbypass(1);
|
||
int x, y;
|
||
if (w)
|
||
{
|
||
Wasabi::Std::getMousePos(&x, &y);
|
||
g_controlMenuTarget = w;
|
||
updateControlMenu(w);
|
||
updateAppBarMenu(w);
|
||
HMENU ctrlmenu = GetSubMenu(controlmenu, 0);
|
||
DoTrackPopup(ctrlmenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, x, y, wa2.getMainWindow());
|
||
}
|
||
WASABI_API_WND->appdeactivation_setbypass(0);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// a close application button was clicked
|
||
//-----------------------------------------------------------------------------------------------
|
||
void appQuit()
|
||
{
|
||
if (!wa2.isExitEnabled()) return ;
|
||
wa2.quit(); // this is in fact *posting* a quit message
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// a fatal skin error occured, we should revert to the wa2 skin (deferred)
|
||
//-----------------------------------------------------------------------------------------------
|
||
#define DCB_UNLOADSKIN 64
|
||
|
||
class deferredUnloadSkin : public TimerClientDI
|
||
{
|
||
public:
|
||
deferredUnloadSkin()
|
||
{
|
||
timerclient_postDeferredCallback(DCB_UNLOADSKIN, 0);
|
||
}
|
||
|
||
virtual int timerclient_onDeferredCallback(intptr_t param1, intptr_t param2)
|
||
{
|
||
if (param1 == DCB_UNLOADSKIN)
|
||
{
|
||
quit_inst();
|
||
delete this;
|
||
return 1;
|
||
}
|
||
else return TimerClientDI::timerclient_onDeferredCallback(param1, param2);
|
||
}
|
||
};
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// this is the actual event for skin fata errors, it is called when a try/except block failed
|
||
// upon calling a skin operation which should not be able to fail (ie: calling a script function pointer)
|
||
//-----------------------------------------------------------------------------------------------
|
||
void onFatalSkinError()
|
||
{
|
||
new deferredUnloadSkin();
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// map a GUID to the toggling of a window for which there is no permanent wndCreationService,
|
||
// ie: library, prefs, avs
|
||
//-----------------------------------------------------------------------------------------------
|
||
|
||
// called by a skinwnd_toggle call when the guid isn't found in the wndcreation services
|
||
int onCreateExternalWindowGuid(GUID g)
|
||
{
|
||
if (g == library_guid)
|
||
{
|
||
SendMessageW(wa2.getMainWindow(), WM_COMMAND, ID_FILE_SHOWLIBRARY, 0);
|
||
return 1;
|
||
}
|
||
else if (g == preferences_guid)
|
||
{
|
||
SendMessageW(wa2.getMainWindow(), WM_COMMAND, WINAMP_OPTIONS_PREFS, 0);
|
||
return 1;
|
||
}
|
||
else if (g == about_guid)
|
||
{
|
||
SendMessageW(wa2.getMainWindow(), WM_COMMAND, WINAMP_HELP_ABOUT, 0);
|
||
return 1;
|
||
}
|
||
else if (g == lightning_bolt_guid)
|
||
{
|
||
SendMessageW(wa2.getMainWindow(), WM_COMMAND, WINAMP_LIGHTNING_CLICK, 0);
|
||
return 1;
|
||
}
|
||
else if (g == colorthemes_guid)
|
||
{
|
||
last_page.setData(L"3");
|
||
SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&ffPrefsItem, IPC_OPENPREFSTOPAGE);
|
||
return 1;
|
||
}
|
||
else if (g == avs_guid)
|
||
{
|
||
if (wa2.isVisRunning())
|
||
{
|
||
SetTimer(wa2.getMainWindow(), 0xC0DE, 50, NULL);
|
||
SetTimer(wa2.getMainWindow(), 0xC0DE + 1, 5000, NULL);
|
||
}
|
||
else
|
||
wa2.toggleVis();
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void onToggleDesktopAlpha(int v)
|
||
{
|
||
if (!toggle_from_wa2 && subWndId == 0 && IsWindow(subWnd)) SendMessageW(subWnd, WM_INITDIALOG, 0, 0);
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
// changes the name of a container so that static containers with the wrong name don't load the config
|
||
// values off the wrong name. this should match the WindowText of the embededwindow. note: this is only
|
||
// necessary for static containers holding an internal embedwnd (ie: library, avs, but not third party wnds
|
||
// as they can't be refered to by GUID anyway [if they can't be refered to by GUID, you can't make a static
|
||
// container for them])
|
||
//-----------------------------------------------------------------------------------------------
|
||
|
||
const wchar_t *onTweakContainerNameW(const wchar_t *name)
|
||
{
|
||
static wchar_t tweaked[96];
|
||
ZERO(tweaked);
|
||
if (!_wcsicmp(name, WASABI_API_LNG->GetStringFromGUIDW(GenMlLangGUID, plugin.hDllInstance, 18, tweaked, sizeof(tweaked)/sizeof(wchar_t))) ||
|
||
!_wcsicmp(name, L"Media Library") ||
|
||
!_wcsicmp(name, L"Winamp Library") ||
|
||
!_wcsicmp(name, L"Library"))
|
||
{
|
||
return WASABI_API_LNGSTRINGW_BUF(IDS_MEDIA_LIBRARY,tweaked, sizeof(tweaked)/sizeof(wchar_t));
|
||
}
|
||
if (!_wcsicmp(name, L"Avs")) return WASABI_API_LNGSTRINGW_BUF(IDS_VISUALIZATIONS,tweaked, sizeof(tweaked)/sizeof(wchar_t));
|
||
return name;
|
||
}
|
||
|
||
const wchar_t *GetMenuItemString(HMENU menu, int id, int bypos)
|
||
{
|
||
static StringW rtn;
|
||
rtn.trunc(0);
|
||
MENUITEMINFOW info = {sizeof(info), MIIM_DATA | MIIM_TYPE | MIIM_STATE | MIIM_ID, MFT_STRING, };
|
||
GetMenuItemInfoW(menu, id, bypos, &info);
|
||
if (info.cch > 0)
|
||
{
|
||
info.dwTypeData = WMALLOC(++info.cch + 1);
|
||
GetMenuItemInfoW(menu, id, bypos, &info);
|
||
info.dwTypeData[info.cch] = 0;
|
||
rtn = info.dwTypeData;
|
||
FREE(info.dwTypeData);
|
||
}
|
||
return rtn;
|
||
}
|
||
|
||
StringW eqmenustring;
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void removeEq()
|
||
{
|
||
if (eqremoved) return ;
|
||
eqremoved = 1;
|
||
eqmenustring = GetMenuItemString(wa2.getPopupMenu(), WINAMP_OPTIONS_EQ, FALSE);
|
||
RemoveMenu(wa2.getPopupMenu(), WINAMP_OPTIONS_EQ, MF_BYCOMMAND);
|
||
wa2.adjustOptionsPopupMenu(-1);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void restoreEq()
|
||
{
|
||
if (!eqremoved) return ;
|
||
MENUITEMINFOW i = {sizeof(i), MIIM_ID | MIIM_STATE | MIIM_TYPE, MFT_STRING, wa2.isWindowVisible(IPC_GETWND_EQ) ? MFS_CHECKED : 0, WINAMP_OPTIONS_EQ};
|
||
i.dwTypeData = eqmenustring.getNonConstVal();
|
||
InsertMenuItemW(wa2.getPopupMenu(), 8, TRUE, &i);
|
||
wa2.adjustOptionsPopupMenu(1);
|
||
eqremoved = 0;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void unpopulateWindowsMenus()
|
||
{
|
||
if (ffwindowsitempos == -1) return ;
|
||
|
||
HMENU menuBarMenu = wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_WINDOWS);
|
||
for(int i = GetMenuItemCount(menuBarMenu)-1; i >= 0; i--)
|
||
{
|
||
MENUITEMINFOW info = {sizeof(info), MIIM_DATA, 0, };
|
||
if(GetMenuItemInfoW(menuBarMenu,i,TRUE,&info))
|
||
{
|
||
if(info.dwItemData == 0xD01){
|
||
RemoveMenu(menuBarMenu,i,MF_BYPOSITION);
|
||
wa2.adjustFFWindowsMenu(-1);
|
||
}
|
||
}
|
||
}
|
||
|
||
HMENU menuPopupMenu = wa2.getPopupMenu();
|
||
for(int i = GetMenuItemCount(menuPopupMenu)-1; i >= 0; i--)
|
||
{
|
||
MENUITEMINFOW info = {sizeof(info), MIIM_DATA, 0, };
|
||
if(GetMenuItemInfoW(menuPopupMenu,i,TRUE,&info))
|
||
{
|
||
if(info.dwItemData == 0xD01){
|
||
RemoveMenu(menuPopupMenu,i,MF_BYPOSITION);
|
||
wa2.adjustOptionsPopupMenu(-1);
|
||
}
|
||
}
|
||
}
|
||
|
||
ffwindowsitempos = -1;
|
||
ffwindowsitempos2 = -1;
|
||
|
||
MenuActions::removeSkinWindowOptions();
|
||
MenuActions::removeSkinOptions();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void populateWindowsMenus()
|
||
{
|
||
if (ffwindowsitempos != -1) unpopulateWindowsMenus();
|
||
MenuActions::installSkinOptions();
|
||
MenuActions::installSkinWindowOptions();
|
||
|
||
ffwindowsitempos = wa2.adjustFFWindowsMenu(0) + NUMSTATICWINDOWS;
|
||
ffwindowsitempos2 = wa2.adjustOptionsPopupMenu(0) + 6 + NUMSTATICWINDOWS + 1;
|
||
|
||
MENUITEMINFOW i = {sizeof(i), };
|
||
i.fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID | MIIM_STATE;
|
||
i.fType = MFT_STRING;
|
||
i.wID = 43000;
|
||
i.dwItemData = 0xD01; // use this as a check so we're only removing the correct items!!
|
||
int pos = ffwindowsitempos;
|
||
int pos2 = ffwindowsitempos2;
|
||
PtrListQuickSorted<StringW, StringWComparator> items;
|
||
|
||
HMENU hMenu = wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_WINDOWS);
|
||
HMENU hMenu2 = wa2.getPopupMenu();
|
||
for (int c = 0;c < SkinParser::getNumContainers();c++)
|
||
{
|
||
Container *cont = SkinParser::enumContainer(c);
|
||
if (cont && wantContainerInMenu(cont))
|
||
{
|
||
i.dwTypeData = const_cast<wchar_t *>(cont->getName());
|
||
if (i.dwTypeData != NULL)
|
||
{
|
||
if (!items.findItem(i.dwTypeData))
|
||
{
|
||
items.addItem(new StringW(i.dwTypeData));
|
||
i.cch = wcslen(i.dwTypeData);
|
||
i.fState = cont->isVisible() ? MFS_CHECKED : 0;
|
||
InsertMenuItemW(hMenu, pos++, TRUE, &i);
|
||
wa2.adjustFFWindowsMenu(1);
|
||
InsertMenuItemW(hMenu2, pos2++, TRUE, &i);
|
||
wa2.adjustOptionsPopupMenu(1);
|
||
}
|
||
}
|
||
}
|
||
i.wID++;
|
||
}
|
||
|
||
int n = WASABI_API_WNDMGR->autopopup_getNumGuids();
|
||
for (int c = 0;c < n;c++)
|
||
{
|
||
GUID guid = WASABI_API_WNDMGR->autopopup_enumGuid(c);
|
||
const wchar_t *groupdesc = WASABI_API_WNDMGR->autopopup_enumGuidDescription(c);
|
||
if (guid != INVALID_GUID && groupdesc && *groupdesc)
|
||
{
|
||
i.dwTypeData = const_cast<wchar_t *>(groupdesc);
|
||
if (!items.findItem(i.dwTypeData))
|
||
{
|
||
items.addItem(new StringW(i.dwTypeData));
|
||
i.cch = wcslen(i.dwTypeData);
|
||
i.fState = WASABI_API_WNDMGR->skinwnd_getNumByGuid(guid) ? MFS_CHECKED : 0;
|
||
InsertMenuItemW(hMenu, pos++, TRUE, &i);
|
||
wa2.adjustFFWindowsMenu(1);
|
||
InsertMenuItemW(hMenu2, pos2++, TRUE, &i);
|
||
wa2.adjustOptionsPopupMenu(1);
|
||
}
|
||
}
|
||
i.wID++;
|
||
}
|
||
|
||
n = WASABI_API_WNDMGR->autopopup_getNumGroups();
|
||
for (int c = 0;c < n;c++)
|
||
{
|
||
const wchar_t *id = WASABI_API_WNDMGR->autopopup_enumGroup(c);
|
||
const wchar_t *groupdesc = WASABI_API_WNDMGR->autopopup_enumGroupDescription(c);
|
||
if (id && groupdesc && *id && *groupdesc)
|
||
{
|
||
i.dwTypeData = const_cast<wchar_t *>(groupdesc);
|
||
// allow localisation of the color editor menu item
|
||
i.dwTypeData = const_cast<wchar_t *>(MenuActions::localizeSkinWindowName(i.dwTypeData));
|
||
if (!items.findItem(i.dwTypeData))
|
||
{
|
||
items.addItem(new StringW(i.dwTypeData));
|
||
i.cch = wcslen(i.dwTypeData);
|
||
i.fState = WASABI_API_WNDMGR->skinwnd_getNumByGroupId(id) ? MFS_CHECKED : 0;
|
||
InsertMenuItemW(hMenu, pos++, TRUE, &i);
|
||
wa2.adjustFFWindowsMenu(1);
|
||
InsertMenuItemW(hMenu2, pos2++, TRUE, &i);
|
||
wa2.adjustOptionsPopupMenu(1);
|
||
}
|
||
}
|
||
i.wID++;
|
||
}
|
||
|
||
items.deleteAll();
|
||
ffwindowstop = i.wID;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void switchSkin(const wchar_t *skinname)
|
||
{
|
||
wa2.switchSkin(skinname);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void addWindowOptionsToContextMenu(ifc_window *w)
|
||
{
|
||
if (g_controlMenuTarget != NULL)
|
||
removeWindowOptionsFromContextMenu();
|
||
if (w == NULL && WASABI_API_WND->rootwndIsValid(lastFocused))
|
||
w = lastFocused;
|
||
g_controlMenuTarget = w;
|
||
|
||
if (g_controlMenuTarget == NULL) return ;
|
||
|
||
/*int opacitysafe = 1;
|
||
int scalelocked = 0;
|
||
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (rootparent && rootparent->getInterface(layoutGuid))
|
||
{
|
||
Layout *l = static_cast<Layout*>(rootparent);
|
||
opacitysafe = l->isTransparencySafe();
|
||
scalelocked = l->isScaleLocked();
|
||
}*/
|
||
|
||
updateControlMenu(w);
|
||
updateAppBarMenu(w);
|
||
|
||
HMENU menu = wa2.getPopupMenu();
|
||
HMENU ctrlmenu = GetSubMenu(controlmenu, 0);
|
||
|
||
// JF> Francis, made this use command IDs (inserts it right before the help ID in the main menu).
|
||
// does this look OK? if you want, revert back to the old one. I just thought this seemed a tiny
|
||
// bit cleaner... :)
|
||
#define ID_HELP_HELPTOPICS 40347
|
||
InsertMenuW(menu, ID_HELP_HELPTOPICS, MF_BYCOMMAND | MF_POPUP, (UINT_PTR)ctrlmenu, WASABI_API_LNGSTRINGW(IDS_WINDOW_SETTINGS));
|
||
InsertMenu(menu, ID_HELP_HELPTOPICS, MF_BYCOMMAND | MF_SEPARATOR, 0, NULL);
|
||
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void removeWindowOptionsFromContextMenu()
|
||
{
|
||
if (g_controlMenuTarget == NULL) return ;
|
||
g_controlMenuTarget = NULL;
|
||
HMENU menu = wa2.getPopupMenu();
|
||
HMENU ctrlmenu = GetSubMenu(controlmenu, 0);
|
||
if (ctrlmenu)
|
||
{
|
||
int l = GetMenuItemCount(menu);
|
||
while (l-- > 0 && GetSubMenu(menu, l) != ctrlmenu);
|
||
if (l >= 0)
|
||
{
|
||
RemoveMenu(menu, l, MF_BYPOSITION);
|
||
RemoveMenu(menu, l, MF_BYPOSITION); // remove sep
|
||
}
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void controlOpacity(int v)
|
||
{
|
||
if (!g_controlMenuTarget) return ;
|
||
if (!WASABI_API_WND->rootwndIsValid(g_controlMenuTarget)) return ;
|
||
v = (int)(((float)v / 100.0f) * 255.0f + 0.5f);
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (rootparent && rootparent->getInterface(layoutGuid))
|
||
{
|
||
Layout *l = static_cast<Layout*>(rootparent);
|
||
if (!cfg_uioptions_linkallalpha.getValueAsInt())
|
||
{
|
||
l->setAlpha(v);
|
||
}
|
||
else
|
||
{
|
||
cfg_uioptions_linkedalpha.setValueAsInt(v);
|
||
}
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void controlScaling(double v)
|
||
{
|
||
if (!g_controlMenuTarget) return ;
|
||
if (!WASABI_API_WND->rootwndIsValid(g_controlMenuTarget)) return ;
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (rootparent) rootparent->setRenderRatio(v);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void lockScaling(int lock)
|
||
{
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (!WASABI_API_WND->rootwndIsValid(g_controlMenuTarget)) return ;
|
||
if (rootparent && rootparent->getInterface(layoutGuid))
|
||
{
|
||
Layout *l = static_cast<Layout*>(rootparent);
|
||
l->lockScale(lock);
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void controlAppBar(int side)
|
||
{
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (rootparent)
|
||
{
|
||
AppBar *ab = (AppBar *)rootparent->getInterface(appBarGuid);
|
||
if (ab)
|
||
{
|
||
ab->appbar_dock(side);
|
||
}
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void controlAppBarAOT()
|
||
{
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (rootparent)
|
||
{
|
||
Layout *l = (Layout *)rootparent->getInterface(layoutGuid);
|
||
if (l)
|
||
{
|
||
int curaot = l->getAppBarAlwaysOnTop();
|
||
l->setAppBarAlwaysOnTop(!curaot);
|
||
}
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void controlAppBarAH()
|
||
{
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (rootparent)
|
||
{
|
||
Layout *l = (Layout *)rootparent->getInterface(layoutGuid);
|
||
if (l)
|
||
{
|
||
int curah = l->getAppBarAutoHide();
|
||
l->setAppBarAutoHide(!curah);
|
||
}
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void updateAppBarMenu(ifc_window *w)
|
||
{
|
||
if (g_controlMenuTarget == NULL) return ;
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (rootparent)
|
||
{
|
||
Layout *l = (Layout *)rootparent->getInterface(layoutGuid);
|
||
if (l)
|
||
{
|
||
HMENU ctrlmenu = GetSubMenu(controlmenu, 0);
|
||
HMENU appbarmenu = GetSubMenu(ctrlmenu, 2);
|
||
if (l->appbar_getEnabledSides() == 0)
|
||
{
|
||
EnableMenuItem(ctrlmenu, 2, MF_BYPOSITION | MF_GRAYED);
|
||
return ;
|
||
}
|
||
else
|
||
EnableMenuItem(ctrlmenu, 2, MF_BYPOSITION | MF_ENABLED);
|
||
int docked = l->appbar_isDocked();
|
||
int side = l->appbar_getSide();
|
||
CheckMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_ALWAYSONTOP, MF_BYCOMMAND | (l->appbar_wantAlwaysOnTop() ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_AUTOHIDE, MF_BYCOMMAND | (l->appbar_wantAutoHide() ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_LEFT, MF_BYCOMMAND | ((docked && side == APPBAR_LEFT) ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_TOP, MF_BYCOMMAND | ((docked && side == APPBAR_TOP) ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_RIGHT, MF_BYCOMMAND | ((docked && side == APPBAR_RIGHT) ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_BOTTOM, MF_BYCOMMAND | ((docked && side == APPBAR_BOTTOM) ? MF_CHECKED : MF_UNCHECKED));
|
||
CheckMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_DISABLED, MF_BYCOMMAND | (!docked ? MF_CHECKED : MF_UNCHECKED));
|
||
EnableMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_AUTOHIDE, MF_BYCOMMAND | ((!docked || l->appbar_isSideAutoHideSafe(side)) ? MF_ENABLED : MF_GRAYED));
|
||
EnableMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_LEFT, MF_BYCOMMAND | (l->appbar_isSideEnabled(APPBAR_LEFT) ? MF_ENABLED : MF_GRAYED));
|
||
EnableMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_TOP, MF_BYCOMMAND | (l->appbar_isSideEnabled(APPBAR_TOP) ? MF_ENABLED : MF_GRAYED));
|
||
EnableMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_RIGHT, MF_BYCOMMAND | (l->appbar_isSideEnabled(APPBAR_RIGHT) ? MF_ENABLED : MF_GRAYED));
|
||
EnableMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_BOTTOM, MF_BYCOMMAND | (l->appbar_isSideEnabled(APPBAR_BOTTOM) ? MF_ENABLED : MF_GRAYED));
|
||
CheckMenuItem(appbarmenu, ID_CONTROLMENU_TOOLBAR_AUTODOCKONDRAG, MF_BYCOMMAND | (cfg_options_appbarondrag ? MF_CHECKED : MF_UNCHECKED));
|
||
}
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
double onTweakRenderRatio(double v)
|
||
{
|
||
if (!cfg_uioptions_uselocks.getValueAsInt())
|
||
return v;
|
||
return wa2.isDoubleSize() ? 2.0 : 1.0;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void onCustomAltF4()
|
||
{
|
||
SendMessageW(wa2.getMainWindow(), WM_CLOSE, 0, 0);
|
||
}
|
||
|
||
int isSkinStillLoading()
|
||
{
|
||
return before_startup_callback;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
void loadExtraColorThemes()
|
||
{
|
||
wchar_t filename[WA_MAX_PATH] = {0};
|
||
GetModuleFileNameW(hInstance, filename, WA_MAX_PATH);
|
||
PathParserW pp(filename);
|
||
StringW path;
|
||
for (int i = 0;i < pp.getNumStrings() - 1;i++)
|
||
{
|
||
path.AppendPath(pp.enumString(i));
|
||
}
|
||
StringW file = path;
|
||
file.AppendPath(L"ColorThemes");
|
||
file.AppendPath(WASABI_API_SKIN->getSkinName());
|
||
file.AppendPath(L"*.xml");
|
||
WASABI_API_SKIN->loadSkinFile(file);
|
||
}
|
||
|
||
double oldscale = 1.;
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
static BOOL CALLBACK customScaleProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
switch (uMsg)
|
||
{
|
||
case WM_INITDIALOG:
|
||
{
|
||
//CUT: double curratio=1.;
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (!rootparent || !WASABI_API_WND->rootwndIsValid(rootparent))
|
||
{
|
||
g_controlMenuTarget = NULL; return TRUE;
|
||
}
|
||
|
||
oldscale = rootparent->getRenderRatio();
|
||
|
||
int u = (int)((oldscale * 100.0f) + 0.5f);
|
||
|
||
SendMessageW(GetDlgItem(hwndDlg, IDC_SLIDER_CUSTOMSCALE), TBM_SETRANGEMAX, 0, 300);
|
||
SendMessageW(GetDlgItem(hwndDlg, IDC_SLIDER_CUSTOMSCALE), TBM_SETRANGEMIN, 0, 10);
|
||
SendMessageW(GetDlgItem(hwndDlg, IDC_SLIDER_CUSTOMSCALE), TBM_SETPOS, 1, u);
|
||
SetDlgItemTextW(hwndDlg, IDC_STATIC_SCALE, StringPrintfW(WASABI_API_LNGSTRINGW(IDS_SCALE_X_PERCENT), u));
|
||
return TRUE;
|
||
}
|
||
case WM_HSCROLL:
|
||
{
|
||
int t = (int)SendMessageW((HWND) lParam, TBM_GETPOS, 0, 0);
|
||
if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_SLIDER_CUSTOMSCALE))
|
||
{
|
||
SetDlgItemTextW(hwndDlg, IDC_STATIC_SCALE, StringPrintfW(WASABI_API_LNGSTRINGW(IDS_SCALE_X_PERCENT), t));
|
||
controlScaling((double)t / 100.0);
|
||
if (g_controlMenuTarget)
|
||
{
|
||
ifc_window *w = g_controlMenuTarget->getDesktopParent();
|
||
UpdateWindow(w->gethWnd());
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case WM_COMMAND:
|
||
switch (LOWORD(wParam))
|
||
{
|
||
case IDOK:
|
||
EndDialog(hwndDlg, IDOK);
|
||
return 0;
|
||
case IDCANCEL:
|
||
EndDialog(hwndDlg, IDCANCEL);
|
||
return 0;
|
||
}
|
||
break;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
double oldalpha = 255.;
|
||
|
||
//-----------------------------------------------------------------------------------------------
|
||
static BOOL CALLBACK customAlphaProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
switch (uMsg)
|
||
{
|
||
case WM_INITDIALOG:
|
||
{
|
||
ifc_window *rootparent = g_controlMenuTarget->getDesktopParent();
|
||
if (!rootparent || !WASABI_API_WND->rootwndIsValid(rootparent))
|
||
{
|
||
g_controlMenuTarget = NULL; return TRUE;
|
||
}
|
||
|
||
int v = 100;
|
||
if (!cfg_uioptions_linkallalpha.getValueAsInt())
|
||
{
|
||
Layout *l = static_cast<Layout *>(rootparent);
|
||
if (l != NULL)
|
||
oldalpha = static_cast<double>(l->getAlpha());
|
||
}
|
||
else
|
||
{
|
||
oldalpha = static_cast<double>(cfg_uioptions_linkedalpha.getValueAsInt());
|
||
}
|
||
v = (int)((oldalpha / 255.0f * 100.0f) + 0.5f);
|
||
SendMessageW(GetDlgItem(hwndDlg, IDC_SLIDER_CUSTOMALPHA), TBM_SETRANGEMAX, 0, 100);
|
||
SendMessageW(GetDlgItem(hwndDlg, IDC_SLIDER_CUSTOMALPHA), TBM_SETRANGEMIN, 0, 10);
|
||
SendMessageW(GetDlgItem(hwndDlg, IDC_SLIDER_CUSTOMALPHA), TBM_SETPOS, 1, v);
|
||
SetDlgItemTextW(hwndDlg, IDC_STATIC_ALPHA, StringPrintfW(WASABI_API_LNGSTRINGW(IDS_OPACITY_X_PERCENT), v));
|
||
return TRUE;
|
||
}
|
||
case WM_HSCROLL:
|
||
{
|
||
int t = (int)SendMessageW((HWND) lParam, TBM_GETPOS, 0, 0);
|
||
if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_SLIDER_CUSTOMALPHA))
|
||
{
|
||
SetDlgItemTextW(hwndDlg, IDC_STATIC_ALPHA, StringPrintfW(WASABI_API_LNGSTRINGW(IDS_OPACITY_X_PERCENT), t));
|
||
controlOpacity(t);
|
||
}
|
||
break;
|
||
}
|
||
case WM_COMMAND:
|
||
switch (LOWORD(wParam))
|
||
{
|
||
case IDOK:
|
||
EndDialog(hwndDlg, IDOK);
|
||
return 0;
|
||
case IDCANCEL:
|
||
EndDialog(hwndDlg, IDCANCEL);
|
||
return 0;
|
||
}
|
||
break;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
void customScaling()
|
||
{
|
||
if (!g_controlMenuTarget) return ;
|
||
if (!WASABI_API_WND->rootwndIsValid(g_controlMenuTarget)) return ;
|
||
ifc_window *w = g_controlMenuTarget->getDesktopParent();
|
||
if (!w || !WASABI_API_WND->rootwndIsValid(w)) return ;
|
||
int r = WASABI_API_DIALOGBOXW(IDD_CUSTOMSCALE, w->gethWnd(), customScaleProc);
|
||
if (r != IDOK)
|
||
controlScaling(oldscale);
|
||
}
|
||
|
||
void customOpacity()
|
||
{
|
||
if (!g_controlMenuTarget) return ;
|
||
if (!WASABI_API_WND->rootwndIsValid(g_controlMenuTarget)) return ;
|
||
ifc_window *w = g_controlMenuTarget->getDesktopParent();
|
||
if (!w || !WASABI_API_WND->rootwndIsValid(w)) return ;
|
||
int r = WASABI_API_DIALOGBOXW(IDD_CUSTOMALPHA, w->gethWnd(), customAlphaProc);
|
||
if (r != IDOK)
|
||
controlOpacity((int)((oldalpha / 255.0f * 100.0f) + 0.5f));
|
||
}
|
||
|
||
void autoOpacifyHover()
|
||
{
|
||
if (!g_controlMenuTarget) return ;
|
||
if (!WASABI_API_WND->rootwndIsValid(g_controlMenuTarget)) return ;
|
||
ifc_window *w = g_controlMenuTarget->getDesktopParent();
|
||
Layout *l = static_cast<Layout*>(w->getInterface(layoutGuid));
|
||
if (l)
|
||
{
|
||
if (!cfg_uioptions_linkallalpha.getValueAsInt())
|
||
{
|
||
int a = l->getAutoOpacify();
|
||
if (a == 2) a = 1;
|
||
else a = !a;
|
||
l->setAutoOpacify(a);
|
||
}
|
||
else
|
||
{
|
||
int a = cfg_uioptions_autoopacitylinked.getValueAsInt();
|
||
if (a == 2) a = 1;
|
||
else a = !a;
|
||
cfg_uioptions_autoopacitylinked.setValueAsInt(a);
|
||
}
|
||
}
|
||
}
|
||
|
||
void autoOpacifyFocus()
|
||
{
|
||
if (!g_controlMenuTarget) return ;
|
||
if (!WASABI_API_WND->rootwndIsValid(g_controlMenuTarget)) return ;
|
||
ifc_window *w = g_controlMenuTarget->getDesktopParent();
|
||
Layout *l = static_cast<Layout*>(w->getInterface(layoutGuid));
|
||
if (l)
|
||
{
|
||
if (!cfg_uioptions_linkallalpha.getValueAsInt())
|
||
{
|
||
int a = l->getAutoOpacify();
|
||
if (a == 1) a = 2;
|
||
else if (a == 0) a = 2;
|
||
else if (a == 2) a = 0;
|
||
l->setAutoOpacify(a);
|
||
}
|
||
else
|
||
{
|
||
int a = cfg_uioptions_autoopacitylinked.getValueAsInt();
|
||
if (a == 1) a = 2;
|
||
else if (a == 0) a = 2;
|
||
else if (a == 2) a = 0;
|
||
cfg_uioptions_autoopacitylinked.setValueAsInt(a);
|
||
}
|
||
}
|
||
}
|
||
|
||
StringW langpackfilename;
|
||
|
||
const wchar_t *localesCustomGetFile()
|
||
{
|
||
const wchar_t *langDir = WASABI_API_LNG->GetLanguageFolder();
|
||
if (!langDir || !*langDir)
|
||
return NULL;
|
||
|
||
langpackfilename = StringPathCombine(langDir, L"freeform");
|
||
return langpackfilename;
|
||
#if 0 // old code
|
||
wchar_t buf[256] = L"";
|
||
GetPrivateProfileStringW(L"Winamp", L"langpack", L"", buf, 256, AutoWide(INI_FILE)); // TODO: maybe we should change all ini file stuff to W versions
|
||
if (*buf == 0)
|
||
return NULL;
|
||
wchar_t *p = wcschr(buf, '.');
|
||
if (p)
|
||
*p = 0;
|
||
|
||
wchar_t filename[WA_MAX_PATH] = {0};
|
||
GetModuleFileNameW(hInstance, filename, WA_MAX_PATH);
|
||
PathParserW pp(filename);
|
||
langpackfilename = L"";
|
||
|
||
for (int i = 0;i < pp.getNumStrings() - 1;i++)
|
||
{
|
||
langpackfilename.AppendPath(pp.enumString(i));
|
||
}
|
||
langpackfilename.AppendPath(L"freeform");
|
||
langpackfilename.AppendPath(L"langpacks");
|
||
langpackfilename.AppendPath(StringPrintfW(L"%s.xml", buf));
|
||
|
||
return langpackfilename;
|
||
#endif
|
||
}
|
||
|
||
const wchar_t *getCustomVar(const wchar_t *var)
|
||
{
|
||
static StringW ret;
|
||
if (WCSCASEEQLSAFE(var, L"@HAVE_LIBRARY@"))
|
||
{
|
||
ret = StringPrintfW(L"%d", we_have_ml);
|
||
return ret;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
void checkMlPresent()
|
||
{
|
||
wchar_t filename[WA_MAX_PATH] = {0};
|
||
GetModuleFileNameW(hInstance, filename, WA_MAX_PATH);
|
||
PathParserW pp(filename);
|
||
StringW path;
|
||
for (int i = 0;i < pp.getNumStrings() - 1;i++)
|
||
{
|
||
path.AppendPath(pp.enumString(i));
|
||
}
|
||
path.AppendPath(L"gen_ml.dll");
|
||
we_have_ml = !WACCESS(path, 0);
|
||
}
|
||
|
||
void initEgg()
|
||
{
|
||
eggstr[0] = ~'N';
|
||
eggstr[1] = ~'U';
|
||
eggstr[2] = ~'L';
|
||
eggstr[3] = ~'L';
|
||
eggstr[4] = ~'S';
|
||
eggstr[5] = ~'O';
|
||
eggstr[6] = ~'F';
|
||
eggstr[7] = ~'T';
|
||
eggstr[8] = 0;
|
||
|
||
{
|
||
int x;
|
||
for (x = 0; x < 8; x ++) eggstr[x] ^= 255;
|
||
}
|
||
}
|
||
|
||
void toggleEgg()
|
||
{
|
||
eggstat = !eggstat;
|
||
if (!eggstat)
|
||
{
|
||
KillTimer(wa2.getMainWindow(), UPDATE_EGG);
|
||
if (lastlayoutegg && WASABI_API_WND->rootwndIsValid(lastlayoutegg)) lastlayoutegg->setTransparencyOverride(-1);
|
||
lastlayoutegg = NULL;
|
||
}
|
||
else SetTimer(wa2.getMainWindow(), UPDATE_EGG, 25, NULL);
|
||
}
|
||
|
||
void getCustomMetaData(const wchar_t *field, wchar_t *buf, int len)
|
||
{
|
||
StringW curfile = WASABI_API_MEDIACORE->core_getCurrent(0);
|
||
if (curfile.isempty())
|
||
{
|
||
buf[0] = 0;
|
||
return ;
|
||
}
|
||
if (!_wcsnicmp(curfile, L"file://", 7))
|
||
curfile = StringW(curfile.getValue() + 7);
|
||
buf[0] = 0;
|
||
|
||
if (WCSCASEEQLSAFE(field, L"filename"))
|
||
{
|
||
WCSCPYN(buf, curfile, len);
|
||
}
|
||
else
|
||
{
|
||
wa2.getMetaData(curfile, field, buf, len);
|
||
}
|
||
}
|
||
|
||
void registerGlobalHotkeys()
|
||
{
|
||
static int registered = 0;
|
||
if (!registered)
|
||
{
|
||
static wchar_t ghkStr[96];
|
||
wa2.registerGlobalHotkey((char*)WASABI_API_LNGSTRINGW_BUF(IDS_GHK_SHOW_NOTIFICATION,ghkStr,96), WM_WA_IPC, 0, IPC_SHOW_NOTIFICATION, HKF_UNICODE_NAME, "genff shn");
|
||
registered = 1;
|
||
}
|
||
}
|
||
|
||
const wchar_t *getSongInfoText()
|
||
{
|
||
return Core::getSongInfoText();
|
||
}
|
||
|
||
const wchar_t *getSongInfoTextTranslated()
|
||
{
|
||
return Core::getSongInfoTextTranslated();
|
||
}
|
||
|
||
OSWINDOWHANDLE getKeyboardForwardWnd(GUID g)
|
||
{
|
||
if (g != INVALID_GUID)
|
||
{
|
||
if (g == playerWndGuid)
|
||
return wa2.getMainWindow();
|
||
else if (g == pleditWndGuid)
|
||
return wa2.getWnd(IPC_GETWND_PE);
|
||
else if (g == videoWndGuid)
|
||
return wa2.getWnd(IPC_GETWND_VIDEO);
|
||
else
|
||
{
|
||
embedWindowState *ews = embedWndGuidMgr.getEmbedWindowState(g);
|
||
if (ews && wa2.isValidEmbedWndState(ews)) return ews->me;
|
||
}
|
||
}
|
||
return WASABI_API_WND->main_getRootWnd()->gethWnd();
|
||
}
|
||
|
||
void onAppBarDockChanged(ifc_window *w)
|
||
{
|
||
setDialogBoxesParent();
|
||
}
|
||
|
||
void onMainLayoutMove(HWND w)
|
||
{
|
||
// for Winamp to appear on the correct taskbar on Windows 8
|
||
// its necessary to set the classic main window to appear on
|
||
// that monitor and to be on-screen (but hidden) otherwise
|
||
// Windows will ignore it and it then makes us look buggy.
|
||
RECT r;
|
||
Wasabi::Std::getViewport(&r, w, 1);
|
||
SetWindowPos(wa2.getMainWindow(), NULL, r.left, r.bottom - 1, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW);
|
||
}
|
||
|
||
void updateAll()
|
||
{
|
||
updatePl();
|
||
#ifdef MINIBROWSER_SUPPORT
|
||
updateMb();
|
||
#endif
|
||
updateVid();
|
||
int n = embedWndGuidMgr.getNumWindowStates();
|
||
for (int i = 0;i < n;i++)
|
||
{
|
||
embedWindowState *ws = NULL;
|
||
GUID g = embedWndGuidMgr.enumWindowState(i, &ws);
|
||
if (g != INVALID_GUID)
|
||
{
|
||
updateEmb(g, ws);
|
||
}
|
||
}
|
||
}
|
||
|
||
void onReParent(HWND wnd)
|
||
{
|
||
updateAll();
|
||
}
|
||
|
||
void onReInit(HWND wnd)
|
||
{
|
||
updateAll();
|
||
}
|
||
|
||
void startFSMonitor()
|
||
{
|
||
g_fsmonitor = new FullScreenMonitor();
|
||
g_fscallback = new Wa5FSCallback();
|
||
g_fsmonitor->registerCallback(g_fscallback);
|
||
}
|
||
|
||
void stopFSMonitor()
|
||
{
|
||
delete g_fsmonitor;
|
||
g_fsmonitor = NULL;
|
||
delete g_fscallback;
|
||
g_fscallback = NULL;
|
||
}
|
||
|
||
void updateParentlessOnTop()
|
||
{
|
||
int i;
|
||
for (i = 0;i < SkinParser::getNumContainers();i++)
|
||
{
|
||
Container *c = SkinParser::enumContainer(i);
|
||
if (c != NULL)
|
||
{
|
||
int j;
|
||
for (j = 0;j < c->getNumLayouts();j++)
|
||
{
|
||
Layout *l = c->enumLayout(j);
|
||
if (l != NULL)
|
||
{
|
||
// skip windows owned by winamp
|
||
// skip appbars, they take care of themselves
|
||
if (l->getNoParent() && !l->appbar_isDocked())
|
||
{
|
||
l->updateOnTop();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void onGoFullscreen()
|
||
{
|
||
// hidden windows will not receive APPBAR_CALLBACK, so forward it to winamp's main
|
||
SendMessageW(wa2.getMainWindow(), APPBAR_CALLBACK, ABN_FULLSCREENAPP, 1);
|
||
// update ontop flag for windows that are not parented to winamp
|
||
updateParentlessOnTop();
|
||
}
|
||
|
||
void onCancelFullscreen()
|
||
{
|
||
// hidden windows will not receive APPBAR_CALLBACK, so forward it to winamp's main
|
||
SendMessageW(wa2.getMainWindow(), APPBAR_CALLBACK, ABN_FULLSCREENAPP, 0);
|
||
// update ontop flag for windows that are not owned by winamp
|
||
updateParentlessOnTop();
|
||
}
|
||
|
||
int processGenericHotkey(const char *hk)
|
||
{
|
||
if (!m_are_we_loaded) return 0;
|
||
|
||
SystemObject::onKeyDown(AutoWide(StringPrintf("HOTKEY: %s", hk)));
|
||
if (VCPU::getComplete())
|
||
{
|
||
DebugStringW(L"HOTKEY: %s trapped by script\n", hk);
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int canExitWinamp()
|
||
{
|
||
return wa2.isExitEnabled();
|
||
}
|
||
|
||
int fsMonitorIsFS()
|
||
{
|
||
return g_fsmonitor->isFullScreen();
|
||
}
|
||
|
||
void modalPush()
|
||
{
|
||
wa2.pushExitDisabled();
|
||
}
|
||
|
||
void modalPop()
|
||
{
|
||
wa2.popExitDisabled();
|
||
} |