aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/General/gen_ff/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Plugins/General/gen_ff/main.cpp')
-rw-r--r--Src/Plugins/General/gen_ff/main.cpp3527
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