BEGIN {
	# XSUB imports
	OpenGL::boot_OpenGL();
	FMOD::boot_FMOD();
	Image::boot_Image();
	PolyRender::boot_PolyRender();
	PBuffer::boot_PBuffer();
	GLSL::boot_GLSL();
	GLSLQuad::boot_GLSLQuad();
	OSG::boot_OSG();
	PlasmaCube::boot_PlasmaCube();
}

use strict;
use warnings;

use GLSLPost;
use Program;
use SVG;
use Mixer;

use XML::Parser;
use XML::Simple;
use Data::Dumper;

# global crud
my $PI = 3.1415926535;
my $white = pack("CCCC", 255,255,255,255);

our $pbuffers = [];

# 5 sec logo + 1 sec ruis overflow
# 2.22 end == 142 sec - 6 sec == 136
# 5 sec silence (foto, rot -10 -> -30 deg, white border)
my $start = [
	# logo zoom
	[    0, NEW, "Image", 0, "logo", { image => "fm.jpg", alignh => 1, alignv => 1, size => 3.0, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[ 5000, FLT, "logo", { size => 3.5 } ],
	[ 5500, DEL, "logo" ],

	# start ruis
	[ 5000, NEW, "Image", 1, "white", { imagedata => \$white, width => 1, height => 1, alignv => 1, alignh => 1.0, size => 3.0, r => 1.0, g => 1.0, b => 1.0, alpha => 0.2 } ],
	[ 5000, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 1.0 } ],
#	[ 5750, SET, "ruis", { greyness => 1.0 } ],
#	[ 6000, FLT, "ruis", { greyness => 0.0, alpha => 0.0 } ],
	[ 6000, FLT, "white", { alpha => 0.6 } ],
	[ 6000, DEL, "ruis" ],
	[ 6000, DEL, "white" ],
];

my $end = [
	# xfade from cf
	[ 00, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 0.0, greyness => 1.0 } ],
	[ 500, FLT, "ruis", { greyness => 0.0, alpha => 1.0 } ],
	[ 500, DEL, "ruis" ],

	# foto zoom
	[    0, NEW, "Image", 0, "actionshot", { image => "foto.jpg", alignh => 1, alignv => 1, rot => -8.0, size => 2.0, r => 1.0, g => 1.0, b => 1.0, alpha => 1.0 } ],
#	[  500, FLT, "actionshot", { rot => 2.0, alpha => 1.0 } ],
	[ 5000, FLT, "actionshot", { rot => 12.0 } ],
	[ 7000, FLT, "actionshot", { rot => 20.0, alpha => 0.0 } ],
	[ 7000, DEL, "actionshot" ],

	# dead battery blink
	[   0, NEW, "Image", 1000, "zoombar", { image => "images/zoombar.png", x => 0.7, y => 1.0, alignh => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[ 000, NEW, "Image", 1000, "battery", { image => "images/battrdead.png", x => 1.0, y => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[ 500, SET, "battery", { alpha => 0 } ], [1000, SET, "battery", { alpha => 1 } ],
	[1500, SET, "battery", { alpha => 0 } ], [2000, SET, "battery", { alpha => 1 } ],
	[2500, SET, "battery", { alpha => 0 } ], [3000, SET, "battery", { alpha => 1 } ],
	[3500, SET, "battery", { alpha => 0 } ], [4000, SET, "battery", { alpha => 1 } ],
	[4500, SET, "battery", { alpha => 0 } ], [5000, SET, "battery", { alpha => 1 } ],
	[5500, SET, "battery", { alpha => 0 } ], [6000, SET, "battery", { alpha => 1 } ],
	[6500, SET, "battery", { alpha => 0 } ], [7000, SET, "battery", { alpha => 1 } ],

	# end ruis
	[ 5000, NEWPOST, "GLSLPost", 2500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 0.0 } ],
	[ 9000, FLT, "ruis", { greyness => 1.0, alpha => 0.0 } ],
];

# programs
my $cf = [
	# fade over ruis
	[    0, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 1.0 } ],
#	[  750, SET, "ruis", { greyness => 1.0 } ],
	[ 1000, FLT, "ruis", { greyness => 0.0 } ],
	[ 1000, DEL, "ruis" ],

	# zoom bar .. controlled by fattest hack ever
	[    0, NEW, "Image", 2000, "zoombar", { image => "images/zoombar.png", x => 0.7, y => 1.0, alignh => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[    0, NEW, "Image", 2000, "zoombalk1", { image => "images/zoombalk.png", x => 0.62, y => 0.9, alignh => 1.0, size => 0.1, r => 1.0, g => 1.0, b => 1.0, fova => 1.1 } ],
	[    0, NEW, "Image", 2000, "zoombalk2", { image => "images/zoombalk.png", x => 0.67, y => 0.9, alignh => 1.0, size => 0.1, r => 1.0, g => 1.0, b => 1.0, fova => 0.88 } ],
	[    0, NEW, "Image", 2000, "zoombalk3", { image => "images/zoombalk.png", x => 0.72, y => 0.9, alignh => 1.0, size => 0.1, r => 1.0, g => 1.0, b => 1.0, fova => 0.76 } ],
	[    0, NEW, "Image", 2000, "zoombalk4", { image => "images/zoombalk.png", x => 0.77, y => 0.9, alignh => 1.0, size => 0.1, r => 1.0, g => 1.0, b => 1.0, fova => 0.68 } ],

	# battery drainage
	[     0, NEW, "Image", 2000, "battery", { image => "images/battr100.png", x => 1.0, y => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[ 16000, NEW, "Image", 2000, "battery", { image => "images/battr090.png", x => 1.0, y => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[ 32000, NEW, "Image", 2000, "battery", { image => "images/battr080.png", x => 1.0, y => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[ 48000, NEW, "Image", 2000, "battery", { image => "images/battr070.png", x => 1.0, y => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[ 64000, NEW, "Image", 2000, "battery", { image => "images/battr060.png", x => 1.0, y => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[ 80000, NEW, "Image", 2000, "battery", { image => "images/battr040.png", x => 1.0, y => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[ 96000, NEW, "Image", 2000, "battery", { image => "images/battr030.png", x => 1.0, y => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[128000, NEW, "Image", 2000, "battery", { image => "images/battr020.png", x => 1.0, y => 1.0, size => 0.3, r => 1.0, g => 1.0, b => 1.0, alpha => 1 } ],
	[136000, DEL, "battery" ],

	# plasma cube in second reality
	[ 48000, NEW, "PlasmaCube", 300, "pc", { x => 16.0, y => 5.0, z => -2.0, alpha => 1.0 } ],
 	[ 58000, FLT, "pc", { x => 16.0, y => 5.0, z => -2.0, alpha => 1.0 } ],
 	[ 59000, FLT, "pc", { x => 16.0, y => 5.0, z => -2.0, alpha => 0.0 } ],
	[ 59000, DEL, "pc" ],

	# demo parts
    [ 00000, NEW, "OSG", 100, "greets",	{ fname => "cfmodels/demos.IVE" }, ], [ 16000, DEL, "greets" ],
    [ 16000, NEW, "OSG", 100, "jarig",	{ fname => "cfmodels/rob.IVE" }, ], [ 32000, DEL, "jarig" ],
	[ 32000, NEW, "OSG", 100, "outline",	{ fname => "cfmodels/outline.IVE" }, ], [ 48000, DEL, "outline" ],
    [ 48000, NEW, "OSG", 100, "second",	{ fname => "cfmodels/second.IVE" }, ], [ 60000, DEL, "second" ],
    [ 60000, NEW, "OSG", 100, "foto",	{ fname => "cfmodels/foto.IVE" }, ], [ 76000, DEL, "foto" ],
    [ 76000, NEW, "OSG", 100, "popular",	{ fname => "cfmodels/popular.IVE" }, ], [ 100000, DEL, "popular" ],
	[ 100000, NEW, "OSG", 100, "demos",	{ fname => "cfmodels/greets.IVE" }, ], [ 116000, DEL, "demos" ],
    [ 116000, NEW, "OSG", 100, "disko",	{ fname => "cfmodels/experiment.IVE" }, ], [ 128000, DEL, "disko" ],
     [ 128000, NEW, "OSG", 100, "einde",	{ fname => "cfmodels/credits.IVE" }, ], [ 136000, DEL, "einde" ],

	# foto flash
    [ 68000, NEWPOST, "GLSLPost", 1500, "flash", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/flash.glslf", white => 0.0 } ],
	[ 68100, FLT, "flash", { white => 1.0 } ], [ 68200, FLT, "flash", { white => 0.0 } ],
	[ 68300, FLT, "flash", { white => 1.0 } ], [ 68400, FLT, "flash", { white => 0.0 } ],
	[ 68500, FLT, "flash", { white => 1.0 } ], [ 68600, FLT, "flash", { white => 0.0 } ],
#	[ 68000, FLT, "flash", { white => 0.0 } ],
#	[ 68100, FLT, "flash", { white => 1.0 } ], [ 68200, FLT, "flash", { white => 0.0 } ],
#	[ 68300, FLT, "flash", { white => 1.0 } ], [ 68400, FLT, "flash", { white => 0.0 } ],
#	[ 68500, FLT, "flash", { white => 1.0 } ], [ 68600, FLT, "flash", { white => 0.0 } ],

	# scene fade ruises
	# greets -> jarig
	[ 15000, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 0.0 } ],
	[ 16000, FLT, "ruis", { greyness => 1.0, alpha => 0.0 } ],
	[ 16500, FLT, "ruis", { greyness => 0.0, alpha => 1.0 } ],
	[ 16500, DEL, "ruis" ],
	# jarig -> outline
	[ 31000, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 0.0 } ],
	[ 32000, FLT, "ruis", { greyness => 1.0, alpha => 0.0 } ],
	[ 32500, FLT, "ruis", { greyness => 0.0, alpha => 1.0 } ],
	[ 32500, DEL, "ruis" ],
	# outline -> second
	[ 47000, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 0.0 } ],
	[ 48000, FLT, "ruis", { greyness => 1.0, alpha => 0.0 } ],
	[ 48500, FLT, "ruis", { greyness => 0.0, alpha => 1.0 } ],
	[ 48500, DEL, "ruis" ],
	# second -> foto
	[ 59000, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 0.0 } ],
	[ 60000, FLT, "ruis", { greyness => 1.0, alpha => 0.0 } ],
	[ 60500, FLT, "ruis", { greyness => 0.0, alpha => 1.0 } ],
	[ 60500, DEL, "ruis" ],
	# foto -> popular
	[ 75000, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 0.0 } ],
	[ 76000, FLT, "ruis", { greyness => 1.0, alpha => 0.0 } ],
	[ 76500, FLT, "ruis", { greyness => 0.0, alpha => 1.0 } ],
	[ 76500, DEL, "ruis" ],
	# popular -> demos thx
	[ 99000, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 0.0 } ],
	[ 100000, FLT, "ruis", { greyness => 1.0, alpha => 0.0 } ],
	[ 100500, FLT, "ruis", { greyness => 0.0, alpha => 1.0 } ],
	[ 100500, DEL, "ruis" ],
	# demos -> disko
	[ 115000, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 0.0 } ],
	[ 116000, FLT, "ruis", { greyness => 1.0, alpha => 0.0 } ],
	[ 116500, FLT, "ruis", { greyness => 0.0, alpha => 1.0 } ],
	[ 116500, DEL, "ruis" ],
	# disko -> einde credits
	[ 127000, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 0.0 } ],
	[ 128000, FLT, "ruis", { greyness => 1.0, alpha => 0.0 } ],
	[ 128500, FLT, "ruis", { greyness => 0.0, alpha => 1.0 } ],
	[ 128500, DEL, "ruis" ],
	# einde credits -> action shot ($end)
	[ 135000, NEWPOST, "GLSLPost", 1500, "ruis", { scale => 0, vertex => "shaders/post.glslv", fragment => "shaders/ruis.glslf", fname => "images/noise.jpg", alpha => 1.0, greyness => 0.0 } ],
	[ 136000, FLT, "ruis", { greyness => 1.0, alpha => 0.0 } ],
#	[ 136500, FLT, "ruis", { greyness => 0.0, alpha => 1.0 } ],
	[ 136500, DEL, "ruis" ],


	# default shaders
    [ 00000, NEWPOST, "GLSLPost", 1001,	"blur",	{ scale => -1, vertex => "shaders/post.glslv", fragment => "shaders/blur.glslf", radius => .010, mintex => [0,0,0] } ],
    [ 00000, NEWPOST, "GLSLPost", 1002,	"add",	{ scale => 1, additive => 0, alpha => .5 } ],

#    [ 00000, NEWPOST, "GLSLPost", 1001,	"vblur",	{ vertex => "shaders/post.glslv", fragment => "shaders/vecblur.glslf", blurvector => [0,.020] } ],
#    [ 00000, NEWPOST, "GLSLPost", 1001,	"hblur",	{ vertex => "shaders/post.glslv", fragment => "shaders/vecblur.glslf", blurvector => [.020,0] } ],
    [ 00000, NEWPOST, "GLSLPost", 1003,	"topgear",	{ fname => "images/topgear.jpg", vertex => "shaders/post.glslv", fragment => "shaders/overlay.glslf", brighten => 1.1 } ],
#   [ 00000, NEWPOST, "GLSLPost", 1001,	"topgear",	{ fname => "images/topgear_sub.jpg", vertex => "shaders/post.glslv", fragment => "shaders/subtract.glslf" } ],
#   [ 00000, NEWPOST, "GLSLPost", 1001,	"topgear",	{ fname => "images/topgear_contrast.jpg", vertex => "shaders/post.glslv", fragment => "shaders/contrast.glslf" } ],
#   [ 00000, NEWPOST, "GLSLPost", 1004,	"color",	{ vertex => "shaders/post.glslv", fragment => "shaders/red.glslf", color => [ 1,0,0,1 ] } ],

#    [ 05000, NEWPOST, "GLSLPost", 10002,	"blur",		{ vertex => "shaders/post.glslv", fragment => "shaders/red.glslf", color => [0,.6,.2,1] } ],
#	[ 2500, FLT, "overlay", { radius => 0.02 }, FLTINOUT ],
#	[ 5000, FLT, "overlay", { radius => 0.0 }, FLTINOUT ],

	# no more zoom
 	[136000, DEL, "zoombar" ],
 	[136000, DEL, "zoombalk1" ],
 	[136000, DEL, "zoombalk2" ],
 	[136000, DEL, "zoombalk3" ],
 	[136000, DEL, "zoombalk4" ],

	[136000, FLT, "fadeout", {} , ],
];

my $demo = [
	[      0, NEW, "Program", 100, "start", { program => $start } ],
	[   6000, DEL, "start" ],
	[   6000, NEW, "Program", 100, "cf", { program => $cf } ],
	[ 142000, DEL, "cf" ],
	[ 142000, NEW, "Program", 100, "end", { program => $end } ],
	[ 151000, DEL, "end" ],
];

sub main {
	my ($x, $y, $dc) = @_;
	my $msec = 000;
	my $finished = 0;
	my $space = 0;
	my $frames = 0;
	my ($fmod, $sound, $channel) = (0,0,0);
	my $fmod_enabled = 1;

	print "Loading FMOD\n";
 	if ($fmod_enabled) {
		$fmod = new FMOD();
		if (!$fmod->Init(2)) {
			print "FMOD failed\n";
			return 1;
		}
 	}

	# mja, not the place, maar wordt wel 1x gealloced nu ..
	$pbuffers = [new PBuffer(), new PBuffer()]; # pingpong buffers

	print "Setting up main Program\n";
	my $p = new Program($dc);
	$p->SetParams({program => $demo});

	print "Starting mp3 stream ..\n";
	if ($fmod_enabled) {
		$sound = $fmod->CreateSound("carnafestimail.mp3");
		$channel = $fmod->PlaySound($sound);
	}

	my $start = OpenGL::glGetTime();
	my $end;
	print "Starting render loop ..\n";
	while(!$finished) {
		OpenGL::glClear();

		$finished = $p->Render(OpenGL::glGetTime() - $start + $msec);

		OpenGL::SwapBuffers();
		$fmod->Update() if $fmod_enabled;

		$frames++;
		$end = OpenGL::glGetTime();
#		print "FPS: ".($frames / (($end - $start)/1000.0))."\r";
#		$| = 1;					# flush print

		OpenGL::glPumpEvents();
		if(OpenGL::glSpacePressed()) {
			if(!$space) {
				print "Pos: " .(OpenGL::glGetTime() - $start + $msec) . "\n";
				$space = 1;
			}
		} else {
			$space = 0;
		}
		if (OpenGL::glIsPressed('f')) {
			OpenGL::ToggleFullScreen();
		}
		if(OpenGL::glEscPressed()) {
			$finished = 1;
		}
		# spoeleuh!
		if(OpenGL::glRightPressed()) {
			$msec += 300;
			$fmod->SetSoundPos($channel, OpenGL::glGetTime() - $start + $msec) if $fmod_enabled;
		}
		if(OpenGL::glLeftPressed()) {
			# hmm... not really wanted effect for FLT variables :D
			$msec -= 300;
			$fmod->SetSoundPos($channel, OpenGL::glGetTime() - $start + $msec) if $fmod_enabled;	# here too!
		}
	}

	$end = OpenGL::glGetTime();
	print "Frames: ".$frames.", Start: ".$start.", End: ".$end."\n";
	print "FPS: ".($frames / (($end - $start)/1000.0))."\n";

	return 0;
}
