123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693 |
- /*
- 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.
- */
- /*
- TO DO
- -----
- -done/v1.06:
- -(nothing yet)
- -
- -
- -to do/v1.06:
- -FFT: high freq. data kinda sucks because of the 8-bit samples we get in;
- look for justin to put 16-bit vis data into wa5.
- -make an 'advanced view' button on config panel; hide complicated stuff
- til they click that.
- -put an asterisk(*) next to the 'max framerate' values that
- are ideal (given the current windows display mode or selected FS dispmode).
- -or add checkbox: "smart sync"
- -> matches FPS limit to nearest integer divisor of refresh rate.
- -debug.txt/logging support!
- -audio: make it a DSP plugin? then we could get the complete, continuous waveform
- and overlap our waveform windows, so we'd never miss a brief high note.
- -bugs:
- -vms plugins sometimes freeze after a several-minute pause; I've seen it
- with most of them. hard to repro, though.
- -running FS on monitor 2, hit ALT-TAB -> minimizes!!!
- -but only if you let go of TAB first. Let go of ALT first and it's fine!
- -> means it's related to the keyup...
- -fix delayloadhelper leak; one for each launch to config panel/plugin.
- -also, delayload(d3d9.dll) still leaks, if plugin has error initializing and
- quits by returning false from PluginInitialize().
- -add config panel option to ignore fake-fullscreen tips
- -"tip" boxes in dxcontext.cpp
- -"notice" box on WM_ACTIVATEAPP?
- -desktop mode:
- -icon context menus: 'send to', 'cut', and 'copy' links do nothing.
- -http://netez.com/2xExplorer/shellFAQ/bas_context.html
- -create a 2nd texture to render all icon text labels into
- (they're the sole reason that desktop mode is slow)
- -in UpdateIconBitmaps, don't read the whole bitmap and THEN
- realize it's a dupe; try to compare icon filename+index or somethign?
- -DRAG AND DROP. COMPLICATED; MANY DETAILS.
- -http://netez.com/2xExplorer/shellFAQ/adv_drag.html
- -http://www.codeproject.com/shell/explorerdragdrop.asp
- -hmm... you can't drag icons between the 2 desktops (ugh)
- -multiple delete/open/props/etc
- -delete + enter + arrow keys.
- -try to solve mysteries w/ShellExecuteEx() and desktop *shortcuts* (*.lnk).
- -(notice that when icons are selected, they get modulated by the
- highlight color, when they should be blended 50% with that color.)
- ---------------------------
- final touches:
- -Tests:
- -make sure desktop still functions/responds properly when winamp paused
- -desktop mode + multimon:
- -try desktop mode on all monitors
- -try moving taskbar around; make sure icons are in the
- right place, that context menus (general & for
- specific icons) pop up in the right place, and that
- text-off-left-edge is ok.
- -try setting the 2 monitors to different/same resolutions
- -check tab order of config panel controls!
- -Clean All
- -build in release mode to include in the ZIP
- -leave only one file open in workspace: README.TXT.
- -TEMPORARILY "ATTRIB -R" ALL FILES BEFORE ZIPPING THEM!
- ---------------------------
- KEEP IN VIEW:
- -EMBEDWND:
- -kiv: on resize of embedwnd, it's out of our control; winamp
- resizes the child every time the mouse position changes,
- and we have to cleanup & reallocate everything, b/c we
- can't tell when the resize begins & ends.
- [justin said he'd fix in wa5, though]
- -kiv: with embedded windows of any type (plugin, playlist, etc.)
- you can't place the winamp main wnd over them.
- -kiv: embedded windows are child windows and don't get the
- WM_SETFOCUS or WM_KILLFOCUS messages when they get or lose
- the focus. (For a workaround, see milkdrop & scroll lock key.)
- -kiv: tiny bug (IGNORE): when switching between embedwnd &
- no-embedding, the window gets scooted a tiny tiny bit.
- -kiv: fake fullscreen mode w/multiple monitors: there is no way
- to keep the taskbar from popping up [potentially overtop of
- the plugin] when you click on something besides the plugin.
- To get around this, use true fullscreen mode.
- -kiv: max_fps implementation assumptions:
- -that most computers support high-precision timer
- -that no computers [regularly] sleep for more than 1-2 ms
- when you call Sleep(1) after timeBeginPeriod(1).
- -reminder: if vms_desktop.dll's interface needs changed,
- it will have to be renamed! (version # upgrades are ok
- as long as it won't break on an old version; if the
- new functionality is essential, rename the DLL.)
- ---------------------------
- REMEMBER:
- -GF2MX + GF4 have icon scooting probs in desktop mode
- (when taskbar is on upper or left edge of screen)
- -Radeon is the one w/super slow text probs @ 1280x1024.
- (it goes unstable after you show playlist AND helpscr; -> ~1 fps)
- -Mark's win98 machine has hidden cursor (in all modes),
- but no one else seems to have this problem.
- -links:
- -win2k-only-style desktop mode: (uses VirtualAllocEx, vs. DLL Injection)
- http://www.digiwar.com/scripts/renderpage.php?section=2&subsection=2
- -http://www.experts-exchange.com/Programming/Programming_Platforms/Win_Prog/Q_20096218.html
- */
- #include "api__vis_milk2.h"
- #include "pluginshell.h"
- #include "utility.h"
- #include "defines.h"
- #include "shell_defines.h"
- #include "resource.h"
- #include "vis.h"
- #include <multimon.h>
- #include "../Winamp/wa_ipc.h"
- #include "../nu/AutoCharFn.h"
- #include <mmsystem.h>
- #pragma comment(lib,"winmm.lib") // for timeGetTime
- // STATE VALUES & VERTEX FORMATS FOR HELP SCREEN TEXTURE:
- #define TEXT_SURFACE_NOT_READY 0
- #define TEXT_SURFACE_REQUESTED 1
- #define TEXT_SURFACE_READY 2
- #define TEXT_SURFACE_ERROR 3
- typedef struct _HELPVERTEX
- {
- float x, y; // screen position
- float z; // Z-buffer depth
- DWORD Diffuse; // diffuse color. also acts as filler; aligns struct to 16 bytes (good for random access/indexed prims)
- float tu, tv; // texture coordinates for texture #0
- } HELPVERTEX, *LPHELPVERTEX;
- #define HELP_VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
- typedef struct _SIMPLEVERTEX
- {
- float x, y; // screen position
- float z; // Z-buffer depth
- DWORD Diffuse; // diffuse color. also acts as filler; aligns struct to 16 bytes (good for random access/indexed prims)
- } SIMPLEVERTEX, *LPSIMPLEVERTEX;
- #define SIMPLE_VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE)
- extern wchar_t* g_szHelp;
- extern int g_szHelp_W;
- extern winampVisModule mod1;
- // resides in vms_desktop.dll/lib:
- void getItemData(int x);
- CPluginShell::CPluginShell()
- {
- // this should remain empty!
- }
- CPluginShell::~CPluginShell()
- {
- // this should remain empty!
- }
- eScrMode CPluginShell::GetScreenMode()
- {
- return m_screenmode;
- }
- int CPluginShell::GetFrame()
- {
- return m_frame;
- }
- float CPluginShell::GetTime()
- {
- return m_time;
- }
- float CPluginShell::GetFps()
- {
- return m_fps;
- }
- HWND CPluginShell::GetPluginWindow()
- {
- if (m_lpDX) return m_lpDX->GetHwnd(); else return NULL;
- }
- int CPluginShell::GetWidth()
- {
- if (m_lpDX) return m_lpDX->m_client_width; else return 0;
- }
- int CPluginShell::GetHeight()
- {
- if (m_lpDX) return m_lpDX->m_client_height; else return 0;
- }
- int CPluginShell::GetCanvasMarginX()
- {
- if (m_lpDX && m_screenmode==WINDOWED) return (m_lpDX->m_client_width - m_lpDX->m_REAL_client_width)/2; else return 0;
- }
- int CPluginShell::GetCanvasMarginY()
- {
- if (m_lpDX && m_screenmode==WINDOWED) return (m_lpDX->m_client_height - m_lpDX->m_REAL_client_height)/2; else return 0;
- }
- HWND CPluginShell::GetWinampWindow()
- {
- return m_hWndWinamp;
- }
- HINSTANCE CPluginShell::GetInstance()
- {
- return m_hInstance;
- }
- wchar_t* CPluginShell::GetPluginsDirPath()
- {
- return m_szPluginsDirPath;
- }
- wchar_t* CPluginShell::GetConfigIniFile()
- {
- return m_szConfigIniFile;
- }
- char* CPluginShell::GetConfigIniFileA()
- {
- return m_szConfigIniFileA;
- }
- int CPluginShell::GetFontHeight(eFontIndex idx)
- {
- if (idx >= 0 && idx < NUM_BASIC_FONTS + NUM_EXTRA_FONTS) return m_fontinfo[idx].nSize; else return 0;
- }
- int CPluginShell::GetBitDepth()
- {
- return m_lpDX->GetBitDepth();
- }
- LPDIRECT3DDEVICE9 CPluginShell::GetDevice()
- {
- if (m_lpDX) return m_lpDX->m_lpDevice; else return NULL;
- }
- D3DCAPS9* CPluginShell::GetCaps()
- {
- if (m_lpDX) return &(m_lpDX->m_caps); else return NULL;
- }
- D3DFORMAT CPluginShell::GetBackBufFormat()
- {
- if (m_lpDX) return m_lpDX->m_current_mode.display_mode.Format; else return D3DFMT_UNKNOWN;
- }
- D3DFORMAT CPluginShell::GetBackBufZFormat()
- {
- if (m_lpDX) return m_lpDX->GetZFormat(); else return D3DFMT_UNKNOWN;
- }
- LPD3DXFONT CPluginShell::GetFont(eFontIndex idx)
- {
- if (idx >= 0 && idx < NUM_BASIC_FONTS + NUM_EXTRA_FONTS) return m_d3dx_font[idx]; else return NULL;
- }
- char* CPluginShell::GetDriverFilename()
- {
- if (m_lpDX) return m_lpDX->GetDriver(); else return NULL;
- }
- char* CPluginShell::GetDriverDescription()
- {
- if (m_lpDX) return m_lpDX->GetDesc(); else return NULL;
- }
- int CPluginShell::InitNondx9Stuff()
- {
- timeBeginPeriod(1);
- m_fftobj.Init(576, NUM_FREQUENCIES);
- if (!InitGDIStuff()) return false;
- return AllocateMyNonDx9Stuff();
- }
- void CPluginShell::CleanUpNondx9Stuff()
- {
- timeEndPeriod(1);
- CleanUpMyNonDx9Stuff();
- CleanUpGDIStuff();
- m_fftobj.CleanUp();
- }
- int CPluginShell::InitGDIStuff()
- {
- wchar_t title[64];
- // note: messagebox parent window should be NULL here, because lpDX is still NULL!
- for (int i=0; i<NUM_BASIC_FONTS + NUM_EXTRA_FONTS; i++)
- {
- if (!(m_font[i] = CreateFontW(m_fontinfo[i].nSize, 0, 0, 0, m_fontinfo[i].bBold ? 900 : 400, m_fontinfo[i].bItalic, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, m_fontinfo[i].bAntiAliased ? ANTIALIASED_QUALITY : DEFAULT_QUALITY, DEFAULT_PITCH, m_fontinfo[i].szFace)))
- {
- MessageBoxW(NULL, WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_GDI_FONTS),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- }
- if (!(m_main_menu = WASABI_API_LOADMENU(IDR_WINDOWED_CONTEXT_MENU)))
- {
- MessageBoxW(NULL, WASABI_API_LNGSTRINGW(IDS_ERROR_LOADING_MAIN_MENU),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- if (!(m_context_menu = GetSubMenu(m_main_menu, 0)))
- {
- MessageBoxW(NULL, WASABI_API_LNGSTRINGW(IDS_ERROR_LOADING_CONTEXT_MENU),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- return true;
- }
- void CPluginShell::CleanUpGDIStuff()
- {
- for (int i=0; i<NUM_BASIC_FONTS + NUM_EXTRA_FONTS; i++)
- {
- if (m_font[i])
- {
- DeleteObject(m_font[i]);
- m_font[i] = NULL;
- }
- }
- /*if (m_context_menu)
- {
- DestroyMenu(m_context_menu);
- m_context_menu = NULL;
- }*/
- if (m_main_menu)
- {
- DestroyMenu(m_main_menu);
- m_main_menu = NULL;
- }
- //CleanUpMyGDIStuff();
- }
- int CPluginShell::InitVJStuff(RECT* pClientRect)
- {
- wchar_t title[64];
- // Init VJ mode (second window for text):
- if (m_vj_mode)
- {
- DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_SYSMENU;
- POINT upper_left_corner;
- upper_left_corner.x = 0;
- upper_left_corner.y = 0;
- // Create direct 3d & get some infos
- if (!(m_vjd3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
- {
- MessageBoxW(NULL, WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_DIRECT3D_DEVICE_FOR_VJ_MODE),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64), MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- // Get ordinal adapter # for the currently-selected Windowed Mode display adapter
- int ordinal_adapter = D3DADAPTER_DEFAULT;
- int nAdapters = m_vjd3d9->GetAdapterCount();
- for (int i=0; i<nAdapters; i++)
- {
- D3DADAPTER_IDENTIFIER9 temp;
- if ((m_vjd3d9->GetAdapterIdentifier(i, /*D3DENUM_NO_WHQL_LEVEL*/ 0, &temp) == D3D_OK) &&
- (memcmp(&temp.DeviceIdentifier, &m_adapter_guid_windowed, sizeof(GUID))==0))
- {
- ordinal_adapter = i;
- break;
- }
- }
- // Get current display mode for windowed-mode adapter:
- D3DDISPLAYMODE dm;
- if (D3D_OK != m_vjd3d9->GetAdapterDisplayMode(ordinal_adapter, &dm))
- {
- MessageBoxW(NULL, WASABI_API_LNGSTRINGW(IDS_VJ_MODE_INIT_ERROR),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- // And get the upper-left corner of the monitor for it:
- HMONITOR hMon = m_vjd3d9->GetAdapterMonitor(ordinal_adapter);
- if (hMon)
- {
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hMon, &mi))
- {
- upper_left_corner.x = mi.rcWork.left;
- upper_left_corner.y = mi.rcWork.top;
- }
- }
- // CREATE THE WINDOW
- RECT rect;
- if (pClientRect)
- {
- rect = *pClientRect;
- AdjustWindowRect(&rect, dwStyle, 0); // convert client->wnd
- }
- else
- {
- SetRect(&rect, 0, 0, 384, 384);
- AdjustWindowRect(&rect, dwStyle, 0); // convert client->wnd
- rect.right -= rect.left;
- rect.left = 0;
- rect.bottom -= rect.top;
- rect.top = 0;
- rect.top += upper_left_corner.y+32;
- rect.left += upper_left_corner.x+32;
- rect.right += upper_left_corner.x+32;
- rect.bottom += upper_left_corner.y+32;
- }
- WNDCLASS wc = {0};
- wc.lpfnWndProc = VJModeWndProc; // our window procedure
- wc.hInstance = GetInstance(); // hInstance of DLL
- wc.hIcon = LoadIcon(GetInstance(), MAKEINTRESOURCE(IDI_PLUGIN_ICON));
- wc.lpszClassName = TEXT_WINDOW_CLASSNAME; // our window class name
- wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; // CS_DBLCLKS lets the window receive WM_LBUTTONDBLCLK, for toggling fullscreen mode...
- wc.cbWndExtra = sizeof(DWORD);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
- if (!RegisterClass(&wc))
- {
- MessageBoxW(NULL, WASABI_API_LNGSTRINGW(IDS_ERROR_REGISTERING_WINDOW_CLASS_FOR_TEXT_WINDOW),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- m_bTextWindowClassRegistered = true;
- //DWORD nThreadID;
- //CreateThread(NULL, 0, TextWindowThread, &rect, 0, &nThreadID);
- // Create the text window
- m_hTextWnd = CreateWindowEx(
- 0,
- TEXT_WINDOW_CLASSNAME, // our window class name
- TEXT_WINDOW_CLASSNAME, // use description for a window title
- dwStyle,
- rect.left, rect.top, // screen position (read from config)
- rect.right - rect.left, rect.bottom - rect.top, // width & height of window (need to adjust client area later)
- NULL, // parent window (winamp main window)
- NULL, // no menu
- GetInstance(), // hInstance of DLL
- NULL
- ); // no window creation data
- if (!m_hTextWnd)
- {
- MessageBoxW(NULL, WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_VJ_WINDOW),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- SetWindowLongPtr(m_hTextWnd, GWLP_USERDATA, (LONG_PTR)this);
- GetClientRect(m_hTextWnd, &rect);
- m_nTextWndWidth = rect.right-rect.left;
- m_nTextWndHeight = rect.bottom-rect.top;
- // Create the device
- D3DPRESENT_PARAMETERS pres_param;
- ZeroMemory(&pres_param,sizeof(pres_param));
- pres_param.BackBufferCount = 0;
- pres_param.BackBufferFormat = dm.Format;
- pres_param.BackBufferWidth = rect.right - rect.left;
- pres_param.BackBufferHeight = rect.bottom - rect.top;
- pres_param.hDeviceWindow = m_hTextWnd;
- pres_param.AutoDepthStencilFormat = D3DFMT_D16;
- pres_param.EnableAutoDepthStencil = FALSE;
- pres_param.SwapEffect = D3DSWAPEFFECT_DISCARD;
- pres_param.MultiSampleType = D3DMULTISAMPLE_NONE;
- pres_param.Flags = 0;
- pres_param.FullScreen_RefreshRateInHz = 0;
- pres_param.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;//D3DPRESENT_INTERVAL_ONE;//D3DPRESENT_INTERVAL_IMMEDIATE;//m_current_mode.allow_page_tearing ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;//D3DPRESENT_INTERVAL_IMMEDIATE;//D3DPRESENT_INTERVAL_ONE;
- //pres_param.FullScreen_PresentationInterval = 0;
- pres_param.Windowed = TRUE;
- HRESULT hr;
- if (D3D_OK != (hr = m_vjd3d9->CreateDevice(ordinal_adapter,//D3DADAPTER_DEFAULT,
- D3DDEVTYPE_HAL,
- m_hTextWnd,
- D3DCREATE_SOFTWARE_VERTEXPROCESSING,
- &pres_param,
- &m_vjd3d9_device)))
- {
- m_vjd3d9_device = NULL;
- MessageBoxW(m_lpDX->GetHwnd(), WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_D3D_DEVICE_FOR_VJ_MODE),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- if (!AllocateFonts(m_vjd3d9_device))
- return false;
- if (m_fix_slow_text) // note that when not doing vj mode, m_lpDDSText is allocated in AllocateDX9Stuff
- AllocateTextSurface();
- m_text.Finish();
- m_text.Init(m_vjd3d9_device, m_lpDDSText, 0);
- m_bClearVJWindow = true;
- }
- return true;
- }
- void CPluginShell::CleanUpVJStuff()
- {
- // ALWAYS set the textures to NULL before releasing textures,
- // otherwise they might still have a hanging reference!
- if (m_lpDX && m_lpDX->m_lpDevice)
- {
- for (int i=0; i<16; i++)
- m_lpDX->m_lpDevice->SetTexture(i, NULL);
- }
- if (m_vjd3d9_device)
- {
- for (int i=0; i<16; i++)
- m_vjd3d9_device->SetTexture(i, NULL);
- }
- if (!m_vj_mode)
- return;
- // clean up VJ mode
- {
- CleanUpFonts();
- SafeRelease(m_lpDDSText);
- SafeRelease(m_vjd3d9_device);
- SafeRelease(m_vjd3d9);
- if (m_hTextWnd)
- {
- //dumpmsg("Finish: destroying text window");
- DestroyWindow(m_hTextWnd);
- m_hTextWnd = NULL;
- //dumpmsg("Finish: text window destroyed");
- }
- if (m_bTextWindowClassRegistered)
- {
- //dumpmsg("Finish: unregistering text window class");
- UnregisterClass(TEXT_WINDOW_CLASSNAME,GetInstance()); // unregister window class
- m_bTextWindowClassRegistered = false;
- //dumpmsg("Finish: text window class unregistered");
- }
- }
- }
- int CPluginShell::AllocateFonts(IDirect3DDevice9* pDevice)
- {
- // Create D3DX system font:
- for (int i=0; i<NUM_BASIC_FONTS + NUM_EXTRA_FONTS; i++)
- if (pCreateFontW(pDevice, //m_font[i],
- m_fontinfo[i].nSize,
- m_fontinfo[i].nSize*4/10,
- m_fontinfo[i].bBold ? 900 : 400,
- 1, // mip levels
- m_fontinfo[i].bItalic,
- DEFAULT_CHARSET,
- OUT_DEFAULT_PRECIS,
- m_fontinfo[i].bAntiAliased ? ANTIALIASED_QUALITY : DEFAULT_QUALITY,
- DEFAULT_PITCH,
- m_fontinfo[i].szFace,
- &m_d3dx_font[i]
- ) != D3D_OK)
- {
- wchar_t title[64];
- MessageBoxW(m_lpDX ? m_lpDX->GetHwnd() : NULL, WASABI_API_LNGSTRINGW(IDS_ERROR_CREATING_D3DX_FONTS),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- // get actual font heights
- for (int i=0; i<NUM_BASIC_FONTS + NUM_EXTRA_FONTS; i++)
- {
- RECT r;
- SetRect(&r, 0, 0, 1024, 1024);
- int h = m_d3dx_font[i]->DrawText(NULL, "M", -1, &r, DT_CALCRECT, 0xFFFFFFFF);
- if (h>0) m_fontinfo[i].nSize = h;
- }
- return true;
- }
- void CPluginShell::CleanUpFonts()
- {
- for (int i=0; i<NUM_BASIC_FONTS + NUM_EXTRA_FONTS; i++)
- SafeRelease(m_d3dx_font[i]);
- }
- void CPluginShell::AllocateTextSurface()
- {
- IDirect3DDevice9 *pDevice = m_vjd3d9_device ? m_vjd3d9_device : GetDevice();
- int w = m_vjd3d9_device ? m_nTextWndWidth : GetWidth() ;
- int h = m_vjd3d9_device ? m_nTextWndHeight : GetHeight();
- if (D3D_OK != pCreateTexture(pDevice, w, h, 1, D3DUSAGE_RENDERTARGET, GetBackBufFormat(), D3DPOOL_DEFAULT, &m_lpDDSText))
- m_lpDDSText = NULL; // OK if there's not enough mem for it!
- else
- {
- // if m_lpDDSText doesn't cover enough of screen, cancel it.
- D3DSURFACE_DESC desc;
- if (D3D_OK == m_lpDDSText->GetLevelDesc(0, &desc))
- {
- if ((desc.Width < 256 && w >= 256) ||
- (desc.Height < 256 && h >= 256) ||
- (desc.Width /(float)w < 0.74f) ||
- (desc.Height/(float)h < 0.74f)
- )
- {
- m_lpDDSText->Release();
- m_lpDDSText = NULL;
- }
- }
- }
- }
- int CPluginShell::AllocateDX9Stuff()
- {
- if (!m_vj_mode)
- {
- AllocateFonts(m_lpDX->m_lpDevice);
- if (m_fix_slow_text) // note that when not doing vj mode, m_lpDDSText is allocated in AllocateDX9Stuff
- AllocateTextSurface();
- }
- /*
- // Create D3DX system font:
- for (int i=0; i<NUM_BASIC_FONTS + NUM_EXTRA_FONTS; i++)
- if (pCreateFontW(m_lpDX->m_lpDevice,
- m_fontinfo[i].nSize,
- m_fontinfo[i].nSize*4/10,
- m_fontinfo[i].bBold ? 900 : 400,
- 0, // mip levels
- m_fontinfo[i].bItalic,
- DEFAULT_CHARSET,
- OUT_DEFAULT_PRECIS,
- m_fontinfo[i].bAntiAliased ? ANTIALIASED_QUALITY : DEFAULT_QUALITY,
- DEFAULT_PITCH,
- m_fontinfo[i].szFace,
- &m_d3dx_font[i]
- ) != D3D_OK)
- {
- MessageBox(m_lpDX->GetHwnd(), "Error creating D3DX fonts", "ERROR", MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return false;
- }
- // get actual font heights
- for (i=0; i<NUM_BASIC_FONTS + NUM_EXTRA_FONTS; i++)
- {
- RECT r;
- SetRect(&r, 0, 0, 1024, 1024);
- int h = m_d3dx_font[i]->DrawText(NULL, "M", -1, &r, DT_CALCRECT, 0xFFFFFFFF);
- if (h>0) m_fontinfo[i].nSize = h;
- }
- */
- if (m_screenmode == DESKTOP)
- if (!InitDesktopMode())
- return false;
- int ret = AllocateMyDX9Stuff();
- // invalidate various 'caches' here:
- m_playlist_top_idx = -1; // invalidating playlist cache forces recompute of playlist width
- //m_icon_list.clear(); // clear desktop mode icon list, so it has to read the bitmaps back in
- if (!m_vj_mode)
- {
- m_text.Finish();
- m_text.Init(GetDevice(), m_lpDDSText, 1);
- }
- return ret;
- }
- void CPluginShell::CleanUpDX9Stuff(int final_cleanup)
- {
- // ALWAYS unbind the textures before releasing textures,
- // otherwise they might still have a hanging reference!
- if (m_lpDX && m_lpDX->m_lpDevice)
- {
- for (int i=0; i<16; i++)
- m_lpDX->m_lpDevice->SetTexture(i, NULL);
- }
- if (m_screenmode == DESKTOP)
- CleanUpDesktopMode();
- if (!m_vj_mode)
- {
- for (int i=0; i<NUM_BASIC_FONTS + NUM_EXTRA_FONTS; i++)
- SafeRelease(m_d3dx_font[i]);
- SafeRelease(m_lpDDSText);
- }
- CleanUpMyDX9Stuff(final_cleanup);
- }
- void CPluginShell::OnUserResizeTextWindow()
- {
- // Update window properties
- RECT w, c;
- GetWindowRect(m_hTextWnd, &w);
- GetClientRect(m_hTextWnd, &c);
- WINDOWPLACEMENT wp;
- ZeroMemory(&wp, sizeof(wp));
- wp.length = sizeof(wp);
- GetWindowPlacement(m_hTextWnd, &wp);
- // 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_hTextWnd, &p))
- {
- c.left += p.x;
- c.right += p.x;
- c.top += p.y;
- c.bottom += p.y;
- }
- if (wp.showCmd != SW_SHOWMINIMIZED)
- {
- if (m_nTextWndWidth != c.right-c.left ||
- m_nTextWndHeight != c.bottom-c.top)
- {
- CleanUpVJStuff();
- if (!InitVJStuff(&c))
- {
- SuggestHowToFreeSomeMem();
- m_lpDX->m_ready = false; // flag to exit
- return;
- }
- }
- // save the new window position:
- //if (wp.showCmd==SW_SHOWNORMAL)
- // SaveTextWindowPos();
- }
- }
- void CPluginShell::OnUserResizeWindow()
- {
- // Update window properties
- RECT w, c;
- GetWindowRect(m_lpDX->GetHwnd(), &w);
- GetClientRect(m_lpDX->GetHwnd(), &c);
- WINDOWPLACEMENT wp;
- ZeroMemory(&wp, sizeof(wp));
- wp.length = sizeof(wp);
- GetWindowPlacement(m_lpDX->GetHwnd(), &wp);
- // 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_lpDX->GetHwnd(), &p))
- {
- c.left += p.x;
- c.right += p.x;
- c.top += p.y;
- c.bottom += p.y;
- }
- if (wp.showCmd != SW_SHOWMINIMIZED)
- {
- int new_REAL_client_w = c.right-c.left;
- int new_REAL_client_h = c.bottom-c.top;
- // kiv: could we just resize when the *snapped* w/h changes? slightly more ideal...
- if (m_lpDX->m_REAL_client_width != new_REAL_client_w ||
- m_lpDX->m_REAL_client_height != new_REAL_client_h)
- {
- //CleanUpVJStuff();
- CleanUpDX9Stuff(0);
- if (!m_lpDX->OnUserResizeWindow(&w, &c))
- {
- // note: a basic warning messagebox will have already been given.
- // now suggest specific advice on how to regain more video memory:
- SuggestHowToFreeSomeMem();
- return;
- }
- if (!AllocateDX9Stuff())
- {
- m_lpDX->m_ready = false; // flag to exit
- return;
- }
- /*if (!InitVJStuff())
- {
- m_lpDX->m_ready = false; // flag to exit
- return;
- }*/
- }
- // save the new window position:
- if (wp.showCmd==SW_SHOWNORMAL)
- m_lpDX->SaveWindow();
- }
- }
- void CPluginShell::StuffParams(DXCONTEXT_PARAMS *pParams)
- {
- pParams->screenmode = m_screenmode;
- pParams->display_mode = m_disp_mode_fs;
- pParams->nbackbuf = 1;
- pParams->m_dualhead_horz = m_dualhead_horz;
- pParams->m_dualhead_vert = m_dualhead_vert;
- pParams->m_skin = (m_screenmode==WINDOWED) ? m_skin : 0;
- switch (m_screenmode)
- {
- case WINDOWED:
- pParams->allow_page_tearing = m_allow_page_tearing_w;
- pParams->adapter_guid = m_adapter_guid_windowed;
- pParams->multisamp = m_multisample_windowed;
- strcpy(pParams->adapter_devicename, m_adapter_devicename_windowed);
- break;
- case FULLSCREEN:
- case FAKE_FULLSCREEN:
- pParams->allow_page_tearing = m_allow_page_tearing_fs;
- pParams->adapter_guid = m_adapter_guid_fullscreen;
- pParams->multisamp = m_multisample_fullscreen;
- strcpy(pParams->adapter_devicename, m_adapter_devicename_fullscreen);
- break;
- case DESKTOP:
- pParams->allow_page_tearing = m_allow_page_tearing_dm;
- pParams->adapter_guid = m_adapter_guid_desktop;
- pParams->multisamp = m_multisample_desktop;
- strcpy(pParams->adapter_devicename, m_adapter_devicename_desktop);
- break;
- }
- pParams->parent_window = (m_screenmode==DESKTOP) ? m_hWndDesktopListView : NULL;
- }
- void CPluginShell::ToggleDesktop()
- {
- CleanUpDX9Stuff(0);
- switch (m_screenmode)
- {
- case WINDOWED:
- case FULLSCREEN:
- case FAKE_FULLSCREEN:
- m_screenmode = DESKTOP;
- break;
- case DESKTOP:
- m_screenmode = WINDOWED;
- break;
- }
- DXCONTEXT_PARAMS params;
- StuffParams(¶ms);
- if (!m_lpDX->StartOrRestartDevice(¶ms))
- {
- // note: a basic warning messagebox will have already been given.
- if (m_lpDX->m_lastErr == DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY)
- SuggestHowToFreeSomeMem();
- return;
- }
- if (!AllocateDX9Stuff())
- {
- m_lpDX->m_ready = false; // flag to exit
- return;
- }
- SetForegroundWindow(m_lpDX->GetHwnd());
- SetActiveWindow(m_lpDX->GetHwnd());
- SetFocus(m_lpDX->GetHwnd());
- }
- #define IPC_IS_PLAYING_VIDEO 501 // from wa_ipc.h
- #define IPC_SET_VIS_FS_FLAG 631 // a vis should send this message with 1/as param to notify winamp that it has gone to or has come back from fullscreen mode
- void CPluginShell::ToggleFullScreen()
- {
- CleanUpDX9Stuff(0);
- switch (m_screenmode)
- {
- case DESKTOP:
- case WINDOWED:
- m_screenmode = m_fake_fullscreen_mode ? FAKE_FULLSCREEN : FULLSCREEN;
- if (m_screenmode == FULLSCREEN && SendMessage(GetWinampWindow(), WM_WA_IPC, 0, IPC_IS_PLAYING_VIDEO) > 1)
- {
- m_screenmode = FAKE_FULLSCREEN;
- }
- SendMessage(GetWinampWindow(), WM_WA_IPC, 1, IPC_SET_VIS_FS_FLAG);
- break;
- case FULLSCREEN:
- case FAKE_FULLSCREEN:
- m_screenmode = WINDOWED;
- SendMessage(GetWinampWindow(), WM_WA_IPC, 0, IPC_SET_VIS_FS_FLAG);
- break;
- }
- DXCONTEXT_PARAMS params;
- StuffParams(¶ms);
- if (!m_lpDX->StartOrRestartDevice(¶ms))
- {
- // note: a basic warning messagebox will have already been given.
- if (m_lpDX->m_lastErr == DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY)
- SuggestHowToFreeSomeMem();
- return;
- }
- if (!AllocateDX9Stuff())
- {
- m_lpDX->m_ready = false; // flag to exit
- return;
- }
- SetForegroundWindow(m_lpDX->GetHwnd());
- SetActiveWindow(m_lpDX->GetHwnd());
- SetFocus(m_lpDX->GetHwnd());
- }
- void CPluginShell::ToggleHelp()
- {
- m_show_help = 1-m_show_help;
- int ret = CheckMenuItem(m_context_menu, ID_SHOWHELP, MF_BYCOMMAND | (m_show_help ? MF_CHECKED : MF_UNCHECKED));
- }
- void CPluginShell::TogglePlaylist()
- {
- m_show_playlist = 1-m_show_playlist;
- m_playlist_top_idx = -1; // <- invalidates playlist cache
- int ret = CheckMenuItem(m_context_menu, ID_SHOWPLAYLIST, MF_BYCOMMAND | (m_show_playlist ? MF_CHECKED : MF_UNCHECKED));
- }
- int CPluginShell::InitDirectX()
- {
- m_lpDX = new DXContext(m_hWndWinamp,m_hInstance,CLASSNAME,WINDOWCAPTION,CPluginShell::WindowProc,(LONG_PTR)this, m_minimize_winamp, m_szConfigIniFile);
- if (!m_lpDX)
- {
- wchar_t title[64];
- MessageBoxW(NULL, WASABI_API_LNGSTRINGW(IDS_UNABLE_TO_INIT_DXCONTEXT),
- WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
- MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- return FALSE;
- }
- if (m_lpDX->m_lastErr != S_OK)
- {
- // warning messagebox will have already been given
- delete m_lpDX;
- return FALSE;
- }
- // initialize graphics
- DXCONTEXT_PARAMS params;
- StuffParams(¶ms);
- if (!m_lpDX->StartOrRestartDevice(¶ms))
- {
- // note: a basic warning messagebox will have already been given.
- if (m_lpDX->m_lastErr == DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY)
- {
- // suggest specific advice on how to regain more video memory:
- SuggestHowToFreeSomeMem();
- }
- delete m_lpDX;
- m_lpDX = NULL;
- return FALSE;
- }
- return TRUE;
- }
- void CPluginShell::CleanUpDirectX()
- {
- SafeDelete(m_lpDX);
- }
- int CPluginShell::PluginPreInitialize(HWND hWinampWnd, HINSTANCE hWinampInstance)
- {
- // PROTECTED CONFIG PANEL SETTINGS (also see 'private' settings, below)
- m_start_fullscreen = 0;
- m_start_desktop = 0;
- m_fake_fullscreen_mode = 0;
- m_max_fps_fs = 30;
- m_max_fps_dm = 30;
- m_max_fps_w = 30;
- m_show_press_f1_msg = 1;
- m_allow_page_tearing_w = 1;
- m_allow_page_tearing_fs = 0;
- m_allow_page_tearing_dm = 0;
- m_minimize_winamp = 1;
- m_desktop_show_icons = 1;
- m_desktop_textlabel_boxes = 1;
- m_desktop_manual_icon_scoot = 0;
- m_desktop_555_fix = 2;
- m_dualhead_horz = 2;
- m_dualhead_vert = 1;
- m_save_cpu = 1;
- m_skin = 1;
- m_fix_slow_text = 0;
- // initialize font settings:
- wcscpy(m_fontinfo[SIMPLE_FONT ].szFace, SIMPLE_FONT_DEFAULT_FACE);
- m_fontinfo[SIMPLE_FONT ].nSize = SIMPLE_FONT_DEFAULT_SIZE ;
- m_fontinfo[SIMPLE_FONT ].bBold = SIMPLE_FONT_DEFAULT_BOLD ;
- m_fontinfo[SIMPLE_FONT ].bItalic = SIMPLE_FONT_DEFAULT_ITAL ;
- m_fontinfo[SIMPLE_FONT ].bAntiAliased = SIMPLE_FONT_DEFAULT_AA ;
- wcscpy(m_fontinfo[DECORATIVE_FONT].szFace, DECORATIVE_FONT_DEFAULT_FACE);
- m_fontinfo[DECORATIVE_FONT].nSize = DECORATIVE_FONT_DEFAULT_SIZE;
- m_fontinfo[DECORATIVE_FONT].bBold = DECORATIVE_FONT_DEFAULT_BOLD;
- m_fontinfo[DECORATIVE_FONT].bItalic = DECORATIVE_FONT_DEFAULT_ITAL;
- m_fontinfo[DECORATIVE_FONT].bAntiAliased = DECORATIVE_FONT_DEFAULT_AA ;
- wcscpy(m_fontinfo[HELPSCREEN_FONT].szFace, HELPSCREEN_FONT_DEFAULT_FACE);
- m_fontinfo[HELPSCREEN_FONT].nSize = HELPSCREEN_FONT_DEFAULT_SIZE;
- m_fontinfo[HELPSCREEN_FONT].bBold = HELPSCREEN_FONT_DEFAULT_BOLD;
- m_fontinfo[HELPSCREEN_FONT].bItalic = HELPSCREEN_FONT_DEFAULT_ITAL;
- m_fontinfo[HELPSCREEN_FONT].bAntiAliased = HELPSCREEN_FONT_DEFAULT_AA ;
- wcscpy(m_fontinfo[PLAYLIST_FONT ].szFace, PLAYLIST_FONT_DEFAULT_FACE);
- m_fontinfo[PLAYLIST_FONT ].nSize = PLAYLIST_FONT_DEFAULT_SIZE;
- m_fontinfo[PLAYLIST_FONT ].bBold = PLAYLIST_FONT_DEFAULT_BOLD;
- m_fontinfo[PLAYLIST_FONT ].bItalic = PLAYLIST_FONT_DEFAULT_ITAL;
- m_fontinfo[PLAYLIST_FONT ].bAntiAliased = PLAYLIST_FONT_DEFAULT_AA ;
- #if (NUM_EXTRA_FONTS >= 1)
- wcscpy(m_fontinfo[NUM_BASIC_FONTS + 0].szFace, EXTRA_FONT_1_DEFAULT_FACE);
- m_fontinfo[NUM_BASIC_FONTS + 0].nSize = EXTRA_FONT_1_DEFAULT_SIZE;
- m_fontinfo[NUM_BASIC_FONTS + 0].bBold = EXTRA_FONT_1_DEFAULT_BOLD;
- m_fontinfo[NUM_BASIC_FONTS + 0].bItalic = EXTRA_FONT_1_DEFAULT_ITAL;
- m_fontinfo[NUM_BASIC_FONTS + 0].bAntiAliased = EXTRA_FONT_1_DEFAULT_AA;
- #endif
- #if (NUM_EXTRA_FONTS >= 2)
- wcscpy(m_fontinfo[NUM_BASIC_FONTS + 1].szFace, EXTRA_FONT_2_DEFAULT_FACE);
- m_fontinfo[NUM_BASIC_FONTS + 1].nSize = EXTRA_FONT_2_DEFAULT_SIZE;
- m_fontinfo[NUM_BASIC_FONTS + 1].bBold = EXTRA_FONT_2_DEFAULT_BOLD;
- m_fontinfo[NUM_BASIC_FONTS + 1].bItalic = EXTRA_FONT_2_DEFAULT_ITAL;
- m_fontinfo[NUM_BASIC_FONTS + 1].bAntiAliased = EXTRA_FONT_2_DEFAULT_AA;
- #endif
- #if (NUM_EXTRA_FONTS >= 3)
- strcpy(m_fontinfo[NUM_BASIC_FONTS + 2].szFace, EXTRA_FONT_3_DEFAULT_FACE);
- m_fontinfo[NUM_BASIC_FONTS + 2].nSize = EXTRA_FONT_3_DEFAULT_SIZE;
- m_fontinfo[NUM_BASIC_FONTS + 2].bBold = EXTRA_FONT_3_DEFAULT_BOLD;
- m_fontinfo[NUM_BASIC_FONTS + 2].bItalic = EXTRA_FONT_3_DEFAULT_ITAL;
- m_fontinfo[NUM_BASIC_FONTS + 2].bAntiAliased = EXTRA_FONT_3_DEFAULT_AA;
- #endif
- #if (NUM_EXTRA_FONTS >= 4)
- strcpy(m_fontinfo[NUM_BASIC_FONTS + 3].szFace, EXTRA_FONT_4_DEFAULT_FACE);
- m_fontinfo[NUM_BASIC_FONTS + 3].nSize = EXTRA_FONT_4_DEFAULT_SIZE;
- m_fontinfo[NUM_BASIC_FONTS + 3].bBold = EXTRA_FONT_4_DEFAULT_BOLD;
- m_fontinfo[NUM_BASIC_FONTS + 3].bItalic = EXTRA_FONT_4_DEFAULT_ITAL;
- m_fontinfo[NUM_BASIC_FONTS + 3].bAntiAliased = EXTRA_FONT_4_DEFAULT_AA;
- #endif
- #if (NUM_EXTRA_FONTS >= 5)
- strcpy(m_fontinfo[NUM_BASIC_FONTS + 4].szFace, EXTRA_FONT_5_DEFAULT_FACE);
- m_fontinfo[NUM_BASIC_FONTS + 4].nSize = EXTRA_FONT_5_DEFAULT_SIZE;
- m_fontinfo[NUM_BASIC_FONTS + 4].bBold = EXTRA_FONT_5_DEFAULT_BOLD;
- m_fontinfo[NUM_BASIC_FONTS + 4].bItalic = EXTRA_FONT_5_DEFAULT_ITAL;
- m_fontinfo[NUM_BASIC_FONTS + 4].bAntiAliased = EXTRA_FONT_5_DEFAULT_AA;
- #endif
- m_disp_mode_fs.Width = DEFAULT_FULLSCREEN_WIDTH;
- m_disp_mode_fs.Height = DEFAULT_FULLSCREEN_HEIGHT;
- m_disp_mode_fs.Format = D3DFMT_UNKNOWN;
- m_disp_mode_fs.RefreshRate = 60;
- // better yet - in case there is no config INI file saved yet, use the current display mode (if detectable) as the default fullscreen res:
- DEVMODE dm;
- dm.dmSize = sizeof(dm);
- dm.dmDriverExtra = 0;
- if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
- {
- m_disp_mode_fs.Width = dm.dmPelsWidth;
- m_disp_mode_fs.Height = dm.dmPelsHeight;
- m_disp_mode_fs.RefreshRate = dm.dmDisplayFrequency;
- m_disp_mode_fs.Format = (dm.dmBitsPerPel==16) ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
- }
- // PROTECTED STRUCTURES/POINTERS
- int i = 0;
- for (int i=0; i<NUM_BASIC_FONTS + NUM_EXTRA_FONTS; i++)
- m_d3dx_font[i] = NULL;
- m_d3dx_desktop_font = NULL;
- m_lpDDSText = NULL;
- ZeroMemory(&m_sound, sizeof(td_soundinfo));
- for (int ch=0; ch<2; ch++)
- for (i=0; i<3; i++)
- {
- m_sound.infinite_avg[ch][i] = m_sound.avg[ch][i] = m_sound.med_avg[ch][i] = m_sound.long_avg[ch][i] = 1.0f;
- }
- // GENERAL PRIVATE STUFF
- //m_screenmode: set at end (derived setting)
- m_frame = 0;
- m_time = 0;
- m_fps = 30;
- m_hWndWinamp = hWinampWnd;
- m_hInstance = hWinampInstance;
- m_lpDX = NULL;
- m_szPluginsDirPath[0] = 0; // will be set further down
- m_szConfigIniFile[0] = 0; // will be set further down
- // m_szPluginsDirPath:
- wchar_t *p;
- if (hWinampWnd
- && (p = (wchar_t *)SendMessage(hWinampWnd, WM_WA_IPC, 0, IPC_GETPLUGINDIRECTORYW))
- && p != (wchar_t *)1)
- {
- swprintf(m_szPluginsDirPath, L"%s\\", p);
- }
- else
- {
- // get path to INI file & read in prefs/settings right away, so DumpMsg works!
- GetModuleFileNameW(m_hInstance, m_szPluginsDirPath, MAX_PATH);
- wchar_t *p = m_szPluginsDirPath + wcslen(m_szPluginsDirPath);
- while (p >= m_szPluginsDirPath && *p != L'\\') p--;
- if (++p >= m_szPluginsDirPath) *p = 0;
- }
- if (hWinampWnd
- && (p = (wchar_t *)SendMessage(hWinampWnd, WM_WA_IPC, 0, IPC_GETINIDIRECTORYW))
- && p != (wchar_t *)1)
- {
- // load settings as well as coping with moving old settings to a contained folder
- wchar_t m_szOldConfigIniFile[MAX_PATH] = {0}, temp[MAX_PATH] = {0}, temp2[MAX_PATH] = {0};
- swprintf(m_szOldConfigIniFile, L"%s\\Plugins\\%s", p, INIFILE);
- swprintf(m_szConfigIniFile, L"%s\\Plugins\\%s%s", p, SUBDIR, INIFILE);
- swprintf(temp, L"%s\\Plugins\\%s", p, SUBDIR);
- swprintf(temp2, L"%s\\Plugins\\", p);
- CreateDirectoryW(temp, NULL);
- if (PathFileExistsW(m_szOldConfigIniFile) && !PathFileExistsW(m_szConfigIniFile))
- {
- MoveFileW(m_szOldConfigIniFile, m_szConfigIniFile);
- wchar_t m_szMsgIniFile[MAX_PATH] = {0}, m_szNewMsgIniFile[MAX_PATH] = {0},
- m_szImgIniFile[MAX_PATH] = {0}, m_szNewImgIniFile[MAX_PATH] = {0},
- m_szAdaptersFile[MAX_PATH] = {0}, m_szNewAdaptersFile[MAX_PATH] = {0};
- swprintf(m_szMsgIniFile, L"%s%s", temp2, MSG_INIFILE);
- swprintf(m_szNewMsgIniFile, L"%s%s", temp, MSG_INIFILE);
- swprintf(m_szImgIniFile, L"%s%s", temp2, IMG_INIFILE);
- swprintf(m_szNewImgIniFile, L"%s%s", temp, IMG_INIFILE);
- swprintf(m_szAdaptersFile, L"%s%s", temp2, ADAPTERSFILE);
- swprintf(m_szNewAdaptersFile, L"%s%s", temp, ADAPTERSFILE);
- MoveFileW(m_szImgIniFile, m_szNewImgIniFile);
- MoveFileW(m_szMsgIniFile, m_szNewMsgIniFile);
- MoveFileW(m_szAdaptersFile, m_szNewAdaptersFile);
- }
- }
- else
- {
- swprintf(m_szConfigIniFile, L"%s%s", m_szPluginsDirPath, INIFILE);
- }
- lstrcpyn(m_szConfigIniFileA,AutoCharFn(m_szConfigIniFile),MAX_PATH);
- // PRIVATE CONFIG PANEL SETTINGS
- m_multisample_fullscreen = D3DMULTISAMPLE_NONE;
- m_multisample_desktop = D3DMULTISAMPLE_NONE;
- m_multisample_windowed = D3DMULTISAMPLE_NONE;
- ZeroMemory(&m_adapter_guid_fullscreen, sizeof(GUID));
- ZeroMemory(&m_adapter_guid_desktop , sizeof(GUID));
- ZeroMemory(&m_adapter_guid_windowed , sizeof(GUID));
- m_adapter_devicename_windowed[0] = 0;
- m_adapter_devicename_fullscreen[0] = 0;
- m_adapter_devicename_desktop[0] = 0;
- // PRIVATE RUNTIME SETTINGS
- m_lost_focus = 0;
- m_hidden = 0;
- m_resizing = 0;
- m_show_help = 0;
- m_show_playlist = 0;
- m_playlist_pos = 0;
- m_playlist_pageups = 0;
- m_playlist_top_idx = -1;
- m_playlist_btm_idx = -1;
- // m_playlist_width_pixels will be considered invalid whenever 'm_playlist_top_idx' is -1.
- // m_playlist[256][256] will be considered invalid whenever 'm_playlist_top_idx' is -1.
- m_exiting = 0;
- m_upper_left_corner_y = 0;
- m_lower_left_corner_y = 0;
- m_upper_right_corner_y = 0;
- m_lower_right_corner_y = 0;
- m_left_edge = 0;
- m_right_edge = 0;
- m_force_accept_WM_WINDOWPOSCHANGING = 0;
- // PRIVATE - GDI STUFF
- m_main_menu = NULL;
- m_context_menu = NULL;
- for (i=0; i<NUM_BASIC_FONTS + NUM_EXTRA_FONTS; i++)
- m_font[i] = NULL;
- m_font_desktop = NULL;
- // PRIVATE - DESKTOP MODE STUFF
- m_icon_list.clear();
- for (i=0; i<MAX_ICON_TEXTURES; i++)
- m_desktop_icons_texture[i] = NULL;
- FindDesktopWindows(&m_hWndProgMan, &m_hWndDesktop, &m_hWndDesktopListView);
- GetDesktopFolder(m_szDesktopFolder);
- m_desktop_icon_size = 32;
- m_desktop_dragging = 0; // '1' when user is dragging icons around
- m_desktop_box = 0; // '1' when user is drawing a box
- m_desktop_wc_registered = 0;
- m_desktop_bk_color = 0xFF000000 | BGR2RGB(::GetSysColor(COLOR_BACKGROUND));
- m_desktop_text_color = 0xFF000000 | BGR2RGB(SendMessage(m_hWndDesktopListView, LVM_GETTEXTCOLOR, 0, 0));
- m_desktop_sel_color = 0xFF000000 | BGR2RGB(::GetSysColor(COLOR_HIGHLIGHT));
- m_desktop_sel_text_color = 0xFF000000 | BGR2RGB(::GetSysColor(COLOR_HIGHLIGHTTEXT));
- m_desktop_icon_state = 0;
- m_desktop_icon_count = 0;
- m_desktop_icon_update_frame = 0;
- m_desktop_icons_disabled = 0;
- m_vms_desktop_loaded = 0;
- m_desktop_hook_set = 0;
- // PRIVATE - MORE TIMEKEEPING
- m_last_raw_time = 0;
- memset(m_time_hist, 0, sizeof(m_time_hist));
- m_time_hist_pos = 0;
- if (!QueryPerformanceFrequency(&m_high_perf_timer_freq))
- m_high_perf_timer_freq.QuadPart = 0;
- m_prev_end_of_frame.QuadPart = 0;
- // PRIVATE AUDIO PROCESSING DATA
- //(m_fftobj needs no init)
- memset(m_oldwave[0], 0, sizeof(float)*576);
- memset(m_oldwave[1], 0, sizeof(float)*576);
- m_prev_align_offset[0] = 0;
- m_prev_align_offset[1] = 0;
- m_align_weights_ready = 0;
- // SEPARATE TEXT WINDOW (FOR VJ MODE)
- m_vj_mode = 0;
- m_hidden_textwnd = 0;
- m_resizing_textwnd = 0;
- m_hTextWnd = NULL;
- m_nTextWndWidth = 0;
- m_nTextWndHeight = 0;
- m_bTextWindowClassRegistered = false;
- m_vjd3d9 = NULL;
- m_vjd3d9_device = NULL;
- //-----
- m_screenmode = NOT_YET_KNOWN;
- OverrideDefaults();
- ReadConfig();
- if (m_start_fullscreen)
- {
- m_screenmode = m_fake_fullscreen_mode ? FAKE_FULLSCREEN : FULLSCREEN;
- if (m_screenmode == FULLSCREEN && SendMessage(GetWinampWindow(), WM_WA_IPC, 0, IPC_IS_PLAYING_VIDEO) > 1)
- {
- m_screenmode = FAKE_FULLSCREEN;
- }
- }
- else if (m_start_desktop)
- m_screenmode = DESKTOP;
- else
- m_screenmode = WINDOWED;
- MyPreInitialize();
- MyReadConfig();
- //-----
- return TRUE;
- }
- int CPluginShell::PluginInitialize()
- {
- // note: initialize GDI before DirectX. Also separate them because
- // when we change windowed<->fullscreen, or lose the device and restore it,
- // we don't want to mess with any (persistent) GDI stuff.
- if (!InitDirectX()) return FALSE; // gives its own error messages
- if (!InitNondx9Stuff()) return FALSE; // gives its own error messages
- if (!AllocateDX9Stuff()) return FALSE; // gives its own error messages
- if (!InitVJStuff()) return FALSE;
- return TRUE;
- }
- void CPluginShell::PluginQuit()
- {
- CleanUpVJStuff();
- CleanUpDX9Stuff(1);
- CleanUpNondx9Stuff();
- CleanUpDirectX();
- SetFocus(m_hWndWinamp);
- SetActiveWindow(m_hWndWinamp);
- SetForegroundWindow(m_hWndWinamp);
- }
- wchar_t* BuildSettingName(wchar_t* name, int number){
- static wchar_t temp[64];
- swprintf(temp, L"%s%d", name, number);
- return temp;
- }
- void CPluginShell::READ_FONT(int n){
- GetPrivateProfileStringW(L"settings",BuildSettingName(L"szFontFace",n),m_fontinfo[n].szFace,m_fontinfo[n].szFace,sizeof(m_fontinfo[n].szFace), m_szConfigIniFile);
- m_fontinfo[n].nSize = GetPrivateProfileIntW(L"settings",BuildSettingName(L"nFontSize",n),m_fontinfo[n].nSize ,m_szConfigIniFile);
- m_fontinfo[n].bBold = GetPrivateProfileIntW(L"settings",BuildSettingName(L"bFontBold",n),m_fontinfo[n].bBold ,m_szConfigIniFile);
- m_fontinfo[n].bItalic = GetPrivateProfileIntW(L"settings",BuildSettingName(L"bFontItalic",n),m_fontinfo[n].bItalic,m_szConfigIniFile);
- m_fontinfo[n].bAntiAliased = GetPrivateProfileIntW(L"settings",BuildSettingName(L"bFontAA",n),m_fontinfo[n].bItalic,m_szConfigIniFile);
- }
- void CPluginShell::ReadConfig()
- {
- int old_ver = GetPrivateProfileIntW(L"settings",L"version" ,-1,m_szConfigIniFile);
- int old_subver = GetPrivateProfileIntW(L"settings",L"subversion",-1,m_szConfigIniFile);
- // nuke old settings from prev. version:
- if (old_ver < INT_VERSION)
- return;
- else if (old_subver < INT_SUBVERSION)
- return;
- //D3DMULTISAMPLE_TYPE m_multisample_fullscreen;
- //D3DMULTISAMPLE_TYPE m_multisample_desktop;
- //D3DMULTISAMPLE_TYPE m_multisample_windowed;
- m_multisample_fullscreen = (D3DMULTISAMPLE_TYPE)GetPrivateProfileIntW(L"settings",L"multisample_fullscreen",m_multisample_fullscreen,m_szConfigIniFile);
- m_multisample_desktop = (D3DMULTISAMPLE_TYPE)GetPrivateProfileIntW(L"settings",L"multisample_desktop",m_multisample_desktop,m_szConfigIniFile);
- m_multisample_windowed = (D3DMULTISAMPLE_TYPE)GetPrivateProfileIntW(L"settings",L"multisample_windowed" ,m_multisample_windowed ,m_szConfigIniFile);
- //GUID m_adapter_guid_fullscreen
- //GUID m_adapter_guid_desktop
- //GUID m_adapter_guid_windowed
- char str[256];
- GetPrivateProfileString("settings","adapter_guid_fullscreen","",str,sizeof(str)-1,m_szConfigIniFileA);
- TextToGuid(str, &m_adapter_guid_fullscreen);
- GetPrivateProfileString("settings","adapter_guid_desktop","",str,sizeof(str)-1,m_szConfigIniFileA);
- TextToGuid(str, &m_adapter_guid_desktop);
- GetPrivateProfileString("settings","adapter_guid_windowed","",str,sizeof(str)-1,m_szConfigIniFileA);
- TextToGuid(str, &m_adapter_guid_windowed);
- GetPrivateProfileString("settings","adapter_devicename_fullscreen","",m_adapter_devicename_fullscreen,sizeof(m_adapter_devicename_fullscreen)-1,m_szConfigIniFileA);
- GetPrivateProfileString("settings","adapter_devicename_desktop", "",m_adapter_devicename_desktop ,sizeof(m_adapter_devicename_desktop)-1,m_szConfigIniFileA);
- GetPrivateProfileString("settings","adapter_devicename_windowed", "",m_adapter_devicename_windowed ,sizeof(m_adapter_devicename_windowed)-1,m_szConfigIniFileA);
- // FONTS
- READ_FONT(0);
- READ_FONT(1);
- READ_FONT(2);
- READ_FONT(3);
- #if (NUM_EXTRA_FONTS >= 1)
- READ_FONT(4);
- #endif
- #if (NUM_EXTRA_FONTS >= 2)
- READ_FONT(5);
- #endif
- #if (NUM_EXTRA_FONTS >= 3)
- READ_FONT(6);
- #endif
- #if (NUM_EXTRA_FONTS >= 4)
- READ_FONT(7);
- #endif
- #if (NUM_EXTRA_FONTS >= 5)
- READ_FONT(8);
- #endif
- m_start_fullscreen = GetPrivateProfileIntW(L"settings",L"start_fullscreen",m_start_fullscreen,m_szConfigIniFile);
- m_start_desktop = GetPrivateProfileIntW(L"settings",L"start_desktop" ,m_start_desktop ,m_szConfigIniFile);
- m_fake_fullscreen_mode = GetPrivateProfileIntW(L"settings",L"fake_fullscreen_mode",m_fake_fullscreen_mode,m_szConfigIniFile);
- m_max_fps_fs = GetPrivateProfileIntW(L"settings",L"max_fps_fs",m_max_fps_fs,m_szConfigIniFile);
- m_max_fps_dm = GetPrivateProfileIntW(L"settings",L"max_fps_dm",m_max_fps_dm,m_szConfigIniFile);
- m_max_fps_w = GetPrivateProfileIntW(L"settings",L"max_fps_w" ,m_max_fps_w ,m_szConfigIniFile);
- m_show_press_f1_msg = GetPrivateProfileIntW(L"settings",L"show_press_f1_msg",m_show_press_f1_msg,m_szConfigIniFile);
- m_allow_page_tearing_w = GetPrivateProfileIntW(L"settings",L"allow_page_tearing_w",m_allow_page_tearing_w,m_szConfigIniFile);
- m_allow_page_tearing_fs= GetPrivateProfileIntW(L"settings",L"allow_page_tearing_fs",m_allow_page_tearing_fs,m_szConfigIniFile);
- m_allow_page_tearing_dm= GetPrivateProfileIntW(L"settings",L"allow_page_tearing_dm",m_allow_page_tearing_dm,m_szConfigIniFile);
- m_minimize_winamp = GetPrivateProfileIntW(L"settings",L"minimize_winamp",m_minimize_winamp,m_szConfigIniFile);
- m_desktop_show_icons = GetPrivateProfileIntW(L"settings",L"desktop_show_icons",m_desktop_show_icons,m_szConfigIniFile);
- m_desktop_textlabel_boxes = GetPrivateProfileIntW(L"settings",L"desktop_textlabel_boxes",m_desktop_textlabel_boxes,m_szConfigIniFile);
- m_desktop_manual_icon_scoot = GetPrivateProfileIntW(L"settings",L"desktop_manual_icon_scoot",m_desktop_manual_icon_scoot,m_szConfigIniFile);
- m_desktop_555_fix = GetPrivateProfileIntW(L"settings",L"desktop_555_fix",m_desktop_555_fix,m_szConfigIniFile);
- m_dualhead_horz = GetPrivateProfileIntW(L"settings",L"dualhead_horz",m_dualhead_horz,m_szConfigIniFile);
- m_dualhead_vert = GetPrivateProfileIntW(L"settings",L"dualhead_vert",m_dualhead_vert,m_szConfigIniFile);
- m_save_cpu = GetPrivateProfileIntW(L"settings",L"save_cpu",m_save_cpu,m_szConfigIniFile);
- m_skin = GetPrivateProfileIntW(L"settings",L"skin",m_skin,m_szConfigIniFile);
- m_fix_slow_text = GetPrivateProfileIntW(L"settings",L"fix_slow_text",m_fix_slow_text,m_szConfigIniFile);
- m_vj_mode = GetPrivateProfileBoolW(L"settings",L"vj_mode",m_vj_mode,m_szConfigIniFile);
- //D3DDISPLAYMODE m_fs_disp_mode
- m_disp_mode_fs.Width = GetPrivateProfileIntW(L"settings",L"disp_mode_fs_w", m_disp_mode_fs.Width ,m_szConfigIniFile);
- m_disp_mode_fs.Height = GetPrivateProfileIntW(L"settings",L"disp_mode_fs_h",m_disp_mode_fs.Height ,m_szConfigIniFile);
- m_disp_mode_fs.RefreshRate = GetPrivateProfileIntW(L"settings",L"disp_mode_fs_r",m_disp_mode_fs.RefreshRate,m_szConfigIniFile);
- m_disp_mode_fs.Format = (D3DFORMAT)GetPrivateProfileIntW(L"settings",L"disp_mode_fs_f",m_disp_mode_fs.Format ,m_szConfigIniFile);
- // note: we don't call MyReadConfig() yet, because we
- // want to completely finish CPluginShell's preinit (and ReadConfig)
- // before calling CPlugin's preinit and ReadConfig.
- }
- void CPluginShell::WRITE_FONT(int n){
- WritePrivateProfileStringW(L"settings",BuildSettingName(L"szFontFace",n),m_fontinfo[n].szFace,m_szConfigIniFile);
- WritePrivateProfileIntW(m_fontinfo[n].bBold, BuildSettingName(L"bFontBold",n), m_szConfigIniFile, L"settings");
- WritePrivateProfileIntW(m_fontinfo[n].bItalic,BuildSettingName(L"bFontItalic",n), m_szConfigIniFile, L"settings");
- WritePrivateProfileIntW(m_fontinfo[n].nSize, BuildSettingName(L"nFontSize",n), m_szConfigIniFile, L"settings");
- WritePrivateProfileIntW(m_fontinfo[n].bAntiAliased, BuildSettingName(L"bFontAA",n),m_szConfigIniFile, L"settings");
- }
- void CPluginShell::WriteConfig()
- {
- //D3DMULTISAMPLE_TYPE m_multisample_fullscreen;
- //D3DMULTISAMPLE_TYPE m_multisample_desktop;
- //D3DMULTISAMPLE_TYPE m_multisample_windowed;
- WritePrivateProfileIntW((int)m_multisample_fullscreen,L"multisample_fullscreen",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW((int)m_multisample_desktop ,L"multisample_desktop" ,m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW((int)m_multisample_windowed ,L"multisample_windowed" ,m_szConfigIniFile,L"settings");
- //GUID m_adapter_guid_fullscreen
- //GUID m_adapter_guid_desktop
- //GUID m_adapter_guid_windowed
- char str[256];
- GuidToText(&m_adapter_guid_fullscreen, str, sizeof(str));
- WritePrivateProfileString("settings","adapter_guid_fullscreen",str,m_szConfigIniFileA);
- GuidToText(&m_adapter_guid_desktop, str, sizeof(str));
- WritePrivateProfileString("settings","adapter_guid_desktop",str,m_szConfigIniFileA);
- GuidToText(&m_adapter_guid_windowed, str, sizeof(str));
- WritePrivateProfileString("settings","adapter_guid_windowed" ,str,m_szConfigIniFileA);
- WritePrivateProfileString("settings","adapter_devicename_fullscreen",m_adapter_devicename_fullscreen,m_szConfigIniFileA);
- WritePrivateProfileString("settings","adapter_devicename_desktop" ,m_adapter_devicename_desktop ,m_szConfigIniFileA);
- WritePrivateProfileString("settings","adapter_devicename_windowed" ,m_adapter_devicename_windowed ,m_szConfigIniFileA);
- // FONTS
- WRITE_FONT(0);
- WRITE_FONT(1);
- WRITE_FONT(2);
- WRITE_FONT(3);
- #if (NUM_EXTRA_FONTS >= 1)
- WRITE_FONT(4);
- #endif
- #if (NUM_EXTRA_FONTS >= 2)
- WRITE_FONT(5);
- #endif
- #if (NUM_EXTRA_FONTS >= 3)
- WRITE_FONT(6);
- #endif
- #if (NUM_EXTRA_FONTS >= 4)
- WRITE_FONT(7);
- #endif
- #if (NUM_EXTRA_FONTS >= 5)
- WRITE_FONT(8);
- #endif
- WritePrivateProfileIntW(m_start_fullscreen,L"start_fullscreen",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_start_desktop ,L"start_desktop" ,m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_fake_fullscreen_mode,L"fake_fullscreen_mode",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_max_fps_fs,L"max_fps_fs",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_max_fps_dm,L"max_fps_dm",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_max_fps_w ,L"max_fps_w" ,m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_show_press_f1_msg,L"show_press_f1_msg",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_allow_page_tearing_w,L"allow_page_tearing_w",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_allow_page_tearing_fs,L"allow_page_tearing_fs",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_allow_page_tearing_dm,L"allow_page_tearing_dm",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_minimize_winamp,L"minimize_winamp",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_desktop_show_icons,L"desktop_show_icons",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_desktop_textlabel_boxes,L"desktop_textlabel_boxes",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_desktop_manual_icon_scoot,L"desktop_manual_icon_scoot",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_desktop_555_fix,L"desktop_555_fix",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_dualhead_horz,L"dualhead_horz",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_dualhead_vert,L"dualhead_vert",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_save_cpu,L"save_cpu",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_skin,L"skin",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_fix_slow_text,L"fix_slow_text",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_vj_mode,L"vj_mode",m_szConfigIniFile,L"settings");
- //D3DDISPLAYMODE m_fs_disp_mode
- WritePrivateProfileIntW(m_disp_mode_fs.Width ,L"disp_mode_fs_w",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_disp_mode_fs.Height ,L"disp_mode_fs_h",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_disp_mode_fs.RefreshRate,L"disp_mode_fs_r",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(m_disp_mode_fs.Format ,L"disp_mode_fs_f",m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(INT_VERSION ,L"version" ,m_szConfigIniFile,L"settings");
- WritePrivateProfileIntW(INT_SUBVERSION ,L"subversion" ,m_szConfigIniFile,L"settings");
- // finally, save the plugin's unique settings:
- MyWriteConfig();
- }
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- int CPluginShell::PluginRender(unsigned char *pWaveL, unsigned char *pWaveR)//, unsigned char *pSpecL, unsigned char *pSpecR)
- {
- // return FALSE here to tell Winamp to terminate the plugin
- if (!m_lpDX || !m_lpDX->m_ready)
- {
- // note: 'm_ready' will go false when a device reset fatally fails
- // (for example, when user resizes window, or toggles fullscreen.)
- m_exiting = 1;
- return false; // EXIT THE PLUGIN
- }
- if (m_hTextWnd)
- m_lost_focus = ((GetFocus() != GetPluginWindow()) && (GetFocus() != m_hTextWnd));
- else
- m_lost_focus = (GetFocus() != GetPluginWindow());
- if ((m_screenmode==WINDOWED && m_hidden) ||
- (m_screenmode==FULLSCREEN && m_lost_focus) ||
- (m_screenmode==WINDOWED && m_resizing)
- )
- {
- Sleep(30);
- return true;
- }
- // test for lost device
- // (this happens when device is fullscreen & user alt-tabs away,
- // or when monitor power-saving kicks in)
- HRESULT hr = m_lpDX->m_lpDevice->TestCooperativeLevel();
- if (hr == D3DERR_DEVICENOTRESET)
- {
- // device WAS lost, and is now ready to be reset (and come back online):
- CleanUpDX9Stuff(0);
- if (m_lpDX->m_lpDevice->Reset(&m_lpDX->m_d3dpp) != D3D_OK)
- {
- // note: a basic warning messagebox will have already been given.
- // now suggest specific advice on how to regain more video memory:
- if (m_lpDX->m_lastErr == DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY)
- SuggestHowToFreeSomeMem();
- return false; // EXIT THE PLUGIN
- }
- if (!AllocateDX9Stuff())
- return false; // EXIT THE PLUGIN
- }
- else if (hr != D3D_OK)
- {
- // device is lost, and not yet ready to come back; sleep.
- Sleep(30);
- return true;
- }
- if (m_vjd3d9_device)
- {
- HRESULT hr = m_vjd3d9_device->TestCooperativeLevel();
- if (hr == D3DERR_DEVICENOTRESET)
- {
- RECT c;
- GetClientRect(m_hTextWnd, &c);
- POINT p;
- p.x = c.left;
- p.y = c.top;
- if (ClientToScreen(m_hTextWnd, &p))
- {
- c.left += p.x;
- c.right += p.x;
- c.top += p.y;
- c.bottom += p.y;
- }
- CleanUpVJStuff();
- if (!InitVJStuff(&c))
- return false; // EXIT THE PLUGIN
- }
- }
- if (m_screenmode==DESKTOP)
- {
- PushWindowToJustBeforeDesktop(GetPluginWindow());
- }
- DoTime();
- AnalyzeNewSound(pWaveL, pWaveR);
- AlignWaves();
- DrawAndDisplay(0);
- EnforceMaxFPS();
- m_frame++;
- return true;
- }
- void CPluginShell::PushWindowToJustBeforeDesktop(HWND h)
- {
- // if our window isn't already at the bottom of the Z order,
- // freshly send it to HWND_BOTTOM.
- // this usually gives us the Program Manager window:
- HWND hWndBottom = GetWindow(h, GW_HWNDLAST);
- // then, bottommost 'normal' window is usually the one just in front of it:
- if (hWndBottom == m_hWndProgMan)
- hWndBottom = GetWindow(hWndBottom, GW_HWNDPREV);
- if (hWndBottom != h)
- {
- m_force_accept_WM_WINDOWPOSCHANGING = 1;
- SetWindowPos(h, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
- m_force_accept_WM_WINDOWPOSCHANGING = 0;
- }
- /*
- HWND hDesktopBkgWnd = FindWindow("SHELLDLL_DefView", "");
- if (hDesktopBkgWnd)
- {
- HWND hWndInFrontOfIcons = GetWindow(h, GW_HWNDPREV);
- if (hWndInFrontOfIcons != h)
- {
- m_force_accept_WM_WINDOWPOSCHANGING = 1;
- SetWindowPos(hDesktopBkgWnd, h, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
- m_force_accept_WM_WINDOWPOSCHANGING = 0;
- }
- }
- */
- }
- void CPluginShell::DrawAndDisplay(int redraw)
- {
- int cx = m_vjd3d9_device ? m_nTextWndWidth : m_lpDX->m_client_width;
- int cy = m_vjd3d9_device ? m_nTextWndHeight : m_lpDX->m_client_height;
- if (m_lpDDSText)
- {
- D3DSURFACE_DESC desc;
- if (D3D_OK == m_lpDDSText->GetLevelDesc(0, &desc))
- {
- cx = min(cx, (int)desc.Width);
- cy = min(cy, (int)desc.Height);
- }
- }
- m_upper_left_corner_y = TEXT_MARGIN + GetCanvasMarginY();
- m_upper_right_corner_y = TEXT_MARGIN + GetCanvasMarginY();
- m_lower_left_corner_y = cy - TEXT_MARGIN - GetCanvasMarginY();
- m_lower_right_corner_y = cy - TEXT_MARGIN - GetCanvasMarginY();
- m_left_edge = TEXT_MARGIN + GetCanvasMarginX();
- m_right_edge = cx - TEXT_MARGIN - GetCanvasMarginX();
- /*if (m_screenmode == DESKTOP || m_screenmode == FAKE_FULLSCREEN)
- {
- // check if taskbar is above plugin window;
- // if so, scoot text & icons out of the way.
- // [...should always be true for Desktop Mode,
- // but it's like this for code simplicity.]
- int taskbar_is_above_plugin_window = 1;
- HWND h = FindWindow("Shell_TrayWnd", NULL);
- while (h) //(..shouldn't be very many windows to iterate through here)
- {
- h = GetWindow(h, GW_HWNDPREV);
- if (h == GetPluginWindow())
- {
- taskbar_is_above_plugin_window = 0;
- break;
- }
- }
- if (taskbar_is_above_plugin_window)
- {
- // respect the taskbar area; make sure the text, desktop icons, etc.
- // don't appear underneath it.
- //m_upper_left_corner_y += m_lpDX->m_monitor_work_rect.top - m_lpDX->m_monitor_rect.top;
- //m_upper_right_corner_y += m_lpDX->m_monitor_work_rect.top - m_lpDX->m_monitor_rect.top;
- //m_lower_left_corner_y -= m_lpDX->m_monitor_rect.bottom - m_lpDX->m_monitor_work_rect.bottom;
- //m_lower_right_corner_y -= m_lpDX->m_monitor_rect.bottom - m_lpDX->m_monitor_work_rect.bottom;
- //m_left_edge += m_lpDX->m_monitor_work_rect.left - m_lpDX->m_monitor_rect.left;
- //m_right_edge -= m_lpDX->m_monitor_rect.right - m_lpDX->m_monitor_work_rect.right;
- m_lpDX->UpdateMonitorWorkRect();
- m_upper_left_corner_y = max(m_upper_left_corner_y , m_lpDX->m_monitor_work_rect.top - m_lpDX->m_monitor_rect.top + TEXT_MARGIN + GetCanvasMarginY());
- m_upper_right_corner_y = max(m_upper_right_corner_y, m_lpDX->m_monitor_work_rect.top - m_lpDX->m_monitor_rect.top + TEXT_MARGIN + GetCanvasMarginY());
- m_lower_left_corner_y = min(m_lower_left_corner_y , m_lpDX->m_client_height - (m_lpDX->m_monitor_rect.bottom - m_lpDX->m_monitor_work_rect.bottom) - TEXT_MARGIN - GetCanvasMarginY());
- m_lower_right_corner_y = min(m_lower_right_corner_y, m_lpDX->m_client_height - (m_lpDX->m_monitor_rect.bottom - m_lpDX->m_monitor_work_rect.bottom) - TEXT_MARGIN - GetCanvasMarginY());
- m_left_edge = max(m_left_edge , m_lpDX->m_monitor_work_rect.left - m_lpDX->m_monitor_rect.left + TEXT_MARGIN + GetCanvasMarginX() );
- m_right_edge = min(m_right_edge, m_lpDX->m_client_width - (m_lpDX->m_monitor_rect.right - m_lpDX->m_monitor_work_rect.right) - TEXT_MARGIN + GetCanvasMarginX());
- }
- }*/
- if (D3D_OK==m_lpDX->m_lpDevice->BeginScene())
- {
- MyRenderFn(redraw);
- PrepareFor2DDrawing_B(GetDevice(), GetWidth(), GetHeight());
- RenderDesktop();
- if (!m_vjd3d9_device) // in VJ mode, this renders to different context, so do it after BeginScene() on 2nd device.
- RenderBuiltInTextMsgs(); // to m_lpDDSText?
- MyRenderUI(&m_upper_left_corner_y, &m_upper_right_corner_y, &m_lower_left_corner_y, &m_lower_right_corner_y, m_left_edge, m_right_edge);
- RenderPlaylist();
- if (!m_vjd3d9_device)
- m_text.DrawNow();
- m_lpDX->m_lpDevice->EndScene();
- }
- // VJ Mode:
- if (m_vj_mode && m_vjd3d9_device && !m_hidden_textwnd && D3D_OK==m_vjd3d9_device->BeginScene())
- {
- if (!m_lpDDSText || m_bClearVJWindow)
- m_vjd3d9_device->Clear(0, 0, D3DCLEAR_TARGET, 0xFF000000, 1.0f, 0);
- m_bClearVJWindow = false;
- // note: when using debug DX runtime, textwnd will flash red/green after frame 4, if no text is drawn on a frame!
- RenderBuiltInTextMsgs();
- PrepareFor2DDrawing_B(m_vjd3d9_device, m_nTextWndWidth, m_nTextWndHeight);
- m_text.DrawNow();
- m_vjd3d9_device->EndScene();
- }
- if (m_screenmode == DESKTOP)
- {
- // window is hidden after creation, until 1st frame is ready to go;
- // now that it's ready, we show it.
- // see dxcontext::Internal_Init()'s call to SetWindowPos() for the DESKTOP case.
- if (!IsWindowVisible(GetPluginWindow()))
- ShowWindow(GetPluginWindow(), SW_SHOWNORMAL);
- }
- if (m_screenmode == WINDOWED && (m_lpDX->m_client_width != m_lpDX->m_REAL_client_width || m_lpDX->m_client_height != m_lpDX->m_REAL_client_height))
- {
- int real_w = m_lpDX->m_REAL_client_width; // real client size, in pixels
- int real_h = m_lpDX->m_REAL_client_height;
- int fat_w = m_lpDX->m_client_width; // oversized VS canvas size, in pixels
- int fat_h = m_lpDX->m_client_height;
- int extra_w = fat_w - real_w;
- int extra_h = fat_h - real_h;
- RECT src, dst;
- SetRect(&src, extra_w/2, extra_h/2, extra_w/2 + real_w, extra_h/2 + real_h);
- SetRect(&dst, 0, 0, real_w, real_h);
- m_lpDX->m_lpDevice->Present(&src, &dst,NULL,NULL);
- }
- else
- m_lpDX->m_lpDevice->Present(NULL,NULL,NULL,NULL);
- if (m_vjd3d9_device && !m_hidden_textwnd)
- m_vjd3d9_device->Present(NULL,NULL,NULL,NULL);
- }
- void CPluginShell::EnforceMaxFPS()
- {
- int max_fps;
- switch (m_screenmode)
- {
- case WINDOWED: max_fps = m_max_fps_w; break;
- case FULLSCREEN: max_fps = m_max_fps_fs; break;
- case FAKE_FULLSCREEN: max_fps = m_max_fps_fs; break;
- case DESKTOP: max_fps = m_max_fps_dm; break;
- }
- if (max_fps <= 0)
- return;
- float fps_lo = (float)max_fps;
- float fps_hi = (float)max_fps;
- if (m_save_cpu)
- {
- // Find the optimal lo/hi bounds for the fps
- // that will result in a maximum difference,
- // in the time for a single frame, of 0.003 seconds -
- // the assumed granularity for Sleep(1) -
- // Using this range of acceptable fps
- // will allow us to do (sloppy) fps limiting
- // using only Sleep(1), and never the
- // second half of it: Sleep(0) in a tight loop,
- // which sucks up the CPU (whereas Sleep(1)
- // leaves it idle).
- // The original equation:
- // 1/(max_fps*t1) = 1/(max*fps/t1) - 0.003
- // where:
- // t1 > 0
- // max_fps*t1 is the upper range for fps
- // max_fps/t1 is the lower range for fps
- float a = 1;
- float b = -0.003f * max_fps;
- float c = -1.0f;
- float det = b*b - 4*a*c;
- if (det>0)
- {
- float t1 = (-b + sqrtf(det)) / (2*a);
- //float t2 = (-b - sqrtf(det)) / (2*a);
- if (t1 > 1.0f)
- {
- fps_lo = max_fps / t1;
- fps_hi = max_fps * t1;
- // verify: now [1.0f/fps_lo - 1.0f/fps_hi] should equal 0.003 seconds.
- // note: allowing tolerance to go beyond these values for
- // fps_lo and fps_hi would gain nothing.
- }
- }
- }
- if (m_high_perf_timer_freq.QuadPart > 0)
- {
- LARGE_INTEGER t;
- QueryPerformanceCounter(&t);
- if (m_prev_end_of_frame.QuadPart != 0)
- {
- int ticks_to_wait_lo = (int)((float)m_high_perf_timer_freq.QuadPart / (float)fps_hi);
- int ticks_to_wait_hi = (int)((float)m_high_perf_timer_freq.QuadPart / (float)fps_lo);
- int done = 0;
- int loops = 0;
- do
- {
- QueryPerformanceCounter(&t);
- __int64 t2 = t.QuadPart - m_prev_end_of_frame.QuadPart;
- if (t2 > 2147483000)
- done = 1;
- if (t.QuadPart < m_prev_end_of_frame.QuadPart) // time wrap
- done = 1;
- // this is sloppy - if your freq. is high, this can overflow (to a (-) int) in just a few minutes
- // but it's ok, we have protection for that above.
- int ticks_passed = (int)(t.QuadPart - m_prev_end_of_frame.QuadPart);
- if (ticks_passed >= ticks_to_wait_lo)
- done = 1;
- if (!done)
- {
- // if > 0.01s left, do Sleep(1), which will actually sleep some
- // steady amount of up to 3 ms (depending on the OS),
- // and do so in a nice way (cpu meter drops; laptop battery spared).
- // otherwise, do a few Sleep(0)'s, which just give up the timeslice,
- // but don't really save cpu or battery, but do pass a tiny
- // amount of time.
- //if (ticks_left > (int)m_high_perf_timer_freq.QuadPart/500)
- if (ticks_to_wait_hi - ticks_passed > (int)m_high_perf_timer_freq.QuadPart/100)
- Sleep(5);
- else if (ticks_to_wait_hi - ticks_passed > (int)m_high_perf_timer_freq.QuadPart/1000)
- Sleep(1);
- else
- for (int i=0; i<10; i++)
- Sleep(0); // causes thread to give up its timeslice
- }
- }
- while (!done);
- }
- m_prev_end_of_frame = t;
- }
- else
- {
- Sleep(1000/max_fps);
- }
- }
- void CPluginShell::DoTime()
- {
- if (m_frame==0)
- {
- m_fps = 30;
- m_time = 0;
- m_time_hist_pos = 0;
- }
- double new_raw_time;
- float elapsed;
- if (m_high_perf_timer_freq.QuadPart != 0)
- {
- // get high-precision time
- // precision: usually from 1..6 us (MICROseconds), depending on the cpu speed.
- // (higher cpu speeds tend to have better precision here)
- LARGE_INTEGER t;
- if (!QueryPerformanceCounter(&t))
- {
- m_high_perf_timer_freq.QuadPart = 0; // something went wrong (exception thrown) -> revert to crappy timer
- }
- else
- {
- new_raw_time = (double)t.QuadPart;
- elapsed = (float)((new_raw_time - m_last_raw_time)/(double)m_high_perf_timer_freq.QuadPart);
- }
- }
- if (m_high_perf_timer_freq.QuadPart == 0)
- {
- // get low-precision time
- // precision: usually 1 ms (MILLIsecond) for win98, and 10 ms for win2k.
- new_raw_time = (double)(timeGetTime()*0.001);
- elapsed = (float)(new_raw_time - m_last_raw_time);
- }
- m_last_raw_time = new_raw_time;
- int slots_to_look_back = (m_high_perf_timer_freq.QuadPart==0) ? TIME_HIST_SLOTS : TIME_HIST_SLOTS/2;
- m_time += 1.0f/m_fps;
- // timekeeping goals:
- // 1. keep 'm_time' increasing SMOOTHLY: (smooth animation depends on it)
- // m_time += 1.0f/m_fps; // where m_fps is a bit damped
- // 2. keep m_time_hist[] 100% accurate (except for filtering out pauses),
- // so that when we look take the difference between two entries,
- // we get the real amount of time that passed between those 2 frames.
- // m_time_hist[i] = m_last_raw_time + elapsed_corrected;
- if (m_frame > TIME_HIST_SLOTS)
- {
- if (m_fps < 60.0f)
- slots_to_look_back = (int)(slots_to_look_back*(0.1f + 0.9f*(m_fps/60.0f)));
- if (elapsed > 5.0f/m_fps || elapsed > 1.0f || elapsed < 0)
- elapsed = 1.0f / 30.0f;
- float old_hist_time = m_time_hist[(m_time_hist_pos - slots_to_look_back + TIME_HIST_SLOTS) % TIME_HIST_SLOTS];
- float new_hist_time = m_time_hist[(m_time_hist_pos - 1 + TIME_HIST_SLOTS) % TIME_HIST_SLOTS]
- + elapsed;
- m_time_hist[m_time_hist_pos] = new_hist_time;
- m_time_hist_pos = (m_time_hist_pos+1) % TIME_HIST_SLOTS;
- float new_fps = slots_to_look_back / (float)(new_hist_time - old_hist_time);
- float damping = (m_high_perf_timer_freq.QuadPart==0) ? 0.93f : 0.87f;
- // damp heavily, so that crappy timer precision doesn't make animation jerky
- if (fabsf(m_fps - new_fps) > 3.0f)
- m_fps = new_fps;
- else
- m_fps = damping*m_fps + (1-damping)*new_fps;
- }
- else
- {
- float damping = (m_high_perf_timer_freq.QuadPart==0) ? 0.8f : 0.6f;
- if (m_frame < 2)
- elapsed = 1.0f / 30.0f;
- else if (elapsed > 1.0f || elapsed < 0)
- elapsed = 1.0f / m_fps;
- float old_hist_time = m_time_hist[0];
- float new_hist_time = m_time_hist[(m_time_hist_pos - 1 + TIME_HIST_SLOTS) % TIME_HIST_SLOTS]
- + elapsed;
- m_time_hist[m_time_hist_pos] = new_hist_time;
- m_time_hist_pos = (m_time_hist_pos+1) % TIME_HIST_SLOTS;
- if (m_frame > 0)
- {
- float new_fps = (m_frame) / (new_hist_time - old_hist_time);
- m_fps = damping*m_fps + (1-damping)*new_fps;
- }
- }
- // Synchronize the audio and video by telling Winamp how many milliseconds we want the audio data,
- // before it's actually audible. If we set this to the amount of time it takes to display 1 frame
- // (1/fps), the video and audio should be perfectly synchronized.
- if (m_fps < 2.0f)
- mod1.latencyMs = 500;
- else if (m_fps > 125.0f)
- mod1.latencyMs = 8;
- else
- mod1.latencyMs = (int)(1000.0f/m_fps*m_lpDX->m_frame_delay + 0.5f);
- }
- void CPluginShell::AnalyzeNewSound(unsigned char *pWaveL, unsigned char *pWaveR)
- {
- // we get 576 samples in from winamp.
- // the output of the fft has 'num_frequencies' samples,
- // and represents the frequency range 0 hz - 22,050 hz.
- // usually, plugins only use half of this output (the range 0 hz - 11,025 hz),
- // since >10 khz doesn't usually contribute much.
- int i;
- float temp_wave[2][576];
- int old_i = 0;
- for (i=0; i<576; i++)
- {
- m_sound.fWaveform[0][i] = (float)((pWaveL[i] ^ 128) - 128);
- m_sound.fWaveform[1][i] = (float)((pWaveR[i] ^ 128) - 128);
- // simulating single frequencies from 200 to 11,025 Hz:
- //float freq = 1.0f + 11050*(GetFrame() % 100)*0.01f;
- //m_sound.fWaveform[0][i] = 10*sinf(i*freq*6.28f/44100.0f);
- // damp the input into the FFT a bit, to reduce high-frequency noise:
- temp_wave[0][i] = 0.5f*(m_sound.fWaveform[0][i] + m_sound.fWaveform[0][old_i]);
- temp_wave[1][i] = 0.5f*(m_sound.fWaveform[1][i] + m_sound.fWaveform[1][old_i]);
- old_i = i;
- }
- m_fftobj.time_to_frequency_domain(temp_wave[0], m_sound.fSpectrum[0]);
- m_fftobj.time_to_frequency_domain(temp_wave[1], m_sound.fSpectrum[1]);
- // sum (left channel) spectrum up into 3 bands
- // [note: the new ranges do it so that the 3 bands are equally spaced, pitch-wise]
- float min_freq = 200.0f;
- float max_freq = 11025.0f;
- float net_octaves = (logf(max_freq/min_freq) / logf(2.0f)); // 5.7846348455575205777914165223593
- float octaves_per_band = net_octaves / 3.0f; // 1.9282116151858401925971388407864
- float mult = powf(2.0f, octaves_per_band); // each band's highest freq. divided by its lowest freq.; 3.805831305510122517035102576162
- // [to verify: min_freq * mult * mult * mult should equal max_freq.]
- for (int ch=0; ch<2; ch++)
- {
- for (i=0; i<3; i++)
- {
- // old guesswork code for this:
- // float exp = 2.1f;
- // int start = (int)(NUM_FREQUENCIES*0.5f*powf(i/3.0f, exp));
- // int end = (int)(NUM_FREQUENCIES*0.5f*powf((i+1)/3.0f, exp));
- // results:
- // old range: new range (ideal):
- // bass: 0-1097 200-761
- // mids: 1097-4705 761-2897
- // treb: 4705-11025 2897-11025
- int start = (int)(NUM_FREQUENCIES * min_freq*powf(mult, (float)i)/11025.0f);
- int end = (int)(NUM_FREQUENCIES * min_freq*powf(mult, (float)(i+1))/11025.0f);
- if (start < 0) start = 0;
- if (end > NUM_FREQUENCIES) end = NUM_FREQUENCIES;
- m_sound.imm[ch][i] = 0;
- for (int j=start; j<end; j++)
- m_sound.imm[ch][i] += m_sound.fSpectrum[ch][j];
- m_sound.imm[ch][i] /= (float)(end-start);
- }
- }
- // some code to find empirical long-term averages for imm[0..2]:
- /*{
- static float sum[3];
- static int count = 0;
- #define FRAMES_PER_SONG 300 // should be at least 200!
- if (m_frame < FRAMES_PER_SONG)
- {
- sum[0] = sum[1] = sum[2] = 0;
- count = 0;
- }
- else
- {
- if (m_frame%FRAMES_PER_SONG == 0)
- {
- char buf[256];
- sprintf(buf, "%.4f, %.4f, %.4f (%d samples / ~%d songs)\n",
- sum[0]/(float)(count),
- sum[1]/(float)(count),
- sum[2]/(float)(count),
- count,
- count/(FRAMES_PER_SONG-10)
- );
- OutputDebugString(buf);
- // skip to next song
- PostMessage(m_hWndWinamp,WM_COMMAND,40048,0);
- }
- else if (m_frame%FRAMES_PER_SONG == 5)
- {
- // then advance to 0-2 minutes into the song:
- PostMessage(m_hWndWinamp,WM_USER,(20 + (warand()%65) + (rand()%65))*1000,106);
- }
- else if (m_frame%FRAMES_PER_SONG >= 10)
- {
- sum[0] += m_sound.imm[0];
- sum[1] += m_sound.imm[1];
- sum[2] += m_sound.imm[2];
- count++;
- }
- }
- }*/
- // multiply by long-term, empirically-determined inverse averages:
- // (for a trial of 244 songs, 10 seconds each, somewhere in the 2nd or 3rd minute,
- // the average levels were: 0.326781557 0.38087377 0.199888934
- for (int ch=0; ch<2; ch++)
- {
- m_sound.imm[ch][0] /= 0.326781557f;//0.270f;
- m_sound.imm[ch][1] /= 0.380873770f;//0.343f;
- m_sound.imm[ch][2] /= 0.199888934f;//0.295f;
- }
- // do temporal blending to create attenuated and super-attenuated versions
- for (int ch=0; ch<2; ch++)
- {
- for (i=0; i<3; i++)
- {
- // m_sound.avg[i]
- {
- float avg_mix;
- if (m_sound.imm[ch][i] > m_sound.avg[ch][i])
- avg_mix = AdjustRateToFPS(0.2f, 14.0f, m_fps);
- else
- avg_mix = AdjustRateToFPS(0.5f, 14.0f, m_fps);
- m_sound.avg[ch][i] = m_sound.avg[ch][i]*avg_mix + m_sound.imm[ch][i]*(1-avg_mix);
- }
- // m_sound.med_avg[i]
- // m_sound.long_avg[i]
- {
- float med_mix = 0.91f;//0.800f + 0.11f*powf(t, 0.4f); // primarily used for velocity_damping
- float long_mix = 0.96f;//0.800f + 0.16f*powf(t, 0.2f); // primarily used for smoke plumes
- med_mix = AdjustRateToFPS(med_mix, 14.0f, m_fps);
- long_mix = AdjustRateToFPS(long_mix, 14.0f, m_fps);
- m_sound.med_avg[ch][i] = m_sound.med_avg[ch][i]*(med_mix) + m_sound.imm[ch][i]*(1-med_mix);
- m_sound.long_avg[ch][i] = m_sound.long_avg[ch][i]*(long_mix) + m_sound.imm[ch][i]*(1-long_mix);
- }
- }
- }
- }
- void CPluginShell::PrepareFor2DDrawing_B(IDirect3DDevice9 *pDevice, int w, int h)
- {
- // New 2D drawing area will have x,y coords in the range <-1,-1> .. <1,1>
- // +--------+ Y=-1
- // | |
- // | screen | Z=0: front of scene
- // | | Z=1: back of scene
- // +--------+ Y=1
- // X=-1 X=1
- // NOTE: After calling this, be sure to then call (at least):
- // 1. SetVertexShader()
- // 2. SetTexture(), if you need it
- // before rendering primitives!
- // Also, be sure your sprites have a z coordinate of 0.
- pDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
- pDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
- pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
- pDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
- pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
- pDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
- pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
- pDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
- pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
- pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
- pDevice->SetRenderState(D3DRS_LOCALVIEWER, FALSE);
- pDevice->SetRenderState(D3DRS_COLORVERTEX, TRUE);
- pDevice->SetTexture(0, NULL);
- pDevice->SetTexture(1, NULL);
- pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);//D3DTEXF_LINEAR);
- pDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);//D3DTEXF_LINEAR);
- pDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
- pDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
- pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
- pDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
- pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
- pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
- pDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
- // set up for 2D drawing:
- {
- D3DXMATRIX Ortho2D;
- D3DXMATRIX Identity;
- pMatrixOrthoLH(&Ortho2D, (float)w, (float)h, 0.0f, 1.0f);
- D3DXMatrixIdentity(&Identity);
- pDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D);
- pDevice->SetTransform(D3DTS_WORLD, &Identity);
- pDevice->SetTransform(D3DTS_VIEW, &Identity);
- }
- }
- void CPluginShell::DrawDarkTranslucentBox(RECT* pr)
- {
- // 'pr' is the rectangle that some text will occupy;
- // a black box will be drawn around it, plus a bit of extra margin space.
- if (m_vjd3d9_device)
- return;
- m_lpDX->m_lpDevice->SetVertexShader(NULL);
- m_lpDX->m_lpDevice->SetPixelShader(NULL);
- m_lpDX->m_lpDevice->SetFVF(SIMPLE_VERTEX_FORMAT);
- m_lpDX->m_lpDevice->SetTexture(0, NULL);
- m_lpDX->m_lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
- m_lpDX->m_lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
- m_lpDX->m_lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
- m_lpDX->m_lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
- m_lpDX->m_lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
- // set up a quad
- SIMPLEVERTEX verts[4];
- for (int i=0; i<4; i++)
- {
- verts[i].x = (i%2==0) ? (float)(-m_lpDX->m_client_width /2 + pr->left) :
- (float)(-m_lpDX->m_client_width /2 + pr->right);
- verts[i].y = (i/2==0) ? (float)-(-m_lpDX->m_client_height/2 + pr->bottom) :
- (float)-(-m_lpDX->m_client_height/2 + pr->top);
- verts[i].z = 0;
- verts[i].Diffuse = (m_screenmode==DESKTOP) ? 0xE0000000 : 0xD0000000;
- }
- m_lpDX->m_lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(SIMPLEVERTEX));
- // undo unusual state changes:
- m_lpDX->m_lpDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
- m_lpDX->m_lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
- }
- void CPluginShell::RenderBuiltInTextMsgs()
- {
- int _show_press_f1_NOW = (m_show_press_f1_msg && m_time < PRESS_F1_DUR);
- {
- RECT r;
- if (m_show_help)
- {
- int y = m_upper_left_corner_y;
- SetRect(&r, 0, 0, GetWidth(), GetHeight());
- if(!g_szHelp_W)
- m_d3dx_font[HELPSCREEN_FONT]->DrawTextA(NULL, (char*)g_szHelp, -1, &r, DT_CALCRECT, 0xFFFFFFFF);
- else
- m_d3dx_font[HELPSCREEN_FONT]->DrawTextW(NULL, g_szHelp, -1, &r, DT_CALCRECT, 0xFFFFFFFF);
- r.top += m_upper_left_corner_y;
- r.left += m_left_edge;
- r.right += m_left_edge + PLAYLIST_INNER_MARGIN*2;
- r.bottom += m_upper_left_corner_y + PLAYLIST_INNER_MARGIN*2;
- DrawDarkTranslucentBox(&r);
- r.top += PLAYLIST_INNER_MARGIN;
- r.left += PLAYLIST_INNER_MARGIN;
- r.right -= PLAYLIST_INNER_MARGIN;
- r.bottom -= PLAYLIST_INNER_MARGIN;
- if(!g_szHelp_W)
- m_d3dx_font[HELPSCREEN_FONT]->DrawTextA(NULL, (char*)g_szHelp, -1, &r, 0, 0xFFFFFFFF);
- else
- m_d3dx_font[HELPSCREEN_FONT]->DrawTextW(NULL, g_szHelp, -1, &r, 0, 0xFFFFFFFF);
- m_upper_left_corner_y += r.bottom-r.top + PLAYLIST_INNER_MARGIN*3;
- }
- // render 'Press F1 for Help' message in lower-right corner:
- if (_show_press_f1_NOW)
- {
- int dx = (int)(160.0f * powf(m_time/(float)(PRESS_F1_DUR), (float)(PRESS_F1_EXP)));
- SetRect(&r, m_left_edge, m_lower_right_corner_y - GetFontHeight(DECORATIVE_FONT), m_right_edge + dx, m_lower_right_corner_y);
- m_lower_right_corner_y -= m_d3dx_font[DECORATIVE_FONT]->DrawTextW(NULL, WASABI_API_LNGSTRINGW(IDS_PRESS_F1_MSG), -1, &r, DT_RIGHT, 0xFFFFFFFF);
- }
- }
- }
- void CPluginShell::RenderPlaylist()
- {
- // draw playlist:
- if (m_show_playlist)
- {
- RECT r;
- int nSongs = SendMessage(m_hWndWinamp,WM_USER, 0, 124);
- int now_playing = SendMessage(m_hWndWinamp,WM_USER, 0, 125);
- if (nSongs <= 0)
- {
- m_show_playlist = 0;
- }
- else
- {
- int playlist_vert_pixels = m_lower_left_corner_y - m_upper_left_corner_y;
- int disp_lines = min(MAX_SONGS_PER_PAGE, (playlist_vert_pixels - PLAYLIST_INNER_MARGIN*2) / GetFontHeight(PLAYLIST_FONT));
- int total_pages = (nSongs) / disp_lines;
- if (disp_lines<=0)
- return;
- // apply PgUp/PgDn keypresses since last time
- m_playlist_pos -= m_playlist_pageups * disp_lines;
- m_playlist_pageups = 0;
- if (m_playlist_pos < 0)
- m_playlist_pos = 0;
- if (m_playlist_pos >= nSongs)
- m_playlist_pos = nSongs-1;
- // NOTE: 'dwFlags' is used for both DDRAW and DX9
- DWORD dwFlags = DT_SINGLELINE;// | DT_NOPREFIX | DT_WORD_ELLIPSIS;
- DWORD color;
- int cur_page = (m_playlist_pos) / disp_lines;
- int cur_line = (m_playlist_pos + disp_lines - 1) % disp_lines;
- int new_top_idx = cur_page * disp_lines;
- int new_btm_idx = new_top_idx + disp_lines;
- wchar_t buf[1024] = {0};
- // ask winamp for the song names, but DO IT BEFORE getting the DC,
- // otherwise vaio will crash (~DDRAW port).
- if (m_playlist_top_idx != new_top_idx ||
- m_playlist_btm_idx != new_btm_idx)
- {
- for (int i=0; i<disp_lines; i++)
- {
- int j = new_top_idx + i;
- if (j < nSongs)
- {
- // clip max len. of song name to 240 chars, to prevent overflows
- lstrcpynW(buf, (wchar_t*)SendMessage(m_hWndWinamp, WM_USER, j, IPC_GETPLAYLISTTITLEW), 240);
- wsprintfW(m_playlist[i], L"%d. %s ", j+1, buf); // leave an extra space @ end, so italicized fonts don't get clipped
- }
- }
- }
- // update playlist cache, if necessary:
- if (m_playlist_top_idx != new_top_idx ||
- m_playlist_btm_idx != new_btm_idx)
- {
- m_playlist_top_idx = new_top_idx;
- m_playlist_btm_idx = new_btm_idx;
- m_playlist_width_pixels = 0;
- int max_w = min(m_right_edge - m_left_edge, m_lpDX->m_client_width - TEXT_MARGIN*2 - PLAYLIST_INNER_MARGIN*2);
- for (int i=0; i<disp_lines; i++)
- {
- int j = new_top_idx + i;
- if (j < nSongs)
- {
- // clip max len. of song name to 240 chars, to prevent overflows
- //strcpy(buf, (char*)SendMessage(m_hWndWinamp, WM_USER, j, 212));
- //buf[240] = 0;
- //sprintf(m_playlist[i], "%d. %s ", j+1, buf); // leave an extra space @ end, so italicized fonts don't get clipped
- SetRect(&r, 0, 0, max_w, 1024);
- m_d3dx_font[PLAYLIST_FONT]->DrawTextW(NULL, m_playlist[i], -1, &r, dwFlags | DT_CALCRECT, 0xFFFFFFFF);
- int w = r.right-r.left;
- if (w>0)
- m_playlist_width_pixels = max(m_playlist_width_pixels, w);
- }
- else
- {
- m_playlist[i][0] = 0;
- }
- }
- if (m_playlist_width_pixels == 0 ||
- m_playlist_width_pixels > max_w)
- m_playlist_width_pixels = max_w;
- }
- int start = max(0, (cur_page)*disp_lines);
- int end = min(nSongs, (cur_page+1)*disp_lines);
- // draw dark box around where the playlist will go:
- RECT r;
- r.top = m_upper_left_corner_y;
- r.left = m_left_edge;
- r.right = m_left_edge + m_playlist_width_pixels + PLAYLIST_INNER_MARGIN*2;
- r.bottom = m_upper_left_corner_y + (end-start)*GetFontHeight(PLAYLIST_FONT) + PLAYLIST_INNER_MARGIN*2;
- DrawDarkTranslucentBox(&r);
- //m_d3dx_font[PLAYLIST_FONT]->Begin();
- // draw playlist text
- int y = m_upper_left_corner_y + PLAYLIST_INNER_MARGIN;
- for (int i=start; i<end; i++)
- {
- SetRect(&r, m_left_edge + PLAYLIST_INNER_MARGIN, y, m_left_edge + PLAYLIST_INNER_MARGIN + m_playlist_width_pixels, y + GetFontHeight(PLAYLIST_FONT));
- if (m_lpDX->GetBitDepth() == 8)
- color = (i==m_playlist_pos) ?
- (i==now_playing ? 0xFFFFFFFF : 0xFFFFFFFF) :
- (i==now_playing ? 0xFFFFFFFF : 0xFF707070);
- else
- color = (i==m_playlist_pos) ?
- (i==now_playing ? PLAYLIST_COLOR_BOTH : PLAYLIST_COLOR_HILITE_TRACK) :
- (i==now_playing ? PLAYLIST_COLOR_PLAYING_TRACK : PLAYLIST_COLOR_NORMAL);
- y += m_d3dx_font[PLAYLIST_FONT]->DrawTextW(NULL, m_playlist[i-start], -1, &r, dwFlags, color);
- }
- //m_d3dx_font[PLAYLIST_FONT]->End();
- }
- }
- }
- void CPluginShell::SuggestHowToFreeSomeMem()
- {
- // This function is called when the plugin runs out of video memory;
- // it lets you show a messagebox to the user so you can (intelligently)
- // suggest how to free up some video memory, based on what settings
- // they've chosen.
- wchar_t str[1024];
- if (m_lpDX->m_current_mode.multisamp != D3DMULTISAMPLE_NONE)
- {
- if (m_lpDX->m_current_mode.screenmode == WINDOWED)
- WASABI_API_LNGSTRINGW_BUF(IDS_TO_FREE_UP_SOME_MEMORY_RESTART_WINAMP_THEN_GO_TO_CONFIG, str, 2048);
- else if (m_lpDX->m_current_mode.screenmode == FAKE_FULLSCREEN)
- WASABI_API_LNGSTRINGW_BUF(IDS_TO_FREE_UP_SOME_MEMORY_RESTART_WINAMP_THEN_GO_TO_CONFIG_2, str, 2048);
- else
- WASABI_API_LNGSTRINGW_BUF(IDS_TO_FREE_UP_SOME_MEMORY_RESTART_WINAMP_THEN_GO_TO_CONFIG_3, str, 2048);
- }
- else
- if (m_lpDX->m_current_mode.screenmode == FULLSCREEN) // true fullscreen
- WASABI_API_LNGSTRINGW_BUF(IDS_TO_FREE_UP_VIDEO_MEMORY, str, 2048);
- else // windowed, desktop mode, or fake fullscreen
- WASABI_API_LNGSTRINGW_BUF(IDS_TO_FREE_UP_VIDEO_MEMORY, str, 2048);
- MessageBoxW(m_lpDX->GetHwnd(), str, WASABI_API_LNGSTRINGW(IDS_MILKDROP_SUGGESTION), MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
- }
- LRESULT CALLBACK CPluginShell::WindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam)
- {
- //if (uMsg==WM_GETDLGCODE)
- // return DLGC_WANTALLKEYS|DLGC_WANTCHARS|DLGC_WANTMESSAGE; // this tells the embedwnd that we want keypresses to flow through to our client wnd.
- if (uMsg == WM_CREATE)
- {
- CREATESTRUCT *create = (CREATESTRUCT *)lParam;
- SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)create->lpCreateParams);
- }
- CPluginShell* p = (CPluginShell*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
- if (p)
- return p->PluginShellWindowProc(hWnd, uMsg, wParam, lParam);
- else
- return DefWindowProcW(hWnd, uMsg, wParam, lParam);
- }
- LRESULT CPluginShell::PluginShellWindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam)
- {
- USHORT mask = 1 << (sizeof(SHORT)*8 - 1);
- //bool bShiftHeldDown = (GetKeyState(VK_SHIFT) & mask) != 0;
- bool bCtrlHeldDown = (GetKeyState(VK_CONTROL) & mask) != 0;
- //bool bAltHeldDown: most keys come in under WM_SYSKEYDOWN when ALT is depressed.
- int i;
- #ifdef _DEBUG
- char caption[256] = "WndProc: frame 0, ";
- if (m_frame > 0)
- {
- float time = m_time;
- int hours = (int)(time/3600);
- time -= hours*3600;
- int minutes = (int)(time/60);
- time -= minutes*60;
- int seconds = (int)time;
- time -= seconds;
- int dsec = (int)(time*100);
- sprintf(caption, "WndProc: frame %d, t=%dh:%02dm:%02d.%02ds, ", m_frame, hours, minutes, seconds, dsec);
- }
- if (uMsg != WM_MOUSEMOVE &&
- uMsg != WM_NCHITTEST &&
- uMsg != WM_SETCURSOR &&
- uMsg != WM_COPYDATA &&
- uMsg != WM_USER)
- OutputDebugMessage(caption, hWnd, uMsg, wParam, lParam);
- #endif
- switch (uMsg)
- {
- case WM_USER:
- if (m_screenmode == DESKTOP)
- {
- // this function resides in vms_desktop.dll;
- // its response will come later, via the WM_COPYDATA
- // message (See below).
- //KIV: **THIS CALL CRASHES EXPLORER IN VISTA**
- getItemData(wParam);
- return 0;
- }
- break;
- case WM_COPYDATA:
- if (m_screenmode == DESKTOP)
- {
- // this message is vms_desktop.dll's response to
- // our call to getItemData().
- PCOPYDATASTRUCT c = (PCOPYDATASTRUCT)lParam;
- if (c && (c->cbData % sizeof(icon_t) == 0))
- {
- icon_t *pNewIcons = (icon_t*)c->lpData;
- EnterCriticalSection(&m_desktop_cs);
- if (m_desktop_icon_state == 1 && (c->dwData & 0x80000000)) // if doing a total refresh...
- {
- // ...we build the list from zero
- int len = c->dwData & 0xFFFF;
- for (int i=0; i<len; i++)
- m_icon_list.push_back(pNewIcons[i]);
- }
- else if (m_desktop_icon_state == 3 && !(c->dwData & 0x80000000))
- {
- // otherwise, we alter existing things in the list:
- IconList::iterator p;
- int start = c->dwData & 0xFFFF;
- int len = c->dwData >> 16;
- int i = 0;
- for (p = m_icon_list.begin(); p != m_icon_list.end() && i<start; p++)
- i++;
- for (; p != m_icon_list.end() && i<start+len; p++)
- {
- p->x = pNewIcons[i-start].x;
- p->y = pNewIcons[i-start].y;
- memcpy(p->name, pNewIcons[i-start].name, sizeof(p->name));
- memcpy(p->pidl, pNewIcons[i-start].pidl, sizeof(p->pidl));
- i++;
- }
- m_desktop_icon_state = 2;
- m_desktop_icon_update_frame = GetFrame();
- }
- LeaveCriticalSection(&m_desktop_cs);
- }
- return 0;
- }
- break;
- case WM_ERASEBKGND:
- // Repaint window when song is paused and image needs to be repainted:
- if (SendMessage(m_hWndWinamp,WM_USER,0,104)!=1 && m_lpDX && m_lpDX->m_lpDevice && GetFrame() > 0) // WM_USER/104 return codes: 1=playing, 3=paused, other=stopped
- {
- m_lpDX->m_lpDevice->Present(NULL,NULL,NULL,NULL);
- return 0;
- }
- break;
- case WM_WINDOWPOSCHANGING:
- if (
- m_screenmode == DESKTOP
- && (!m_force_accept_WM_WINDOWPOSCHANGING)
- && m_lpDX && m_lpDX->m_ready
- )
- {
- // unless we requested it ourselves or it's init time,
- // prevent the fake desktop window from moving around
- // in the Z order! (i.e., keep it on the bottom)
- // without this code, when you click on the 'real' desktop
- // in a multimon setup, any windows that are overtop of the
- // 'fake' desktop will flash, since they'll be covered
- // up by the fake desktop window (but then shown again on
- // the next frame, when we detect that the fake desktop
- // window isn't on bottom & send it back to the bottom).
- LPWINDOWPOS pwp = (LPWINDOWPOS)lParam;
- if (pwp)
- pwp->flags |= SWP_NOOWNERZORDER | SWP_NOZORDER;
- }
- if (m_screenmode==WINDOWED && m_lpDX && m_lpDX->m_ready && m_lpDX->m_current_mode.m_skin)
- m_lpDX->SaveWindow();
- break;
- case WM_NCACTIVATE:
- // *Very Important Handler!*
- // -Without this code, the app would not work properly when running in true
- // fullscreen mode on multiple monitors; it would auto-minimize whenever the
- // user clicked on a window in another display.
- if (wParam == 0 &&
- m_screenmode == FULLSCREEN &&
- m_frame > 0 &&
- !m_exiting &&
- m_lpDX &&
- m_lpDX->m_ready
- && m_lpDX->m_lpD3D &&
- m_lpDX->m_lpD3D->GetAdapterCount() > 1
- )
- {
- return 0;
- }
- break;
- case WM_DESTROY:
- // note: don't post quit message here if the window is being destroyed
- // and re-created on a switch between windowed & FAKE fullscreen modes.
- if (!m_lpDX->TempIgnoreDestroyMessages())
- {
- // this is a final exit, and not just destroy-then-recreate-the-window.
- // so, flag DXContext so it knows that someone else
- // will take care of destroying the window!
- m_lpDX->OnTrulyExiting();
- PostQuitMessage(0);
- }
- return FALSE;
- break;
- // benski> a little hack to get the window size correct. it seems to work
- case WM_USER+555:
- if (m_lpDX && m_lpDX->m_ready && m_screenmode==WINDOWED && !m_resizing)
- {
- OnUserResizeWindow();
- m_lpDX->SaveWindow();
- }
- break;
- case WM_MOVE:
- m_lpDX->SaveWindow();
- break;
- case WM_SIZE:
- // clear or set activity flag to reflect focus
- if (m_lpDX && m_lpDX->m_ready && m_screenmode==WINDOWED && !m_resizing)
- {
- m_hidden = (SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam) ? TRUE : FALSE;
- if (SIZE_MAXIMIZED==wParam || SIZE_RESTORED==wParam) // the window has been maximized or restored
- OnUserResizeWindow();
- }
- break;
- case WM_ENTERSIZEMOVE:
- m_resizing = 1;
- break;
- case WM_EXITSIZEMOVE:
- if (m_lpDX && m_lpDX->m_ready && m_screenmode==WINDOWED)
- OnUserResizeWindow();
- m_lpDX->SaveWindow();
- m_resizing = 0;
- break;
- case WM_GETMINMAXINFO:
- {
- // don't let the window get too small
- MINMAXINFO* p = (MINMAXINFO*)lParam;
- if (p->ptMinTrackSize.x < 64)
- p->ptMinTrackSize.x = 64;
- p->ptMinTrackSize.y = p->ptMinTrackSize.x*3/4;
- }
- return 0;
- case WM_MOUSEMOVE:
- if (m_screenmode==DESKTOP && (m_desktop_dragging==1 || m_desktop_box==1))
- {
- m_desktop_drag_curpos.x = LOWORD(lParam);
- m_desktop_drag_curpos.y = HIWORD(lParam);
- if (m_desktop_box==1)
- {
- // update selection based on box coords
- RECT box, temp;
- box.left = min(m_desktop_drag_curpos.x, m_desktop_drag_startpos.x);
- box.right = max(m_desktop_drag_curpos.x, m_desktop_drag_startpos.x);
- box.top = min(m_desktop_drag_curpos.y, m_desktop_drag_startpos.y);
- box.bottom = max(m_desktop_drag_curpos.y, m_desktop_drag_startpos.y);
- IconList::iterator p;
- for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
- {
- p->selected = 0;
- if (IntersectRect(&temp, &box, &p->label_rect))
- p->selected = 1;
- else if (IntersectRect(&temp, &box, &p->icon_rect))
- p->selected = 1;
- }
- }
- // repaint window manually, if winamp is paused
- if (SendMessage(m_hWndWinamp,WM_USER,0,104) != 1)
- {
- PushWindowToJustBeforeDesktop(GetPluginWindow());
- DrawAndDisplay(1);
- }
- //return 0;
- }
- m_lpDX->SaveWindow();
- break;
- case WM_LBUTTONUP:
- if (m_screenmode==DESKTOP)
- {
- if (m_desktop_dragging)
- {
- m_desktop_dragging = 0;
- // move selected item(s) to new cursor position
- int dx = LOWORD(lParam) - m_desktop_drag_startpos.x;
- int dy = HIWORD(lParam) - m_desktop_drag_startpos.y;
- if (dx!=0 || dy!=0)
- {
- int idx=0;
- IconList::iterator p;
- for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
- {
- if (p->selected)
- {
- SendMessage(m_hWndDesktopListView, LVM_SETITEMPOSITION, idx, MAKELPARAM(p->x + dx, p->y + dy));
- p->x += dx;
- p->y += dy;
- }
- idx++;
- }
- }
- // repaint window manually, if winamp is paused
- if (SendMessage(m_hWndWinamp,WM_USER,0,104) != 1)
- {
- PushWindowToJustBeforeDesktop(GetPluginWindow());
- DrawAndDisplay(1);
- }
- }
- if (m_desktop_box)
- {
- m_desktop_box = 0;
- // repaint window manually, if winamp is paused
- if (SendMessage(m_hWndWinamp,WM_USER,0,104) != 1)
- {
- PushWindowToJustBeforeDesktop(GetPluginWindow());
- DrawAndDisplay(1);
- }
- }
- //return 0;
- }
- break;
- case WM_USER + 1666:
- if (wParam == 1 && lParam == 15)
- {
- if (m_screenmode == FULLSCREEN || m_screenmode == FAKE_FULLSCREEN)
- ToggleFullScreen();
- }
- return 0;
- case WM_LBUTTONDOWN:
- case WM_LBUTTONDBLCLK:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- // Toggle between Fullscreen and Windowed modes on double-click
- // note: this requires the 'CS_DBLCLKS' windowclass style!
- if (m_screenmode != DESKTOP)
- {
- SetFocus(hWnd);
- if (uMsg==WM_LBUTTONDBLCLK && m_frame>0)
- {
- ToggleFullScreen();
- return 0;
- }
- }
- else
- {
- POINT pt;
- pt.x = LOWORD(lParam);
- pt.y = HIWORD(lParam);
- int done = 0;
- for (int pass=0; pass<2 && !done; pass++)
- {
- IconList::iterator p;
- for (p = m_icon_list.begin(); p != m_icon_list.end(); p++)
- {
- RECT *pr = (pass==0) ? &p->icon_rect : &p->label_rect;
- int bottom_extend = (pass==0) ? 3 : 0; // accepts clicks in the 3-pixel gap between the icon and the text label.
- if (pt.x >= pr->left &&
- pt.x <= pr->right &&
- pt.y >= pr->top &&
- pt.y <= pr->bottom + bottom_extend)
- {
- switch (uMsg)
- {
- case WM_RBUTTONUP:
- //pt.x += m_lpDX->m_monitor_rect.left;
- //pt.y += m_lpDX->m_monitor_rect.top;
- DoExplorerMenu(GetPluginWindow(), (LPITEMIDLIST)p->pidl, pt);
- break;
- case WM_LBUTTONDBLCLK:
- {
- char buf[MAX_PATH];
- sprintf(buf, "%s\\%s", m_szDesktopFolder, p->name);
- ExecutePidl((LPITEMIDLIST)p->pidl, buf, m_szDesktopFolder, GetPluginWindow());
- }
- break;
- case WM_LBUTTONDOWN:
- m_desktop_dragging = 1;
- memcpy(m_desktop_drag_pidl, p->pidl, sizeof(m_desktop_drag_pidl));
- m_desktop_drag_startpos.x = LOWORD(lParam);
- m_desktop_drag_startpos.y = HIWORD(lParam);
- m_desktop_drag_curpos.x = LOWORD(lParam);
- m_desktop_drag_curpos.y = HIWORD(lParam);
- if (!(wParam & MK_CONTROL)) // if CTRL not held down
- {
- if (!p->selected)
- {
- DeselectDesktop();
- p->selected = 1;
- }
- }
- else
- {
- p->selected = 1-p->selected;
- }
- break;
- case WM_RBUTTONDOWN:
- DeselectDesktop();
- p->selected = 1;
- break;
- }
- done = 1;
- break;
- }
- }
- }
- if (!done)
- {
- // deselect all, unless they're CTRL+clicking and missed an icon.
- if (uMsg!=WM_LBUTTONDOWN || !(wParam & MK_CONTROL))
- DeselectDesktop();
- if (uMsg==WM_RBUTTONUP)// || uMsg==WM_RBUTTONDOWN)
- {
- // note: can't use GetMenu and TrackPopupMenu here because the hwnd param to TrackPopupMenu must belong to current application.
- // (before sending coords to desktop window, xform them into its client coords:)
- POINT pt;
- pt.x = LOWORD(lParam);
- pt.y = HIWORD(lParam);
- ScreenToClient(m_hWndDesktopListView, &pt);
- lParam = MAKELPARAM(pt.x + m_lpDX->m_monitor_rect.left, pt.y + m_lpDX->m_monitor_rect.top);
- PostMessage(m_hWndDesktopListView, uMsg, wParam, lParam);
- //PostMessage(m_hWndDesktopListView, WM_CONTEXTMENU, (WPARAM)m_hWndDesktopListView, lParam);
- }
- else if (uMsg==WM_LBUTTONDOWN)
- {
- m_desktop_box = 1;
- m_desktop_drag_startpos.x = LOWORD(lParam);
- m_desktop_drag_startpos.y = HIWORD(lParam);
- m_desktop_drag_curpos.x = LOWORD(lParam);
- m_desktop_drag_curpos.y = HIWORD(lParam);
- }
- }
- // repaint window manually, if winamp is paused
- if (SendMessage(m_hWndWinamp,WM_USER,0,104) != 1)
- {
- PushWindowToJustBeforeDesktop(GetPluginWindow());
- DrawAndDisplay(1);
- }
- //return 0;
- }
- break;
- case WM_SETFOCUS:
- // note: this msg never comes in when embedwnd is used, but that's ok, because that's only
- // in Windowed mode, and m_lost_focus only makes us sleep when fullscreen.
- m_lost_focus = 0;
- break;
- case WM_KILLFOCUS:
- // note: this msg never comes in when embedwnd is used, but that's ok, because that's only
- // in Windowed mode, and m_lost_focus only makes us sleep when fullscreen.
- m_lost_focus = 1;
- break;
- case WM_SETCURSOR:
- if (
- (m_screenmode == FULLSCREEN) ||
- (m_screenmode == FAKE_FULLSCREEN && m_lpDX->m_fake_fs_covers_all)
- )
- {
- // hide the cursor
- SetCursor(NULL);
- return TRUE; // prevent Windows from setting cursor to window class cursor
- }
- break;
- case WM_NCHITTEST:
- // Prevent the user from selecting the menu in fullscreen mode
- if (m_screenmode != WINDOWED)
- return HTCLIENT;
- break;
- case WM_SYSCOMMAND:
- // Prevent *moving/sizing* and *entering standby mode* when in fullscreen mode
- switch (wParam)
- {
- case SC_MOVE:
- case SC_SIZE:
- case SC_MAXIMIZE:
- case SC_KEYMENU:
- if (m_screenmode != WINDOWED)
- return 1;
- break;
- case SC_MONITORPOWER:
- if (m_screenmode == FULLSCREEN || m_screenmode == FAKE_FULLSCREEN)
- return 1;
- break;
- }
- break;
- case WM_CONTEXTMENU:
- // launch popup context menu. see handler for WM_COMMAND also.
- if (m_screenmode == DESKTOP)
- {
- // note: execution should never reach this point,
- // because we don't pass WM_RBUTTONUP to DefWindowProc
- // when in desktop mode!
- return 0;
- }
- else if (m_screenmode == WINDOWED) // context menus only allowed in ~windowed modes
- {
- TrackPopupMenuEx(m_context_menu, TPM_VERTICAL, LOWORD(lParam), HIWORD(lParam), hWnd, NULL);
- return 0;
- }
- break;
- case WM_COMMAND:
- // handle clicks on items on context menu.
- if (m_screenmode == WINDOWED)
- {
- switch (LOWORD(wParam))
- {
- case ID_QUIT:
- m_exiting = 1;
- PostMessage(hWnd, WM_CLOSE, 0, 0);
- return 0;
- case ID_GO_FS:
- if (m_frame > 0)
- ToggleFullScreen();
- return 0;
- case ID_DESKTOP_MODE:
- if (m_frame > 0)
- ToggleDesktop();
- return 0;
- case ID_SHOWHELP:
- ToggleHelp();
- return 0;
- case ID_SHOWPLAYLIST:
- TogglePlaylist();
- return 0;
- }
- // then allow the plugin to override any command:
- if (MyWindowProc(hWnd, uMsg, wParam, lParam) == 0)
- return 0;
- }
- break;
- /*
- KEY HANDLING: the basic idea:
- -in all cases, handle or capture:
- -ZXCVBRS, zxcvbrs
- -also make sure it's case-insensitive! (lowercase come through only as WM_CHAR; uppercase come in as both)
- -(ALT+ENTER)
- -(F1, ESC, UP, DN, Left, Right, SHIFT+l/r)
- -(P for playlist)
- -when playlist showing: steal J, HOME, END, PGUP, PGDN, UP, DOWN, ESC
- -(BLOCK J, L)
- -when integrated with winamp (using embedwnd), also handle these keys:
- -j, l, L, CTRL+L [windowed mode only!]
- -CTRL+P, CTRL+D
- -CTRL+TAB
- -ALT-E
- -ALT+F (main menu)
- -ALT+3 (id3)
- */
- case WM_SYSKEYDOWN:
- if (wParam==VK_RETURN && m_frame > 0)
- {
- ToggleFullScreen();
- return 0;
- }
- // if in embedded mode (using winamp skin), pass ALT+ keys on to winamp
- // ex: ALT+E, ALT+F, ALT+3...
- if (m_screenmode==WINDOWED && m_lpDX->m_current_mode.m_skin)
- return PostMessage(m_hWndWinamp, uMsg, wParam, lParam); // force-pass to winamp; required for embedwnd
- break;
- case WM_SYSKEYUP:
- if (m_screenmode==WINDOWED && m_lpDX->m_current_mode.m_skin)
- return PostMessage(m_hWndWinamp, uMsg, wParam, lParam); // force-pass to winamp; required for embedwnd
- break;
- case WM_SYSCHAR:
- if ((wParam=='k' || wParam=='K'))
- {
- OnAltK();
- return 0;
- }
- if ((wParam=='d' || wParam=='D') && m_frame > 0)
- {
- ToggleDesktop();
- return 0;
- }
- break;
- case WM_CHAR:
- // if playlist is showing, steal p/j keys from the plugin:
- if (m_show_playlist)
- {
- switch (wParam)
- {
- case 'j':
- case 'J':
- m_playlist_pos = SendMessage(m_hWndWinamp,WM_USER, 0, 125);
- return 0;
- default:
- {
- int nSongs = SendMessage(m_hWndWinamp,WM_USER, 0, 124);
- int found = 0;
- int orig_pos = m_playlist_pos;
- int inc = (wParam>='A' && wParam<='Z') ? -1 : 1;
- while (1)
- {
- if (inc==1 && m_playlist_pos >= nSongs-1)
- break;
- if (inc==-1 && m_playlist_pos <= 0)
- break;
- m_playlist_pos += inc;
- char buf[32];
- strncpy(buf, (char*)SendMessage(m_hWndWinamp, WM_USER, m_playlist_pos, 212), 31);
- buf[31] = 0;
- // remove song # and period from beginning
- char *p = buf;
- while (*p >= '0' && *p <= '9') p++;
- if (*p == '.' && *(p+1) == ' ')
- {
- p += 2;
- int pos = 0;
- while (*p != 0)
- {
- buf[pos++] = *p;
- p++;
- }
- buf[pos++] = 0;
- }
- int wParam2 = (wParam>='A' && wParam<='Z') ? (wParam + 'a'-'A') : (wParam + 'A'-'a');
- if (buf[0]==wParam || buf[0]==wParam2)
- {
- found = 1;
- break;
- }
- }
- if (!found)
- m_playlist_pos = orig_pos;
- }
- return 0;
- }
- }
- // then allow the plugin to override any keys:
- if (MyWindowProc(hWnd, uMsg, wParam, lParam) == 0)
- return 0;
- // finally, default key actions:
- if (wParam == keyMappings[5] || wParam == keyMappings[6]) // 'z' or 'Z'
- {
- PostMessage(m_hWndWinamp,WM_COMMAND,40044,0);
- return 0;
- }
- else
- {
- switch (wParam)
- {
- // WINAMP PLAYBACK CONTROL KEYS:
- case 'x':
- case 'X':
- PostMessage(m_hWndWinamp,WM_COMMAND,40045,0);
- return 0;
- case 'c':
- case 'C':
- PostMessage(m_hWndWinamp,WM_COMMAND,40046,0);
- return 0;
- case 'v':
- case 'V':
- PostMessage(m_hWndWinamp,WM_COMMAND,40047,0);
- return 0;
- case 'b':
- case 'B':
- PostMessage(m_hWndWinamp,WM_COMMAND,40048,0);
- return 0;
- case 's':
- case 'S':
- //if (SendMessage(m_hWndWinamp,WM_USER,0,250))
- // sprintf(m_szUserMessage, "shuffle is now OFF"); // shuffle was on
- //else
- // sprintf(m_szUserMessage, "shuffle is now ON"); // shuffle was off
- // toggle shuffle
- PostMessage(m_hWndWinamp,WM_COMMAND,40023,0);
- return 0;
- case 'r':
- case 'R':
- // toggle repeat
- PostMessage(m_hWndWinamp,WM_COMMAND,40022,0);
- return 0;
- case 'p':
- case 'P':
- TogglePlaylist();
- return 0;
- case 'l':
- // note that this is actually correct; when you hit 'l' from the
- // MAIN winamp window, you get an "open files" dialog; when you hit
- // 'l' from the playlist editor, you get an "add files to playlist" dialog.
- // (that sends IDC_PLAYLIST_ADDMP3==1032 to the playlist, which we can't
- // do from here.)
- PostMessage(m_hWndWinamp,WM_COMMAND,40029,0);
- return 0;
- case 'L':
- PostMessage(m_hWndWinamp,WM_COMMAND,40187,0);
- return 0;
- case 'j':
- PostMessage(m_hWndWinamp,WM_COMMAND,40194,0);
- return 0;
- }
- return 0;//DefWindowProc(hWnd,uMsg,wParam,lParam);
- }
- break; // end case WM_CHAR
- case WM_KEYUP:
- // allow the plugin to override any keys:
- if (MyWindowProc(hWnd, uMsg, wParam, lParam) == 0)
- return 0;
- /*
- switch(wParam)
- {
- case VK_SOMETHING:
- ...
- break;
- }
- */
- return 0;
- break;
- case WM_KEYDOWN:
- if (m_show_playlist)
- {
- switch (wParam)
- {
- case VK_ESCAPE:
- if(m_show_playlist)
- TogglePlaylist();
- //m_show_playlist = 0;
- return 0;
- case VK_UP:
- {
- int nRepeat = lParam & 0xFFFF;
- if (GetKeyState(VK_SHIFT) & mask)
- m_playlist_pos -= 10*nRepeat;
- else
- m_playlist_pos -= nRepeat;
- }
- return 0;
- case VK_DOWN:
- {
- int nRepeat = lParam & 0xFFFF;
- if (GetKeyState(VK_SHIFT) & mask)
- m_playlist_pos += 10*nRepeat;
- else
- m_playlist_pos += nRepeat;
- }
- return 0;
- case VK_HOME:
- m_playlist_pos = 0;
- return 0;
- case VK_END:
- m_playlist_pos = SendMessage(m_hWndWinamp,WM_USER, 0, 124) - 1;
- return 0;
- case VK_PRIOR:
- if (GetKeyState(VK_SHIFT) & mask)
- m_playlist_pageups += 10;
- else
- m_playlist_pageups++;
- return 0;
- case VK_NEXT:
- if (GetKeyState(VK_SHIFT) & mask)
- m_playlist_pageups -= 10;
- else
- m_playlist_pageups--;
- return 0;
- case VK_RETURN:
- SendMessage(m_hWndWinamp,WM_USER, m_playlist_pos, 121); // set sel
- SendMessage(m_hWndWinamp,WM_COMMAND, 40045, 0); // play it
- return 0;
- }
- }
- // allow the plugin to override any keys:
- if (MyWindowProc(hWnd, uMsg, wParam, lParam) == 0)
- return 0;
- switch (wParam)
- {
- case VK_F1:
- m_show_press_f1_msg = 0;
- ToggleHelp();
- return 0;
- case VK_ESCAPE:
- if (m_show_help)
- ToggleHelp();
- else
- {
- if (m_screenmode == FAKE_FULLSCREEN || m_screenmode == FULLSCREEN)
- {
- ToggleFullScreen();
- }
- else if (m_screenmode == DESKTOP)
- {
- ToggleDesktop();
- }
- // exit the program on escape
- //m_exiting = 1;
- //PostMessage(hWnd, WM_CLOSE, 0, 0);
- }
- return 0;
- case VK_UP:
- // increase volume
- {
- int nRepeat = lParam & 0xFFFF;
- for (i=0; i<nRepeat*2; i++) PostMessage(m_hWndWinamp,WM_COMMAND,40058,0);
- }
- return 0;
- case VK_DOWN:
- // decrease volume
- {
- int nRepeat = lParam & 0xFFFF;
- for (i=0; i<nRepeat*2; i++) PostMessage(m_hWndWinamp,WM_COMMAND,40059,0);
- }
- return 0;
- case VK_LEFT:
- case VK_RIGHT:
- {
- bool bShiftHeldDown = (GetKeyState(VK_SHIFT) & mask) != 0;
- int cmd = (wParam == VK_LEFT) ? 40144 : 40148;
- int nRepeat = lParam & 0xFFFF;
- int reps = (bShiftHeldDown) ? 6*nRepeat : 1*nRepeat;
- for (int i=0; i<reps; i++)
- PostMessage(m_hWndWinamp,WM_COMMAND,cmd,0);
- }
- return 0;
- default:
- // pass CTRL+A thru CTRL+Z, and also CTRL+TAB, to winamp, *if we're in windowed mode* and using an embedded window.
- // be careful though; uppercase chars come both here AND to WM_CHAR handler,
- // so we have to eat some of them here, to avoid them from acting twice.
- if (m_screenmode==WINDOWED && m_lpDX && m_lpDX->m_current_mode.m_skin)
- {
- if (bCtrlHeldDown && ((wParam >= 'A' && wParam <= 'Z') || wParam==VK_TAB))
- {
- PostMessage(m_hWndWinamp, uMsg, wParam, lParam);
- return 0;
- }
- }
- return 0;
- }
- return 0;
- break;
- }
- return MyWindowProc(hWnd, uMsg, wParam, lParam);//DefWindowProc(hWnd, uMsg, wParam, lParam);
- //return 0L;
- }
- LRESULT CALLBACK CPluginShell::DesktopWndProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam)
- {
- CPluginShell* p = (CPluginShell*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
- if (p)
- return p->PluginShellDesktopWndProc(hWnd, uMsg, wParam, lParam);
- else
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
- }
- LRESULT CPluginShell::PluginShellDesktopWndProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam)
- {
- //#ifdef _DEBUG
- // OutputDebugMessage("kbfocus", hWnd, uMsg, wParam, lParam);
- //#endif
- switch (uMsg)
- {
- case WM_KEYDOWN:
- case WM_KEYUP:
- case WM_CHAR:
- case WM_SYSCHAR:
- case WM_SYSKEYDOWN:
- case WM_SYSKEYUP:
- //PostMessage(GetPluginWindow(), uMsg, wParam, lParam);
- PluginShellWindowProc(GetPluginWindow(), uMsg, wParam, lParam);
- return 0;
- break;
- }
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
- }
- void CPluginShell::AlignWaves()
- {
- // align waves, using recursive (mipmap-style) least-error matching
- // note: NUM_WAVEFORM_SAMPLES must be between 32 and 576.
- int align_offset[2] = { 0, 0 };
- #if (NUM_WAVEFORM_SAMPLES < 576) // [don't let this code bloat our DLL size if it's not going to be used]
- int nSamples = NUM_WAVEFORM_SAMPLES;
- #define MAX_OCTAVES 10
- int octaves = (int)floorf(logf((float)(576-nSamples))/logf(2.0f));
- if (octaves < 4)
- return;
- if (octaves > MAX_OCTAVES)
- octaves = MAX_OCTAVES;
- for (int ch=0; ch<2; ch++)
- {
- // only worry about matching the lower 'nSamples' samples
- float temp_new[MAX_OCTAVES][576];
- float temp_old[MAX_OCTAVES][576];
- static float temp_weight[MAX_OCTAVES][576];
- static int first_nonzero_weight[MAX_OCTAVES];
- static int last_nonzero_weight[MAX_OCTAVES];
- int spls[MAX_OCTAVES];
- int space[MAX_OCTAVES];
- memcpy(temp_new[0], m_sound.fWaveform[ch], sizeof(float)*576);
- memcpy(temp_old[0], &m_oldwave[ch][m_prev_align_offset[ch]], sizeof(float)*nSamples);
- spls[0] = 576;
- space[0] = 576 - nSamples;
- // potential optimization: could reuse (instead of recompute) mip levels for m_oldwave[2][]?
- int octave = 0;
- for (octave=1; octave<octaves; octave++)
- {
- spls[octave] = spls[octave-1]/2;
- space[octave] = space[octave-1]/2;
- for (int n=0; n<spls[octave]; n++)
- {
- temp_new[octave][n] = 0.5f*(temp_new[octave-1][n*2] + temp_new[octave-1][n*2+1]);
- temp_old[octave][n] = 0.5f*(temp_old[octave-1][n*2] + temp_old[octave-1][n*2+1]);
- }
- }
- if (!m_align_weights_ready)
- {
- m_align_weights_ready = 1;
- for (octave=0; octave<octaves; octave++)
- {
- int compare_samples = spls[octave] - space[octave];
- int n = 0;
- for (n=0; n<compare_samples; n++)
- {
- // start with pyramid-shaped pdf, from 0..1..0
- if (n < compare_samples/2)
- temp_weight[octave][n] = n*2/(float)compare_samples;
- else
- temp_weight[octave][n] = (compare_samples-1 - n)*2/(float)compare_samples;
- // TWEAK how much the center matters, vs. the edges:
- temp_weight[octave][n] = (temp_weight[octave][n] - 0.8f)*5.0f + 0.8f;
- // clip:
- if (temp_weight[octave][n]>1) temp_weight[octave][n] = 1;
- if (temp_weight[octave][n]<0) temp_weight[octave][n] = 0;
- }
- n = 0;
- while (temp_weight[octave][n] == 0 && n < compare_samples)
- n++;
- first_nonzero_weight[octave] = n;
- n = compare_samples-1;
- while (temp_weight[octave][n] == 0 && n >= 0)
- n--;
- last_nonzero_weight[octave] = n;
- }
- }
- int n1 = 0;
- int n2 = space[octaves-1];
- for (octave = octaves-1; octave>=0; octave--)
- {
- // for example:
- // space[octave] == 4
- // spls[octave] == 36
- // (so we test 32 samples, w/4 offsets)
- int compare_samples = spls[octave]-space[octave];
- int lowest_err_offset = -1;
- float lowest_err_amount = 0;
- for (int n=n1; n<n2; n++)
- {
- float err_sum = 0;
- //for (int i=0; i<compare_samples; i++)
- for (int i=first_nonzero_weight[octave]; i<=last_nonzero_weight[octave]; i++)
- {
- float x = (temp_new[octave][i+n] - temp_old[octave][i]) * temp_weight[octave][i];
- if (x>0)
- err_sum += x;
- else
- err_sum -= x;
- }
- if (lowest_err_offset == -1 || err_sum < lowest_err_amount)
- {
- lowest_err_offset = n;
- lowest_err_amount = err_sum;
- }
- }
- // now use 'lowest_err_offset' to guide bounds of search in next octave:
- // space[octave] == 8
- // spls[octave] == 72
- // -say 'lowest_err_offset' was 2
- // -that corresponds to samples 4 & 5 of the next octave
- // -also, expand about this by 2 samples? YES.
- // (so we'd test 64 samples, w/8->4 offsets)
- if (octave > 0)
- {
- n1 = lowest_err_offset*2 -1;
- n2 = lowest_err_offset*2+2+1;
- if (n1 < 0) n1=0;
- if (n2 > space[octave-1]) n2 = space[octave-1];
- }
- else
- align_offset[ch] = lowest_err_offset;
- }
- }
- #endif
- memcpy(m_oldwave[0], m_sound.fWaveform[0], sizeof(float)*576);
- memcpy(m_oldwave[1], m_sound.fWaveform[1], sizeof(float)*576);
- m_prev_align_offset[0] = align_offset[0];
- m_prev_align_offset[1] = align_offset[1];
- // finally, apply the results: modify m_sound.fWaveform[2][0..576]
- // by scooting the aligned samples so that they start at m_sound.fWaveform[2][0].
- for (int ch=0; ch<2; ch++)
- if (align_offset[ch]>0)
- {
- for (int i=0; i<nSamples; i++)
- m_sound.fWaveform[ch][i] = m_sound.fWaveform[ch][i+align_offset[ch]];
- // zero the rest out, so it's visually evident that these samples are now bogus:
- memset(&m_sound.fWaveform[ch][nSamples], 0, (576-nSamples)*sizeof(float));
- }
- }
- LRESULT CALLBACK CPluginShell::VJModeWndProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam)
- {
- CPluginShell* p = (CPluginShell*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
- if (p)
- return p->PluginShellVJModeWndProc(hWnd, uMsg, wParam, lParam);
- else
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
- }
- LRESULT CPluginShell::PluginShellVJModeWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- #ifdef _DEBUG
- if (message != WM_MOUSEMOVE &&
- message != WM_NCHITTEST &&
- message != WM_SETCURSOR &&
- message != WM_COPYDATA &&
- message != WM_USER)
- {
- char caption[256] = "VJWndProc: frame 0, ";
- if (m_frame > 0)
- {
- float time = m_time;
- int hours = (int)(time/3600);
- time -= hours*3600;
- int minutes = (int)(time/60);
- time -= minutes*60;
- int seconds = (int)time;
- time -= seconds;
- int dsec = (int)(time*100);
- sprintf(caption, "VJWndProc: frame %d, t=%dh:%02dm:%02d.%02ds, ", m_frame, hours, minutes, seconds, dsec);
- }
- OutputDebugMessage(caption, hwnd, message, wParam, lParam);
- }
- #endif
- switch (message)
- {
- case WM_KEYDOWN:
- case WM_KEYUP:
- case WM_CHAR:
- case WM_SYSKEYDOWN:
- case WM_SYSKEYUP:
- case WM_SYSCHAR:
- // pass keystrokes on to plugin!
- return PluginShellWindowProc(GetPluginWindow(),message,wParam,lParam);
- case WM_ERASEBKGND:
- // Repaint window when song is paused and image needs to be repainted:
- if (SendMessage(m_hWndWinamp,WM_USER,0,104)!=1 && m_vjd3d9_device && GetFrame() > 0) // WM_USER/104 return codes: 1=playing, 3=paused, other=stopped
- {
- m_vjd3d9_device->Present(NULL,NULL,NULL,NULL);
- return 0;
- }
- break;
- /*
- case WM_WINDOWPOSCHANGING:
- if (m_screenmode == DESKTOP)
- {
- LPWINDOWPOS pwp = (LPWINDOWPOS)lParam;
- if (pwp)
- pwp->flags |= SWP_NOOWNERZORDER | SWP_NOZORDER;
- }
- break;
- case WM_ACTIVATEAPP:
- // *Very Important Handler!*
- // -Without this code, the app would not work properly when running in true
- // fullscreen mode on multiple monitors; it would auto-minimize whenever the
- // user clicked on a window in another display.
- if (wParam == 1 &&
- m_screenmode == DESKTOP &&
- m_frame > 0 &&
- !m_exiting
- )
- {
- return 0;
- }
- break;
- /*
- case WM_NCACTIVATE:
- // *Very Important Handler!*
- // -Without this code, the app would not work properly when running in true
- // fullscreen mode on multiple monitors; it would auto-minimize whenever the
- // user clicked on a window in another display.
- // (NOTE: main window also handles this message this way)
- if (wParam == 0 &&
- m_screenmode == FULLSCREEN &&
- m_frame > 0 &&
- !m_exiting &&
- m_lpDX &&
- m_lpDX->m_ready
- && m_lpDX->m_lpD3D &&
- m_lpDX->m_lpD3D->GetAdapterCount() > 1
- )
- {
- return 0;
- }
- break;
- */
- /*
- case WM_ACTIVATEAPP:
- if (wParam == 1 &&
- m_screenmode == DESKTOP &&
- m_frame > 0 &&
- !m_exiting &&
- m_vjd3d9_device
- )
- {
- return 0;
- }
- break;
- */
- /*
- case WM_WINDOWPOSCHANGING:
- if (
- m_screenmode == DESKTOP
- && (!m_force_accept_WM_WINDOWPOSCHANGING)
- && m_lpDX && m_lpDX->m_ready
- )
- {
- // unless we requested it ourselves or it's init time,
- // prevent the fake desktop window from moving around
- // in the Z order! (i.e., keep it on the bottom)
-
- // without this code, when you click on the 'real' desktop
- // in a multimon setup, any windows that are overtop of the
- // 'fake' desktop will flash, since they'll be covered
- // up by the fake desktop window (but then shown again on
- // the next frame, when we detect that the fake desktop
- // window isn't on bottom & send it back to the bottom).
- LPWINDOWPOS pwp = (LPWINDOWPOS)lParam;
- if (pwp)
- pwp->flags |= SWP_NOOWNERZORDER | SWP_NOZORDER;
- }
- break;
- */
- case WM_CLOSE:
- // if they close the VJ window (by some means other than ESC key),
- // this will make the graphics window close, too.
- m_exiting = 1;
- if (GetPluginWindow())
- PostMessage(GetPluginWindow(), WM_CLOSE, 0, 0);
- break;
- case WM_GETMINMAXINFO:
- {
- // don't let the window get too small
- MINMAXINFO* p = (MINMAXINFO*)lParam;
- if (p->ptMinTrackSize.x < 64)
- p->ptMinTrackSize.x = 64;
- p->ptMinTrackSize.y = p->ptMinTrackSize.x*3/4;
- }
- return 0;
- case WM_SIZE:
- // clear or set activity flag to reflect focus
- if (m_vjd3d9_device && !m_resizing_textwnd)
- {
- m_hidden_textwnd = (SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam) ? TRUE : FALSE;
- if (SIZE_MAXIMIZED==wParam || SIZE_RESTORED==wParam) // the window has been maximized or restored
- OnUserResizeTextWindow();
- }
- break;
- case WM_ENTERSIZEMOVE:
- m_resizing_textwnd = 1;
- break;
- case WM_EXITSIZEMOVE:
- if (m_vjd3d9_device)
- OnUserResizeTextWindow();
- m_resizing_textwnd = 0;
- break;
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
- }
|