|
|
|
#!/usr/local/bin/perl
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
use utf8;
|
|
|
|
use open qw/:std :encoding(utf8)/;
|
|
|
|
binmode(STDOUT, ":utf8");
|
|
|
|
|
|
|
|
use Gtk3 '-init';
|
|
|
|
use Glib 'TRUE', 'FALSE';
|
|
|
|
|
|
|
|
my %window_params = (
|
|
|
|
title => [ 'yt-dlp GUI' ], icon_name => [ 'youtube' ],
|
|
|
|
position => [ 'center' ], border_width => [ 20 ],
|
|
|
|
resizable => [ FALSE ], default_size => [ 480, 240 ],
|
|
|
|
);
|
|
|
|
my @labels = (
|
|
|
|
{ e => undef, label => 'Video URL:', control => 'url' },
|
|
|
|
{ e => undef, label => 'Title:', control => 'title' },
|
|
|
|
{ e => undef, label => 'Resolution:', control => 'resolution' },
|
|
|
|
{ e => undef, label => 'Scale:', control => 'scale' },
|
|
|
|
);
|
|
|
|
my %grids = (
|
|
|
|
buttons => { e => undef, properties => { column_spacing => 8,
|
|
|
|
row_spacing => 8, halign => 'end', valign => 'end' } },
|
|
|
|
checkboxes => { e => undef, properties => { column_spacing => 8,
|
|
|
|
row_spacing => 8, hexpand => TRUE } },
|
|
|
|
main => { e => undef, properties => { column_spacing => 8,
|
|
|
|
row_spacing => 8, hexpand => TRUE } }
|
|
|
|
);
|
|
|
|
my %controls = (
|
|
|
|
url => { e => undef, type => 'Entry', width => 2,
|
|
|
|
properties => { halign => 'fill', hexpand => TRUE } },
|
|
|
|
title => { e => undef, type => 'Entry', width => 3,
|
|
|
|
properties => { halign => 'fill', hexpand => TRUE } },
|
|
|
|
resolution => { e => undef, type => 'ComboBoxText', width => 1,
|
|
|
|
properties => { halign => 'start', hexpand => FALSE } },
|
|
|
|
scale => { e => undef, type => 'ComboBoxText', width => 1,
|
|
|
|
properties => { halign => 'start', hexpand => FALSE } },
|
|
|
|
);
|
|
|
|
my %checkboxes = (
|
|
|
|
ontop => { e => undef, o => 1, label => 'On-Top',
|
|
|
|
opt => ' --ontop' },
|
|
|
|
border => { e => undef, o => 2, label => 'Without borders',
|
|
|
|
opt => ' --no-border' },
|
|
|
|
alldesk => { e => undef, o => 3, label => 'On all workspaces',
|
|
|
|
opt => ' --on-all-workspaces' },
|
|
|
|
);
|
|
|
|
my $chk_rows = 3;
|
|
|
|
my %buttons = (
|
|
|
|
get_info => Gtk3::Button->new_from_icon_name("gtk-find", 4),
|
|
|
|
cancel => Gtk3::Button->new_from_stock("gtk-cancel"),
|
|
|
|
ok => Gtk3::Button->new_from_stock("gtk-ok")
|
|
|
|
);
|
|
|
|
my ($url, $title) = ('', '');
|
|
|
|
my $wnd = undef;
|
|
|
|
|
|
|
|
_ui();
|
|
|
|
|
|
|
|
Gtk3::main();
|
|
|
|
|
|
|
|
sub _ui {
|
|
|
|
$wnd = Gtk3::Window::new();
|
|
|
|
my $sr = undef;
|
|
|
|
my $t = undef;
|
|
|
|
my @x = [];
|
|
|
|
my $x = undef;
|
|
|
|
|
|
|
|
foreach my $k ( keys %window_params ) {
|
|
|
|
$sr = 'set_' . $k;
|
|
|
|
@x = map { $_ } @{$window_params{$k}};
|
|
|
|
$wnd->$sr(map { defined $_ ? $_ : () } $x[0],
|
|
|
|
map { defined $_ ? $_ : () } $x[1] );
|
|
|
|
}
|
|
|
|
|
|
|
|
my $vbox = Gtk3::Box->new('vertical', 8);
|
|
|
|
$wnd->add($vbox);
|
|
|
|
|
|
|
|
foreach my $k ( keys %grids ) {
|
|
|
|
$grids{$k}{e} = Gtk3::Grid->new();
|
|
|
|
|
|
|
|
foreach my $p ( keys %{$grids{$k}{properties}} ) {
|
|
|
|
$sr = 'set_' . $p;
|
|
|
|
$x = $grids{$k}{properties}{$p};
|
|
|
|
$grids{$k}{e}->$sr($x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$vbox->pack_start($grids{main}{e}, TRUE, TRUE, 0);
|
|
|
|
$vbox->pack_start($grids{buttons}{e}, TRUE, TRUE, 0);
|
|
|
|
|
|
|
|
for (my $i = 0; $i <= $#labels; $i++) {
|
|
|
|
$labels[$i]{e} = Gtk3::Label->new($labels[$i]{label});
|
|
|
|
$labels[$i]{e}->set_halign("start");
|
|
|
|
$grids{main}{e}->attach($labels[$i]{e}, 0, $i, 1, 1);
|
|
|
|
$t = 'Gtk3::' . $controls{$labels[$i]{control}}{type};
|
|
|
|
$controls{$labels[$i]{control}}{e} = $t->new();
|
|
|
|
|
|
|
|
foreach my $k ( keys %{$controls{$labels[$i]{control}}{properties}} ) {
|
|
|
|
$sr = 'set_' . $k;
|
|
|
|
$x = $controls{$labels[$i]{control}}{properties}{$k};
|
|
|
|
$controls{$labels[$i]{control}}{e}->$sr($x);
|
|
|
|
}
|
|
|
|
|
|
|
|
$grids{main}{e}->attach_next_to($controls{$labels[$i]{control}}{e},
|
|
|
|
$labels[$i]{e}, 'right',
|
|
|
|
$controls{$labels[$i]{control}}{width}, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
$grids{main}{e}->attach_next_to($buttons{get_info},
|
|
|
|
$controls{$labels[0]{control}}{e}, 'right', 1, 1);
|
|
|
|
$grids{buttons}{e}->attach($buttons{ok}, 0, 0, 1, 1);
|
|
|
|
$grids{buttons}{e}->attach($buttons{cancel}, 1, 0, 1, 1);
|
|
|
|
|
|
|
|
$grids{main}{e}->attach($grids{checkboxes}{e}, 2, 2, 1, 4);
|
|
|
|
|
|
|
|
my @k = (
|
|
|
|
sort { $checkboxes{$a}{o} <=> $checkboxes{$b}{o} } keys %checkboxes );
|
|
|
|
while ( my ($i, $k) = each @k ) {
|
|
|
|
$checkboxes{$k}{e} = Gtk3::CheckButton->new_with_label(
|
|
|
|
$checkboxes{$k}{label});
|
|
|
|
$grids{checkboxes}{e}->attach($checkboxes{$k}{e},
|
|
|
|
int($i / $chk_rows), $i % $chk_rows, 1, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ( "x0.5", "x1", "x2" ) { $controls{scale}{e}->append_text($_); }
|
|
|
|
$controls{scale}{e}->set_active(1);
|
|
|
|
|
|
|
|
$buttons{get_info}->signal_connect( clicked => \&_get_info );
|
|
|
|
$buttons{cancel}->signal_connect( clicked => sub { $wnd->destroy } );
|
|
|
|
$buttons{ok}->signal_connect( clicked => \&_play );
|
|
|
|
|
|
|
|
$wnd->signal_connect( destroy => sub { Gtk3->main_quit } );
|
|
|
|
$wnd->show_all;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub _get_info {
|
|
|
|
$url = $controls{url}{e}->get_text();
|
|
|
|
|
|
|
|
if ( $url ne '' ) {
|
|
|
|
$title = qx{yt-dlp --no-warnings --quiet --get-title "$url"};
|
|
|
|
if ( $title ne '' ) {
|
|
|
|
my @out = qx{yt-dlp --no-warnings --quiet --list-formats "$url" | grep -v "audio" | awk '\$2=="mp4" {print \$3}' | uniq | awk -F'x' '{print \$2"p"}'};
|
|
|
|
|
|
|
|
foreach ( @out ) {
|
|
|
|
$_ =~ s/[\r\n]+$//;
|
|
|
|
$controls{resolution}{e}->append_text( $_ );
|
|
|
|
}
|
|
|
|
|
|
|
|
$controls{resolution}{e}->set_active(0);
|
|
|
|
$controls{title}{e}->set_text($title);
|
|
|
|
} else {$controls{title}{e}->set_text("Error: "); }
|
|
|
|
} else { $controls{title}{e}->set_text("Error: Empty url."); }
|
|
|
|
}
|
|
|
|
|
|
|
|
sub _play {
|
|
|
|
if ( $url ne '' ) {
|
|
|
|
my $resolution = $controls{resolution}{e}->get_active_text();
|
|
|
|
$resolution =~ s/p$//;
|
|
|
|
my $scale = $controls{scale}{e}->get_active_text();
|
|
|
|
$scale =~ s/^x//;
|
|
|
|
|
|
|
|
my $options = '--no-terminal';
|
|
|
|
|
|
|
|
foreach my $k ( keys %checkboxes ) {
|
|
|
|
if ( $checkboxes{$k}{e}->get_active ) {
|
|
|
|
$options .= $checkboxes{$k}{opt};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$options .= ' --window-scale=' . $scale;
|
|
|
|
$options .= " --ytdl-format=\"bv*[height<=$resolution]+ba/b[height<=$resolution] / wv*+ba/w\"";
|
|
|
|
|
|
|
|
my $cmd = "mpv $options $url";
|
|
|
|
|
|
|
|
{ exec ($cmd) }; print STDERR "Couldn't exec mpv: $!";
|
|
|
|
|
|
|
|
$wnd->destroy();
|
|
|
|
|
|
|
|
exit 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|