[xiph-cvs] cvs commit: BlueberryArmageddon blueberry_armageddon

Monty xiphmont at xiph.org
Sun Mar 31 23:58:40 PST 2002



xiphmont    02/03/31 23:58:40

  Added:       .        blueberry_armageddon
  Log:
  Another fun little script I don;t want to lose by accident

Revision  Changes    Path
1.1                  BlueberryArmageddon/blueberry_armageddon

Index: blueberry_armageddon
===================================================================
#!/usr/bin/perl

#use Socket;
#use Sys::Hostname;
#use Time::Local;
use IPC::Open3;
#use File::Glob ':glob';
use Tk;
use Tk::Xrm;
use Tk qw(exit); 
use CDDB;

$version="Blueberry Armageddon 20020401";
$width=400;
($device)=@ARGV;

$query='cdparanoia -d $device -Q 2>&1';
$rip='cdparanoia -ez -d $device $track -w $wavfile';
$encode='oggenc -q 4.99 -a {$metaartist} -t {$metatitle} -l {$metaalbum} $wavfile -o $outfile';
$playrip='cdparanoia -vZd $device $playstatus $pipe';
$play='play -t wav $pipe ';

$trackbase="/media/audio/albums";
$unfiled="/media/audio/unfiled";
$suffix=".ogg";

if($#ARGV<0){
    print "Usage: Rip /dev/???\n\n";
    exit(1);
}

<p># build the UI
my $toplevel=new MainWindow(-class=>'MontyRip');
my $Xname=$toplevel->Class;

$toplevel->optionAdd("$Xname.background",  "#3d84ff",20);
$toplevel->optionAdd("$Xname*highlightBackground",  "#80c0d3",20);
$toplevel->optionAdd("$Xname.Panel.background",  "#3d84ff",20);
$toplevel->optionAdd("$Xname.Panel.foreground",  "#d0d0d0",20);
$toplevel->optionAdd("$Xname.Panel.font",
                     '-*-helvetica-bold-o-*-*-18-*-*-*-*-*-*-*',20);
$toplevel->optionAdd("$Xname*Statuslabel.font",
                     '-*-helvetica-bold-r-*-*-18-*-*-*-*-*-*-*',20);
$toplevel->optionAdd("$Xname*Statuslabel.foreground", "#606060");
$toplevel->optionAdd("$Xname*Status.font",
                     '-*-helvetica-bold-r-*-*-18-*-*-*-*-*-*-*',20);

$toplevel->optionAdd("$Xname*AlertDetail.font",
                     '-*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*',20);

<p>$toplevel->optionAdd("$Xname*background",  "#d0d0d0",20);
$toplevel->optionAdd("$Xname*foreground",  '#000000',20);

$toplevel->optionAdd("$Xname*Button*background",  "#f0d0b0",20);
$toplevel->optionAdd("$Xname*Button*foreground",  '#000000',20);
$toplevel->optionAdd("$Xname*Button*borderWidth",  '2',20);
$toplevel->optionAdd("$Xname*Button*relief",  'groove',20);
$toplevel->optionAdd("$Xname*Button*padY",  1,20);

$toplevel->optionAdd("$Xname*Checkbutton*background",  "#f0d0b0",20);
$toplevel->optionAdd("$Xname*Checkbutton*foreground",  '#000000',20);
$toplevel->optionAdd("$Xname*Checkbutton*borderWidth",  '2',20);
$toplevel->optionAdd("$Xname*Checkbutton*relief",  'groove',20);

$toplevel->optionAdd("$Xname*activeBackground",  "#ffffff",20);
$toplevel->optionAdd("$Xname*activeForeground",  '#0000a0',20);
$toplevel->optionAdd("$Xname*borderWidth",         0,20);
$toplevel->optionAdd("$Xname*relief",         'flat',20);
$toplevel->optionAdd("$Xname*activeBorderWidth",         1,20);
$toplevel->optionAdd("$Xname*highlightThickness",         0,20);
$toplevel->optionAdd("$Xname*padX",         2,20);
$toplevel->optionAdd("$Xname*padY",         2,20);
$toplevel->optionAdd("$Xname*font",    
                     '-*-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*',20);
