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