1
0

Svis.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. //#define PLUGIN_NAME "Nullsoft Tiny Fullscreen"
  2. #define PLUGIN_VERSION "v2.16"
  3. #include <windows.h>
  4. #include <commctrl.h>
  5. #include <ddraw.h>
  6. #include "resource.h"
  7. #include "../winamp/vis.h"
  8. #include "../winamp/wa_ipc.h"
  9. #include "../Agave/Language/api_language.h"
  10. #include <api/service/waServiceFactory.h>
  11. /* global variables */
  12. wchar_t g_title[1024]={0};
  13. wchar_t *ini_file = 0;
  14. HWND hwndParent = 0;
  15. HFONT hFont = 0;
  16. unsigned char *g_scrollbuf;
  17. extern void do_min(HWND hwnd);
  18. extern void do_unmin(HWND hwnd);
  19. extern BOOL DirectMouseWheel_ProcessDialogMessage(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam);
  20. /* wasabi based services for localisation support */
  21. api_service *WASABI_API_SVC = 0;
  22. api_language *WASABI_API_LNG = 0;
  23. HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
  24. /* window procedures */
  25. static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  26. static INT_PTR CALLBACK dlgProc1(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  27. /* winamp vis module functions */
  28. static winampVisModule *getModule(int which);
  29. static void config_write(struct winampVisModule *this_mod);
  30. static void config_read(struct winampVisModule *this_mod);
  31. static void config(struct winampVisModule *this_mod);
  32. static int init(struct winampVisModule *this_mod);
  33. static int render_sa_vp_mono(struct winampVisModule *this_mod);
  34. static int render_sa(struct winampVisModule *this_mod);
  35. static int render_osc(struct winampVisModule *this_mod);
  36. static int render_osc_sa_mono(struct winampVisModule *this_mod);
  37. static int render_super_vp(struct winampVisModule *this_mod);
  38. static void quit(struct winampVisModule *this_mod);
  39. /* uninitialized data (zeroed) */
  40. DDBLTFX ddbfx;
  41. HWND g_hwnd;
  42. LPDIRECTDRAW lpDD;
  43. LPDIRECTDRAWPALETTE ddp;
  44. LPDIRECTDRAWSURFACE lpDDSPrim;
  45. LPDIRECTDRAWSURFACE lpDDSBack;
  46. unsigned char *fb_locked;
  47. int scrpitch;
  48. unsigned char last[4][4096];
  49. int lpos;
  50. int rpos;
  51. unsigned char colpoints[2][6][3];
  52. winampVisModule mod[4];
  53. int hadjusted;
  54. COLORREF custcolors[16];
  55. /* initialized data */
  56. wchar_t szAppName[] = L"NSFSVis";
  57. winampVisHeader hdr = { VIS_HDRVER, 0, getModule };
  58. unsigned char orig_colpoints[2][6][3] =
  59. {
  60. {
  61. { 200, 0, 0 },
  62. { 250, 0, 25 },
  63. { 243, 65, 5 },
  64. { 237, 163, 7 },
  65. { 250, 250, 0 },
  66. { 255, 255, 255 }
  67. },{
  68. { 34, 29, 54 },
  69. { 251, 125, 0 },
  70. { 255, 160, 66 },
  71. { 242, 237, 21 },
  72. { 255, 255, 0 },
  73. { 255, 255, 255 },
  74. }
  75. };
  76. struct
  77. {
  78. int w,h,nbands, hpercent,scope,scopesc;
  79. int falloff;
  80. int peak_falloff, peak_hold;
  81. } configst={640,480,188,80,1,33,8,8,1};
  82. /* function implimentations */
  83. void sd_config(struct winampVisModule *this_mod);
  84. int sd_init(struct winampVisModule *this_mod);
  85. int sd_render(struct winampVisModule *this_mod);
  86. void sd_quit(struct winampVisModule *this_mod);
  87. extern "C" {
  88. // do this so we can have the original hinstance of our vis for localisation
  89. /*BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
  90. {
  91. if(fdwReason == DLL_PROCESS_ATTACH)
  92. {
  93. visDll = hinstDLL;
  94. DisableThreadLibraryCalls(hinstDLL);
  95. }
  96. return TRUE;
  97. }*/
  98. static HINSTANCE GetMyInstance()
  99. {
  100. MEMORY_BASIC_INFORMATION mbi = {0};
  101. if(VirtualQuery(GetMyInstance, &mbi, sizeof(mbi)))
  102. return (HINSTANCE)mbi.AllocationBase;
  103. return NULL;
  104. }
  105. /* this is the only exported symbol. returns our main header. */
  106. __declspec( dllexport ) winampVisHeader* winampVisGetHeader(HWND hwndParent)
  107. {
  108. static char module1[96], module2[96], module3[96], module4[96];
  109. OSVERSIONINFO version = {0};
  110. version.dwOSVersionInfoSize = sizeof(version);
  111. if (!GetVersionEx(&version)) ZeroMemory(&version, sizeof(OSVERSIONINFO));
  112. if (version.dwMajorVersion < 6 ||
  113. (version.dwMajorVersion <= 6 && version.dwMinorVersion < 2)) // Windows 8.x+
  114. {
  115. if(!WASABI_API_LNG_HINST)
  116. {
  117. // loader so that we can get the localisation service api for use
  118. WASABI_API_SVC = (api_service*)SendMessage(hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);
  119. if (WASABI_API_SVC == (api_service*)1) WASABI_API_SVC = NULL;
  120. waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(languageApiGUID);
  121. if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
  122. // need to have this initialised before we try to do anything with localisation features
  123. WASABI_API_START_LANG(GetMyInstance(),VisNFSFLangGUID);
  124. }
  125. static char szDescription[256];
  126. char temp[256];
  127. wsprintfA(szDescription,"%s %s",WASABI_API_LNGSTRING_BUF(IDS_NULLSOFT_TINY_FULLSCREEN, temp, 256), PLUGIN_VERSION);
  128. hdr.description = szDescription;
  129. mod[1].latencyMs=1000/60;
  130. mod[1].delayMs=5;
  131. mod[1].spectrumNch=
  132. mod[1].waveformNch=1;
  133. mod[1].Init=init;
  134. mod[1].Config=config;
  135. mod[1].Quit=quit;
  136. mod[1].description=WASABI_API_LNGSTRING_BUF(IDS_SEXY_SCROLLING_VOICEPRINT,module1,96);
  137. mod[1].Render=render_super_vp;
  138. mod[2]=mod[1];
  139. mod[2].description=WASABI_API_LNGSTRING_BUF(IDS_SPECTRUM_ANALYZER_VOICEPRINT,module2,96);
  140. mod[2].waveformNch--;
  141. mod[2].Render=render_sa_vp_mono;
  142. mod[3]=mod[1];
  143. mod[3].description=WASABI_API_LNGSTRING_BUF(IDS_SPECTRUM_ANALYZER_OSCILLOSCOPE,module3,96);
  144. mod[3].Render=render_osc_sa_mono;
  145. mod[0]=mod[1];
  146. mod[0].description=WASABI_API_LNGSTRING_BUF(IDS_RANDOM_INTELLIGENT_VISUALIZATION,module4,96);
  147. mod[0].spectrumNch--;
  148. mod[0].delayMs=1;
  149. mod[0].Init=sd_init;
  150. mod[0].Config=sd_config;
  151. mod[0].Render=sd_render;
  152. mod[0].Quit=sd_quit;
  153. return &hdr;
  154. }
  155. return NULL;
  156. }
  157. };
  158. winampVisModule *getModule(int which)
  159. {
  160. OSVERSIONINFO version = {0};
  161. version.dwOSVersionInfoSize = sizeof(version);
  162. if (!GetVersionEx(&version)) ZeroMemory(&version, sizeof(OSVERSIONINFO));
  163. if (version.dwMajorVersion < 6 ||
  164. (version.dwMajorVersion <= 6 && version.dwMinorVersion < 2)) // Windows 8.x+
  165. {
  166. if (which < 4 && which >= 0) return mod+which;
  167. }
  168. return 0;
  169. }
  170. /* configuration. Passed this_mod, as a "this" parameter. Allows you to make one configuration
  171. function that shares code for all your modules (you don't HAVE to use it though, you can make
  172. config1(), config2(), etc...)
  173. */
  174. void config(struct winampVisModule *this_mod)
  175. {
  176. config_read(this_mod);
  177. if (WASABI_API_DIALOGBOXW(IDD_DIALOG1,this_mod->hwndParent,dlgProc1) == IDOK)
  178. config_write(this_mod);
  179. }
  180. int DD_Init(int this_w, int this_h, PALETTEENTRY *palette)
  181. {
  182. DDSURFACEDESC DDsd;
  183. DDSCAPS ddscaps;
  184. DDsd.dwSize = sizeof(DDsd);
  185. DDsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
  186. DDsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP;
  187. DDsd.dwBackBufferCount = 1;
  188. ddbfx.dwSize=sizeof(ddbfx);
  189. if (DirectDrawCreate(NULL,&lpDD,NULL) != DD_OK)
  190. {
  191. lpDD=0;
  192. return 1;
  193. }
  194. if (IDirectDraw_SetCooperativeLevel(lpDD,g_hwnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN) != DD_OK ||
  195. IDirectDraw_SetDisplayMode(lpDD,this_w,this_h,8) != DD_OK ||
  196. IDirectDraw_CreateSurface(lpDD,&DDsd, &lpDDSPrim, NULL) != DD_OK)
  197. {
  198. IDirectDraw_Release(lpDD);
  199. lpDD=0;
  200. return 1;
  201. }
  202. IDirectDrawSurface_GetSurfaceDesc(lpDDSPrim,&DDsd);
  203. scrpitch = DDsd.lPitch;
  204. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  205. if (IDirectDrawSurface_GetAttachedSurface(lpDDSPrim,&ddscaps, &lpDDSBack) != DD_OK)
  206. {
  207. IDirectDraw_Release(lpDD);
  208. lpDD=0;
  209. return 1;
  210. }
  211. if (IDirectDraw_CreatePalette(lpDD,DDPCAPS_8BIT|DDPCAPS_ALLOW256,palette,&ddp,NULL) == DD_OK)
  212. IDirectDrawSurface_SetPalette(lpDDSPrim,ddp);
  213. {
  214. RECT r1={0,0,this_w,this_h};
  215. RECT r2=r1;
  216. IDirectDrawSurface_Blt(lpDDSBack,&r1,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  217. IDirectDrawSurface_Blt(lpDDSPrim,&r2,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  218. }
  219. fb_locked=0;
  220. return 0;
  221. }
  222. void initwindow(struct winampVisModule *this_mod, int w, int h)
  223. {
  224. if (SendMessage(this_mod->hwndParent,WM_WA_IPC,0,IPC_IS_PLAYING_VIDEO)>1)
  225. {
  226. g_hwnd=0;
  227. MessageBox(this_mod->hwndParent,
  228. WASABI_API_LNGSTRING(IDS_CANNOT_GO_FULLSCREEN_WHEN_VIDEO_PLAYING),
  229. hdr.description,MB_OK|MB_ICONINFORMATION);
  230. return;
  231. }
  232. WNDCLASSW wc={0,WndProc,0,0,this_mod->hDllInstance,0,0,(HBRUSH)GetStockObject(BLACK_BRUSH),0,szAppName};
  233. UnregisterClassW(szAppName,this_mod->hDllInstance);
  234. RegisterClassW(&wc);
  235. hwndParent=this_mod->hwndParent;
  236. g_hwnd = CreateWindowEx(WS_EX_APPWINDOW|WS_EX_TOPMOST,"NSFSVis",this_mod->description,
  237. WS_VISIBLE|WS_POPUP|WS_SYSMENU,0,0,w,h,hwndParent,NULL,
  238. this_mod->hDllInstance,0);
  239. SendMessage(this_mod->hwndParent, WM_WA_IPC, (WPARAM)g_hwnd, IPC_SETVISWND);
  240. }
  241. int init(struct winampVisModule *this_mod)
  242. {
  243. PALETTEENTRY palette[256];
  244. int x,e,a;
  245. config_read(this_mod);
  246. initwindow(this_mod,configst.w,configst.h);
  247. if (!g_hwnd)
  248. {
  249. return 1;
  250. }
  251. SetTimer(g_hwnd,0,1000,NULL);
  252. {
  253. char *t=(char*)palette;
  254. int x=sizeof(palette);
  255. while (x--) *t++=0;
  256. }
  257. palette[255].peRed=palette[255].peGreen=palette[255].peBlue=255;
  258. palette[254].peRed=colpoints[0][5][0];
  259. palette[254].peGreen=colpoints[0][5][1];
  260. palette[254].peBlue=colpoints[0][5][2];
  261. palette[253].peRed=colpoints[1][5][0];
  262. palette[253].peGreen=colpoints[1][5][1];
  263. palette[253].peBlue=colpoints[1][5][2];
  264. if (this_mod == mod+1)
  265. {
  266. PALETTEENTRY *p=palette+1;
  267. unsigned char *t=colpoints[1][0];
  268. for (a = 0; a < 4; a ++)
  269. {
  270. int dr, dg, db;
  271. int r=*t++;
  272. int g=*t++;
  273. int b=*t++;
  274. dr=((t[0]-r)<<16)/60;
  275. dg=((t[1]-g)<<16)/60;
  276. db=((t[2]-b)<<16)/60;
  277. r<<=16;
  278. g<<=16;
  279. b<<=16;
  280. for (x = 0; x < 60; x ++)
  281. {
  282. p->peRed = r>>16;
  283. p->peGreen = g>>16;
  284. p->peBlue = b>>16;
  285. r+=dr;g+=dg;b+=db;
  286. p++;
  287. }
  288. }
  289. }
  290. else
  291. {
  292. PALETTEENTRY *p=palette+1;
  293. unsigned char *t=colpoints[0][0];
  294. for (e = 0; e < 3; e ++)
  295. {
  296. for (a = 0; a < 4; a ++)
  297. {
  298. int dr, dg, db;
  299. int r=*t++;
  300. int g=*t++;
  301. int b=*t++;
  302. dr=(t[0]-r);
  303. dg=(t[1]-g);
  304. db=(t[2]-b);
  305. r<<=4;
  306. g<<=4;
  307. b<<=4;
  308. for (x = 0; x < 16; x ++)
  309. {
  310. p->peRed = r>>4;
  311. p->peGreen = g>>4;
  312. p->peBlue = b>>4;
  313. r+=dr;g+=dg;b+=db;
  314. p++;
  315. }
  316. }
  317. t+=3*2;
  318. }
  319. }
  320. do_min(this_mod->hwndParent);
  321. if (DD_Init(configst.w,configst.h,palette))
  322. {
  323. DestroyWindow(g_hwnd);
  324. do_unmin(this_mod->hwndParent);
  325. return 1;
  326. }
  327. char *t=(char*)last;
  328. int y=sizeof(last);
  329. while (y--) *t++=0;
  330. hadjusted=((configst.h)*configst.hpercent)/100;
  331. if (hadjusted>configst.h) hadjusted=configst.h;
  332. if (hadjusted < 1) hadjusted=1;
  333. if (this_mod == mod+1) g_scrollbuf = (unsigned char *)GlobalAlloc(GPTR,configst.w*hadjusted);
  334. else g_scrollbuf = (unsigned char *)GlobalAlloc(GPTR,hadjusted);
  335. if (!g_scrollbuf)
  336. {
  337. IDirectDraw_Release(lpDD);
  338. lpDD=0;
  339. DestroyWindow(g_hwnd);
  340. do_unmin(this_mod->hwndParent);
  341. return 1;
  342. }
  343. return 0;
  344. }
  345. unsigned char *DD_Enter(int l, int t, int r, int b)
  346. {
  347. int h;
  348. DDSURFACEDESC d={sizeof(d),};
  349. RECT r2={l,t,r,b};
  350. if (fb_locked) return fb_locked;
  351. if (l<r && t<b) IDirectDrawSurface_Blt(lpDDSBack,&r2,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  352. if ((h = IDirectDrawSurface_Lock(lpDDSBack,NULL,&d,DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY,NULL)) != DD_OK)
  353. {
  354. if (h == DDERR_SURFACELOST)
  355. {
  356. IDirectDrawSurface_Restore(lpDDSPrim);
  357. }
  358. return 0;
  359. }
  360. return (fb_locked = (unsigned char *) d.lpSurface);
  361. }
  362. void DD_Unlock(int w, int transparent)
  363. {
  364. if (fb_locked)
  365. {
  366. HDC hdc;
  367. RECT r1={0,0,w,32};
  368. RECT r3=r1;
  369. IDirectDrawSurface_Unlock(lpDDSBack,fb_locked);
  370. fb_locked=0;
  371. if (!transparent) IDirectDrawSurface_Blt(lpDDSBack,&r1,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  372. if (IDirectDrawSurface_GetDC(lpDDSBack,&hdc) == DD_OK)
  373. {
  374. if (!transparent) SetBkColor(hdc,0);
  375. else SetBkMode(hdc,TRANSPARENT);
  376. SetTextColor(hdc,RGB(255,255,255));
  377. HFONT oldfont = (HFONT)SelectObject(hdc,hFont);
  378. DrawTextW(hdc,g_title,-1,&r3,DT_CENTER|DT_TOP|DT_SINGLELINE);
  379. SelectObject(hdc,oldfont);
  380. IDirectDrawSurface_ReleaseDC(lpDDSBack,hdc);
  381. }
  382. IDirectDrawSurface_Flip(lpDDSPrim,NULL, DDFLIP_WAIT);
  383. }
  384. }
  385. void _render_analyzer(struct winampVisModule *this_mod, int hdiv)
  386. {
  387. int x;
  388. int pos;
  389. int dpos;
  390. unsigned char *sd=this_mod->spectrumData[0];
  391. unsigned char *sb;
  392. int len=min(configst.w,4096);
  393. sb=fb_locked+scrpitch*(configst.h-1);
  394. pos=0;
  395. dpos=(400<<16)/configst.w;
  396. for (x = 0; x < len; x ++)
  397. {
  398. unsigned char *f = sb++;
  399. int c = 2;
  400. int lo=0;
  401. int lv=last[0][x]-configst.falloff*2;
  402. int ipos=(pos>>16);
  403. int l = (((int)sd[ipos+1])*((pos&0xffff)) + ((int)sd[ipos ])*(0x10000-(pos&0xffff)))>>16;
  404. l = l*(ipos+40)/80;
  405. l>>=hdiv;
  406. if (l > (128>>hdiv)-1) l = (128>>hdiv)-1;
  407. pos+=dpos;
  408. if (configst.peak_hold)
  409. {
  410. if ((int)last[2][x]+configst.peak_falloff < 255) last[2][x]+=configst.peak_falloff;
  411. else last[2][x]=255;
  412. if (last[3][x] < last[2][x]/32) last[3][x]=0;
  413. else last[3][x]-=last[2][x]/32;
  414. if (l*2 > last[3][x])
  415. {
  416. last[2][x]=0;
  417. last[3][x]=l*2;
  418. }
  419. if (last[3][x]/2 >= l) lo=(-(int)last[3][x]/2)*scrpitch;
  420. }
  421. if (l < lv) l = lv;
  422. last[0][x]= l;
  423. while (l--)
  424. {
  425. f[0] = c/2;
  426. c+=1+hdiv;
  427. f -= scrpitch;
  428. }
  429. if (lo) sb[lo-1]=254;
  430. }
  431. }
  432. void _render_scope(struct winampVisModule *this_mod, int hr)
  433. {
  434. int x;
  435. unsigned char *wd=this_mod->waveformData[0];
  436. int scsc;
  437. int pos,dpos,lastv;
  438. unsigned char *sb;
  439. scsc=(configst.scopesc*hr)/100;
  440. if (scsc < 1) scsc=1;
  441. if (scsc > hr) scsc=hr;
  442. sb=fb_locked+scrpitch*(configst.h/2-scsc/2);
  443. lastv=-1;
  444. pos=0;
  445. dpos=(575<<16)/configst.w;
  446. for (x = 0; x < configst.w; x ++)
  447. {
  448. int tv = (((int)wd[(pos>>16)+1]^128)*((pos&0xffff)) + ((int)wd[(pos>>16)] ^128)*(0x10000-(pos&0xffff)))>>16;
  449. tv=(tv*scsc)>>8;
  450. pos+=dpos;
  451. if (lastv<0) lastv=tv;
  452. if (tv==lastv) sb[scrpitch*lastv]=253;
  453. else
  454. {
  455. while (tv < lastv) sb[scrpitch*lastv--]=253;
  456. while (tv > lastv) sb[scrpitch*lastv++]=253;
  457. }
  458. sb++;
  459. }
  460. }
  461. int render_super_vp(struct winampVisModule *this_mod)
  462. {
  463. int tb=min(configst.nbands,511);
  464. int sy=((configst.h-hadjusted)/2);
  465. unsigned char *src=&this_mod->spectrumData[0][tb];
  466. unsigned char *op;
  467. unsigned char *p1=g_scrollbuf;
  468. unsigned char *p2=g_scrollbuf+configst.w;
  469. unsigned int pos=0;
  470. unsigned int dpos=(tb<<16)/hadjusted;
  471. if (!g_scrollbuf || !DD_Enter(0,0,configst.w,min(sy,32))) return 0;
  472. op=fb_locked+sy*scrpitch;
  473. int y=hadjusted/2;
  474. while (y--)
  475. {
  476. int x=configst.w-1;
  477. while (x--)
  478. {
  479. *p1++=p1[1];
  480. *p2++=p2[1];
  481. }
  482. x = (((int)src[0 - (pos>>16)])*((pos&0xffff)) + ((int)src[1 - (pos>>16)])*(0x10000-(pos&0xffff)))>>16;
  483. pos+=dpos;
  484. if (++x > 240) x = 240;
  485. *p1++ = x;
  486. x = (((int)src[0 - (pos>>16)])*((pos&0xffff)) + ((int)src[1 - (pos>>16)])*(0x10000-(pos&0xffff)))>>16;
  487. pos+=dpos;
  488. if (++x > 240) x = 240;
  489. *p2++ = x;
  490. memcpy(op,p1-configst.w,configst.w);
  491. op+=scrpitch;
  492. memcpy(op,p2-configst.w,configst.w);
  493. op+=scrpitch;
  494. p1+=configst.w;
  495. p2+=configst.w;
  496. }
  497. if (configst.scope) _render_scope(this_mod,hadjusted);
  498. DD_Unlock(configst.w,1);
  499. return 0;
  500. }
  501. int render_sa_vp_mono(struct winampVisModule *this_mod)
  502. {
  503. int x;
  504. unsigned char *sd=this_mod->spectrumData[0];
  505. unsigned char *b3,*b1,*b2;
  506. int pos=0;
  507. int vsize=hadjusted;
  508. int dpos=(min(configst.nbands,511)<<16)/vsize;
  509. if (!DD_Enter(0,configst.h-64,configst.w,configst.h)) return 0;
  510. if (vsize > configst.h-32-64) vsize=configst.h-32-64;
  511. b1 = fb_locked + scrpitch*((configst.h-32-64)/2+32+vsize/2) + lpos;
  512. b2 = b1+rpos-lpos;
  513. _render_analyzer(this_mod,1);
  514. for (x = 0; x < vsize; x ++)
  515. {
  516. b1[0] = g_scrollbuf[x];
  517. b1-=scrpitch;
  518. }
  519. if (rpos < configst.w-2) b3 = b2+1;
  520. else b3 = b2 - (configst.w-2);
  521. for (x = 0; x < vsize; x++)
  522. {
  523. int ipos=(pos>>16);
  524. int l = (((int)sd[ipos+1])*((pos&0xffff)) + ((int)sd[ipos]) *(0x10000-(pos&0xffff)))>>16;
  525. l=(l*240)/1024;
  526. pos+=dpos;
  527. if (l > 63) l = 63;
  528. l+=65;
  529. b2[0]=l;
  530. g_scrollbuf[x]=l;
  531. b2-=scrpitch;
  532. b3[0] = 255;
  533. b3-=scrpitch;
  534. }
  535. lpos=rpos;
  536. if (++rpos >= configst.w) rpos -= configst.w;
  537. DD_Unlock(configst.w,0);
  538. return 0;
  539. }
  540. int render_osc_sa_mono(struct winampVisModule *this_mod)
  541. {
  542. if (!DD_Enter(0,0,configst.w,configst.h)) return 0;
  543. _render_analyzer(this_mod,0);
  544. _render_scope(this_mod,configst.h);
  545. DD_Unlock(configst.w,1);
  546. return 0;
  547. }
  548. /*
  549. cleanup (opposite of init()). Destroys the window, unregisters the window class
  550. */
  551. void quit(struct winampVisModule *this_mod)
  552. {
  553. IDirectDrawSurface_Release(lpDDSPrim);
  554. IDirectDraw_Release(lpDD);
  555. DestroyWindow(g_hwnd);
  556. if (g_scrollbuf) GlobalFree(g_scrollbuf);
  557. g_scrollbuf=0;
  558. UnregisterClassW(szAppName,this_mod->hDllInstance);
  559. do_unmin(this_mod->hwndParent);
  560. }
  561. /*
  562. window procedure for our window
  563. */
  564. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  565. {
  566. if (message == WM_CREATE){
  567. if(hFont) DeleteObject(hFont);
  568. HDC hdc = GetDC(hwnd);
  569. hFont = CreateFontW(-MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72),
  570. 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, 0, 0, L"Arial");
  571. ReleaseDC(hwnd,hdc);
  572. }
  573. else if (message == WM_PAINT)
  574. {
  575. PAINTSTRUCT ps = {0};
  576. HDC hdc = BeginPaint(hwnd,&ps);
  577. EndPaint(hwnd,&ps);
  578. }
  579. else if (message == WM_KEYUP || message == WM_KEYDOWN)
  580. {
  581. if (wParam == VK_ESCAPE) DestroyWindow(hwnd);
  582. else
  583. {
  584. PostMessage(hwndParent,message,wParam,lParam);
  585. }
  586. }
  587. else if (message ==WM_USER+1666)
  588. {
  589. if (wParam == 1 && lParam == 15)
  590. {
  591. DestroyWindow(hwnd);
  592. }
  593. return 0;
  594. }
  595. else if (message == WM_DESTROY)
  596. {
  597. SendMessage(hwndParent, WM_WA_IPC, 0, IPC_SETVISWND);
  598. if(hFont) DeleteObject(hFont);
  599. PostQuitMessage(0);
  600. }
  601. else if (message == WM_TIMER)
  602. {
  603. g_title[0] = 0;
  604. GetWindowTextW(hwndParent,g_title,sizeof(g_title)-1-32);
  605. wchar_t *p = g_title;
  606. while (p && *p) p = CharNextW(p); p = CharPrevW(g_title,p);
  607. while (p >= g_title)
  608. {
  609. if (p[0] == L'-' && p[1] == L' ' && p[2] == L'W' && p[3] == L'i') break;
  610. p = CharPrevW(g_title,p);
  611. }
  612. if (p >= g_title)
  613. {
  614. wchar_t *e=p;
  615. while (e && *e && *e != L'[') e = CharNextW(e);
  616. while (p >= g_title && *p == L' ') p = CharPrevW(g_title,p);
  617. if (p < g_title) p = CharNextW(p);
  618. *(p = CharNextW(p)) = L' ';
  619. *p = 0;
  620. if (e && *e)
  621. {
  622. int n=29;
  623. while (e && *e && n--)
  624. {
  625. *p = *e;
  626. p = CharNextW(p);
  627. e = CharNextW(e);
  628. }
  629. *p = 0;
  630. }
  631. }
  632. else g_title[0]=0;
  633. LRESULT t = (SendMessage(hwndParent,WM_USER,0,105) + 500) / 1000;
  634. if (t)
  635. {
  636. p = g_title;
  637. while (p && *p) p = CharNextW(p);
  638. LRESULT tt = (SendMessage(hwndParent,WM_USER,1,105)*1000);
  639. if(tt > 0){
  640. int length = tt/=1000,
  641. minutes = length/60,
  642. seconds = length - (minutes*60);
  643. wsprintfW(p,L" [%d:%02d / %d:%02d]",t/60,t%60,minutes,seconds);
  644. }
  645. else{
  646. wsprintfW(p,L" [%d:%02d / %d:%02d]",t/60,t%60);
  647. }
  648. }
  649. // if we did not get a time then remove the '-' on the end
  650. else{
  651. *(p = CharPrevW(g_title,p)) = 0;
  652. }
  653. }
  654. else if (message == WM_SETCURSOR) SetCursor(NULL);
  655. else return DefWindowProc(hwnd,message,wParam,lParam);
  656. return 0;
  657. }
  658. void init_inifile(struct winampVisModule *this_mod)
  659. {
  660. ini_file = (wchar_t*)SendMessage(this_mod->hwndParent,WM_WA_IPC,0,IPC_GETINIFILEW);
  661. }
  662. static void config_read(struct winampVisModule *this_mod)
  663. {
  664. init_inifile(this_mod);
  665. if (!GetPrivateProfileStructW(szAppName,L"colors",colpoints,sizeof(colpoints),ini_file))
  666. {
  667. int x=sizeof(colpoints);
  668. char *i=(char*)orig_colpoints, *o=(char*)colpoints;
  669. while (x--) *o++=*i++;
  670. }
  671. GetPrivateProfileStructW(szAppName,L"config",&configst,sizeof(configst),ini_file);
  672. }
  673. void config_write(struct winampVisModule *this_mod)
  674. {
  675. init_inifile(this_mod);
  676. WritePrivateProfileStructW(szAppName,L"colors",colpoints,sizeof(colpoints),ini_file);
  677. WritePrivateProfileStructW(szAppName,L"config",&configst,sizeof(configst),ini_file);
  678. }
  679. void do_vprintcol(HWND hwndDlg, unsigned char *t)
  680. {
  681. CHOOSECOLORW cs={sizeof(cs),hwndDlg,};
  682. cs.hInstance = 0;
  683. cs.rgbResult=t[0] | (t[1]<<8) | (t[2]<<16);
  684. cs.lpCustColors = custcolors;
  685. cs.Flags = CC_RGBINIT|CC_FULLOPEN;
  686. if (ChooseColorW(&cs))
  687. {
  688. t[0] = (unsigned char) cs.rgbResult;
  689. t[1] = (unsigned char) (cs.rgbResult>>8);
  690. t[2] = (unsigned char) (cs.rgbResult>>16);
  691. InvalidateRect(hwndDlg,NULL,0);
  692. }
  693. }
  694. static HRESULT WINAPI _cb(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
  695. {
  696. if (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==8)
  697. {
  698. wchar_t s[32] = {0};
  699. wsprintfW(s, L"%dx%d", lpDDSurfaceDesc->dwWidth, lpDDSurfaceDesc->dwHeight);
  700. LRESULT idx = SendMessageW((HWND)lpContext,CB_ADDSTRING,0,(LPARAM)s);
  701. SendMessage((HWND)lpContext,CB_SETITEMDATA,idx,MAKELONG(lpDDSurfaceDesc->dwWidth,lpDDSurfaceDesc->dwHeight));
  702. if ((int)lpDDSurfaceDesc->dwWidth == configst.w && (int)lpDDSurfaceDesc->dwHeight == configst.h)
  703. SendMessage((HWND)lpContext,CB_SETCURSEL,idx,0);
  704. }
  705. return DDENUMRET_OK;
  706. }
  707. static INT_PTR CALLBACK dlgProc1(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  708. {
  709. if (uMsg == WM_DRAWITEM)
  710. {
  711. DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
  712. unsigned char *thiscol=NULL;
  713. if (di->CtlID >= IDC_AP1 && di->CtlID <= IDC_VP6) thiscol=colpoints[0][di->CtlID-IDC_AP1];
  714. if (thiscol)
  715. {
  716. HBRUSH b, ob;
  717. RECT r;
  718. GetClientRect(di->hwndItem,&r);
  719. b = CreateSolidBrush(thiscol[0] | (thiscol[1]<<8) | (thiscol[2]<<16));
  720. ob = (HBRUSH) SelectObject(di->hDC,b);
  721. Rectangle(di->hDC,r.left,r.top,r.right,r.bottom);
  722. SelectObject(di->hDC,ob);
  723. DeleteObject(b);
  724. }
  725. }
  726. if (uMsg == WM_INITDIALOG)
  727. {
  728. SetWindowText(hwndDlg,hdr.description);
  729. if (configst.peak_hold) CheckDlgButton(hwndDlg,IDC_CHECK1,BST_CHECKED);
  730. SendDlgItemMessage(hwndDlg,IDC_FALLOFF,TBM_SETRANGE,0,MAKELONG(1,40));
  731. SendDlgItemMessage(hwndDlg,IDC_FALLOFF,TBM_SETPOS,1,configst.falloff);
  732. SendDlgItemMessage(hwndDlg,IDC_FALLOFF2,TBM_SETRANGE,0,MAKELONG(1,40));
  733. SendDlgItemMessage(hwndDlg,IDC_FALLOFF2,TBM_SETPOS,1,configst.peak_falloff);
  734. {
  735. LPDIRECTDRAW dd;
  736. if (DirectDrawCreate(NULL,&dd,NULL) == DD_OK)
  737. {
  738. IDirectDraw_EnumDisplayModes(dd,0,NULL,GetDlgItem(hwndDlg,IDC_MODELIST),_cb);
  739. IDirectDraw_Release(dd);
  740. }
  741. SendDlgItemMessage(hwndDlg,IDC_BANDS,TBM_SETRANGE,0,MAKELONG(30,511));
  742. SendDlgItemMessage(hwndDlg,IDC_BANDS,TBM_SETPOS,1,configst.nbands);
  743. SendDlgItemMessage(hwndDlg,IDC_SCSCALE,TBM_SETRANGE,0,MAKELONG(1,100));
  744. SendDlgItemMessage(hwndDlg,IDC_SCSCALE,TBM_SETPOS,1,configst.scopesc);
  745. SendDlgItemMessage(hwndDlg,IDC_VUSE,TBM_SETRANGE,0,MAKELONG(1,100));
  746. SendDlgItemMessage(hwndDlg,IDC_VUSE,TBM_SETPOS,1,configst.hpercent);
  747. if (configst.scope) CheckDlgButton(hwndDlg,IDC_SCOPE,BST_CHECKED);
  748. }
  749. }
  750. if (uMsg == WM_CLOSE)
  751. {
  752. uMsg=WM_COMMAND;
  753. wParam=IDCANCEL;
  754. }
  755. if (uMsg == WM_COMMAND)
  756. {
  757. int w=LOWORD(wParam);
  758. if (w == IDOK || w == IDCANCEL)
  759. {
  760. configst.falloff = SendDlgItemMessage(hwndDlg,IDC_FALLOFF,TBM_GETPOS,0,0);
  761. configst.peak_falloff = SendDlgItemMessage(hwndDlg,IDC_FALLOFF2,TBM_GETPOS,0,0);
  762. configst.peak_hold=!!IsDlgButtonChecked(hwndDlg,IDC_CHECK1);
  763. configst.scope=IsDlgButtonChecked(hwndDlg,IDC_SCOPE)?1:0;
  764. configst.scopesc = SendDlgItemMessage(hwndDlg,IDC_SCSCALE,TBM_GETPOS,0,0);
  765. configst.nbands = SendDlgItemMessage(hwndDlg,IDC_BANDS,TBM_GETPOS,0,0);
  766. configst.hpercent = SendDlgItemMessage(hwndDlg,IDC_VUSE,TBM_GETPOS,0,0);
  767. EndDialog(hwndDlg,w);
  768. }
  769. if (w == IDC_MODELIST && HIWORD(wParam) == CBN_SELCHANGE)
  770. {
  771. DWORD n=SendDlgItemMessage(hwndDlg,IDC_MODELIST,CB_GETCURSEL,0,0);
  772. if (n != CB_ERR)
  773. {
  774. n=SendDlgItemMessage(hwndDlg,IDC_MODELIST,CB_GETITEMDATA,n,0);
  775. if (n != CB_ERR)
  776. {
  777. configst.w=LOWORD(n);
  778. configst.h=HIWORD(n);
  779. }
  780. }
  781. }
  782. if (w == IDC_DEFVP || w == IDC_DEFAP)
  783. {
  784. int p=(w != IDC_DEFAP);
  785. int x=sizeof(colpoints)/2;
  786. char *i=(char*)orig_colpoints[p], *o=(char*)colpoints[p];
  787. if (p) x-=3;
  788. while (x--) *o++=*i++;
  789. InvalidateRect(hwndDlg,NULL,FALSE);
  790. }
  791. if (w >= IDC_AP1 && w <= IDC_VP6) do_vprintcol(hwndDlg,colpoints[0][w-IDC_AP1]);
  792. }
  793. if (FALSE != DirectMouseWheel_ProcessDialogMessage(hwndDlg, uMsg, wParam, lParam))
  794. {
  795. return TRUE;
  796. }
  797. return 0;
  798. }