$toplevel->optionAdd("$Xname*Entry.font",    
                     '-*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*',20);

$toplevel->optionAdd("$Xname*Exit.font",    
                     '-*-helvetica-bold-r-*-*-10-*-*-*-*-*-*-*',20);
$toplevel->optionAdd("$Xname*Exit.relief",          'groove',20);
$toplevel->optionAdd("$Xname*Exit.padX",          1,20);
$toplevel->optionAdd("$Xname*Exit.padY",          1,20);
$toplevel->optionAdd("$Xname*Exit.borderWidth",          2,20);
$toplevel->optionAdd("$Xname*Exit*background",  "#a0a0a0",20);
$toplevel->optionAdd("$Xname*Exit*disabledForeground",  "#ffffff",20);

$toplevel->optionAdd("$Xname*Entry.background",  "#ffffff",20);
$toplevel->optionAdd("$Xname*Entry.disabledForeground",  "#c0c0c0",20);
$toplevel->optionAdd("$Xname*Entry.relief",  "sunken",20);
$toplevel->optionAdd("$Xname*Entry.borderWidth",  1,20);

$toplevel->optionAdd("$Xname*Field.background",  "#ffffff",20);
$toplevel->optionAdd("$Xname*Field.disabledForeground",  "#c0c0c0",20);
$toplevel->optionAdd("$Xname*Field.relief",  "flat",20);
$toplevel->optionAdd("$Xname*Field.borderWidth",  1,20);

$toplevel->optionAdd("$Xname*Label.disabledForeground",  "#c0c0c0",20);
$toplevel->optionAdd("$Xname*Label.borderWidth",  1,20);

$toplevel->configure(-background=>$toplevel->optionGet("background",""));

#$toplevel->resizable(FALSE,FALSE);

$window_shell=$toplevel->Label(Name=>"shell",borderwidth=>1,relief=>raised)->
    place(-x=>10,-y=>36,-relwidth=>1.0,-relheight=>1.0,
          -width=>-20,-height=>-46,-anchor=>'nw');

$window_quit=$window_shell->Button(-class=>"Exit",text=>"quit")->
    place(-x=>-1,-y=>-1,-relx=>1.0,-rely=>1.0,-anchor=>'se');

$window_version=$toplevel->
    Label(Name=>"logo text",-class=>"Panel",text=>$version)->
    place(-x=>5,-y=>5,-anchor=>'nw');

$y=8;
$x=5;

$window_statuslabel=$window_shell->
    Label(Name=>"statuslabel",-class=>"Statuslabel",text=>"Status: ")->
    place(-x=>$x,-y=>$y,-anchor=>'nw');

$window_status=$window_shell->
    Label(Name=>"status",-class=>"Status",text=>"Starting...",-anchor=>'w')->
    place(-x=>0,-y=>0,-relx=>1.,-anchor=>'nw',-in=>$window_statuslabel);

$y+=$window_statuslabel->reqheight()*1.3;

$window_quit->configure(-command=>[sub{Shutdown();}]);

$window_device_label=$window_shell->Label(text=>"device: ")->
    place(-x=>$x,-y=>$y,-anchor=>'nw');
$window_device=$window_shell->Label(-class=>"Field",text=>"$device")->
    place(-relx=>1.,-anchor=>'nw',-bordermode=>outside,
          -in=>$window_device_label);

$window_go=$window_shell->Button(text=>"go",-state=>'disabled')->
    place(-x=>-$x,-y=>$y,-relx=>1.,-anchor=>'ne',-bordermode=>outside);

$window_check=$window_shell->Button(text=>"recheck",-state=>disabled)->
    place(-anchor=>'ne',-bordermode=>outside,-in=>$window_go);

$window_scan=$window_shell->Button(text=>"rescan")->
    place(-anchor=>'ne',-bordermode=>outside,-in=>$window_check);

$y+=$window_scan->reqheight()*1.2+5;

$window_artist_label=$window_shell->Label(text=>"artist: ")->
    place(-x=>$x,-y=>$y,-anchor=>'nw');
        
