Skip to content

Instantly share code, notes, and snippets.

@vividsnow
Created May 17, 2013 00:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vividsnow/5596062 to your computer and use it in GitHub Desktop.
Save vividsnow/5596062 to your computer and use it in GitHub Desktop.
random stuff from live coding session using https://github.com/vividsnow/perl-live
# some handy modules to print things
use Data::Dump 'dd';
use DDP colored => 1, filters => { -external => [ 'PDL' ] };
dd my $h = bless { a => 1 }, 'test';
p $h
# ok - lets test scoping
say my $v = 0;
sub inc { state $i = 2; $v+=$i };
my $inc = sub { $v++ };
say $inc->();
say inc;
do {
my $v;
$v = 25;
say "inside $v";
};
say "ouside $v";
# now some PDL stuff
use PDL;
use PDL::Graphics::Simple;
p my $data = random(4,5) * sequence(4,5);
imag random(500,150);
use aliased 'Math::SegmentedEnvelope' => 'envelope';
map { line pdl envelope->new(is_morph=>1)->table(256) } 1..10;
hold;
release;
# we are in AnyEvent loop so..
my @codes;
my $w = AE::timer 0, 1, sub { map $_->(), @codes };
push @codes, sub { say 'hello world' };
undef $w; # stop timer
# or other AnyEvent stuff
use AnyEvent::Util;
(
fork_call {
dd "start..";
my $s = random(250,50,500);
"done!";
} sub { dd shift }
) # use C-M-x keybinding to eval everything between braces
use IO::Socket;
my ($s1, $s2) = IO::Socket->socketpair(AF_UNIX, SOCK_STREAM, PF_UNIX);
my $sr1 = AE::io $s1, 0, sub { print "on s1: ", scalar <$s1> };
my $sr2 = AE::io $s2, 0, sub { print "on s2: ", scalar <$s2> };
say $s2 'hi';
use AnyEvent::Fork;
(
AnyEvent::Fork->new->eval('
use PDL;
sub run {
my ($fh, $sock) = @_;
for (1..5) {
random((250)x3)->pow(3)->dims;
syswrite $sock, "fork-work - ok\n"
}
}')
->send_fh($s2)->run('run')
)
# live modification of http app
use Plack::Builder;
use Twiggy::Server;
my $r = sub { say 'got req'; join ' | ', (rand)x4; };
my $app = builder {
mount '/point' => sub { [200,[],[$r->()." what's up?\n"]] },
mount '/' => sub { [200,[],[$r->()." test\n"]] },
mount '/other' => sub { [200,[],[$r->()." hi\n"]] },
mount '/else' => sub { [200,[],[$r->()." else\n"]] }
};
my $server = Twiggy::Server->new(qw(port 9030));
$server->register_service($app);
$server->{exit_guard}->end; # stop listen
# another web server using AnyEvent::HTTPD
use AnyEvent::HTTPD;
use vars qw($hd $cb @cbs);#another approach for persist state - predefine globals
$hd = AnyEvent::HTTPD->new(port => 9020);
$cb = $hd->reg_cb( map { my $n = $_; '/'.$n => sub {
$_[1]->respond({ content => ['text/plain', "hi, ".ucfirst($n)."\n"] })
} } qw(one two tri) );
$hd->unreg_cb($cb);
# lets speak to SuperCollider using OSC
use Net::LibLO;
# same from perl
my $lo = Net::LibLO->new;
$lo->send(57120, '/beep', 'i', 100 * int rand(10) + 1);
# let it beep on http request
my $i = 0;
push my @cbs, $hd->reg_cb('/kick' => sub {
$lo->send(57120, '/beep', 'i', 100 * int rand(10) + 1);
$_[1]->respond({content => ['text/plain',"i beeped ".$i++." times\n"]});
})
# lets respond SuperCollider messages
$lo->add_method('/respond', "i", sub { dd splice(@_,5) });
say $lo->get_port;
my $osc_watch = AE::timer 0, 1/60, sub { $lo->recv_noblock };
# ok - now some OpenGL stuff
# init context
use OpenGL ':all';
use Async::Interrupt;
my %c = ( # window config
box => [(0)x2,450,220],
a => 60, np => 1, nf => 15 # view angle, near/far plane
);
glutInit();
glutInitWindowSize(@{$c{box}}[2,3]); glutInitWindowPosition(@{$c{box}}[0,1]);
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_ALPHA|GLUT_DEPTH);
glutSetWindow(glutCreateWindow('perl live demo'));
glShadeModel(GL_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS);
glutReshapeFunc(sub {
my @box = map glutGet(eval 'GLUT_WINDOW_'.$_), qw(WIDTH HEIGHT);
glViewport(0,0, @box);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective($c{a}, $box[0]/$box[1], $c{np}, $c{nf});
glMatrixMode(GL_MODELVIEW);
});
glutKeyboardFunc(sub {
my (@pos, $fullscreen);
my %key_action = (
p => sub { # quit
glutKeyboardFunc(0); glutReshapeFunc(0);
glutDestroyWindow(glutGetWindow());
},
f => sub { $fullscreen = $fullscreen ? do { # toggle fullscreen
glutReshapeWindow(@pos[2,3]);
glutPositionWindow(@pos[0,1]); 0
} : do {
@pos = map glutGet(eval "GLUT_WINDOW_".$_), qw(X Y WIDTH HEIGHT);
#glutFullScreen(); 1;
glutReshapeWindow(1280,720); glutPositionWindow(0,0); 1
} },
a => sub { say 'opengl key press' }
);
sub { if (my $cb = $key_action{chr $_[0]}) { $cb->() } }
}->());
my $start = AE::now;
my (@draw, @backup);
glutDisplayFunc(sub { my $dt = AE::now - $start;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 0);
glLoadIdentity();
map { glPushMatrix; $_->($dt); glPopMatrix } @draw;
glutSwapBuffers();
});
my $gl_watch = AE::timer(0, 1/60, sub {
glutMainLoopEvent;
glutPostRedisplay if glutGetWindow;
});
# ok - gl context!
# some aliases
(
*pum = \&glPushMatrix;
*clr = \&glColor4f;
*mov = \&glTranslatef;
*scl = \&glScaled;
*rot = \&glRotatef;
*ver = \&glVertex3f;
*pom = \&glPopMatrix;
*wsphere = \&glutWireSphere;
sub points { glBegin(GL_POINTS); shift->(); glEnd }
sub lines { glBegin(GL_LINES); shift->(); glEnd }
sub iso { glPushAttrib(GL_ALL_ATTRIB_BITS); shift->(); glPopAttrib }
)
# some time dependent variable
my $square_size;
my $w1 = AE::timer(0, 1/60, sub {
state $started = AE::now; state $e = envelope->new(is_morph => 1);
$square_size = $e->at(AE::now - $started);
});
undef $w1;
use Math::Trig 'pi';
(
push @draw, sub { my $ts = shift;
mov qw(0 0 -4);
clr qw(0.6 0.2 0.4 1);
scl (($square_size * 2.5)x2, 1);
rot (($ts + pi/3.4)*360, 0, 0, 1);
wsphere (0.5,(5)x2); scl ((0.1)x3);
}
)
# etc..
# time for shaders :)
# quick shader program
(
my $shader = sub {
my $id = glCreateProgramObjectARB;
my @objects = map {
glAttachObjectARB($id, $_);
glShaderSourceARB_p($_, shift); $_;
} map {
glCreateShaderObjectARB(eval 'GL_'.uc($_).'_SHADER');
} qw(fragment vertex);
glLinkProgramARB($id);
wantarray ? ($id, @objects) : $id;
}->(<<FRAG
uniform float time = 0.;
void main(void) {
float d = distance(vec2(0.5), gl_PointCoord);
if (d >= 0.5) { discard; }
gl_FragColor = vec4(gl_Color.rgb, (1. - pow(d*2.,2.)) * gl_Color.a * (cos(time) * 0.5 + 0.5));
}
FRAG
, <<VERT
void main(void) {
gl_Position = ftransform();
gl_FrontColor = gl_Color;
gl_PointSize = gl_Point.size;
}
VERT
);
)
# some routines to check state
map {say glGetInfoLogARB_p($_)} glGetAttachedObjectsARB_p($shader), $shader;
say gluErrorString(glGetError);
# and cleanup
map { glDeleteObjectARB($_) } glGetAttachedObjectsARB_p($shader), $shader;
map { glDeleteProgramsARB_p($_) } $shader;
# backup current draws
push my @backup, splice @draw;
# revert
push @draw, splice @backup;
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
glEnable(GL_POINT_SPRITE);
# shader test
(push @draw, sub {
my $ts = shift;
mov(-1,1,-5);
glUseProgramObjectARB($shader);
glUniform1fARB(glGetUniformLocationARB_p($shader, 'time'), $ts*7);
glPointSize(glutGet(GLUT_WINDOW_HEIGHT) * 0.4 * sin($ts) ** 2);
glBegin(GL_POINTS);
clr(cos($ts/2)/3+0.5,sin($ts*2)/3+0.5,cos($ts*5)/3+0.5,1);
glVertex3f(0,0,0);
glEnd;
glUseProgramObjectARB(0);
})
pop @draw;
# :) gl is fun
# ok - now gui showcase
undef $w1; # stop sizing
# GUIs!
use Gtk2;
Gtk2->init;
$gtk::window = Gtk2::Window->new ('toplevel');
$gtk::window->add (do {
my $button = Gtk2::Button->new ('Quit!');
$button->signal_connect (clicked => sub { print "gtk click\n" });
$button;
} );
$gtk::window->show_all;
use Wx;
use Wx::Event qw(EVT_BUTTON);
$wx::app = Wx::SimpleApp->new;
$wx::button = Wx::Button->new(
Wx::Panel->new($wx::frame = Wx::Frame->new( undef, -1, "wx" ), -1),
-1, 'Click me!', [30, 20], [-1, -1]
);
EVT_BUTTON( $wx::frame, $wx::button, sub { print "wx click\n" } );
$wx::frame->Show(1);
use Prima qw(Application Buttons);
$'prima = Prima::MainWindow->new(
text => 'Hello world!',
size => [ 200, 200],
)->insert(
Button => centered => 1,
text => 'Hello world!',
onClick => sub { print "prima click\n" },
);
use Tk;
$tk::mw = MainWindow->new;
$tk::mw->Button (
-text => "Hello World!",
-command => sub { print "tk click\n" }
)->pack;
# and SDL
use SDL;
use SDLx::App;
use SDL::Event;
use SDL::Events;
$sdl::event = SDL::Event->new;
$sdl::app = SDLx::App->new(
title => 'sdl', width => 150, height => 80, depth => 32
);
$sdl::poll = sub { while ( SDL::Events::poll_event($sdl::event) ) {
print "sdl click\n" if $sdl::event->type eq SDL_MOUSEBUTTONDOWN;
}};
# watch for their events
my $gui_events = AE::timer 0, 1/20, sub {
Gtk2->main_iteration_do("");
$wx::app->Yield;
$::application->yield;
DoOneEvent(Tk::DONT_WAIT() | Tk::ALL_EVENTS());
$sdl::poll->();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment