#!/usr/bin/perl -w

#    HacBurn-0.3.5 is a Gtk2 based cd writing application.
#    Copyright (C) 2005 Andrei Perhinschi (aperh@users.sourceforge.net)
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

# load modules
use CDDB_get qw ( get_cddb get_discids );
use File::Spec;
use Fcntl;
use Gtk2 '-init';
use Gtk2::SimpleList;
use Net::Ping;

# determine temp dir
$tempdir = File::Spec->tmpdir;
print "Temporary Dir: $tempdir\n";

# default mode is data/tao
$set_data_burn = 1;
$set_music_burn = 0;
$mode = "-tao";

# scan for CD drives
&drive_scan;

# main window creation
$mw = Gtk2::Window->new;
$mw->set_title ( "HacBurn 0.3.5 - Data Project" );

# buttons
$burn = Gtk2::Button->new ( "Burn" );
$music_cd = Gtk2::Button->new ( "Music CD" );
$data_cd = Gtk2::Button->new ( "Data CD" );
$more_opt = Gtk2::Button->new ( "Options" );

$make_iso = Gtk2::Button->new ( "Make Iso" );
$load_iso = Gtk2::Button->new ( "Load Iso/Cue" );
$eject_cd = Gtk2::Button->new ( "Eject CD" );
$load_cd = Gtk2::Button->new ( "Load CD" );

$copy_cd = Gtk2::Button->new ( "Copy CD" );
$rip_cd = Gtk2::Button->new ( "Rip CD" );
$blank_rw = Gtk2::Button->new ( "Blank RW" );
$exit = Gtk2::Button->new ( "Exit" );

$about = Gtk2::Button->new("About");

# Checkbuttons
$blank_all = Gtk2::CheckButton->new_with_label ( "Blank All" );
$blank_fast = Gtk2::CheckButton->new_with_label ( "Blank Fast" );
$size_650_mb = Gtk2::CheckButton->new_with_label ( "650mb CD" );
$size_700_mb = Gtk2::CheckButton->new_with_label ( "700mb CD" );

# entry boxes
$image_entry = Gtk2::Entry->new;
$dev_entry = Gtk2::ComboBoxEntry->new_text;
$speed_entry = Gtk2::ComboBoxEntry->new_text;

# populate entry boxes

@speeds = ( "0X", "2X", "4X", "8X", "12X", "16X", "20X", "24X", "32X", "36X", "40X", "48X", "52X" );

foreach $dev_var ( @drives ) {
	$i = 0;
	$dev_entry->insert_text ( $i, $dev_var );
	$i++;
	}

foreach $speed_var (@speeds) {
	$i = 0;
	$speed_entry->insert_text ( $i, "$speed_var" );
	$i++;
	}

# entry labels
$image_label = Gtk2::Label->new ( "Iso/Cue file" );
$dev_label = Gtk2::Label->new ( "Writer device" );
$speed_label = Gtk2::Label->new ( "Burn speed" );

# progressbar
$progress = Gtk2::ProgressBar->new;

# default progressbar values
$size_700_mb->set_active ( 1 );
$MB = 700;
$mb = 734003200;
$progress_text = "0.0";
$progress->set_text ( "$progress_text% - $MB mb Cd" );
$progress->set_fraction ( 0 );

# packboxes
$first_button_box = new Gtk2::HBox ( 1, 0 );
$first_button_box->pack_start ( $burn, 0, 1, 0 ); 
$first_button_box->pack_start ( $music_cd, 0, 1, 0 ); 
$first_button_box->pack_start ( $data_cd, 0, 1, 0 ); 
$first_button_box->pack_start ( $more_opt, 0, 1, 0 ); 

$second_button_box = new Gtk2::HBox ( 1, 0 );
$second_button_box->pack_start ( $make_iso, 0, 1, 0 ); 
$second_button_box->pack_start ( $blank_rw, 0, 1, 0 ); 
$second_button_box->pack_start ( $eject_cd, 0, 1, 0 ); 
$second_button_box->pack_start ( $load_cd, 0, 1, 0 ); 

$third_button_box = new Gtk2::HBox ( 1, 0 );
$third_button_box->pack_start ( $copy_cd, 0, 1, 0 ); 
$third_button_box->pack_start ( $rip_cd, 0, 1, 0 ); 
$third_button_box->pack_start ( $about, 0, 1, 0 ); 
$third_button_box->pack_start ( $exit, 0, 1, 0 ); 

$thirdbox = new Gtk2::HBox ( 1, 0 );
$thirdbox->pack_start ( $blank_all, 0, 1, 0 ); 
$thirdbox->pack_start ( $blank_fast, 0, 0, 0 ); 

$eighthbox = new Gtk2::HBox ( 1, 0 );
$eighthbox->pack_start ( $size_650_mb, 0, 1, 0 ); 
$eighthbox->pack_start ( $size_700_mb, 0, 0, 0 ); 

$image_box = new Gtk2::HBox ( 1,0 );
$image_box->pack_start ( $image_entry, 0, 1, 0 );
$image_box->pack_start ( $load_iso, 0, 0, 0 );

$dev_box = new Gtk2::HBox ( 1,0 );
$dev_box->pack_start ( $dev_entry, 0, 0, 0 ); 
$dev_box->pack_start ( $dev_label, 0, 0, 0 );

$speed_box = new Gtk2::HBox ( 1,0 );
$speed_box->pack_start ( $speed_entry, 0, 0, 0 ); 
$speed_box->pack_start ( $speed_label, 0, 0, 0 );

$secondary_box = new Gtk2::VBox ( 1, 0 );
$secondary_box->pack_start ( $first_button_box, 0, 1, 0 );
$secondary_box->pack_start ( $second_button_box, 0, 1, 0 );
$secondary_box->pack_start ( $third_button_box, 0, 1, 0 );
$secondary_box->pack_start ( $image_box, 0, 1, 0 );
$secondary_box->pack_start ( $dev_box, 0, 1, 0 );
$secondary_box->pack_start ( $speed_box, 0, 1, 0 );
$secondary_box->pack_start ( $thirdbox, 0, 1, 0 ); 
$secondary_box->pack_start ( $eighthbox, 0, 1, 0 ); 
$secondary_box->pack_start ( $progress, 0, 1, 0 ); 

$main_box = new Gtk2::VBox ( 0, 0 );
$main_box->pack_start ( $secondary_box, 0, 1, 0 );

# callback registration
$mw->signal_connect(destroy => sub { Gtk2->main_quit;} );

$about->signal_connect(clicked => sub { about () } );

$burn->signal_connect(clicked => sub { burn () } );
$music_cd->signal_connect (clicked => sub { music_funct () } );
$data_cd->signal_connect (clicked => sub { destroy_music (), destroy_mkiso (), destroy_rip () } );
$more_opt->signal_connect (clicked => sub{ more_options () } );

$make_iso->signal_connect (clicked => sub { data_funct () } );
$load_iso->signal_connect (clicked => sub { iso_select () } );
$eject_cd->signal_connect (clicked => sub { eject () } );
$load_cd->signal_connect (clicked => sub { load () } );

$copy_cd->signal_connect (clicked => sub { copy_cd () } );
$rip_cd->signal_connect (clicked => sub { rip_funct () } );
$blank_rw->signal_connect (clicked => sub { blank_rw () } );
$exit->signal_connect (clicked =>  sub { Gtk2->main_quit; } );

$blank_all->signal_connect (clicked => sub { unclick_blank_fast () } );
$blank_fast->signal_connect (clicked => sub { unclick_blank_all () } );
$size_650_mb->signal_connect (clicked => sub { unclick_700_mb () } );
$size_700_mb->signal_connect (clicked => sub { unclick_650_mb () } );

# set window attributes and show it
$mw->add ( $main_box );
$mw->show_all ();

# print defaults
print "Default Mode: Data/TAO\n";

# gtk2 event loop
Gtk2->main;


### Subroutines

# about 
sub about {

$about_logo = Gtk2::Gdk::Pixbuf->new_from_file ( "/usr/share/pixmaps/hacburn.png" );
$about_dialog = Gtk2::AboutDialog->new;
$about_dialog->set_authors ( "Andrei Perhinschi - lead programmer", "Iani Tararache - logo", "Access Excess - webmaster" );
$about_dialog->set_comments ( "HacBurn 0.3.5 is a graphical interface to several CD recording applications." );
$about_dialog->set_copyright ( "Copyright Andrei Perhinschi 2005" );
$about_dialog->set_license ( "GPL" );
$about_dialog->set_name ( "HacBurn" );
$about_dialog->set_version ( "0.3.5" );
$about_dialog->set_website ( "www.hacburn.sourceforge.net" );
$about_dialog->set_logo ( $about_logo );

$about_dialog->show_all;
}

