Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

cursebox v0.9 - "The Cursed Jukebox"

by odie (Sexton)
on Sep 13, 2000 at 17:28 UTC ( #32270=perlcraft: print w/ replies, xml ) Need Help??

   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: }

Comment on cursebox v0.9 - "The Cursed Jukebox"
Download Code
RE: cursebox v0.9 - switch{} coding style
by Corion (Pope) 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.

      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.
      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

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlcraft [id://32270]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2015-07-03 22:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (57 votes), past polls