File Coverage

blib/lib/POE/Framework/MIDI/Conductor.pm
Criterion Covered Total %
statement 616 631 97.6
branch 16 34 47.0
condition 3 9 33.3
subroutine 17 18 94.4
pod 0 14 0.0
total 652 706 92.3


line stmt bran cond sub pod time code
1             # $Id: Conductor.pm,v 1.3 2004/12/11 16:24:23 root Exp $
2              
3             package POE::Framework::MIDI::Conductor;
4              
5 6     6   210803 use strict;
  6         10  
  6         207  
6 6     6   29 use vars '$VERSION'; $VERSION = '0.02';
  6         10  
  6         9003  
7              
8             sub new {
9 7     7 0 10754 my ( $self, $class ) = ({}, shift);
10 7 50       50 $self->{cfg} = shift or die "I need a config hashref to start the conductor.";
11 7         26 bless( $self, $class );
12 7         47 $self->{bars} = {};
13 7         31 return $self;
14             }
15              
16             sub musician_names {
17 4     4 0 17 my $self = shift;
18 4 50       23 my $musicians = $self->{cfg}->{musicians} or die "no musicians defined in config";
19 4         7 my $to_return;
20 4         13 for (@$musicians) {
21 9         28 push @$to_return, $_->{name};
22             }
23 4         16 return $to_return;
24             }
25              
26             # register a bar/phrase in the internal datastructure
27             sub add_bar {
28 58     58 0 166 my $self = shift;
29 58         64 my $params = shift;
30 58 50 33     444 die "Malformed add_bar data - " . Dumper($params) . "\n\n"
      33        
31             unless ($params->{musician_name} and $params->{barnum} and $params->{bar});
32 58 50       175 die "$params->{bar} isn't a P:F:M:Bar object"
33             unless (ref($params->{bar}) =~ /POE::Framework::MIDI::Bar/);
34 58         310 $self->{bars}->{$params->{musician_name}}->{$params->{barnum}} = $params->{bar};
35             }
36              
37              
38             sub bars {
39 1     1 0 2 my $self = shift;
40 1         5 return $self->{bars};
41             }
42              
43             # convert event objects (note, rest, bar, etc) to perl code for
44             # midi simple. this gets pretty ugly.
45             sub render {
46 3 50   3 0 17 my ( $self, $filename ) = @_ or die "render needs a filename to render to";
47 3         13 my $musicians = $self->{cfg}->{musicians};
48 3         24 my $perlcode = $self->perl_head;
49            
50 3         10 for my $musician (@$musicians) {
51 6         20 my $events = $self->{bars}->{$musician->{name}};
52 6         38 my $musician_perlcode = $self->musician_subroutine_header($musician);
53 6         14 my $channel = $musician->{channel};
54 6         9 my $patch = $musician->{patch};
55            
56 6         51 for my $event (
  132         320  
57             sort { $events->{$a}->number <=> $events->{$b}->number }
58             keys %$events
59             ) {
60             # $this_event is a bar, a phrase or maybe a noop
61 57         90 my $this_event = $events->{$event};
62            
63             # we need the events out of the bar or phrase
64 57         157 my $eventstack = $this_event->events;
65 57         73 my $printwrap = 5; # how many events to print per line..so we can debug later
66 57         57 my $wrap;
67              
68 57         97 for my $stackitem (@$eventstack) {
69 543         570 ++$wrap;
70 543         1132 $musician_perlcode .= $self->perl_from_event(
71             event => $stackitem,
72             musician_name => $musician->{name}) .'; ';
73 543 100       1240 if ($wrap >= $printwrap) {
74 90         113 $musician_perlcode .= "\n\t";
75 90         127 $wrap = 0;
76             }
77             }
78             }
79            
80 6         73 $perlcode .= $musician_perlcode . "\n}";
81             }
82              
83 3 50       21 if ($self->{cfg}->{debug}) {
84 0 0       0 open DEBUG, ">debug.perl" or die "Can't open debug.perl for writing - $!\n";
85 0         0 print DEBUG $perlcode;
86 0         0 close DEBUG;
87             }
88              
89 3 50   3 0 28 eval "$perlcode" or
  3     3 0 13  
  3     1 0 1529  
  3     1 0 17  
  3     1 0 6  
  3     2   37584  
  3     1   454  
  1         225  
  1         85  
  1         43  
  1         88  
  1         52  
  1         148  
  1         117  
  1         88  
  1         52  
  1         95  
  1         97  
  1         87  
  1         53  
  1         85  
  1         83  
  1         128  
  1         53  
  1         134  
  1         44  
  1         77  
  1         37  
  1         134  
  1         52  
  1         80  
  1         95  
  1         104  
  1         92  
  1         103  
  1         78  
  1         130  
  1         55  
  1         78  
  1         76  
  1         75  
  1         89  
  1         135  
  1         101  
  1         67  
  1         41  
  1         130  
  1         288  
  1         83  
  1         75  
  1         74  
  1         46  
  1         86  
  1         115  
  1         118  
  1         53  
  1         98  
  1         77  
  1         75  
  1         47  
  1         102  
  2         114  
  2         181  
  2         97  
  2         455  
  2         406  
  2         345  
  2         338  
  2         437  
  2         433  
  2         450  
  2         465  
  2         450  
  2         459  
  2         451  
  2         456  
  2         410  
  2         389  
  1         104  
  1         109  
  1         107  
  1         99  
  1         115  
  1         95  
  1         97  
  1         101  
  1         109  
  1         105  
  1         142  
  1         105  
  1         106  
  1         105  
  1         101  
  1         101  
  1         105  
  1         115  
  1         116  
  1         121  
  1         135  
  1         115  
  1         120  
  1         117  
  1         117  
  1         143  
  1         125  
  1         113  
  1         114  
  1         127  
  1         113  
  1         110  
  1         107  
  1         108  
  1         110  
  1         111  
  1         111  
  1         109  
  1         114  
  1         117  
  1         99  
  1         100  
  1         97  
  1         109  
  1         98  
  1         161  
  1         101  
  1         97  
  1         94  
  1         93  
  1         100  
  1         108  
  1         106  
  1         97  
  1         102  
  1         96  
  1         166  
  1         106  
  1         102  
  1         107  
  1         120  
  1         107  
  1         104  
  1         104  
  1         102  
  1         104  
  1         105  
  1         103  
  1         104  
  1         100  
  1         99  
  1         100  
  1         103  
  1         105  
  1         104  
  1         105  
  1         113  
  1         105  
  1         100  
  1         104  
  1         104  
  1         129  
  1         114  
  1         161  
  1         121  
  1         111  
  1         111  
  1         109  
  1         111  
  1         109  
  1         118  
  1         125  
  1         137  
  1         113  
  1         111  
  1         108  
  1         111  
  1         110  
  1         110  
  1         112  
  1         110  
  1         109  
  1         124  
  1         96  
  1         101  
  1         111  
  1         102  
  1         111  
  1         94  
  1         104  
  1         104  
  1         105  
  1         101  
  1         107  
  1         108  
  1         105  
  1         103  
  1         105  
  1         108  
  1         145  
  1         106  
  1         106  
  1         116  
  1         100  
  1         101  
  1         102  
  1         106  
  1         104  
  1         106  
  1         122  
  1         106  
  1         102  
  1         106  
  1         106  
  1         105  
  1         106  
  1         103  
  1         118  
  1         203  
  1         99  
  1         97  
  1         106  
  1         108  
  1         111  
  1         106  
  1         122  
  1         113  
  1         113  
  1         112  
  1         111  
  1         110  
  1         110  
  1         116  
  1         141  
  1         8517  
  1         148  
  1         105  
  1         103  
  1         104  
  1         122  
  1         125  
  1         105  
  1         102  
  1         105  
  1         102  
  1         94  
  1         95  
  1         102  
  1         108  
  1         97  
  1         101  
  1         95  
  1         103  
  1         97  
  1         99  
  1         98  
  1         99  
  1         97  
  1         96  
  1         100  
  1         95  
  1         95  
  1         96  
  1         109  
  1         104  
  1         101  
  1         96  
  1         100  
  1         92  
  1         174  
  1         107  
  1         109  
  1         115  
  1         113  
  1         115  
  1         113  
  1         114  
  1         117  
  1         183  
  1         133  
  1         118  
  1         115  
  1         117  
  1         114  
  1         114  
  1         117  
  1         119  
  1         115  
  1         125  
  1         114  
  1         114  
  1         115  
  1         118  
  1         122  
  1         121  
  1         110  
  1         103  
  1         105  
  1         100  
  1         95  
  1         94  
  1         99  
  1         100  
  1         131  
  1         101  
  1         116  
  1         81  
  1         61  
  1         103  
  1         97  
  1         110  
  1         98  
  1         97  
  1         100  
  1         116  
  1         97  
  1         95  
  1         93  
  1         104  
  1         108  
  1         101  
  1         103  
  1         95  
  1         106  
  1         104  
  1         105  
  1         121  
  1         109  
  1         125  
  1         125  
  1         117  
  1         120  
  1         118  
  1         120  
  1         117  
  1         114  
  1         114  
  1         115  
  1         118  
  1         118  
  1         115  
  1         173  
  1         119  
  1         115  
  1         115  
  1         119  
  1         119  
  1         117  
  1         119  
  1         104  
  1         123  
  1         97  
  1         109  
  1         103  
  1         98  
  1         96  
  1         107  
  1         102  
  1         105  
  1         100  
  1         98  
  1         98  
  1         97  
  1         98  
  1         102  
  1         99  
  1         98  
  1         94  
  1         97  
  1         103  
  1         109  
  1         102  
  1         128  
  1         94  
  1         109  
  1         104  
  1         105  
  1         103  
  1         143  
  1         110  
  1         103  
  1         102  
  1         103  
  1         107  
  1         105  
  1         106  
  1         104  
  1         115  
  1         177  
  1         101  
  1         105  
  1         107  
  1         125  
  1         118  
  1         111  
  1         118  
  1         118  
  1         113  
  1         118  
  1         121  
  1         119  
  1         112  
  1         124  
  1         128  
  1         122  
  1         118  
  1         117  
  1         113  
  1         108  
  1         116  
  1         110  
  1         108  
  1         137  
  1         123  
  1         104  
  1         97  
  1         97  
  1         97  
  1         109  
  1         95  
  1         99  
  1         99  
  1         97  
  1         127  
  1         99  
  1         99  
  1         99  
  1         98  
  1         98  
  1         100  
  1         109  
  1         96  
  1         99  
  1         103  
  1         104  
  1         101  
  1         106  
  1         102  
  1         93  
  1         104  
  1         96  
  1         107  
  1         103  
  1         105  
  1         101  
  1         108  
  1         104  
  1         107  
  1         104  
  1         117  
  1         108  
  1         4355  
  1         126  
  1         101  
  1         101  
  1         101  
  1         99  
  1         98  
  1         95  
  1         138  
  1         102  
  1         103  
  1         106  
  1         98  
  1         123  
  1         106  
  1         109  
  1         107  
  1         100  
  1         105  
  1         106  
  1         104  
  1         102  
  1         106  
  1         106  
  1         104  
  1         105  
  1         105  
  1         103  
  1         112  
  1         101  
  1         106  
  1         107  
  1         105  
  1         108  
  1         107  
  1         143  
  1         109  
  1         104  
  1         190  
  1         123  
  1         111  
  1         119  
  1         113  
  1         108  
  1         130  
  1         112  
  1         111  
  1         107  
  1         112  
  1         108  
  1         125  
  1         113  
  1         112  
  1         111  
  1         108  
  1         108  
  1         114  
  1         127  
  1         111  
  1         118  
  1         107  
  1         128  
  1         106  
  1         98  
  1         99  
  1         98  
  1         105  
  1         105  
  1         104  
  1         106  
  1         199  
  1         118  
  1         108  
  1         105  
  1         113  
  1         105  
  1         104  
  1         103  
  1         100  
  1         100  
  1         122  
  1         116  
  1         109  
  1         107  
  1         104  
  1         103  
  1         104  
  1         102  
  1         100  
  1         94  
  1         104  
  1         82  
  1         82  
  1         81  
  1         80  
  1         80  
90             die "uh oh - bad stuff happened during rendering: " . join "\n", $@;
91             }
92              
93             # header chunk of perl code for eventual eval
94             sub perl_head {
95 4     4 0 10 my $self = shift;
96 4         851 my $now = scalar(localtime);
97 4         32 my $code = qq!
98             # magically generated by $0 - $now
99            
100             use MIDI::Simple;
101             no strict 'subs';
102             new_score;
103             set_tempo 500000;
104              
105             synch(! ;
106             # add the subroutine refs
107 4         10 for (@{$self->{cfg}->{musicians}}) {
  4         69  
108 9         36 $code .= "\\&$_->{name},";
109             }
110 4         38 $code =~ s/\,$/)\;\n\n/;
111              
112 4         18 $code .= "\nwrite_score '$self->{cfg}->{filename}';\n\n";
113 4         17 return $code;
114             }
115              
116             # create perlcode from an event for eventual
117             # eval to MIDI::Simple code.
118             sub perl_from_event {
119 544     544 0 627 my $self = shift;
120             #my $p = shift;
121 544         1199 my %params = @_;
122 544 50 33     2213 die "perl from event needs an event, and a musician_name: \n\n"
123             unless ($params{event} and $params{musician_name});
124              
125             # what type of event do we have?
126              
127             # should MIDI::Bar recursively call this sub for notes and rests, or keep
128             # the seperate code?
129 544         758 my $eventname = ref $params{event};
130              
131 544 50       1315 if ($eventname eq 'POE::Framework::MIDI::Bar') {
    100          
    100          
    50          
132 0         0 my $stack = $params{event}->events; # get the bar's eventstack
133              
134 0         0 for my $stackitem (@$stack) {
135 0 0       0 if ($eventname eq 'POE::Framework::MIDI::Note') {
    0          
136 0         0 my $duration = $stackitem->duration;
137 0         0 my $note = $stackitem->note;
138             # n wn, Cs4
139 0         0 return "n $duration, $note";
140             }
141             elsif ($eventname eq 'POE::Framework::MIDI::Rest') {
142 0         0 my $duration = $stackitem->duration;
143 0         0 return "r $duration";
144             }
145             }
146             }
147             elsif ($eventname eq 'POE::Framework::MIDI::Note') {
148 517         1323 my $duration = $params{event}->duration;
149 517         1285 my $note = $params{event}->note;
150             # n wn, Cs4
151 517         1358 return "n $duration, $note";
152             }
153             elsif ($eventname eq 'POE::Framework::MIDI::Rest') {
154 12         32 my $duration = $params{event}->duration;
155 12         39 return "r $duration";
156             }
157             elsif($eventname eq 'POE::Framework::MIDI::Interval') {
158 15         48 my $duration = $params{event}->duration;
159 15         49 my $notes = $params{event}->notes;
160 15         80 return "n $duration, " . join ",", @$notes;
161             }
162            
163             else {
164 0         0 warn "Unhandled event type $params{event} ignored";
165             }
166             }
167              
168             # the perl code to start a musician subroutine for MIDI::Simplels
169             # 'synch' function
170             sub musician_subroutine_header {
171 6     6 0 13 my ($self,$musician) = @_;
172 6         20 my ($name,$channel,$patch) = ($musician->{name}, $musician->{channel},$musician->{patch});
173            
174 6         35 return qq!
175             sub $name {
176             noop c$channel, f, o4;
177             patch_change $channel, $patch;
178             #instrument_name $name;
179              
180             !;
181             }
182              
183             # eventually this should evolve into a way for musicians or $self to query about
184             # what any musician played in any bar for follow the leader-type-stuff, and so on.
185             sub query {
186 0     0 0 0 my $self = shift;
187 0 0       0 my $querystring = shift or die __PACKAGE__ . "query needs a querystring";
188 0         0 print "query $querystring\n";
189             }
190              
191             1;
192              
193             __END__