/** Example Winamp AVS plug-in Copyright (c) 2000, Nullsoft Inc. Hello, welcome to the first Advanced Visualization Studio tutorial! The hope is that together, we can learn to utilize AVS's powerful features: Namely direct access to the frame buffer, EZ beat detection, and the ability to stack plug-ins written by other developers for an infinite array of possible effects. I hereby present: Tutorial 0: BOX- Simplicity at its finest. Displays a rectangle on screen on every beat. Oh, and you can change its color too... Check avstut00.avs for a demonstration of a spinning rectangle's power! good luck and have fun! **/ #include #include "resource.h" #include "avs_ape.h" #define MOD_NAME "Tutorials / BOX v1.0" #define UNIQUEIDSTRING "Nullsoft Tut0: BOX" // extended APE api support APEinfo *g_extinfo; extern "C" { void __declspec(dllexport) _AVS_APE_SetExtInfo(HINSTANCE hDllInstance, APEinfo *ptr) { g_extinfo = ptr; } } class C_THISCLASS : public C_RBASE { protected: public: C_THISCLASS(); virtual ~C_THISCLASS(); virtual int render(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h); virtual HWND conf(HINSTANCE hInstance, HWND hwndParent); virtual char *get_desc(); virtual void load_config(unsigned char *data, int len); virtual int save_config(unsigned char *data); int enabled; // toggles plug-in on and off int color; // color of rectangle }; // global configuration dialog pointer static C_THISCLASS *g_ConfigThis; // global DLL instance pointer (not needed in this example, but could be useful) static HINSTANCE g_hDllInstance; // this is where we deal with the configuration screen static BOOL CALLBACK g_DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: if (g_ConfigThis->enabled) { CheckDlgButton(hwndDlg,IDC_CHECK1,BST_CHECKED); } return 1; case WM_DRAWITEM: DRAWITEMSTRUCT *di; di=(DRAWITEMSTRUCT *)lParam; if (di->CtlID == IDC_DEFCOL) { int w; int color; w=di->rcItem.right-di->rcItem.left; color=g_ConfigThis->color; color = ((color>>16)&0xff)|(color&0xff00)|((color<<16)&0xff0000); // paint nifty color button HBRUSH hBrush,hOldBrush; LOGBRUSH lb={BS_SOLID,color,0}; hBrush = CreateBrushIndirect(&lb); hOldBrush=(HBRUSH)SelectObject(di->hDC,hBrush); Rectangle(di->hDC,di->rcItem.left,di->rcItem.top,di->rcItem.right,di->rcItem.bottom); SelectObject(di->hDC,hOldBrush); DeleteObject(hBrush); } return 0; case WM_COMMAND: // see if enable checkbox is checked if (LOWORD(wParam) == IDC_CHECK1) { g_ConfigThis->enabled= (IsDlgButtonChecked(hwndDlg,IDC_CHECK1)?1:0); } // is colorbox is selected? if (LOWORD(wParam) == IDC_DEFCOL) { static COLORREF custcolors[16]; int *a; CHOOSECOLOR cs; a=&g_ConfigThis->color; cs.lStructSize = sizeof(cs); cs.hwndOwner = hwndDlg; cs.hInstance = 0; cs.rgbResult=((*a>>16)&0xff)|(*a&0xff00)|((*a<<16)&0xff0000); cs.lpCustColors = custcolors; cs.Flags = CC_RGBINIT|CC_FULLOPEN; // go to windows color selection screen if (ChooseColor(&cs)) { *a = ((cs.rgbResult>>16)&0xff)|(cs.rgbResult&0xff00)|((cs.rgbResult<<16)&0xff0000); } InvalidateRect(GetDlgItem(hwndDlg,IDC_DEFCOL),NULL,TRUE); } return 0; } return 0; } // set up default configuration C_THISCLASS::C_THISCLASS() { //set initial color color=RGB(255,0,0); enabled=1; } // virtual destructor C_THISCLASS::~C_THISCLASS() { } // RENDER FUNCTION: // render should return 0 if it only used framebuffer, or 1 if the new output data is in fbout. this is // used when you want to do something that you'd otherwise need to make a copy of the framebuffer. // w and h are the-*/ width and height of the screen, in pixels. // isBeat is 1 if a beat has been detected. // visdata is in the format of [spectrum:0,wave:1][channel][band]. int C_THISCLASS::render(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h) { int halfw; int halfh; // is this effect on? if (!enabled) { return 0; } // did we just hit a beat? if(isBeat) { // draw our magic box halfw=w/2; halfh=h/2; framebuffer+=(((halfh/2)*w)+ (halfw/2)); for(int j=0;j= 4) { // load activation toggle enabled=GET_INT(); pos+=4; } if (len-pos >= 4) { // load the box color color=GET_INT(); pos+=4; } } // write configuration to data, return length. config data should not exceed 64k. #define PUT_INT(y) data[pos]=(y)&255; data[pos+1]=(y>>8)&255; data[pos+2]=(y>>16)&255; data[pos+3]=(y>>24)&255 int C_THISCLASS::save_config(unsigned char *data) { int pos=0; PUT_INT(enabled); pos+=4; PUT_INT(color); pos+=4; return pos; } // export stuff C_RBASE *R_RetrFunc(char *desc) // creates a new effect object if desc is NULL, otherwise fills in desc with description { if (desc) { strcpy(desc,MOD_NAME); return NULL; } return (C_RBASE *) new C_THISCLASS(); } extern "C" { __declspec (dllexport) int _AVS_APE_RetrFunc(HINSTANCE hDllInstance, char **info, int *create) // return 0 on failure { g_hDllInstance=hDllInstance; *info=UNIQUEIDSTRING; *create=(int)(void*)R_RetrFunc; return 1; } }; /** Final Thoughts: Alright! Hopefully you guys can take the next step and display more than just a colored rectangle ;) The exciting thing is, each time you write an AVS plug-in, you exponentially increase AVS's potential, unlocking the possibility of an effect you never expected. Good luck, I hope this has helped! See you next time! **/