# scan for drives
sub drive_scan {

my $op_s = `uname -s`;
my $kern_ver = `uname -r`;
chomp $op_s;
$kern_ver = substr $kern_ver, 0, 3;

unless ( $op_s eq "SunOS" ) {
	open ( FSTAB, "/etc/fstab" )
		or die "Could not open /etc/fstab\n";
	}
else {
	open ( FSTAB, "/etc/vfstab" )
		or die "Could not open /etc/vfstab\n";
	}

while ( <FSTAB> ) {
	push @nodes, "$_\n" if /iso9660/ || /cd9660/;
	}

close ( FSTAB )
	or die "Could not close /etc/fstab\n";

foreach my $node ( @nodes ) {
	$node =~ /\s/;
	$node = "$`";
	print "NODE: $node\n";
	}


if ( $op_s eq "Linux" && $kern_ver eq "2.6" ) {
	@scanbus = `cdrecord dev=ATA -scanbus`;	
	}
else {
	@scanbus = `cdrecord -scanbus`;
	}

foreach my $dev_device ( @scanbus ) {
	if ( $dev_device =~ /Removable/ ) {
	my $drive = $dev_device;
	$drive =~ /\051/;
	$drive = "$'";
	$drive =~ s/\'//g;
	$drive =~ /Removable/;
	$drive = "$`";
	print "DRIVE: $drive\n";
	push @drives, $drive;

	@dev_device_ar = split /\s/, $dev_device;
	$dev_device = $dev_device_ar[1];
	if ( $op_s eq "Linux" && $kern_ver eq "2.6" ) {
		$dev_device = "ATA:$dev_device";
		}
	print "DEV_DEVICE: $dev_device\n";
	push @devices, $dev_device;
		}
	}

print "This computer is running $op_s\n";

}

# get device
sub get_dev {

# retrieve the scsi target of selected drive
$dev_entry_child = $dev_entry->get_child;
$dev_sub = $dev_entry_child->get_text;
foreach $dev_sub_var ( @drives ) {
	if ( $dev_sub_var eq $dev_sub ) {
		for my $n ( 0 .. $#drives ) {
			if ( $drives[$n] eq $dev_sub ) {
				$dev = $devices[$n];
				}
			}
		}
	}

# retrieve the device node of the selected scsi target
if ( $_[0] eq "node" ) {
	print "REQUESTING NODE FROM GET_DEV\n";

	# sort device nodes
	@nodes = sort {$a cmp $b} ( @nodes );
	print "NODES:\n @nodes\n";

	#sort scsi targets
	@devices = sort {$a cmp $b} ( @devices );
	print "DEVICES:\n @devices\n";

	foreach my $device ( @devices ) {
		if ( $device eq $dev ) {
			for my $n ( 0 .. $#devices ) {
				if ( $devices[$n] eq $device ) {
				$dev = $nodes[$n];
				print "DEV: $dev\n";
					}
				}
			}
		}
	}
}

# check for disc
sub get_disc {

&get_dev ( "node" );

# do a little bit of sysopen magic
# to check disc existence
if ( defined $dev ) {
	print "dev: $dev\n";
	sysopen ( FROM_DEV, $dev, O_RDONLY );
	if ( $! =~ /medium/ ) {
		$disc_capacity = 0;
		print "Could not open $dev: $!\n";
		}
	else {
		$disc_capacity = 1;
		close ( FROM_DEV )
			or die "Could not close $dev\n";
		}
	print "DISC_CAPACITY: $disc_capacity\n";
	}

else {
	$drive_error_dialog = Gtk2::MessageDialog->new(
	$mw,
	"destroy-with-parent",
	"error",
	"ok",
	"Please select a drive and retry.");
	$drive_error_dialog->show;
	if ( "ok" eq $drive_error_dialog->run ) {
		$drive_error_dialog->destroy;
		}
	die "No drive selected";
	}
	
if ( $disc_capacity == 0 ) {
	$disc_error_dialog = Gtk2::MessageDialog->new(
	$mw,
	"destroy-with-parent",
	"error",
	"ok",
	"There is no disc in drive $dev.\nPlease insert a disc and retry.");
	$disc_error_dialog->show;
	if ( "ok" eq $disc_error_dialog->run ) {
		$disc_error_dialog->destroy;
		}
	die "No disc in drive $dev";
	}
return ( $disc_capacity );
}

# no device and/or no blanking option selected
sub error_dev_rw {

$rw_dialog_error = Gtk2::MessageDialog->new(
	$mw,
	"destroy-with-parent",
	"error",
	"ok",
	"Please choose a CD drive and/or blanking option");

$rw_dialog_error->show_all;

if ( "ok" eq $rw_dialog_error->run ) {
	$rw_dialog_error->destroy;
	return;
	}
}

# no device and/or no speed selected
sub error_dev_speed {

$dev_speed_dialog_error = Gtk2::MessageDialog->new(
	$mw,
	"destroy-with-parent",
	"error",
	"ok",
	"Please choose a CD drive and/or a speed");

$dev_speed_dialog_error->show_all;

if ( "ok" eq $dev_speed_dialog_error->run ) {
	$dev_speed_dialog_error->destroy;
	return;
	}
}

# rw blanking
sub blank_rw {

&get_disc;

if ( defined $dev && defined $erase ) {
	&get_disc;
	if ( $disc_capacity == 0 ) {
		return;
		}

	$rw_dialog = Gtk2::MessageDialog->new(
	$mw,
	"destroy-with-parent",
	"question",
	"ok",
	"Erase CD in drive $dev_sub in mode $erase ?");

	$rw_dialog->add_button( "Cancel"  ,"cancel" ) ; 
	
	if ( "ok" eq $rw_dialog->run ) {
		$rw_dialog->destroy;
		print "Starting to erase disc in $dev in mode $erase\n";
		system ( "cdrecord dev=$dev blank=$erase" );
		print "Done erasing disc in $dev in mode $erase\n";
		}
	
	if ( "cancel" ) {
		$rw_dialog->destroy;
		$dev = undef;
		return;
		}
	}

else {
	&error_dev_rw;
	}
}

