File Coverage

blib/lib/App/Music/PlayTab.pm
Criterion Covered Total %
statement 203 317 64.0
branch 108 182 59.3
condition 9 26 34.6
subroutine 27 43 62.7
pod 0 39 0.0
total 347 607 57.1


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package App::Music::PlayTab;
4              
5             # Author : Johan Vromans
6             # Created On : Tue Sep 15 15:59:04 1992
7             # Last Modified By: Johan Vromans
8             # Last Modified On: Wed Mar 26 10:54:22 2014
9             # Update Count : 398
10             # Status : Unknown, Use with caution!
11              
12             ################ Common stuff ################
13              
14 2     2   1867 use strict;
  2         3  
  2         51  
15 2     2   8 use warnings;
  2         3  
  2         172  
16              
17             our $VERSION = "2.026";
18              
19             # Package or program libraries, if appropriate.
20             # $LIBDIR = $ENV{'LIBDIR'} || '/usr/local/lib/sample';
21             # use lib qw($LIBDIR);
22             # require 'common.pl';
23              
24             # Package name.
25             my $my_package = 'Sciurix';
26             # Program name and version.
27             my ($my_name, $my_version) = ( 'playtab', $VERSION );
28              
29 2     2   7 use base qw(Exporter);
  2         2  
  2         209  
30             our @EXPORT = qw(run);
31              
32             ################ Command line parameters ################
33              
34 2     2   1188 use Getopt::Long;
  2         14988  
  2         6  