$window_artist=$window_shell->
    Entry(-width=>1024,-textvariable=>\$artist)->
    place(-x=>$x+$window_artist_label->reqwidth(),-y=>$y,
          -relwidth=>1.,
          -width=>-10-$window_artist_label->reqwidth(),
          -anchor=>'nw');

$y+=$window_artist_label->reqheight();

$window_album_label=$window_shell->Label(text=>"album: ")->
    place(-x=>$x,-y=>$y,-anchor=>'nw');

$window_album=$window_shell->
    Entry(-width=>1024,-textvariable=>\$album)->
    place(-x=>$x+$window_artist_label->reqwidth(),-y=>$y,
          -relwidth=>1.,
          -width=>-10-$window_artist_label->reqwidth(),
          -anchor=>'nw');

$y+=$window_artist_label->reqheight()+5;
$infoy=$y;

$tracks=0;
for(my$i=1;$i<=99;$i++){
    my$text="track$i: ";
    $text="track0$i: " if($i<10);
    
    $window_track_label[$i]=$window_shell->Label(text=>$text);
    $trackname[$i]="";
    $window_track[$i]=$window_shell->
        Entry(-width=>1024,-textvariable=>\$trackname[$i]);
    $window_play[$i]=$window_shell->
        Button(text=>"play",-command=>[main::playtrack,$i]);
    $window_rip[$i]=$window_shell->
        Checkbutton(-variable=>\$trackrip[$i],text=>"rip");
}

$totaly=int(46+$window_quit->reqheight()+10+$y);

$toplevel->geometry($width.'x'.$totaly);

$window_scan->configure(-command=>[sub{Rescan();}]);
$window_check->configure(-command=>[sub{Recheck();}]);
$window_go->configure(-command=>[sub{Rip();}]);

Status("Ready to Query");
my $ripstatus=0;
my $playstatus=0;

# main loop 
Tk::MainLoop();

ub playstop{
    if($playstatus>0){

        unlink "/tmp/$$.pipe";
        $toplevel->fileevent(PLAY_STDERR,'readable' => ''); 
        Status("Stopping playback");
        close (PLAY_STDERR);

        kill 15, ($playpid1);
        waitpid $playpid1,0;
        waitpid $playpid2,0;
    
        $window_play[$playstatus]->configure(text=>"play");
        Status("Playback stopped");
        $playstatus=0;
    }
}

ub playtrack{
    my($tracknum)=@_;

    if($playstatus>0 && $playstatus==$tracknum){
        playstop();
    }else{
        playstop();
        $playstatus=$tracknum;
        $window_play[$tracknum]->configure(text=>"stop");

        # creating a process -> process pipe is buggy if we [the Perl
        # script] are not one of the processes (first one works,
        # subsequent ones always fail).  So, make a named pipe
        # instead.

        my$pipe="/tmp/$$.pipe";
        system('mknod', $pipe, 'p')
            && system('mkfifo', $pipe)
                && die "can't mknod $pipe: $!";
    
        my$glob;
        eval "\$glob=\"$playrip\"";
        my$glob2;
        eval "\$glob2=\"$play\"";
        $SIG{PIPE} = 'IGNORE';

        die "pipe call failed unexpectedly: $!" unless 
            pipe PLAY_STDERR,WRITEH2;
        
        $playpid1=open3("STDIN","STDOUT",">&WRITEH2",$glob);
        $playpid2=open3("STDIN","STDOUT",">&WRITEH2",$glob2);

        die $! unless close WRITEH2;
        Status("Playing track $tracknum...");
        $toplevel->fileevent(PLAY_STDERR,'readable'=>[sub{PlayStderr();}]);
        
    }
}

ub Cancel{
    Status("Cancelling");
    if(defined($rippid) && $rippid>=0){
        $toplevel->fileevent(RIP_STDERR,'readable' => ''); 
        kill 15, ($rippid);
        close (RIP_STDERR);
        unlink $wavfile;
        unlink $outfile;
        waitpid $rippid,0;
    }
    $window_go->configure(-command=>[sub{Rip();}],text=>"go");
    $window_scan->configure(-command=>[sub{Rescan();}],text=>"rescan");
    $ripstatus=0;
    $rippid=-1;
    Status("Ready");
}    

