#!/usr/bin/perl
#------------------------------------------------------------------------------
# aria2::gui
# A graphical user interface for aria2
#
# Copyright (C) 2007 Rudolf Martin
#
# 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 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.
#
#
# Homepage:
www.martin-achern.de/wgetgui/
# Email:
[email protected]
#
#------------------------------------------------------------------------------
use Tk;
use strict;
use warnings;
use Tk:
rogressBar;
use IO::Handle;
my $version="0.3beta";
my $proxy_url;
my $proxy_port;
my $proxy_user;
my $proxy_passw;
my @options;
my $outline;
my @message;
my $mode = 0;
my $linux;
if ( $^O =~ /linux/) {
$linux=1; # 1=Linux
} else {
$linux=0; # 0=Windoze
}
my $ent_output;
my $pid;
my $child;
my $percent_done;
##------------------------------------------------------------------------------
#--- GUI creation
my $mw = new MainWindow;
$mw->title("Aria2::GUI ".$version);
#------------------------------------------------------------------------------
# frame mode
#
my $frame_mode = $mw->Frame(-relief=>"groove",
-borderwidth => "2")
->pack(-side=>'top',
-fill=>'x',
);
my $frame_mode_url = $frame_mode->Frame()
->pack(-fill=>'x');
$frame_mode_url->Radiobutton(-text=>"URL",
-width=>10,
-variable=>\$mode,
-anchor=>'w',
-value=>"0")
->pack(-side=>"left");
my $ent_url = $frame_mode_url->Entry(-width=>50,)
->pack(-side => 'left',
-fill=>'x',
-expand=>'1',
);
$frame_mode_url->Button(-text => "Clear",
-command => sub { $ent_url->delete('0', 'end') }
)
->pack(-side => 'left');
my $frame_mode_tor = $frame_mode->Frame()
->pack(-fill=>'x');
$frame_mode_tor->Radiobutton(-text=>"Torrent -T",
-width=>10,
-variable=>\$mode,
-anchor=>'w',
-value=>"1")
->pack(-side=>"left");
my $ent_tor = $frame_mode_tor->Entry()
->pack(-side => 'left',
-fill=>'x',
-expand=>'1',
);
$frame_mode_tor->Button(-text => "Clear",
-command => sub { $ent_tor->delete('0', 'end') }
)
->pack(-side => 'left');
my $frame_mode_meta = $frame_mode->Frame()
->pack(-fill=>'x');
$frame_mode_meta->Radiobutton(-text=>"Metalink -M",
-width=>10,
-variable=>\$mode,
-anchor=>'w',
-value=>"2")
->pack(-side=>"left");
my $ent_meta = $frame_mode_meta->Entry()
->pack(-side => 'left',
-fill=>'x',
-expand=>'1',
);
$frame_mode_meta->Button(-text => "Clear",
-command => sub { $ent_meta->delete('0', 'end') }
)
->pack(-side => 'left');
##------------------------------------------------------------------------------
# frame in the middle
my $frame_middle = $mw->Frame()
->pack(-side=>'top',
-fill=>'both',
-expand=>'1',
);
##------------------------------------------------------------------------------
# Frame middle left
#
my $frame_left = $frame_middle->Frame(-relief=>"groove",
-borderwidth => "2")
->pack(-fill=>'both',
-expand=>"1",
-side=>"left",
);
my $frame_tries = $frame_left->Frame
->pack(
-fill=>'x');
my $ch_tries = $frame_tries->Checkbutton(-text => "Tries -m:",
-anchor=>'w')
->pack(
-side=>'left',
-fill=>'x');
my $ent_tries = $frame_tries->Entry(-width=>'2')
->pack(-side=>"left",
-fill=>'x',
);
$ent_tries->insert (0,5);
my $frame_split = $frame_left->Frame
->pack(
-fill=>'x');
my $ch_split = $frame_split->Checkbutton(-text => "Split -s:",
-anchor=>'w')
->pack(
-side=>'left',
-fill=>'x');
my $ent_split = $frame_split->Entry(-width=>'2')
->pack(-side=>"left",
-fill=>'x',
);
$ent_split->insert (0,1);
my $ch_overwrite = $frame_left->Checkbutton(-text => "Allow-overwrite",
-anchor=>'w')
->pack(
-fill=>'x');
my $ch_proxy;
$ch_proxy = $frame_left->Checkbutton(-text => "Use Proxy",
-command => sub {
if ($ch_proxy->{'Value'}) { config_proxy() }
},
-anchor=>'w')
->pack(
-fill=>'x');
my $frame_user = $frame_left->Frame
->pack(-fill=>'x');
$frame_user->Label( -text=>"HTTP-User:" )
->pack(-side=>"left");
my $ent_user = $frame_user->Entry(-width=>'5')
->pack(-side=>"left",
-fill=>'x',
-expand=>'1');
my $frame_passw = $frame_left->Frame
->pack(-fill=>'x');
$frame_passw->Label( -text=>"HTTP-Password:" )
->pack(-side=>"left");
my $ent_passw = $frame_passw->Entry(-width=>'10',
-show=>'*')
->pack(-side=>"left",
-fill=>'x',
-expand=>'1',
);
##------------------------------------------------------------------------------
# Frame middle right
#
my $ch_logfile;
my $ent_logfile;
my $frame_right= $frame_middle->Frame(-relief=>"groove",
-borderwidth => "2")
->pack(-fill=>'both',
-expand=>"1",
-side=>"left",
);
my $frame_logfile = $frame_right->Frame
->pack(-fill=>'x',
);
$ch_logfile = $frame_logfile->Checkbutton(-text => "Logfile -l:",
-command => sub {
if ($ch_logfile->{'Value'}) {
$ent_logfile->configure('-state'=>'normal');
} else {
$ent_logfile->configure('-state'=>'disabled')
}
},
-anchor=>'w')
->pack(-fill=>'x',
-side=>"left",
);
$ent_logfile = $frame_logfile->Entry(-width=>'5')
->pack(-side=>"left",
-fill=>'x',
-expand=>'1',
);
$ent_logfile->insert('end',"default.log");
$ent_logfile->configure('-state'=>'disabled');
my $frame_dir = $frame_right->Frame
->pack(-fill=>'x',
);
my $ent_custdir;
my $ch_custdir;
$ch_custdir = $frame_dir->Checkbutton(-text => "Directory -d:",
-command => sub {
if ($ch_custdir->{'Value'}) {$ent_custdir->configure(-state=>'normal')}
else {$ent_custdir->configure(-state=>'disabled')};
},
-anchor=>'w')
->pack(-fill=>'x',
-side=>"left",
);
$ent_custdir = $frame_dir->Entry(
# -state=>'disabled'
)
->pack(
-fill=>'x',
-side=>"left",
-expand=>'1',
);
$ent_custdir->insert('end',"download");
$ent_custdir->configure('-state'=>'disabled');
my $ent_outfile;
my $ch_outfile;
my $frame_outfile = $frame_right->Frame
->pack(-fill=>'x',
);
$ch_outfile = $frame_outfile->Checkbutton(-text => "Output file -o:",
-command => sub {
if ($ch_outfile->{'Value'}) {$ent_outfile->configure(-state=>'normal')}
else {$ent_outfile->configure(-state=>'disabled')};
},
-anchor=>'w')
->pack(-fill=>'x',
-side=>"left",
);
$ent_outfile = $frame_outfile->Entry(
)
->pack(
-side=>'left',
-fill=>'x',
-expand=>'1',
);
$ent_outfile->insert('end',"outfile");
$ent_outfile->configure('-state'=>'disabled');
my $ch_refer;
my $ent_refer;
my $frame_refer = $frame_right->Frame
->pack(-fill=>'x',
);
$ch_refer = $frame_refer->Checkbutton(-text => "Referer :",
-command => sub {
if ($ch_refer->{'Value'}) {$ent_refer->configure(-state=>'normal')}
else {$ent_refer->configure(-state=>'disabled')};
},
-anchor=>'w')
->pack(-fill=>'x',
-side=>"left",
);
$ent_refer = $frame_refer->Entry()
->pack(
-side=>'left',
-expand=>'1',
-fill=>'x');
$ent_refer->configure('-state'=>'disabled');
my $ch_addpar;
my $ent_addpar;
my $frame_addpar = $frame_right->Frame
->pack(-fill=>'x',
);
$ch_addpar = $frame_addpar->Checkbutton(-text => "Additional Param. :",
-command => sub {
if ($ch_addpar->{'Value'}) {$ent_addpar->configure(-state=>'normal')}
else {$ent_addpar->configure(-state=>'disabled')};
},
-anchor=>'w')
->pack(-fill=>'x',
-side=>"left",
);
$ent_addpar = $frame_addpar->Entry()
->pack(
-side=>'left',
-expand=>'1',
-fill=>'x');
$ent_addpar->configure('-state'=>'disabled');
#------------------------------------------------------------------------------
# Frame progress
#
#my $frame_progress = $mw->Frame(-relief=>"groove",
# -borderwidth => "2")
#
# ->pack(-side => 'top',
# -fill=>'x',
# -expand=>'1');
#
#
# $frame_progress->Label( -text=>"output from aria2c:" )
# ->pack(-side=>"left");
# $ent_output = $frame_progress->Entry(-width=>"10",
# -textvariable=>\$outline,
# )
# ->pack(-side=>"left",
# -fill=>'x',
# -expand=>'1'
# );
#
#------------------------------------------------------------------------------
# Frame action buttons bottom
#
my $frame_action = $mw->Frame(-relief=>"groove",
-borderwidth => "2")
->pack(-side => 'top',
-fill=>'x',
-expand=>'1');
my @buttons = (
['START aria2c' => sub { &start_aria2();
&show_message();
}],
['QUIT' => sub { exit }],
['SAVE Sett.' => sub { &save_settings() }],
['LOAD Sett.' => sub { &load_settings() }],
['About' => sub { &about() }],
);
foreach my $button (@buttons) {
my $b = $frame_action->Button(
-text => $button->[0],
-command => $button->[1],
# -width => 10,
);
$b->pack(-side => 'left',
-fill=>'x',
-expand=>'1');
}
MainLoop;
#------------------------------------------------------------------------------
# Start aria2
#------------------------------------------------------------------------------
sub start_aria2 {
@message=();
&check_options();
if ($linux) {
# system ("aria2c", @options);
&download_lin();
} else {
system ("aria2c", @options);
#&download_win();
};
print "\nAria2::GUI execution finished with command:\n";
print "aria2c @options\n";
print "End of command.\n";
}
#------------------------------------------------------------------------------
# download Linux
#------------------------------------------------------------------------------
sub download_lin {
#
# upload the images
# uses pipe --> elegant and safe --> linuxlike
local $/ = "\r";
if ($pid = open $child, "-|") {
# parent
#
my $top_working = $mw->Toplevel(
-title=>'aria2::gui',
);
$top_working->geometry("+".int($mw->x+50).
"+".int($mw->y+50));
$top_working->Label(-text => "\nAria2c is working\nPlease wait.\n($pid)\n")
->pack;
my $progressbar = $top_working->ProgressBar(
-width => 20, # height for horizontal
-length => 180, # width for horizonzal
-anchor => 'w', # horizontal
-from => 0,
-to => 100,
-blocks => 1,
-colors => [0, 'green', 50, 'yellow' , 80, 'red'],
-variable => \$percent_done
)
->pack(
-fill=>'x');
$top_working->Button(
-text => "Cancel download",
-command => sub {
print STDOUT "Canceled by user\n";
kill 9 => $pid if defined $pid;
# $top_working->destroy;
}
)
->pack();
$mw->update;
#
#
while ( <$child> ) {
print "$_\n";
# cut percentage from output
m/ (\d+)%/;
$percent_done=$1;
$progressbar->value($percent_done);
$mw->update();
}
close $child;
$top_working->destroy;
} else {
# child
die "connot fork: $!" unless defined $pid;
# STDOUT->autoflush(1);
print STDOUT "Child Pid $$ has started\n";
exec ("aria2c", @options);
CORE::exit;
}
}
#------------------------------------------------------------------------------
# download Windoze
#------------------------------------------------------------------------------
sub download_win {
#
# upload the images
#print "sleep\n";
#sleep(2); #test
my @output = `aria2c @options`; # uses the shell --> unsafe
foreach (@output) {
print;
#$outline=$_;
#$ent_outline->update(); # progress?
# $progressbar->value($percent_done);
# $progressbar->update();
# collect output into array, one line per element, no errors!
push (@message, $_);
}
}
#------------------------------------------------------------------------------
# Check options
#------------------------------------------------------------------------------
sub check_options {
# we have to collect all options
# we do it the same manner as the wget-documentation
# and put the data in one array
my $entry;
@options = (); # empty array
# Logging
#
if ($ch_logfile ->{'Value'}) {
$entry = $ent_logfile->get;
push (@options, "-l$entry");
}
if ($ch_outfile->{'Value'}) {
$entry = $ent_outfile->get;
push (@options, "-o$entry") ;
}
if ($ch_tries->{'Value'}) {
$entry = $ent_tries->get;
push (@options, "-m$entry");
}
if ($ch_split->{'Value'}) {
$entry = $ent_split->get;
push (@options, "-s$entry");
}
if ($ch_overwrite->{'Value'}) {
push (@options, "--allow-overwrite=true");
}
$entry = $ent_user->get;
if ($entry) {push(@options, "--http-user=$entry")};
$entry = $ent_passw->get;
if ($entry) {push(@options, "--http-password=$entry")};
if ($ch_custdir->{'Value'}) {
$entry = $ent_custdir->get;
push (@options, "-d$entry") ;
}
if ($ch_refer->{'Value'}) {
$entry = $ent_refer->get;
push (@options, "--referer=$entry") ;
}
if ($ch_proxy->{'Value'}) {
if ($proxy_user) {push(@options, "--http-proxy-user=$proxy_user")};
if ($proxy_passw) {push(@options, "--http-proxy-password=$proxy_passw")};
push(@options, "--http-proxy=$proxy_url:$proxy_port");
push(@options, "--http-proxy-method=get");
}
if ($ch_addpar->{'Value'}) {
$entry = $ent_addpar->get;
if ($entry) {push(@options, "$entry")};
}
if($mode==0){
$entry = $ent_url->get;
my @url = split / /, $entry ;
push(@options, "@url");
} elsif ($mode==1){
$entry = $ent_tor->get;
push(@options, "-T$entry");
} elsif ($mode==2){
$entry = $ent_meta->get;
push(@options, "-M$entry")
};
}
#------------------------------------------------------------------------------
# showmessage
#------------------------------------------------------------------------------
sub show_message {
# open new window
my $response = $mw->messageBox(-icon => 'info',
-message => 'Download has finished!',
-title => 'aria2::gui',
-type => 'Ok',
-default => 'Ok');
}
#------------------------------------------------------------------------------
# showmessage
#------------------------------------------------------------------------------
sub show_message2 {
# open new window
my $top_message = $mw->Toplevel(
-title=>'End of download',
);
$top_message->Label(-text => "Aria2c has finished with following output:")
->pack;
my $text_output = $top_message->Scrolled('Text', -scrollbars => 'oe',
-width=>'60',
-height=>'30',
-wrap=>'char',
)
->pack();
$text_output->insert("end", "@message\n");
$top_message->Button(
-text => "OK",
-command => sub { $top_message->destroy }
)
->pack();
}
#------------------------------------------------------------------------------
# Save Settingfile
#------------------------------------------------------------------------------
sub save_settings {
my $filename = $mw->getSaveFile(
-filetypes =>[
['ariaguirc', ['*rc', '.rc']],
['Text Files', ['.txt', '.text']],
],
-initialdir => ".",
-initialfile => "ariaguirc",
-title => "Save settings",
);
if ($filename) {
open SETTING, ">$filename"
or warn "Can not open ariaguirc!";
&check_options();
foreach (@options) {
print SETTING "$_\n";
}
close SETTING;
}
}
#------------------------------------------------------------------------------
# Load Settingfile
#------------------------------------------------------------------------------
sub load_settings {
my $filename = $mw->getOpenFile(
-filetypes =>[
['ariaguirc', ['*rc', '.rc']],
['Text Files', ['.txt', '.text']],
],
-initialdir => ".",
-initialfile => "ariaguirc",
-title => "Load settings",
);
if ($filename) {
open SETTING, "<$filename"
or warn "Can not open ariaguirc!";
# reset all settings
{
$ch_logfile->deselect;
$ent_logfile->configure(-state=>'normal');
$ent_logfile->delete(0,'end');
$ent_logfile->insert('end',"default.log");
$ch_outfile->deselect;
$ent_outfile->configure(-state=>'normal');
$ent_outfile->delete(0,'end');
$ent_outfile->insert('end',"outfile");
$ch_tries->deselect;
$ent_tries->delete(0,'end');
$ch_split->deselect;
$ent_split->delete(0,'end');
$ch_overwrite->deselect;
$ent_user->delete(0,'end');
$ent_passw->delete(0,'end');
$ch_addpar->deselect;
$ent_addpar->delete(0,'end');
$ch_custdir->deselect;
$ent_custdir->configure(-state=>'normal');
$ent_custdir->delete(0,'end');
$ent_custdir->insert('end',"download");
#
$ch_refer->deselect;
$ent_refer->configure(-state=>'normal');
$ent_refer->delete(0,'end');
#
$ch_proxy->deselect;
$proxy_url="";
$proxy_port="";
$proxy_user="";
$proxy_passw="";
#
$mode=0;
$ent_url->delete(0,'end');
$ent_tor->delete(0,'end');
$ent_meta->delete(0,'end');
}
while (<SETTING>) {
chomp;
SWITCH:{
# logging
/^-l(.*)$/ && do {
$ch_logfile->select;
$ent_logfile->delete(0,'end');
$ent_logfile->insert('end',$1);
last SWITCH;
};
/^-o(.*)$/ && do {
$ch_outfile->select;
$ent_outfile->delete(0,'end');
$ent_outfile->insert('end',$1);
last SWITCH;
};
# download
/^-m(\d+)$/ && do {
$ch_tries->select;
$ent_tries->insert('end',$1);
last SWITCH;
};
/^-s(\d+)$/ && do {
$ch_split->select;
$ent_split->insert('end',$1);
last SWITCH;
};
/^--allow-overwrite=true$/ && do {
$ch_overwrite->select;
last SWITCH;
};
/^--http-user=(.*)$/ && do {
$ent_user->insert('end',$1);
last SWITCH;
};
/^--http-password=(.*)$/ && do {
$ent_passw->insert('end',$1);
last SWITCH;
};
# directory
/^-d(.*)$/ && do {
$ch_custdir->select;
$ent_custdir->delete(0,'end');
$ent_custdir->insert('end',$1);
last SWITCH;
};
# referer
/^--referer=(.*)$/ && do {
$ch_refer->select;
$ent_refer->delete(0,'end');
$ent_refer->insert('end',$1);
last SWITCH;
};
# http
/^--http-proxy-user=(.*)$/ && do {
$proxy_user=$1;
last SWITCH;
};
/^--http-proxy-password=(.*)$/ && do {
$proxy_passw=$1;
last SWITCH;
};
/^--http-proxy=(.*)
.*)$/ && do {
$proxy_url=$1;
$proxy_port=$2;
$ch_proxy->select;
last SWITCH;
};
#mode
/^-T(.*)$/ && do {
$mode=1;
$ent_tor->delete(0,'end');
$ent_tor->insert('end',$1);
last SWITCH;
};
/^-M(.*)$/ && do {
$mode=2;
$ent_meta->delete(0,'end');
$ent_meta->insert('end',$1);
last SWITCH;
};
# URL
/^(http.*)$/ && do {
$mode=0;
$ent_url->delete(0,'end');
$ent_url->insert('end',$1);
last SWITCH;
};
#
}
}
close SETTING;
}
}
#------------------------------------------------------------------------------
# Configure Proxy
#------------------------------------------------------------------------------
sub config_proxy {
# open new window
my $top_proxy = $mw->Toplevel(
-title=>'Configure Proxy',
);
$top_proxy->geometry("+".int($mw->x+50).
"+".int($mw->y+50));
my $frame_puser = $top_proxy->Frame()
->pack(-fill=>'x');
$frame_puser->Label( -text=>"Proxy User:" )
->pack(-side=>"left");
my $ent_puser = $frame_puser->Entry(-width=>"5",
-textvariable=>\$proxy_user,
)
->pack(-side=>"left",
-fill=>'x',
-expand=>'1'
);
my $frame_ppassw = $top_proxy->Frame
->pack(-fill=>'x');
$frame_ppassw->Label( -text=>"Proxy Password:" )
->pack(-side=>"left");
my $ent_ppassw = $frame_ppassw->Entry(-width=>"12",
-textvariable=>\$proxy_passw,
)
->pack(-side=>"left",
-fill=>'x',
-expand=>'1'
);
$top_proxy->Label( -text=>"Proxy URL:",
-anchor=>'w')
->pack(-fill=>'x');
my $ent_purl = $top_proxy->Entry(
-textvariable=>\$proxy_url,
)
->pack(-fill=>'x');
my $frame_pport = $top_proxy->Frame
->pack(-fill=>'x');
$frame_pport->Label( -text=>"Proxy Port:" )
->pack(-side=>"left");
my $ent_pport = $frame_pport->Entry(-width=>"12",
-textvariable=>\$proxy_port,
)
->pack(-side=>"left",
-fill=>'x',
-expand=>'1'
);
my $frame_butt = $top_proxy->Frame
->pack(
-fill=>'x',
-expand=>'1',
);
$frame_butt->Button(
-text => "OK",
-command => sub { $top_proxy->destroy }
)
->pack(-side => 'left',
-fill=>'x',
-expand=>'1',
);
$frame_butt->Button(
-text => "Clear",
-command => sub {
$proxy_user="";
$proxy_passw="";
$proxy_url="";
$proxy_port="";
}
)
->pack(-side => 'left',
-fill=>'x',
-expand=>'1',
);
}
#------------------------------------------------------------------------------
# About
#------------------------------------------------------------------------------
sub about {
# open new window
my $text = << ' END_OFF_TEXT';
aria2::gui
A graphical user interface for aria2
Copyright (C) 2007 Rudolf Martin
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.
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.
Homepage:
www.martin-achern.de/wgetgui/
Email:
[email protected]
END_OFF_TEXT
my $top_about = $mw->Toplevel(
-title=>'About aria2::gui',
);
my $text_about = $top_about->Text(
-width=>60,
)
->pack();
$text_about->insert("end", $text);
$text_about->configure(-state=>'disabled');
$top_about->Button(
-text => "OK",
-command => sub { $top_about->destroy }
)
->pack();
}
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# bug: read proxy-setting
# new: proxy-method=get
# new: --allow-overwrite=true
#