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(_pm);
_pm := nil;
end;
end.