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

318 lines
8.2 KiB
C++

#include <windows.h>
#include <commctrl.h>
#include <ddraw.h>
#include <math.h>
#include "../Winamp/wa_ipc.h"
#include "resource.h"
#include "../Agave/Language/api_language.h"
#include <api/service/waServiceFactory.h>
#include "dd.h"
#include "../winamp/vis.h"
int (*warand)(void)=0;
extern wchar_t szAppName[];
extern void init_inifile(struct winampVisModule *this_mod);
extern wchar_t *ini_file;
static int g_width=640, g_height=480;
static int g_divx=16, g_divy=12, g_fadeout=2;
static C_DD g_dd;
extern HWND g_hwnd,hwndParent;
static int running;
int g_minflag;
extern api_service *WASABI_API_SVC;
void do_min(HWND hwnd)
{
g_minflag=!IsIconic(hwnd);
if (g_minflag)
{
ShowWindow(hwnd,SW_MINIMIZE);
Sleep(100);
}
}
void do_unmin(HWND hwnd)
{
if (g_minflag)
{
g_minflag=0;
ShowWindow(hwnd,SW_RESTORE);
SetForegroundWindow(hwnd);
}
}
static void readconfig(struct winampVisModule *this_mod)
{
init_inifile(this_mod);
g_width=GetPrivateProfileIntW(szAppName, L"sdwidth", 640, ini_file);
g_height=GetPrivateProfileIntW(szAppName, L"sdheight", 480, ini_file);
g_divx=GetPrivateProfileIntW(szAppName, L"sdx", 16, ini_file);
g_divy=GetPrivateProfileIntW(szAppName, L"sdy", 12, ini_file);
g_fadeout=GetPrivateProfileIntW(szAppName, L"sdfadeout", 2, ini_file);
}
extern void drawscope(unsigned char *out, int w, int h, unsigned char *visdata);
extern unsigned char *getnewpalette();
extern void moveframe_init(int w, int h, int divx, int divy, int fadeval);
extern void moveframe(unsigned char *in, unsigned char *out, unsigned char *visdata);
extern void moveframe_quit();
static void writeInt(wchar_t *name, int value)
{
wchar_t buf[32] = {0};
wsprintfW(buf, L"%d", value);
WritePrivateProfileStringW(szAppName, name, buf, ini_file);
}
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 == g_width && (int)lpDDSurfaceDesc->dwHeight == g_height)
SendMessage((HWND)lpContext,CB_SETCURSEL,idx,0);
}
return DDENUMRET_OK;
}
BOOL IsDirectMouseWheelMessage(const UINT uMsg)
{
static UINT WINAMP_WM_DIRECT_MOUSE_WHEEL = WM_NULL;
if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL)
{
WINAMP_WM_DIRECT_MOUSE_WHEEL = RegisterWindowMessageW(L"WINAMP_WM_DIRECT_MOUSE_WHEEL");
if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL)
return FALSE;
}
return (WINAMP_WM_DIRECT_MOUSE_WHEEL == uMsg);
}
HWND ActiveChildWindowFromPoint(HWND hwnd, POINTS cursor_s, const int *controls, size_t controlsCount)
{
POINT pt;
POINTSTOPOINT(pt, cursor_s);
while(controlsCount--)
{
RECT controlRect;
HWND controlWindow = GetDlgItem(hwnd, controls[controlsCount]);
if (NULL != controlWindow &&
FALSE != GetClientRect(controlWindow, &controlRect))
{
MapWindowPoints(controlWindow, HWND_DESKTOP, (POINT*)&controlRect, 2);
if (FALSE != PtInRect(&controlRect, pt))
{
unsigned long windowStyle;
windowStyle = (unsigned long)GetWindowLongPtrW(controlWindow, GWL_STYLE);
if(WS_VISIBLE == ((WS_VISIBLE | WS_DISABLED) & windowStyle))
return controlWindow;
break;
}
}
}
return NULL;
}
BOOL DirectMouseWheel_ProcessDialogMessage(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
{
if (FALSE != IsDirectMouseWheelMessage(uMsg))
{
const int controls[] =
{
IDC_BANDS,
IDC_VUSE,
IDC_FALLOFF,
IDC_FALLOFF2,
IDC_SCSCALE,
IDC_SLIDER1,
};
HWND targetWindow = ActiveChildWindowFromPoint(hwnd, MAKEPOINTS(lParam), controls, ARRAYSIZE(controls));
if (NULL != targetWindow)
{
SendMessage(targetWindow, WM_MOUSEWHEEL, wParam, lParam);
SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (long)TRUE);
return TRUE;
}
}
return FALSE;
}
static INT_PTR CALLBACK dlgProc1(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
{
if (uMsg == WM_INITDIALOG)
{
LPDIRECTDRAW dd;
if (DirectDrawCreate(NULL,&dd,NULL) == DD_OK)
{
IDirectDraw_EnumDisplayModes(dd,0,NULL,GetDlgItem(hwndDlg,IDC_MODELIST),_cb);
IDirectDraw_Release(dd);
}
SetDlgItemInt(hwndDlg,IDC_EDIT1,g_divx,0);
SetDlgItemInt(hwndDlg,IDC_EDIT2,g_divy,0);
SendDlgItemMessage(hwndDlg,IDC_SLIDER1,TBM_SETRANGE,0,MAKELONG(0,32));
SendDlgItemMessage(hwndDlg,IDC_SLIDER1,TBM_SETPOS,1,g_fadeout);
return 1;
}
if (uMsg == WM_CLOSE || (uMsg == WM_COMMAND && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)))
{
BOOL t;
g_divx=GetDlgItemInt(hwndDlg,IDC_EDIT1,&t,0);
g_divy=GetDlgItemInt(hwndDlg,IDC_EDIT2,&t,0);
g_fadeout = SendDlgItemMessage(hwndDlg,IDC_SLIDER1,TBM_GETPOS,0,0);
EndDialog(hwndDlg,IDOK);
}
if (uMsg == WM_COMMAND)
{
if (LOWORD(wParam) == 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)
{
g_width=LOWORD(n);
g_height=HIWORD(n);
}
}
}
}
if (FALSE != DirectMouseWheel_ProcessDialogMessage(hwndDlg, uMsg, wParam, lParam))
{
return TRUE;
}
return 0;
}
void sd_config(struct winampVisModule *this_mod)
{
if (running) return;
running=1;
readconfig(this_mod);
// loader so that we can get the localisation service api for use
WASABI_API_SVC = (api_service*)SendMessage(this_mod->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(this_mod->hDllInstance,VisNFSFLangGUID);
WASABI_API_DIALOGBOXW(IDD_DIALOG2,this_mod->hwndParent,dlgProc1);
writeInt(L"sdwidth", g_width);
writeInt(L"sdheight", g_height);
writeInt(L"sdx", g_divx);
writeInt(L"sdy", g_divy);
writeInt(L"sdfadeout", g_fadeout);
running=0;
}
static int __inline is_mmx(void) {
_asm {
sub eax, eax
sub edx, edx
inc eax
_emit 0x0f
_emit 0xa2
test eax, eax
jz noMMX
and edx, 0x800000
mov eax, edx
noMMX:
sub ebx, ebx // make sure compiler knows ebx and ecx are blown.
sub ecx, ecx
}
}
int sd_init(struct winampVisModule *this_mod)
{
if (running) return 1;
running=1;
if (!is_mmx())
{
char err[16];
running=0;
MessageBox(this_mod->hwndParent,WASABI_API_LNGSTRING(IDS_MMX_NOT_FOUND),
WASABI_API_LNGSTRING_BUF(IDS_ERROR,err,16),MB_OK);
return 1;
}
readconfig(this_mod);
warand = (int (*)())SendMessage(this_mod->hwndParent, WM_WA_IPC, 0, IPC_GET_RANDFUNC);
extern void initwindow(struct winampVisModule *this_mod,int,int);
initwindow(this_mod,g_width,g_height);
if (!g_hwnd)
{
running=0;
return 1;
}
do_min(this_mod->hwndParent);
SetForegroundWindow(g_hwnd);
char *t=g_dd.open(g_width,g_height,g_hwnd);
if (t)
{
char error[32];
DestroyWindow(g_hwnd);
g_hwnd=NULL;
do_unmin(this_mod->hwndParent);
UnregisterClassW(szAppName,this_mod->hDllInstance);
MessageBox(this_mod->hwndParent,t,WASABI_API_LNGSTRING_BUF(IDS_DIRECTDRAW_ERROR,error,32),MB_OK);
running=0;
return 1;
}
moveframe_init(g_width,g_height,g_divx,g_divy,g_fadeout);
g_dd.setpalette(getnewpalette(),5000);
return 0;
}
// render function. This draws a frame. Returns 0 if successful, 1 if visualization should end.
int sd_render(struct winampVisModule *this_mod)
{
unsigned char *in, *out;
if (g_dd.palette_fadeleft() < -500)
{
g_dd.setpalette(getnewpalette(),3500);
}
if (!g_dd.lock(&in,&out)) return 0;
moveframe(in,out,this_mod->waveformData[0]);
drawscope(out,g_width,g_height,this_mod->waveformData[0]);
g_dd.unlock();
return 0;
}
// cleanup (opposite of init()). Destroys the window, unregisters the window class
void sd_quit(struct winampVisModule *this_mod)
{
g_dd.close();
moveframe_quit();
ShowCursor(TRUE);
if (g_hwnd) DestroyWindow(g_hwnd);
g_hwnd=0;
UnregisterClassW(szAppName,this_mod->hDllInstance);
running=0;
do_unmin(this_mod->hwndParent);
}