#!/usr/bin/perl use strict; use warnings; use SDL; use SDL::App; use SDL::Surface; use SDL::Cursor; use SDL::Event; use SDL::Mixer; use SDL::Sound; use SDL::TTFont; # Constants my $padding = 3; # Find and handle arguments my $numArgs = $#ARGV + 1; my ($width, $height, $box_size) = ( 11, 3, 80); my $app = new SDL::App( -title=>'Keyboard', -width=>$width * $box_size + $padding, -height=>$height * $box_size + $padding, -depth=>32, -flags=>SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWACCEL, ); my $mixer = new SDL::Mixer(-frequency=>44100, -channels=>2, -size=>1024); my @rects = (); my @sounds = (); my @modified_areas = (); my ($colorOn, $colorOff); my $lastPress = 0; my $actions_playing = { SDL_KEYDOWN() => \&process_event_playing_keypress, }; my $actions = $actions_playing; &event_loop(); sub event_loop { my $next_heartbeat = $app->ticks; my $event = new SDL::Event; # Load Sounds for( my $i = 1; $i <= 11; $i ++ ) { @sounds = (@sounds, new SDL::Sound("./instruments/guitar/I$i.wav"), new SDL::Sound("./instruments/piano/I$i.wav"), new SDL::Sound("./instruments/drums/I$i.wav")); } $colorOff = new SDL::Color(-r=>95, -g=>95, -b=>95); $colorOn = new SDL::Color(-r=>25, -g=>25, -b=>150); # Build Boxes for (my $i = 0; $i < $width; $i ++ ) { for (my $j = 0; $j < $height; $j ++ ) { @rects = (@rects, new SDL::Rect( -x=>$i * $box_size + $padding, -y=>$j * $box_size + $padding, -width=>$box_size - $padding, -height=>$box_size - $padding )); } } clear_boxes(); $app->update(@modified_areas); MAIN_LOOP: while(1) { while ($event->poll) { my $type = $event->type(); last MAIN_LOOP if ($type == SDL_QUIT); last MAIN_LOOP if ($type == SDL_KEYDOWN && $event->key_name() eq 'escape'); if ( exists($actions->{$type}) && ref( $actions->{$type} ) eq "CODE" ) { $actions->{$type}->($event); } } $app->delay(5); } } sub clear_boxes() { for ( my $i = 0; $i < $width * $height; $i ++ ) { $app->fill($rects[$i], $colorOff); push(@modified_areas, $rects[$i]); } } sub handle_press { my ($key) = @_; $mixer->play_channel(-1, $sounds[$key], 0); $app->fill($rects[$lastPress], $colorOff); if ( $key % 3 == 0 ) { $app->fill($rects[$key + 2], $colorOn); $lastPress = $key + 2; } else { $app->fill($rects[$key - 1], $colorOn); $lastPress = $key - 1; } } sub process_event_playing_keypress { my $event = shift; my $key_name = $event->key_name(); # Piano if($key_name eq "q") { handle_press(1); } if($key_name eq "w") { handle_press(4); } if($key_name eq "e") { handle_press(7); } if($key_name eq "r") { handle_press(10); } if($key_name eq "t") { handle_press(13); } if($key_name eq "y") { handle_press(16); } if($key_name eq "u") { handle_press(19); } if($key_name eq "i") { handle_press(22); } if($key_name eq "o") { handle_press(25); } if($key_name eq "p") { handle_press(28); } if($key_name eq "[") { handle_press(31); } # Drums if($key_name eq "a") { handle_press(2); } if($key_name eq "s") { handle_press(5); } if($key_name eq "d") { handle_press(8); } if($key_name eq "f") { handle_press(11); } if($key_name eq "g") { handle_press(14); } if($key_name eq "h") { handle_press(17); } if($key_name eq "j") { handle_press(20); } if($key_name eq "k") { handle_press(23); } if($key_name eq "l") { handle_press(26); } if($key_name eq ";") { handle_press(29); } if($key_name eq "'") { handle_press(32); } # Guitar if($key_name eq "z") { handle_press(0); } if($key_name eq "x") { handle_press(3); } if($key_name eq "c") { handle_press(6); } if($key_name eq "v") { handle_press(9); } if($key_name eq "b") { handle_press(12); } if($key_name eq "n") { handle_press(15); } if($key_name eq "m") { handle_press(18); } if($key_name eq ",") { handle_press(21); } if($key_name eq ".") { handle_press(24); } if($key_name eq "/") { handle_press(27); } if($key_name eq "right shift") { handle_press(30); } $app->update(@modified_areas); }