# more options
sub more_options {

$options_dialog = Gtk2::Dialog->new_with_buttons(
	"More Options",
	$mw,
	"destroy-with-parent",
	"gtk-help"=>"help",
	"gtk-cancel"=>"cancel",
	"gtk-ok"=>"ok");

# chkbuttons
$tao_button = Gtk2::CheckButton->new_with_label ( "TAO" );
$dao_button = Gtk2::CheckButton->new_with_label ( "DAO" );
$ob_button = Gtk2::CheckButton->new_with_label ( "Overburn" );
$nopad_button = Gtk2::CheckButton->new_with_label ( "Remove audio padding" );
$pad_button = Gtk2::CheckButton->new_with_label ( "Add audio padding" );
$nofix_button = Gtk2::CheckButton->new_with_label ( "Don't fixate disc" );
$eject_done = Gtk2::CheckButton->new_with_label ( "Eject When Done " );
$dummy_cd = Gtk2::CheckButton->new_with_label ( "Dummy CD" );
$use_db = Gtk2::CheckButton->new_with_label ( "Use cd database (requires net connection)" );

@option_buttons = ( $tao_button, $dao_button, $ob_button, $nopad_button, $pad_button, $nofix_button, $eject_done, $dummy_cd, $use_db );

@options = ( $mode, $pad, $overburn, $nofix, $dummy, $eject, $using_db );

# extra packboxes
$options_box = new Gtk2::VBox ( 1,0 );
$options_box->pack_start ( $tao_button, 0, 0, 0 );
$options_box->pack_start ( $dao_button, 0, 0, 0 );
$options_box->pack_start ( $ob_button, 0, 0, 0 );
$options_box->pack_start ( $nopad_button, 0, 0, 0 );
$options_box->pack_start ( $pad_button, 0, 0, 0 );
$options_box->pack_start ( $nofix_button, 0, 0, 0 );
$options_box->pack_start ( $eject_done, 0, 0, 0 );
$options_box->pack_start ( $dummy_cd, 0, 0, 0 );
$options_box->pack_start ( $use_db, 0, 0, 0 );

$options_dialog->vbox->add ( $options_box );
$options_dialog->show_all;

foreach $option ( @options ) {
	if ( defined $option ) {
		foreach $opt_but ( @option_buttons ) {
			if ( $option eq "-tao" && $opt_but eq $tao_button ) {
			$opt_but->set_active ( 1 );
				}
			if ( $option eq "-dao" && $opt_but eq $dao_button ) {
			$opt_but->set_active ( 1 );
				}
			if ( $option eq "-pad" && $opt_but eq $pad_button ) {
			$opt_but->set_active ( 1 );
				}
			if ( $option eq "-nopad" && $opt_but eq $nopad_button ) {
			$opt_but->set_active ( 1 );
				}
			if ( $option eq "-overburn" && $opt_but eq $ob_button ) {
			$opt_but->set_active ( 1 );
				}
			if ( $option eq "-eject" && $opt_but eq $eject_done ) {
			$opt_but->set_active ( 1 );
				}
			if ( $option eq "-dummy" && $opt_but eq $dummy_cd ) {
			$opt_but->set_active ( 1 );
				}
			if ( $option eq "-nofix" && $opt_but eq $nofix_button ) {
			$opt_but->set_active ( 1 );
				}
			if ( $option eq "using_db" && $opt_but eq $use_db ) {
			$opt_but->set_active ( 1 );
				}
			}
		}
	}

$tao_button->signal_connect ( clicked => sub { tao_mode () } );
$dao_button->signal_connect ( clicked => sub { dao_mode () } );
$nopad_button->signal_connect ( clicked => sub { nopad_mode () } );
$pad_button->signal_connect ( clicked => sub { pad_mode () } );
$eject_done->signal_connect ( clicked => sub { eject_done () } );
$dummy_cd->signal_connect ( clicked => sub { dummy_cd () } );
$use_db->signal_connect ( clicked => sub { use_db () } );

	# set tao mode
	sub tao_mode {

	if ( $tao_button->get_active ) {
		$mode = "-tao";
		$dao_button->set_active ( 0 );
		}
	}

	# set dao mode
	sub dao_mode {

	if ( $dao_button->get_active ) {
		$mode = "-dao";
		$tao_button->set_active ( 0 );
		}
	}

	# set nopad mode
	sub nopad_mode {
	
	if ( $nopad_button->get_active ) {
		$pad_button->set_active ( 0 );
		$pad = "-nopad";
		}
	}

	# set pad mode
	sub pad_mode {
	
	if ( $pad_button->get_active ) {
		$nopad_button->set_active ( 0 );
		$pad = "-pad";
		}
	}
	
	# eject after a burn
	sub eject_done {
	
	if ( $eject_done->get_active ) {
		$eject = "-eject";
		}
	
	else {
		$eject = undef;
		}
	}
	
	# dummy cd
	sub dummy_cd {
	
	if ( $dummy_cd->get_active ) {
		$dummy = "-dummy";
		}
	
	else {
		$dummy = undef;
		}
	}

	# use db
	sub use_db {
	
	if ( $use_db->get_active ) {
		$using_db = "using_db";
		}
	
	else {
		$using_db = "not_using_db";
		}
	}

# ok button press
if ( "ok" eq $options_dialog->run ) {
	if ( $ob_button->get_active ) {
		$overburn = "-overburn";
		}
	if ( $nofix_button->get_active ) {
		$nofix = "-nofix";
		}

	$options_dialog->destroy;
	}

# cancel button press
if ( "cancel" ) {
	$options_dialog->destroy;
	}
}



# cd copying (data only for now)
sub copy_cd {

$copy_dialog = Gtk2::Dialog->new_with_buttons(
	"Copy CD",
	$mw,
	"destroy-with-parent",
	"gtk-help"=>"help",
	"gtk-cancel"=>"cancel",
	"gtk-ok"=>"ok");

# entry boxes
$copy_from_entry = Gtk2::ComboBoxEntry->new_text ();
$copy_to_entry = Gtk2::ComboBoxEntry->new_text ();
$copy_speed_entry = Gtk2::ComboBoxEntry->new_text ();

# populate entry boxes
foreach my $copy_from_dev_var ( @drives ) {
	my $i = 0;
	$copy_from_entry->insert_text ( $i, $copy_from_dev_var );
	$i++;
	}

foreach my $copy_to_dev_var ( @drives ) {
	my $i = 0;
	$copy_to_entry->insert_text ( $i, $copy_to_dev_var );
	$i++;
	}

foreach my $copy_speed_var ( @speeds ) {
	my $i = 0;
	$copy_speed_entry->insert_text ( $i, "$copy_speed_var" );
	$i++;
	}

# entry labels
$copy_from_label = Gtk2::Label->new ("Copy From" );
$copy_to_label = Gtk2::Label->new ( "Copy To" );
$copy_speed_label = Gtk2::Label->new ( "Copy Speed" );

# chkbuttons
$two_drives = Gtk2::CheckButton->new_with_label ( "2 CD Drives" );
$one_drive = Gtk2::CheckButton->new_with_label ( "1 CD Drive" );
$two_drives->set_active ( 1 );

# callbacks
$two_drives->signal_connect ( clicked => sub { two_drives () } );
$one_drive->signal_connect ( clicked => sub { one_drive () } );

# extra packboxes
$copy_from_box = new Gtk2::HBox ( 1,0 );
$copy_from_box->pack_start ( $copy_from_label, 0, 0, 0 );
$copy_from_box->pack_start ( $copy_from_entry, 0, 0, 0 );

$copy_to_box = new Gtk2::HBox ( 1,0 );
$copy_to_box->pack_start ( $copy_to_label, 0, 0, 0 );
$copy_to_box->pack_start ( $copy_to_entry, 0, 0, 0 );

$copy_speed_box = new Gtk2::HBox ( 1,0 );
$copy_speed_box->pack_start ( $copy_speed_label, 0, 0, 0 );
$copy_speed_box->pack_start ( $copy_speed_entry, 0, 0, 0 );

$drive_box = new Gtk2::HBox ( 1,0 );
$drive_box->pack_start ( $two_drives, 0, 0, 0 );
$drive_box->pack_start ( $one_drive, 0, 0, 0 );

$copy_dialog->vbox->add ( $copy_from_box );
$copy_dialog->vbox->add ( $copy_to_box );
$copy_dialog->vbox->add ( $copy_speed_box );
$copy_dialog->vbox->add ( $drive_box );

$copy_dialog->show_all;

# ok button press
if ("ok" eq $copy_dialog->run) {
	if ( $two_drives->get_active ) {
		$copy_speed_entry_child = $copy_speed_entry->get_child;
		$copy_speed = $copy_speed_entry_child->get_text;
		$copy_speed =~ s/X//g;

		$copy_from_entry_child = $copy_from_entry->get_child;
		$copy_from_sub = $copy_from_entry_child->get_text;
		foreach $copy_from_sub_var ( @drives ) {
			if ( $copy_from_sub_var eq $copy_from_sub ) {
				for my $a ( 0 .. $#drives ) {
					if ( $drives[$a] eq $copy_from_sub ) {
						$copy_from = $devices[$a];
						}
					}
				}
			}

		$copy_to_entry_child = $copy_to_entry->get_child;
		$copy_to_sub = $copy_to_entry_child->get_text;
		foreach $copy_to_sub_var ( @drives ) {
			if ( $copy_to_sub_var eq $copy_to_sub ) {
				for my $a ( 0 .. $#drives ) {
					if ( $drives[$a] eq $copy_to_sub ) {
						$copy_to = $devices[$a];
						}
					}
				}
			}
		&two_drive_copy;
		}

	if ($one_drive->get_active) {
		$copy_speed_entry_child = $copy_speed_entry->get_child;
		$copy_speed = $copy_speed_entry_child->get_text;
		$copy_speed =~ s/X//g;

		$copy_from_entry_child = $copy_from_entry->get_child;
		$copy_from_sub = $copy_from_entry_child->get_text;
		foreach $copy_from_sub_var ( @drives ) {
			if ( $copy_from_sub_var eq $copy_from_sub ) {
				for my $a ( 0 .. $#drives ) {
					if ( $drives[$a] eq $copy_from_sub ) {
						$copy_from = $devices[$a];
						}
					}
				}
			}
		&one_drive_copy;
		}
	}

# cancel button press
if ( "cancel" ) {
	$copy_dialog->destroy;
	}
}

sub two_drives {

if ( $two_drives->get_active ) {
	if ( !$copy_to_box->is_sensitive ) {
		$copy_to_box->set_sensitive ( 1 );
		}
	$one_drive->set_active ( 0 );
	}
}

sub one_drive {

if ( $one_drive->get_active ) {
	if ( $copy_to_box->is_sensitive ) {
		$copy_to_box->set_sensitive ( 0 );
		}
	$two_drives->set_active ( 0 );
	}
}

