Browse Source

yt-dlp-gui - yt-dlp-gui - gui generation rewritten.

master
Sergey Kiselev 6 months ago
parent
commit
3273607a80
  1. 261
      yt-dlp-gui

261
yt-dlp-gui

@ -8,156 +8,177 @@ use open qw/:std :encoding(utf8)/;
binmode(STDOUT, ":utf8"); binmode(STDOUT, ":utf8");
use Gtk3 '-init'; use Gtk3 '-init';
use Glib "TRUE", "FALSE"; use Glib 'TRUE', 'FALSE';
my $wnd = Gtk3::Window::new(); my %window_params = (
my @labels = undef; title => [ 'yt-dlp GUI' ], icon_name => [ 'youtube' ],
my %chks = ( position => [ 'center' ], border_width => [ 20 ],
ontop => { o => 1, opt => ' --ontop', lbl => 'On-Top', chk => undef }, resizable => [ FALSE ], default_size => [ 480, 240 ],
border => { o => 2, opt => ' --no-border', lbl => 'Without borders', chk => undef }, );
alldesk => { o => 3, opt => ' --on-all-workspaces', lbl => 'On all workspaces', chk => undef} 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 $txt_URL = Gtk3::Entry->new(); my %checkboxes = (
my $txt_Title = Gtk3::Entry->new(); ontop => { e => undef, o => 1, label => 'On-Top',
my $cb_Resolution = Gtk3::ComboBoxText->new(); opt => ' --ontop' },
my $cb_Scale = Gtk3::ComboBoxText->new(); border => { e => undef, o => 2, label => 'Without borders',
my $btn_Get = Gtk3::Button->new_from_icon_name("gtk-find", 4); 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(); _ui();
Gtk3::main(); Gtk3::main();
sub _ui { sub _ui {
my $vbox = Gtk3::VBox::new(); $wnd = Gtk3::Window::new();
my $grid = Gtk3::Grid->new(); my $sr = undef;
my $grid_btn = Gtk3::Grid->new(); my $t = undef;
my $grid_opt = Gtk3::Grid->new(); my @x = [];
my $grid_header = Gtk3::Grid->new(); my $x = undef;
my $btn_Cancel = Gtk3::Button->new_from_stock("gtk-cancel"); foreach my $k ( keys %window_params ) {
my $btn_Ok = Gtk3::Button->new_from_stock("gtk-ok"); $sr = 'set_' . $k;
@x = map { $_ } @{$window_params{$k}};
my $img = Gtk3::Image->new_from_icon_name("youtube", 6); $wnd->$sr(map { defined $_ ? $_ : () } $x[0],
$img->set_halign("start"); map { defined $_ ? $_ : () } $x[1] );
}
$wnd->set_title("yt-dlp GUI");
$wnd->set_default_size(480, 240);
$wnd->set_icon_name("youtube");
$wnd->set_position("center");
$wnd->set_border_width(20);
$wnd->set_resizable(FALSE);
$wnd->signal_connect( destroy => sub { Gtk3->main_quit } );
$grid->set_column_spacing(10); my $vbox = Gtk3::Box->new('vertical', 8);
$grid->set_row_spacing(10); $wnd->add($vbox);
$grid->set_hexpand(TRUE);
foreach my $k ( keys %grids ) {
$grids{$k}{e} = Gtk3::Grid->new();
$grid_btn->set_column_spacing(10); foreach my $p ( keys %{$grids{$k}{properties}} ) {
$grid_btn->set_row_spacing(10); $sr = 'set_' . $p;
$grid_btn->set_halign("end"); $x = $grids{$k}{properties}{$p};
$grid_btn->set_valign("end"); $grids{$k}{e}->$sr($x);
}
}
$grid_opt->set_column_spacing(10); $vbox->pack_start($grids{main}{e}, TRUE, TRUE, 0);
$grid_opt->set_row_spacing(10); $vbox->pack_start($grids{buttons}{e}, TRUE, TRUE, 0);
$grid_opt->set_hexpand(TRUE);
$grid_header->set_column_spacing(10); for (my $i = 0; $i <= $#labels; $i++) {
$grid_header->set_row_spacing(0); $labels[$i]{e} = Gtk3::Label->new($labels[$i]{label});
$grid_header->set_hexpand(TRUE); $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 ( "Video URL:", "Title:", "Resolution:", "Scale:" ) { foreach my $k ( keys %{$controls{$labels[$i]{control}}{properties}} ) {
push(@labels, Gtk3::Label->new($_)); $sr = 'set_' . $k;
$labels[$#labels]->set_halign("start"); $x = $controls{$labels[$i]{control}}{properties}{$k};
$grid->attach($labels[$#labels], 0, $#labels, 1, 1); $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);
} }
my @k = ( sort { $chks{$a}{o} <=> $chks{$b}{o} } keys %chks ); $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 ) { while ( my ($i, $k) = each @k ) {
$chks{$k}{chk} = Gtk3::CheckButton->new_with_label($chks{$k}{lbl}); $checkboxes{$k}{e} = Gtk3::CheckButton->new_with_label(
$grid_opt->attach($chks{$k}{chk}, 0, $i, 1, 1); $checkboxes{$k}{label});
$grids{checkboxes}{e}->attach($checkboxes{$k}{e},
int($i / $chk_rows), $i % $chk_rows, 1, 1);
} }
foreach ( "x0.5", "x1", "x2" ) { foreach ( "x0.5", "x1", "x2" ) { $controls{scale}{e}->append_text($_); }
$cb_Scale->append_text( $_ ); $controls{scale}{e}->set_active(1);
}
$cb_Scale->set_active(1);
$txt_URL->set_halign("fill");
$txt_URL->set_hexpand(TRUE);
$txt_Title->set_halign("fill");
$txt_Title->set_hexpand(TRUE);
$cb_Resolution->set_halign("start");
$cb_Resolution->set_hexpand(FALSE);
$cb_Scale->set_halign("start");
$cb_Scale->set_hexpand(FALSE);
$btn_Get->signal_connect( clicked => \&_get_info );
$btn_Cancel->signal_connect( clicked => sub { $wnd->destroy } );
$btn_Ok->signal_connect( clicked => \&_play );
$grid_header->attach($img, 0, 1, 1, 1);
$grid_header->attach(Gtk3::Label->new("Please enter video URL"), 1, 1, 1, 1);
$grid->attach($txt_URL, 1, 1, 2, 1);
$grid->attach($btn_Get, 3, 1, 1, 1);
$grid->attach($txt_Title, 1, 2, 3, 1);
$grid->attach($cb_Resolution, 1, 3, 1, 1);
$grid->attach($cb_Scale, 1, 4, 1, 1);
$grid->attach($grid_opt, 2, 3, 1, 4);
$grid_btn->attach($btn_Ok, 0, 1, 1, 1);
$grid_btn->attach($btn_Cancel, 1, 1, 1, 1);
$vbox->add($grid_header);
$vbox->add($grid);
$vbox->add($grid_btn);
$wnd->add($vbox); $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; $wnd->show_all;
} }
sub _get_info { sub _get_info {
my $url = $txt_URL->get_text(); $url = $controls{url}{e}->get_text();
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"}'};
my $title = qx{yt-dlp --no-warnings --quiet --get-title "$url"}; if ( $url ne '' ) {
$title = qx{yt-dlp --no-warnings --quiet --get-title "$url"};
foreach ( @out ) { if ( $title ne '' ) {
$_ =~ s/[\r\n]+$//; 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"}'};
$cb_Resolution->append_text( $_ );
} foreach ( @out ) {
$_ =~ s/[\r\n]+$//;
$cb_Resolution->set_active(0); $controls{resolution}{e}->append_text( $_ );
}
$txt_Title->set_text($title);
$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 { sub _play {
my $res = $cb_Resolution->get_active_text(); if ( $url ne '' ) {
$res =~ s/p$//; my $resolution = $controls{resolution}{e}->get_active_text();
my $scale = $cb_Scale->get_active_text(); $resolution =~ s/p$//;
$scale =~ s/^x//; my $scale = $controls{scale}{e}->get_active_text();
$scale =~ s/^x//;
my $opts = "--no-terminal";
my $options = '--no-terminal';
my @k = ( sort { $chks{$a}{o} <=> $chks{$b}{o} } keys %chks );
while ( my ($i, $k) = each @k ) { foreach my $k ( keys %checkboxes ) {
if ( $chks{$k}{chk}->get_active ) { if ( $checkboxes{$k}{e}->get_active ) {
$opts .= $chks{$k}{opt}; $options .= $checkboxes{$k}{opt};
}
} }
}
$opts .= " --window-scale=" . $scale;
$opts .= " --ytdl-format=\"bv*[height<=$res]+ba/b[height<=$res] / wv*+ba/w\""; $options .= ' --window-scale=' . $scale;
$options .= " --ytdl-format=\"bv*[height<=$resolution]+ba/b[height<=$resolution] / wv*+ba/w\"";
my $url = "\"" . $txt_URL->get_text() . "\""; my $cmd = "mpv $options $url";
my $cmd = "mpv $opts $url"; { exec ($cmd) }; print STDERR "Couldn't exec mpv: $!";
{ exec ($cmd) }; print STDERR "Couldn't exec mpv: $!"; $wnd->destroy();
$wnd->destroy(); exit 0;
}
exit 0;
} }

Loading…
Cancel
Save