source: gutenbach/debian/lib/sipbmp3-filter @ 5e66bb4

debianmacno-cupsnodebathenaweb
Last change on this file since 5e66bb4 was 5e66bb4, checked in by jhawk <jhawk>, 17 years ago

Try to support WAV. First cu. What a failure.

  • Property mode set to 100755
File size: 18.8 KB
Line 
1#!/usr/athena/bin/perl
2# Play the data on STDIN as an audio file
3#
4# $Id: sipbmp3-filter,v 1.15 2007-12-22 04:20:29 jhawk 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
16use Getopt::Std;
17
18# Get the MP3Info module from this directory, because I suck.
19unshift(@INC, "/usr/local/bin");
20require MP3::Info;
21import MP3::Info;
22&use_winamp_genres();
23
24print STDERR "STDERR FROM SPOOL FILTER\n";
25
26# set real uid to be effective uid
27$< = $>;
28
29# Attach necessary lockers
30system("/bin/athena/attach -h -n -q infoagents sipb outland ' .
31    'consult 2>&1 > /dev/null");
32
33# Select the correct output device and set the volume
34system("/usr/local/bin/audio_setdevice -out headphones 100 ' .
35    '2>&1 </dev/null > /dev/null");
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
60# All the filter_options from lpd
61getopt('ACFHJLPQRZacdefhijklnprswxy', \%opts);
62
63# Status messages at start of playback
64open(ZEPHYR, '|/usr/athena/bin/zwrite -d -n -c sipb-auto -i ' .
65  'sipbmp3@xcb -s "SIPB LPR music spooler"');
66print(ZEPHYR "User $opts{'n'} on host $opts{'H'} is playing:\n");
67
68# So, the file we're currently processing is "-d/-e".
69# Do some magic to make sure it's an MP3, and get the important bits
70# to zephyr out.
71open(DATAFILE, "$opts{'d'}/$opts{'e'}");
72sysread(DATAFILE, $magic, 3);
73close(DATAFILE);
74
75# MPEG header is beshort &0xffe0
76# meditate upon the header:
77($magic0, $magic1, @magic2) = unpack("C3", $magic);
78if ((($magic0 & 0xff) == 0xff) &&
79    (($magic1 & 0xe0) == 0xe0)) {
80  # MPEG audio file, we like it
81  # Fall through
82} elsif ($magic eq "ID3") {
83  # ID3 v2 does sketchy things with "garbage" beginning with ID3 at file start.
84  # MPEG audio file with ID3 tag, we like it
85  # Fall through
86} elsif ($magic eq "EXT") {
87  # This is an external stream reference (a jered-special)
88  &play_external_reference(\%opts, $magic);
89  exit 0;
90} elsif ($magic eq "htt") {
91  # This is an external stream reference (a jered-special)
92  &play_external_reference(\%opts, $magic);
93  exit 0;
94} elsif ($magic eq "Ogg") {
95  # Ogg-Vorbis audio file
96  &play_ogg_audio(\%opts);
97  exit 0;
98} elsif ($magic0 == 0x52 && $magic1 == 0x49) {
99  &play_wav_audio(\%opts);
100  exit 0;
101} else {
102    # add more cases later, whine for now
103    printf(ZEPHYR "I don't think this is an MPEG audio file... %02x %02x\n",
104           $magic0, $magic1);
105    print ZEPHYR "I'm going to try playing it as one anyway.\n";
106}
107# Default
108&play_mpeg_audio(\%opts);
109
110
111# Play an external stream reference
112sub play_external_reference {
113    # Retrieve those command line opts.
114    my %opts = %{shift(@_)};
115    my $magic = shift(@_);
116
117    # External references are *not* playlists; they only support
118    # a single URL in order to be fair.  A reference is structured as
119    # follows:
120    #
121    # EXT <format>\n
122    # <URI>[ <user:pass>]\n
123    # Descriptive text of the file that will be\n
124    # played; this may span multiple lines until the\n
125    # EOF
126    #
127    # Where <URI> is a valid URI for the stream, and <format> is a
128    # recognized format name (currently 'MP3' or 'OGG' or 'SHOUTCAST').
129    # <user:pass> is an optional user and password pair for HTTP Basic Auth.
130    my $format, $uri, $userpass;
131
132    if ("$magic" eq "EXT") {
133      if (<STDIN> =~ /^EXT (.*)$/) {
134        # Found the header
135        $format = $1;
136      } else {
137        print ZEPHYR "Couldn't read EXT header\n";
138        close(ZEPHYR);
139      }
140 
141      if (<STDIN> =~ /^(\S*)\s*(.*)$/) {
142        # Found the URI (and optionally user:pass)
143        $uri = $1;
144        if ($2) {
145        $userpass = $2;
146        }
147      } else {
148        print ZEPHYR "Couldn't read URI for external reference\n";
149        close(ZEPHYR);
150      }
151  } elsif ("$magic" eq "htt") {
152      if (<STDIN> =~ /^(\S*)\s*(.*)$/) {
153          $uri=$1;
154          my $pid = open(W3M, "-|");
155          unless (defined $pid) {
156              print ZEPHYR "Couldn't fork: $!\n";
157              close(ZEPHYR);
158              die;
159          }
160
161          if ($pid) { #parent
162              $contenttype="unknown";
163              while (<W3M>) {
164                  if ($_ =~ /^Content-Type:\s(\S*)/) {
165                      $contenttype=$1;
166                  }
167              }
168              if ($contenttype eq "audio/mpeg") { $format="MP3" }
169              elsif ($contenttype eq "application/x-ogg") { $format="OGG" }
170              elsif ($contenttype eq "application/ogg") { $format="OGG" }
171              elsif ($contenttype eq "audio/x-scpls") { $format="SHOUTCAST" }
172              else {
173                  print ZEPHYR
174                      "Unknown Content-Type $contenttype for URI $uri\n";
175                  close(ZEPHYR);
176              }
177              close(W3M) || print ZEPHYR "w3m exited $?\n";
178          }
179          else { # child
180              exec("/mit/sipb/bin/w3m", "-dump_head", $uri)
181                  || die "Couldn't exec";
182          }
183      } else {
184        print ZEPHYR "Couldn't read URI for external reference\n";
185        close(ZEPHYR);
186    }
187  } else {
188      print ZEPHYR "Unknown syntax in play_external_reference(): $magic\n";
189      close(ZEPHYR);
190  }
191
192    # Echo the rest to the zephyr
193    while (<STDIN>) {
194      print ZEPHYR $_;
195    }
196    print ZEPHYR "\n";
197
198    # Play the thing the right way
199    if (($format eq "MP3") ||
200        ($format eq "mp3")) {
201      print ZEPHYR "MP3 audio stream...\n";
202      close(ZEPHYR);
203      &play_mpeg_stream($uri, $userpass);
204    }
205    elsif ($format eq "SHOUTCAST") {
206        print ZEPHYR "Shoutcast playlist...\n";
207        #Don't close ZEPHYR yet, will print the name of the stream if available
208        $uri = &get_shoutcast($uri);
209        close(ZEPHYR);
210        &play_mpeg_stream($uri, undef);
211    }   
212    elsif (($format eq "OGG") ||
213             ($format eq "ogg")) {
214      print ZEPHYR "OggVorbis stream...\n";
215      close(ZEPHYR);
216      &play_ogg_stream($uri, $userpass);
217    } else {
218      print ZEPHYR "Unrecognized stream format: $format\n";
219      close(ZEPHYR);
220    }
221}
222
223# Process a Shoutcast playlist
224# get_shoutcast(URI)
225sub get_shoutcast {
226  my $uri = shift(@_);
227 
228  # grab the shoutcast .pls file
229  my $pid = open(W3M, "-|");
230  unless (defined $pid) {
231      print ZEPHYR "Couldn't fork: $!\n";
232      close(ZEPHYR);
233      die;
234  }
235  if (!$pid) { # child
236      exec("/mit/sipb/bin/w3m","-dump_source",$uri) || die "Couldn't fork";
237  }
238  while (<W3M>) {
239      if (/^File\d+=(\S+)/) {
240          push(@uris, $1);
241      }
242      if (/^Title\d+=(.+)$/) {
243          push(@titles, $1);
244      }
245  }
246  close(W3M);
247 
248  # choose a random server
249  $server = int(rand scalar(@uris));
250  # print the name of the stream if available
251  print ZEPHYR "$titles[$server]\n";
252  return $uris[$server];
253}
254
255# Play an MPEG audio stream
256# play_mpeg_stream(URI, userpass)
257sub play_mpeg_stream {
258  my $uri = shift(@_);
259  my $userpass = shift(@_);
260
261  # Add the user:pass argument if is was given to us
262  my $up = '';
263  if ($userpass) {
264    $up = '-u ' . $userpass;
265  }
266
267  system("ps ax | grep ogg123 | awk '{print $2}' | xargs kill -9");
268  system("ps ax | grep mpg123 | awk '{print $2}' | xargs kill -9");
269  system("chmod a+rw /dev/audio");
270
271  # Prepare to write status:
272  open(ZEPHYR, '|/usr/athena/bin/zwrite -d -n -c sipb-auto -i ' .
273       'sipbmp3@xcb -s "SIPB LPR music spooler"');
274     
275  # fork for mpg123
276  my $pid = open(MP3STATUS, "-|");
277  unless (defined $pid) {
278      print ZEPHYR "Couldn't fork: $!\n";
279      close(ZEPHYR);
280      return;
281  }
282 
283  if ($pid) { #parent
284      # Check if there were any errors
285      if ($_ = <MP3STATUS>) {
286          print ZEPHYR "Playback completed with the following errors:\n";
287          print ZEPHYR $_;
288          while (<MP3STATUS>) {
289              print ZEPHYR $_;
290          }
291      } else {
292          print ZEPHYR "Playback completed successfully.\n";
293      }
294      close(MP3STATUS) || print ZEPHYR "mpg123 exited $?\n";
295     
296      close(ZEPHYR);
297  }
298  else { # child
299      # redirect STDERR to STDOUT
300      open STDERR, '>&STDOUT';
301
302      # disabling the buffer seems to improve streaming performances
303      # (files don't get cut in the middle) - perhaps mpg123 fails to
304      # wait for OS TCP buffer to be filled. -- jtwang 22 Oct 2003
305      #exec("/mit/infoagents/bin/mpg123", "-b16384", "-q", $up, $uri ||
306      #   die "Couldn't exec";
307      exec("/mit/infoagents/bin/mpg123", "-q", $up, $uri) ||
308          die "Couldn't exec";
309  }
310}
311
312# ID3 comments often have useless crap because tools like iTunes were
313# written by drooling idiots
314sub filter_comment {
315  my $comment = shift(@_);
316
317  if ($comment =~ /^engiTunes_CDDB/) {
318    return undef;
319  }
320  return $comment;
321}
322
323
324# Play an MPEG audio file
325sub play_mpeg_audio {
326    # Retrieve those command line opts.
327    my %opts = %{shift(@_)};
328
329    my %MPEGModes = ( 0 => "stereo",
330                      1 => "joint-stereo",
331                      2 => "dual-channel",
332                      3 => "single-channel");
333
334    # If it's an MP3 file, try to extract useful data
335    my $tag = get_mp3tag("$opts{'d'}/$opts{'e'}");
336    if (!$tag) {
337        print ZEPHYR "No ID3 tag found\n";
338        my @fnamearray = split /,/, $opts{'J'};
339        foreach $fname (@fnamearray) {
340            print ZEPHYR "Filename: $fname\n";
341        }
342#           print ZEPHYR "Filename: $opts{'J'}\n\n";
343    } else {
344      print ZEPHYR "Title          : $tag->{TITLE}\n";
345      print ZEPHYR "Artist         : $tag->{ARTIST}\n";
346      print ZEPHYR "Album          : $tag->{ALBUM}\n";
347      if ($tag->{TRACKNUM} =~ /(.*)\/.*/) {
348          $tag->{TRACKNUM} = $1;
349      }
350      if ($tag->{TRACKNUM}) {
351          print ZEPHYR "Track #        : $tag->{TRACKNUM}\n";
352      }
353      if ($tag->{YEAR}) {
354        print ZEPHYR "Year           : $tag->{YEAR}\n";
355      }
356      if ($tag->{GENRE}) {
357        # iTunes (?) does something weird with genres, leaving them
358        # as the string "(##)" where ## is the genre type. Let's deal
359        # with this.
360        if ($tag->{GENRE} =~ /^\((\d*)\)$/) {
361          $tag->{GENRE} = $MP3::Info::mp3_genres[$1];
362        }
363        if ($tag->{GENRE} =~ /^(\d*)$/) {
364          $tag->{GENRE} = $MP3::Info::mp3_genres[$1];
365        }
366        print ZEPHYR "Genre          : $tag->{GENRE}\n";
367      }
368      if (ref $tag->{COMMENT} eq 'ARRAY') {
369        foreach $index (0 .. $#{$tag->{COMMENT}}) {
370          if ($comment = filter_comment(@{$tag->{COMMENT}}[$index])) {
371            print ZEPHYR "Comment        : $comment\n";
372          }
373        }
374      } elsif ($tag->{COMMENT}) {
375        if ($comment = filter_comment($tag->{COMMENT})) {
376          print ZEPHYR "Comment        : $comment\n";
377        }
378      }
379
380      # Maybe get some extended ID3v2 info?
381      my $v2tag = get_mp3tag("$opts{'d'}/$opts{'e'}", 2, 1);
382      %lessinfo = %$v2tag;
383      foreach $dtag (keys %MP3::Info::v2_to_v1_names) {
384        delete $lessinfo{$dtag};
385      }
386      delete $lessinfo{'GENRE'};
387      # Delete annoying useless crap
388      my @bad_tags = ('GEO', 'GEOB', # General encapsulated object
389                      'PIC', 'APIC', # Attached picture.
390                      );
391      foreach $dtag (@bad_tags) {
392          delete $lessinfo{$dtag};
393      }
394      while (($key,$val) = each %lessinfo) {
395        printf ZEPHYR "%-15s: %s\n", $MP3::Info::v2_tag_names{$key}, $val;
396      }
397      print ZEPHYR "\n";
398    }
399
400    my $info = get_mp3info("$opts{'d'}/$opts{'e'}");
401    if (!$info) {
402        print ZEPHYR "No MPEG header found\n";
403    } else {
404        print ZEPHYR "MPEG $info->{VERSION} layer $info->{LAYER}, ";
405        if ($info->{VBR}) {
406            print ZEPHYR "VBR ";
407        }
408        print ZEPHYR "$info->{BITRATE} kbit/s, $info->{FREQUENCY} kHz ";
409        print ZEPHYR $MPEGModes{$info->{STEREO}};
410        print ZEPHYR "\n\n";
411        printf ZEPHYR "Track length: %d:%02ds\n", $info->{MM}, $info->{SS};
412    }
413    close(ZEPHYR);
414
415    # Play the file
416    # mpg123 is a crock.  If you don't give it -q, it needs to be on a pty
417    # or it SEGVs. Really.
418
419    system("chmod a+rw /dev/audio");
420    system("ps ax | grep ogg123 | awk '{print $2}' | xargs kill -9");
421    system("ps ax | grep mpg123 | awk '{print $2}' | xargs kill -9");
422    system("/mit/infoagents/bin/mpg123 -b 16384 -q - >/tmp/mpg123.out 2>&1");
423
424    # Done. Status:
425    open(ZEPHYR, '|/usr/athena/bin/zwrite -d -n -c sipb-auto -i ' .
426         'sipbmp3@xcb -s "SIPB LPR music spooler"');
427
428    # Check if there were any errors
429    open(MP3STATUS, "/tmp/mpg123.out");
430    if ($_ = <MP3STATUS>) {
431        print ZEPHYR "Playback completed with the following errors:\n";
432        print ZEPHYR $_;
433        while (<MP3STATUS>) {
434            print ZEPHYR $_;
435        }
436    } else {
437        print ZEPHYR "Playback completed successfully.\n";
438        # Repeat tag data for those playing at home
439        if (!$tag) {
440          print ZEPHYR "No ID3 tag found\n";
441          print ZEPHYR "Filename: $opts{'J'}\n\n";
442        } else {
443          print ZEPHYR "Title          : $tag->{TITLE}\n";
444          print ZEPHYR "Artist         : $tag->{ARTIST}\n";
445          print ZEPHYR "Album          : $tag->{ALBUM}\n";
446          if ($tag->{TRACKNUM} =~ /(.*)\/.*/) {
447              $tag->{TRACKNUM} = $1;
448          }
449          if ($tag->{TRACKNUM}) {
450              print ZEPHYR "Track #        : $tag->{TRACKNUM}\n";
451          }
452          if ($tag->{YEAR}) {
453            print ZEPHYR "Year           : $tag->{YEAR}\n";
454          }
455          if ($tag->{GENRE}) {
456              print ZEPHYR "Genre          : $tag->{GENRE}\n";
457          }
458          if (ref $tag->{COMMENT} eq 'ARRAY') {
459            foreach $index (0 .. $#{$tag->{COMMENT}}) {
460              if ($comment = filter_comment(@{$tag->{COMMENT}}[$index])) {
461                print ZEPHYR "Comment        : $comment\n";
462              }
463            }
464          } elsif ($tag->{COMMENT}) {
465            if ($comment = filter_comment($tag->{COMMENT})) {
466              print ZEPHYR "Comment        : $comment\n";
467            }
468          }
469
470          # others
471          while (($key,$val) = each %lessinfo) {
472            printf ZEPHYR "%-15s: %s\n", $MP3::Info::v2_tag_names{$key}, $val;
473          }
474        }
475    }
476    close(MP3STATUS);
477    unlink(MP3STATUS);
478
479    close(ZEPHYR);
480}
481
482# Play an OggVorbis audio stream (doesn't support auth!)
483# play_ogg_stream(URI)
484#  Mostly copied from play_ogg_audio
485sub play_ogg_stream {
486  my $uri = shift(@_);
487
488  system("chmod a+rw /dev/audio");
489  system("ps -aef | grep ogg123 | awk '{print $2}' | xargs kill -9");
490  system("ps -aef | grep mpg123 | awk '{print $2}' | xargs kill -9");
491
492  # Prepare to write status:
493  open(ZEPHYR, '|/usr/athena/bin/zwrite -d -n -c sipb-auto -i sipbmp3@xcb -s "SIPB LPR music spooler"');
494  system("/mit/sipb/bin/ogg123 -b 256 -dau -q -f - $uri 2> /tmp/ogg123.out | audioplay");
495
496  # Check if there were any errors
497  open(OGGSTATUS, "/tmp/ogg123.out");
498  if ($_ = <OGGSTATUS>) {
499    print ZEPHYR "Playback completed with the following errors:\n";
500    print ZEPHYR $_;
501    while (<OGGSTATUS>) {
502      print ZEPHYR $_;
503    }
504  } else {
505    print ZEPHYR "Playback completed successfully.\n";
506    # Repeat tag data for those playing at home
507    if (!$ogginfo{'title'}) {
508      print ZEPHYR "No ogginfo data found\n";
509      print ZEPHYR "Filename: $opts{'J'}\n\n";
510    } else {
511      print ZEPHYR "Title          : $ogginfo{'title'}\n";
512      print ZEPHYR "Artist         : $ogginfo{'artist'}\n";
513      print ZEPHYR "Album          : $ogginfo{'album'}\n";
514      print ZEPHYR "Track #        : $ogginfo{'tracknumber'}\n";
515
516      # others
517      while (($key,$val) = each %lessinfo) {
518        printf ZEPHYR "%-15s: %s\n", $key, $val;
519      }
520    }
521  }
522
523  close(OGGSTATUS);
524  unlink(OGGSTATUS);
525
526  close(ZEPHYR);
527}
528
529# Play an OggVorbis audio file
530sub play_ogg_audio {
531  # Retrieve those command line opts.
532  my %opts = %{shift(@_)};
533
534  # Get ogginfo stuff
535  open(OGGINFO, "/mit/sipb/bin/ogginfo $opts{'d'}/$opts{'e'}|");
536  while (<OGGINFO>) {
537    if (/(.*)=(.*)/) {
538      $ogginfo{lc("$1")} = $2;
539    }
540  }
541  close(OGGINFO);
542
543  # If there's no title, print the filename
544  if (!$ogginfo{'title'}) {
545    print ZEPHYR "No ogginfo data found\n";
546    print ZEPHYR "Filename: $opts{'J'}\n";
547  } else {
548    print ZEPHYR "Title          : $ogginfo{'title'}\n";
549    print ZEPHYR "Artist         : $ogginfo{'artist'}\n";
550    print ZEPHYR "Album          : $ogginfo{'album'}\n";
551    print ZEPHYR "Track #        : $ogginfo{'tracknumber'}\n";
552
553    # others
554    %lessinfo = %ogginfo;
555    delete $lessinfo{'filename'};
556    delete $lessinfo{'title'};
557    delete $lessinfo{'artist'};
558    delete $lessinfo{'album'};
559    delete $lessinfo{'tracknumber'};
560    delete $lessinfo{'header_integrity'};
561    delete $lessinfo{'stream_integrity'};
562    delete $lessinfo{'file_truncated'};
563    delete $lessinfo{'version'};
564    delete $lessinfo{'channels'};
565    delete $lessinfo{'bitrate_upper'};
566    delete $lessinfo{'bitrate_nominal'};
567    delete $lessinfo{'bitrate_lower'};
568    delete $lessinfo{'bitrate_average'};
569    delete $lessinfo{'length'};
570    delete $lessinfo{'playtime'};
571    delete $lessinfo{'kbps'};
572    delete $lessinfo{'time'};
573    delete $lessinfo{'rg_radio'};
574    delete $lessinfo{'rg_audiophile'};
575    delete $lessinfo{'rg_peak'};
576    delete $lessinfo{'replaygain_album_peak'};
577    delete $lessinfo{'replaygain_track_peak'};
578    delete $lessinfo{'replaygain_album_gain'};
579    delete $lessinfo{'replaygain_track_gain'};
580
581    while (($key,$val) = each %lessinfo) {
582      printf ZEPHYR "%-15s: %s\n", $key, $val;
583    }
584  }
585
586  printf ZEPHYR "\nOgg Vorbis, average %.1f kbit/s, %d channels\n\n",
587    $ogginfo{'bitrate_average'}/1024, $ogginfo{'channels'};
588  print ZEPHYR "Track length: $ogginfo{'playtime'}s\n";
589  close(ZEPHYR);
590
591  # Play the file
592
593  system("chmod a+rw /dev/audio");
594  system("ps -aef | grep ogg123 | awk '{print $2}' | xargs kill -9");
595  system("ps -aef | grep mpg123 | awk '{print $2}' | xargs kill -9");
596  system("/mit/sipb/bin/ogg123 -b 40000 -dau -q -f - - 2> /tmp/ogg123.out | audioplay");
597
598  # Done. Status:
599  open(ZEPHYR, '|/usr/athena/bin/zwrite -d -n -c sipb-auto -i sipbmp3@xcb -s "SIPB LPR music spooler"');
600
601  # Check if there were any errors
602  open(OGGSTATUS, "/tmp/ogg123.out");
603  if ($_ = <OGGSTATUS>) {
604    print ZEPHYR "Playback completed with the following errors:\n";
605    print ZEPHYR $_;
606    while (<OGGSTATUS>) {
607      print ZEPHYR $_;
608    }
609  } else {
610    print ZEPHYR "Playback completed successfully.\n";
611    # Repeat tag data for those playing at home
612    if (!$ogginfo{'title'}) {
613      print ZEPHYR "No ogginfo data found\n";
614      print ZEPHYR "Filename: $opts{'J'}\n\n";
615    } else {
616      print ZEPHYR "Title          : $ogginfo{'title'}\n";
617      print ZEPHYR "Artist         : $ogginfo{'artist'}\n";
618      print ZEPHYR "Album          : $ogginfo{'album'}\n";
619      print ZEPHYR "Track #        : $ogginfo{'tracknumber'}\n";
620
621      # others
622      while (($key,$val) = each %lessinfo) {
623        printf ZEPHYR "%-15s: %s\n", $key, $val;
624      }
625    }
626  }
627
628  close(OGGSTATUS);
629  unlink(OGGSTATUS);
630
631  close(ZEPHYR);
632}
633
634# Play a WAV audio file
635sub play_wav_audio {
636  # Retrieve those command line opts.
637  my %opts = %{shift(@_)};
638
639  print ZEPHYR "No info\n";
640  print ZEPHYR "Filename: $opts{'J'}\n";
641  close(ZEPHYR);
642
643  # Play the file
644
645  system("chmod a+rw /dev/audio");
646  system("ps -aef | grep audioplay | awk '{print $2}' | xargs kill -9");
647  system("/usr/bin/audioplay $opts{'J'}");
648}
Note: See TracBrowser for help on using the repository browser.