35             sub app_options();
36              
37             my $output;
38             my $preamble;
39             my $gxpose = 0; # global xpose value
40             my $verbose = 0; # verbose processing
41             my $lilypond = 0; # use LilyPond syntax
42             my $bpm = 4;
43             my $syntax; # show syntax help
44              
45             # Development options (not shown with -help).
46             my $debug = 0; # debugging
47             my $trace = 0; # trace (show process)
48             my $test = 0; # test
49              
50             ################ Presets ################
51              
52             # Print dimensions.
53             my $std_width = 30;
54             my $std_height = -15;
55             my $std_margin = 40;
56             my $std_gridscale = 8;
57              
58             my @Rom = qw(I II III IV V VI VII VIII IX X XI XII);
59              
60             ################ The Process ################
61              
62             my $line; # current line (for messages)
63             my $linetype = 0; # type of current line
64             my $posttext;
65              
66             my $xpose = $gxpose;
67              
68             sub run {
69 2 50   2 0 613 local (@ARGV) = @_ ? @_ : @ARGV;
70              
71 2         5 app_options();
72 2 50       7 print STDOUT ("ok 1\n") if $test;
73              
74 2 50       5 if ( defined $output ) {
75 2 50 50     244 open(OUTPUT, ">$output") or print STDOUT ("not ") if $test;
76 2 50       13 print STDOUT ("ok 2\n") if $test;
77             }
78             else {
79 0 0       0 die("Test mode requires -output option to be set\n") if $test;
80 0         0 *OUTPUT = *STDOUT;
81             }
82              
83             # Options post-processing.
84 2   33     19 $trace |= ($debug || $test);
85              
86 2         4 ps_preamble();
87 2 50       6 print STDOUT ("ok 3\n") if $test;
88              
89 2         77 while ( <> ) {
90 56 50       119 next if /^\s*#/;
91 56 50 66     139 next if $lilypond && /^\s*%/;
92 56 100       77 $lilypond && s/\s+%\s*\d+\s*$//;
93 56 100       153 next unless /\S/;
94 46         57 chomp($line = $_);
95              
96 46         48 s/\^\s+//;
97 46 100       80 if ( /^!\s*(.*)/ ) {
98 12         16 control($1);
99 12         32 next;
100             }
101              
102 34 50       73 if ( /^\s*\[/ ) {
    50          
103 0         0 while ( /^\s*\[([^]]+)\](.*)/ ) {
104 0         0 eval { chord($1) };
  0         0  
105 0 0       0 errout($@) if $@;
106 0         0 $_ = $2;
107             }
108 0         0 $linetype = 2;
109 0         0 next;
110             }
111             elsif ( $linetype == 2 ) {
112 0         0 print_newline(4);
113 0         0 $linetype = 0;
114             }
115              
116 34 100 66     133 if ( /^\s*\|/ ) {
    100          
117 30 100       52 print_newline() if $linetype;
118 30         40 bar($_);
119 30         26 $linetype = 1;
120 30         180 next;
121             }
122             elsif ( $linetype == 1 && /^%?[-+=<]/ ) {
123 3         12 print_newline();
124 3         2 $linetype = 0;
125             }
126              
127             # Spacing/margin notes.
128 4 100       13 if ( /^%?=(.*)/ ) {
129 1         3 print_margin(2, $1);
130 1         1 $linetype = 0;
131 1         5 next;
132             }
133 3 50       11 if ( /^%?-(.*)/ ) {
134 3         8 print_margin(1, $1);
135 3         3 $linetype = 0;
136 3         8 next;
137             }
138 0 0       0 if ( /^%?\+(.*)/ ) {
139 0         0 print_margin(0, $1);
140 0         0 $linetype = 0;
141 0         0 next;
142             }
143 0 0       0 if ( /^%?\
144 0         0 print_margin(0, undef);
145 0         0 $linetype = 0;
146 0         0 next;
147             }
148              
149 0         0 text($_);
150 0         0 $linetype = 0;
151             }
152 2 50       11 print STDOUT ("ok 4\n") if $test;
153              
154 2         8 ps_trailer ();
155 2 50       10 print STDOUT ("ok 5\n") if $test;
156              
157 2 50       151 close OUTPUT if defined $output;
158 2 50       34 exit 0 unless $test;
159             }
160              
161             ################ Subroutines ################
162              
163             sub bar {
164 30     30 0 31 my ($line) = @_;
165              
166 30         55 on_top();
167              
168 30 100       36 if ( $lilypond ) {
169             # LilyPond chords use : and ., so don't split on these.
170 21         159 $line =~ s/([|`'])/ $1 /g; #'`])/;
171             }
172             else {
173 9         100 $line =~ s/([|.:`'])/ $1 /g; #'`])/;
174             }
175 30         179 $line =~ s/ +/ /g;
176              
177 30         82 my (@c) = split(' ', $line);
178 30         24 my $firstbar = 1;
179              
180 30         44 while ( @c > 0 ) {
181 519         354 eval {
182 519         361 my $c = shift(@c);
183 519 100       1010 if ( $c eq '|' ) {
    50          
    100          
    50          
    50          
    50          
    50          
    50          
184 141         150 print_bar($firstbar);
185 141         110 $firstbar = 0;
186             }
187             elsif ( $c eq ':' ) {
188 0         0 print_again();
189             }
190             elsif ( $c eq '.' ) {
191 260         243 print_space();
192             }
193             elsif ( $c eq '%' ) {
194 0         0 my $xs = 1;
195 0   0     0 while ( @c > 0 && $c[0] eq '.' ) {
196 0         0 shift(@c);
197 0         0 $xs++;
198             }
199 0         0 print_same('1', $xs);
200             }
201             elsif ( $c eq '-' ) {
202 0         0 print_rest();
203             }
204             elsif ( $c eq '\'' ) {
205 0         0 ps_skip(4);
206             }
207             elsif ( $c eq '`' ) {
208 0         0 ps_skip(-4);
209             }
210             elsif ( lc($c) eq 'ta' ) {
211 0         0 print_turnaround();
212             }
213             else {
214 118         115 ps_move();
215 118         113 my $chord = parse_chord($c);
216              
217 118 100       194 if ( $chord->is_rest ) {
218 7         7 print_rest();
219             }
220             else {
221 111 100       198 $chord->transpose($xpose) if $xpose;
222 111         129 print_chord($chord);
223 111         119 ps_step();
224             }
225 118 100       180 if ( my $d = $chord->duration ) {
226 81         121 $d = int($d / ($chord->duration_base / $bpm));
227 81         165 unshift(@c, ('.') x ($d-1));
228             }
229             }
230             };
231 519 50       710 die($@) if $@ =~ /can\'t locate/i;
232 519 50       981 errout($@) if $@;
233             }
234 30 50       41 if ( defined $posttext ) {
235 0         0 ps_skip(4);
236 0         0 ps_move();
237 0         0 print OUTPUT ('SF (', $posttext, ') show', "\n");
238 0         0 undef $posttext;
239             }
240 30         36 print_newline();
241             }
242              
243             sub control {
244 12     12 0 20 local ($_) = @_;
245              
246             # Title.
247 12 100       26 if ( /^t(itle)?\s+(.*)/i ) {
248 2         20 print_title(1, $+);
249 2         3 return;
250             }
251              
252             # Subtitle(s).
253 10 100       16 if ( /^s(ub(title)?)?\s+(.*)/i ) {
254 2         3 print_title(0, $+);
255 2         1 return;
256             }
257              
258             # Width adjustment.
259 8 100       18 if ( /^w(idth)?\s+([-+]?\d+)/i ) {
260 2         4 ps_set_width($2);
261 2         2 return;
262             }
263              
264             # Height adjustment.
265 6 100       11 if ( /^h(eight)?\s+([-+]?\d+)/i ) {
266 1         2 ps_set_height($2);
267 1         1 return;
268             }
269              
270             # Margin width adjustment.
271 5 50       8 if ( /^m(argin)?\s+([-+]?\d+)/i ) {
272 0         0 ps_set_margin($2);
273 0         0 return;
274             }
275              
276             # Transpose.
277 5 100       16 if ( /^x(pose)?\s+([-+])(\d+)/i ) {
278 1         2 $xpose += $2.$3;
279 1         1 return;
280             }
281              
282             # Bar numbering
283 4 100       7 if ( /^n(umber)?\s+([-+]?\d+)?/i ) {
284 1 50       9 set_barno(defined $2 ? $2 ? $2 < 0 ? $2+1 : $2 : undef : 1);
    50          
    50          
285 1         1 return;
286             }
287              
288             # LilyPond syntax
289 3 50       11 if ( /^l(?:y|ilypond)?(?:\s+(\d+))?/i ) {
290 3 100       6 $lilypond = defined $1 ? $1 : 1;
291 3 50 66     10 $bpm = ($lilypond && defined $1) ? $1 : 4;
292 3         4 return;
293             }
294              
295 0 0       0 if ( /^\>\s+(.+)/i ) {
296 0         0 $posttext = $1;
297 0         0 return;
298             }
299              
300              
301 0         0 errout("Unrecognized control");
302             }
303              
304             my $chordparser;
305             my $lilyparser;
306             sub parse_chord {
307 118     118 0 86 my $chord = shift;
308 118         75 my $parser;
309 118 100       135 if ( $lilypond ) {
310 81 100       104 unless ( $lilyparser ) {
311 1         491 require App::Music::PlayTab::LyChord;
312 1         12 $lilyparser = App::Music::PlayTab::LyChord->new;
313             }
314 81         66 $parser = $lilyparser;
315             }
316             else {
317 37 100       51 unless ( $chordparser ) {
318 2         538 require App::Music::PlayTab::Chord;
319 2         12 $chordparser = App::Music::PlayTab::Chord->new;
320             }
321 37         29 $parser = $chordparser;
322             }
323 118         217 $parser->parse($chord);
324             }
325              
326             sub chord {
327 0     0 0 0 my (@l) = split(' ',$_[0]);
328              
329 0 0 0     0 die("Illegal [chord] spec, need 7 or 8 values")
330             unless @l == 8 || @l == 7;
331              
332 0         0 my $cn = shift(@l);
333 0         0 my $chord = eval { parse_chord($cn) };
  0         0  
334              
335 0         0 my @c = ();
336 0         0 my $c = '()';
337 0         0 foreach ( @l ) {
338 0 0       0 $_ = -1 if lc($_) eq "x";
339 0 0       0 if ( /^@(\d+)/ ) {
340 0 0       0 $c = "($Rom[$1-1])" if $1 > 1;
341 0         0 next;
342             }
343 0 0 0     0 die("Illegal [chord] spec, need 6 numbers")
344             unless /^-?\d$/ || @c == 6;
345 0         0 push(@c, $_);
346             }
347              
348 0         0 on_top();
349              
350 0 0       0 my $ps = $chord ? $chord->ps : "($cn) root";
351              
352 0         0 print OUTPUT ('1000 1000 moveto', "\n",
353             $ps, "\n",
354             'currentpoint pop 1000 sub 2 div', "\n");
355 0         0 ps_move();
356 0         0 print OUTPUT (2.5*$std_gridscale, ' exch sub 8 add 0 rmoveto ',
357             $ps, "\n");
358 0         0 ps_move();
359 0         0 print OUTPUT ('8 ', -5-(4*$std_gridscale), " rmoveto @c $c dots\n");
360 0         0 ps_skip(80);
361             }
362              
363             sub text {
364 0     0 0 0 my ($line) = @_;
365 0         0 ps_push_actual_margin(0);
366 0         0 on_top();
367 0         0 ps_move();
368 0         0 print OUTPUT ('SF (', $line, ') show', "\n");
369 0         0 ps_advance();
370 0         0 ps_pop_actual_margin();
371             }
372              
373             sub errout {
374 0     0 0 0 my $msg = "@_";
375 0         0 $msg =~ s/ at .*line \d+.*//s;
376 0         0 warn("$msg\n", "Line $.: $line\n");
377             }
378              
379             ################ Print Routines ################
380              
381             my $x0 = 0;
382             my $y0 = 0;
383             my $x = 0;
384             my $y = 0;
385             my $xd = 0;
386             my $yd = 0;
387             my $xw = 0;
388             my $yd_width = 0;
389             my $xm = 0;
390             my $md = 0;
391             my $on_top = 0;
392             my $barno;
393              
394             sub set_barno {
395 1     1 0 2 $barno = shift;
396             }
397              
398             sub print_title {
399 4     4 0 10 my ($new, $title) = @_;
400              
401 4 100       8 if ( $new ) {
402 2         3 ps_page();
403             }
404 4         5 ps_move();
405 4 100       7 print OUTPUT ($new ? 'TF (' : 'SF (', $title, ') show', "\n");
406 4         6 ps_advance();
407 4         2 $on_top = 1;
408 4         4 undef $barno;
409 4         4 $xpose = $gxpose;
410             }
411              
412             # begin scope for $prev_chord
413             my $prev_chord;
414              
415             sub print_chord {
416 111     111 0 83 my($chord) = @_;
417 111         171 print OUTPUT ($chord->ps, "\n");
418 111         125 $prev_chord = $chord;
419             }
420              
421             sub print_again {
422 0     0 0 0 ps_move();
423 0         0 print OUTPUT ($prev_chord->ps, "\n");
424 0         0 ps_step();
425             }
426              
427             # end scope for $prev_chord
428              
429             sub print_bar {
430 141     141 0 104 my ($first) = @_;
431 141         148 ps_move();
432 141 100       144 if ( defined($barno) ) {
433 101 100       104 if ( $first ) {
434 22 100       37 print OUTPUT $barno > 0 ? ("($barno) barn\n") : ("bar\n");
435             }
436             else {
437 79         62 print OUTPUT ("bar\n");
438 79         54 $barno++;
439             }
440             }
441             else {
442 40         78 print OUTPUT ("bar\n");
443             }
444 141         149 ps_skip(4);
445             }
446              
447             sub print_newline {
448 58     58 0 56 &ps_advance;
449             }
450              
451             sub print_space {
452 260     260 0 215 ps_step();
453             }
454              
455             sub print_rest {
456 7     7 0 8 ps_move();
457 7         7 print OUTPUT ("rest\n");
458 7         9 ps_step();
459             }
460              
461             sub print_same {
462 0     0 0 0 my ($wh, $xs) = @_;
463 0         0 ps_push_x(($xs * $xd) / 2);
464 0         0 ps_move();
465 0         0 print OUTPUT ("same$wh\n");
466 0         0 ps_pop_x();
467 0         0 ps_skip($xs * $xd);
468             }
469              
470             sub print_turnaround {
471 0     0 0 0 ps_move();
472 0         0 print OUTPUT ("ta\n");
473 0         0 ps_step();
474             }
475              
476             sub print_margin {
477 4     4 0 7 my ($full, $margin) = @_;
478 4 100       8 unless ( on_top() ) {
479 3         5 ps_advance($full);
480             }
481 4 50       8 $xm = 0, return unless defined $margin;
482 4 100       11 return unless $margin =~ /\S/;
483 3         3 $margin =~ s/^\s+//;
484 3         4 $margin =~ s/\s$//;
485 3         2 $xm = 0;
486 3         5 ps_move();
487 3         4 print OUTPUT ('SF (', $margin, ') show', "\n");
488 3         3 $xm = $md;
489             }
490              
491             sub on_top {
492 34 100   34 0 49 return 0 unless $on_top;
493 2         3 $x = 0;
494 2         3 $y = 4*$yd;
495 2         2 $on_top = 0;
496 2         12 return 1;
497             }
498              
499             ################ PostScript routines ################
500              
501             my $ps_pages = 0;
502              
503             sub ps_page {
504 2 50   2 0 13 print OUTPUT ('end showpage', "\n") if $ps_pages;
505 2         6 print OUTPUT ('%%Page: ', ++$ps_pages. ' ', $ps_pages, "\n",
506             'tabdict begin', "\n");
507 2         3 $x = $y = $xm = 0;
508 2         2 $xd = $std_width;
509 2         2 $yd = $std_height;
510 2         2 $md = $std_margin;
511             }
512              
513             sub ps_set_margin {
514 0     0 0 0 my $v = shift;
515 0 0       0 croak("ps_set_margin: number or increment\n")
516             unless $v =~ /^([-+])?(\d+)$/;
517 0 0       0 if ( defined $1 ) {
518 0         0 $md += $1.$2;
519             }
520             else {
521 0         0 $md = $2;
522             }
523             }
524              
525             my @oldmargin;
526             sub ps_push_actual_margin {
527 0     0 0 0 push(@oldmargin, $xm);
528 0         0 $xm = shift;
529             }
530              
531             sub ps_pop_actual_margin {
532 0     0 0 0 $xm = pop(@oldmargin);
533             }
534              
535             sub ps_set_width {
536 2     2 0 4 my $v = shift;
537 2 50       6 croak("ps_set_width: number or increment\n")
538             unless $v =~ /^([-+])?(\d+)$/;
539 2 50       4 if ( defined $1 ) {
540 2         6 $xd += $1.$2;
541             }
542             else {
543 0         0 $xd = $2;
544             }
545             }
546              
547             sub ps_set_height {
548 1     1 0 1 my $v = shift;
549 1 50       4 croak("ps_set_height: number or increment\n")
550             unless $v =~ /^([-+])?(\d+)$/;
551 1 50       2 if ( defined $1 ) {
552 1         3 $yd -= $1.$2;
553             }
554             else {
555 0         0 $yd = -$2;
556             }
557             }
558              
559             sub ps_move {
560 273     273 0 625 print OUTPUT ($x0+$x+$xm, ' ' , $y0+$y, ' m ');
561             }
562              
563             sub ps_step {
564 378     378 0 266 $x += $xd;
565             }
566              
567             sub ps_advance {
568 65     65 0 43 $x = 0;
569 65         40 $y += $yd;
570 65 100       110 $y += ($_[0]-1)*$yd if defined $_[0];
571             }
572              
573             sub ps_skip {
574 141     141 0 116 $x += $_[0];
575             }
576              
577             my @oldx;
578             sub ps_push_x {
579 0     0 0 0 push(@oldx, $x);
580 0         0 $x += shift;
581             }
582              
583             sub ps_pop_x {
584 0     0 0 0 $x = pop(@oldx);
585             }
586              
587             sub ps_preamble {
588 2     2 0 2 my $data;
589 2 50       4 if ( defined $preamble ) {
590 2 50       36 open(DATA, $preamble) or die("$preamble: $!\n");
591 2         9 local($/);
592 2         57 $data = ;
593 2         15 close(DATA);
594             }
595             else {
596 0         0 require App::Music::PlayTab::PostScript::Preamble;
597 0         0 $data = App::Music::PlayTab::PostScript::Preamble->preamble;
598             }
599 2         41 $data =~ s/\$std_gridscale/$std_gridscale/g;
600 2         119 print OUTPUT ($data);
601              
602 2         3 $x0 = 50;
603 2         2 $y0 = 800;
604 2         3 $xd = $std_width;
605 2         2 $yd = $std_height;
606 2         2 $x = $y = $xm = 0;
607 2         3 $ps_pages = 0;
608             }
609              
610             sub ps_trailer {
611 2     2 0 6 print OUTPUT <
612             end showpage
613             %%Trailer
614             %%Pages: $ps_pages
615             %%EOF
616             EOD
617             }
618              
619             ################ Command Line Options ################
620              
621             sub app_ident;
622             sub app_usage($);
623              
624             sub app_options() {
625 2     2 0 2 my $help = 0; # handled locally
626 2         2 my $ident = 0; # handled locally
627              
628             # Process options, if any.
629             # Make sure defaults are set before returning!
630 2 50       8 return unless @ARGV > 0;
631              
632 2 50 33     7 if ( !GetOptions('output=s' => \$output,
633             'preamble=s' => \$preamble,
634             'transpose|x=i' => \$gxpose,
635             'lilypond=i' => \$lilypond,
636             'syntax' => \$syntax,
637             'ident' => \$ident,
638             'verbose' => \$verbose,
639             'trace' => \$trace,
640             'help' => \$help,
641             'test' => \$test,
642             'debug' => \$debug,
643             )
644             or abs($gxpose) > 11 )
645             {
646 0         0 app_usage(2);
647             }
648 2 50       1372 app_ident if $ident;
649 2 50       6 if ( $help ) {
650 0         0 app_usage(0);
651 0         0 exit(0);
652             }
653 2 50       38 if ( $syntax ) {
654 0 0       0 $lilypond ? ly_syntax() : syntax();
655 0         0 pr_syntax();
656 0         0 exit(0);
657             }
658 2 50       6 $bpm = $lilypond if $lilypond;
659             }
660              
661             sub app_ident {
662 0     0 0   print STDERR ("This is $my_package [$my_name $my_version]\n");
663             }
664              
665             sub app_usage($) {
666 0     0 0   my ($exit) = @_;
667 0           app_ident;
668 0           print STDERR <
669             Usage: $0 [options] [file ...]
670             --output XXX output file name
671             --transpose +/-N transpose all
672             --lilypond N use LilyPond chord syntax, N = bpm
673             --help this message
674             --syntax explain chord syntax
675             --ident show identification
676             --verbose verbose information
677             EndOfUsage
678 0 0         exit $exit if $exit != 0;
679             }
680              
681             sub syntax {
682 0     0 0   print STDERR <
683             Notes: C, D, E, F, G, A, B.
684             Raised with '#' or suffix 'is', e.g. A#, Ais.
685             Lowered with 'b' or suffix 's' or 'es', e.g. Bes, As, Eb.
686              
687             Chords: note + optional modifiers.
688             Chord modifiers Meaning [examples]
689             --------------------------------------------------------------
690             nothing major triad [C]
691             - or min or m minor triad [Cm Fmin Gb-]
692             + or aug augmented triad [Caug B+]
693             o or 0 or dim diminished triad [Co D0 Fdim]
694             --------------------------------------------------------------
695             maj7 major 7th chord [Cmaj7]
696             % half-diminished 7 chord [C%]
697             6,7,9,11,13 chord additions [C69]
698             sus sus4, sus2 suspended 4th, 2nd [Csus]
699             --------------------------------------------------------------
700             # raise the pitch of the note to a sharp [C11#9]
701             b lower the pitch of the note to a flat [C11b9]
702             --------------------------------------------------------------
703             no substract a note from a chord [C9no11]
704             --------------------------------------------------------------
705             () and _ may be used to avoid ambiguity, e.g. C(#9) <-> C#9 <-> C#_9
706              
707             Other: Meaning
708             --------------------------------------------------------------
709             . Chord space
710             - Rest
711             : Repeats previous chord
712             % Repeat pattern
713             / Powerchord constructor [D/G D/E-]
714             --------------------------------------------------------------
715             EOD
716             }
717              
718             sub ly_syntax {
719 0     0 0   print STDERR <
720             Notes: c, d, e, f, g, a, b.
721             Raised with suffix 'is', e.g. ais.
722             Lowered with suffix 'es', e.g. bes, ees.
723              
724             Chords: note + optional duration + optional modifiers.
725              
726             Duration = 1, 2, 4, 8, with possible dots, e.g., "2.".
727             No duration means: use the duration of the previous chord.
728              
729             Modifiers are preceeded with a ":".
730              
731             Modifiers Meaning [examples]
732             --------------------------------------------------------------
733             nothing major triad c4
734             m minor triad c4:m
735             aug augmented triad c4:aug
736             dim diminished triad c4:dim
737             --------------------------------------------------------------
738             maj major 7th chord c4:maj
739             6,7,9,11,13 chord additions c4:7 c4:6.9 (dot required)
740             sus sus4, sus2 suspended 4th, 2nd c4:sus
741             --------------------------------------------------------------
742             + raise the pitch of an added note c4:11.9+
743             - lower the pitch of an added note c4:11.9-
744             --------------------------------------------------------------
745             ^ substract a note from a chord c4:9.^11
746             --------------------------------------------------------------
747              
748             Other: Meaning
749             --------------------------------------------------------------
750             r Rest r2
751             s Rest s4
752             / Powerchord constructor d/g d/e:m
753             --------------------------------------------------------------
754             EOD
755             }
756              
757             sub pr_syntax {
758 0     0 0   print STDERR <
759             EOD
760             }
761              
762             ################ Documentation ################
763              
764             =head1 NAME
765              
766             App::Music::PlayTab - Print chords of songs in a tabular fashion.
767              
768             =head1 SYNOPSIS
769              
770             =head2 playtab
771              
772             playtab [options] [file ...]
773              
774             Options:
775             --transpose +/-N transpose all songs
776             --output XXX set outout file
777             --lilypond N accept chords in LilyPond syntax, N = bpm
778             --syntax print chord syntax
779             --ident show identification
780             --help brief help message
781             --verbose verbose information
782              
783             =head2 App::Music::PlayTab
784              
785             use App::Music::PlayTab;
786             run(); # arguments in @ARGV
787             run(@args); # explicit arguments
788              
789             perl -MApp::Music::PlayTab -e run ...arguments...
790              
791             =head1 DESCRIPTION
792              
793             This utility program is intended for musicians. It produces tabular
794             chord diagrams that are very handy for playing rhythm guitar or bass
795             in jazz, blues, and popular music.
796              
797             I wrote it since in official (and unofficial) sheet music, I find it
798             often hard to stick to the structure of the piece. Also, as a guitar
799             player, I do not need all the detailed notes and such that are only
800             important for melody instruments. And usually I cannot turn over the
801             pages while playing.
802              
803             For more info and examples,
804             see http://johan.vromans.org/software/sw_playtab.html .
805              
806             B is just a trivial wrapper around the App::Music::PlayTab module.
807              
808             =head1 COMMAND LINE OPTIONS
809              
810             =over 8
811              
812             =item B<--transpose> I
813              
814             Transposes all songs by I. This can be B<+> or B<-> 11 semitones.
815              
816             When transposing up, chords will be represented sharp if necessary;
817             when transposing down, chords will be represented flat if necessary.
818             For example, chord A transposed +1 will become A-sharp, but when
819             transposed -11 it will become B-flat.
820              
821             =item B<--output> I
822              
823             Designates I as the output file for the program.
824              
825             =item B<--lilypond>
826              
827             Interpet chord names according to LilyPond syntax.
828              
829             =item B<--help>
830              
831             Print a brief help message and exits.
832              
833             =item B<--ident>
834              
835             Prints program identification.
836              
837             =item B<--verbose>
838              
839             More verbose information.
840              
841             =item I
842              
843             Input file(s).
844              
845             =back
846              
847             =head1 INPUT SYNTAX
848              
849             The input for playtab is plain ASCII. It contains the chords, the
850             division in bars, with optional annotations.
851              
852             An example:
853              
854             !t Blue Bossa
855              
856             Bossanova
857             =
858             | c-9 ... | f-9 ... | d% . g7 . | c-9 ... |
859             | es-9 . as6 . | desmaj7 ... | d% . g7 . | c-9 . d% g7 |
860              
861             The first line, '!t' denotes the title of the song. Each song must
862             start with a title line.
863              
864             The title line may be followed by one or more '!s', subtitles, for
865             example to indicate the composer.
866              
867             The text "Bossanova" is printed below the title and subtitle.
868              
869             The "=" indicates some vertical space. Likewise, you can use '-' and
870             '+' as '=', but with a different vertical spacing.
871              
872             The next lines show the bars of the song. In the first bar is the c-9
873             chord (Cminor9), followed by three dots. The dots indicate that this
874             chord is repeated for all 4 beats of this bar. In the 3rd bar each
875             chord take two beats: d5% (d half dim), a dot, g7 and another dot.
876              
877             Run playtab with B<-h> or B<--help> for the syntax of chords.
878              
879             If you use "=" followed by some text, the printout is indented and the
880             text sticks out to the left. With this you can tag groups of bars, for
881             example the parts of a song that must be played in a certain order.
882             For example:
883              
884             !t Donna Lee
885             !s Charlie Parker
886              
887             Order: A B A B
888              
889             = A
890             | as . | f7 . | bes7 . | bes7 . |
891             | bes-7 . | es7 . | as . | es-7 D7 |
892             | des . | des-7 . | as . | f7 . |
893             | bes7 . | bes7 . | bes-7 . | es7 . |
894              
895             = B
896             | as . | f7 . | bes7 . | bes7 . |
897             | c7 . | c7 . | f- . | c7#9 . |
898             | f- . | c7 . | f- . | aso . |
899             | as f7 | bes-7 es7 | as - | bes-7 es7 |
900              
901             To see how this looks, see http://johan.vromans.org/software/sw_playtab.html .
902              
903             You can modify the width of the bars with a '!w' control. Standard
904             width of a beat is 30. '!w +5' increases the width to 35. '!w 25' sets
905             it to 25. You get the idea. You can also change the height with '!h'
906             (default is 15) and margin with '!m' (default width is 40).
907              
908             You can transpose an individual song with '!x I', where
909             I can range from -11 to +11, inclusive. A positive transpose
910             value will make sharps, a negative value will make flats.
911              
912             '!n' enables bar numbering. '!n 0' disables numbering, '!n I'
913             starts numbering at I. I may be negative, e.g., to skip
914             numbering an intro.
915              
916             '!ly' or '!lilypond' enables LilyPond chord name recognition. If
917             followed by a '0', switches to classical chord name syntax.
918              
919             Look at the examples, that is (currently) the best way to get grip on
920             what the program does.
921              
922             Oh, I almost forgot: it can print guitar chord diagrams as well.
923             See "bluebossa", "sophisticatedlady" and some others.
924              
925             Have fun, and let me know your ideas!
926              
927             =head1 INPUT SYNTAX
928              
929             Notes: C, D, E, F, G, A, B.
930             Raised with '#' or suffix 'is', e.g. A#, Ais.
931             Lowered with 'b' or suffix 's' or 'es', e.g. Bes, As, Eb.
932              
933             Chords: note + optional modifiers.
934             Chord modifiers Meaning [examples]
935             --------------------------------------------------------------
936             nothing major triad [C]
937             - or min or m minor triad [Cm Fmin Gb-]
938             + or aug augmented triad [Caug B+]
939             o or 0 or dim diminished triad [Co D0 Fdim]
940             --------------------------------------------------------------
941             maj7 major 7th chord [Cmaj7]
942             % half-diminished 7 chord [C%]
943             6,7,9,11,13 chord additions [C69]
944             sus sus4, sus2 suspended 4th, 2nd [Csus]
945             --------------------------------------------------------------
946             # raise the pitch of the note to a sharp [C11#9]
947             b lower the pitch of the note to a flat [C11b9]
948             --------------------------------------------------------------
949             no substract a note from a chord [C9no11]
950             --------------------------------------------------------------
951             _ may be used to avoid ambiguity, e.g. C_#9 <-> C#9 <-> C#_9
952              
953             Other: Meaning
954             --------------------------------------------------------------
955             . Chord space
956             - Rest
957             : Repeats previous chord
958             % Repeat
959             / Powerchord constructor [D/G D/E-]
960             --------------------------------------------------------------
961              
962             =head1 LILYPOND INPUT SYNTAX
963              
964             Notes: c, d, e, f, g, a, b.
965             Raised with suffix 'is', e.g. ais.
966             Lowered with suffix 'es', e.g. bes, ees.
967              
968             Chords: note + optional duration + optional modifiers.
969              
970             Duration = 1, 2, 4, 8, with possible dots, e.g., "2.".
971             No duration means: use the duration of the previous chord.
972              
973             Modifiers are preceeded with a ":".
974              
975             Modifiers Meaning [examples]
976             --------------------------------------------------------------
977             nothing major triad c4
978             m minor triad c4:m
979             aug augmented triad c4:aug
980             dim diminished triad c4:dim
981             --------------------------------------------------------------
982             maj major 7th chord c4:maj
983             6,7,9,11,13 chord additions c4:7 c4:6.9 (dot required)
984             sus sus4, sus2 suspended 4th, 2nd c4:sus
985             --------------------------------------------------------------
986             + raise the pitch of an added note c4:11.9+
987             - lower the pitch of an added note c4:11.9-
988             --------------------------------------------------------------
989             ^ substract a note from a chord c4:9.^11
990             --------------------------------------------------------------
991              
992             Other: Meaning
993             --------------------------------------------------------------
994             r Rest r2
995             s Rest s4
996             / Powerchord constructor d/g d/e:m
997             --------------------------------------------------------------
998              
999             See also: http://lilypond.org/doc/stable/Documentation/user/lilypond/Chord-names
1000              
1001             =head1 SEE ALSO
1002              
1003             http://chordie.sourceforge.net/
1004              
1005             =head1 AUTHOR
1006              
1007             Johan Vromans, Squirrel Consultancy Ejvromans@squirrel.nlE
1008              
1009             =head1 COPYRIGHT AND DISCLAIMER
1010              
1011             This program is Copyright 1990,2013 by Johan Vromans.
1012              
1013             This program is free software; you may redistribute it and/or modify
1014             it under the same terms as Perl itself.
1015              
1016             =cut
1017              
1018             1;