source: gutenbach/debian/lib/sipbmp3-filter @ 6d813c3

debianmacno-cupsnodebathenaweb
Last change on this file since 6d813c3 was 6d813c3, checked in by root <root@…>, 16 years ago

Fix broken _mp3 files from cups.mit.edu.
Signed-off-by: root <root@…>

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