winamp/Src/Plugins/Visualization/vis_nsfs/Svis.cpp
2024-09-24 14:54:57 +02:00

892 lines
23 KiB
C++

//#define PLUGIN_NAME "Nullsoft Tiny Fullscreen"
#define PLUGIN_VERSION "v2.16"
#include <windows.h>
#include <commctrl.h>
#include <ddraw.h>
#include "resource.h"
#include "../winamp/vis.h"
#include "../winamp/wa_ipc.h"
#include "../Agave/Language/api_language.h"
#include <api/service/waServiceFactory.h>
/* global variables */
wchar_t g_title[1024]={0};
wchar_t *ini_file = 0;
HWND hwndParent = 0;
HFONT hFont = 0;
unsigned char *g_scrollbuf;
extern void do_min(HWND hwnd);
extern void do_unmin(HWND hwnd);
extern BOOL DirectMouseWheel_ProcessDialogMessage(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam);
/* wasabi based services for localisation support */
api_service *WASABI_API_SVC = 0;
api_language *WASABI_API_LNG = 0;
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
/* window procedures */
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK dlgProc1(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
/* winamp vis module functions */
static winampVisModule *getModule(int which);
static void config_write(struct winampVisModule *this_mod);
static void config_read(struct winampVisModule *this_mod);
static void config(struct winampVisModule *this_mod);
static int init(struct winampVisModule *this_mod);
static int render_sa_vp_mono(struct winampVisModule *this_mod);
static int render_sa(struct winampVisModule *this_mod);
static int render_osc(struct winampVisModule *this_mod);
static int render_osc_sa_mono(struct winampVisModule *this_mod);
static int render_super_vp(struct winampVisModule *this_mod);
static void quit(struct winampVisModule *this_mod);
/* uninitialized data (zeroed) */
DDBLTFX ddbfx;
HWND g_hwnd;
LPDIRECTDRAW lpDD;
LPDIRECTDRAWPALETTE ddp;
LPDIRECTDRAWSURFACE lpDDSPrim;
LPDIRECTDRAWSURFACE lpDDSBack;
unsigned char *fb_locked;
int scrpitch;
unsigned char last[4][4096];
int lpos;
int rpos;
unsigned char colpoints[2][6][3];
winampVisModule mod[4];
int hadjusted;
COLORREF custcolors[16];
/* initialized data */
wchar_t szAppName[] = L"NSFSVis";
winampVisHeader hdr = { VIS_HDRVER, 0, getModule };
unsigned char orig_colpoints[2][6][3] =
{
{
{ 200, 0, 0 },
{ 250, 0, 25 },
{ 243, 65, 5 },
{ 237, 163, 7 },
{ 250, 250, 0 },
{ 255, 255, 255 }
},{
{ 34, 29, 54 },
{ 251, 125, 0 },
{ 255, 160, 66 },
{ 242, 237, 21 },
{ 255, 255, 0 },
{ 255, 255, 255 },
}
};
struct
{
int w,h,nbands, hpercent,scope,scopesc;
int falloff;
int peak_falloff, peak_hold;
} configst={640,480,188,80,1,33,8,8,1};
/* function implimentations */
void sd_config(struct winampVisModule *this_mod);
int sd_init(struct winampVisModule *this_mod);
int sd_render(struct winampVisModule *this_mod);
void sd_quit(struct winampVisModule *this_mod);
extern "C" {
// do this so we can have the original hinstance of our vis for localisation
/*BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if(fdwReason == DLL_PROCESS_ATTACH)
{
visDll = hinstDLL;
DisableThreadLibraryCalls(hinstDLL);
}
return TRUE;
}*/
static HINSTANCE GetMyInstance()
{
MEMORY_BASIC_INFORMATION mbi = {0};
if(VirtualQuery(GetMyInstance, &mbi, sizeof(mbi)))
return (HINSTANCE)mbi.AllocationBase;
return NULL;
}
/* this is the only exported symbol. returns our main header. */
__declspec( dllexport ) winampVisHeader* winampVisGetHeader(HWND hwndParent)
{
static char module1[96], module2[96], module3[96], module4[96];
OSVERSIONINFO version = {0};
version.dwOSVersionInfoSize = sizeof(version);
if (!GetVersionEx(&version)) ZeroMemory(&version, sizeof(OSVERSIONINFO));
if (version.dwMajorVersion < 6 ||
(version.dwMajorVersion <= 6 && version.dwMinorVersion < 2)) // Windows 8.x+
{
if(!WASABI_API_LNG_HINST)
{
// loader so that we can get the localisation service api for use
WASABI_API_SVC = (api_service*)SendMessage(hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);
if (WASABI_API_SVC == (api_service*)1) WASABI_API_SVC = NULL;
waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(languageApiGUID);
if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
// need to have this initialised before we try to do anything with localisation features
WASABI_API_START_LANG(GetMyInstance(),VisNFSFLangGUID);
}
static char szDescription[256];
char temp[256];
wsprintfA(szDescription,"%s %s",WASABI_API_LNGSTRING_BUF(IDS_NULLSOFT_TINY_FULLSCREEN, temp, 256), PLUGIN_VERSION);
hdr.description = szDescription;
mod[1].latencyMs=1000/60;
mod[1].delayMs=5;
mod[1].spectrumNch=
mod[1].waveformNch=1;
mod[1].Init=init;
mod[1].Config=config;
mod[1].Quit=quit;
mod[1].description=WASABI_API_LNGSTRING_BUF(IDS_SEXY_SCROLLING_VOICEPRINT,module1,96);
mod[1].Render=render_super_vp;
mod[2]=mod[1];
mod[2].description=WASABI_API_LNGSTRING_BUF(IDS_SPECTRUM_ANALYZER_VOICEPRINT,module2,96);
mod[2].waveformNch--;
mod[2].Render=render_sa_vp_mono;
mod[3]=mod[1];
mod[3].description=WASABI_API_LNGSTRING_BUF(IDS_SPECTRUM_ANALYZER_OSCILLOSCOPE,module3,96);
mod[3].Render=render_osc_sa_mono;
mod[0]=mod[1];
mod[0].description=WASABI_API_LNGSTRING_BUF(IDS_RANDOM_INTELLIGENT_VISUALIZATION,module4,96);
mod[0].spectrumNch--;
mod[0].delayMs=1;
mod[0].Init=sd_init;
mod[0].Config=sd_config;
mod[0].Render=sd_render;
mod[0].Quit=sd_quit;
return &hdr;
}
return NULL;
}
};
winampVisModule *getModule(int which)
{
OSVERSIONINFO version = {0};
version.dwOSVersionInfoSize = sizeof(version);
if (!GetVersionEx(&version)) ZeroMemory(&version, sizeof(OSVERSIONINFO));
if (version.dwMajorVersion < 6 ||
(version.dwMajorVersion <= 6 && version.dwMinorVersion < 2)) // Windows 8.x+
{
if (which < 4 && which >= 0) return mod+which;
}
return 0;
}
/* configuration. Passed this_mod, as a "this" parameter. Allows you to make one configuration
function that shares code for all your modules (you don't HAVE to use it though, you can make
config1(), config2(), etc...)
*/
void config(struct winampVisModule *this_mod)
{
config_read(this_mod);
if (WASABI_API_DIALOGBOXW(IDD_DIALOG1,this_mod->hwndParent,dlgProc1) == IDOK)
config_write(this_mod);
}
int DD_Init(int this_w, int this_h, PALETTEENTRY *palette)
{
DDSURFACEDESC DDsd;
DDSCAPS ddscaps;
DDsd.dwSize = sizeof(DDsd);
DDsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
DDsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP;
DDsd.dwBackBufferCount = 1;
ddbfx.dwSize=sizeof(ddbfx);
if (DirectDrawCreate(NULL,&lpDD,NULL) != DD_OK)
{
lpDD=0;
return 1;
}
if (IDirectDraw_SetCooperativeLevel(lpDD,g_hwnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN) != DD_OK ||
IDirectDraw_SetDisplayMode(lpDD,this_w,this_h,8) != DD_OK ||
IDirectDraw_CreateSurface(lpDD,&DDsd, &lpDDSPrim, NULL) != DD_OK)
{
IDirectDraw_Release(lpDD);
lpDD=0;
return 1;
}
IDirectDrawSurface_GetSurfaceDesc(lpDDSPrim,&DDsd);
scrpitch = DDsd.lPitch;
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
if (IDirectDrawSurface_GetAttachedSurface(lpDDSPrim,&ddscaps, &lpDDSBack) != DD_OK)
{
IDirectDraw_Release(lpDD);
lpDD=0;
return 1;
}
if (IDirectDraw_CreatePalette(lpDD,DDPCAPS_8BIT|DDPCAPS_ALLOW256,palette,&ddp,NULL) == DD_OK)
IDirectDrawSurface_SetPalette(lpDDSPrim,ddp);
{
RECT r1={0,0,this_w,this_h};
RECT r2=r1;
IDirectDrawSurface_Blt(lpDDSBack,&r1,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
IDirectDrawSurface_Blt(lpDDSPrim,&r2,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
}
fb_locked=0;
return 0;
}
void initwindow(struct winampVisModule *this_mod, int w, int h)
{
if (SendMessage(this_mod->hwndParent,WM_WA_IPC,0,IPC_IS_PLAYING_VIDEO)>1)
{
g_hwnd=0;
MessageBox(this_mod->hwndParent,
WASABI_API_LNGSTRING(IDS_CANNOT_GO_FULLSCREEN_WHEN_VIDEO_PLAYING),
hdr.description,MB_OK|MB_ICONINFORMATION);
return;
}
WNDCLASSW wc={0,WndProc,0,0,this_mod->hDllInstance,0,0,(HBRUSH)GetStockObject(BLACK_BRUSH),0,szAppName};
UnregisterClassW(szAppName,this_mod->hDllInstance);
RegisterClassW(&wc);
hwndParent=this_mod->hwndParent;
g_hwnd = CreateWindowEx(WS_EX_APPWINDOW|WS_EX_TOPMOST,"NSFSVis",this_mod->description,
WS_VISIBLE|WS_POPUP|WS_SYSMENU,0,0,w,h,hwndParent,NULL,
this_mod->hDllInstance,0);
SendMessage(this_mod->hwndParent, WM_WA_IPC, (WPARAM)g_hwnd, IPC_SETVISWND);
}
int init(struct winampVisModule *this_mod)
{
PALETTEENTRY palette[256];
int x,e,a;
config_read(this_mod);
initwindow(this_mod,configst.w,configst.h);
if (!g_hwnd)
{
return 1;
}
SetTimer(g_hwnd,0,1000,NULL);
{
char *t=(char*)palette;
int x=sizeof(palette);
while (x--) *t++=0;
}
palette[255].peRed=palette[255].peGreen=palette[255].peBlue=255;
palette[254].peRed=colpoints[0][5][0];
palette[254].peGreen=colpoints[0][5][1];
palette[254].peBlue=colpoints[0][5][2];
palette[253].peRed=colpoints[1][5][0];
palette[253].peGreen=colpoints[1][5][1];
palette[253].peBlue=colpoints[1][5][2];
if (this_mod == mod+1)
{
PALETTEENTRY *p=palette+1;
unsigned char *t=colpoints[1][0];
for (a = 0; a < 4; a ++)
{
int dr, dg, db;
int r=*t++;
int g=*t++;
int b=*t++;
dr=((t[0]-r)<<16)/60;
dg=((t[1]-g)<<16)/60;
db=((t[2]-b)<<16)/60;
r<<=16;
g<<=16;
b<<=16;
for (x = 0; x < 60; x ++)
{
p->peRed = r>>16;
p->peGreen = g>>16;
p->peBlue = b>>16;
r+=dr;g+=dg;b+=db;
p++;
}
}
}
else
{
PALETTEENTRY *p=palette+1;
unsigned char *t=colpoints[0][0];
for (e = 0; e < 3; e ++)
{
for (a = 0; a < 4; a ++)
{
int dr, dg, db;
int r=*t++;
int g=*t++;
int b=*t++;
dr=(t[0]-r);
dg=(t[1]-g);
db=(t[2]-b);
r<<=4;
g<<=4;
b<<=4;
for (x = 0; x < 16; x ++)
{
p->peRed = r>>4;
p->peGreen = g>>4;
p->peBlue = b>>4;
r+=dr;g+=dg;b+=db;
p++;
}
}
t+=3*2;
}
}
do_min(this_mod->hwndParent);
if (DD_Init(configst.w,configst.h,palette))
{
DestroyWindow(g_hwnd);
do_unmin(this_mod->hwndParent);
return 1;
}
char *t=(char*)last;
int y=sizeof(last);
while (y--) *t++=0;
hadjusted=((configst.h)*configst.hpercent)/100;
if (hadjusted>configst.h) hadjusted=configst.h;
if (hadjusted < 1) hadjusted=1;
if (this_mod == mod+1) g_scrollbuf = (unsigned char *)GlobalAlloc(GPTR,configst.w*hadjusted);
else g_scrollbuf = (unsigned char *)GlobalAlloc(GPTR,hadjusted);
if (!g_scrollbuf)
{
IDirectDraw_Release(lpDD);
lpDD=0;
DestroyWindow(g_hwnd);
do_unmin(this_mod->hwndParent);
return 1;
}
return 0;
}
unsigned char *DD_Enter(int l, int t, int r, int b)
{
int h;
DDSURFACEDESC d={sizeof(d),};
RECT r2={l,t,r,b};
if (fb_locked) return fb_locked;
if (l<r && t<b) IDirectDrawSurface_Blt(lpDDSBack,&r2,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
if ((h = IDirectDrawSurface_Lock(lpDDSBack,NULL,&d,DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY,NULL)) != DD_OK)
{
if (h == DDERR_SURFACELOST)
{
IDirectDrawSurface_Restore(lpDDSPrim);
}
return 0;
}
return (fb_locked = (unsigned char *) d.lpSurface);
}
void DD_Unlock(int w, int transparent)
{
if (fb_locked)
{
HDC hdc;
RECT r1={0,0,w,32};
RECT r3=r1;
IDirectDrawSurface_Unlock(lpDDSBack,fb_locked);
fb_locked=0;
if (!transparent) IDirectDrawSurface_Blt(lpDDSBack,&r1,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
if (IDirectDrawSurface_GetDC(lpDDSBack,&hdc) == DD_OK)
{
if (!transparent) SetBkColor(hdc,0);
else SetBkMode(hdc,TRANSPARENT);
SetTextColor(hdc,RGB(255,255,255));
HFONT oldfont = (HFONT)SelectObject(hdc,hFont);
DrawTextW(hdc,g_title,-1,&r3,DT_CENTER|DT_TOP|DT_SINGLELINE);
SelectObject(hdc,oldfont);
IDirectDrawSurface_ReleaseDC(lpDDSBack,hdc);
}
IDirectDrawSurface_Flip(lpDDSPrim,NULL, DDFLIP_WAIT);
}
}
void _render_analyzer(struct winampVisModule *this_mod, int hdiv)
{
int x;
int pos;
int dpos;
unsigned char *sd=this_mod->spectrumData[0];
unsigned char *sb;
int len=min(configst.w,4096);
sb=fb_locked+scrpitch*(configst.h-1);
pos=0;
dpos=(400<<16)/configst.w;
for (x = 0; x < len; x ++)
{
unsigned char *f = sb++;
int c = 2;
int lo=0;
int lv=last[0][x]-configst.falloff*2;
int ipos=(pos>>16);
int l = (((int)sd[ipos+1])*((pos&0xffff)) + ((int)sd[ipos ])*(0x10000-(pos&0xffff)))>>16;
l = l*(ipos+40)/80;
l>>=hdiv;
if (l > (128>>hdiv)-1) l = (128>>hdiv)-1;
pos+=dpos;
if (configst.peak_hold)
{
if ((int)last[2][x]+configst.peak_falloff < 255) last[2][x]+=configst.peak_falloff;
else last[2][x]=255;
if (last[3][x] < last[2][x]/32) last[3][x]=0;
else last[3][x]-=last[2][x]/32;
if (l*2 > last[3][x])
{
last[2][x]=0;
last[3][x]=l*2;
}
if (last[3][x]/2 >= l) lo=(-(int)last[3][x]/2)*scrpitch;
}
if (l < lv) l = lv;
last[0][x]= l;
while (l--)
{
f[0] = c/2;
c+=1+hdiv;
f -= scrpitch;
}
if (lo) sb[lo-1]=254;
}
}
void _render_scope(struct winampVisModule *this_mod, int hr)
{
int x;
unsigned char *wd=this_mod->waveformData[0];
int scsc;
int pos,dpos,lastv;
unsigned char *sb;
scsc=(configst.scopesc*hr)/100;
if (scsc < 1) scsc=1;
if (scsc > hr) scsc=hr;
sb=fb_locked+scrpitch*(configst.h/2-scsc/2);
lastv=-1;
pos=0;
dpos=(575<<16)/configst.w;
for (x = 0; x < configst.w; x ++)
{
int tv = (((int)wd[(pos>>16)+1]^128)*((pos&0xffff)) + ((int)wd[(pos>>16)] ^128)*(0x10000-(pos&0xffff)))>>16;
tv=(tv*scsc)>>8;
pos+=dpos;
if (lastv<0) lastv=tv;
if (tv==lastv) sb[scrpitch*lastv]=253;
else
{
while (tv < lastv) sb[scrpitch*lastv--]=253;
while (tv > lastv) sb[scrpitch*lastv++]=253;
}
sb++;
}
}
int render_super_vp(struct winampVisModule *this_mod)
{
int tb=min(configst.nbands,511);
int sy=((configst.h-hadjusted)/2);
unsigned char *src=&this_mod->spectrumData[0][tb];
unsigned char *op;
unsigned char *p1=g_scrollbuf;
unsigned char *p2=g_scrollbuf+configst.w;
unsigned int pos=0;
unsigned int dpos=(tb<<16)/hadjusted;
if (!g_scrollbuf || !DD_Enter(0,0,configst.w,min(sy,32))) return 0;
op=fb_locked+sy*scrpitch;
int y=hadjusted/2;
while (y--)
{
int x=configst.w-1;
while (x--)
{
*p1++=p1[1];
*p2++=p2[1];
}
x = (((int)src[0 - (pos>>16)])*((pos&0xffff)) + ((int)src[1 - (pos>>16)])*(0x10000-(pos&0xffff)))>>16;
pos+=dpos;
if (++x > 240) x = 240;
*p1++ = x;
x = (((int)src[0 - (pos>>16)])*((pos&0xffff)) + ((int)src[1 - (pos>>16)])*(0x10000-(pos&0xffff)))>>16;
pos+=dpos;
if (++x > 240) x = 240;
*p2++ = x;
memcpy(op,p1-configst.w,configst.w);
op+=scrpitch;
memcpy(op,p2-configst.w,configst.w);
op+=scrpitch;
p1+=configst.w;
p2+=configst.w;
}
if (configst.scope) _render_scope(this_mod,hadjusted);
DD_Unlock(configst.w,1);
return 0;
}
int render_sa_vp_mono(struct winampVisModule *this_mod)
{
int x;
unsigned char *sd=this_mod->spectrumData[0];
unsigned char *b3,*b1,*b2;
int pos=0;
int vsize=hadjusted;
int dpos=(min(configst.nbands,511)<<16)/vsize;
if (!DD_Enter(0,configst.h-64,configst.w,configst.h)) return 0;
if (vsize > configst.h-32-64) vsize=configst.h-32-64;
b1 = fb_locked + scrpitch*((configst.h-32-64)/2+32+vsize/2) + lpos;
b2 = b1+rpos-lpos;
_render_analyzer(this_mod,1);
for (x = 0; x < vsize; x ++)
{
b1[0] = g_scrollbuf[x];
b1-=scrpitch;
}
if (rpos < configst.w-2) b3 = b2+1;
else b3 = b2 - (configst.w-2);
for (x = 0; x < vsize; x++)
{
int ipos=(pos>>16);
int l = (((int)sd[ipos+1])*((pos&0xffff)) + ((int)sd[ipos]) *(0x10000-(pos&0xffff)))>>16;
l=(l*240)/1024;
pos+=dpos;
if (l > 63) l = 63;
l+=65;
b2[0]=l;
g_scrollbuf[x]=l;
b2-=scrpitch;
b3[0] = 255;
b3-=scrpitch;
}
lpos=rpos;
if (++rpos >= configst.w) rpos -= configst.w;
DD_Unlock(configst.w,0);
return 0;
}
int render_osc_sa_mono(struct winampVisModule *this_mod)
{
if (!DD_Enter(0,0,configst.w,configst.h)) return 0;
_render_analyzer(this_mod,0);
_render_scope(this_mod,configst.h);
DD_Unlock(configst.w,1);
return 0;
}
/*
cleanup (opposite of init()). Destroys the window, unregisters the window class
*/
void quit(struct winampVisModule *this_mod)
{
IDirectDrawSurface_Release(lpDDSPrim);
IDirectDraw_Release(lpDD);
DestroyWindow(g_hwnd);
if (g_scrollbuf) GlobalFree(g_scrollbuf);
g_scrollbuf=0;
UnregisterClassW(szAppName,this_mod->hDllInstance);
do_unmin(this_mod->hwndParent);
}
/*
window procedure for our window
*/
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_CREATE){
if(hFont) DeleteObject(hFont);
HDC hdc = GetDC(hwnd);
hFont = CreateFontW(-MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72),
0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, 0, 0, L"Arial");
ReleaseDC(hwnd,hdc);
}
else if (message == WM_PAINT)
{
PAINTSTRUCT ps = {0};
HDC hdc = BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
}
else if (message == WM_KEYUP || message == WM_KEYDOWN)
{
if (wParam == VK_ESCAPE) DestroyWindow(hwnd);
else
{
PostMessage(hwndParent,message,wParam,lParam);
}
}
else if (message ==WM_USER+1666)
{
if (wParam == 1 && lParam == 15)
{
DestroyWindow(hwnd);
}
return 0;
}
else if (message == WM_DESTROY)
{
SendMessage(hwndParent, WM_WA_IPC, 0, IPC_SETVISWND);
if(hFont) DeleteObject(hFont);
PostQuitMessage(0);
}
else if (message == WM_TIMER)
{
g_title[0] = 0;
GetWindowTextW(hwndParent,g_title,sizeof(g_title)-1-32);
wchar_t *p = g_title;
while (p && *p) p = CharNextW(p); p = CharPrevW(g_title,p);
while (p >= g_title)
{
if (p[0] == L'-' && p[1] == L' ' && p[2] == L'W' && p[3] == L'i') break;
p = CharPrevW(g_title,p);
}
if (p >= g_title)
{
wchar_t *e=p;
while (e && *e && *e != L'[') e = CharNextW(e);
while (p >= g_title && *p == L' ') p = CharPrevW(g_title,p);
if (p < g_title) p = CharNextW(p);
*(p = CharNextW(p)) = L' ';
*p = 0;
if (e && *e)
{
int n=29;
while (e && *e && n--)
{
*p = *e;
p = CharNextW(p);
e = CharNextW(e);
}
*p = 0;
}
}
else g_title[0]=0;
LRESULT t = (SendMessage(hwndParent,WM_USER,0,105) + 500) / 1000;
if (t)
{
p = g_title;
while (p && *p) p = CharNextW(p);
LRESULT tt = (SendMessage(hwndParent,WM_USER,1,105)*1000);
if(tt > 0){
int length = tt/=1000,
minutes = length/60,
seconds = length - (minutes*60);
wsprintfW(p,L" [%d:%02d / %d:%02d]",t/60,t%60,minutes,seconds);
}
else{
wsprintfW(p,L" [%d:%02d / %d:%02d]",t/60,t%60);
}
}
// if we did not get a time then remove the '-' on the end
else{
*(p = CharPrevW(g_title,p)) = 0;
}
}
else if (message == WM_SETCURSOR) SetCursor(NULL);
else return DefWindowProc(hwnd,message,wParam,lParam);
return 0;
}
void init_inifile(struct winampVisModule *this_mod)
{
ini_file = (wchar_t*)SendMessage(this_mod->hwndParent,WM_WA_IPC,0,IPC_GETINIFILEW);
}
static void config_read(struct winampVisModule *this_mod)
{
init_inifile(this_mod);
if (!GetPrivateProfileStructW(szAppName,L"colors",colpoints,sizeof(colpoints),ini_file))
{
int x=sizeof(colpoints);
char *i=(char*)orig_colpoints, *o=(char*)colpoints;
while (x--) *o++=*i++;
}
GetPrivateProfileStructW(szAppName,L"config",&configst,sizeof(configst),ini_file);
}
void config_write(struct winampVisModule *this_mod)
{
init_inifile(this_mod);
WritePrivateProfileStructW(szAppName,L"colors",colpoints,sizeof(colpoints),ini_file);
WritePrivateProfileStructW(szAppName,L"config",&configst,sizeof(configst),ini_file);
}
void do_vprintcol(HWND hwndDlg, unsigned char *t)
{
CHOOSECOLORW cs={sizeof(cs),hwndDlg,};
cs.hInstance = 0;
cs.rgbResult=t[0] | (t[1]<<8) | (t[2]<<16);
cs.lpCustColors = custcolors;
cs.Flags = CC_RGBINIT|CC_FULLOPEN;
if (ChooseColorW(&cs))
{
t[0] = (unsigned char) cs.rgbResult;
t[1] = (unsigned char) (cs.rgbResult>>8);
t[2] = (unsigned char) (cs.rgbResult>>16);
InvalidateRect(hwndDlg,NULL,0);
}
}
static HRESULT WINAPI _cb(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
{
if (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==8)
{
wchar_t s[32] = {0};
wsprintfW(s, L"%dx%d", lpDDSurfaceDesc->dwWidth, lpDDSurfaceDesc->dwHeight);
LRESULT idx = SendMessageW((HWND)lpContext,CB_ADDSTRING,0,(LPARAM)s);
SendMessage((HWND)lpContext,CB_SETITEMDATA,idx,MAKELONG(lpDDSurfaceDesc->dwWidth,lpDDSurfaceDesc->dwHeight));
if ((int)lpDDSurfaceDesc->dwWidth == configst.w && (int)lpDDSurfaceDesc->dwHeight == configst.h)
SendMessage((HWND)lpContext,CB_SETCURSEL,idx,0);
}
return DDENUMRET_OK;
}
static INT_PTR CALLBACK dlgProc1(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
{
if (uMsg == WM_DRAWITEM)
{
DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
unsigned char *thiscol=NULL;
if (di->CtlID >= IDC_AP1 && di->CtlID <= IDC_VP6) thiscol=colpoints[0][di->CtlID-IDC_AP1];
if (thiscol)
{
HBRUSH b, ob;
RECT r;
GetClientRect(di->hwndItem,&r);
b = CreateSolidBrush(thiscol[0] | (thiscol[1]<<8) | (thiscol[2]<<16));
ob = (HBRUSH) SelectObject(di->hDC,b);
Rectangle(di->hDC,r.left,r.top,r.right,r.bottom);
SelectObject(di->hDC,ob);
DeleteObject(b);
}
}
if (uMsg == WM_INITDIALOG)
{
SetWindowText(hwndDlg,hdr.description);
if (configst.peak_hold) CheckDlgButton(hwndDlg,IDC_CHECK1,BST_CHECKED);
SendDlgItemMessage(hwndDlg,IDC_FALLOFF,TBM_SETRANGE,0,MAKELONG(1,40));
SendDlgItemMessage(hwndDlg,IDC_FALLOFF,TBM_SETPOS,1,configst.falloff);
SendDlgItemMessage(hwndDlg,IDC_FALLOFF2,TBM_SETRANGE,0,MAKELONG(1,40));
SendDlgItemMessage(hwndDlg,IDC_FALLOFF2,TBM_SETPOS,1,configst.peak_falloff);
{
LPDIRECTDRAW dd;
if (DirectDrawCreate(NULL,&dd,NULL) == DD_OK)
{
IDirectDraw_EnumDisplayModes(dd,0,NULL,GetDlgItem(hwndDlg,IDC_MODELIST),_cb);
IDirectDraw_Release(dd);
}
SendDlgItemMessage(hwndDlg,IDC_BANDS,TBM_SETRANGE,0,MAKELONG(30,511));
SendDlgItemMessage(hwndDlg,IDC_BANDS,TBM_SETPOS,1,configst.nbands);
SendDlgItemMessage(hwndDlg,IDC_SCSCALE,TBM_SETRANGE,0,MAKELONG(1,100));
SendDlgItemMessage(hwndDlg,IDC_SCSCALE,TBM_SETPOS,1,configst.scopesc);
SendDlgItemMessage(hwndDlg,IDC_VUSE,TBM_SETRANGE,0,MAKELONG(1,100));
SendDlgItemMessage(hwndDlg,IDC_VUSE,TBM_SETPOS,1,configst.hpercent);
if (configst.scope) CheckDlgButton(hwndDlg,IDC_SCOPE,BST_CHECKED);
}
}
if (uMsg == WM_CLOSE)
{
uMsg=WM_COMMAND;
wParam=IDCANCEL;
}
if (uMsg == WM_COMMAND)
{
int w=LOWORD(wParam);
if (w == IDOK || w == IDCANCEL)
{
configst.falloff = SendDlgItemMessage(hwndDlg,IDC_FALLOFF,TBM_GETPOS,0,0);
configst.peak_falloff = SendDlgItemMessage(hwndDlg,IDC_FALLOFF2,TBM_GETPOS,0,0);
configst.peak_hold=!!IsDlgButtonChecked(hwndDlg,IDC_CHECK1);
configst.scope=IsDlgButtonChecked(hwndDlg,IDC_SCOPE)?1:0;
configst.scopesc = SendDlgItemMessage(hwndDlg,IDC_SCSCALE,TBM_GETPOS,0,0);
configst.nbands = SendDlgItemMessage(hwndDlg,IDC_BANDS,TBM_GETPOS,0,0);
configst.hpercent = SendDlgItemMessage(hwndDlg,IDC_VUSE,TBM_GETPOS,0,0);
EndDialog(hwndDlg,w);
}
if (w == IDC_MODELIST && HIWORD(wParam) == CBN_SELCHANGE)
{
DWORD n=SendDlgItemMessage(hwndDlg,IDC_MODELIST,CB_GETCURSEL,0,0);
if (n != CB_ERR)
{
n=SendDlgItemMessage(hwndDlg,IDC_MODELIST,CB_GETITEMDATA,n,0);
if (n != CB_ERR)
{
configst.w=LOWORD(n);
configst.h=HIWORD(n);
}
}
}
if (w == IDC_DEFVP || w == IDC_DEFAP)
{
int p=(w != IDC_DEFAP);
int x=sizeof(colpoints)/2;
char *i=(char*)orig_colpoints[p], *o=(char*)colpoints[p];
if (p) x-=3;
while (x--) *o++=*i++;
InvalidateRect(hwndDlg,NULL,FALSE);
}
if (w >= IDC_AP1 && w <= IDC_VP6) do_vprintcol(hwndDlg,colpoints[0][w-IDC_AP1]);
}
if (FALSE != DirectMouseWheel_ProcessDialogMessage(hwndDlg, uMsg, wParam, lParam))
{
return TRUE;
}
return 0;
}