aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Visualization/vis_avs/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Plugins/Visualization/vis_avs/main.cpp')
-rw-r--r--Src/Plugins/Visualization/vis_avs/main.cpp604
1 files changed, 604 insertions, 0 deletions
diff --git a/Src/Plugins/Visualization/vis_avs/main.cpp b/Src/Plugins/Visualization/vis_avs/main.cpp
new file mode 100644
index 00000000..05b16d5c
--- /dev/null
+++ b/Src/Plugins/Visualization/vis_avs/main.cpp
@@ -0,0 +1,604 @@
+/*
+ LICENSE
+ -------
+Copyright 2005 Nullsoft, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of Nullsoft nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+#include <windows.h>
+#include <math.h>
+#include <process.h>
+#include "draw.h"
+#include "wnd.h"
+#include "r_defs.h"
+#include "render.h"
+#include "vis.h"
+#include "cfgwnd.h"
+#include "resource.h"
+#include "bpm.h"
+#include "api.h"
+#include "../winamp/wa_ipc.h"
+#include "../Agave/Language/api_language.h"
+#include <api/service/waServiceFactory.h>
+
+#include <stdio.h>
+
+#ifdef REAPLAY_PLUGIN
+#include "../../jmde/reaper_plugin.h"
+const char *(*get_ini_file)();
+int (*vuGetVisData)(char *vdata, int size);
+#endif
+
+#define PLUGIN_VERSION "v2.93"
+
+#include "avs_eelif.h"
+
+extern void GetClientRect_adj(HWND hwnd, RECT *r);
+
+static unsigned char g_logtab[256];
+HINSTANCE g_hInstance;
+
+/* char *verstr=
+#ifndef LASER
+"Advanced Visualization Studio"
+#else
+"AVS/Laser"
+#endif
+" v2.92"
+;
+*/
+
+static unsigned int WINAPI RenderThread(LPVOID a);
+
+static void config(struct winampVisModule *this_mod);
+static int init(struct winampVisModule *this_mod);
+static int render(struct winampVisModule *this_mod);
+static void quit(struct winampVisModule *this_mod);
+
+HANDLE g_hThread;
+volatile int g_ThreadQuit;
+
+static CRITICAL_SECTION g_cs;
+
+static unsigned char g_visdata[2][2][576];
+static int g_visdata_pstat;
+
+/* 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;
+static char module1[128];
+
+static winampVisModule *getModule(int which);
+static winampVisHeader hdr = { VIS_HDRVER, 0, getModule };
+
+// use this to get our own HINSTACE since overriding DllMain(..) causes instant crashes (should see why)
+
+static HINSTANCE GetMyInstance()
+{
+ MEMORY_BASIC_INFORMATION mbi = {0};
+ if(VirtualQuery(GetMyInstance, &mbi, sizeof(mbi)))
+ return (HINSTANCE)mbi.AllocationBase;
+ return NULL;
+}
+
+extern "C" {
+ __declspec( dllexport ) winampVisHeader* winampVisGetHeader(HWND hwndParent)
+ {
+ 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(),VisAVSLangGUID);
+ }
+
+ #ifndef LASER
+ static char szDescription[256];
+ wsprintfA(szDescription,"%s " PLUGIN_VERSION,WASABI_API_LNGSTRING_BUF(IDS_AVS,module1,128));
+ hdr.description = szDescription;
+ #else
+ hdr.description = "AVS/Laser "PLUGIN_VERSION;
+ #endif
+
+ return &hdr;
+ }
+}
+
+static winampVisModule *getModule(int which)
+{
+ static winampVisModule mod =
+ {
+#ifdef LASER
+ "Advanced Visualization Studio/Laser",
+#else
+ module1,
+#endif
+ NULL, // hwndParent
+ NULL, // hDllInstance
+ 0, // sRate
+ 0, // nCh
+ 1000/70, // latencyMS
+ 1000/70,// delayMS
+ 2, // spectrumNch
+ 2, // waveformNch
+ { 0, }, // spectrumData
+ { 0, }, // waveformData
+ config,
+ init,
+ render,
+ quit
+ };
+ if (which==0) return &mod;
+ return 0;
+}
+
+void about(HWND hwndParent)
+
+ {
+ static int about_here = 0;
+ char aboutbuf[1024] = {0}, aboutTitle[48] = {0};
+ if (about_here)
+ {
+ SetActiveWindow(FindWindow("#32770",WASABI_API_LNGSTRING_BUF(IDS_ABOUT_AVS,aboutTitle,48)));
+ return;
+ }
+ about_here = 1;
+ wsprintf(aboutbuf,WASABI_API_LNGSTRING(IDS_ABOUT_STRING),hdr.description);
+ MessageBox(hwndParent,aboutbuf,WASABI_API_LNGSTRING_BUF(IDS_ABOUT_AVS,aboutTitle,48),0);
+ about_here = 0;
+}
+
+HWND GetDialogBoxParent(HWND winamp)
+{
+ HWND parent = (HWND)SendMessage(winamp, WM_WA_IPC, 0, IPC_GETDIALOGBOXPARENT);
+ if (!parent || parent == (HWND)1)
+ return winamp;
+ return parent;
+
+/*
+BOOL CALLBACK aboutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ SetDlgItemText(hwndDlg,IDC_VERSTR,verstr);
+
+ return 1;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDOK: case IDCANCEL:
+ EndDialog(hwndDlg,0);
+ return 0;
+ }
+ return 0;
+ }
+ return 0;
+*/
+
+}
+
+static void config(struct winampVisModule *this_mod)
+{
+ if (!g_hwnd || !IsWindow(g_hwnd))
+ {
+ about(GetDialogBoxParent(this_mod->hwndParent));
+// DialogBox(this_mod->hDllInstance,MAKEINTRESOURCE(IDD_DIALOG2),this_mod->hwndParent,aboutProc);
+ }
+ else
+ {
+ SendMessage(g_hwnd,WM_USER+33,0,0);
+ }
+}
+
+CRITICAL_SECTION g_render_cs;
+static int g_is_beat;
+char g_path[1024];
+
+int beat_peak1,beat_peak2, beat_cnt,beat_peak1_peak;
+
+void main_setRenderThreadPriority()
+{
+ int prios[]={
+ GetThreadPriority(GetCurrentThread()),
+ THREAD_PRIORITY_IDLE,
+ THREAD_PRIORITY_LOWEST,
+ THREAD_PRIORITY_NORMAL,
+ THREAD_PRIORITY_HIGHEST,
+ };
+ SetThreadPriority(g_hThread,prios[cfg_render_prio]);
+}
+
+extern void previous_preset(HWND hwnd);
+extern void next_preset(HWND hwnd);
+extern void random_preset(HWND hwnd);
+
+#if 0//syntax highlighting
+HINSTANCE hRich;
+#endif
+
+static int init(struct winampVisModule *this_mod)
+{
+ DWORD id;
+ FILETIME ft;
+#if 0//syntax highlighting
+ if (!hRich) hRich=LoadLibrary("RICHED32.dll");
+#endif
+ GetSystemTimeAsFileTime(&ft);
+ srand(ft.dwLowDateTime|ft.dwHighDateTime^GetCurrentThreadId());
+ g_hInstance=this_mod->hDllInstance;
+ GetModuleFileName(g_hInstance,g_path,MAX_PATH);
+ char *p=g_path+strlen(g_path);
+ while (p > g_path && *p != '\\') p--;
+ *p = 0;
+
+#ifdef WA2_EMBED
+ if (SendMessage(this_mod->hwndParent,WM_USER,0,0) < 0x2900)
+ {
+ char title[16];
+ MessageBox(this_mod->hwndParent,WASABI_API_LNGSTRING(IDS_REQUIRES_2_9_PLUS),
+ WASABI_API_LNGSTRING_BUF(IDS_AVS_ERROR,title,16),MB_OK|MB_ICONSTOP);
+ return 1;
+ }
+#endif
+
+#ifndef NO_MMX
+ extern int is_mmx(void);
+ if (!is_mmx())
+ {
+ char title[16];
+ MessageBox(this_mod->hwndParent,WASABI_API_LNGSTRING(IDS_NO_MMX_SUPPORT),
+ WASABI_API_LNGSTRING_BUF(IDS_AVS_ERROR,title,16),MB_OK|MB_ICONSTOP);
+ return 1;
+ }
+#endif
+
+#ifdef LASER
+ strcat(g_path,"\\avs_laser");
+#else
+ strcat(g_path,"\\avs");
+#endif
+ CreateDirectory(g_path,NULL);
+
+ InitializeCriticalSection(&g_cs);
+ InitializeCriticalSection(&g_render_cs);
+ g_ThreadQuit=0;
+ g_visdata_pstat=1;
+
+ AVS_EEL_IF_init();
+
+ if (Wnd_Init(this_mod)) return 1;
+
+ {
+ int x;
+ for (x = 0; x < 256; x ++)
+ {
+ double a=log((double)x*60.0/255.0 + 1.0)/log(60.0);
+ int t=(int)(a*255.0);
+ if (t<0)t=0;
+ if (t>255)t=255;
+ g_logtab[x]=(unsigned char )t;
+ }
+ }
+
+ initBpm();
+
+ Render_Init(g_hInstance);
+
+ CfgWnd_Create(this_mod);
+
+ g_hThread=(HANDLE)_beginthreadex(NULL,0,RenderThread,0,0,(unsigned int *)&id);
+ main_setRenderThreadPriority();
+ SetForegroundWindow(g_hwnd);
+ SetFocus(g_hwnd);
+
+ return 0;
+}
+
+static int render(struct winampVisModule *this_mod)
+{
+ int x,avs_beat=0,b;
+ if (g_ThreadQuit) return 1;
+ EnterCriticalSection(&g_cs);
+ if (g_ThreadQuit)
+ {
+ LeaveCriticalSection(&g_cs);
+ return 1;
+ }
+ if (g_visdata_pstat)
+ for (x = 0; x< 576*2; x ++)
+ g_visdata[0][0][x]=g_logtab[(unsigned char)this_mod->spectrumData[0][x]];
+ else
+ {
+ for (x = 0; x < 576*2; x ++)
+ {
+ int t=g_logtab[(unsigned char)this_mod->spectrumData[0][x]];
+ if (g_visdata[0][0][x] < t)
+ g_visdata[0][0][x] = t;
+ }
+ }
+ memcpy(&g_visdata[1][0][0],this_mod->waveformData,576*2);
+ {
+ int lt[2]={0,0};
+ int x;
+ int ch;
+ for (ch = 0; ch < 2; ch ++)
+ {
+ unsigned char *f=(unsigned char*)&this_mod->waveformData[ch][0];
+ for (x = 0; x < 576; x ++)
+ {
+ int r= *f++^128;
+ r-=128;
+ if (r<0)r=-r;
+ lt[ch]+=r;
+ }
+ }
+ lt[0]=max(lt[0],lt[1]);
+
+ beat_peak1=(beat_peak1*125+beat_peak2*3)/128;
+
+ beat_cnt++;
+
+ if (lt[0] >= (beat_peak1*34)/32 && lt[0] > (576*16))
+ {
+ if (beat_cnt>0)
+ {
+ beat_cnt=0;
+ avs_beat=1;
+ }
+ beat_peak1=(lt[0]+beat_peak1_peak)/2;
+ beat_peak1_peak=lt[0];
+ }
+ else if (lt[0] > beat_peak2)
+ {
+ beat_peak2=lt[0];
+ }
+ else beat_peak2=(beat_peak2*14)/16;
+
+ }
+ b=refineBeat(avs_beat);
+ if (b) g_is_beat=1;
+ g_visdata_pstat=0;
+ LeaveCriticalSection(&g_cs);
+ return 0;
+}
+
+static void quit(struct winampVisModule *this_mod)
+{
+#define DS(x)
+ //MessageBox(this_mod->hwndParent,x,"AVS Debug",MB_OK)
+ if (g_hThread)
+ {
+ DS("Waitin for thread to quit\n");
+ g_ThreadQuit=1;
+ if (WaitForSingleObject(g_hThread,10000) != WAIT_OBJECT_0)
+ {
+ DS("Terminated thread (BAD!)\n");
+ //MessageBox(NULL,"error waiting for thread to quit","a",MB_TASKMODAL);
+ TerminateThread(g_hThread,0);
+ }
+ DS("Thread done... calling ddraw_quit\n");
+ DDraw_Quit();
+
+ DS("Calling cfgwnd_destroy\n");
+ CfgWnd_Destroy();
+ DS("Calling render_quit\n");
+ Render_Quit(this_mod->hDllInstance);
+
+ DS("Calling wnd_quit\n");
+ Wnd_Quit();
+
+ DS("closing thread handle\n");
+ CloseHandle(g_hThread);
+ g_hThread=NULL;
+
+ DS("calling eel quit\n");
+ AVS_EEL_IF_quit();
+
+ DS("cleaning up critsections\n");
+ DeleteCriticalSection(&g_cs);
+ DeleteCriticalSection(&g_render_cs);
+
+ DS("smp_cleanupthreads\n");
+ C_RenderListClass::smp_cleanupthreads();
+ }
+#undef DS
+#if 0//syntax highlighting
+ if (hRich) FreeLibrary(hRich);
+ hRich=0;
+#endif
+}
+
+#define FPS_NF 64
+
+static unsigned int WINAPI RenderThread(LPVOID a)
+{
+ int framedata[FPS_NF]={0,};
+ int framedata_pos=0;
+ int s=0;
+ char vis_data[2][2][576];
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ srand(ft.dwLowDateTime|ft.dwHighDateTime^GetCurrentThreadId());
+ while (!g_ThreadQuit)
+ {
+ int w,h,*fb=NULL, *fb2=NULL,beat=0;
+
+#ifdef REAPLAY_PLUGIN
+ if(!IsWindowVisible(g_hwnd))
+ {
+ Sleep(1);
+ continue;
+ }
+
+ char visdata[576*2*2];
+ int ret = vuGetVisData(visdata, sizeof(visdata));
+ if (!ret)
+ {
+ memset(&vis_data[0][0][0],0,576*2*2);
+ beat=0;
+ }
+ else
+ {
+ int x;
+ unsigned char *v=(unsigned char *)visdata;
+ for (x = 0; x < 576*2; x ++)
+ vis_data[0][0][x]=g_logtab[*v++];
+ for (x = 0; x < 576*2; x ++)
+ ((unsigned char *)vis_data[1][0])[x]=*v++;
+
+ v=(unsigned char *)visdata+1152;
+ {
+ int lt[2]={0,0};
+ int ch;
+ for (ch = 0; ch < 2; ch ++)
+ {
+ for (x = 0; x < 576; x ++)
+ {
+ int r=*v++^128;
+ r-=128;
+ if (r<0)r=-r;
+ lt[ch]+=r;
+ }
+ }
+ lt[0]=max(lt[0],lt[1]);
+
+ beat_peak1=(beat_peak1*125+beat_peak2*3)/128;
+ beat_cnt++;
+
+ if (lt[0] >= (beat_peak1*34)/32 && lt[0] > (576*16))
+ {
+ if (beat_cnt>0)
+ {
+ beat_cnt=0;
+ beat=1;
+ }
+ beat_peak1=(lt[0]+beat_peak1_peak)/2;
+ beat_peak1_peak=lt[0];
+ }
+ else if (lt[0] > beat_peak2)
+ {
+ beat_peak2=lt[0];
+ }
+ else beat_peak2=(beat_peak2*14)/16;
+
+ }
+// EnterCriticalSection(&g_title_cs);
+ beat=refineBeat(beat);
+// LeaveCriticalSection(&g_title_cs);
+ }
+#else
+ EnterCriticalSection(&g_cs);
+ memcpy(&vis_data[0][0][0],&g_visdata[0][0][0],576*2*2);
+ g_visdata_pstat=1;
+ beat=g_is_beat;
+ g_is_beat=0;
+ LeaveCriticalSection(&g_cs);
+#endif
+
+ if (!g_ThreadQuit)
+ {
+ if (IsWindow(g_hwnd)&&!g_in_destroy) DDraw_Enter(&w,&h,&fb,&fb2);
+ else break;
+ if (fb&&fb2)
+ {
+ extern int g_dlg_w, g_dlg_h, g_dlg_fps;
+#ifdef LASER
+ g_laser_linelist->ClearLineList();
+#endif
+
+ EnterCriticalSection(&g_render_cs);
+ int t=g_render_transition->render(vis_data,beat,s?fb2:fb,s?fb:fb2,w,h);
+ LeaveCriticalSection(&g_render_cs);
+ if (t&1) s^=1;
+
+#ifdef LASER
+ s=0;
+ memset(fb,0,w*h*sizeof(int));
+ LineDrawList(g_laser_linelist,fb,w,h);
+#endif
+ if (IsWindow(g_hwnd)) DDraw_Exit(s);
+
+ int lastt=framedata[framedata_pos];
+ int thist=GetTickCount();
+ framedata[framedata_pos]=thist;
+ g_dlg_w=w;
+ g_dlg_h=h;
+ if (lastt)
+ {
+ g_dlg_fps=MulDiv(sizeof(framedata)/sizeof(framedata[0]),10000,thist-lastt);
+ }
+ framedata_pos++;
+ if (framedata_pos >= sizeof(framedata)/sizeof(framedata[0])) framedata_pos=0;
+
+ }
+ int fs=DDraw_IsFullScreen();
+ int sv=(fs?(cfg_speed>>8):cfg_speed)&0xff;
+ Sleep(min(max(sv,1),100));
+ }
+ }
+ _endthreadex(0);
+ return 0;
+}
+
+#ifdef REAPLAY_PLUGIN
+static winampVisModule dummyMod;
+extern "C"
+{
+
+ REAPER_PLUGIN_DLL_EXPORT int REAPER_PLUGIN_ENTRYPOINT(REAPER_PLUGIN_HINSTANCE hInstance, reaper_plugin_info_t *rec)
+ {
+ g_hInstance=hInstance;
+ if (rec)
+ {
+ if (rec->caller_version != REAPER_PLUGIN_VERSION || !rec->GetFunc)
+ return 0;
+
+ *((void **)&get_ini_file) = rec->GetFunc("get_ini_file");
+ *((void **)&vuGetVisData) = rec->GetFunc("vuGetVisData");
+ if (!get_ini_file || !vuGetVisData)
+ return 0;
+
+ dummyMod.hwndParent=rec->hwnd_main;
+ dummyMod.hDllInstance=g_hInstance;
+ init(&dummyMod);
+
+ return 1;
+ }
+ else
+ {
+ quit(&dummyMod);
+ return 0;
+ }
+ }
+
+};
+#endif