1: #!/usr/bin/perl -w
2: # I have no idea if it will display ok on unusual term size.
3: # There are a few functions not implemented yet. Playlists
4: # can not be saved/loaded, and songs cannot me added. Instead
5: # cursebox will recursively parse the dir it is started in
6: # and find all *.mp3 files. It will consider them to be mp3
7: # files no matter what. It will not follow sym links.
8: # There are no safeguards despite forks, etc, so it is not
9: # gauranteed to work properly (although it seems to). It is
10: # after all v0.9.
11: # cursebox requires the following:
12: # -- ncurses
13: # -- CPAN Curses module
14: # -- A term capable of color
15: # Sorry for the ugly and messy code... =)
16:
17: use Curses;
18: $SIG{CHLD} = 'IGNORE';
19:
20: # CURSES INIT
21: initscr;
22: start_color;
23: noecho;
24: halfdelay(1);
25: nl();
26: intrflush(stdscr, 0);
27: keypad(stdscr, 1);
28: init_pair(1,1,0);
29: init_pair(2,2,0);
30: init_pair(3,3,0);
31: init_pair(5,5,0);
32:
33: # CURSEBOX INIT
34: $mark = -1;
35: $centersongnr = 0;
36: $randplay = 0;
37: $pid=0;
38: $playingon = 0;
39: $playno = 0;
40: $mode = "play"; # play, help, add, ver
41: $pwd=`pwd`;
42: chop($pwd);
43: &parsedir($pwd);
44: &refreshmid;
45: &setup;
46:
47: # MAIN
48: &loop;
49: exit(1);
50:
51: sub parsedir {
52: my $pwd=$_[0];
53: chdir($pwd);
54: opendir(DIR, $pwd);
55: my @files=readdir(DIR);
56: closedir(DIR);
57: foreach (@files) {
58: unless ( $_ =~ m/^\.$/ || $_ =~ m/^\.\.$/ ) {
59: if ( -d $_ && !-l $_ ) {
60: $npwd="$pwd/$_";
61: parsedir($npwd);
62: chdir("..");
63: } else {
64: if ( $_ =~ m/\.mp3$/i ) {
65: $mp3s[$#mp3s+1]="$pwd/$_";
66: }
67: }
68: }
69: }
70: }
71:
72: sub loop {
73: while ( 1 ) {
74: $char = getch();
75: unless ($char eq "-1") {
76: &interpret;
77: }
78: unless ( kill 0 => $pid ) {
79: if ($playingon) {
80: if ( $randplay ) {
81: &playrand;
82: } else {
83: &skip;
84: }
85: }
86: }
87: }
88: }
89:
90: sub interpret {
91: SWITCH: {
92: if ( $mode eq "help" ) { &interprethelp ; last SWITCH;}
93: if ( $mode eq "play" ) { &interpretplay ; last SWITCH;}
94: if ( $mode eq "cred" ) { &interpretcred ; last SWITCH;}
95: }
96: }
97:
98: sub interpretcred {
99: SWITCH: {
100: if ( $char eq "c" ) { &setmode("play") ; last SWITCH; }
101: &invalid;
102: }
103: }
104:
105: sub interprethelp {
106: SWITCH: {
107: if ( $char eq "h" ) { &setmode("play") ; last SWITCH; }
108: &invalid;
109: }
110: }
111:
112: sub interpretplay {
113: SWITCH: {
114: if ( $char eq "n" ) { &skip ; last SWITCH; }
115: if ( $char eq "m" ) { &movesong ; last SWITCH; }
116: if ( $char eq "b" ) { &back ; last SWITCH; }
117: if ( $char eq "r" ) { &rand ; last SWITCH; }
118: if ( $char eq "c" ) { &setmode("cred") ; last SWITCH; }
119: if ( $char eq "s" ) { &stop ; last SWITCH; }
120: if ( $char eq "p" ) { &play ; last SWITCH; }
121: if ( $char eq "q" ) { &quit ; last SWITCH; }
122: if ( $char eq "d" ) { &delsong ; last SWITCH; }
123: if ( $char eq "h" ) { &setmode("help") ; last SWITCH; }
124: if ( $char eq "g" ) { &gotocent ; last SWITCH; }
125: if ( $char eq "259" ) { &up ; last SWITCH; }
126: if ( $char eq "258" ) { &down ; last SWITCH; }
127: if ( $char eq "\n" ) { &goto ; last SWITCH; }
128: &invalid;
129: }
130: }
131:
132: sub setmode {
133: $mode=$_[0];
134: &refreshmid;
135: }
136:
137: sub refreshmid {
138: if ($mode eq "play") {
139: &midplay;
140: }
141: if ($mode eq "help") {
142: &midhelp;
143: }
144: if ($mode eq "cred") {
145: &midcred;
146: }
147: if ($mode eq "add") {
148: &midadd;
149: }
150: }
151:
152: sub midplay {
153: if ( $#mp3s == -1 ) {
154: &emptylist;
155: } else {
156: $nooflines = $LINES-7;
157: $centerline = int($nooflines/2);
158: $songnumber = $centersongnr-$centerline;
159: while ($songnumber < 0) {
160: $songnumber = $songnumber + $#mp3s+1;
161: }
162: for ( $i=0 ; $i<$nooflines ; $i++ ) {
163: if ($songnumber>$#mp3s) { $songnumber=0; }
164: $shownumber = $songnumber+1;
165: $playname = $mp3s[$songnumber];
166: $nr = length($playname) - ($COLS-8);
167: if ( $nr > 0 ) {
168: $playname =~ s/^.{$nr}//;
169: $playname =~ s/^.{3}/\.\.\./;
170: }
171: $printwidth = $COLS-3;
172: $sprintstring = "%-".$printwidth."s";
173: $printnum = sprintf("%-4s", $shownumber);
174: $playname = sprintf($sprintstring, " ".$printnum.$playname);
175: $attrm=0;$attrc=0;$attrp=0;
176: if ($songnumber==$mark && $mark!=-1 ) {$attrm=1;}
177: if ($songnumber==$playno || ($songnumber==-1 && $playno==$#mp3s)){$attrp=1;}
178: if ($i==$centerline) {$attrc=1;}
179: if ($attrm) {attron(COLOR_PAIR(1))}
180: if ($attrc) {attron(A_BOLD)}
181: if ($attrp) {attron(COLOR_PAIR(2))}
182: addstr((6+$i), 1, $playname);
183: if ($attrm) {attroff(COLOR_PAIR(1))}
184: if ($attrc) {attroff(A_BOLD)}
185: if ($attrp) {attroff(COLOR_PAIR(2))}
186: $songnumber++;
187: }
188: refresh;
189: }
190: }
191:
192: sub playsong {
193: if ( $#mp3s >= 0 ) {
194: if ( $pid == 0 ) {
195: if ( $playno < 0 ) {
196: $playno = $#mp3s;
197: }
198: if ( $playno > $#mp3s ) {
199: $playno = 0;
200: }
201: $playname=$mp3s[$playno];
202: $playnameqtd = quotemeta( $playname );
203: $mpgcommand="mpg123 -q $playnameqtd";
204: &refreshmid;
205: $pid = fork();
206: if ( $pid == 0 ) {
207: open(STDERR, "/dev/null");
208: exec($mpgcommand);
209: exit 1;
210: }
211: }
212: }
213: }
214:
215: sub setup {
216: attron(COLOR_PAIR(1));
217: box(stdscr, 0, 0);
218: move(5,1);
219: hline(0, 78);
220: attroff(COLOR_PAIR(1));
221: $sprintstring = "The Cursed JukeBox ( cursebox v0.9 )";
222: $nr = $COLS/2-length($sprintstring)/2;
223: $nr = int($nr);
224: attron(COLOR_PAIR(2));
225: addstr(0, $nr, $sprintstring );
226: attroff(COLOR_PAIR(2));
227: addstr(1, 2, "COMMANDS: (N)ext (B)ack (S)top (P)lay".
228: " (R)andom (M)ark/(M)ove");
229: addstr(2, 2, " (Q)quit (D)elete (H)elp (C)redits (G)oto");
230: addstr(3, 2, " Arrow Keys to scroll, <ENTER> to Select.");
231: addstr(4, 2, "RANDOM: PLAYING: ");
232: attron(COLOR_PAIR(1));
233: addstr(4, 12, "OFF");
234: addstr(4, 31, "OFF");
235: attroff(COLOR_PAIR(1));
236: refresh;
237: }
238:
239: sub emptylist {
240: $nooflines = $LINES-7;
241: $centerline = int($nooflines/2-1);
242: $songnumber = $centersongnr-$centerline;
243: $clearpatt = "%".($COLS-2)."s";
244: $clearline = sprintf($clearpatt, "");
245: for ( $i=0 ; $i<$nooflines ; $i++ ) {
246: addstr(($i+6),1,$clearline);
247: }
248: $sprintstring = "SONGLIST EMPTY";
249: $nr = int($COLS/2-length($sprintstring)/2);
250: addstr(($LINES/2+3), $nr, $sprintstring );
251: refresh;
252: }
253:
254: sub midcred {
255: $nooflines = $LINES-7;
256: $centerline = int($nooflines/2-1);
257: $songnumber = $centersongnr-$centerline;
258: $clearpatt = "%".($COLS-2)."s";
259: $clearline = sprintf($clearpatt, "");
260: for ( $i=0 ; $i<$nooflines ; $i++ ) {
261: addstr(($i+6),1,$clearline);
262: }
263: addstr(6,1,"The Cursed Jukebox ( cursebox v0.9 )");
264: addstr(8,1,"Cursebox uses:");
265: addstr(9,1," mpg123");
266: addstr(10,1," perl");
267: addstr(11,1," Curses, the perl ncurses interface ( Yes, you".
268: " need a color Term .)");
269: addstr(13,1,"Tools used in coding:");
270: addstr(14,1," vim ( VI Improved )");
271: addstr(15,1," man ( RTFM... )");
272: addstr(17,1,"Cursebox has been created in vga text mode on a".
273: " debian linux i386 machine");
274: addstr(18,1,"by Mats Ström. ( d99msr\@efd.lth.se )");
275: addstr(20,1,"A big \"hooray\" goes to www.perlmonks.org. Good".
276: "place to ask questions.");
277: addstr(22,1,"Press C to exit this screen.");
278: refresh;
279: }
280:
281: sub midhelp {
282: $nooflines = $LINES-7;
283: $centerline = int($nooflines/2-1);
284: $songnumber = $centersongnr-$centerline;
285: $clearpatt = "%".($COLS-2)."s";
286: $clearline = sprintf($clearpatt, "");
287: for ( $i=0 ; $i<$nooflines ; $i++ ) {
288: addstr(($i+6),1,$clearline);
289: }
290: addstr(6,1,"Use Up/Down arrow keys to scroll in the playlist.");
291: addstr(7,1,"Enter will start playing the song on the highlighted line.");
292: addstr(9,1,"N Next: Play next song. If random is on, it skips to".
293: "a random song.");
294: addstr(10,1,"B Back: Play previous song. If random is on, it skips".
295: "to a random song.");
296: addstr(11,1,"S Stop: Stop playing.");
297: addstr(12,1,"P Play: Start playing.");
298: addstr(13,1,"R Random: Toggle random play on/off.");
299: addstr(14,1,"Q Quit: Exit program. ( Yes, CTRL-C works as well. )");
300: addstr(15,1,"G Goto: This will move your view to the playing song.");
301: addstr(16,1,"H Help: Display this text.");
302: addstr(17,1,"C Credits: Show credits and information about cursebox.");
303: addstr(18,1,"M Mark: Pressing M once will mark a message for moving.".
304: "The line will");
305: addstr(19,1," turn red. Move with the arrow keys to another song".
306: "and press M again.");
307: addstr(20,1," The marked line will be removed and inserted at new".
308: "position.");
309: addstr(22,1,"Press H to exit help.");
310: refresh;
311: }
312:
313: sub playrand {
314: $playno=int(rand($#mp3s+1));
315: if ( $playno == $#mp3s+1 ) {
316: $playno=$#mp3s;
317: }
318: &stop;
319: &play;
320: }
321:
322: sub delsong {
323: if ( $#mp3s >= 0 ) {
324: splice(@mp3s,$centersongnr,1);
325: if ( $centersongnr == $playno ) {
326: $playno = $centersongnr;
327: if ( $playingon ) {
328: &stop;
329: &play;
330: }
331: }
332: if ( $centersongnr < $playno ) {
333: $playno--;
334: }
335: if ( $centersongnr == ($#mp3s+1) ) {
336: $centersongnr = 0;
337: }
338: if ( $playno > ($#mp3s+1) ) {
339: $playno=$#mp3s+1;
340: }
341: &refreshmid;
342: } else {
343: &invalid;
344: }
345: }
346:
347: sub up {
348: $centersongnr--;
349: if ( $centersongnr < 0 ) {
350: $centersongnr = $#mp3s;
351: }
352: &refreshmid;
353: }
354:
355: sub down {
356: $centersongnr++;
357: if ( $centersongnr > $#mp3s ) {
358: $centersongnr = 0;
359: }
360: &refreshmid;
361: }
362:
363: sub movesong {
364: if ( $#mp3s >= 0 ) {
365: if ( $mark == -1 ) {
366: $mark = $centersongnr;
367: } else {
368: $tmp = $mp3s[$mark];
369: splice(@mp3s,$mark,1);
370: splice(@mp3s,$centersongnr,0,$tmp);
371: SWITCH: {
372: if ( $playno == $centersongnr ) { $playno = $mark; ; last SWITCH; }
373: if ( $playno == $mark ) { $playno = $centersongnr; ; last SWITCH; }
374: $playno=$playno;
375: }
376: $mark=-1;
377: }
378: &refreshmid;
379: } else {
380: &invalid;
381: }
382: }
383:
384: sub goto {
385: if ( $#mp3s >= 0 ) {
386: &play;
387: $playno = $centersongnr;
388: if ( kill 0 => $pid ) {
389: if ( $pid != 0 ) {
390: &killsong;
391: }
392: &playsong;
393: }
394: } else {
395: &invalid;
396: }
397: }
398:
399: sub gotocent {
400: if ( $#mp3s >= 0 ) {
401: $centersongnr = $playno;
402: &refreshmid;
403: }
404: }
405:
406: sub stop {
407: attron(COLOR_PAIR(1));
408: addstr(4, 31, "OFF");
409: attroff(COLOR_PAIR(1));
410: refresh;
411: if ($pid != 0) {
412: &killsong;
413: }
414: $playingon = 0;
415: }
416:
417: sub play {
418: if ( $#mp3s >= 0 ) {
419: attron(COLOR_PAIR(2));
420: addstr(4, 31, "ON ");
421: attroff(COLOR_PAIR(2));
422: refresh;
423: unless ($playingon) {
424: &playsong;
425: }
426: $playingon = 1;
427: } else {
428: &invalid;
429: }
430: }
431:
432: sub skip {
433: if ( $#mp3s >= 0 ) {
434: &play;
435: unless ( $randplay ) {
436: $playno++;
437: unless ( $pid == 0 ){
438: &killsong;
439: }
440: &playsong;
441: } else {
442: unless ( $pid == 0 ){
443: &killsong;
444: }
445: &playrand;
446: }
447: } else {
448: &invalid;
449: }
450: }
451:
452: sub back {
453: if ( $#mp3s >= 0 ) {
454: &play;
455: unless ( $randplay ) {
456: $playno--;
457: unless ( $pid == 0 ) {
458: &killsong;
459: }
460: &playsong;
461: } else {
462: unless ( $pid == 0 ){
463: &killsong;
464: }
465: &playrand;
466: }
467: } else {
468: &invalid;
469: }
470: }
471:
472: sub rand {
473: if ( $randplay ) {
474: attron(COLOR_PAIR(1));
475: addstr(4, 12, "OFF"); refresh;
476: attroff(COLOR_PAIR(1));
477: $randplay = 0;
478: } else {
479: attron(COLOR_PAIR(2));
480: addstr(4, 12, "ON ");
481: attroff(COLOR_PAIR(2));
482: refresh;
483: $randplay = 1;
484: }
485: }
486:
487: sub killsong {
488: unless ( $pid == 0 ){
489: while ( kill 0 => $pid ) {
490: kill TERM, $pid;
491: }
492: }
493: $pid=0;
494: }
495:
496: sub quit {
497: &killsong;
498: endwin;
499: exit(1);
500: }
501:
502: sub invalid {
503: beep;
504: refresh;
505: }
RE: cursebox v0.9 - switch{} coding style
by Corion (Patriarch) on Sep 13, 2000 at 22:47 UTC
|
Update: Please use strict; !
Though I have not used this code, I have one comment to
make in the spirit of TIMTOWTDI (hopefully a good comment) - I find the simulated switch statement to map a keypress to an action rather clumsy, as it does not really allow to easily
add other actions later or add other actions dynamically.
In such situations, I prefer to use a hash of code references, like this :
my %actions = (
"n" => \&skip,
"m" => \&movesong,
# ... rest ommited ...
"\n" => \&goto,
);
and the routine interpretplay() would then
look like this (sadly, untested) :
sub interpretplay {
if (exists $actions{$char}) {
&$actions{$char};
} else {
&invalid;
};
};
or, if the whole state machine would be changed to use hashes, one could even use a single interpret()
method that would simply look at the $current_state
hash reference to find the action to be executed.
Dynamically loaded actions would then simply modify the
%actions hash with their entry.
| [reply] [d/l] [select] |
|
This is sample code for odie to look at, and will probably be changing. Please don't vote on this node.
#!/usr/local/bin/perl -w
use strict;
{
my %hash = ('a' => {-func => \&sub_one, -parm => 'subone'},
'b' => {-func => \&sub_two, -parm => 'two,two_a,two_
+b'},
'c' => {-func => \&sub_three, -parm => ''},
);
&{$hash {'a'}->{-func}} (split ',', $hash {'a'}->{-parm});
&{$hash {'b'}->{-func}} (split ',', $hash {'b'}->{-parm});
&{$hash {'c'}->{-func}} (split ',', $hash {'c'}->{-parm});
}
sub sub_one
{
print "sub_one got ", scalar @_, " parameters\n";
print "sub_one parameters: $_\n" foreach (@_);
}
sub sub_two
{
print "sub_two got ", scalar @_, " parameters\n";
print "sub_two parameters: $_\n" foreach (@_);
}
sub sub_three
{
print "sub_three got ", scalar @_, " parameters\n";
print "sub_three parameters: $_\n" foreach (@_);
}
--Chris
e-mail jcwren | [reply] [d/l] |
|
Well... As I said, it is version 0.9 and the code is a
complete mess. The whole thing started as a sinple recursive
hack that played every mp3 file found, using mpg123.
I honestly didn't expect to continue building it... =)
I will naturally make the code a lot more efficient, and
less spammy, and use strict. This code is still very much
in a state of "hack". Version 1.0 will be posted when complete.
| [reply] |
|
|