ub Skip{
    Status("Skipping");
    if(defined($rippid) && $rippid>=0){
        $toplevel->fileevent(RIP_STDERR,'readable' => ''); 
        kill 15, ($rippid);
        close (RIP_STDERR);
        unlink $wavfile;
        unlink $outfile;
        waitpid $rippid,0;
    }
    $rippid=-1;
    Rip();
}    

ub Rip{
    $ripstatus++;

    $window_go->configure(-command=>[sub{Cancel();}],text=>"cancel");
    $window_scan->configure(-command=>[sub{Skip();}],text=>"skip");
    print STDERR "\n";

    while($ripstatus<=$tracks){
        if($trackrip[$ripstatus]){
            # rip this track; event driven, set up the callback.

            my$track=$ripstatus;
            my$title=$trackname[$track];
            $wavfile="/tmp/$$.wav";
            my$glob;
            eval "\$glob=\"$rip\"";
            print "$glob\n";
            
            die "pipe call failed unexpectedly: $!" unless 
                pipe RIP_STDERR,WRITEH;
            $rippid=open3("STDIN",">&STDOUT",">&WRITEH",$glob);

            close WRITEH;
            Status("Starting read...");
            $toplevel->fileevent(RIP_STDERR,'readable'=>[sub{ReadStderr();}]);

            return;
        }
        $ripstatus++;
    }
    # all done!
    $window_go->configure(-command=>[sub{Rip();}],text=>"go");
    $window_scan->configure(-command=>[sub{Rescan();}],text=>"rescan");
    Status("Done");
    $ripstatus=0;
}

ub Track_Path{
    my($tracknum)=@_;
    $trackpad=$tracknum;
    $trackpad="0$tracknum" if($tracknum<10);
    "$trackbase/$artist/$album/$artist - $album - $trackpad - $trackname[$tracknum]$suffix";
}

ub Rescan{
    Status("Scanning disc");
    $toplevel->update();

    $window_go->configure(-state=>"disabled");

    # get table of contents
    my$foo;
    eval "\$foo=\"$query\"";
    my$output=`$foo`;
    my$leadout;
    $tracks=0;
    $output=~s/[^=]+=+\n(.+)/$1/;
    my @toc;
    foreach (split(/\n/,$output)){
        if(m/^\s*([0-9]+)\.\s+(\d+)\s+\S+\s+(\d+)/){
            my$f=$3+150;
            my$s=int($f/75);
            $f-=$s*75;
            my$m=int($s/60);
            $s-=$m*60;
            $tracks=$1 if ($1>$tracks);
            $leadout=$2+$3+150;
            push @toc,"$1 $m $s $f";
        }
    } 

    if($tracks>0){
        my$f=$leadout;
        my$s=int($f/75);
        $f-=$s*75;
        my$m=int($s/60);
        $s-=$m*60;
        push @toc, "999 $m $s $f";
    }

    if($tracks==0){
        $artist="";
        $album="";
        AlbumUpdate();
        Status("Query failed");
        Alert("Could not query cdrom; drive empty?",$output);
    }else{
        for(my$i=1;$i<=$tracks;$i++){
            $trackrip[$i]=1;
        } 
            
        Status("Querying database");
        $toplevel->update();

        # perform cddb query
        my $cddb = new CDDB() or die $!;
        my @discs = $cddb->get_discs_by_toc(@toc);

        my at temp=@{$discs[0]};
      
        if(!defined(@discs)|| $#discs<0 || !defined(@temp[1])){
            Status("Album Loaded; no CDDB entry");
            for(my$i=1;$i<=$tracks;$i++){
                $trackname[$i]="";
            }
            $artist="";
            $album="";
        }else{
            my ($genre, $cddb_id, $title) = @{$discs[0]};
            $title=~/(.+)\s\/\s(.+)/;
            $artist=$1;
            $album=$2;
            $artist=~s/\//:/g;
            $album=~s/\//:/g;
            my $disc_info     = $cddb->get_disc_details($genre, $cddb_id);

            for(my$i=0;$i<$tracks;$i++){
                $trackname[$i+1]=$disc_info->{"ttitles"}[$i];
                $trackname[$i+1]=~s/\//:/g;
            }

            Recheck();
            Status("Album Loaded");
        }
        $cddb->DESTROY();

        AlbumUpdate();
        $window_go->configure(-state=>"normal");
        $window_check->configure(-state=>"normal");
    }
}

