home *** CD-ROM | disk | FTP | other *** search
/ Enter 2002 September / EnterCD 9_2002.iso / Multimedia / DJ Mix Pro 3.0 / djmixprosetup.exe / #setuppath# / plugins / sdk / Pulsing.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-07-22  |  8.7 KB  |  323 lines

  1. //
  2. //        DJ Mix Pro visualisation plugin example :
  3. //
  4. //      Pulsing Star
  5. //
  6. //      (C) 2001 Beatlock Technology
  7. //
  8. //
  9. //      See comments in "DJMixPlugin.h"
  10. //      but don't expect a real documentation
  11. //
  12. //      
  13. //    The resulting DLL is to be dropped in the DJ Mix Pro 
  14. //    plugins folder
  15. //
  16.  
  17.  
  18.  
  19. /* includes for this plugin */
  20. #include "math.h"
  21. #include "windows.h"
  22. #include "windowsx.h"
  23. #include "string.h"
  24. #include "stdio.h"
  25.  
  26. /* mandatory DJ Mix Pro plugin include */
  27. #include "Pulsing.h"
  28.  
  29. //cache for costfull values
  30. short cosvals[256];
  31. short sinvals[256];
  32.  
  33. //usual colors
  34. COLORREF BACKBRUSH  = GetSysColor(COLOR_BTNFACE);
  35. COLORREF MONOBRUSH  = GetSysColor(COLOR_BTNSHADOW);
  36. COLORREF BLUEBRUSH  = RGB(0,0,255);
  37. COLORREF GREENBRUSH  = RGB(0,255,0);
  38. COLORREF REDBRUSH = RGB(255,0,0);
  39. COLORREF YELLOWBRUSH= RGB(255,255,0) ;
  40. COLORREF PINKBRUSH= RGB(255,128,255) ;
  41. COLORREF BRAWNBRUSH = RGB(255,0,255);
  42. COLORREF ORANGEBRUSH = RGB(255,128,0);
  43. COLORREF VIOLETBRUSH = RGB(255,0,255);
  44. COLORREF CYANBRUSH = RGB(0,255,255);
  45. COLORREF OLIVEBRUSH = RGB(0,128,0);
  46. COLORREF WHITEBRUSH = RGB(255,255,255);
  47. COLORREF BLACKBRUSH = RGB(0,0,0);
  48.  
  49. //name of plugin
  50. char* Pulsing::name = "Pulsing star";
  51.  
  52. //events dispatcher, for a windows plugin
  53. LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
  54.     HDC        hdc;
  55.     PAINTSTRUCT ps; 
  56.  
  57.     //get back object 
  58.     Pulsing* me =(Pulsing*) GetWindowLong(hwnd,GWL_USERDATA);
  59.  
  60.     //not yet.
  61.     if ( ! me)
  62.         return DefWindowProc(hwnd,msg,wParam,lParam);
  63.  
  64.     switch (msg) {
  65.  
  66.             
  67.     case WM_PAINT:
  68.         //redraw in window
  69.         hdc = BeginPaint(hwnd,&ps);
  70.         me->Redraw(hdc);
  71.         EndPaint(hwnd,&ps);
  72.         break;
  73.  
  74.         
  75.     case WM_CLOSE:
  76.         //we MUST notify DJ Mix Pro when plugin is closing
  77.         SendMessage(me->parent, PLUGGINUNLOADED, 0, 0);
  78.         break;    
  79.  
  80.     }
  81.     //Default windows processing
  82.     return DefWindowProc(hwnd,msg,wParam,lParam);
  83. }
  84.  
  85.  
  86.  
  87.  
  88. //load is when user selects this plugin in menu
  89. void Pulsing::Load(HINSTANCE instance, HWND parent)
  90. {
  91.     Pulsing::parent = parent;
  92.     numrecorded=0;
  93.     bpm = -1;
  94.     lastclosest=0.;
  95.     //cache sin and cos values
  96. #define PI 3.14159265358979323846
  97.     for (int  i = 0; i < 256; i++ ) {
  98.         cosvals[i] = (short) ( (double)(1 << 14) * cos( i * 2. * PI / 256. ));
  99.         sinvals[i] = (short) ( (double)(1 << 14) * sin( i * 2. * PI / 256. ));
  100.     }
  101.  
  102.     
  103.     //create window class
  104.     WNDCLASS    cls;
  105.     const DWORD  dwExStyle = 0;
  106.     cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  107.     cls.hIcon          = LoadIcon(instance,IDI_APPLICATION);
  108.     cls.lpszMenuName   = 0;
  109.     cls.lpszClassName  = "Pluggin";
  110.     cls.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  111.     cls.hInstance      = instance;
  112.     cls.style          = CS_BYTEALIGNCLIENT ;
  113.     cls.lpfnWndProc    = MainWndProc;
  114.     cls.cbWndExtra     = 0;
  115.     cls.cbClsExtra     = 0;
  116.     RegisterClass(&cls);
  117.  
  118.     //create window itself, child of parent here. 
  119.     win=CreateWindowEx(dwExStyle,
  120.                             "Pluggin",    // Class name
  121.                             "Pulsing star",             // Caption
  122.                             WS_OVERLAPPEDWINDOW,    // Style bits
  123.                             CW_USEDEFAULT, 0,       // Position
  124.                             200,200,                // Size
  125.                             (HWND)parent,             // Parent window 
  126.                             (HMENU)NULL,            // use class menu
  127.                             instance,          // handle to window instance
  128.                             (LPSTR)NULL             // no params to pass on
  129.                            );
  130.  
  131.     //if failed : 
  132.     if ( ! win) {
  133.         //we MUST notify plugin is closing
  134.         SendMessage(parent, PLUGGINUNLOADED, 0, 0);
  135.         return;
  136.     }
  137.  
  138.     //store object pointer
  139.     SetWindowLong(win,GWL_USERDATA,  (long)this);
  140.  
  141.     ShowWindow(win,SW_SHOW);
  142. }
  143. //unload is when another plugin is being loaded (changing)
  144. /* this plugin must then do some cleanup */
  145. void Pulsing::Unload()
  146. {
  147.     if (win) {
  148.         DestroyWindow(win);
  149.         win = 0;
  150.     }
  151. }
  152.  
  153. //returns plugin name to DJ Mix Pro, to display in menu
  154. char* Pulsing::GetName() {
  155.     return name;
  156. }
  157.  
  158. //receive beat information . double parameters are in seconds,
  159. //but with no continuity guarantee. Programmer must
  160. //always check there was no position move in between
  161. //using "which" (gives the beat "number")
  162. // 
  163. void Pulsing::Refresh(double where, double closest, long which){
  164.     Pulsing::where = where;
  165.     Pulsing::closest = closest;
  166.  
  167.  
  168.     //record closest beat position
  169.     //is supposed to smooth BPM value
  170.     if ( lastwhich == -1){
  171.         lastclosest= closest;
  172.         lastwhich = which;
  173.     }
  174.     if ( lastwhich != which) {
  175.         //check if there is a discontinuity
  176.         if (  lastwhich +1 == which ) {
  177.             lastclosesthist[numrecorded%NUMRECORDS] = closest-lastclosest;
  178.             numrecorded++;
  179.         }
  180.         lastclosest= closest;
  181.         lastwhich= which;
  182.  
  183.         if ( numrecorded >0) {
  184.             double sum = 0;
  185.             int count = 0;
  186.             for ( int i = 0; i < numrecorded &&i <NUMRECORDS; i++){
  187.                 if (lastclosesthist[i]){
  188.                     sum += lastclosesthist[i];
  189.                     count++;
  190.                 }
  191.  
  192.             }
  193.             if ( count) {
  194.                 sum /= numrecorded>NUMRECORDS?NUMRECORDS: numrecorded ;
  195.                 bpm = 60. / sum;
  196.             }else {
  197.                 bpm = -1;
  198.             }
  199.  
  200.         }else {
  201.             //default value for unknown BPM
  202.              bpm = -1;
  203.         }
  204.  
  205.     }
  206.     //force window to redraw    
  207.     RECT rc ;
  208.     GetClientRect(win, &rc);
  209.     InvalidateRect(win, &rc, FALSE);
  210.     UpdateWindow(win);
  211. }
  212.  
  213. void Pulsing::Redraw(HDC hdc)
  214. {
  215.  
  216.     //processing redraw order
  217.     RECT rc ;
  218.     //get window size
  219.     GetClientRect(win, &rc);
  220.     int w,h;
  221.     w = rc.right - rc.left;
  222.     h = rc.bottom - rc.top;
  223.  
  224.  
  225.  
  226.     //beatfactor is distance from here to closest beat in percent 
  227.     //( 100 on a beat, 0 just in the middle of 2 beats )
  228.     //interval between 2 beats is 60. / bpm
  229.     //so "here" is about between last beat and next beat
  230.     //if we want to have 100% on a beat pos 
  231.     // and 0% in the middle here is the formula (trust me...)
  232.     double beatFactor = 100. - fabs(where-closest) * 2 *100 / (  60. / bpm );
  233.     if ( beatFactor <0)
  234.         beatFactor =0;
  235.     if (beatFactor >100)
  236.         beatFactor =100;
  237.  
  238.     //if beatFactor didnt change, nothing to redraw
  239.     if (  beatFactor==lastBeatFactor)
  240.         return;
  241.     
  242.     //smallest dimension of window
  243.     int radius = w > h ? h:w;
  244.     radius = (int)(radius * beatFactor / 250);
  245.  
  246.     // Paint (erase) the background in standard color
  247.     HBRUSH hbr;
  248.     hbr = (HBRUSH)SelectObject(hdc, CreateSolidBrush(BACKBRUSH));
  249.     PatBlt(hdc, rc.left, rc.top, w , h   , PATCOPY);
  250.     DeleteObject(SelectObject(hdc, hbr));
  251.  
  252.     HPEN hpen =  (HPEN) SelectObject(hdc,CreatePen( PS_NULL, 0, REDBRUSH ));
  253.     hbr = (HBRUSH) SelectObject(hdc, CreateSolidBrush(REDBRUSH));
  254.     //draw Filled Star ( 10 points, odd points have 
  255.     POINT  p[10];
  256.  
  257.     //star is turning slowly
  258.     int startangle = ((long)where) %  60 * 256 /  60;
  259.     for ( int i = 0; i < 10; i++ ) {
  260.         int pointradius;
  261.         if ( i % 2 )
  262.             pointradius = radius /2;
  263.         else
  264.             pointradius =  radius*3/2;
  265.         p[i].x =     (rc.right +rc.left) / 2 + pointradius * sinvals[ ( startangle +  i *  256 / 10 ) %256] / (1 << 14) ; 
  266.         p[i].y =     (rc.bottom +rc.top) / 2 - pointradius * cosvals[ ( startangle +  i *  256 / 10 ) %256] / (1 << 14); 
  267.     }
  268.     Polygon(  hdc, p,10); 
  269.  
  270.     DeleteObject(SelectObject(hdc, hbr));
  271.     DeleteObject(SelectObject(hdc, hpen));
  272.  
  273.     int TEXTMYHEIGHT = w > h ? h:w;
  274.     TEXTMYHEIGHT /= 3;
  275.  
  276.     //now draw BPM text string
  277.     char msg[32] ;
  278.     if ( bpm > 0)
  279.         sprintf (msg, "%3.1lf",  bpm);
  280.     else
  281.         strcpy(msg, "???");
  282.  
  283.     int prevmode2 = SetBkMode(hdc, TRANSPARENT);
  284.     COLORREF prevcolor2 = SetTextColor(  hdc, YELLOWBRUSH); 
  285.     UINT lastAlign =  SetTextAlign( hdc,TA_CENTER|TA_BASELINE ); 
  286.  
  287.     //this would need font caching for performance
  288.     HFONT hfont = (HFONT) SelectObject(hdc,
  289.             CreateFont( TEXTMYHEIGHT,  // logical height of font 
  290.                     0,  // logical average character width 
  291.                     0,  // angle of escapement 
  292.                     0,  // base-line orientation angle 
  293.                     FW_NORMAL ,  // font weight 
  294.                     FALSE,  // italic attribute flag 
  295.                     FALSE,  // underline attribute flag 
  296.                     FALSE,  // strikeout attribute flag 
  297.                     ANSI_CHARSET,  // character set identifier 
  298.                     OUT_DEFAULT_PRECIS,  // output precision 
  299.                     CLIP_DEFAULT_PRECIS ,  // clipping precision 
  300.                     DEFAULT_QUALITY ,  // output quality 
  301.                     DEFAULT_PITCH,  // pitch and family 
  302.                     0  // pointer to typeface name string 
  303.             )
  304.             ); 
  305.  
  306.     TextOut(hdc, (rc.right +rc.left) / 2, (rc.bottom +rc.top)/2+TEXTMYHEIGHT/4, msg, lstrlen(msg));
  307.     DeleteObject(SelectObject(hdc, hfont));
  308.  
  309.     SetBkMode(hdc, prevmode2);
  310.     SetTextColor(  hdc, prevcolor2);
  311.     SetTextAlign( hdc,lastAlign); 
  312.  
  313.  
  314.  
  315. }
  316.  
  317. //only published func of the plugin DLL.
  318. //builds an object.
  319. //all other functions are vitual methods of object. 
  320. extern "C"
  321. __declspec( dllexport )  DJMixPlugin* CreateFunc() {
  322.     return new Pulsing();
  323. }