# two drive copy
sub two_drive_copy {

print "$copy_from\n";
print "$copy_to\n";
print "$copy_speed\n";

system ( "cdrecord -v dev=$copy_to speed=$copy_speed -isosize $copy_from" );
}

# one drive copy
sub one_drive_copy {

print "$copy_from\n";
print "$copy_to\n";
print "$copy_speed\n";

# rip iso of cd
system ( "dd if=$copy_from of=$tempdir/cd_copy_image.iso" );

# eject cd
system ( "eject $copy_from" );

# prompt for new cd
$insert_dialog = Gtk2::MessageDialog->new (
$mw,
"destroy-with-parent",
"warning",
"ok",
"Insert blank CD and click Ok" );

$insert_dialog->add_button ( "Cancel"  ,"cancel" ) ; 
$insert_dialog->show_all;

# burn new cd
if ( "ok" eq $insert_dialog->run ) {
	$insert_dialog->destroy;
	system ( "eject -t $copy_from" );
	system ( "cdrecord -v speed=$copy_speed dev=$copy_from $tempdir/cd_copy_image.iso" );
	$copy_dialog->destroy;	
	}

if ( "cancel" ) {
	$insert_dialog->destroy;
	}
}

# called by burn button
sub burn {

&get_disc;

$speed_entry_child = $speed_entry->get_child;
$speed = $speed_entry_child->get_text;
$speed =~ s/X//g;

# ask to proceed with burn
if ( defined $dev && $speed ne "") {
	&get_disc;
	if ( $disc_capacity == 0 ) {
		return;
		}

	$burn_confirm_dialog = Gtk2::MessageDialog->new(
	$mw,
	"destroy-with-parent",
	"question",
	"ok",
	"Burn CD in drive $dev?");

	$burn_confirm_dialog->add_button( "Cancel"  ,"cancel" ) ; 

	$image_file = $image_entry->get_text;
	
	# perform data burn
	if ( $set_data_burn == 1 ) {
		if ( $image_file ne "") {
			print "burning data now...\n";
			&data_burn;
			return;
			}
		
		# no iso/cue file given
		else {
			$data_burn_error = Gtk2::MessageDialog->new(
			$mw,
			"destroy-with-parent",
			"error",
			"ok",
			"Please load an iso or cue file.");
		
			$data_burn_error->show_all;
		
			if ( "ok" eq $data_burn_error->run ) {
				$data_burn_error->destroy;
				return;
				}
			}
		}

	# perform music burn
	if ( $set_music_burn == 1 ) {
		if ( exists $music_files[0] ) {
			print "burning music now...\n";
			&music_burn;
			return;
			}

		# no mp3/ogg/wav files given
		else {
			$music_burn_error = Gtk2::MessageDialog->new(
			$mw,
			"destroy-with-parent",
			"error",
			"ok",
			"Please add at least one mp3/ogg/wav file to the list and convert it to wav.");
		
			$music_burn_error->show_all;
		
			if ( "ok" eq $music_burn_error->run ) {
				$music_burn_error->destroy;
				return;
				}
			}
		}
	}
# no speed given
else {
	&error_dev_speed;
	}
}

# called by data chkbutton
sub data_funct {

if ( exists $mkiso[0] ) {
	&destroy_mkiso;
	}
if ( !exists $mkiso[0] ) {
	&mkiso;
	}
}

# data burn
sub data_burn {

$image_file = $image_entry->get_text;
$image_ext = substr ( $image_file, -3, 3 );

$speed_entry_child = $speed_entry->get_child;
$speed = $speed_entry_child->get_text;
$speed =~ s/X//g;

&get_disc;


if ( $image_ext eq "iso" ) {
	$image_file =~ s/\s/\\ /g;
	print "$image_file\n";
	print "$speed\n";
	print "$dev\n";
	system ( "cdrecord -v $eject $dummy speed=$speed dev=$dev -data $mode $pad $nofix $overburn $image_file\n" );
	$dev = undef;
	return;	
	}

if ( $image_ext eq "cue" ) {
	$image_file =~ s/\s/\\ /g;
	print "$image_file\n";
	print "$speed\n";
	print "$dev\n";
	system ( "cdrecord -v $eject $dummy speed=$speed dev=$dev -data -dao $pad $nofix $overburn cuefile=$image_file" );
	return;
	}
}

# This is the iso making sub
sub mkiso {

if (exists $music[0]) {
	&destroy_music;
	}
if (exists $rip[0]) {
	&destroy_rip;
	}

$mw->set_title ( "HacBurn 0.3.5 - Make Iso" );

# mkiso window + list
$mkiso_window = new Gtk2::ScrolledWindow ( undef,undef );		# scroll window
$mkiso_list = Gtk2::SimpleList->new ( 'Filename' => 'text',
					'Size (Kb)' => 'int');		# file list
$mkiso_list->get_selection->set_mode ( 'multiple' );
$mkiso_window->add_with_viewport ( $mkiso_list );			# add to scroll window

# buttons
$add_mkiso = Gtk2::Button->new ( "Add" );
$remove_mkiso = Gtk2::Button->new ( "Remove" );
$build_iso = Gtk2::Button->new ( "Build Iso" );
$cancel_mkiso = Gtk2::Button->new ( "Cancel" );

# entrybox
$mkiso_entry = Gtk2::Entry->new ();

# entry button
$mkiso_entry_button = Gtk2::Button->new ( "Save Iso image as" );

# callbacks
$add_mkiso->signal_connect ( clicked => sub { add_mkiso () } );
$remove_mkiso->signal_connect ( clicked => sub { remove_mkiso () } );
$mkiso_entry_button->signal_connect ( clicked => sub { save_mkiso () } );
$build_iso->signal_connect ( clicked => sub { build_iso () } );
$cancel_mkiso->signal_connect ( clicked => sub { destroy_mkiso () } );

# packboxes
$abox = new Gtk2::HBox ( 1, 0 );
$abox->pack_start ( $add_mkiso, 0, 1, 0 );
$abox->pack_start ( $remove_mkiso, 0, 1, 0 );
$abox->pack_start ( $build_iso, 0, 1, 0 );
$abox->pack_start ( $cancel_mkiso, 0, 1, 0 );

$save_mkiso_box = new Gtk2::HBox ( 1,0 );
$save_mkiso_box->pack_start ( $mkiso_entry_button, 0, 1, 0 ); 
$save_mkiso_box->pack_start ( $mkiso_entry, 0, 1, 0 );

$bbox = new Gtk2::VBox ( 0, 0 );
$bbox->pack_start ( $mkiso_window, 0, 0, 0 );
$bbox->pack_start ( $abox, 0, 0, 0 );
$bbox->pack_start ( $save_mkiso_box, 0, 0, 0 );

$bbox->show_all;
$main_box->pack_start ( $bbox, 0, 1, 0 );

@mkiso = ( $mkiso_window,				# add all widgets to one array
	$mkiso_list,
	$mkiso_entry,
	$mkiso_entry_button,
	$add_mkiso,
	$remove_mkiso,
	$build_iso,
	$cancel_mkiso,
	$abox,
	$bbox );
}

