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