diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/General/gen_ff/main.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Plugins/General/gen_ff/main.cpp')
-rw-r--r-- | Src/Plugins/General/gen_ff/main.cpp | 3527 |
1 files changed, 3527 insertions, 0 deletions
diff --git a/Src/Plugins/General/gen_ff/main.cpp b/Src/Plugins/General/gen_ff/main.cpp new file mode 100644 index 00000000..728d99a4 --- /dev/null +++ b/Src/Plugins/General/gen_ff/main.cpp @@ -0,0 +1,3527 @@ +#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". © 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(); +}
\ No newline at end of file |