Annotation of mp3/daemon/playmp3s.pl, Revision 1.8
1.1 andrew 1: #!/usr/bin/perl
1.8 ! andrew 2: # $RedRiver: playmp3s.pl,v 1.7 2010/10/28 19:21:29 andrew Exp $
1.1 andrew 3: ########################################################################
4: # PlayMP3.pl *** play's MP3s off a playlist using mp3play
5: #
6: # 04-14-00
7: # Written by andrew fresh <andrew@mad-techies.org>
8: ########################################################################
9:
10: use strict;
11: use warnings;
12: use diagnostics;
13:
14: use vars qw/ %cfgs /;
15:
16: my $config_file = shift || "/etc/playmp3s.conf";
17:
1.3 andrew 18: my %cfgs = readconfig($config_file);
19:
1.1 andrew 20: my $err_log = $cfgs{errors} || "/var/log/playmp3s.log";
21:
1.6 andrew 22: my $Num_History = 0;
1.4 andrew 23:
1.1 andrew 24: Print_PlayLog("Beginning playtime\n\n");
25:
26: my %Full_Playlist;
27: $Full_Playlist{last_mod} = 0;
28: my $playlist_last_mod = 0;
29:
30: my @playlist;
31:
1.8 ! andrew 32: for ( ;; ) {
! 33:
! 34: # while(1) {
! 35: my $save_playlist;
! 36:
! 37: my ($last_mod) = ( stat( $cfgs{list} ) )[9];
! 38: if ( $playlist_last_mod != $last_mod ) {
! 39: @playlist = ();
! 40: $playlist_last_mod = $last_mod;
! 41: }
! 42:
! 43: while ( !@playlist ) {
! 44: Print_PlayLog("Getting Playlist . . .\n");
! 45:
! 46: # bail("getting playlist");
! 47: @playlist = get_playlist( $cfgs{list} );
! 48: unless (@playlist) {
! 49:
! 50: # bail("getting full playlist");
! 51: @playlist = get_full_playlist( $cfgs{fulllist} );
! 52:
! 53: Print_PlayLog("Got full playlist\n");
! 54: $save_playlist = 0;
! 55: }
! 56: else {
! 57: Print_PlayLog("Got normal playlist\n");
! 58: $save_playlist = 1;
! 59: }
! 60: unless (@playlist) { sleep 10; }
! 61: }
! 62: Print_PlayLog("Got playlist\n");
! 63:
! 64: Print_PlayLog("getting song to play . . .\n");
! 65: my $song = int rand( scalar(@playlist) );
! 66: my $filename = splice( @playlist, $song, 1 );
! 67: Print_PlayLog("\tGot $song - filename is\n\t$filename\n");
! 68:
! 69: Print_PlayLog("displaying file that is playing . . . ");
! 70: DisplayPlaying( $cfgs{currenthtml}, $filename );
! 71: Print_PlayLog("done\n");
! 72:
! 73: Print_PlayLog("Adding Last. . .");
! 74: AddLast(
! 75: $filename, $cfgs{playedlist}, $Num_History,
! 76: $cfgs{playedhtml}, $cfgs{addurl}
! 77: );
! 78: Print_PlayLog("done\n");
! 79:
! 80: if ($save_playlist) {
! 81: Print_PlayLog("Saving Playlist. . .");
! 82: save_playlist( $cfgs{list}, @playlist )
! 83: || bail("Unable to save playlist!: $!");
! 84: Print_PlayLog("done\n");
! 85: }
! 86:
! 87: Print_PlayLog("Playing: $filename . . .\n");
! 88:
! 89: my $player;
! 90: my $play = "$cfgs{basedir}$filename";
! 91: if ( defined $filename && $filename =~ /\.mp3$/i ) {
! 92: $player = $cfgs{mp3play};
! 93: }
! 94: elsif ( $filename =~ /\.ogg$/i ) {
! 95: $player = $cfgs{oggplay};
! 96:
! 97: #$play =~ s/(\(|\)|&|"|'| |-)/\\$1/g;
! 98: }
! 99:
! 100: if ( not $player =~ s/\{\}/"$play"/g ) {
! 101: $player .= ' "' . $play . '"';
! 102: }
! 103: Print_PlayLog("$player\n");
! 104: `$player`;
! 105:
! 106: # my $kid = 0;
! 107: # while ($kid ne -1 && ContinueRun()) {
! 108: # while ($kid ne -1) {
! 109: # print "waiting to end . . . ";
! 110: # my $kid = waitpid(-1,&WNOHANG);
! 111: # print "done.\n";
! 112: # }
! 113:
! 114: Print_PlayLog("Displaying Nothing . . .");
! 115: DisplayPlaying( $cfgs{currenthtml}, "Nothing" );
! 116: Print_PlayLog("done\n");
! 117:
! 118: #@playlist = ();
! 119:
! 120: sleep 1;
1.1 andrew 121: }
122:
1.8 ! andrew 123: sub Install {
1.1 andrew 124:
125: # add your additional install messages or functions here
126: print "\nThank you for installing this file\n";
127: }
128:
129: sub Remove {
1.8 ! andrew 130:
1.1 andrew 131: # add your additional remove messages or functions here
132: print "\nSorry you had to leave\n";
133: }
134:
135: sub Help {
1.8 ! andrew 136:
1.1 andrew 137: # add your additional help messages or functions here
138: print "\nYou don't really need help do you??\n";
139: }
140:
141: #########################################################################
142: # GetTime
143: sub GetTime {
1.8 ! andrew 144: my $hours = shift || 0;
! 145: my ( $sec, $min, $hour, $mday, $mon, $year,,, )
! 146: = localtime( time - ( 3600 * $hours ) ); # 86400 seconds is one day
! 147:
! 148: if ( $min < 10 ) { $min = "0$min" }
! 149: if ( $sec < 10 ) { $sec = "0$sec" }
! 150: if ( $hour < 10 ) { $hour = "0$hour" }
! 151: if ( $mday < 10 ) { $mday = "0$mday" }
! 152: if ( $mon < 10 ) { $mon = "0$mon" }
! 153:
! 154: my $time
! 155: = ( $year + 1900 ) . '-'
! 156: . ++$mon . '-'
! 157: . $mday . ' '
! 158: . $hour . ':'
! 159: . $min . ':'
! 160: . $sec;
! 161: return $time;
1.1 andrew 162: }
163: #########################################################################
164:
165: #######################################################################
166: # read in the Playlist
167: sub get_full_playlist {
1.8 ! andrew 168: my $FILE = shift;
! 169: my ($last_mod) = ( stat($FILE) )[9];
1.1 andrew 170:
1.8 ! andrew 171: if ( $Full_Playlist{last_mod} != $last_mod ) {
! 172: my @list;
! 173: @list = get_playlist($FILE);
! 174:
! 175: @list = grep !m#$cfgs{skipregex}#io, @list;
! 176:
! 177: my @played_list = get_playlist( $cfgs{playedlist} );
! 178:
! 179: my %played;
! 180: @played{@played_list} = ();
! 181:
! 182: delete $Full_Playlist{list};
! 183:
! 184: my $list_size = 0;
! 185: foreach my $song (@list) {
! 186: $list_size++;
! 187: $Full_Playlist{list}{$song} = 1
! 188: unless ( exists $played{$song} );
! 189: }
! 190: my $history = int $list_size * 0.1;
! 191: if ($history) {
! 192: Print_PlayLog("New history is $history\n");
! 193: $Num_History = $history;
! 194: }
1.1 andrew 195:
1.8 ! andrew 196: $Full_Playlist{last_mod} = $last_mod;
! 197: }
1.1 andrew 198:
1.8 ! andrew 199: return keys %{ $Full_Playlist{list} };
1.1 andrew 200: }
201: #######################################################################
202:
203: #######################################################################
204: # read in the Playlist
205: sub get_playlist {
1.8 ! andrew 206: my $FILE = shift;
! 207: my @lines;
1.1 andrew 208:
1.8 ! andrew 209: # open PLAYlistLOG, ">c:/ps/playlistlog.txt";
1.1 andrew 210:
1.8 ! andrew 211: # print PLAYlistLOG "Getting Playlist from file: $FILE\n";
! 212: # close PLAYlistLOG;
! 213: if ( -e $FILE ) {
! 214: open( FILE, $FILE ) || bail("Couldn't open $FILE: $!");
! 215: chomp( @lines = <FILE> );
! 216: close(FILE) || bail("Couldn't close $FILE: $!");
! 217: }
! 218: else {
! 219: open( FILE, ">$FILE" ) || return @lines;
! 220: close(FILE) || bail("Couldn't close $FILE: $!");
! 221: return @lines;
! 222: }
! 223: return @lines;
! 224: }
1.1 andrew 225:
226: #######################################################################
227: # writes back the new playlist
228: sub save_playlist {
1.8 ! andrew 229: my $FILE = shift;
! 230: my @lines = @_;
! 231: open( FILE, ">$FILE" )
! 232: || bail("Couldn\'t open playlist to save $FILE: $!");
! 233: foreach (@lines) {
! 234: print FILE "$_\n";
! 235: }
! 236: close(FILE) || bail("Couldn't close $FILE: $!");
! 237: return 1;
1.1 andrew 238: }
239:
240: #######################################################################
241: # Prints a webpage with the currently playing song
242: sub DisplayPlaying {
1.8 ! andrew 243:
! 244: my $htmlfile = shift;
! 245: my $playing = shift;
! 246:
! 247: open BLANK, ">$htmlfile" or bail("Unable to open $htmlfile: $!");
! 248: print BLANK "<html>\n<head>\n\t<title>' . $playing . '</title>\n";
! 249: print BLANK "<meta HTTP-EQUIV=\"REFRESH\" CONTENT=\"5\">\n";
! 250: print BLANK "<meta HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">\n";
! 251: print BLANK "</head>\n";
! 252: print BLANK '<body leftmargin="0" topmargin="0" ',
! 253: 'marginwidth="0" marginheight="0">', "\n\n";
! 254: print BLANK
! 255: "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n";
! 256: print BLANK " <tr>\n";
! 257: print BLANK
! 258: " <td align=\"left\"><b><i>Currently playing:</i> $playing</b></td>\n";
! 259: print BLANK " <td align=\"right\">Started at: "
! 260: . GetTime()
! 261: . "</td>\n";
! 262: print BLANK " </tr>\n";
! 263: print BLANK "</table>\n";
1.1 andrew 264:
265: # print BLANK "<center><b>Currently playing: $playing</b><br>\nStarted at: " . GetTime() . "</center>";
266:
1.8 ! andrew 267: print BLANK "</body>\n</head>\n</html>\n";
! 268: close BLANK || bail("Unable to close BLANK: $!");
1.1 andrew 269: }
270:
271: #######################################################################
272: # Prints a webpage with the previously played song
1.6 andrew 273: # AddLast($filename, $cfgs{playedlist}, $Num_History, $cfgs{playedhtml}, $cfgs{addurl});
1.1 andrew 274: sub AddLast {
1.8 ! andrew 275: my $lastsong = shift;
! 276: my $lastlist = shift;
! 277: my $history = shift;
! 278: my $htmlfile = shift;
! 279: my $addurl = shift;
! 280:
! 281: my @LIST = get_playlist($lastlist);
! 282:
! 283: DisplayPrevious( $htmlfile, $addurl, @LIST ) if $htmlfile;
! 284:
! 285: unshift @LIST, $lastsong;
! 286: splice( @LIST, $history ) if $history;
! 287: save_playlist( $lastlist, @LIST );
1.7 andrew 288:
1.8 ! andrew 289: # Remove song from full list so we don't play it again.
! 290: delete $Full_Playlist{list}{$lastsong};
1.1 andrew 291: }
292:
293: #######################################################################
294: # Prints a webpage with the previously played song
295: sub DisplayPrevious {
296:
1.8 ! andrew 297: my $htmlfile = shift;
! 298: my $addurl = shift;
! 299: my $lastplay = shift;
! 300: my @played = @_;
! 301: open BLANK, ">$htmlfile" or bail("Unable to open $htmlfile: $!");
! 302: print BLANK "<html>\n<head>\n\t<title>' . $lastplay . '</title>\n";
! 303: print BLANK "<meta HTTP-EQUIV=\"REFRESH\" CONTENT=\"30\">\n";
! 304: print BLANK "<meta HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">\n";
! 305: print BLANK "<body>\n\n";
! 306:
! 307: print BLANK "<p>[ <a href=\"bin/ShowFiles.pl\">Beginning</a> | \n";
! 308: print BLANK "<a href=\"bin/ShowAll.pl\">All MP3's</a> |\n";
! 309: print BLANK "<a href=\"bin/ShowPlaylist.pl\">Playlist</a> |\n";
! 310: print BLANK "<a href=\"ShowPlaylist.pl?newlist.lst\">New Files</a> |\n";
! 311: print BLANK "<a href=\"played.htm\">Previously played</a> ]<p>\n";
! 312:
! 313: print BLANK "<center><b>Last played: <a href=\"$addurl\?"
! 314: . EncodeURL("$lastplay")
! 315: . "\" target=\"bottom\">$lastplay</a></b><br>\nStarted at: "
! 316: . GetTime()
! 317: . "</center><p>\n";
! 318:
! 319: print BLANK "before that:<br>\n";
! 320:
! 321: print BLANK "<UL>\n";
! 322:
! 323: foreach my $song (@played) {
! 324: print BLANK "\t<li>Song: <a href=\"$addurl\?"
! 325: . EncodeURL("$song")
! 326: . "\" target=\"bottom\">$song</a></li>\n";
! 327: }
1.1 andrew 328:
1.8 ! andrew 329: print BLANK "</UL>\n";
1.1 andrew 330:
1.8 ! andrew 331: print BLANK "</body>\n</head>\n</html>\n";
! 332: close BLANK || bail("Unable to close played.htm: $!");
1.1 andrew 333: }
334:
335: ########################################################################
336: # *** EncodeURL: %encodes the parameters of the URL
337: sub EncodeURL {
1.8 ! andrew 338: my $strURL = shift;
! 339: $strURL =~ s/(\W)/sprintf("%%%x", ord($1))/eg;
! 340: return $strURL;
1.1 andrew 341: }
342:
343: ########################################################################
344: # read in config file.
345: sub readconfig {
1.8 ! andrew 346: my $CONFIG = shift;
! 347: my $delimter = shift || '=';
! 348: my %configs;
! 349: if ( -e $CONFIG ) {
! 350: open( CONFIG, $CONFIG ) or bail("Couldn\'t open $CONFIG: $!");
! 351: while (<CONFIG>) {
! 352: chomp; # no newline
! 353: s/#.*//; # no comments
! 354: s/^\s+//; # no leading white space
! 355: s/\s+$//; # no trailing white space
! 356: next unless length; # anything left?
! 357: my ( $var, $value ) = split( /\s*$delimter\s*/, $_, 2 );
! 358:
! 359: # $var =~ tr/A-Za-z0-9_\.\,\/\\ / /cd; # delete all the non alphanumerics
! 360: # $value =~ tr/A-Za-z0-9_\/\.\,\\ / /cd; # delete all the non alphanumerics
! 361: $var =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
! 362: $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
! 363: $configs{$var} = $value;
! 364: }
! 365: close CONFIG or bail("Couldn't close $CONFIG: $!");
! 366: }
! 367: else {
! 368: print '<!-- No config file: ' . $CONFIG;
! 369: print ' -->';
! 370: print "\n";
! 371: }
! 372: return %configs;
1.1 andrew 373: }
374: ########################################################################
375:
1.8 ! andrew 376: #sub ForkMP3Player { # This forks the MP3 player.
1.1 andrew 377: ## KillPlaying(0);
1.8 ! andrew 378: #
1.1 andrew 379: # my $player = shift;
380: # my $song = shift;
381: #
382: # $player =! s/%%f%%/\"$song\"/ig;
383: #
1.8 ! andrew 384: #
1.1 andrew 385: # FORK: {
386: # if ($Mp3Playerpid = fork) {
387: # # parent here
388: ## print "\nMp3Playerpid: ", $Mp3Playerpid;
389: # # child process pid is available in $pid
390: # print "Parent PID: $Mp3Playerpid\n";
391: # } elsif (defined $Mp3Playerpid) { # $pid is zero here if defined
392: # # child here
393: # print "\nPlaying $song\n";
394: ## exec("$configs{mp3play} -b 16384 --reopen --aggressive -m \"$song\"");
395: # print "\n";
396: ## exec("$player \"$song\"");
397: # exec("$player");
398: # exit(0);
399: # # parent process pid is available with getppid
1.8 ! andrew 400: # } elsif ($! =~ /No more process/) {
1.1 andrew 401: # # EAGAIN, supposedly recoverable fork error
402: # sleep 5;
403: # redo FORK;
404: # } else {
405: # # weird fork error
406: # bail("\nCan't fork: $!");
407: # }
408: # }
409: #}
410:
1.8 ! andrew 411: #######################################################################
! 412: # Bail: this subrouting dies and displays the error to the browser.
! 413: # gotten from the example in the O'Reilly
! 414: # _Learning_Perl_on_Win32_Systems_
! 415: sub bail {
! 416: open ERR, '>>$err_log';
! 417:
! 418: # open ERR, ">>c:/ps/error.txt";
1.1 andrew 419:
1.8 ! andrew 420: my $error = "@_";
! 421: print "Unexpected Error: $error\n";
! 422: print ERR "Unexpected Error: $error\n";
! 423: close ERR;
1.1 andrew 424:
1.8 ! andrew 425: # exit;
! 426: }
1.1 andrew 427:
1.8 ! andrew 428: sub Print_PlayLog {
! 429: open PLAYLOG, ">>/tmp/playlog" or bail("Unable to open PLAYLOG");
! 430: print GetTime(), "\t", @_;
! 431: print PLAYLOG GetTime(), "\t", @_;
! 432: close PLAYLOG;
1.1 andrew 433: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>