[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