unit projectM; {$IFDEF FPC} {$IFNDEF win32} {$LINKLIB libprojectM} {$ENDIF} {$MODE DELPHI} {$PACKENUM 4} {$PACKRECORDS C} {$ENDIF} interface uses SysUtils; const {$IFDEF win32} libprojectM = 'libprojectM.dll'; {$ELSE} libprojectM = 'libprojectM.so'; {$ENDIF} const PROJECTM_VERSION = '0.99'; PROJECTM_TITLE = 'projectM 0.99'; type // 16bit non-interleaved data TPCM16 = array[0..1, 0..511] of Smallint; PPCM16 = ^TPCM16; // 8bit non-interleaved data TPCM8_512 = array[0..1, 0..511] of byte; PPCM8_512 = ^TPCM8_512; { Event types } type TProjectMEvent = integer; const PROJECTM_KEYUP = 0; PROJECTM_KEYDOWN = 1; PROJECTM_VIDEORESIZE = 2; PROJECTM_VIDEOQUIT = 3; PROJECTM_NONE = 4; { Keycodes } type TProjectMKeycode = integer; const PROJECTM_K_RETURN = 0; PROJECTM_K_RIGHT = 1; PROJECTM_K_LEFT = 2; PROJECTM_K_UP = 3; PROJECTM_K_DOWN = 4; PROJECTM_K_PAGEUP = 5; PROJECTM_K_PAGEDOWN = 6; PROJECTM_K_INSERT = 7; PROJECTM_K_DELETE = 8; PROJECTM_K_ESCAPE = 9; PROJECTM_K_LSHIFT = 10; PROJECTM_K_RSHIFT = 11; PROJECTM_K_CAPSLOCK = 12; PROJECTM_K_LCTRL = 13; PROJECTM_K_HOME = 14; PROJECTM_K_END = 15; PROJECTM_K_BACKSPACE = 16; PROJECTM_K_F1 = 17; PROJECTM_K_F2 = (PROJECTM_K_F1 + 1); PROJECTM_K_F3 = (PROJECTM_K_F1 + 2); PROJECTM_K_F4 = (PROJECTM_K_F1 + 3); PROJECTM_K_F5 = (PROJECTM_K_F1 + 4); PROJECTM_K_F6 = (PROJECTM_K_F1 + 5); PROJECTM_K_F7 = (PROJECTM_K_F1 + 6); PROJECTM_K_F8 = (PROJECTM_K_F1 + 7); PROJECTM_K_F9 = (PROJECTM_K_F1 + 8); PROJECTM_K_F10 = (PROJECTM_K_F1 + 9); PROJECTM_K_F11 = (PROJECTM_K_F1 + 10); PROJECTM_K_F12 = (PROJECTM_K_F1 + 11); PROJECTM_K_0 = 48; PROJECTM_K_1 = (PROJECTM_K_0 + 1); PROJECTM_K_2 = (PROJECTM_K_0 + 2); PROJECTM_K_3 = (PROJECTM_K_0 + 3); PROJECTM_K_4 = (PROJECTM_K_0 + 4); PROJECTM_K_5 = (PROJECTM_K_0 + 5); PROJECTM_K_6 = (PROJECTM_K_0 + 6); PROJECTM_K_7 = (PROJECTM_K_0 + 7); PROJECTM_K_8 = (PROJECTM_K_0 + 8); PROJECTM_K_9 = (PROJECTM_K_0 + 9); { Upper case } PROJECTM_K_A_UPPERCASE = 65; PROJECTM_K_B_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 1); PROJECTM_K_C_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 2); PROJECTM_K_D_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 3); PROJECTM_K_E_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 4); PROJECTM_K_F_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 5); PROJECTM_K_G_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 6); PROJECTM_K_H_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 7); PROJECTM_K_I_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 8); PROJECTM_K_J_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 9); PROJECTM_K_K_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 10); PROJECTM_K_L_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 11); PROJECTM_K_M_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 12); PROJECTM_K_N_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 13); PROJECTM_K_O_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 14); PROJECTM_K_P_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 15); PROJECTM_K_Q_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 16); PROJECTM_K_R_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 17); PROJECTM_K_S_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 18); PROJECTM_K_T_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 19); PROJECTM_K_U_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 20); PROJECTM_K_V_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 21); PROJECTM_K_W_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 22); PROJECTM_K_X_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 23); PROJECTM_K_Y_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 24); PROJECTM_K_Z_UPPERCASE = (PROJECTM_K_A_UPPERCASE + 25); { Lower case } PROJECTM_K_a_LOWERCASE = 97; PROJECTM_K_b_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 1); PROJECTM_K_c_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 2); PROJECTM_K_d_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 3); PROJECTM_K_e_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 4); PROJECTM_K_f_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 5); PROJECTM_K_g_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 6); PROJECTM_K_h_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 7); PROJECTM_K_i_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 8); PROJECTM_K_j_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 9); PROJECTM_K_k_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 10); PROJECTM_K_l_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 11); PROJECTM_K_m_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 12); PROJECTM_K_n_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 13); PROJECTM_K_o_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 14); PROJECTM_K_p_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 15); PROJECTM_K_q_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 16); PROJECTM_K_r_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 17); PROJECTM_K_s_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 18); PROJECTM_K_t_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 19); PROJECTM_K_u_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 20); PROJECTM_K_v_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 21); PROJECTM_K_w_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 22); PROJECTM_K_x_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 23); PROJECTM_K_y_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 24); PROJECTM_K_z_LOWERCASE = (PROJECTM_K_a_LOWERCASE + 25); PROJECTM_K_NONE = (PROJECTM_K_z_LOWERCASE + 1); { Modifiers } type TProjectMModifier = integer; const PROJECTM_KMOD_LSHIFT = 0; PROJECTM_KMOD_RSHIFT = 1; PROJECTM_KMOD_CAPS = 2; PROJECTM_KMOD_LCTRL = 3; PROJECTM_KMOD_RCTRL = 4; type PProjectM = ^TProjectM; TProjectM = class(TObject) private _pm: Pointer; public constructor Create(gx, gy: integer; fps: integer; texsize: integer; width, height: integer; presetsDir, fontsDir: string); procedure ResetGL(width, height: Integer); procedure SetTitle(title: string); procedure RenderFrame(); procedure AddPCMfloat(pcmData: PSingle; samples: integer); procedure AddPCM16(pcmData: PPCM16); procedure AddPCM16Data(pcmData: PSmallint; samples: Smallint); procedure AddPCM8_512(pcmData: PPCM8_512); procedure RandomPreset(); procedure PreviousPreset(); procedure NextPreset(); procedure ToggleShowPresetNames(); procedure KeyHandler(event: TProjectMEvent; keycode: TProjectMKeycode; modifier: TProjectMModifier); destructor Destroy(); override; end; implementation uses {$IFNDEF win32} baseunix, {$ENDIF} OpenGL12; {**************** INTERNAL SECTION ****************} type PPSingle = ^PSingle; type _TContextType = Integer; const AGL_CONTEXT = 0; CGL_CONTEXT = 1; NSGL_CONTEXT = 2; GLX_CONTEXT = 3; WGL_CONTEXT = 4; type _PRenderTarget = ^_TRenderTarget; _TRenderTarget = record { Texture size } texsize: Integer; { Application context } origContextType: _TContextType; usePbuffers: Integer; {$ifdef LINUX} lock_func: procedure(); cdecl; unlock_func: procedure(); cdecl; {$endif} { Opaque pbuffer context and pbuffer } {$ifdef MACOS} origContext: Pointer; pbufferContext: Pointer; pbuffer: Pointer; {$endif} { Render target texture ID for non-pbuffer systems } textureID: array[0..2] of TGLuint; end; _PProjectM = ^_TProjectM; _TProjectM = record presetURL: PChar; presetName: PChar; fontURL: PChar; hasInit: Integer; noSwitch: Integer; pcmframes: Integer; freqframes: Integer; totalframes: Integer; showfps: Integer; showtitle: Integer; showpreset: Integer; showhelp: Integer; showstats: Integer; studio: Integer; fbuffer: PGLubyte; {$ifndef Win32} { The first ticks value of the application } startTime: timeval; {$else} startTime: Longint; {$endif Win32} Time: Single; { Render target texture ID } renderTarget: _PRenderTarget; disp: array[0..79] of Char; wave_o: Single; //int texsize=1024; //size of texture to do actual graphics fvw: Integer; //fullscreen dimensions fvh: Integer; wvw: Integer; //windowed dimensions wvh: Integer; vw: Integer; //runtime dimensions vh: Integer; fullscreen: Integer; maxsamples: Integer; //size of PCM buffer numsamples: Integer; //size of new PCM info pcmdataL: PSingle; //holder for most recent pcm data pcmdataR: PSingle; //holder for most recent pcm data avgtime: Integer; //# frames per preset title: PChar; drawtitle: Integer; correction: Integer; vol: Single; //per pixel equation variables gridx: PPSingle; //grid containing interpolated mesh gridy: PPSingle; origtheta: PPSingle; //grid containing interpolated mesh reference values origrad: PPSingle; origx: PPSingle; //original mesh origy: PPSingle; origx2: PPSingle; //original mesh origy2: PPSingle; { Timing information } mspf: Integer; timed: Integer; timestart: Integer; nohard: Integer; count: Integer; realfps, fpsstart: Single; { PCM data } vdataL: array[0..511] of Single; //holders for FFT data (spectrum) vdataR: array[0..511] of Single; { Various toggles } doPerPixelEffects: Integer; doIterative: Integer; { ENGINE VARIABLES } { From engine_vars.h } preset_name: array[0..255] of Char; { PER FRAME CONSTANTS BEGIN } zoom: Single; zoomexp: Single; rot: Single; warp: Single; sx: Single; sy: Single; dx: Single; dy: Single; cx: Single; cy: Single; gy: Integer; gx: Integer; decay: Single; wave_r: Single; wave_g: Single; wave_b: Single; wave_x: Single; wave_y: Single; wave_mystery: Single; ob_size: Single; ob_r: Single; ob_g: Single; ob_b: Single; ob_a: Single; ib_size: Single; ib_r: Single; ib_g: Single; ib_b: Single; ib_a: Single; meshx: Integer; meshy: Integer; mv_a: Single; mv_r: Single; mv_g: Single; mv_b: Single; mv_l: Single; mv_x: Single; mv_y: Single; mv_dy: Single; mv_dx: Single; treb: Single; mid: Single; bass: Single; bass_old: Single; beat_sensitivity: Single; treb_att: Single; mid_att: Single; bass_att: Single; progress: Single; frame: Integer; { PER_FRAME CONSTANTS END } { PER_PIXEL CONSTANTS BEGIN } x_per_pixel: Single; y_per_pixel: Single; rad_per_pixel: Single; ang_per_pixel: Single; { PER_PIXEL CONSTANT END } fRating: Single; fGammaAdj: Single; fVideoEchoZoom: Single; fVideoEchoAlpha: Single; nVideoEchoOrientation: Integer; nWaveMode: Integer; bAdditiveWaves: Integer; bWaveDots: Integer; bWaveThick: Integer; bModWaveAlphaByVolume: Integer; bMaximizeWaveColor: Integer; bTexWrap: Integer; bDarkenCenter: Integer; bRedBlueStereo: Integer; bBrighten: Integer; bDarken: Integer; bSolarize: Integer; bInvert: Integer; bMotionVectorsOn: Integer; fps: Integer; fWaveAlpha: Single; fWaveScale: Single; fWaveSmoothing: Single; fWaveParam: Single; fModWaveAlphaStart: Single; fModWaveAlphaEnd: Single; fWarpAnimSpeed: Single; fWarpScale: Single; fShader: Single; { Q VARIABLES START } q1: Single; q2: Single; q3: Single; q4: Single; q5: Single; q6: Single; q7: Single; q8: Single; { Q VARIABLES END } zoom_mesh: PPSingle; zoomexp_mesh: PPSingle; rot_mesh: PPSingle; sx_mesh: PPSingle; sy_mesh: PPSingle; dx_mesh: PPSingle; dy_mesh: PPSingle; cx_mesh: PPSingle; cy_mesh: PPSingle; x_mesh: PPSingle; y_mesh: PPSingle; rad_mesh: PPSingle; theta_mesh: PPSingle; end; { projectM.h declarations } procedure _projectM_init(pm: _PProjectM); cdecl; external libprojectM name 'projectM_init'; procedure _projectM_reset(pm: _PProjectM); cdecl; external libprojectM name 'projectM_reset'; procedure _projectM_resetGL(pm: _PProjectM; width: Integer; height: Integer); cdecl; external libprojectM name 'projectM_resetGL'; procedure _projectM_setTitle(pm: _PProjectM; title: PChar); cdecl; external libprojectM name 'projectM_setTitle'; procedure _renderFrame(pm: _PProjectM); cdecl; external libprojectM name 'renderFrame'; { PCM.h declarations } procedure _addPCMfloat(pcm_data: PSingle; samples: integer); cdecl; external libprojectM name 'addPCMfloat'; procedure _addPCM16(pcm_data: PPCM16); cdecl; external libprojectM name 'addPCM16'; procedure _addPCM16Data(pcm_data: PSmallint; samples: Smallint); cdecl; external libprojectM name 'addPCM16Data'; procedure _addPCM8_512(pcm_data: PPCM8_512); cdecl; external libprojectM name 'addPCM8'; { console_interface.h declarations } procedure _key_handler(pm: _PProjectM; event: TProjectMEvent; keycode: TProjectMKeycode; modifier: TProjectMModifier); cdecl; external libprojectM name 'key_handler'; {**************** EXTERNAL SECTION ****************} constructor TProjectM.Create(gx, gy: integer; fps: integer; texsize: integer; width, height: integer; presetsDir, fontsDir: string); var pm: _PProjectM; begin New(pm); _pm := pm; _projectM_reset(pm); pm^.fullscreen := 0; pm^.renderTarget^.texsize := texsize; pm^.gx := gx; pm^.gy := gy; pm^.fps := fps; pm^.renderTarget^.usePbuffers := 0; pm^.fontURL := PChar(fontsDir); pm^.presetURL := PChar(presetsDir); _projectM_init(pm); end; procedure TProjectM.ResetGL(width, height: Integer); begin _projectM_resetGL(_pm, width, height); end; procedure TProjectM.SetTitle(title: string); var pm: _PProjectM; begin pm := _pm; pm^.title := PChar(title); pm^.showtitle := 1; end; procedure TProjectM.RenderFrame(); begin _renderFrame(_pm); end; procedure TProjectM.AddPCMfloat(pcmData: PSingle; samples: integer); begin _addPCMfloat(pcmData, samples); end; procedure TProjectM.AddPCM16(pcmData: PPCM16); begin _addPCM16(pcmData); end; procedure TProjectM.AddPCM16Data(pcmData: PSmallint; samples: Smallint); begin _addPCM16Data(pcmData, samples); end; procedure TProjectM.AddPCM8_512(pcmData: PPCM8_512); begin _addPCM8_512(pcmData); end; procedure TProjectM.KeyHandler(event: TProjectMEvent; keycode: TProjectMKeycode; modifier: TProjectMModifier); begin _key_handler(_pm, event, keycode, modifier); end; procedure TProjectM.RandomPreset(); begin KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_r_LOWERCASE, PROJECTM_KMOD_LSHIFT); end; procedure TProjectM.PreviousPreset(); begin KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_p_LOWERCASE, PROJECTM_KMOD_LSHIFT); end; procedure TProjectM.NextPreset(); begin KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_n_LOWERCASE, PROJECTM_KMOD_LSHIFT); end; procedure TProjectM.ToggleShowPresetNames(); begin KeyHandler(PROJECTM_KEYDOWN, PROJECTM_K_F3, PROJECTM_KMOD_LSHIFT); end; destructor TProjectM.Destroy(); begin Dispose(_PProjectM(_pm)); _pm := nil; end; end.