ub Recheck{
    for(my$i=1;$i<=$tracks;$i++){
        $trackrip[$i]=0 if(-e Track_Path($i));
    }
}

ub AlbumUpdate{
    my $y=$infoy;

    # re-place widgets up to number of tracks...
    for(my$i=1;$i<=$tracks;$i++){
        $window_track_label[$i]->
            place(-y=>$y,-x=>$x,-anchor=>'nw',-bordermode=>outside);
        $window_rip[$i]->
            place(-y=>$y,-x=>-$x,-relx=>1.,-anchor=>'ne',-bordermode=>outside);
        $window_play[$i]->
            place(-y=>$y,-x=>-$x-$window_rip[$i]->reqwidth(),-relx=>1.,
                  -anchor=>'ne',-bordermode=>outside);
        $window_track[$i]->
            place(-y=>$y,
                  -x=>$x+$window_track_label[$i]->reqwidth(),
                  -relwidth=>1.,
                  -width=> -15
                           -$window_rip[$i]->reqwidth()
                           -$window_track_label[$i]->reqwidth()
                           -$window_play[$i]->reqwidth(),
                  -anchor=>'nw',-bordermode=>outside);

<p>        $y+=$window_rip[$i]->reqheight();
    }
    # unplace widgets past number of tracks
    for(my$i=$tracks+1;$i<=99;$i++){
        $window_track_label[$i]->placeForget();
        $window_track[$i]->placeForget();
        $window_play[$i]->placeForget();
        $window_rip[$i]->placeForget();
    }

    my $totaly=int(46+$window_quit->reqheight()+10+$y);
    my $geometry=$toplevel->geometry();
    $toplevel->minsize(400,$totaly);
    $geometry=~/^(\d+)/;
    $toplevel->geometry($1."x$totaly");
}

ub Shutdown{
    Cancel();
    playstop();
  Tk::exit(0);
}

<p>sub Status{
    my$text=shift @_;
    $window_status->configure(text=>"$text");
    #$toplevel->update();
}

ub Alert{
    my($message,$detail,$window)=@_;

    $window=$toplevel if(!defined($window));
    $modal->destroy() if(defined($modal));

    print STDERR "\n\n$message :: $detail\n";

    $modal=new MainWindow(-class=>"$Xname");
    $modal->configure(-background=>$modal->optionGet("background",""));
    
    $modal_shell=$modal->Label(-class=>Alert,Name=>"shell",
                               borderwidth=>1,relief=>raised)->
                                   place(-x=>4,-y=>4,-relwidth=>1.0,-relheight=>1.0,
                                         -width=>-8,-height=>-8,-anchor=>'nw');

    $modal_exit=$modal_shell->
        Button(-class=>"Exit",text=>"X")->
                   place(-x=>-1,-y=>-1,-relx=>1.0,-rely=>1.0,-anchor=>'se');
    
    $modal_message=$modal_shell->
        Label(text=>$message,-class=>"AlertText")->
            place(-x=>5,-y=>10);

    my$width=$modal_message->reqwidth();
    $width=300 if($width<300);
    
    $detail="" if(!defined($detail));
    $modal_detail=$modal_shell->
        Message(text=>$detail,-class=>"AlertDetail",
                -width=>($width-$modal_exit->reqwidth()))->
            place(-relx=>0,-y=>5,-rely=>1.0,-anchor=>'nw',
                  -in=>$modal_message);

    $width+=20;
    my$height=$modal_message->reqheight()+$modal_detail->reqheight()+30;

    my$xx=$window->rootx();
    my$yy=$window->rooty();
    my$ww=$window->width();
    my$hh=$window->height();

    my$x=$xx+$ww/2-$width/2;
    my$y=$yy+$hh/2-$height/2;

    $modal->geometry($width."x".$height."+".int($x)."+".int($y));
    $modal->resizable(FALSE,FALSE);
    $modal->transient($window);
    $modal_exit->configure(-command=>[sub{$modal->destroy();undef $modal}]);
}

