source: gutenbach/debian/lib/sipbmp3-filter @ 06133dc

debianmacno-cupsnodebathenaweb
Last change on this file since 06133dc was 06133dc, checked in by quentin <quentin>, 16 years ago

stop using getopt, since it's Wrong.

  • Property mode set to 100755
File size: 6.3 KB
Line 
1#!/usr/athena/bin/perl
2# Play the data on STDIN as an audio file
3#
4# $Id: sipbmp3-filter,v 1.21 2008-10-05 23:55:59 quentin Exp $
5# $Source: /tmp/tmp.UFBNno9997/RCS/sipbmp3-filter,v $
6#
7# TODO
8# ----
9# Make this structured code. It's a mess.
10# Repeat what we just played for EXT files too
11# Support HTTP Auth on ogg streams
12# License, cleanup and package
13#
14# Jered Floyd <jered@mit.edu> takes very little credit for this code
15# apparently neither does Quentin Smith <quentin@mit.edu>
16
17use Image::ExifTool qw(ImageInfo);
18use File::Spec::Functions;
19use LWP::UserAgent;
20use Data::Dumper;
21
22my $ua = new LWP::UserAgent;
23
24close(STDERR);
25open(STDERR, ">>", "/tmp/sipbmp3.log") or warn "Couldn't open log: $!";
26
27$ENV{"TERM"}="vt100";
28
29print STDERR "STDERR FROM SPOOL FILTER\n";
30
31# set real uid to be effective uid
32$< = $>;
33
34# Select the correct output device and set the volume
35#system("amixer -q set Headphone 100\% unmute");
36
37# The command line we get from lpd is (no spaces between options and args):
38#  -C lpr -C class
39#  -A LPRng internal identifier
40#  -H originating host
41#  -J lpr -J jobname (default: list of files)
42#  -L lpr -U username
43#  -P logname
44#  -Q queuename (lpr -Q)
45#  -Z random user-specified options
46#  -a printcap af (accounting file name)
47#  -d printcap sd entry (spool dir)
48#  -e print job data file name (currently being processed)
49#  -h print job originiating host (same as -H)
50#  -j job number in spool queue
51#  -k print job control file name
52#  -l printcap pl (page length)
53#  -n user name (same as -L)
54#  -s printcap sf (status file)
55#  -w printcap pw (page width)
56#  -x printcap px (page x dimension)
57#  -y printcap py (page y dimension)
58# accounting file name
59
60printf(STDERR "Got \@ARGV: %s\n", Dumper(\@ARGV));
61
62my %opts;
63
64my @NEWARGV;
65
66foreach my $arg (@ARGV) {
67  if ($arg =~ m/^-([a-zA-Z])(.*)$/) {
68    $opts{$1} = $2;
69  } else {
70    push @NEWARGV, @ARGV;
71  }
72}
73
74@ARGV = @NEWARGV;
75
76# Status messages at start of playback
77open(ZEPHYR, '|/usr/athena/bin/zwrite -d -n -c sipb-auto -i ' .
78  'sipbmp3@zsr -s "SIPB LPR music spooler"');
79print(ZEPHYR "$opts{'n'}\@$opts{'H'} is playing:\n");
80
81# So, the file we're currently processing is "-d/-e".
82
83# Read the metadata information from the file.
84my ($filepath) = catfile($opts{'d'}, $opts{'e'});
85my ($fileinfo) = ImageInfo($filepath);
86my ($magic) = $fileinfo->{FileType};
87
88if ($magic) {
89    printf(ZEPHYR "%s file %s\n", $magic, $opts{'J'});
90    printf(ZEPHYR "\@b(%s)\n", $fileinfo->{'Title'}) if exists $fileinfo->{'Title'};
91    foreach my $key (qw/Artist Album AlbumArtist/) {
92        printf(ZEPHYR "%s\n", $fileinfo->{$key}) if exists $fileinfo->{$key};
93    }
94}
95elsif ($opts{'C'} eq 'Z') {
96    $filepath = resolve_external_reference($filepath, \%opts);
97}
98elsif (-T $filepath) {
99    split_playlist($filepath, \%opts);
100    close(ZEPHYR);
101    exit 0;
102}
103printf(STDERR Dumper(\%opts));
104#printf(STDERR "Job priority %s\n", $opts{'C'}) if $opts{'C'} eq 'Z';
105#printf(ZEPHYR "Job priority %s\n", $opts{'C'}) if ($opts{'C'} && ($opts{'C'} ne 'A'));
106close(ZEPHYR);
107play_mplayer_audio($filepath, \%opts);
108
109# Play an external stream reference
110sub resolve_external_reference {
111    # Retrieve those command line opts.
112    my ($filepath, $opts) = @_;
113
114    my $format, $uri, $userpass;
115
116    if (<STDIN> =~ /^(\S+)/) {
117        $uri=$1;
118
119        my $response = $ua->head($uri);
120       
121        $contenttype=($response->content_type() or "unknown");
122       
123        if ($contenttype eq "audio/mpeg") { $format="MP3" }
124        elsif ($contenttype eq "application/x-ogg") { $format="OGG" }
125        elsif ($contenttype eq "application/ogg") { $format="OGG" }
126        elsif ($contenttype eq "audio/x-scpls") { $format="SHOUTCAST" }
127        else {
128            print ZEPHYR
129                "Unknown Content-Type $contenttype for URI $uri\n";
130            close(ZEPHYR);
131        }
132    } else {
133        print ZEPHYR "Couldn't read URI for external reference\n";
134        close(ZEPHYR);
135        return $filepath;
136    }
137
138    if ($format eq "SHOUTCAST") {
139        print ZEPHYR "Shoutcast playlist...\n";
140        #Don't close ZEPHYR yet, will print the name of the stream if available
141        return &get_shoutcast($uri);
142    } elsif ($format eq "MP3") {
143    } elsif ($format eq "OGG") {
144    } else {
145      print ZEPHYR "Unrecognized stream format: $format\n";
146    }
147    return $uri;
148}
149
150sub split_playlist {
151    my ($file, $opts) = @_;
152
153    my $i = 0;
154   
155    while (<STDIN>) {
156        chomp;
157        if (/^([^#]\S+)/) {
158            printf (STDERR "Found line: %s\n", $_);
159            open(LPR, "|-", qw/mit-lpr -Psipbmp3@localhost -CZ/, '-J'.$opts->{J});
160            print LPR $1;
161            close(LPR);
162        $i++;
163        }
164    }
165    printf(ZEPHYR "Playlist containing %d valid entries, split into separate jobs.\n", $i);
166}
167
168# Process a Shoutcast playlist
169# get_shoutcast(URI)
170sub get_shoutcast {
171  my $uri = shift(@_);
172 
173  my $response = $ua->get($uri);
174
175  foreach (split("\n", $response->content())) {
176      if (/^File\d+=(\S+)/) {
177          push(@uris, $1);
178      }
179      if (/^Title\d+=(.+)$/) {
180          push(@titles, $1);
181      }
182  }
183 
184  # choose a random server
185  $server = int(rand scalar(@uris));
186  # print the name of the stream if available
187  print ZEPHYR "$titles[$server]\n";
188  return $uris[$server];
189}
190
191sub play_mplayer_audio {
192    my ($filepath, $opts) = @_;
193
194    # Prepare to write status:
195    open(ZEPHYR, '|/usr/athena/bin/zwrite -d -n -c sipb-auto -i ' .
196         'sipbmp3@zsr -s "SIPB LPR music spooler"');
197   
198    # fork for mpg123
199    my $pid = open(MP3STATUS, "-|");
200    unless (defined $pid) {
201        print ZEPHYR "Couldn't fork: $!\n";
202        close(ZEPHYR);
203        return;
204    }
205   
206    if ($pid) { #parent
207        # Check if there were any errors
208        if ($_ = <MP3STATUS>) {
209            print ZEPHYR "Playback completed with the following errors:\n";
210            print ZEPHYR $_;
211            while (<MP3STATUS>) {
212                print ZEPHYR $_;
213            }
214        } else {
215            print ZEPHYR "Playback completed successfully.\n";
216        }
217        close(MP3STATUS) || print ZEPHYR "mplayer exited $?\n";
218       
219        close(ZEPHYR);
220    }
221  else { # child
222      # redirect STDERR to STDOUT
223      open STDERR, '>&STDOUT';
224      # make sure that mplayer doesn't try to intepret the file as keyboard input
225      close(STDIN);
226      open(STDIN, "/dev/null");
227      #print STDERR Dumper([qw|/usr/bin/mplayer -nolirc -ao alsa -quiet|, $filepath]);
228      exec(qw|/usr/bin/mplayer -nolirc -ao alsa -really-quiet|, $filepath) ||
229          die "Couldn't exec";
230  }
231}
232
233# ID3 comments often have useless crap because tools like iTunes were
234# written by drooling idiots
235sub filter_comment {
236  my $comment = shift(@_);
237
238  if ($comment =~ /^engiTunes_CDDB/) {
239    return undef;
240  }
241  return $comment;
242}
243
244
Note: See TracBrowser for help on using the repository browser.