123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419 |
- /*
- LICENSE
- -------
- Copyright 2005-2013 Nullsoft, Inc.
- All rights reserved.
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of Nullsoft nor the names of its contributors may be used to
- endorse or promote products derived from this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "api__vis_milk2.h"
- #include "DXContext.h"
- #include "utility.h"
- #include "shell_defines.h"
- #include "resource.h"
- #define COMPILE_MULTIMON_STUBS 1
- #include <multimon.h>
- #include <strsafe.h>
- // note: added WS_EX_CONTROLPARENT and WS_TABSTOP for embedwnd so window frame will pass on KB commands to us, if it has focus & receives them.
- // however, it is still not working. Maksim says he needs to use GetNextDlgTabItem() and then it will work.
- // aha- had to remove WS_EX_CONTROLPARENT and WS_OVERLAPPED. Should now work with winamp 5.5 build 1620.
- #define MY_EXT_WINDOW_STYLE (m_current_mode.m_skin ? 0/*WS_EX_CONTROLPARENT*/ : ((m_current_mode.screenmode==DESKTOP) ? (WS_EX_TOOLWINDOW) : 0)) // note: changed from TOOLWINDOW to APPWINDOW b/c we wanted the plugin to appear in the taskbar.
- #define SKINNED_WS (WS_VISIBLE|WS_CHILDWINDOW/*|WS_OVERLAPPED*/|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_TABSTOP)
- #define MY_WINDOW_STYLE (m_current_mode.m_skin ? SKINNED_WS : ((m_current_mode.screenmode==FAKE_FULLSCREEN || m_current_mode.screenmode==DESKTOP) ? WS_POPUP : WS_OVERLAPPEDWINDOW)) // note: WS_POPUP (by itself) removes all borders, captions, etc.
- #include "vis.h"
- extern winampVisModule mod1;
- DXContext::DXContext(HWND hWndWinamp,HINSTANCE hInstance,LPCWSTR szClassName,LPCSTR szWindowCaption,WNDPROC pProc,LONG_PTR uWindowLong, int minimize_winamp, wchar_t* szIniFile)
- {
- m_classAtom = 0;
- m_szWindowCaption[0] = 0;
- m_hwnd = NULL;
- m_lpD3D = NULL;
- m_lpDevice = NULL;
- m_hmod_d3d9 = NULL;
- m_hmod_d3dx9 = NULL;
- m_zFormat = D3DFMT_UNKNOWN;
- for (int i=0; i<MAX_DXC_ADAPTERS; i++)
- m_orig_windowed_mode_format[i] = D3DFMT_UNKNOWN;
- m_ordinal_adapter = D3DADAPTER_DEFAULT;
- m_ignore_wm_destroy = 0;
- m_hwnd_winamp = hWndWinamp;
- m_minimize_winamp = minimize_winamp;
- m_winamp_minimized = 0;
- m_truly_exiting = 0;
- m_bpp = 0;
- m_frame_delay = 0;
- StringCbCopyW(m_szIniFile, sizeof(m_szIniFile), szIniFile);
- memset(&myWindowState,0,sizeof(myWindowState));
- m_szDriver[0] = 0;
- m_szDesc[0] = 0;
- WNDCLASSW wc = {0};
- // clear the error register
- m_lastErr = S_OK;
- // clear the active flag
- m_ready=FALSE;
- // Set up and register window class
- wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; // CS_DBLCLKS lets the window receive WM_LBUTTONDBLCLK, for toggling fullscreen mode...
- wc.lpfnWndProc = (WNDPROC) pProc;
- wc.cbWndExtra = sizeof(DWORD);
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PLUGIN_ICON));//NULL;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = szClassName;
- m_classAtom = RegisterClassW(&wc);
- if (!m_classAtom)
- {
- wchar_t title[64];
- int y = GetLastError();
- m_lastErr = DXC_ERR_REGWIN;
- MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_UNABLE_TO_REGISTER_WINDOW_CLASS),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- Internal_CleanUp();
- return;
- }
- StringCbCopy(m_szWindowCaption, sizeof(m_szWindowCaption), szWindowCaption);
- m_hInstance = hInstance;
- m_uWindowLong = uWindowLong;
- }
- DXContext::~DXContext()
- {
- Internal_CleanUp();
- }
- void DXContext::Internal_CleanUp()
- {
- // clear active flag
- m_ready=FALSE;
- // release 3D interfaces
- SafeRelease(m_lpDevice);
- SafeRelease(m_lpD3D);
- // destroy the window
- if (m_truly_exiting)
- {
- // somebody else will destroy the window for us!
- m_hwnd = NULL;
- if (m_hmod_d3d9)
- {
- FreeLibrary(m_hmod_d3d9);
- m_hmod_d3d9 = NULL;
- }
- if (m_hmod_d3dx9)
- {
- m_hmod_d3dx9 = NULL;
- }
- }
- if (myWindowState.me)
- {
- DestroyWindow(myWindowState.me);
- myWindowState.me = NULL;
- m_hwnd = NULL;
- }
- else if (m_hwnd)
- {
- DestroyWindow(m_hwnd);
- m_hwnd = NULL;
- }
- // unregister window class. note: only works if window is already destroyed!
- if (m_classAtom)
- {
- UnregisterClass(MAKEINTATOM(m_classAtom), m_hInstance);
- m_classAtom = 0;
- }
- RestoreWinamp();
- }
- void DXContext::GetSnappedClientSize()
- {
- // Call this whenever you set m_REAL_client_width/height while in windowed mode,
- // to compute an appropriate (oversized) internal canvas size. At the end of each
- // frame, for display, the canvas will be centered & cropped.
- m_client_width = m_REAL_client_width;
- m_client_height = m_REAL_client_height;
- #if (SNAP_WINDOWED_MODE_BLOCKSIZE >= 1)
- if (m_current_mode.screenmode == WINDOWED)
- {
- // oversize it - then we'll just crop - so onscreen text has no stretching :)
- m_client_width = max(1, (m_REAL_client_width + 31)/32)*32;
- m_client_height = max(1, (m_REAL_client_height + 31)/32)*32;
- }
- #endif
- }
- BOOL DXContext::TestFormat(int ordinal_adapter, D3DFORMAT fmt)
- {
- if (D3D_OK==m_lpD3D->CheckDeviceType(ordinal_adapter,D3DDEVTYPE_HAL,fmt,fmt,FALSE))
- return TRUE;
- return FALSE;
- }
- BOOL DXContext::TestDepth(int ordinal_adapter, D3DFORMAT fmt)
- {
- if (D3D_OK!=m_lpD3D->CheckDeviceFormat(ordinal_adapter,D3DDEVTYPE_HAL,m_current_mode.display_mode.Format,
- D3DUSAGE_DEPTHSTENCIL,D3DRTYPE_SURFACE,fmt))
- return FALSE;
- if (D3D_OK!=m_lpD3D->CheckDepthStencilMatch(ordinal_adapter,D3DDEVTYPE_HAL,
- m_current_mode.display_mode.Format,m_current_mode.display_mode.Format,fmt))
- return FALSE;
- return TRUE;
- }
- int DXContext::CheckAndCorrectFullscreenDispMode(int ordinal_adapter, D3DDISPLAYMODE *pdm)
- {
- // given the user's choice of fullscreen display mode,
- // go through all the display modes available to the currently-selected adapter
- // and find the best match.
- // returns 1 if it altered pdm to the best match,
- // or 0 if it was able to find a perfect match.
- // if it returns 1, you might want to notify the user.
- #define MAX_DISPLAY_MODES 4096
- D3DDISPLAYMODE list[MAX_DISPLAY_MODES];
- int nCount = min(m_lpD3D->GetAdapterModeCount(ordinal_adapter, D3DFMT_A8R8G8B8), MAX_DISPLAY_MODES);
- int nValid = 0;
- for (int i=0; i<nCount; i++)
- if (m_lpD3D->EnumAdapterModes(ordinal_adapter, D3DFMT_A8R8G8B8, i, &list[nValid]) == D3D_OK)
- nValid++;
- // do many passes through the set until we find a match,
- // each time relaxing more constraints.
- // outline of the passes:
- int bpp_desired = 0;
- switch (pdm->Format)
- {
- case D3DFMT_R8G8B8 : bpp_desired = 32; break;
- case D3DFMT_A8R8G8B8: bpp_desired = 32; break;
- case D3DFMT_X8R8G8B8: bpp_desired = 32; break;
- case D3DFMT_R5G6B5 : bpp_desired = 16; break;
- case D3DFMT_X1R5G5B5: bpp_desired = 16; break;
- case D3DFMT_A1R5G5B5: bpp_desired = 16; break;
- case D3DFMT_A4R4G4B4: bpp_desired = 16; break;
- case D3DFMT_R3G3B2 : bpp_desired = 8; break;
- case D3DFMT_A8R3G3B2: bpp_desired = 16; break;
- case D3DFMT_X4R4G4B4: bpp_desired = 16; break;
- }
- // rep MATCH:
- // 0. w,h,r,f
- // 1. w,h,-,f
- // 2. w,h,r,- pass:
- // 3. w,h,-,- -on pass 0, for 'f', match exact format
- // 4. 8,6,r,f -on pass 1, for 'f', just match # of bits per pixel
- // 5. 8,6,-,f (more relaxed match)
- // 6. 8,6,r,-
- // 7. 8,6,-,-
- // 8. -,-,r,f
- // 9. -,-,-,f
- // 10. -,-,r,-
- // 11. -,-,-,-
- int found = 0;
- for (int rep=0; rep<12 && !found; rep++)
- {
- for (int pass=0; pass<2 && !found; pass++)
- {
- for (int i=0; i<nValid && !found; i++)
- {
- bool bMatch = true;
- int bpp_this_mode = 0;
- switch (list[i].Format)
- {
- case D3DFMT_R8G8B8 : bpp_this_mode = 32; break;
- case D3DFMT_A8R8G8B8: bpp_this_mode = 32; break;
- case D3DFMT_X8R8G8B8: bpp_this_mode = 32; break;
- case D3DFMT_R5G6B5 : bpp_this_mode = 16; break;
- case D3DFMT_X1R5G5B5: bpp_this_mode = 16; break;
- case D3DFMT_A1R5G5B5: bpp_this_mode = 16; break;
- case D3DFMT_A4R4G4B4: bpp_this_mode = 16; break;
- case D3DFMT_R3G3B2 : bpp_this_mode = 8; break;
- case D3DFMT_A8R3G3B2: bpp_this_mode = 16; break;
- case D3DFMT_X4R4G4B4: bpp_this_mode = 16; break;
- }
- if (rep < 4)
- {
- if (pdm->Width != list[i].Width)
- bMatch = false;
- if (pdm->Height != list[i].Height)
- bMatch = false;
- }
- else if (rep < 8)
- {
- if (DEFAULT_FULLSCREEN_WIDTH != list[i].Width)
- bMatch = false;
- if (DEFAULT_FULLSCREEN_HEIGHT != list[i].Height)
- bMatch = false;
- }
- if (((rep/2)%2)==0)
- {
- if (pass==0 && pdm->Format != list[i].Format)
- bMatch = false;
- else if (pass==1 && bpp_desired != bpp_this_mode)
- bMatch = false;
- }
- if (((rep%2)==0) && pdm->RefreshRate != list[i].RefreshRate)
- {
- bMatch = false;
- }
- if (bMatch)
- {
- memcpy(pdm, &list[i], sizeof(D3DDISPLAYMODE));
- found = 1;
- if (rep != 0 || pass != 0)
- {
- return 1;
- }
- }
- }
- }
- }
- return 0;
- }
- BOOL CALLBACK MyMonitorEnumProc(
- HMONITOR hMonitor, // handle to display monitor
- HDC hdcMonitor, // handle to monitor DC
- LPRECT lprcMonitor, // monitor intersection rectangle
- LPARAM dwData // data
- )
- {
- RECT* p = (RECT*)dwData;
- if (hMonitor)
- {
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hMonitor, &mi))
- {
- p->top = min(p->top , mi.rcMonitor.top);
- p->left = min(p->left , mi.rcMonitor.left);
- p->right = max(p->right , mi.rcMonitor.right);
- p->bottom = max(p->bottom, mi.rcMonitor.bottom);
- }
- }
- return TRUE;
- }
- int DXContext::GetWindowedModeAutoSize(int iteration)
- {
- // note: requires 'm_monitor_rect' has been set!
- // generically determine size of window, for windowed mode:
- int x = m_monitor_rect.right-m_monitor_rect.left;
- int y = m_monitor_rect.bottom-m_monitor_rect.top;
- // if running in horz/vert-span multi-display mode, base the window size on
- // an actual display size, not the giant double-sized monitor. Also, position
- // the window on the same monitor that Winamp is on.
- if (x >= y*2)
- {
- x /= 2;
- // move window to same display that Winamp is on:
- WINDOWPLACEMENT wp;
- wp.length = sizeof(wp);
- if (GetWindowPlacement(m_hwnd_winamp, &wp))
- {
- int winamp_center_x = (wp.rcNormalPosition.right + wp.rcNormalPosition.left)/2;
- if (winamp_center_x > x)
- {
- m_monitor_rect.left += x;
- m_monitor_rect.right += x;
- }
- }
- }
- else if (y > x*4/3)
- {
- y /= 2;
- // move window to same display that Winamp is on:
- WINDOWPLACEMENT wp;
- wp.length = sizeof(wp);
- if (GetWindowPlacement(m_hwnd_winamp, &wp))
- {
- int winamp_center_y = (wp.rcNormalPosition.top + wp.rcNormalPosition.bottom)/2;
- if (winamp_center_y > y)
- {
- m_monitor_rect.top += y;
- m_monitor_rect.bottom += y;
- }
- }
- }
- int size = min(x, y);
- size = (int)(size*DEFAULT_WINDOW_SIZE);
- size = (size/64 - iteration)*64;
- if (size < 64)
- size = 64;
- return size;
- }
- void DXContext::WriteSafeWindowPos()
- {
- if (m_current_mode.screenmode == WINDOWED)
- {
- WritePrivateProfileIntW(64, L"nMainWndTop", m_szIniFile, L"settings");
- WritePrivateProfileIntW(64, L"nMainWndLeft", m_szIniFile, L"settings");
- WritePrivateProfileIntW(64+256, L"nMainWndRight", m_szIniFile, L"settings");
- WritePrivateProfileIntW(64+256, L"nMainWndBottom", m_szIniFile, L"settings");
- WritePrivateProfileIntW(64, L"avs_wx",m_szIniFile,L"settings");
- WritePrivateProfileIntW(64, L"avs_wy",m_szIniFile,L"settings");
- WritePrivateProfileIntW(256, L"avs_ww",m_szIniFile,L"settings");
- WritePrivateProfileIntW(256, L"avs_wh",m_szIniFile,L"settings");
- }
- }
- // {0000000A-000C-0010-FF7B-01014263450C}
- const GUID avs_guid =
- { 10, 12, 16, { 255, 123, 1, 1, 66, 99, 69, 12 } };
- BOOL DXContext::Internal_Init(DXCONTEXT_PARAMS *pParams, BOOL bFirstInit)
- {
- memcpy(&m_current_mode, pParams, sizeof(DXCONTEXT_PARAMS));
- memset(&myWindowState,0,sizeof(myWindowState));
- // various checks
- if (m_current_mode.screenmode != WINDOWED)
- m_current_mode.m_skin = 0;
- // 1. destroy old window
- if (m_hwnd)
- {
- m_ignore_wm_destroy = 1;
- DestroyWindow(m_hwnd);
- m_ignore_wm_destroy = 0;
- m_hwnd = NULL;
- }
- // 2. CHECK TO MAKE SURE DIRECTX/DDRAW IS INSTALLED
- if (bFirstInit)
- {
- // Test for DirectX 9 + start it
- // note: if you don't call LoadLibrary here, and you're on a system
- // where DX9 is missing, Direct3DCreate8() might crash; so call it.
- int d3d9_already_loaded = (GetModuleHandle("d3d9.dll") != NULL) ? 1 : 0;
- if (!d3d9_already_loaded)
- m_hmod_d3d9 = LoadLibrary("d3d9.dll");
- if ((!d3d9_already_loaded && !m_hmod_d3d9) ||
- !(m_lpD3D = Direct3DCreate9(D3D_SDK_VERSION))
- )
- {
- MissingDirectX(NULL);
- m_lastErr = DXC_ERR_CREATE3D;
- return FALSE;
- }
- if (!m_hmod_d3dx9)
- m_hmod_d3dx9 = FindD3DX9(m_hwnd_winamp);
- if ((!m_hmod_d3dx9))
- {
- MissingDirectX(NULL);
- m_lastErr = DXC_ERR_CREATE3D;
- return FALSE;
- }
- }
- // 3. get the smallest single rectangle that encloses ALL the monitors on the desktop:
- SetRect(&m_all_monitors_rect, 0, 0, 0, 0);
- EnumDisplayMonitors(NULL, NULL, MyMonitorEnumProc, (LPARAM)&m_all_monitors_rect);
- // 4. some DirectX- / DDraw-specific stuff. Also determine hPluginMonitor.
- HMONITOR hPluginMonitor = NULL;
- {
- D3DADAPTER_IDENTIFIER9 temp;
- // find the ordinal # of the adapter whose GUID matches what the user picked from the config panel,
- // and whose DeviceName matches as well.
- // if no match found, use D3DADAPTER_DEFAULT.
- m_ordinal_adapter = D3DADAPTER_DEFAULT;
- int nAdapters = m_lpD3D->GetAdapterCount();
- {
- for (int i=0; i<nAdapters; i++)
- {
- if ((m_lpD3D->GetAdapterIdentifier(i, /*D3DENUM_NO_WHQL_LEVEL*/ 0, &temp) == D3D_OK) &&
- (memcmp(&temp.DeviceIdentifier, &m_current_mode.adapter_guid, sizeof(GUID))==0) &&
- !strcmp(temp.DeviceName, m_current_mode.adapter_devicename)
- )
- {
- m_ordinal_adapter = i;
- break;
- }
- }
- }
- if (m_lpD3D->GetAdapterIdentifier(m_ordinal_adapter, /*D3DENUM_NO_WHQL_LEVEL*/ 0, &temp) == D3D_OK)
- {
- StringCbCopy(m_szDriver, sizeof(m_szDriver), temp.Driver);
- StringCbCopy(m_szDesc, sizeof(m_szDesc), temp.Description);
- }
- int caps_ok = 0;
- int caps_tries = 0;
- int changed_fs_disp_mode;
- // try to get the device caps for the adapter selected from the config panel.
- // if GetDeviceCaps() fails, it's probably because the adapter has been
- // removed from the system (or disabled), so we try again with other adapter(s).
- do
- {
- changed_fs_disp_mode = 0;
- SetRect(&m_monitor_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
- // get bounding rect of the monitor attached to the adapter (to assist w/window positioning)
- // note: in vert/horz span setups (psuedo-multimon),
- // this will be 2048x768 or 1024x1536 or something like that.
- hPluginMonitor = m_lpD3D->GetAdapterMonitor(m_ordinal_adapter);
- /*if (hPluginMonitor)
- {
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hPluginMonitor, &mi))
- {
- memcpy(&m_monitor_rect, &mi.rcMonitor, sizeof(RECT));
- memcpy(&m_monitor_work_rect, &mi.rcWork, sizeof(RECT));
- }
- }*/
- if (bFirstInit)
- {
- for (int i=0; i<min(nAdapters, MAX_DXC_ADAPTERS); i++)
- {
- // if this is the first call to Init, get the display mode's original color format,
- // before we go changing it:
- D3DDISPLAYMODE d3ddm;
- if (FAILED(m_lpD3D->GetAdapterDisplayMode(i, &d3ddm)))
- {
- d3ddm.Format = D3DFMT_UNKNOWN;
- }
- m_orig_windowed_mode_format[i] = d3ddm.Format;
- }
- }
- // figure out pixel (color) format for back buffer: (m_current_mode.display_mode.Format)
- if (m_current_mode.screenmode!=FULLSCREEN && m_ordinal_adapter < MAX_DXC_ADAPTERS)
- m_current_mode.display_mode.Format = m_orig_windowed_mode_format[m_ordinal_adapter];
- // else
- // for fullscreen, use what they gave us
- if (m_current_mode.display_mode.Format == D3DFMT_UNKNOWN ||
- !TestFormat(m_ordinal_adapter, m_current_mode.display_mode.Format))
- {
- // if they try to run the plugin without ever running the config panel
- // first (& pressing OK), then the fullscreen pixelformat hasn't been
- // chosen... so we try all the possilibities until one works:
- if (TestFormat(m_ordinal_adapter,D3DFMT_A8R8G8B8)) m_current_mode.display_mode.Format = D3DFMT_A8R8G8B8;
- else if (TestFormat(m_ordinal_adapter,D3DFMT_X8R8G8B8)) m_current_mode.display_mode.Format = D3DFMT_X8R8G8B8;
- else if (TestFormat(m_ordinal_adapter,D3DFMT_R8G8B8)) m_current_mode.display_mode.Format = D3DFMT_R8G8B8 ;
- else if (TestFormat(m_ordinal_adapter,D3DFMT_R5G6B5)) m_current_mode.display_mode.Format = D3DFMT_R5G6B5 ;
- else if (TestFormat(m_ordinal_adapter,D3DFMT_X1R5G5B5)) m_current_mode.display_mode.Format = D3DFMT_X1R5G5B5;
- else if (TestFormat(m_ordinal_adapter,D3DFMT_A1R5G5B5)) m_current_mode.display_mode.Format = D3DFMT_A1R5G5B5;
- else if (TestFormat(m_ordinal_adapter,D3DFMT_A4R4G4B4)) m_current_mode.display_mode.Format = D3DFMT_A4R4G4B4;
- else if (TestFormat(m_ordinal_adapter,D3DFMT_X4R4G4B4)) m_current_mode.display_mode.Format = D3DFMT_X4R4G4B4;
- }
- if (m_current_mode.display_mode.Format==D3DFMT_UNKNOWN)
- {
- wchar_t title[64];
- m_lastErr = DXC_ERR_FORMAT;
- MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_DIRECTX_INIT_FAILED),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return FALSE;
- }
- if (m_current_mode.screenmode == FULLSCREEN)
- changed_fs_disp_mode = CheckAndCorrectFullscreenDispMode(m_ordinal_adapter, &m_current_mode.display_mode);
- // figure out pixel format of the z-buffer: (m_zFormat)
- m_zFormat = D3DFMT_UNKNOWN;
- /*
- if (TestDepth(m_ordinal_adapter,D3DFMT_D32 )) m_zFormat=D3DFMT_D32;
- else if (TestDepth(m_ordinal_adapter,D3DFMT_D24S8 )) m_zFormat=D3DFMT_D24S8;
- else if (TestDepth(m_ordinal_adapter,D3DFMT_D24X4S4 )) m_zFormat=D3DFMT_D24X4S4;
- else if (TestDepth(m_ordinal_adapter,D3DFMT_D24X8 )) m_zFormat=D3DFMT_D24X8;
- else if (TestDepth(m_ordinal_adapter,D3DFMT_D16 )) m_zFormat=D3DFMT_D16;
- else if (TestDepth(m_ordinal_adapter,D3DFMT_D15S1 )) m_zFormat=D3DFMT_D15S1;
- else if (TestDepth(m_ordinal_adapter,D3DFMT_D16_LOCKABLE)) m_zFormat=D3DFMT_D16_LOCKABLE;
- */
- // get device caps:
- memset(&m_caps, 0, sizeof(m_caps));
- if (FAILED(m_lpD3D->GetDeviceCaps(m_ordinal_adapter, D3DDEVTYPE_HAL, &m_caps)))
- {
- // that adapter was found in the system, but it might be disabled
- // (i.e. 'extend my Windows desktop onto this monitor') is unchecked)
- // so, try other adapters (try all sequentially).
- if (caps_tries < nAdapters)
- {
- // try again, this time using the default adapter:
- m_ordinal_adapter = caps_tries;
- caps_tries++;
- }
- else
- {
- wchar_t title[64];
- m_lastErr = DXC_ERR_CAPSFAIL;
- MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_DXC_ERR_CAPSFAIL),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return FALSE;
- }
- }
- else
- {
- caps_ok = 1;
- }
- }
- while (!caps_ok);
- if (changed_fs_disp_mode)
- {
- wchar_t title[64];
- MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_FS_DISPLAY_MODE_SELECTED_IS_INVALID),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_WARNING, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- }
- switch (m_current_mode.display_mode.Format)
- {
- case D3DFMT_R8G8B8 : m_bpp = 32; break;
- case D3DFMT_A8R8G8B8: m_bpp = 32; break;
- case D3DFMT_X8R8G8B8: m_bpp = 32; break;
- case D3DFMT_R5G6B5 : m_bpp = 16; break;
- case D3DFMT_X1R5G5B5: m_bpp = 16; break;
- case D3DFMT_A1R5G5B5: m_bpp = 16; break;
- case D3DFMT_A8R3G3B2: m_bpp = 16; break;
- case D3DFMT_A4R4G4B4: m_bpp = 16; break;
- case D3DFMT_X4R4G4B4: m_bpp = 16; break;
- case D3DFMT_R3G3B2 : m_bpp = 8; break; // misleading? implies a palette...
- }
- }
- // 5. set m_monitor_rect and m_monitor_work_rect.
- if (hPluginMonitor)
- {
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hPluginMonitor, &mi))
- {
- m_monitor_rect = mi.rcMonitor;
- m_monitor_rect_orig = mi.rcMonitor;
- m_monitor_work_rect = mi.rcWork;
- m_monitor_work_rect_orig = mi.rcWork;
- }
- }
- // 6. embedded window stuff [where the plugin window is integrated w/winamp]
- if (m_current_mode.m_skin)
- {
- // set up the window's position on screen
- // note that we'd prefer to set the CLIENT size we want, but we can't, so we'll just do
- // this here, and later, adjust the client rect size to what's left...
- int size = GetWindowedModeAutoSize(0); // note: requires 'm_monitor_rect' has been set!
- myWindowState.r.left = GetPrivateProfileIntW(L"settings",L"avs_wx",64,m_szIniFile);
- myWindowState.r.top = GetPrivateProfileIntW(L"settings",L"avs_wy",64,m_szIniFile);
- myWindowState.r.right = myWindowState.r.left + GetPrivateProfileIntW(L"settings",L"avs_ww",size+24,m_szIniFile);
- myWindowState.r.bottom = myWindowState.r.top + GetPrivateProfileIntW(L"settings",L"avs_wh",size+40,m_szIniFile);
- // only works on winamp 2.90+!
- int success = 0;
- if (GetWinampVersion(mod1.hwndParent) >= 0x2900)
- {
- SET_EMBED_GUID((&myWindowState), avs_guid);
- myWindowState.flags |= EMBED_FLAGS_NOTRANSPARENCY;
- HWND (*e)(embedWindowState *v);
- *(void**)&e = (void *)SendMessage(mod1.hwndParent,WM_WA_IPC,(LPARAM)0,IPC_GET_EMBEDIF);
- if (e)
- {
- m_current_mode.parent_window = e(&myWindowState);
- if (m_current_mode.parent_window)
- {
- SetWindowText(m_current_mode.parent_window, m_szWindowCaption);
- success = 1;
- }
- }
- }
- if (!success)
- m_current_mode.m_skin = 0;
- }
- // remember the client rect that was originally desired...
- RECT windowed_mode_desired_client_rect;
- windowed_mode_desired_client_rect.top = GetPrivateProfileIntW(L"settings",L"nMainWndTop",-1,m_szIniFile);
- windowed_mode_desired_client_rect.left = GetPrivateProfileIntW(L"settings",L"nMainWndLeft",-1,m_szIniFile);
- windowed_mode_desired_client_rect.right = GetPrivateProfileIntW(L"settings",L"nMainWndRight",-1,m_szIniFile);
- windowed_mode_desired_client_rect.bottom = GetPrivateProfileIntW(L"settings",L"nMainWndBottom",-1,m_szIniFile);
- // ...and in case windowed mode init fails severely,
- // set it up to try next time for a simple 256x256 window.
- WriteSafeWindowPos();
- // 7. create the window, if not already created
- if (!m_hwnd)
- {
- m_hwnd = CreateWindowEx(
- MY_EXT_WINDOW_STYLE, // extended style
- MAKEINTATOM(m_classAtom), // class
- m_szWindowCaption, // caption
- MY_WINDOW_STYLE, // style
- windowed_mode_desired_client_rect.left, // left
- windowed_mode_desired_client_rect.top, // top
- windowed_mode_desired_client_rect.right - windowed_mode_desired_client_rect.left, // temporary width
- windowed_mode_desired_client_rect.bottom - windowed_mode_desired_client_rect.top, // temporary height
- m_current_mode.parent_window, // parent window
- NULL, // menu
- m_hInstance, // instance
- (LPVOID)m_uWindowLong
- ); // parms
- if (!m_hwnd)
- {
- wchar_t title[64];
- m_lastErr = DXC_ERR_CREATEWIN;
- MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_CREATEWINDOW_FAILED),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return FALSE;
- }
- SendMessage(m_hwnd_winamp, WM_WA_IPC, (WPARAM)m_hwnd, IPC_SETVISWND);
- if (m_current_mode.m_skin)
- {
- if (GetWinampVersion(mod1.hwndParent) < 0x5051)
- ShowWindow(m_current_mode.parent_window,SW_SHOWNA); // showing the parent wnd will make it size the child, too
- else
- SendMessage(m_current_mode.parent_window, WM_USER+102, 0, 0); // benski> major hack alert. winamp's embedwnd will call ShowWindow in response. SendMessage moves us over to the main thread (we're currently sitting on the viz thread)
- }
- }
- // 8. minimize winamp before creating devices & such, so there aren't
- // any confusing window-focus issues
- MinimizeWinamp(hPluginMonitor);
- // 9. loop to try and create the window.
- // if in windowed mode and not enough vidmem, it will try again w/smaller window
- // (repeatedly, until window client size would be < 64)
- int iteration = 0;
- int device_ok = 0;
- do
- {
- // set the window position
- if (m_current_mode.screenmode==DESKTOP ||
- m_current_mode.screenmode==FAKE_FULLSCREEN)
- {
- int x = m_monitor_rect.right - m_monitor_rect.left;
- int y = m_monitor_rect.bottom - m_monitor_rect.top;
- if (x >= y*2)
- {
- // (pseudo-multimon modes like 2048x768)
- int mid = (m_monitor_rect.left + m_monitor_rect.right)/2;
- if (m_current_mode.m_dualhead_horz==1) // show on left side
- m_monitor_rect.right = mid;
- else if (m_current_mode.m_dualhead_horz==2) // show on right side
- m_monitor_rect.left = mid;
- }
- else if (y > x*4/3)
- {
- // (pseudo-multimon modes like 1024x1536)
- int mid = (m_monitor_rect.top + m_monitor_rect.bottom)/2;
- if (m_current_mode.m_dualhead_vert==1) // show on top half
- m_monitor_rect.bottom = mid;
- else if (m_current_mode.m_dualhead_vert==2) // show on bottom half
- m_monitor_rect.top = mid;
- }
- // recompute width & height (into x,y):
- x = m_monitor_rect.right - m_monitor_rect.left;
- y = m_monitor_rect.bottom - m_monitor_rect.top;
- m_client_width = x;
- m_client_height = y;
- m_window_width = x;
- m_window_height = y;
- if (m_current_mode.screenmode == DESKTOP)
- {
- // note: we initially hide the window, and then
- // only display it once the desktop is all nice & ready.
- // see CPluginShell::DrawAndDisplay().
- RECT r = m_monitor_rect;
- // if possible, shrink the desktop window so it doesn't cover the taskbar.
- HWND hTaskbar = FindWindow("Shell_TrayWnd", "");
- if (hTaskbar)
- {
- RECT taskbar;
- GetWindowRect(hTaskbar, &taskbar);
- int tbw = taskbar.right - taskbar.left;
- int tbh = taskbar.bottom-taskbar.top;
- if (taskbar.bottom == m_monitor_rect.bottom &&
- taskbar.left == m_monitor_rect.left &&
- taskbar.right == m_monitor_rect.right)
- {
- r.bottom -= tbh;
- }
- else if (taskbar.top == m_monitor_rect.top &&
- taskbar.left == m_monitor_rect.left &&
- taskbar.right == m_monitor_rect.right)
- {
- r.top += tbh;
- }
- else if (taskbar.left == m_monitor_rect.left &&
- taskbar.top == m_monitor_rect.top &&
- taskbar.bottom == m_monitor_rect.bottom)
- {
- r.left += tbw;
- }
- else if (taskbar.right == m_monitor_rect.right &&
- taskbar.top == m_monitor_rect.top &&
- taskbar.bottom == m_monitor_rect.bottom)
- {
- r.right -= tbw;
- }
- m_client_width = r.right - r.left;
- m_client_height = r.bottom - r.top;
- m_REAL_client_width = m_client_width;
- m_REAL_client_height = m_client_height;
- m_window_width = m_client_width;
- m_window_height = m_client_height;
- //...ok, but text is squished - some w/h is not right...
- }
- SetWindowPos(m_hwnd,HWND_BOTTOM,r.left,r.top,r.right-r.left,r.bottom-r.top,SWP_HIDEWINDOW);
- }
- else // FAKE_FULLSCREEN
- {
- if (memcmp(&m_all_monitors_rect, &m_monitor_rect, sizeof(RECT))==0)
- {
- // there's only one display, and it's entirely covered
- // by the plugin -> PUT THE PLUGIN ABOVE THE TASKBAR
- // -> normally, if the user clicked another window,
- // it would pop the taskbar to the top; but we don't
- // have to worry about that here, since we're taking
- // up the whole screen.
- // -> don't worry about making the text, etc. avoid
- // the taskbar in this case (see DrawAndDisplay())
- // -> DO worry about hiding the mouse cursor in this case
- // (see WM_SETCURSOR handler)
- m_fake_fs_covers_all = 1;
- //SetWindowPos(m_hwnd,HWND_TOPMOST,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW);
- }
- else
- {
- // there is space to work outside of the plugin window.
- // -> here we pretty much have to let the taskbar stay on
- // top, because it really likes to be there; i.e.,
- // if you click any other window, it automatically
- // pops up again.
- // -> therefore, TRY TO KEEP THE WINDOW ON BOTTOM
- // (below the taskbar). (see PushWindowToBack)
- // -> don't worry about hiding the mouse cursor in this case
- // (see WM_SETCURSOR handler)
- // -> DO worry about making the text, etc. avoid
- // the taskbar in this case (see DrawAndDisplay())
- // (note that if taskbar is in the way, they can move it,
- // since there are other monitors available)
- m_fake_fs_covers_all = 0;
- //SetWindowPos(m_hwnd,HWND_TOP,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW);
- }
- SetWindowPos(m_hwnd,HWND_TOPMOST,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW);
- }
- }
- else if (m_current_mode.screenmode == FULLSCREEN)
- {
- int x = m_current_mode.display_mode.Width ;
- int y = m_current_mode.display_mode.Height;
- int cx = m_monitor_rect.right - m_monitor_rect.left;
- int cy = m_monitor_rect.bottom - m_monitor_rect.top;
- // test #1
- if (x >= y*2 || y > x*4/3) // tackle problem of vert/horz spans
- {
- wchar_t title[64];
- int ret = MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_TRYING_TO_ENTER_FS_MODE_WITH_MULTIPLE_DISPLAYS),
- WASABI_API_LNGSTRINGW_BUF(IDS_TIP, title, 64),
- MB_OKCANCEL|MB_SETFOREGROUND|MB_TOPMOST);
- if (ret==IDCANCEL)
- {
- m_lastErr = DXC_ERR_USER_CANCELED;
- return FALSE;
- }
- }
- // test #2
- if ((cx >= cy*2 && x < y*2) || (cy > cx*4/3 && y <= x*4/3))
- {
- wchar_t title[64];
- int ret = MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_TRYING_TO_ENTER_FS_MODE_WITH_MULTIPLE_DISPLAYS_2),
- WASABI_API_LNGSTRINGW_BUF(IDS_TIP, title, 64),
- MB_OKCANCEL|MB_SETFOREGROUND|MB_TOPMOST);
- if (ret==IDCANCEL)
- {
- m_lastErr = DXC_ERR_USER_CANCELED;
- return FALSE;
- }
- }
- m_client_width = x;
- m_client_height = y;
- m_window_width = x;
- m_window_height = y;
- SetWindowPos(m_hwnd,HWND_TOPMOST,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW);
- }
- else // WINDOWED
- {
- RECT margin;
- if (m_current_mode.m_skin)
- {
- RECT r1, r2;
- GetWindowRect(m_current_mode.parent_window, &r1);
- GetWindowRect(m_hwnd , &r2);
- margin.left = r2.left - r1.left;
- margin.right = r1.right - r2.right;
- margin.top = r2.top - r1.top;
- margin.bottom= r1.bottom - r2.bottom;
- }
- else
- {
- RECT r1;
- SetRect(&r1, 0, 0, 256, 256);
- AdjustWindowRect(&r1, MY_WINDOW_STYLE, 0);
- margin.left = 0 - r1.left;
- margin.right = r1.right - 256;
- margin.top = 0 - r1.top;
- margin.bottom= r1.bottom - 256;
- }
- int autosize = 1;
- RECT r = windowed_mode_desired_client_rect;
- if (iteration==0 && r.top != -1 && r.left != -1 && r.bottom != -1 && r.right != -1)
- {
- // use prev. window coordinates:
- m_REAL_client_width = r.right - r.left;
- m_REAL_client_height = r.bottom - r.top;
- GetSnappedClientSize();
- if (m_current_mode.m_skin) // check this here in case they got a non-aligned size by resizing when "integrated with winamp" was unchecked, then checked it & ran the plugin...
- {
- // STRANGE ALIGNMENTS FOR THE WINDOW FRAME: (required by winamp 2):
- // the window frame's width must be divisible by 25, and height by 29.
- if (GetWinampVersion(mod1.hwndParent) < 0x4000) // ... winamp 5 doesn't have this prob. (test vs. 0x4000 because winamp5 betas have version tags like 0x4987)
- {
- m_REAL_client_width = ((m_client_width + margin.left + margin.right)/25)*25 - margin.left - margin.right;
- m_REAL_client_height = ((m_client_height + margin.top + margin.bottom)/29)*29 - margin.top - margin.bottom;
- GetSnappedClientSize();
- }
- }
- // transform screen-space CLIENT rect into screen-space WINDOW rect
- r.top = windowed_mode_desired_client_rect.top - margin.top;
- r.left = windowed_mode_desired_client_rect.left - margin.left;
- r.right = r.left + margin.left + m_REAL_client_width + margin.right;
- r.bottom = r.top + margin.top + m_REAL_client_height + margin.bottom;
- // make sure the window is entirely visible on the selected monitor;
- // otherwise, autosize/place it.
- // (note that this test is only appled 1) at startup, and 2) after a resize/max/restore.
- // this test is not applied when merely moving the window.)
- if (r.top >= m_monitor_work_rect.top &&
- r.left >= m_monitor_work_rect.left &&
- r.right <= m_monitor_work_rect.right &&
- r.bottom <= m_monitor_work_rect.bottom)
- {
- if (m_current_mode.m_skin)
- {
- m_window_width = m_REAL_client_width ; // m_window_width/height are for OUR borderless window, not the embedwnd parent frame.
- m_window_height = m_REAL_client_height;
- SetWindowPos(m_current_mode.parent_window,HWND_NOTOPMOST, r.left, r.top, r.right-r.left, r.bottom-r.top, /*SWP_SHOWWINDOW|*//*SWP_ASYNCWINDOWPOS*/0);
- SetWindowPos(m_hwnd ,HWND_NOTOPMOST, windowed_mode_desired_client_rect.left,
- windowed_mode_desired_client_rect.top,
- m_REAL_client_width,
- m_REAL_client_height,
- SWP_SHOWWINDOW);
- }
- else
- {
- m_window_width = r.right - r.left;
- m_window_height = r.bottom - r.top;
- SetWindowPos(m_hwnd,HWND_NOTOPMOST,r.left,r.top,m_window_width,m_window_height,SWP_SHOWWINDOW);
- }
- autosize = 0;
- }
- }
- if (autosize)
- {
- int size = GetWindowedModeAutoSize(iteration); // note: requires 'm_monitor_rect' has been set!
- m_REAL_client_width = size;
- m_REAL_client_height = size;
- GetSnappedClientSize();
- if (m_current_mode.m_skin)
- {
- // STRANGE ALIGNMENTS FOR THE WINDOW FRAME: (required by winamp 2):
- // the window frame's width must be divisible by 25, and height by 29.
- if (GetWinampVersion(mod1.hwndParent) < 0x4000) // ... winamp 5 doesn't have this prob. (test vs. 0x4000 because winamp5 betas have version tags like 0x4987)
- {
- m_REAL_client_width = ((m_client_width + margin.left + margin.right)/25)*25 - margin.left - margin.right;
- m_REAL_client_height = ((m_client_height + margin.top + margin.bottom)/29)*29 - margin.top - margin.bottom;
- GetSnappedClientSize();
- }
- m_window_width = m_client_width ; // m_window_width/height are for OUR [borderless] window, not the parent window (which is the embedwnd frame).
- m_window_height = m_client_height;
- SetWindowPos(m_current_mode.parent_window,HWND_NOTOPMOST, m_monitor_work_rect.left+32, m_monitor_work_rect.top+32, m_client_width + margin.left + margin.right, m_client_height + margin.top + margin.bottom, /*SWP_SHOWWINDOW|*//*SWP_ASYNCWINDOWPOS*/0);
- SetWindowPos(m_hwnd ,HWND_NOTOPMOST, m_monitor_work_rect.left+32 + margin.left, m_monitor_work_rect.top+32 + margin.top, m_client_width, m_client_height, SWP_SHOWWINDOW);
- }
- else
- {
- SetRect(&r, 0, 0, size, size);
- AdjustWindowRect(&r, MY_WINDOW_STYLE, 0);
- m_window_width = r.right - r.left;
- m_window_height = r.bottom - r.top;
- SetWindowPos(m_hwnd,HWND_NOTOPMOST, m_monitor_work_rect.left+32, m_monitor_work_rect.top+32, m_window_width, m_window_height, SWP_SHOWWINDOW);
- }
- }
- }
- m_frame_delay = 1; // set this to 2 if you use triple buffering!
- {
- m_current_mode.display_mode.Width = m_client_width;
- m_current_mode.display_mode.Height = m_client_height;
- // set up m_d3dpp (presentation parameters):
- ZeroMemory(&m_d3dpp,sizeof(m_d3dpp));
- m_d3dpp.Windowed = (m_current_mode.screenmode==FULLSCREEN) ? 0 : 1;
- m_d3dpp.BackBufferFormat = m_current_mode.display_mode.Format;
- m_d3dpp.BackBufferWidth = m_client_width;
- m_d3dpp.BackBufferHeight = m_client_height;
- m_d3dpp.BackBufferCount = m_current_mode.nbackbuf;
- if (m_current_mode.screenmode==FULLSCREEN)
- m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//D3DSWAPEFFECT_FLIP;
- else // windowed or fake FS
- m_d3dpp.SwapEffect = (m_current_mode.allow_page_tearing) ? D3DSWAPEFFECT_DISCARD : D3DSWAPEFFECT_COPY;//D3DSWAPEFFECT_DISCARD;//D3DSWAPEFFECT_FLIP;
- // note: multisampling is only allowed if swapeffect is DISCARD!
- m_d3dpp.MultiSampleType = (m_d3dpp.SwapEffect==D3DSWAPEFFECT_DISCARD) ? m_current_mode.multisamp : D3DMULTISAMPLE_NONE;
- //m_d3dpp.hDeviceWindow = m_hwnd;
- if (m_current_mode.screenmode==FULLSCREEN)
- {
- m_d3dpp.FullScreen_RefreshRateInHz = m_current_mode.display_mode.RefreshRate;//D3DPRESENT_RATE_DEFAULT;
- m_d3dpp.PresentationInterval = m_current_mode.allow_page_tearing ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;//D3DPRESENT_INTERVAL_IMMEDIATE;//D3DPRESENT_INTERVAL_ONE;
- }
- if (m_zFormat != D3DFMT_UNKNOWN)
- {
- m_d3dpp.EnableAutoDepthStencil=TRUE;
- m_d3dpp.AutoDepthStencilFormat=m_zFormat;
- }
- // finally, create the device:
- HRESULT hRes;
- if (FAILED(hRes = m_lpD3D->CreateDevice(
- m_ordinal_adapter,
- D3DDEVTYPE_HAL,
- m_hwnd,
- (m_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING,
- &m_d3dpp,
- &m_lpDevice)))
- {
- int code = LOWORD(hRes);
- wchar_t str[1024];
- if (code==2156) //D3DERR_NOTAVAILABLE
- {
- m_lastErr = DXC_ERR_CREATEDEV_NOT_AVAIL;
- wchar_t str[2048];
- WASABI_API_LNGSTRINGW_BUF(IDS_UNABLE_TO_CREATE_DIRECTX_DEVICE, str, 2048);
- if (m_current_mode.screenmode == FULLSCREEN)
- StringCbCatW(str, sizeof(str), WASABI_API_LNGSTRINGW(IDS_OLDER_DISPLAY_ADAPTER_CATENATION));
- else
- StringCbCatW(str, sizeof(str), WASABI_API_LNGSTRINGW(IDS_OLDER_DISPLAY_ADAPTER_CATENATION_2));
- MessageBoxW(m_hwnd,str,
- WASABI_API_LNGSTRINGW(IDS_MILKDROP_ERROR),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return FALSE;
- }
- else if (m_current_mode.screenmode==WINDOWED && m_client_width>64)
- {
- // DO NOTHING; try again w/smaller window
- }
- else if (m_current_mode.screenmode != WINDOWED || m_client_width <= 64)
- {
- // usually, code==2154 here, which is D3DERR_OUTOFVIDEOMEMORY
- m_lastErr = DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY;
- StringCbPrintfW(str, sizeof(str), WASABI_API_LNGSTRINGW(IDS_DIRECTX_INIT_FAILED_X), LOWORD(hRes));
- // NOTE: *A 'SUGGESTION' SCREEN SHOULD APPEAR NEXT, PROVIDED BY THE CALLER*
- MessageBoxW(m_hwnd, str,
- WASABI_API_LNGSTRINGW(IDS_MILKDROP_ERROR),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return FALSE;
- }
- }
- else
- {
- device_ok = 1;
- }
- }
- iteration++;
- }
- while (!device_ok);
- // set initial viewport
- SetViewport();
- // for desktop mode, push window to back again:
- if (m_current_mode.screenmode==DESKTOP)
- SetWindowPos(m_hwnd,HWND_BOTTOM,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
- if (m_current_mode.m_skin)
- {
- if (GetWinampVersion(mod1.hwndParent) < 0x5051)
- SetFocus(m_current_mode.parent_window);
- else
- PostMessage(m_current_mode.parent_window, WM_USER+103, 0, 0);
-
- //SetActiveWindow(m_current_mode.parent_window);
- //SetForegroundWindow(m_current_mode.parent_window);
- }
- /*if (m_current_mode.screenmode == WINDOWED)
- SaveWindow();*/
- // return success
- m_ready = TRUE;
- // benski> a little hack to get the window size correct. it seems to work
- if (m_current_mode.screenmode==WINDOWED)
- PostMessage(m_hwnd, WM_USER+555, 0, 0);
- return TRUE;
- }
- BOOL DXContext::StartOrRestartDevice(DXCONTEXT_PARAMS *pParams)
- {
- // call this to [re]initialize the DirectX environment with new parameters.
- // examples: startup; toggle windowed/fullscreen mode; change fullscreen resolution;
- // and so on.
- // be sure to clean up all your DirectX stuff first (textures, vertex buffers,
- // D3DX allocations, etc.) and reallocate it afterwards!
- // note: for windowed mode, 'pParams->disp_mode' (w/h/r/f) is ignored.
- // destroy old window
- if (myWindowState.me)
- {
- m_ignore_wm_destroy = 1;
- if (m_current_mode.screenmode == WINDOWED)
- SaveWindow();
- DestroyWindow(myWindowState.me);
- myWindowState.me = NULL;
- m_ignore_wm_destroy = 0;
- m_hwnd=0;
- }
- else if (m_hwnd)
- {
- SendMessage(m_hwnd_winamp, WM_WA_IPC, NULL, IPC_SETVISWND);
- m_ignore_wm_destroy = 1;
- DestroyWindow(m_hwnd);
- m_ignore_wm_destroy = 0;
- m_hwnd = NULL;
- }
- if (!m_ready)
- {
- // first-time init: create a fresh new device
- return Internal_Init(pParams, TRUE);
- }
- else
- {
- // re-init: preserve the DX9 object (m_lpD3D),
- // but destroy and re-create the DX9 device (m_lpDevice).
- m_ready = FALSE;
- SafeRelease(m_lpDevice);
- // but leave the D3D object!
- RestoreWinamp();
- return Internal_Init(pParams, FALSE);
- }
- }
- BOOL DXContext::OnUserResizeWindow(RECT *new_window_rect, RECT *new_client_rect)
- {
- // call this function on WM_EXITSIZEMOVE when running windowed.
- // don't bother calling this when fullscreen.
- // be sure to clean up all your DirectX stuff first (textures, vertex buffers,
- // D3DX allocations, etc.) and reallocate it afterwards!
- if (!m_ready || (m_current_mode.screenmode != WINDOWED))
- return FALSE;
- if ((m_client_width == new_client_rect->right - new_client_rect->left) &&
- (m_client_height == new_client_rect->bottom - new_client_rect->top) &&
- (m_window_width == new_window_rect->right - new_window_rect->left) &&
- (m_window_height == new_window_rect->bottom - new_window_rect->top))
- {
- return TRUE;
- }
- m_ready = FALSE;
- m_window_width = new_window_rect->right - new_window_rect->left;
- m_window_height = new_window_rect->bottom - new_window_rect->top;
- m_REAL_client_width = new_client_rect->right - new_client_rect->left;
- m_REAL_client_height = new_client_rect->bottom - new_client_rect->top;
- GetSnappedClientSize(); //sets m_client_width/height, but with snapping, if in windowed mode.
- m_d3dpp.BackBufferWidth = m_client_width;
- m_d3dpp.BackBufferHeight = m_client_height;
- if (m_lpDevice->Reset(&m_d3dpp) != D3D_OK)
- {
- WriteSafeWindowPos();
- wchar_t title[64];
- MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_WINDOW_RESIZE_FAILED),
- WASABI_API_LNGSTRINGW_BUF(IDS_OUT_OF_VIDEO_MEMORY, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- m_lastErr = DXC_ERR_RESIZEFAILED;
- return FALSE;
- }
- SetViewport();
- m_ready = TRUE;
- return TRUE;
- }
- void DXContext::SetViewport()
- {
- D3DVIEWPORT9 v;
- v.X = 0;
- v.Y = 0;
- v.Width = m_client_width;
- v.Height = m_client_height;
- v.MinZ = 0.0f;
- v.MaxZ = 1.0f;
- m_lpDevice->SetViewport(&v);
- }
- void DXContext::MinimizeWinamp(HMONITOR hPluginMonitor)
- {
- // minimize Winamp window
- HMONITOR hWinampMon = MonitorFromWindow(m_hwnd_winamp, MONITOR_DEFAULTTONEAREST);
- HMONITOR hPluginMon = hPluginMonitor;//MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);//m_lpD3D->GetAdapterMonitor(ordinal_adapter);
- if ((m_current_mode.screenmode == FULLSCREEN || m_current_mode.screenmode == FAKE_FULLSCREEN) &&
- (m_minimize_winamp) &&
- (hWinampMon && hPluginMon && hPluginMon==hWinampMon) &&
- (!m_winamp_minimized)
- )
- {
- // nitpicky check: if we're in fake fullscreen mode
- // and are only going to display on half the screen,
- // don't minimize Winamp.
- if (m_current_mode.screenmode == FAKE_FULLSCREEN)
- {
- int x = m_monitor_rect.right - m_monitor_rect.left;
- int y = m_monitor_rect.bottom - m_monitor_rect.top;
- if ((x >= y*2 && m_current_mode.m_dualhead_horz != 0) ||
- (y > x*4/3 && m_current_mode.m_dualhead_vert != 0))
- {
- return;
- }
- }
- ShowWindow(m_hwnd_winamp, SW_MINIMIZE);
- // also restore the focus to the plugin window, since this will steal it:
- SetFocus(m_hwnd);
- SetActiveWindow(m_hwnd);
- SetForegroundWindow(m_hwnd);
- m_winamp_minimized = 1;
- }
- }
- void DXContext::RestoreWinamp()
- {
- if (m_winamp_minimized)
- {
- ShowWindow(m_hwnd_winamp, SW_RESTORE);
- m_winamp_minimized = 0;
- }
- }
- void DXContext::UpdateMonitorWorkRect()
- {
- // get active monitor's bounding rectangle (to assist w/window positioning)
- // note: in vert/horz span setups (psuedo-multimon),
- // this will be 2048x768 or 1024x1536 or something like that.
- // calling this each frame allows you to detect when the taskbar
- // moves around on the screen (from edge to edge), and rearrange
- // the visual elements accordingly, so nothing is obscured.
- HMONITOR hMon = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);//m_lpD3D->GetAdapterMonitor(m_ordinal_adapter);
- if (hMon)
- {
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hMon, &mi))
- {
- m_monitor_work_rect = mi.rcWork;
- m_monitor_work_rect_orig = mi.rcWork;
- // if the monitor rect we're using is the same as the
- // whole area of the monitor, there's no need to update it...
- //if (memcmp(&mi.rcMonitor, &m_monitor_rect, sizeof(RECT))==0)
- // return;
- // otherwise, we're doing a half-screen special case
- // and are running in some pseudo-multimon res like
- // 2048x768 or 1024x1536, but only using half of it
- // (i.e. fake fullscreen or desktop mode)
- // therefore... we need to update the work-area rectangle
- // to reflect which half of the screen it's on.
- if (m_monitor_rect.left == mi.rcMonitor.left)
- m_monitor_work_rect.left = mi.rcWork.left;
- else
- m_monitor_work_rect.left = m_monitor_rect.left + (mi.rcWork.left - mi.rcMonitor.left);
- if (m_monitor_rect.top == mi.rcMonitor.top)
- m_monitor_work_rect.top = mi.rcWork.top;
- else
- m_monitor_work_rect.top = m_monitor_rect.top + (mi.rcWork.top - mi.rcMonitor.top);
- if (m_monitor_rect.right == mi.rcMonitor.right)
- m_monitor_work_rect.right = mi.rcWork.right;
- else
- m_monitor_work_rect.right = m_monitor_rect.right;
- if (m_monitor_rect.bottom == mi.rcMonitor.bottom)
- m_monitor_work_rect.bottom = mi.rcWork.bottom;
- else
- m_monitor_work_rect.bottom = m_monitor_rect.bottom;
- }
- }
- }
- void DXContext::SaveWindow()
- {
- if ( m_hwnd == NULL )
- return;
- if (m_current_mode.screenmode == WINDOWED)
- {
- RECT c;
- GetClientRect(m_hwnd, &c);
- // convert client rect from client coords to screen coords:
- // (window rect is already in screen coords...)
- POINT p;
- p.x = c.left;
- p.y = c.top;
- if (ClientToScreen(m_hwnd, &p))
- {
- c.left += p.x;
- c.right += p.x;
- c.top += p.y;
- c.bottom += p.y;
- }
- // save bounds for window CLIENT area, but in screen coords
- WritePrivateProfileIntW(c.top, L"nMainWndTop", m_szIniFile, L"settings");
- WritePrivateProfileIntW(c.left, L"nMainWndLeft", m_szIniFile, L"settings");
- WritePrivateProfileIntW(c.right, L"nMainWndRight", m_szIniFile, L"settings");
- WritePrivateProfileIntW(c.bottom,L"nMainWndBottom", m_szIniFile, L"settings");
- // also save bounds for embedwnd
- if (m_current_mode.m_skin && myWindowState.me)
- {
- WritePrivateProfileIntW(myWindowState.r.left,L"avs_wx",m_szIniFile,L"settings");
- WritePrivateProfileIntW(myWindowState.r.top ,L"avs_wy",m_szIniFile,L"settings");
- WritePrivateProfileIntW(myWindowState.r.right-myWindowState.r.left,L"avs_ww",m_szIniFile,L"settings");
- WritePrivateProfileIntW(myWindowState.r.bottom-myWindowState.r.top,L"avs_wh",m_szIniFile,L"settings");
- }
- else if (!m_current_mode.m_skin && m_hwnd)
- {
- RECT r;
- GetWindowRect(m_hwnd, &r);
- WritePrivateProfileIntW(r.left,L"avs_wx",m_szIniFile,L"settings");
- WritePrivateProfileIntW(r.top ,L"avs_wy",m_szIniFile,L"settings");
- WritePrivateProfileIntW(r.right-r.left,L"avs_ww",m_szIniFile,L"settings");
- WritePrivateProfileIntW(r.bottom-r.top,L"avs_wh",m_szIniFile,L"settings");
- }
- }
- }
|