ub ReadStderr{
    my$saveflag=0;

    $bytes=sysread RIP_STDERR, my$scalar, 4096;
    if($bytes==0){
        $toplevel->fileevent(RIP_STDERR,'readable' => ''); 
        Alert("ripper unexpectedly exited!","Skipping track $ripstatus for now...");
        Skip();
    }

    push my at lines, split /[\n\r]/, $saved_stderr.$scalar;
    if((chomp $scalar)==0){
        $saved_stderr=$lines[$#lines];
    }else{
        $saved_stderr="";
    }
    
    foreach my$line (@lines){

        if($line=~/Done encoding file/){
            $saved_stderr="";
            
            # shut down
            waitpid $rippid,0;
            $rippid=-1;
            $toplevel->fileevent(RIP_STDERR,'readable' => ''); 
            close(RIP_STDERR);

            # move the file
            my$trackname="$trackbase";
            mkdir $trackname if(!-e $trackname);

            $trackname="$trackbase/$artist";
            mkdir $trackname if(!-e $trackname);

            $trackname="$trackbase/$artist/$album";
            mkdir $trackname if(!-e $trackname);

            my$trackname=Track_Path($ripstatus);
            print STDERR "moving $outfile to $trackname\n";
            unlink $wavfile;

            $trackname=~s/\"/\\\"/g;
            die "could not move file!: $!" if `mv "$outfile" "$trackname"`;

            # add to unfiled list
            $trackname.='\n';
            `echo "$trackname" >> $unfiled;`;

            # unclick the rip button
            Recheck();

            #rip next
            Rip();
            last;
        }

        if($line=~/\[finished\]/){
            # cdparanoia finished
            $saved_stderr="";
            $toplevel->fileevent(RIP_STDERR,'readable' => ''); 

            waitpid $rippid,0;
            $rippid=-1;
            close(RIP_STDERR);

            my$metatitle=$trackname[$ripstatus];
            $metaartist=$artist;
            $metaalbum=$album;
            $wavfile="/tmp/$$.wav";
            $outfile="/tmp/$$.ogg";

            $metatitle=~s/\"/\\\"/g;
            $metaartist=~s/\"/\\\"/g;
            $metaalbum=~s/\"/\\\"/g;

            my$glob;
            eval "\$glob=\"$encode\"";
            $glob=~s/[\{\}]/\"/g;
            
            print "$glob\n";
            
            die "pipe call failed unexpectedly: $!" unless 
                pipe RIP_STDERR,WRITEH;
            $rippid=open3("STDIN",">&STDOUT",">&WRITEH",$glob);

            close WRITEH;
            Status("Starting encode...");
            $toplevel->fileevent(RIP_STDERR,'readable'=>[sub{ReadStderr();}]);
            last;
        }
        
        if($line=~/Encoding with/){
            Status("Encoding track $ripstatus");
            next;
        }
        if($line=~/\[\s*(\d*\.\d)\%\]/){
            Status("Encoding track $ripstatus [$1%]");
            next;
        }
    
        if($line=~/to sector\s*(\d+)/){
            $endsector=$1;
        }

        if($line=~/\[wrote\]\s\@\s(\d+)/){
            $left=$endsector-int($1/1176);
            Status("Reading track $ripstatus [$left]");
        }
            
    }

<p>}

ub PlayStderr{
    my$saveflag=0;

    $bytes2=sysread PLAY_STDERR, my$scalar, 4096;

    print $scalar;

    if($bytes2==0){
        playstop();
        return;
    }

    push my at lines, split /[\n\r]/, $saved_stderr2.$scalar;
    if((chomp $scalar)==0){
        $saved_stderr2=$lines[$#lines];
    }else{
        $saved_stderr2="";
    }
    
    foreach my$line (@lines){

        if($line=~/\[finished\]/){
            # cdparanoia finished
            $saved_stderr2="";
            playstop();
            return;
        }
    }
}

<p><p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list