#include "precomp__gen_ff.h" #include #include #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 #include "../winamp/wa_ipc.h" #include "../gen_hotkeys/wa_hotkeys.h" #include #include #include #include #include #include #include "menuactions.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "skininfo.h" #include #include #include "wa2core.h" #include #include #include #include #include #include "../nu/AutoWide.h" #include #include //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 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(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(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(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;cgetName() == NULL) continue; if (id == 0) { if (cont) cont->toggle(); return 1; } id--; } } int n = WASABI_API_WNDMGR->autopopup_getNumGuids(); for (c=0;cautopopup_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;cautopopup_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 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( factory->getInterface() ); } } template 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;igetNumLayouts();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(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(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 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(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(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(groupdesc); // allow localisation of the color editor menu item i.dwTypeData = const_cast(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(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(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(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(rootparent); if (l != NULL) oldalpha = static_cast(l->getAlpha()); } else { oldalpha = static_cast(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(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(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(); }