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