# add file to mkiso list
sub add_mkiso {

$mkiso_add_window = Gtk2::FileChooserDialog->new(
	"Add File",
	$mw,
	"open",
	"gtk-cancel"=>"cancel",
	"gtk-ok"=>"ok" );
$mkiso_add_window->set_select_multiple ( 1 );

if ( "ok" eq $mkiso_add_window->run ) {

	@mkiso_add_filenames = $mkiso_add_window->get_filenames;
	print "@mkiso_add_filenames\n";

	foreach $mkiso_add_filename ( @mkiso_add_filenames ) {
		if ( $mkiso_add_filename =~ /\)/ || $mkiso_add_filename =~ /\(/ ) {
			$mkiso_name_error = Gtk2::MessageDialog->new(
			$mw,
			"destroy-with-parent",
			"warning",
			"ok",
			"This filename contains one or more parantheses, mkisofs chokes on parantheses. Please rename the file and retry.");
			$mkiso_name_error->show_all;
			if ( "ok" eq $mkiso_name_error->run ) {
				$mkiso_name_error->destroy;
				$mkiso_add_window->destroy;
				return;
				}
			}
	
		@mkiso_file_parts = split ( /\//, $mkiso_add_filename );
		$mkiso_file_shortname = "$mkiso_file_parts[@mkiso_file_parts - 1]";
		$mkiso_add_size = -s $mkiso_add_filename;
	
		$mkiso_add_filename =~ s/\s/\\ /g;
		push @mkiso_files, "$mkiso_add_filename";
	
		$filled_size = $progress->get_fraction;
	#	print "filled_size: $filled_size\n";
		
		$fraction1 = ( ( $mkiso_add_size * 100) / $mb );
	#	print "fraction1: $fraction1\n";
		$fraction2 = ( ( $fraction1 / 100) + $filled_size );
	#	print "fraction2: $fraction2\n";
	
		$fraction4 = $progress->get_text;
		$fraction4 = substr ( $fraction4, 0, 6 );
		$fraction3 = ( $fraction1 + $fraction4 );
	#	print "fraction3: $fraction3\n";

		$fraction3 = substr ( $fraction3, 0, 6 );	
		$mkiso_add_size = ( $mkiso_add_size / 1000 );	
		push @{$mkiso_list->{data}}, [$mkiso_file_shortname, $mkiso_add_size];	

		$progress->set_text ( "$fraction3 % - $MB mb Cd" );
		$progress->set_fraction ( $fraction2 );
		}
	}

$mkiso_add_window->show_all;
$mkiso_add_window->destroy;
}

# remove file from mkiso list
sub remove_mkiso {

@mkiso_index = $mkiso_list->get_selected_indices;
splice @{ $mkiso_list->{data} }, $mkiso_index[0], 1;
splice @mkiso_files, $mkiso_index[0], 1;

$progress->set_fraction ( 0 );

$fraction4 = $progress->get_text;
$fraction4 = substr ( $fraction4, 0, 6 );
$fraction1 = substr ( $fraction1, 0, 6 );
$fraction3 = ( $fraction4 - $fraction1 );
#print "fraction4: $fraction4\n";
#print "fraction1: $fraction1\n";
#print "fraction3: $fraction3\n";
$fraction3 = substr ( $fraction3, 1, 3 );
$progress->set_text ( "$fraction3 % - $MB mb Cd" );

foreach $still_listed ( @mkiso_files ) {
	$filled_size = $progress->get_fraction;
#	print "filled_size: $filled_size\n";
	$mkiso_add_size = -s "$still_listed";
	$fraction1 = ( ( $mkiso_add_size * 100) / $mb );
#	print "fraction1: $fraction1\n";
	$fraction2 = ( ( $fraction1 / 100) + $filled_size );
#	print "fraction2: $fraction2\n";
	$progress->set_fraction ( $fraction2 );
	}
}

# iso filename to save under
sub save_mkiso {

$mkiso_save_window = Gtk2::FileChooserDialog->new(
	"Save File As",
	$mw,
	"save",
	"gtk-cancel"=>"cancel",
	"gtk-ok"=>"ok" );

if ( "ok" eq $mkiso_save_window->run ) {
	$mkiso_save_filename = $mkiso_save_window->get_filename;
	}

$mkiso_entry->set_text ( $mkiso_save_filename );
$mkiso_save_window->show_all;
$mkiso_save_window->destroy;
}

# build iso
sub build_iso {

system ( "mkisofs -o $mkiso_save_filename @mkiso_files\n" );
}

# destroy mkiso widgets
sub destroy_mkiso {

$mw->set_title ( "HacBurn 0.3.5 - Data Project" );
if ( exists $mkiso[9] ) {
	$bbox->destroy;
	}
$mw->resize ( 300, 200 );
$progress->set_text ( "0.0% - $MB mb Cd" );
$progress->set_fraction (0);
splice ( @mkiso, 0, 10 );
}

# called by music button
sub music_funct {

if ( exists $music[0] ) {
	&destroy_music;
	}
if ( !exists $music[0] ) {
	&music;
	}
}

# music burn
sub music_burn {

$speed_entry_child = $speed_entry->get_child;
$speed = $speed_entry_child->get_text;
$speed =~ s/X//g;

&get_disc;

print "@music_files\n";

system ( "cdrecord -v $eject $dummy speed=$speed dev=$dev -audio $mode $pad $nofix $overburn @music_files\n" );
unlink ( @music_files );

}

# This is the music burning sub
sub music {

if ( exists $mkiso[0] ) {
	&destroy_mkiso;
	}
if ( exists $rip[0] ) {
	&destroy_rip;
	}
$mw->set_title ( "HacBurn 0.3.5 - Music Project" );

$set_data_burn = 0;
$set_music_burn = 1;

# set -pad by default
$pad = "-pad";

# make image_entry/image_label insensitive
$image_entry->set_sensitive ( 0 );
$image_label->set_sensitive ( 0 );

# data window + list
$music_window = new Gtk2::ScrolledWindow(undef,undef);			# scroll window
$music_list = Gtk2::SimpleList->new ( 'Filename' => 'text',
					'Size (Kb)' => 'int');		# file list
$music_window->add_with_viewport( $music_list );			# add to scroll window

# buttons
$music_add = Gtk2::Button->new ( "Add" );
$remove_music = Gtk2::Button->new ( "Remove" );
$convert_music = Gtk2::Button->new ( "Make .wav" );
$cancel_music = Gtk2::Button->new ( "Cancel" );

# callbacks
$music_add->signal_connect ( clicked => sub { add_music () } );
$remove_music->signal_connect ( clicked => sub { remove_music () } );
$convert_music->signal_connect ( clicked => sub { convert_music () } );
$cancel_music->signal_connect ( clicked => sub { destroy_music () } );

# packboxes
$cbox = new Gtk2::HBox ( 1, 0 );
$cbox->pack_start ( $music_add, 0, 1, 0 );
$cbox->pack_start ( $remove_music, 0, 1, 0 );
$cbox->pack_start ( $convert_music, 0, 1, 0 );
$cbox->pack_start ( $cancel_music, 0, 1, 0 );

$dbox = new Gtk2::VBox(0, 0);
$dbox->pack_start ( $music_window, 0, 0, 0 );
$dbox->pack_start ( $cbox, 0, 0, 0 );

$dbox->show_all;
$main_box->pack_start ( $dbox, 0, 1, 0 );
@music = ($music_window,				# add all widgets to one array
	$music_list,
	$music_add,
	$remove_music,
	$convert_music,
	$cancel_music,
	$cbox,
	$dbox);
}

# add file to music list
sub add_music {

$music_add_window = Gtk2::FileChooserDialog->new(
	"Add File",
	$mw,
	"open",
	"gtk-cancel"=>"cancel",
	"gtk-ok"=>"ok");

$music_filter = Gtk2::FileFilter->new;
$music_filter->add_mime_type ( 'audio/x-mp3' );
$music_filter->add_pattern ( "*.mp3" );
$music_filter->set_name ( ".mp3" );
$music_add_window->add_filter ( $music_filter );

$music_filter2 = Gtk2::FileFilter->new;
$music_filter2->add_mime_type ( 'application/ogg' );
$music_filter2->add_pattern ( "*.ogg" );
$music_filter2->set_name ( ".ogg" );
$music_add_window->add_filter ( $music_filter2 );

$music_filter3 = Gtk2::FileFilter->new;
$music_filter3->add_mime_type ( 'audio/x-wav' );
$music_filter3->add_pattern ( "*.wav" );
$music_filter3->set_name ( ".wav" );
$music_add_window->add_filter ( $music_filter3 );

$music_add_window->set_select_multiple ( 1 );

if ("ok" eq $music_add_window->run) {
	@music_add_filenames = $music_add_window->get_filenames;

foreach $music_add_filename ( @music_add_filenames ) {
		if ( $music_add_filename =~ /\)/ || $music_add_filename =~ /\(/ ) {
			$music_name_error = Gtk2::MessageDialog->new(
			$mw,
			"destroy-with-parent",
			"warning",
			"ok",
			"This filename contains one or more parantheses, mpg321/ogg123 choke on parantheses. Please rename the file and retry.");
		
			$music_name_error->show_all;
			if ( "ok" eq $music_name_error->run ) {
				$music_name_error->destroy;
				$music_add_window->destroy;
				return;
				}
			}

		@music_file_parts = split(/\//, $music_add_filename);
		$music_file_shortname = "$music_file_parts[@music_file_parts - 1]";
		push @music_files, "$music_add_filename";
	
		$filled_size = $progress->get_fraction;
	#	print "filled_size: $filled_size\n";
	
		$music_add_size = -s $music_add_filename;
		$fraction1 = ( ( $music_add_size * 100) / $mb );
	#	print "fraction1: $fraction1\n";
		$fraction2 = ( ( $fraction1 / 100) + $filled_size );
	#	print "fraction2: $fraction2\n";
	
		$fraction4 = $progress->get_text;
		$fraction4 = substr ( $fraction4, 0, 6 );
		$fraction3 = ( $fraction1 + $fraction4 );
	#	print "fraction3: $fraction3\n";
		$fraction3 = substr ( $fraction3, 0, 6 );
	
		$music_add_size = ( $music_add_size / 1000 );
		
		push @{$music_list->{data}}, [$music_file_shortname, $music_add_size];
	
		$progress->set_text ( "$fraction3 % - $MB mb Cd" );
		$progress->set_fraction ( $fraction2 );
		}
	}

$music_add_window->show_all;
$music_add_window->destroy;
}

# remove file from music list
sub remove_music {

@music_index = $music_list->get_selected_indices;
splice @{ $music_list->{data} }, $music_index[0], 1;
splice @music_files, $music_index[0], 1;

$progress->set_fraction ( 0 );

$fraction4 = $progress->get_text;
$fraction4 = substr ( $fraction4, 0, 6 );
$fraction1 = substr ( $fraction1, 0, 6 );
$fraction3 = ( $fraction4 - $fraction1 );
#print "fraction3: $fraction3\n";
$fraction3 = substr ( $fraction3, 1, 3 );
$progress->set_text ( "$fraction3 % - $MB mb Cd ");

foreach $still_listed ( @music_files ) {
	$filled_size = $progress->get_fraction;
#	print "filled_size: $filled_size\n";
	$music_add_size = -s "$still_listed";
	$fraction1 = ( ( $music_add_size * 100) / $mb );
#	print "fraction1: $fraction1\n";
	$fraction2 = ( ( $fraction1 / 100 ) + $filled_size );
#	print "fraction2: $fraction2\n";
	$progress->set_fraction ( $fraction2 );
	}
}

# converts mp3 files to wav files.
sub convert_music {

foreach $music_file ( @music_files ) {
	# change spaces to "/ "
	$music_file =~ s/\s/\\ /g;

	# skip wav files
	if ( $music_file =~ m/(?<=.)wav/ ) {
		next;
		}

	# duplicate filename
	$music_file_original = $music_file;

	# remove the filename from the full path
	@parts = split( /\//, $music_file );

	# save wav file in local tempdir
	$music_file = "$tempdir/$parts[@parts - 1].wav";

	# convert from mp3 to wav
	if ( $music_file =~ m/(?<=.)mp3/ ) {
		system ( "mpg321 --wav $music_file $music_file_original" );
		}

	# convert from ogg to wav
	if ( $music_file =~ m/(?<=.)ogg/ ) {
		system ( "ogg123 -d wav -f $music_file $music_file_original" );
		}
	}
}

# destroy music widgets
sub destroy_music {

$mw->set_title ( "HacBurn 0.3.5 - Data Project" );
$set_data_burn = 1;
$set_music_burn = 0;
if ( exists $music[7] ) {
	$dbox->destroy;
	}
$mw->resize ( 300, 200 );
splice ( @music, 0, 8 );

# unset -pad
$pad = undef;

# make image_entry/image_label sensitive
$image_entry->set_sensitive ( 1 );
$image_label->set_sensitive ( 1 );
}

# iso select sub
sub iso_select {

$iso_window = Gtk2::FileChooserDialog->new (
	"Select Iso",
	$mw,
	"open",
	"gtk-cancel"=>"cancel",
	"gtk-ok"=>"ok");

$iso_filter = Gtk2::FileFilter->new;
$iso_filter->add_mime_type ( 'application/x-cd-image' );
$iso_filter->add_pattern ( "*.iso" );
$iso_filter->set_name ( ".iso" );
$iso_window->add_filter ( $iso_filter );

$iso_filter2 = Gtk2::FileFilter->new;
$iso_filter2->add_mime_type ( 'text/plain' );
$iso_filter2->add_pattern ( "*.cue" );
$iso_filter2->set_name ( ".cue" );
$iso_window->add_filter ( $iso_filter2 );

if ( "ok" eq $iso_window->run ) {
	$iso_file = $iso_window->get_filename;
	}

$image_entry->set_text ( $iso_file );

$iso_window->show_all;
$iso_window->destroy;
}

# eject cd
sub eject {

&get_dev ( "node" );
if ( defined $dev ) {
	system ( "eject $dev" );	}
else {
	$eject_error = Gtk2::MessageDialog->new(
	$mw,
	"destroy-with-parent",
	"error",
	"ok",
	"Please choose a CD drive.");

	$eject_error->show_all;

	if ( "ok" eq $eject_error->run ) {
		$eject_error->destroy;
		return;
		}
	}
}

# load cd
sub load {
		
&get_dev ( "node" );
if ( defined $dev ) {
	system ( "eject -t $dev" );
	}
else {
	$load_error = Gtk2::MessageDialog->new(
	$mw,
	"destroy-with-parent",
	"error",
	"ok",
	"Please choose a CD drive.");

	$load_error->show_all;

	if ( "ok" eq $load_error->run ) {
		$load_error->destroy;
		return;
		}
	}
}

# unclicks $blank_fast
sub unclick_blank_fast {

if ( $blank_all->get_active ) {
	$blank_fast->set_active ( 0 );
	$erase = "all";
	}
}

# unclicks $blank_all
sub unclick_blank_all {

if ( $blank_fast->get_active ) {
	$blank_all->set_active ( 0 );
	$erase = "fast";
	}
}

# unclicks $size_650_mb
sub unclick_650_mb {

if ( $size_700_mb->get_active ) {
	$size_650_mb->set_active ( 0 );
	$MB = 700;
	$mb = 734003200;
	$progress->set_text ( "$progress_text% - $MB mb Cd" );
	}
}

# unclicks $size_700_mb
sub unclick_700_mb {

if ( $size_650_mb->get_active ) {
	$size_700_mb->set_active ( 0 );
	$MB = 650;
	$mb = 681574400;
	$progress->set_text ( "$progress_text% - $MB mb Cd" );
	}
}

# called by rip button
sub rip_funct {

&get_dev ( "node" );

if ( $dev ne "" ) {
	if ( exists $rip[0] ) {
		&destroy_rip;
		}
	if ( !exists $rip[0] ) {
		&rip_cd;
		}
	}

else {
	$rip_error = Gtk2::MessageDialog->new(
	$mw,
	"destroy-with-parent",
	"error",
	"ok",
	"Please choose a CD drive.");

	$rip_error->show_all;

	if ( "ok" eq $rip_error->run ) {
		$rip_error->destroy;
		return;
		}
	}
}

# This is the music ripping sub
sub rip_cd {

if ( exists $mkiso[0] ) {
	&destroy_mkiso;
	}
if ( exists $music[0] ) {
	&destroy_music;
	}

$mw->set_title ( "HacBurn 0.3.5 - Rip CD" );

# set default values
$server = "freedb.freedb.org";
$port = 8880;
$cddb_mode = "http";
$ping_type = "icmp";
$ping_to = "5";

# rip window + list
$rip_window = new Gtk2::ScrolledWindow(undef,undef);			# scroll window
$rip_list = Gtk2::SimpleList->new ( 	'Track' => 'text',		# track number
					'Artist' => 'text',		# artist
					'Title' => 'text', );		# track title
$rip_list->get_selection->set_mode ('multiple');			# multiple selections
$rip_window->add_with_viewport( $rip_list );				# add to scroll window

&cd_data;

# buttons
$rip_all = Gtk2::Button->new ( "Rip All" );
$rip_sel = Gtk2::Button->new ( "Rip Selected" );
$rip_rescan = Gtk2::Button->new ( "Rescan CD" );
$cancel_rip = Gtk2::Button->new ( "Cancel" );

$rip_cddb_options = Gtk2::Button->new ( "CD database Options" );
$rip_options = Gtk2::Button->new ( "Rip Options" );

# callbacks
$rip_all->signal_connect ( clicked => sub { rip_all () } );
$rip_sel->signal_connect ( clicked => sub { rip_sel () } );
$rip_rescan->signal_connect ( clicked => sub { cd_data () } );
$cancel_rip->signal_connect ( clicked => sub { destroy_rip () } );
$rip_cddb_options->signal_connect ( clicked => sub { rip_cddb_options () } );
$rip_options->signal_connect ( clicked => sub { rip_options () } );

# packboxes
$ebox = new Gtk2::HBox ( 1, 0 );
$ebox->pack_start ( $rip_all, 0, 1, 0 );
$ebox->pack_start ( $rip_sel, 0, 1, 0 );
$ebox->pack_start ( $rip_rescan, 0, 1, 0 );
$ebox->pack_start ( $cancel_rip, 0, 1, 0 );

$gbox = new Gtk2::HBox ( 1, 0 );
$gbox->pack_start ( $rip_cddb_options, 0, 1, 0 );
$gbox->pack_start ( $rip_options, 0, 1, 0 );

$fbox = new Gtk2::VBox(0, 0);
$fbox->pack_start ( $rip_window, 0, 0, 0 );
$fbox->pack_start ( $ebox, 0, 0, 0 );
$fbox->pack_start ( $gbox, 0, 0, 0 );

$fbox->show_all;
$main_box->pack_start ( $fbox, 0, 1, 0 );
@rip = ($rip_window,				# add all widgets to one array
	$rip_list,
	$rip_cd,
	$cancel_rip,
	$ebox,
	$fbox);
}

# destroy rip widgets
sub destroy_rip {

$mw->set_title ( "HacBurn 0.3.5 - Data Project" );
if ( exists $rip[0] ) {
	$fbox->destroy;
	}
$mw->resize ( 300, 200 );
splice @{rip_list->{data}}, 0;
splice ( @rip, 0, 6 );
}

# connect to cd database server
# and retrieve data
sub cd_data {

splice @{$rip_list->{data}}, 0;		# make sure list is empty
splice @eth_ppp, 0;			# make sure we get new ifconfig info
$reachable = undef;
$net_device_run = undef;
&get_disc;
if ( $disc_capacity == 0 ) {
	die ( "No CD in drive $dev" );
	}

if ( $using_db eq "using_db" ) {
	# check if connection exists and get disc data
	@eth_ppp = `ifconfig -a`;
	foreach $if_eth_ppp ( @eth_ppp ) {
		if ( $if_eth_ppp =~ /LOOPBACK/ ) {
			$if_eth_ppp =~ s/RUNNING//;
			print "$if_eth_ppp\n";
			}

		# this means the cable is plugged in (linux)
		if ( $if_eth_ppp =~ /RUNNING/ ) {
			$net_device_run = 1;
			}
		# this means the cable is unplugged (netbsd)
		if ( $if_eth_ppp =~ /no\ carrier/ ) {
			$net_device_run = undef;
			}
		}

	#print "NET_DEVICE_EX: $net_device_ex\n";
	print "NET_DEVICE_RUN: $net_device_run\n";

	if ( defined $net_device_run ) {
		$connection = Net::Ping->new ( $ping_type, $ping_to );
		$reachable = $connection->ping ( $server );
		}

	print "REACHABLE: $reachable\n";
	}
	
# get CD data from server
if ( $reachable == 1 ) {
	my %cddb_config;
	$cddb_config{input}=0;
	$cddb_config{CDDB_HOST}=$server;			# set cddb host
	$cddb_config{CDDB_PORT}=$port;				# set cddb port
	$cddb_config{CDDB_MODE}=$cddb_mode;			# set cddb mode: cddb or http
	$cddb_config{CD_DEVICE}=$dev;				# set cd device
	
	print "Retrieving data from $server on port $port . . .\n";
	%cd=get_cddb(\%cddb_config);
	unless(defined $cd{title}) {
		die "no cddb entry found";
		}
	print "artist: $cd{artist}\n";
	print "title: $cd{title}\n";
	print "category: $cd{cat}\n";
	print "cddbid: $cd{id}\n";
	print "trackno: $cd{tno}\n";
	$list_album = $cd{title};
	chomp $list_album;

	my $n = 1;
	foreach my $track ( @{$cd{track}} ) {
		print "track $n: $track\n";
		$list_no = $n;
		$list_artist = $cd{artist};
		$list_track = $track;
		push @{$rip_list->{data}}, [$list_no, $list_artist, $list_track];
		$n++;
		}
	print "Done\n";
	}

# fill table with default information
else {
	print "No connection established with $server\n";
	# get number of tracks from cd
	$tracks = get_discids($dev);
	$tracks = Data::Dumper->Dump($tracks,["diskid","total","toc"]);
	$tracks =~ /total\s\=\s\'/;
	$tracks = "$'";
	$tracks =~/\'/;
	$tracks = "$`";
	print "$tracks\n";

	my $n = 1;
	foreach my $track ( 1 .. $tracks ) {
		$list_no = $track;
		$list_album = "Unknown Album";
		$list_artist = "Unkown Artist";
		$list_track = "Track$track";
		push @{$rip_list->{data}}, [$list_no, $list_artist, $list_track];
		$n++;
		}
	print "Done\n";
	}
}

# rip all tracks
sub rip_all {

$rip_list->get_selection->select_all;

&rip_sel;
}

# rip selected tracks
sub rip_sel {

&get_disc;

if ( defined $mp3_bitrate ) {
	@rip_index = $rip_list->get_selected_indices;
	foreach $track_no ( @rip_index ) {
		$track_old = $track_no;
		$track_no++;
		unless ( -d "$ENV{HOME}/$list_album" ) {
			mkdir ( "$ENV{HOME}/$list_album" );
			}
		$track_name_list = $rip_list->{data}[$track_old][2];
		$track_file_name = "$ENV{HOME}/$list_album/$list_artist - $track_name_list";
		$track_file_name =~ s/\s/\\ /g;
		print "$track_file_name\n";
		system ( "cdparanoia $Z $Y -d $dev $track_no - | lame -b $mp3_bitrate -m $mp3_mode - $track_file_name.mp3" );
		}
	}

	if ( defined $ogg_bitrate ) {
	@rip_index = $rip_list->get_selected_indices;
	foreach $track_no ( @rip_index ) {
		$track_old = $track_no;
		$track_no++;
		unless ( -d "$ENV{HOME}/$list_album" ) {
			mkdir ( "$ENV{HOME}/$list_album" );
			}
		$track_name_list = $rip_list->{data}[$track_old][2];
		$track_file_name = "$ENV{HOME}/$list_album/$list_artist - $track_name_list";
		$track_file_name =~ s/\s/\\ /g;
		print "$track_file_name\n";
		system ( "cdparanoia $Z $Y -d $dev $track_no - | oggenc -b $ogg_bitrate - -o $track_file_name.ogg" );
		}
	}

	if ( !defined $ogg_bitrate && !defined $mp3_bitrate) {
	@rip_index = $rip_list->get_selected_indices;
	foreach $track_no ( @rip_index ) {
		$track_old = $track_no;
		$track_no++;
		unless ( -d "$ENV{HOME}/$list_album" ) {
			mkdir ( "$ENV{HOME}/$list_album" );
			}
		$track_name_list = $rip_list->{data}[$track_old][2];
		$track_file_name = "$ENV{HOME}/$list_album/$list_artist - $track_name_list";
		$track_file_name =~ s/\s/\\ /g;
		print "$track_file_name\n";
		system ( "cdparanoia $Z $Y -d $dev $track_no $track_file_name.wav" );
		}
	}
}

# cddb connection options
sub rip_cddb_options {

$cddb_options_dialog = Gtk2::Dialog->new_with_buttons(
	"CDDB Options",
	$mw,
	"destroy-with-parent",
	"gtk-help"=>"help",
	"gtk-cancel"=>"cancel",
	"gtk-ok"=>"ok");

# entry boxes
$server_entry = Gtk2::Entry->new;
$port_entry = Gtk2::Entry->new;
$mode_entry = Gtk2::Entry->new;
$ping_type_entry = Gtk2::Entry->new;
$ping_to_entry = Gtk2::Entry->new;

# entry labels
$server_label = Gtk2::Label->new ( "CDDB Server" );
$port_label = Gtk2::Label->new ( "Port" );
$mode_label = Gtk2::Label->new ( "Mode (cddb/http)" );
$ping_type_label = Gtk2::Label->new ( "Ping (icmp/udp/tcp)" );
$ping_to_label = Gtk2::Label->new ( "Ping Timeout (seconds)" );

# default values
$server_entry->set_text ( $server );
$port_entry->set_text ( $port );
$mode_entry->set_text ( $cddb_mode );
$ping_type_entry->set_text ( $ping_type );
$ping_to_entry->set_text ( $ping_to );

# extra packboxes
$server_opt = new Gtk2::HBox ( 1, 0 );
$server_opt->pack_start ( $server_entry, 0, 1, 0 );
$server_opt->pack_start ( $server_label, 0, 1, 0 );
$port_opt = new Gtk2::HBox ( 1, 0 );
$port_opt->pack_start ( $port_entry, 0, 1, 0 );
$port_opt->pack_start ( $port_label, 0, 1, 0 );
$mode_opt = new Gtk2::HBox ( 1, 0 );
$mode_opt->pack_start ( $mode_entry, 0, 1, 0 );
$mode_opt->pack_start ( $mode_label, 0, 1, 0 );
$ping_type_opt = new Gtk2::HBox ( 1, 0 );
$ping_type_opt->pack_start ( $ping_type_entry, 0, 1, 0 );
$ping_type_opt->pack_start ( $ping_type_label, 0, 1, 0 );
$ping_to_opt = new Gtk2::HBox ( 1, 0 );
$ping_to_opt->pack_start ( $ping_to_entry, 0, 1, 0 );
$ping_to_opt->pack_start ( $ping_to_label, 0, 1, 0 );

$cddb_opt_box = new Gtk2::VBox(0, 0);
$cddb_opt_box->pack_start ( $server_opt, 0, 1, 0 );
$cddb_opt_box->pack_start ( $port_opt, 0, 1, 0 );
$cddb_opt_box->pack_start ( $mode_opt, 0, 1, 0 );
$cddb_opt_box->pack_start ( $ping_type_opt, 0, 1, 0 );
$cddb_opt_box->pack_start ( $ping_to_opt, 0, 1, 0 );

$cddb_options_dialog->vbox->add ( $cddb_opt_box );
$cddb_options_dialog->show_all;

if ( "ok" eq $cddb_options_dialog->run ) {
	$server = $server_entry->get_text;
	$port = $port_entry->get_text;
	$mode = $mode_entry->get_text;
	$ping_type = $ping_type_entry->get_text;
	$ping_to = $ping_to_entry->get_text;
	$cddb_options_dialog->destroy;
	&cd_data;
	}

if ( "cancel" ) {
	$cddb_options_dialog->destroy;
	return;
	}
}

# ripping options
sub rip_options {

$rip_options_dialog = Gtk2::Dialog->new_with_buttons(
	"Encoding Options",
	$mw,
	"destroy-with-parent",
	"gtk-help"=>"help",
	"gtk-cancel"=>"cancel",
	"gtk-ok"=>"ok");

# chkbuttons
$mp3_encode = Gtk2::CheckButton->new_with_label ( "Use mp3 encoding by LAME" );
$ogg_encode = Gtk2::CheckButton->new_with_label ( "Use ogg encoding" );
$cdparanoia_paranoia = Gtk2::CheckButton->new_with_label ( "Disable paranoia" );
$cdparanoia_ex_paranoia = Gtk2::CheckButton->new_with_label ( "Disable extra paranoia" );

if ( defined $mp3_bitrate ) {
	$mp3_encode->set_active ( 1 );
	}
if ( defined $ogg_bitrate ) {
	$ogg_encode->set_active ( 1 );
	}
if ( defined $Z ) {
	$cdparanoia_paranoia->set_active ( 1 );
	}
if ( defined $Y ) {
	$cdparanoia_ex_paranoia->set_active ( 1 );
	}

# scale widgets
$mp3_bit_scale = Gtk2::HScale->new_with_range ( 8, 320, 8 );
$mp3_bit_scale_label = Gtk2::Label->new ( "Kbits per second:" );
$mp3_bit_scale->set_value ( $mp3_bitrate );

$ogg_bit_scale = Gtk2::HScale->new_with_range ( 8, 320, 8 );
$ogg_bit_scale_label = Gtk2::Label->new ( "Kbits per second:" );
$ogg_bit_scale->set_value ( $ogg_bitrate );


# combobox entries
$mp3_mode_entry = Gtk2::ComboBoxEntry->new_text;
$mp3_mode_label = Gtk2::Label->new ( "Encoding Mode" );
$mp3_mode_entry->insert_text ( 0, "stereo" );
$mp3_mode_entry->insert_text ( 1, "joint stereo" );
$mp3_mode_entry->insert_text ( 2, "dual channel" );
$mp3_mode_entry->insert_text ( 3, "mono" );

if ( defined $mp3_mode_active ) {
	$mp3_mode_entry->set_active ( $mp3_mode_active );
	}

$presets_entry = Gtk2::ComboBoxEntry->new_text;
#$presets_label = Gtk2::Label->new ( "Preset" );
$presets_entry->insert_text ( 0, "standard" );
$presets_entry->insert_text ( 1, "extreme" );
$presets_entry->insert_text ( 2, "insane" );

# packboxes

# mp3 box
$mp3_mode_box = new Gtk2::HBox(1, 0);
$mp3_mode_box->pack_start ( $mp3_mode_entry, 0, 1, 0 );
$mp3_mode_box->pack_start ( $mp3_mode_label, 0, 1, 0 );

#$presets_box = new Gtk2::HBox(1, 0);
#$presets_box->pack_start ( $presets_entry, 0, 1, 0 );
#$presets_box->pack_start ( $presets_label, 0, 1, 0 );


$mp3_frame_box = new Gtk2::VBox(0, 0);
$mp3_frame_box->pack_start ( $mp3_encode, 0, 1, 0 );
$mp3_frame_box->pack_start ( $mp3_bit_scale_label, 0, 1, 0 );
$mp3_frame_box->pack_start ( $mp3_bit_scale, 0, 1, 0 );
$mp3_frame_box->pack_start ( $mp3_mode_box, 0, 1, 0 );
#$mp3_frame_box->pack_start ( $presets_box, 0, 1, 0 );

# mp3 box

# ogg box
$ogg_frame_box = new Gtk2::VBox(0, 0);
$ogg_frame_box->pack_start ( $ogg_encode, 0, 1, 0 );
$ogg_frame_box->pack_start ( $ogg_bit_scale_label, 0, 1, 0 );
$ogg_frame_box->pack_start ( $ogg_bit_scale, 0, 1, 0 );
# ogg box


# cdparanoia box
$cdparanoia_box1 = new Gtk2::HBox(1, 0);
$cdparanoia_box1->pack_start ( $cdparanoia_paranoia, 0, 1, 0 );
$cdparanoia_box1->pack_start ( $cdparanoia_ex_paranoia, 0, 1, 0 );

$cdparanoia_frame_box = new Gtk2::VBox(0, 0);
$cdparanoia_frame_box->pack_start ( $cdparanoia_box1, 0, 1, 0 );

$cdp_frame = Gtk2::Frame->new ( "Disable cdparanoia options" );
$cdp_frame->add ( $cdparanoia_frame_box );
# cdparanoia box


# notebook widget
$rip_notebook = Gtk2::Notebook->new();
$rip_notebook->append_page( $mp3_frame_box, "Mp3" );  
$rip_notebook->append_page( $ogg_frame_box, "Ogg" );  
$rip_notebook->append_page( $cdp_frame, "CDParanoia" );  

# callbacks
$mp3_encode->signal_connect ( clicked => sub { mp3_encode () } );
$ogg_encode->signal_connect ( clicked => sub { ogg_encode () } );

# extra packboxes
$rip_options_dialog->vbox->add ( $rip_notebook );
$rip_options_dialog->show_all;


if ( "ok" eq $rip_options_dialog->run ) {
	if ( $mp3_encode->get_active ) {
		$mp3_bitrate = $mp3_bit_scale->get_value;
		$mp3_mode_entry_child = $mp3_mode_entry->get_child;
		$mp3_mode = $mp3_mode_entry_child->get_text;
		$mp3_mode = substr $mp3_mode, 0, 1;
		$mp3_mode_active = $mp3_mode_entry->get_active;
		print "Rip in mp3\n";
#		$presets_entry_child = $presets_entry->get_child;
#		$presets = $presets_entry_child->get_text;
		}

	if ( $ogg_encode->get_active ) {
		$ogg_bitrate = $ogg_bit_scale->get_value;
		print "Rip in ogg\n";
		}

	if ( !$mp3_encode->get_active && !$ogg_encode->get_active) {
		print "Rip in wav, do not encode to mp3 or ogg\n";
		}

	if ( $cdparanoia_paranoia->get_active) {
		$Z = "-Z";
		}
	else {
		$Z = undef;
		}
	if ( $cdparanoia_ex_paranoia->get_active) {
		$Y = "-Y";
		}
	else {
		$Y = undef;
		}
	$rip_options_dialog->destroy;
	print "$Z $Y\n";
	}



if ( "cancel" ) {
	$rip_options_dialog->destroy;
	return;
	}


	# extra subs
	sub mp3_encode {

	if ( $mp3_encode->get_active ) {
		$ogg_bitrate = undef;
		$ogg_encode->set_active ( 0 );
		}
	}

	sub ogg_encode {

	if ( $ogg_encode->get_active ) {
		$mp3_bitrate = undef;
		$mp3_encode->set_active ( 0 );
		}
	}
}










