From d36b8a907549c605b1bc93071ad034f3a7b2f062 Mon Sep 17 00:00:00 2001 From: Karolis Date: Sun, 5 May 2024 22:40:06 +0300 Subject: [PATCH 01/20] Bump debian compat level to 10 Will not package with level 5, minimum 7 is required, but everything <10 is deprecated. --- debian/compat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/compat b/debian/compat index 7ed6ff82..f599e28b 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -5 +10 From 93f4218fc2e9fd4e1f8d425af2e68d355a8f97b1 Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Sun, 5 May 2024 23:17:48 +0300 Subject: [PATCH 02/20] copy-paste from last.fm to listenbrainz --- plugins/listenbrainz.pm | 293 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 plugins/listenbrainz.pm diff --git a/plugins/listenbrainz.pm b/plugins/listenbrainz.pm new file mode 100644 index 00000000..3e634dec --- /dev/null +++ b/plugins/listenbrainz.pm @@ -0,0 +1,293 @@ +# Copyright (C) 2005-2009 Quentin Sculo +# +# This file is part of Gmusicbrowser. +# Gmusicbrowser is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation + +=for gmbplugin AUDIOSCROBBLER +name last.fm +title last.fm plugin +desc Submit played songs to last.fm +=cut + + +package GMB::Plugin::AUDIOSCROBBLER; +use strict; +use warnings; +use constant +{ CLIENTID => 'gmb', VERSION => '0.1', + OPT => 'PLUGIN_AUDIOSCROBBLER_',#used to identify the plugin's options + SAVEFILE => 'audioscrobbler.queue', #file used to save unsent data +}; +use Digest::MD5 'md5_hex'; +require $::HTTP_module; + +our $ignore_current_song; + +my $self=bless {},__PACKAGE__; +my @ToSubmit; my $NowPlaying; my $NowPlayingID; my $unsent_saved=0; +my $interval=5; my ($timeout,$waiting); +my ($HandshakeOK,$submiturl,$nowplayingurl,$sessionid); +my ($Serrors,$Stop); +my $Log= Gtk3::ListStore->new('Glib::String'); +Load(); + +sub Start +{ ::Watch($self,PlayingSong=> \&SongChanged); + ::Watch($self,Played => \&Played); + ::Watch($self,Save => \&Save); + $self->{on}=1; + Sleep(); + SongChanged() if $::TogPlay; + $Serrors=$Stop=undef; +} +sub Stop +{ $waiting->abort if $waiting; + Glib::Source->remove($timeout) if $timeout; + $timeout=$waiting=undef; + ::UnWatch($self,$_) for qw/PlayingSong Played Save/; + $self->{on}=undef; + $interval=5; + #@ToSubmit=(); +} + +sub prefbox +{ my $vbox= Gtk3::VBox->new(::FALSE, 2); + my $sg1= Gtk3::SizeGroup->new('horizontal'); + my $sg2= Gtk3::SizeGroup->new('horizontal'); + my $entry1=::NewPrefEntry(OPT.'USER',_"username :", cb => \&userpass_changed, sizeg1 => $sg1,sizeg2=>$sg2); + my $entry2=::NewPrefEntry(OPT.'PASS',_"password :", cb => \&userpass_changed, sizeg1 => $sg1,sizeg2=>$sg2, hide => 1); + my $label2= Gtk3::Button->new(_"(see http://www.last.fm)"); + $label2->set_relief('none'); + $label2->signal_connect(clicked => sub + { my $url='http://www.last.fm'; + my $user=$::Options{OPT.'USER'}; + $url.="/user/$user/" if defined $user && $user ne ''; + ::openurl($url); + }); + my $ignore= Gtk3::CheckButton->new(_"Don't submit current song"); + $ignore->signal_connect(toggled=>sub { return if $_[0]->{busy}; $ignore_current_song= $_[0]->get_active ? $::SongID : undef; ::HasChanged('Lastfm_ignore_current'); }); + ::Watch($ignore,Lastfm_ignore_current => sub { $_[0]->{busy}=1; $_[0]->set_active(defined $ignore_current_song); delete $_[0]->{busy}; } ); + my $queue= Gtk3::Label->new; + my $sendnow= Gtk3::Button->new(_"Send now"); + $sendnow->signal_connect(clicked=> \&SendNow); + my $qbox= ::Hpack($queue,$sendnow); + $vbox->pack_start($_,::FALSE,::FALSE,0) for $label2,$entry1,$entry2,$ignore,$qbox; + $vbox->add( ::LogView($Log) ); + $qbox->{label}=$queue; + $qbox->{button}=$sendnow; + $qbox->show_all; + update_queue_label($qbox); + $qbox->set_no_show_all(1); + ::Watch($qbox,Lastfm_state_change=>\&update_queue_label); + return $vbox; +} +sub update_queue_label +{ my $qbox=shift; + my $label= $qbox->{label}; + if (@ToSubmit && (@ToSubmit>1 || (!$waiting && (!$timeout || $interval>10)))) + { $label->set_text(::__n("%d song waiting to be sent","%d songs waiting to be sent", scalar @ToSubmit )); + $label->get_parent->show; + $qbox->{button}->set_sensitive(!$waiting); + } + else { $label->get_parent->hide } +} +sub userpass_changed +{ $HandshakeOK=$Serrors=undef; + $Stop=undef if $Stop && $Stop eq 'BadAuth'; +} + +sub SongChanged +{ if (defined $ignore_current_song) + { return if defined $::SongID && $::SongID == $ignore_current_song; + $ignore_current_song=undef; ::HasChanged('Lastfm_ignore_current'); + } + $NowPlaying=undef; + my ($title,$artist,$album,$track,$length)= Songs::Get($::SongID,qw/title artist album track length/); + return if $title eq '' || $artist eq ''; + $NowPlaying= [ $artist, $title, $album, $length, $track, '' ]; + $NowPlayingID=$::SongID; + Sleep(); +} + +sub Played +{ my (undef,$ID,undef,$start_time,$seconds,$coverage)=@_; + return if $ignore_current_song; + return unless $seconds>10; + my $length= Songs::Get($ID,'length'); + if ($length>=30 && ($seconds >= 240 || $coverage >= .5) ) + { my ($title,$artist,$album,$track)= Songs::Get($ID,qw/title artist album track/); + return if $title eq '' || $artist eq ''; + ::IdleDo("9_".__PACKAGE__,10000,\&Save) if @ToSubmit>$unsent_saved; + push @ToSubmit,[ $artist,$title,$album,'',$length,$start_time,$track,'P' ]; + Sleep(); + ::QHasChanged('Lastfm_state_change'); + } +} + +sub Handshake +{ $HandshakeOK=0; + my $user=$::Options{OPT.'USER'}; + return 0 unless defined $user && $user ne ''; + my $pass=$::Options{OPT.'PASS'}; + my $time=time; + my $auth=md5_hex(md5_hex($pass).$time); + Send(\&response_cb,'http://post.audioscrobbler.com/?hs=true&p=1.2&c='.CLIENTID.'&v='.VERSION."&u=$user&t=$time&a=$auth"); +} + +sub response_cb +{ my ($response,@lines)=@_; + my $error; + if (!defined $response) {$error=_"connection failed";} + elsif ($response eq 'OK') { } + elsif ($response=~m/^FAILED (.*)$/) {$error=$1} + elsif ($response eq 'BADAUTH') {$error=_("User authentification error"); $Stop='BadAuth';} + elsif ($response eq 'BANNED') {$error=_("Client banned, contact gmusicbrowser's developer"); $Stop='Banned';} + elsif ($response eq 'BADTIME') {$error=_("System clock is not close enough to the current time"); $Stop='BadTime';} + else {$error=_"unknown error";} + + if (defined $error) + { unless ($Stop) + { $interval*=2; + $interval=30*60 if $interval>30*60; + $interval=60 if $interval<60; + $error.= ::__x( ' (' . _("retry in {seconds} s") . ')', seconds => $interval); + } + Log(_("Handshake failed : ").$error); + } + else + { ($sessionid,$nowplayingurl,$submiturl)=@lines; + $interval=5; + $HandshakeOK=1; + $Serrors=0; + Log(_"Handshake OK"); + } +} + +sub Submit +{ my $post="s=$sessionid"; + my $i=0; + my $url; + if (@ToSubmit) + { while (my $aref=$ToSubmit[$i]) + { my @data= map { defined $_ ? ::url_escapeall($_) : "" } @$aref; + $post.=sprintf "&a[$i]=%s&t[$i]=%s&b[$i]=%s&m[$i]=%s&l[$i]=%s&i[$i]=%s&n[$i]=%s&o[$i]=%s&r[$i]=", @data; + $i++; + last if $i==50; #don't submit more than 50 songs at a time + } + $url=$submiturl; + return unless $i; + } + elsif ($NowPlaying) + { if (!defined $::PlayingID || $::PlayingID!=$NowPlayingID) { $NowPlaying=undef; return } + my @data= map { defined $_ ? ::url_escapeall($_) : "" } @$NowPlaying; + $post.= sprintf "&a=%s&t=%s&b=%s&l=%s&n=%s&m=%s", @data; + $url=$nowplayingurl; + } + else {return} + my $response_cb=sub + { my ($response,@lines)=@_; + my $error; + if (!defined $response) {$error=_"connection failed"; $Serrors++} + elsif ($response eq 'OK') + { $Serrors=0; + if ($i) + { Log( _("Submit OK") . ' ('. + ($i>1 ? ::__n("%d song","%d songs",$i) + : ::__x( _"{song} by {artist}", song=> $ToSubmit[0][1], artist => $ToSubmit[0][0]) ) . ')' ); + splice @ToSubmit,0,$i; + ::IdleDo("9_".__PACKAGE__,10000,\&Save) if $unsent_saved; + } + elsif ($NowPlaying) + { Log( _("Submit Now-Playing OK") . ' ('. + ::__x( _"{song} by {artist}", song=> $NowPlaying->[1], artist => $NowPlaying->[0]) . ')' ); + $NowPlaying=undef; + } + } + elsif ($response eq 'BADSESSION') + { $error=_"Bad session"; + $HandshakeOK=0; + } + elsif ($response=~m/^FAILED (.*)$/) + { $error=$1; + $Serrors++; + } + else {$error=_"unknown error"; $Serrors++} + + $HandshakeOK=0 if $Serrors && $Serrors>2; + + if (defined $error) + { Log(_("Submit failed : ").$error); + } + }; + + warn "submitting: $post\n" if $::debug; + Send($response_cb,$url,$post); +} + +sub SendNow +{ $interval=5; + $Serrors=$Stop=undef; + Glib::Source->remove($timeout) if $timeout; + Awake(); +} +sub Sleep +{ #warn "Sleep\n"; + return unless $self->{on}; + ::QHasChanged('Lastfm_state_change'); + return if $Stop || $waiting || $timeout; + $timeout=Glib::Timeout->add(1000*$interval,\&Awake) if @ToSubmit || $NowPlaying; + #warn "Sleeping $interval seconds\n" if $timeout; +} +sub Awake +{ #warn "Awoke\n"; + $timeout=undef; + return 0 if !$self->{on} || $waiting; + if ($HandshakeOK) { Submit(); } + else { Handshake(); } + Sleep(); + return 0; +} +sub Send +{ my ($response_cb,$url,$post)=@_; + my $cb=sub + { my @response=(defined $_[0])? split "\012",$_[0] : (); + $waiting=undef; + &$response_cb(@response); + Sleep(); + }; + $waiting=Simple_http::get_with_cb(cb => $cb,url => $url,post => $post); + ::QHasChanged('Lastfm_state_change'); +} + +sub Log +{ my $text=$_[0]; + $Log->set( $Log->prepend,0, localtime().' '.$text ); + warn "$text\n" if $::debug; + if (my $iter=$Log->iter_nth_child(undef,50)) { $Log->remove($iter); } +} + +sub Load #read unsent data +{ return unless -r $::HomeDir.SAVEFILE; + return unless open my$fh,'<:utf8',$::HomeDir.SAVEFILE; + while (my $line=<$fh>) + { chomp $line; + my @data=split "\x1D",$line; + push @ToSubmit,\@data if @data==8; + } + close $fh; + Log(::__("Loaded %d unsent song from previous session","Loaded %d unsent songs from previous session", scalar @ToSubmit)); +} +sub Save #save unsent data to a file +{ $unsent_saved=@ToSubmit; + unless (@ToSubmit) + { unlink $::HomeDir.SAVEFILE; return } + my $fh; + unless (open $fh,'>:utf8',$::HomeDir.SAVEFILE) + { warn "Error creating '$::HomeDir".SAVEFILE."' : $!\nUnsent last.fm data will be lost.\n"; return; } + print $fh join("\x1D",@$_)."\n" for @ToSubmit; + close $fh; +} + +1; From c04d1ae8e9fc7c751122716ef1da89000239fdcd Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Sun, 5 May 2024 23:54:28 +0300 Subject: [PATCH 03/20] rename all instances, restore original querystring --- plugins/listenbrainz.pm | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/plugins/listenbrainz.pm b/plugins/listenbrainz.pm index 3e634dec..9fd9ec00 100644 --- a/plugins/listenbrainz.pm +++ b/plugins/listenbrainz.pm @@ -1,24 +1,24 @@ -# Copyright (C) 2005-2009 Quentin Sculo +# Copyright (C) 2024 Carl di Ortus # # This file is part of Gmusicbrowser. # Gmusicbrowser is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3, as # published by the Free Software Foundation -=for gmbplugin AUDIOSCROBBLER -name last.fm -title last.fm plugin -desc Submit played songs to last.fm +=for gmbplugin LISTENBRAINZ +name listenbrainz +title listenbrainz.org plugin +desc Submit played songs to listenbrainz =cut -package GMB::Plugin::AUDIOSCROBBLER; +package GMB::Plugin::LISTENBRAINZ; use strict; use warnings; use constant { CLIENTID => 'gmb', VERSION => '0.1', - OPT => 'PLUGIN_AUDIOSCROBBLER_',#used to identify the plugin's options - SAVEFILE => 'audioscrobbler.queue', #file used to save unsent data + OPT => 'PLUGIN_LISTENBRAINZ_',#used to identify the plugin's options + SAVEFILE => 'listenbrainz.queue', #file used to save unsent data }; use Digest::MD5 'md5_hex'; require $::HTTP_module; @@ -58,17 +58,17 @@ sub prefbox my $sg2= Gtk3::SizeGroup->new('horizontal'); my $entry1=::NewPrefEntry(OPT.'USER',_"username :", cb => \&userpass_changed, sizeg1 => $sg1,sizeg2=>$sg2); my $entry2=::NewPrefEntry(OPT.'PASS',_"password :", cb => \&userpass_changed, sizeg1 => $sg1,sizeg2=>$sg2, hide => 1); - my $label2= Gtk3::Button->new(_"(see http://www.last.fm)"); + my $label2= Gtk3::Button->new(_"(see https://listenbrainz.org)"); $label2->set_relief('none'); $label2->signal_connect(clicked => sub - { my $url='http://www.last.fm'; + { my $url='https://listenbrainz.org'; my $user=$::Options{OPT.'USER'}; $url.="/user/$user/" if defined $user && $user ne ''; ::openurl($url); }); my $ignore= Gtk3::CheckButton->new(_"Don't submit current song"); - $ignore->signal_connect(toggled=>sub { return if $_[0]->{busy}; $ignore_current_song= $_[0]->get_active ? $::SongID : undef; ::HasChanged('Lastfm_ignore_current'); }); - ::Watch($ignore,Lastfm_ignore_current => sub { $_[0]->{busy}=1; $_[0]->set_active(defined $ignore_current_song); delete $_[0]->{busy}; } ); + $ignore->signal_connect(toggled=>sub { return if $_[0]->{busy}; $ignore_current_song= $_[0]->get_active ? $::SongID : undef; ::HasChanged('Listenbrainz_ignore_current'); }); + ::Watch($ignore,Listenbrainz_ignore_current => sub { $_[0]->{busy}=1; $_[0]->set_active(defined $ignore_current_song); delete $_[0]->{busy}; } ); my $queue= Gtk3::Label->new; my $sendnow= Gtk3::Button->new(_"Send now"); $sendnow->signal_connect(clicked=> \&SendNow); @@ -80,7 +80,7 @@ sub prefbox $qbox->show_all; update_queue_label($qbox); $qbox->set_no_show_all(1); - ::Watch($qbox,Lastfm_state_change=>\&update_queue_label); + ::Watch($qbox,Listenbrainz_state_change=>\&update_queue_label); return $vbox; } sub update_queue_label @@ -101,7 +101,7 @@ sub userpass_changed sub SongChanged { if (defined $ignore_current_song) { return if defined $::SongID && $::SongID == $ignore_current_song; - $ignore_current_song=undef; ::HasChanged('Lastfm_ignore_current'); + $ignore_current_song=undef; ::HasChanged('Listenbrainz_ignore_current'); } $NowPlaying=undef; my ($title,$artist,$album,$track,$length)= Songs::Get($::SongID,qw/title artist album track length/); @@ -122,7 +122,7 @@ sub Played ::IdleDo("9_".__PACKAGE__,10000,\&Save) if @ToSubmit>$unsent_saved; push @ToSubmit,[ $artist,$title,$album,'',$length,$start_time,$track,'P' ]; Sleep(); - ::QHasChanged('Lastfm_state_change'); + ::QHasChanged('Listenbrainz_state_change'); } } @@ -133,7 +133,7 @@ sub Handshake my $pass=$::Options{OPT.'PASS'}; my $time=time; my $auth=md5_hex(md5_hex($pass).$time); - Send(\&response_cb,'http://post.audioscrobbler.com/?hs=true&p=1.2&c='.CLIENTID.'&v='.VERSION."&u=$user&t=$time&a=$auth"); + Send(\&response_cb,'http://proxy.listenbrainz.org/?hs=true&p=1.2&c='.CLIENTID.'&v='.VERSION."&u=$user&t=$time&a=$auth"); } sub response_cb @@ -235,7 +235,7 @@ sub SendNow sub Sleep { #warn "Sleep\n"; return unless $self->{on}; - ::QHasChanged('Lastfm_state_change'); + ::QHasChanged('Listenbrainz_state_change'); return if $Stop || $waiting || $timeout; $timeout=Glib::Timeout->add(1000*$interval,\&Awake) if @ToSubmit || $NowPlaying; #warn "Sleeping $interval seconds\n" if $timeout; @@ -258,7 +258,7 @@ sub Send Sleep(); }; $waiting=Simple_http::get_with_cb(cb => $cb,url => $url,post => $post); - ::QHasChanged('Lastfm_state_change'); + ::QHasChanged('Listenbrainz_state_change'); } sub Log @@ -285,7 +285,7 @@ sub Save #save unsent data to a file { unlink $::HomeDir.SAVEFILE; return } my $fh; unless (open $fh,'>:utf8',$::HomeDir.SAVEFILE) - { warn "Error creating '$::HomeDir".SAVEFILE."' : $!\nUnsent last.fm data will be lost.\n"; return; } + { warn "Error creating '$::HomeDir".SAVEFILE."' : $!\nUnsent listenbrainz.org data will be lost.\n"; return; } print $fh join("\x1D",@$_)."\n" for @ToSubmit; close $fh; } From bb1e8c5cecaf2f199c1496f732e558026dc7bb31 Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Sun, 2 Jun 2024 13:28:24 +0300 Subject: [PATCH 04/20] redo listenbrainz plugin with native API --- plugins/listenbrainz.pm | 206 ++++++++++++++-------------------------- simple_http_wget.pm | 30 ++++-- 2 files changed, 91 insertions(+), 145 deletions(-) diff --git a/plugins/listenbrainz.pm b/plugins/listenbrainz.pm index 9fd9ec00..1669b159 100644 --- a/plugins/listenbrainz.pm +++ b/plugins/listenbrainz.pm @@ -18,7 +18,6 @@ use warnings; use constant { CLIENTID => 'gmb', VERSION => '0.1', OPT => 'PLUGIN_LISTENBRAINZ_',#used to identify the plugin's options - SAVEFILE => 'listenbrainz.queue', #file used to save unsent data }; use Digest::MD5 'md5_hex'; require $::HTTP_module; @@ -26,38 +25,33 @@ require $::HTTP_module; our $ignore_current_song; my $self=bless {},__PACKAGE__; -my @ToSubmit; my $NowPlaying; my $NowPlayingID; my $unsent_saved=0; -my $interval=5; my ($timeout,$waiting); -my ($HandshakeOK,$submiturl,$nowplayingurl,$sessionid); -my ($Serrors,$Stop); +my @ToSubmit; my @NowPlaying; my $NowPlayingID; +my $interval=10; my ($timeout,$waiting); +my ($Stop); my $Log= Gtk3::ListStore->new('Glib::String'); -Load(); sub Start { ::Watch($self,PlayingSong=> \&SongChanged); ::Watch($self,Played => \&Played); - ::Watch($self,Save => \&Save); $self->{on}=1; Sleep(); SongChanged() if $::TogPlay; - $Serrors=$Stop=undef; + $Stop=undef; } sub Stop { $waiting->abort if $waiting; Glib::Source->remove($timeout) if $timeout; $timeout=$waiting=undef; - ::UnWatch($self,$_) for qw/PlayingSong Played Save/; + ::UnWatch($self,$_) for qw/PlayingSong Played/; $self->{on}=undef; - $interval=5; - #@ToSubmit=(); + $interval=10; } sub prefbox { my $vbox= Gtk3::VBox->new(::FALSE, 2); my $sg1= Gtk3::SizeGroup->new('horizontal'); my $sg2= Gtk3::SizeGroup->new('horizontal'); - my $entry1=::NewPrefEntry(OPT.'USER',_"username :", cb => \&userpass_changed, sizeg1 => $sg1,sizeg2=>$sg2); - my $entry2=::NewPrefEntry(OPT.'PASS',_"password :", cb => \&userpass_changed, sizeg1 => $sg1,sizeg2=>$sg2, hide => 1); + my $entry2=::NewPrefEntry(OPT.'TOKEN',_"Token :", cb => \&Stop, sizeg1 => $sg1,sizeg2=>$sg2, hide => 1); my $label2= Gtk3::Button->new(_"(see https://listenbrainz.org)"); $label2->set_relief('none'); $label2->signal_connect(clicked => sub @@ -73,7 +67,7 @@ sub prefbox my $sendnow= Gtk3::Button->new(_"Send now"); $sendnow->signal_connect(clicked=> \&SendNow); my $qbox= ::Hpack($queue,$sendnow); - $vbox->pack_start($_,::FALSE,::FALSE,0) for $label2,$entry1,$entry2,$ignore,$qbox; + $vbox->pack_start($_,::FALSE,::FALSE,0) for $label2,$entry2,$ignore,$qbox; $vbox->add( ::LogView($Log) ); $qbox->{label}=$queue; $qbox->{button}=$sendnow; @@ -86,28 +80,27 @@ sub prefbox sub update_queue_label { my $qbox=shift; my $label= $qbox->{label}; - if (@ToSubmit && (@ToSubmit>1 || (!$waiting && (!$timeout || $interval>10)))) - { $label->set_text(::__n("%d song waiting to be sent","%d songs waiting to be sent", scalar @ToSubmit )); + if (@ToSubmit && (!$waiting && (!$timeout || $interval>10))) + { $label->set_text(::__n("song waiting to be sent")); $label->get_parent->show; $qbox->{button}->set_sensitive(!$waiting); } else { $label->get_parent->hide } } -sub userpass_changed -{ $HandshakeOK=$Serrors=undef; - $Stop=undef if $Stop && $Stop eq 'BadAuth'; -} sub SongChanged { if (defined $ignore_current_song) { return if defined $::SongID && $::SongID == $ignore_current_song; $ignore_current_song=undef; ::HasChanged('Listenbrainz_ignore_current'); } - $NowPlaying=undef; - my ($title,$artist,$album,$track,$length)= Songs::Get($::SongID,qw/title artist album track length/); + @NowPlaying=undef; + my ($title,$artist,$album)= Songs::Get($::SongID,qw/title artist album/); return if $title eq '' || $artist eq ''; - $NowPlaying= [ $artist, $title, $album, $length, $track, '' ]; + warn "set NowPlaying"; + @NowPlaying= ( $artist, $title, $album ); $NowPlayingID=$::SongID; + $interval=10; + $timeout=undef; Sleep(); } @@ -117,147 +110,110 @@ sub Played return unless $seconds>10; my $length= Songs::Get($ID,'length'); if ($length>=30 && ($seconds >= 240 || $coverage >= .5) ) - { my ($title,$artist,$album,$track)= Songs::Get($ID,qw/title artist album track/); + { my ($title,$artist,$album)= Songs::Get($ID,qw/title artist album/); return if $title eq '' || $artist eq ''; - ::IdleDo("9_".__PACKAGE__,10000,\&Save) if @ToSubmit>$unsent_saved; - push @ToSubmit,[ $artist,$title,$album,'',$length,$start_time,$track,'P' ]; + warn "set ToSumbit"; + @ToSubmit= ( $artist, $title, $album ); + $interval=10; + $timeout=undef; Sleep(); ::QHasChanged('Listenbrainz_state_change'); } } -sub Handshake -{ $HandshakeOK=0; - my $user=$::Options{OPT.'USER'}; - return 0 unless defined $user && $user ne ''; - my $pass=$::Options{OPT.'PASS'}; - my $time=time; - my $auth=md5_hex(md5_hex($pass).$time); - Send(\&response_cb,'http://proxy.listenbrainz.org/?hs=true&p=1.2&c='.CLIENTID.'&v='.VERSION."&u=$user&t=$time&a=$auth"); -} - -sub response_cb -{ my ($response,@lines)=@_; - my $error; - if (!defined $response) {$error=_"connection failed";} - elsif ($response eq 'OK') { } - elsif ($response=~m/^FAILED (.*)$/) {$error=$1} - elsif ($response eq 'BADAUTH') {$error=_("User authentification error"); $Stop='BadAuth';} - elsif ($response eq 'BANNED') {$error=_("Client banned, contact gmusicbrowser's developer"); $Stop='Banned';} - elsif ($response eq 'BADTIME') {$error=_("System clock is not close enough to the current time"); $Stop='BadTime';} - else {$error=_"unknown error";} - - if (defined $error) - { unless ($Stop) - { $interval*=2; - $interval=30*60 if $interval>30*60; - $interval=60 if $interval<60; - $error.= ::__x( ' (' . _("retry in {seconds} s") . ')', seconds => $interval); - } - Log(_("Handshake failed : ").$error); - } - else - { ($sessionid,$nowplayingurl,$submiturl)=@lines; - $interval=5; - $HandshakeOK=1; - $Serrors=0; - Log(_"Handshake OK"); - } -} - sub Submit -{ my $post="s=$sessionid"; +{ my $i=0; - my $url; + my $url= 'https://api.listenbrainz.org/1/submit-listens'; + my $listen_type; + my $listened_at; + my @payload; if (@ToSubmit) - { while (my $aref=$ToSubmit[$i]) - { my @data= map { defined $_ ? ::url_escapeall($_) : "" } @$aref; - $post.=sprintf "&a[$i]=%s&t[$i]=%s&b[$i]=%s&m[$i]=%s&l[$i]=%s&i[$i]=%s&n[$i]=%s&o[$i]=%s&r[$i]=", @data; - $i++; - last if $i==50; #don't submit more than 50 songs at a time - } - $url=$submiturl; - return unless $i; + { @payload= @ToSubmit; + $listen_type= "single"; + $listened_at= time(); } - elsif ($NowPlaying) - { if (!defined $::PlayingID || $::PlayingID!=$NowPlayingID) { $NowPlaying=undef; return } - my @data= map { defined $_ ? ::url_escapeall($_) : "" } @$NowPlaying; - $post.= sprintf "&a=%s&t=%s&b=%s&l=%s&n=%s&m=%s", @data; - $url=$nowplayingurl; + elsif (@NowPlaying) + { if (!defined $::PlayingID || $::PlayingID!=$NowPlayingID) { @NowPlaying=undef; return } + @payload= @NowPlaying; + $listen_type= "playing_now"; + $listened_at= undef; } else {return} + my $post= '{"listen_type": "'.$listen_type.'", "payload": [{'; + $post.= '"listened_at": '.$listened_at.',' if $listened_at; + $post.= '"track_metadata": {"artist_name": "'.$payload[0].'", "track_name": "'.$payload[1].'"'; + $post.=', "release_name": "'.$payload[2].'"' if $payload[2]; + $post.='}}]}'; my $response_cb=sub { my ($response,@lines)=@_; my $error; - if (!defined $response) {$error=_"connection failed"; $Serrors++} - elsif ($response eq 'OK') - { $Serrors=0; - if ($i) - { Log( _("Submit OK") . ' ('. - ($i>1 ? ::__n("%d song","%d songs",$i) - : ::__x( _"{song} by {artist}", song=> $ToSubmit[0][1], artist => $ToSubmit[0][0]) ) . ')' ); - splice @ToSubmit,0,$i; - ::IdleDo("9_".__PACKAGE__,10000,\&Save) if $unsent_saved; - } - elsif ($NowPlaying) - { Log( _("Submit Now-Playing OK") . ' ('. - ::__x( _"{song} by {artist}", song=> $NowPlaying->[1], artist => $NowPlaying->[0]) . ')' ); - $NowPlaying=undef; - } + if (!defined $response) {$error=_"connection failed";} + elsif ($response eq '{"status":"ok"}') + { if (@ToSubmit) { + Log( _("Submit OK ") . + ::__x( _"{song} by {artist}", song=> $payload[1], artist => $payload[0]) ); + undef @ToSubmit; + $interval=10; + return + }; + if (@NowPlaying) { + Log( _("NowPlaying OK ") . + ::__x( _"{song} by {artist}", song=> $payload[1], artist => $payload[0]) ); + $interval=60; + return + }; } elsif ($response eq 'BADSESSION') { $error=_"Bad session"; - $HandshakeOK=0; } elsif ($response=~m/^FAILED (.*)$/) { $error=$1; - $Serrors++; } - else {$error=_"unknown error"; $Serrors++} - - $HandshakeOK=0 if $Serrors && $Serrors>2; + else {$error=_"unknown error";} if (defined $error) { Log(_("Submit failed : ").$error); + Log(_("Response : ").$response) if $response; + $interval*=2; } }; - warn "submitting: $post\n" if $::debug; - Send($response_cb,$url,$post); + my $authtoken=$::Options{OPT.'TOKEN'}; + Send($response_cb,$url,$post,$authtoken); } sub SendNow -{ $interval=5; - $Serrors=$Stop=undef; +{ $interval=10; + $Stop=undef; Glib::Source->remove($timeout) if $timeout; Awake(); } + sub Sleep -{ #warn "Sleep\n"; - return unless $self->{on}; +{ return unless $self->{on}; ::QHasChanged('Listenbrainz_state_change'); return if $Stop || $waiting || $timeout; - $timeout=Glib::Timeout->add(1000*$interval,\&Awake) if @ToSubmit || $NowPlaying; - #warn "Sleeping $interval seconds\n" if $timeout; + $timeout=Glib::Timeout->add(1000*$interval,\&Awake) if @ToSubmit || @NowPlaying; } + sub Awake -{ #warn "Awoke\n"; - $timeout=undef; +{ $timeout=undef; return 0 if !$self->{on} || $waiting; - if ($HandshakeOK) { Submit(); } - else { Handshake(); } + Submit(); Sleep(); return 0; } + sub Send -{ my ($response_cb,$url,$post)=@_; +{ my ($response_cb,$url,$post,$authtoken)=@_; my $cb=sub { my @response=(defined $_[0])? split "\012",$_[0] : (); $waiting=undef; &$response_cb(@response); Sleep(); }; - $waiting=Simple_http::get_with_cb(cb => $cb,url => $url,post => $post); + $waiting=Simple_http::get_with_cb(cb => $cb,url => $url,post => $post,authtoken => $authtoken); ::QHasChanged('Listenbrainz_state_change'); } @@ -268,26 +224,4 @@ sub Log if (my $iter=$Log->iter_nth_child(undef,50)) { $Log->remove($iter); } } -sub Load #read unsent data -{ return unless -r $::HomeDir.SAVEFILE; - return unless open my$fh,'<:utf8',$::HomeDir.SAVEFILE; - while (my $line=<$fh>) - { chomp $line; - my @data=split "\x1D",$line; - push @ToSubmit,\@data if @data==8; - } - close $fh; - Log(::__("Loaded %d unsent song from previous session","Loaded %d unsent songs from previous session", scalar @ToSubmit)); -} -sub Save #save unsent data to a file -{ $unsent_saved=@ToSubmit; - unless (@ToSubmit) - { unlink $::HomeDir.SAVEFILE; return } - my $fh; - unless (open $fh,'>:utf8',$::HomeDir.SAVEFILE) - { warn "Error creating '$::HomeDir".SAVEFILE."' : $!\nUnsent listenbrainz.org data will be lost.\n"; return; } - print $fh join("\x1D",@$_)."\n" for @ToSubmit; - close $fh; -} - 1; diff --git a/simple_http_wget.pm b/simple_http_wget.pm index 3e19ebea..6ce9dfb1 100644 --- a/simple_http_wget.pm +++ b/simple_http_wget.pm @@ -22,7 +22,7 @@ sub get_with_cb { my $self=bless {}; my %params=@_; $self->{params}=\%params; - my ($callback,$url,$post)=@params{qw/cb url post/}; + my ($callback,$url,$post,$authtoken)=@params{qw/cb url post authtoken/}; delete $params{cache} unless $UseCache; if (my $cached= $params{cache} && GMB::Cache::get($url)) { warn "cached result\n" if $::debug; @@ -36,13 +36,24 @@ sub get_with_cb : $orig_proxy; $ENV{http_proxy}=$proxy; - my $useragent= $params{user_agent} || 'Mozilla/5.0'; - my $accept= $params{'accept'} || ''; - my $gzip= $gzip_ok ? '--header=Accept-Encoding: gzip' : ''; - my @cmd_and_args= (qw/wget --timeout=40 -S -O -/, $gzip, "--header=Accept: $accept", "--user-agent=$useragent"); - push @cmd_and_args, "--referer=$params{referer}" if $params{referer}; - push @cmd_and_args, '--post-data='.$post if $post; #FIXME not sure if I should escape something - push @cmd_and_args, '--',$url; + my $cmd_and_args= 'wget --timeout=40 -S -O -'; + $cmd_and_args.= " -U ".($params{user_agent} || "'Mozilla/5.0'"); + $cmd_and_args.= " --header='Accept-Encoding: gzip'" if $gzip_ok; + $cmd_and_args.= " --header='Authorization: Token ".$authtoken."'" if $authtoken; + $cmd_and_args.= " --header='Content-Type: application/json'" if $authtoken; + $cmd_and_args.= " --referer=$params{referer}" if $params{referer}; + $cmd_and_args.= " --post-data='".$post."'" if $post; #FIXME not sure if I should escape something + $cmd_and_args.= " -- '$url'"; + warn "$cmd_and_args\n"; + + # my $useragent= $params{user_agent} || 'Mozilla/5.0'; + # my @cmd_and_args= (qw/wget --timeout=40 -S -O -/, "--user-agent='$useragent'"); + # push @cmd_and_args, "--header='Authorization: Token ".$authtoken."'" if $authtoken; + # push @cmd_and_args, "--header='Content-Type: application/json'" if $authtoken; + # push @cmd_and_args, "--referer=$params{referer}" if $params{referer}; + # push @cmd_and_args, "--post-data='".$post."'" if $post; #FIXME not sure if I should escape something + # push @cmd_and_args, '--',$url; + # warn "@cmd_and_args\n"; pipe my($content_fh),my$wfh; pipe my($error_fh),my$ewfh; my $pid=fork; @@ -52,7 +63,8 @@ sub get_with_cb open my($olderr), ">&", \*STDERR; open \*STDOUT,'>&='.fileno $wfh; open \*STDERR,'>&='.fileno $ewfh; - exec @cmd_and_args or print $olderr "launch failed (@cmd_and_args) : $!\n"; + #exec @cmd_and_args or print $olderr "launch failed (@cmd_and_args) : $!\n"; + exec $cmd_and_args or print $olderr "launch failed ($cmd_and_args) : $!\n"; POSIX::_exit(1); } close $wfh; close $ewfh; From ac5a78917f4f3ff9616475296aca513a1c63479d Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Sat, 10 Aug 2024 17:23:15 +0300 Subject: [PATCH 05/20] fix duplicate listenbrainz submits --- plugins/listenbrainz.pm | 28 ++++++++++++++++++---------- simple_http.pm | 9 +++++++-- simple_http_wget.pm | 11 +---------- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/plugins/listenbrainz.pm b/plugins/listenbrainz.pm index 1669b159..3909ae3b 100644 --- a/plugins/listenbrainz.pm +++ b/plugins/listenbrainz.pm @@ -39,7 +39,9 @@ sub Start $Stop=undef; } sub Stop -{ $waiting->abort if $waiting; +{ + @NowPlaying=undef; + $waiting->abort if $waiting; Glib::Source->remove($timeout) if $timeout; $timeout=$waiting=undef; ::UnWatch($self,$_) for qw/PlayingSong Played/; @@ -89,18 +91,17 @@ sub update_queue_label } sub SongChanged -{ if (defined $ignore_current_song) +{ + @NowPlaying=undef; + if (defined $ignore_current_song) { return if defined $::SongID && $::SongID == $ignore_current_song; $ignore_current_song=undef; ::HasChanged('Listenbrainz_ignore_current'); } - @NowPlaying=undef; my ($title,$artist,$album)= Songs::Get($::SongID,qw/title artist album/); return if $title eq '' || $artist eq ''; - warn "set NowPlaying"; @NowPlaying= ( $artist, $title, $album ); $NowPlayingID=$::SongID; $interval=10; - $timeout=undef; Sleep(); } @@ -112,10 +113,8 @@ sub Played if ($length>=30 && ($seconds >= 240 || $coverage >= .5) ) { my ($title,$artist,$album)= Songs::Get($ID,qw/title artist album/); return if $title eq '' || $artist eq ''; - warn "set ToSumbit"; @ToSubmit= ( $artist, $title, $album ); $interval=10; - $timeout=undef; Sleep(); ::QHasChanged('Listenbrainz_state_change'); } @@ -139,14 +138,16 @@ sub Submit $listen_type= "playing_now"; $listened_at= undef; } - else {return} + else { return; } my $post= '{"listen_type": "'.$listen_type.'", "payload": [{'; $post.= '"listened_at": '.$listened_at.',' if $listened_at; $post.= '"track_metadata": {"artist_name": "'.$payload[0].'", "track_name": "'.$payload[1].'"'; $post.=', "release_name": "'.$payload[2].'"' if $payload[2]; $post.='}}]}'; my $response_cb=sub - { my ($response,@lines)=@_; + { + my ($response,@lines)=@_; + #warn "response: $response"; my $error; if (!defined $response) {$error=_"connection failed";} elsif ($response eq '{"status":"ok"}') @@ -154,6 +155,7 @@ sub Submit Log( _("Submit OK ") . ::__x( _"{song} by {artist}", song=> $payload[1], artist => $payload[0]) ); undef @ToSubmit; + undef $waiting; $interval=10; return }; @@ -161,6 +163,7 @@ sub Submit Log( _("NowPlaying OK ") . ::__x( _"{song} by {artist}", song=> $payload[1], artist => $payload[0]) ); $interval=60; + undef $waiting; return }; } @@ -180,6 +183,9 @@ sub Submit }; my $authtoken=$::Options{OPT.'TOKEN'}; + #warn "PAYLOAD - @payload"; + #warn "NOWPLAYING - @NowPlaying"; + #warn "TOSUBMIT - @ToSubmit"; Send($response_cb,$url,$post,$authtoken); } @@ -198,7 +204,8 @@ sub Sleep } sub Awake -{ $timeout=undef; +{ Glib::Source->remove($timeout) if $timeout; + $timeout=undef; return 0 if !$self->{on} || $waiting; Submit(); Sleep(); @@ -213,6 +220,7 @@ sub Send &$response_cb(@response); Sleep(); }; + $waiting=Simple_http::get_with_cb(cb => $cb,url => $url,post => $post,authtoken => $authtoken); ::QHasChanged('Listenbrainz_state_change'); } diff --git a/simple_http.pm b/simple_http.pm index a4e67cfb..a03e8b6a 100644 --- a/simple_http.pm +++ b/simple_http.pm @@ -28,7 +28,7 @@ sub get_with_cb my %params=@_; $self->{params}=\%params; delete $params{cache} unless $UseCache; - my ($callback,$url,$post)=@params{qw/cb url post/}; + my ($callback,$url,$post,$authtoken)=@params{qw/cb url post authtoken/}; if (my $cached= $params{cache} && GMB::Cache::get($url)) { warn "cached result\n" if $::debug; Glib::Timeout->add(10,sub { $callback->( ${$cached->{data}}, type=>$cached->{type}, filename=>$cached->{filename}, ); 0}); @@ -109,11 +109,16 @@ sub connecting_cb print $socket "Host: $host:$port".EOL; print $socket "User-Agent: $useragent".EOL; print $socket "Referer: $params->{referer}".EOL if $params->{referer}; + print $socket "Authorization: Token $params->{authtoken}".EOL if $params->{authtoken}; print $socket "Accept: $accept".EOL; print $socket "Accept-Encoding: gzip".EOL if $gzip_ok; #print $socket "Connection: Keep-Alive".EOL; if (defined $post) - { print $socket 'Content-Type: application/x-www-form-urlencoded; charset=utf-8'.EOL; + { if ($params->{authtoken}) { + print $socket 'Content-Type: application/json'.EOL; + } else { + print $socket 'Content-Type: application/x-www-form-urlencoded; charset=utf-8'.EOL; + } print $socket "Content-Length: ".length($post).EOL.EOL; print $socket $post.EOL; } diff --git a/simple_http_wget.pm b/simple_http_wget.pm index 6ce9dfb1..42567245 100644 --- a/simple_http_wget.pm +++ b/simple_http_wget.pm @@ -44,16 +44,8 @@ sub get_with_cb $cmd_and_args.= " --referer=$params{referer}" if $params{referer}; $cmd_and_args.= " --post-data='".$post."'" if $post; #FIXME not sure if I should escape something $cmd_and_args.= " -- '$url'"; - warn "$cmd_and_args\n"; + #warn "$cmd_and_args\n"; - # my $useragent= $params{user_agent} || 'Mozilla/5.0'; - # my @cmd_and_args= (qw/wget --timeout=40 -S -O -/, "--user-agent='$useragent'"); - # push @cmd_and_args, "--header='Authorization: Token ".$authtoken."'" if $authtoken; - # push @cmd_and_args, "--header='Content-Type: application/json'" if $authtoken; - # push @cmd_and_args, "--referer=$params{referer}" if $params{referer}; - # push @cmd_and_args, "--post-data='".$post."'" if $post; #FIXME not sure if I should escape something - # push @cmd_and_args, '--',$url; - # warn "@cmd_and_args\n"; pipe my($content_fh),my$wfh; pipe my($error_fh),my$ewfh; my $pid=fork; @@ -63,7 +55,6 @@ sub get_with_cb open my($olderr), ">&", \*STDERR; open \*STDOUT,'>&='.fileno $wfh; open \*STDERR,'>&='.fileno $ewfh; - #exec @cmd_and_args or print $olderr "launch failed (@cmd_and_args) : $!\n"; exec $cmd_and_args or print $olderr "launch failed ($cmd_and_args) : $!\n"; POSIX::_exit(1); } From ef7924ed4f3f4b99601d91da42b8c8e60da8921a Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Wed, 14 Aug 2024 21:54:49 +0300 Subject: [PATCH 06/20] save post body to file, wget use filename --- plugins/listenbrainz.pm | 45 ++++++++++++++++++++++++++++++----------- simple_http_wget.pm | 4 ++-- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/plugins/listenbrainz.pm b/plugins/listenbrainz.pm index 3909ae3b..15244067 100644 --- a/plugins/listenbrainz.pm +++ b/plugins/listenbrainz.pm @@ -15,11 +15,12 @@ desc Submit played songs to listenbrainz package GMB::Plugin::LISTENBRAINZ; use strict; use warnings; +use JSON; use constant { CLIENTID => 'gmb', VERSION => '0.1', OPT => 'PLUGIN_LISTENBRAINZ_',#used to identify the plugin's options + SAVEFILE => 'listenbrainz.queue', #file used to save unsent data }; -use Digest::MD5 'md5_hex'; require $::HTTP_module; our $ignore_current_song; @@ -139,19 +140,29 @@ sub Submit $listened_at= undef; } else { return; } - my $post= '{"listen_type": "'.$listen_type.'", "payload": [{'; - $post.= '"listened_at": '.$listened_at.',' if $listened_at; - $post.= '"track_metadata": {"artist_name": "'.$payload[0].'", "track_name": "'.$payload[1].'"'; - $post.=', "release_name": "'.$payload[2].'"' if $payload[2]; - $post.='}}]}'; + my $post= { + listen_type => $listen_type, + payload => [ + { + #listened_at => $listened_at, + track_metadata => { + artist_name => $payload[0], + track_name => $payload[1] + #release_name => $payload[2] + } + } + ] + }; + $post->{payload}[0]->{listened_at} = $listened_at if $listened_at; + $post->{payload}[0]->{track_metadata}->{release_name} = $payload[2] if $payload[2]; my $response_cb=sub { my ($response,@lines)=@_; - #warn "response: $response"; my $error; if (!defined $response) {$error=_"connection failed";} elsif ($response eq '{"status":"ok"}') - { if (@ToSubmit) { + { unlink $::HomeDir.SAVEFILE; + if (@ToSubmit) { Log( _("Submit OK ") . ::__x( _"{song} by {artist}", song=> $payload[1], artist => $payload[0]) ); undef @ToSubmit; @@ -183,10 +194,8 @@ sub Submit }; my $authtoken=$::Options{OPT.'TOKEN'}; - #warn "PAYLOAD - @payload"; - #warn "NOWPLAYING - @NowPlaying"; - #warn "TOSUBMIT - @ToSubmit"; - Send($response_cb,$url,$post,$authtoken); + Save($post); + Send($response_cb,$url,$::HomeDir.SAVEFILE,$authtoken); } sub SendNow @@ -232,4 +241,16 @@ sub Log if (my $iter=$Log->iter_nth_child(undef,50)) { $Log->remove($iter); } } +sub Save +{ my $savebody=$_[0]; + unless ($savebody) + { unlink $::HomeDir.SAVEFILE; return } + my $fh; + unless (open $fh,'>:utf8',$::HomeDir.SAVEFILE) + { warn "Error creating '$::HomeDir".SAVEFILE."' : $!\nUnsent listenbrainz.org data will be lost.\n"; return; } + my $json=(to_json $savebody); + print $fh $json; + close $fh; +} + 1; diff --git a/simple_http_wget.pm b/simple_http_wget.pm index 42567245..d71eb154 100644 --- a/simple_http_wget.pm +++ b/simple_http_wget.pm @@ -42,10 +42,10 @@ sub get_with_cb $cmd_and_args.= " --header='Authorization: Token ".$authtoken."'" if $authtoken; $cmd_and_args.= " --header='Content-Type: application/json'" if $authtoken; $cmd_and_args.= " --referer=$params{referer}" if $params{referer}; - $cmd_and_args.= " --post-data='".$post."'" if $post; #FIXME not sure if I should escape something + $cmd_and_args.= " --post-file='".$post."'" if $post; $cmd_and_args.= " -- '$url'"; #warn "$cmd_and_args\n"; - + pipe my($content_fh),my$wfh; pipe my($error_fh),my$ewfh; my $pid=fork; From 5255ba09b8175677afe81a40ac696dba81536864 Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Thu, 3 Apr 2025 21:27:51 +0300 Subject: [PATCH 07/20] immediately submit on song change --- gmusicbrowser_songs.pm | 18 ++++++++++++++++++ plugins/listenbrainz.pm | 6 ++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/gmusicbrowser_songs.pm b/gmusicbrowser_songs.pm index 3d84a476..b7a90779 100644 --- a/gmusicbrowser_songs.pm +++ b/gmusicbrowser_songs.pm @@ -1151,6 +1151,24 @@ our %timespan_menu= editsubmenu=>0, category=>'extra', }, +# https://github.com/carl-di-ortus/gmusicbrowser/issues/3 +# https://picard-docs.musicbrainz.org/downloads/MusicBrainz_Picard_Tag_Map.html +# musicbrainz_trackid => +# { name => _"MBID", +# id3v2 => 'TXXX;MusicBrainz Release Track Id;%v', vorbis => 'musicbrainz_releasetrackid', ape => 'MUSICBRAINZ_RELEASETRACKID', ilst => "----:com.apple.iTunes:MusicBrainz Release Track Id", 'id3v2.3' => 'TXXX;MusicBrainz Release Track Id;%v', +# flags => 'fgaescpi', +# type => 'string', +# category=>'extra', +# postread=> sub { my $v=shift; warn "V $v"; }, +# }, +# acoustid => +# { name => _"AcoustID", +# id3v2 => 'TXXX;Acoustid Id;%v', vorbis => 'ACOUSTID_ID', ape => 'ACOUSTID_ID', ilst => "----:com.apple.iTunes:Acoustid Id", +# flags => 'fgaescpi', +# type => 'string', +# category=>'extra', +# postread=> sub { my $v=shift }, +# }, style => { name => _"Styles", width => 180, flags => 'fgaescpil', type => 'flags', diff --git a/plugins/listenbrainz.pm b/plugins/listenbrainz.pm index 15244067..138b12cb 100644 --- a/plugins/listenbrainz.pm +++ b/plugins/listenbrainz.pm @@ -16,9 +16,10 @@ package GMB::Plugin::LISTENBRAINZ; use strict; use warnings; use JSON; +use List::Util qw(max); use constant { CLIENTID => 'gmb', VERSION => '0.1', - OPT => 'PLUGIN_LISTENBRAINZ_',#used to identify the plugin's options + OPT => 'PLUGIN_LISTENBRAINZ_', #used to identify the plugin's options SAVEFILE => 'listenbrainz.queue', #file used to save unsent data }; require $::HTTP_module; @@ -103,7 +104,7 @@ sub SongChanged @NowPlaying= ( $artist, $title, $album ); $NowPlayingID=$::SongID; $interval=10; - Sleep(); + SendNow(); } sub Played @@ -190,6 +191,7 @@ sub Submit { Log(_("Submit failed : ").$error); Log(_("Response : ").$response) if $response; $interval*=2; + $interval=max($interval, 300); } }; From 79c4961613a936f7968d599f0c15c1844df639fc Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Thu, 3 Apr 2025 21:53:38 +0300 Subject: [PATCH 08/20] add .vscode to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 66708ab8..6f0dc07a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ locale/ po/gmusicbrowser.pot nytprof* t/samples/ + +.vscode/ +TODO \ No newline at end of file From 4c237c474dd5018475c586f135452f2a2c824a09 Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Fri, 4 Apr 2025 15:18:39 +0300 Subject: [PATCH 09/20] Remove obsolete/unmaintained http clients --- .gitignore | 2 +- debian/control | 2 +- gmusicbrowser.pl | 9 +- plugins/albuminfo.pm | 2 +- plugins/artistinfo.pm | 2 +- plugins/audioscrobbler.pm | 2 +- plugins/fetch_cover.pm | 2 +- plugins/listenbrainz.pm | 2 +- plugins/lyrics.pm | 2 +- simple_http.pm | 228 -------------------------------------- simple_http_AE.pm | 117 ------------------- 11 files changed, 10 insertions(+), 360 deletions(-) delete mode 100644 simple_http.pm delete mode 100644 simple_http_AE.pm diff --git a/.gitignore b/.gitignore index 6f0dc07a..f56bb8a2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ nytprof* t/samples/ .vscode/ -TODO \ No newline at end of file +TODO diff --git a/debian/control b/debian/control index b0c7a1ac..2459fbc6 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ Standards-Version: 3.7.3 Package: gmusicbrowser Architecture: all Depends: perl, libgtk3-perl, libgtk-3-0 -Recommends: libintl-perl, libnet-dbus-perl, libglib-object-introspection-perl, gir1.2-gstreamer-1.0, libdigest-crc-perl, libhtml-parser-perl, libio-compress-perl +Recommends: libintl-perl, libnet-dbus-perl, libglib-object-introspection-perl, gir1.2-gstreamer-1.0, libdigest-crc-perl, libhtml-parser-perl, libio-compress-perl, wget Suggests: mpv, mplayer, mpg123, vorbis-tools, alsa-utils, gir1.2-webkit2, gir1.2-notify, gir1.2-wnck, gir1.2-poppler Description: very customizable jukebox for large collections of music files The interface is extremely customizable. It has easy access to related songs diff --git a/gmusicbrowser.pl b/gmusicbrowser.pl index dbaf30d3..5bbfcf65 100755 --- a/gmusicbrowser.pl +++ b/gmusicbrowser.pl @@ -528,18 +528,13 @@ BEGIN } # end of command line handling -our $HTTP_module; our ($Play_package,%PlayPacks); my ($PlayNext_package,$Vol_package); BEGIN{ require 'gmusicbrowser_songs.pm'; require 'gmusicbrowser_tags.pm'; require 'gmusicbrowser_layout.pm'; require 'gmusicbrowser_list.pm'; -$HTTP_module= -e $DATADIR.SLASH.'simple_http_wget.pm' && (grep -x $_.SLASH.'wget', split /:/, $ENV{PATH}) ? 'simple_http_wget.pm' : - -e $DATADIR.SLASH.'simple_http_AE.pm' && (grep -f $_.SLASH.'AnyEvent'.SLASH.'HTTP.pm', @INC) ? 'simple_http_AE.pm' : - 'simple_http.pm'; -#warn "using $HTTP_module for http requests\n"; -#require $HTTP_module; +require 'simple_http_wget.pm'; # load gstreamer backend module if (!$CmdLine{nogst}) @@ -10306,7 +10301,7 @@ sub Start $self->Done; } else - { unless (eval {require $::HTTP_module}) {warn "Loading $::HTTP_module failed, can't download $display_uri\n"; $self->Done; return} + { warn "Downloading '$display_uri' to '$destpath'\n" if $::debug; ::Progress( $progressid, bartext_append=>$display_uri, title=>_"Downloading"); $self->{waiting}= Simple_http::get_with_cb(url => $uri, cache=>1, progress=>1, cb => sub { $self->Downloaded(@_); }); diff --git a/plugins/albuminfo.pm b/plugins/albuminfo.pm index ff3cac45..dba07eae 100644 --- a/plugins/albuminfo.pm +++ b/plugins/albuminfo.pm @@ -21,7 +21,7 @@ package GMB::Plugin::ALBUMINFO; use strict; use warnings; use utf8; -require $::HTTP_module; +require 'simple_http_wget.pm'; use base 'Gtk3::Box'; use constant { OPT => 'PLUGIN_ALBUMINFO_', diff --git a/plugins/artistinfo.pm b/plugins/artistinfo.pm index 2fbda13b..a89bab85 100644 --- a/plugins/artistinfo.pm +++ b/plugins/artistinfo.pm @@ -19,7 +19,7 @@ package GMB::Plugin::ARTISTINFO; use strict; use warnings; use utf8; -require $::HTTP_module; +require 'simple_http_wget.pm'; use base 'Gtk3::Box'; use constant { OPT => 'PLUGIN_ARTISTINFO_', # MUST begin by PLUGIN_ followed by the plugin ID / package name diff --git a/plugins/audioscrobbler.pm b/plugins/audioscrobbler.pm index 3e634dec..4842018f 100644 --- a/plugins/audioscrobbler.pm +++ b/plugins/audioscrobbler.pm @@ -21,7 +21,7 @@ use constant SAVEFILE => 'audioscrobbler.queue', #file used to save unsent data }; use Digest::MD5 'md5_hex'; -require $::HTTP_module; +require 'simple_http_wget.pm'; our $ignore_current_song; diff --git a/plugins/fetch_cover.pm b/plugins/fetch_cover.pm index 78c243bf..b67498b2 100644 --- a/plugins/fetch_cover.pm +++ b/plugins/fetch_cover.pm @@ -14,7 +14,7 @@ desc Adds a menu entry to artist/album context menu, allowing to search the pict package GMB::Plugin::FETCHCOVER; use strict; use warnings; -require $::HTTP_module; +require 'simple_http_wget.pm'; use base 'Gtk3::Window'; use constant { OPT => 'PLUGIN_FETCHCOVER_', diff --git a/plugins/listenbrainz.pm b/plugins/listenbrainz.pm index 138b12cb..7896766f 100644 --- a/plugins/listenbrainz.pm +++ b/plugins/listenbrainz.pm @@ -22,7 +22,7 @@ use constant OPT => 'PLUGIN_LISTENBRAINZ_', #used to identify the plugin's options SAVEFILE => 'listenbrainz.queue', #file used to save unsent data }; -require $::HTTP_module; +require 'simple_http_wget.pm'; our $ignore_current_song; diff --git a/plugins/lyrics.pm b/plugins/lyrics.pm index 4cf862c1..de808f30 100644 --- a/plugins/lyrics.pm +++ b/plugins/lyrics.pm @@ -15,7 +15,7 @@ package GMB::Plugin::LYRICS; use strict; use warnings; use utf8; -require $::HTTP_module; +require 'simple_http_wget.pm'; our @ISA; BEGIN {push @ISA,'GMB::Context';} use base 'Gtk3::Box'; diff --git a/simple_http.pm b/simple_http.pm deleted file mode 100644 index a03e8b6a..00000000 --- a/simple_http.pm +++ /dev/null @@ -1,228 +0,0 @@ -# Copyright (C) 2005-2011 Quentin Sculo -# -# This file is part of Gmusicbrowser. -# Gmusicbrowser is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation - -package Simple_http; -use strict; -use warnings; -use Socket;# 1.3; ? -use Fcntl; -use IO::Handle; - -use constant { EOL => "\015\012" }; -my %ipcache; #FIXME purge %ipcache from time to time -my $UseCache= *GMB::Cache::add{CODE}; - -my $gzip_ok; -BEGIN -{ eval { require IO::Uncompress::Gunzip; $gzip_ok=1; }; -} - -sub get_with_cb -{ my $self=bless {}; - my $error; - if (ref $_[0]) {$self=shift; $error='Too many redirections' if 5 < $self->{redirect}++; } - my %params=@_; - $self->{params}=\%params; - delete $params{cache} unless $UseCache; - my ($callback,$url,$post,$authtoken)=@params{qw/cb url post authtoken/}; - if (my $cached= $params{cache} && GMB::Cache::get($url)) - { warn "cached result\n" if $::debug; - Glib::Timeout->add(10,sub { $callback->( ${$cached->{data}}, type=>$cached->{type}, filename=>$cached->{filename}, ); 0}); - return $self; - } - warn "simple_http : fetching $url\n" if $::debug; - - my ($host,$port,$file); - my $socket; - { last if $error; - - if ( $url=~s#^([a-z]+)://## && $1 ne 'http' ) - { $error="Protocol $1 not supported"; last; } - ($host,$port,$file)= $url=~m#^([^/:]+)(?::(\d+))?(.*)$#; - if (defined $host) - { $port=80 unless defined $port; - $file='/' if $file eq ''; - } - else { $error='Bad url : http://'.$url; last; } - - my $proxyhost=$::Options{Simplehttp_ProxyHost}; - if ($::Options{Simplehttp_Proxy} && defined $proxyhost && $proxyhost ne '') - { $file="http://$host:".$port.$file; - $host=$proxyhost; - $port=$::Options{Simplehttp_ProxyPort}; - $port=80 unless defined $port && $port=~m/^\d+$/; - } - my $addr; - if ($host=~m#^\d+\.\d+\.\d+.\d+$#) {$addr=inet_aton($host);} - else { $addr=$ipcache{$host}||=inet_aton($host)}#FIXME not asynchronous, use a fork ? - unless ($addr) - { $error="Can't resolve host $host"; last; } - socket($socket, PF_INET, SOCK_STREAM, getprotobyname('tcp')); - my $paddr=pack_sockaddr_in(0, INADDR_ANY); - unless ( bind $socket,$paddr ) - { $error=$!; last; } - $self->{file}=$file; - $self->{port}=$port; - $self->{host}=$host; - my $sin=sockaddr_in($port,$addr); - fcntl $socket,F_SETFL,O_NONBLOCK; #unless $^O eq "MSWin32" - connect $socket,$sin; - } - $self->{sock}=$socket; - if (defined $error) - { $error="Cannot connect to server $host:$port : $error" if $host; - warn "$error\n"; - Glib::Timeout->add(10,sub { $callback->(undef,error=>$error); 0 }); - return $self; - } - $self->{buffer}=''; - $self->{watch}=Glib::IO->add_watch(fileno($socket),['out','hup'],\&connecting_cb,$self); - - return $self; -} - -sub connecting_cb -{ my $failed= ($_[1] >= 'hup'); #connection failed - my $self=$_[2]; - my $socket=$self->{sock}; - my $port=$self->{port}; - my $host=$self->{host}; - my $params= $self->{params}; - - if ($failed) - { warn "Cannot connect to server $host:$port\n"; - close $socket; - $params->{cb}(undef,error=>"Connection failed"); - return 0; - } - -#binmode $socket,':encoding(iso-8859-1)'; - my $post=$params->{post}; - my $method=defined $post ? 'POST' : 'GET'; - my $useragent= $params->{user_agent} || 'Mozilla/5.0'; - my $accept= $params->{'accept'} || ''; - print $socket "$method $self->{file} HTTP/1.0".EOL; - print $socket "Host: $host:$port".EOL; - print $socket "User-Agent: $useragent".EOL; - print $socket "Referer: $params->{referer}".EOL if $params->{referer}; - print $socket "Authorization: Token $params->{authtoken}".EOL if $params->{authtoken}; - print $socket "Accept: $accept".EOL; - print $socket "Accept-Encoding: gzip".EOL if $gzip_ok; - #print $socket "Connection: Keep-Alive".EOL; - if (defined $post) - { if ($params->{authtoken}) { - print $socket 'Content-Type: application/json'.EOL; - } else { - print $socket 'Content-Type: application/x-www-form-urlencoded; charset=utf-8'.EOL; - } - print $socket "Content-Length: ".length($post).EOL.EOL; - print $socket $post.EOL; - } - print $socket EOL; - - $socket->autoflush(1); - $self->{buffer}=''; - $self->{watch}=Glib::IO->add_watch(fileno($socket),['in','hup'],\&receiving_cb,$self); - - return 0; -} - -sub progress -{ my $self=shift; - my ($length)= $self->{buffer}=~m/\015\012Content-Length:\s*(\d+)\015\012/i; - my $pos= index $self->{buffer}, EOL.EOL; - my $progress; - my $size=0; - if ($pos>=0) - { $size=length($self->{buffer})-2-$pos; - if ($length) - { $progress= $size/$length; - $progress=undef if $progress>1; - } - } - # $progress is undef or between 0 and 1 - return $progress,$size; -} - -sub receiving_cb -{ my $self=$_[2]; - return 1 if read $self->{sock},$self->{buffer},1024,length($self->{buffer}); - close $self->{sock}; - $self->{sock}=$self->{watch}=undef; - #warn "watch done\n"; - my $url=$self->{params}{url}; - my $callback=$self->{params}{cb}; - my $EOL=EOL; - my ($headers,$response)=split /$EOL$EOL/o,delete $self->{buffer},2; - $headers='empty answer' unless defined $headers; - (my$result,$headers)=split /$EOL/o,$headers,2; - if ($::debug) - { warn "0|$_\n" for $result,split /$EOL/o,$headers; - } - $headers.=EOL; - my %headers; - $headers{lc $1}=$2 while $headers=~m/([^:]*): (.*?)$EOL/og; - - my $filename; - if ($headers{'content-disposition'} && $headers{'content-disposition'}=~m#^\s*\w+\s*;\s*filename(\*)?=(.*)$#mgi) - { $filename=$2; my $rfc5987=$1; - #decode filename, not perfectly, but good enough (http://greenbytes.de/tech/tc2231/ is a good reference) - $filename=~s#\\(.)#"\x00".ord($1)."\x00"#ge; - my $enc='iso-8859-1'; - if ($rfc5987 && $filename=~s#^([A-Za-z0-9_-]+)'\w*'##) {$enc=$1; $filename=::decode_url($filename)} #RFC5987 - else - { if ($filename=~s/^"(.*)"$/$1/) { $filename=~s#\x00(\d+)\x00#chr($1)#ge; $filename=~s#\\(.)#"\x00".ord($1)."\x00"#ge; } - elsif ($filename=~m#[^A-Za-z0-9_.\x00-]#) {$filename=''} - } - $filename=~s#\x00(\d+)\x00#chr($1)#ge; - $filename= eval {Encode::decode($enc,$filename)}; - } - if (my $enc=$headers{'content-encoding'}) - { if ($enc eq 'gzip' && $gzip_ok) - { my $gzipped= $response; - IO::Uncompress::Gunzip::gunzip( \$gzipped, \$response ) - or do {warn "simple_http : gunzip failed: $IO::Uncompress::Gunzip::GunzipError\n"; $result='gunzip error';}; - } - else - { warn "simple_http_wget : can't decode '$enc' encoding\n"; - $result='gzipped'; - } - } - if ($result=~m#^HTTP/1\.\d+ 200 OK#) - { #warn "ok $url\n$callback\n"; - my $type=$headers{'content-type'}; - if ($self->{params}{cache} && defined $response) - { GMB::Cache::add($url,{data=>\$response,type=>$type,size=>length($response),filename=>$filename}); - } - $callback->($response, type=>$type, url=>$self->{params}{url}, filename=>$filename); - } - elsif ($result=~m#^HTTP/1\.\d+ 30[123]# && $headers{location}) #redirection - { my $url=$headers{location}; - unless ($url=~m#^http://#) - { my $base=$self->{params}{url}; - if ($url=~m#^/#){$base=~s#^(?:http://)?([^/]+).*$#$1#;} - else {$base=~s#[^/]*$##;} - $url=$base.$url; - } - $self->{params}{url}=$url; - $self->get_with_cb( %{$self->{params}} ); - } - else - { warn "Error fetching $url : $result\n"; - $callback->(undef,error=>$result); - } - return 0; -} - -sub abort -{ my $self=$_[0]; - Glib::Source->remove($self->{watch}) if defined $self->{watch}; - close $self->{sock} if defined $self->{sock}; - $self->{sock}=$self->{watch}=undef; -} - -1; diff --git a/simple_http_AE.pm b/simple_http_AE.pm deleted file mode 100644 index f670b9bb..00000000 --- a/simple_http_AE.pm +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright (C) 2010-2011 Quentin Sculo -# -# This file is part of Gmusicbrowser. -# Gmusicbrowser is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation - -package Simple_http; -use strict; -use warnings; -use AnyEvent::HTTP; -my $UseCache= *GMB::Cache::add{CODE}; - -my $gzip_ok; -BEGIN -{ eval { require IO::Uncompress::Gunzip; $gzip_ok=1; }; -} - -sub get_with_cb -{ my $self=bless {}; - my %params=@_; - $self->{params}=\%params; - my ($callback,$url,$post)=@params{qw/cb url post/}; - delete $params{cache} unless $UseCache; - if (my $cached= $params{cache} && GMB::Cache::get($url)) - { warn "cached result\n" if $::debug; - Glib::Timeout->add(10,sub { $callback->( ${$cached->{data}}, type=>$cached->{type}, filename=>$cached->{filename}, ); 0}); - return $self; - } - warn "simple_http_AE : fetching $url\n" if $::debug; - - my $proxy= $::Options{Simplehttp_Proxy} ? $::Options{Simplehttp_ProxyHost}.':'.($::Options{Simplehttp_ProxyPort}||3128) - : $ENV{http_proxy}; - AnyEvent::HTTP::set_proxy($proxy); - - my %headers; - $headers{'Content-Type'}= 'application/x-www-form-urlencoded; charset=utf-8' if $post; - $headers{'Referer'}= $params{referer} if $params{referer}; - $headers{'User-Agent'}= $params{user_agent} || 'Mozilla/5.0'; - $headers{Accept}= $params{'accept'} || ''; - $headers{'Accept-Encoding'}= $gzip_ok ? 'gzip' : ''; - my $method= $post ? 'POST' : 'GET'; - my @args; - push @args, body => $post if $post; - if ($params{progress}) # enable progress info via progress() - { push @args, on_header=> sub { $self->{content_length}=$_[0]{"content-length"}; $self->{content}=''; 1; }, - on_body => sub { $self->{content}.= $_[0]; 1; }; - } - $self->{request}= http_request( $method, $url, @args, headers=>\%headers, sub { $self->finished(@_) } ); - return $self; -} - -sub finished -{ my ($self,$response,$headers)=@_; - $response= $self->{content} if exists $self->{content}; - my $url= $self->{params}{url}; - my $callback= $self->{params}{cb}; - delete $_[0]{request}; - #warn "$_=>$headers->{$_}\n" for sort keys %$headers; - my $filename; - if ($headers->{'content-disposition'} && $headers->{'content-disposition'}=~m#^\s*\w+\s*;\s*filename(\*)?=(.*)$#mgi) - { $filename=$2; my $rfc5987=$1; - #decode filename, not perfectly, but good enough (http://greenbytes.de/tech/tc2231/ is a good reference) - $filename=~s#\\(.)#"\x00".ord($1)."\x00"#ge; - my $enc='iso-8859-1'; - if ($rfc5987 && $filename=~s#^([A-Za-z0-9_-]+)'\w*'##) {$enc=$1; $filename=::decode_url($filename)} #RFC5987 - else - { if ($filename=~s/^"(.*)"$/$1/) { $filename=~s#\x00(\d+)\x00#chr($1)#ge; $filename=~s#\\(.)#"\x00".ord($1)."\x00"#ge; } - elsif ($filename=~m#[^A-Za-z0-9_.\x00-]#) {$filename=''} - } - $filename=~s#\x00(\d+)\x00#chr($1)#ge; - $filename= eval {Encode::decode($enc,$filename)}; - } - if (my $enc=$headers->{'content-encoding'}) - { if ($enc eq 'gzip' && $gzip_ok) - { my $gzipped= $response; - IO::Uncompress::Gunzip::gunzip( \$gzipped, \$response ) - or do {warn "simple_http : gunzip failed: $IO::Uncompress::Gunzip::GunzipError\n"; $headers->{Status}='gunzip error'; $headers->{Reason}='';}; - } - else - { warn "simple_http : can't decode '$enc' encoding\n"; - $headers->{Status}='encoded'; $headers->{Reason}=''; - } - } - if ($headers->{Reason} eq 'OK') # and $headers->{Status} == 200 ? - { my $type= $headers->{'content-type'}; - if ($self->{params}{cache} && defined $response) - { GMB::Cache::add($url,{data=>\$response,type=>$type,size=>length($response),filename=>$filename}); - } - $callback->($response,type=>$type,url=>$self->{params}{url},filename=>$filename); - } - else - { my $error= $headers->{Status}.' '.$headers->{Reason}; - warn "Error fetching $url : $error\n"; - $callback->(undef,error=>$error); - } -} - -sub progress -{ my $self=shift; - my $length= $self->{content_length}; - return $length,0 unless exists $self->{content}; - my $size= length $self->{content}; - my $progress; - if ($length && $size) - { $progress= $size/$length; - $progress=undef if $progress>1; - } - # $progress is undef or between 0 and 1 - return $progress,$size; -} - -sub abort -{ delete $_[0]{request}; -} - -1; From 82543a6f7894f0b2992cf542ee71033d2c2afe11 Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Fri, 4 Apr 2025 16:51:36 +0300 Subject: [PATCH 10/20] Remove duplicate timer removal, fixes non-critical Glib-critical warning --- plugins/listenbrainz.pm | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/listenbrainz.pm b/plugins/listenbrainz.pm index 138b12cb..01c6dcf0 100644 --- a/plugins/listenbrainz.pm +++ b/plugins/listenbrainz.pm @@ -203,7 +203,6 @@ sub Submit sub SendNow { $interval=10; $Stop=undef; - Glib::Source->remove($timeout) if $timeout; Awake(); } From bc0fa6918ee44f097c143d9603e56ef6591fc383 Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Fri, 4 Apr 2025 22:39:01 +0300 Subject: [PATCH 11/20] Rewrite http post with LWP --- debian/control | 2 +- plugins/listenbrainz.pm | 74 +++++++++-------------------- simple_http_wget.pm | 100 ++++++++++++++++------------------------ 3 files changed, 65 insertions(+), 111 deletions(-) diff --git a/debian/control b/debian/control index 2459fbc6..c2a2c98a 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ Standards-Version: 3.7.3 Package: gmusicbrowser Architecture: all Depends: perl, libgtk3-perl, libgtk-3-0 -Recommends: libintl-perl, libnet-dbus-perl, libglib-object-introspection-perl, gir1.2-gstreamer-1.0, libdigest-crc-perl, libhtml-parser-perl, libio-compress-perl, wget +Recommends: libintl-perl, libnet-dbus-perl, libglib-object-introspection-perl, gir1.2-gstreamer-1.0, libdigest-crc-perl, libhtml-parser-perl, libio-compress-perl, libwww-perl, wget Suggests: mpv, mplayer, mpg123, vorbis-tools, alsa-utils, gir1.2-webkit2, gir1.2-notify, gir1.2-wnck, gir1.2-poppler Description: very customizable jukebox for large collections of music files The interface is extremely customizable. It has easy access to related songs diff --git a/plugins/listenbrainz.pm b/plugins/listenbrainz.pm index 094f25c2..23302492 100644 --- a/plugins/listenbrainz.pm +++ b/plugins/listenbrainz.pm @@ -28,7 +28,7 @@ our $ignore_current_song; my $self=bless {},__PACKAGE__; my @ToSubmit; my @NowPlaying; my $NowPlayingID; -my $interval=10; my ($timeout,$waiting); +my $interval=10; my ($timeout); my ($Stop); my $Log= Gtk3::ListStore->new('Glib::String'); @@ -43,9 +43,8 @@ sub Start sub Stop { @NowPlaying=undef; - $waiting->abort if $waiting; Glib::Source->remove($timeout) if $timeout; - $timeout=$waiting=undef; + $timeout=undef; ::UnWatch($self,$_) for qw/PlayingSong Played/; $self->{on}=undef; $interval=10; @@ -76,21 +75,8 @@ sub prefbox $qbox->{label}=$queue; $qbox->{button}=$sendnow; $qbox->show_all; - update_queue_label($qbox); - $qbox->set_no_show_all(1); - ::Watch($qbox,Listenbrainz_state_change=>\&update_queue_label); return $vbox; } -sub update_queue_label -{ my $qbox=shift; - my $label= $qbox->{label}; - if (@ToSubmit && (!$waiting && (!$timeout || $interval>10))) - { $label->set_text(::__n("song waiting to be sent")); - $label->get_parent->show; - $qbox->{button}->set_sensitive(!$waiting); - } - else { $label->get_parent->hide } -} sub SongChanged { @@ -145,11 +131,9 @@ sub Submit listen_type => $listen_type, payload => [ { - #listened_at => $listened_at, track_metadata => { artist_name => $payload[0], track_name => $payload[1] - #release_name => $payload[2] } } ] @@ -158,41 +142,30 @@ sub Submit $post->{payload}[0]->{track_metadata}->{release_name} = $payload[2] if $payload[2]; my $response_cb=sub { - my ($response,@lines)=@_; - my $error; - if (!defined $response) {$error=_"connection failed";} - elsif ($response eq '{"status":"ok"}') - { unlink $::HomeDir.SAVEFILE; - if (@ToSubmit) { - Log( _("Submit OK ") . - ::__x( _"{song} by {artist}", song=> $payload[1], artist => $payload[0]) ); - undef @ToSubmit; - undef $waiting; - $interval=10; - return - }; - if (@NowPlaying) { - Log( _("NowPlaying OK ") . - ::__x( _"{song} by {artist}", song=> $payload[1], artist => $payload[0]) ); - $interval=60; - undef $waiting; - return - }; - } - elsif ($response eq 'BADSESSION') - { $error=_"Bad session"; - } - elsif ($response=~m/^FAILED (.*)$/) - { $error=$1; - } - else {$error=_"unknown error";} + my ($response,$error)=@_; - if (defined $error) + if ($error) { Log(_("Submit failed : ").$error); Log(_("Response : ").$response) if $response; $interval*=2; $interval=max($interval, 300); + return; } + + unlink $::HomeDir.SAVEFILE; + if (@ToSubmit) { + Log( _("Submit OK ") . + ::__x( _"{song} by {artist}", song=> $payload[1], artist => $payload[0]) ); + undef @ToSubmit; + $interval=10; + return + }; + if (@NowPlaying) { + Log( _("NowPlaying OK ") . + ::__x( _"{song} by {artist}", song=> $payload[1], artist => $payload[0]) ); + $interval=60; + return + }; }; my $authtoken=$::Options{OPT.'TOKEN'}; @@ -209,14 +182,14 @@ sub SendNow sub Sleep { return unless $self->{on}; ::QHasChanged('Listenbrainz_state_change'); - return if $Stop || $waiting || $timeout; + return if $Stop || $timeout; $timeout=Glib::Timeout->add(1000*$interval,\&Awake) if @ToSubmit || @NowPlaying; } sub Awake { Glib::Source->remove($timeout) if $timeout; $timeout=undef; - return 0 if !$self->{on} || $waiting; + return 0 if !$self->{on}; Submit(); Sleep(); return 0; @@ -226,12 +199,11 @@ sub Send { my ($response_cb,$url,$post,$authtoken)=@_; my $cb=sub { my @response=(defined $_[0])? split "\012",$_[0] : (); - $waiting=undef; &$response_cb(@response); Sleep(); }; - $waiting=Simple_http::get_with_cb(cb => $cb,url => $url,post => $post,authtoken => $authtoken); + Simple_http::post_with_cb(cb => $cb,url => $url,post => $post,authtoken => $authtoken); ::QHasChanged('Listenbrainz_state_change'); } diff --git a/simple_http_wget.pm b/simple_http_wget.pm index d71eb154..7574905d 100644 --- a/simple_http_wget.pm +++ b/simple_http_wget.pm @@ -8,14 +8,43 @@ package Simple_http; use strict; use warnings; -use POSIX ':sys_wait_h'; #for WNOHANG in waitpid -use IO::Handle; - -my $UseCache= *GMB::Cache::add{CODE}; -my $orig_proxy=$ENV{http_proxy}; -my $gzip_ok; -BEGIN -{ eval { require IO::Uncompress::Gunzip; $gzip_ok=1; }; +use LWP::UserAgent; + +my $proxy= $::Options{Simplehttp_Proxy} + ? $::Options{Simplehttp_ProxyHost}.':'.($::Options{Simplehttp_ProxyPort}||3128) + : ''; + +sub post_with_cb +{ + my $self=bless {}; + my %params=@_; + $self->{params}=\%params; + my ($callback,$url,$post,$authtoken)=@params{qw/cb url post authtoken/}; + + my $ua = LWP::UserAgent->new(); + #$ua->agent('Mozilla/5.0'); + $ua->default_header('Authorization' => "Token $authtoken") if $authtoken; + $ua->default_header('Content-Type' => 'application/json') if $authtoken; + $ua->proxy("https", "connect://$proxy/") if $proxy; + $ua->timeout(40); + + open my $fh, '<', $post or die "failed to open: $!"; + my $content = do { local $/; <$fh> }; + close $fh; + + my $response = $ua->post($url, + Content_Type => 'application/json', + Content => $content ); + + my $result = $response->decoded_content; + if ($response->is_success) { + $callback->($result, error=>undef); + } + else { + warn "Error fetching $url : $result\n"; + warn $response->status_line; + $callback->($response->status_line, error=>$result); + } } sub get_with_cb @@ -23,22 +52,11 @@ sub get_with_cb my %params=@_; $self->{params}=\%params; my ($callback,$url,$post,$authtoken)=@params{qw/cb url post authtoken/}; - delete $params{cache} unless $UseCache; - if (my $cached= $params{cache} && GMB::Cache::get($url)) - { warn "cached result\n" if $::debug; - Glib::Timeout->add(10,sub { $callback->( ${$cached->{data}}, type=>$cached->{type}, filename=>$cached->{filename}, ); 0}); - return $self; - } warn "simple_http_wget : fetching $url\n" if $::debug; - my $proxy= $::Options{Simplehttp_Proxy} ? $::Options{Simplehttp_ProxyHost}.':'.($::Options{Simplehttp_ProxyPort}||3128) - : $orig_proxy; - $ENV{http_proxy}=$proxy; - my $cmd_and_args= 'wget --timeout=40 -S -O -'; $cmd_and_args.= " -U ".($params{user_agent} || "'Mozilla/5.0'"); - $cmd_and_args.= " --header='Accept-Encoding: gzip'" if $gzip_ok; $cmd_and_args.= " --header='Authorization: Token ".$authtoken."'" if $authtoken; $cmd_and_args.= " --header='Content-Type: application/json'" if $authtoken; $cmd_and_args.= " --referer=$params{referer}" if $params{referer}; @@ -72,12 +90,15 @@ sub get_with_cb return $self; } +#private sub receiving_e_cb { my $self=$_[2]; return 1 if read $self->{error_fh},$self->{ebuffer},1024,length($self->{ebuffer}); close $self->{error_fh}; return $self->{ewatch}=0; } + +#private sub receiving_cb { my $self=$_[2]; return 1 if read $self->{content_fh},$self->{content},1024,length($self->{content}); @@ -94,7 +115,7 @@ sub receiving_cb my $filename; while ($self->{ebuffer}=~m#^ Content-Disposition:\s*\w+\s*;\s*filename(\*)?=(.*)$#mgi) { $filename=$2; my $rfc5987=$1; - #decode filename, not perfectly, but good enough (http://greenbytes.de/tech/tc2231/ is a good reference) + $filename=~s#\\(.)#"\x00".ord($1)."\x00"#ge; my $enc='iso-8859-1'; if ($rfc5987 && $filename=~s#^([A-Za-z0-9_-]+)'\w*'##) {$enc=$1; $filename=::decode_url($filename)} #RFC5987 @@ -105,24 +126,9 @@ sub receiving_cb $filename=~s#\x00(\d+)\x00#chr($1)#ge; $filename= eval {Encode::decode($enc,$filename)}; } - my ($enc)= $self->{ebuffer}=~m#^ Content-Encoding:\s*(.*)#mg; - if ($enc) - { if ($enc eq 'gzip' && $gzip_ok) - { my $gzipped= $self->{content}; - IO::Uncompress::Gunzip::gunzip( \$gzipped, \$self->{content} ) - or do {warn "simple_http_wget : gunzip failed: $IO::Uncompress::Gunzip::GunzipError\n"; $result='gunzip error';}; - } - else - { warn "simple_http_wget : can't decode '$enc' encoding\n"; - $result='encoded'; - } - } if ($result=~m#^HTTP/1\.\d+ 200 OK#) { my $response=\$self->{content}; - if ($self->{params}{cache} && defined $$response) - { GMB::Cache::add($url,{data=>$response,type=>$type,size=>length($$response),filename=>$filename}); - } $callback->($$response,type=>$type,url=>$self->{params}{url},filename=>$filename); } else @@ -132,28 +138,4 @@ sub receiving_cb return $self->{watch}=0; } -sub progress -{ my $self=shift; - my $length; - $length=$1 while $self->{ebuffer}=~m/Content-Length:\s*(\d+)/ig; - my $size= length $self->{content}; - my $progress; - if ($length && $size) - { $progress= $size/$length; - $progress=undef if $progress>1; - } - # $progress is undef or between 0 and 1 - return $progress,$size; -} - -sub abort -{ my $self=$_[0]; - Glib::Source->remove($self->{watch}) if $self->{watch}; - Glib::Source->remove($self->{ewatch}) if $self->{ewatch}; - kill INT=>$self->{pid} if $self->{pid}; - close $self->{content_fh} if defined $self->{content_fh}; - close $self->{error_fh} if defined $self->{error_fh}; - $self->{pid}=$self->{content_fh}=$self->{error_fh}=$self->{watch}=$self->{ewatch}=undef; -} - 1; From e39803939cb105ebd7a5a22579b03478a2b9c853 Mon Sep 17 00:00:00 2001 From: Carl di Ortus Date: Fri, 4 Apr 2025 23:16:45 +0300 Subject: [PATCH 12/20] Rewrite http get with LWP, drop wget dependency --- debian/control | 2 +- gmusicbrowser.pl | 9 +--- plugins/albuminfo.pm | 16 +++---- plugins/artistinfo.pm | 12 ++--- plugins/audioscrobbler.pm | 17 ++++--- plugins/fetch_cover.pm | 26 +++-------- plugins/lyrics.pm | 42 +++--------------- plugins/webcontext.pm | 4 +- simple_http_wget.pm | 93 ++++++--------------------------------- 9 files changed, 45 insertions(+), 176 deletions(-) diff --git a/debian/control b/debian/control index c2a2c98a..39d3daf5 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ Standards-Version: 3.7.3 Package: gmusicbrowser Architecture: all Depends: perl, libgtk3-perl, libgtk-3-0 -Recommends: libintl-perl, libnet-dbus-perl, libglib-object-introspection-perl, gir1.2-gstreamer-1.0, libdigest-crc-perl, libhtml-parser-perl, libio-compress-perl, libwww-perl, wget +Recommends: libintl-perl, libnet-dbus-perl, libglib-object-introspection-perl, gir1.2-gstreamer-1.0, libdigest-crc-perl, libhtml-parser-perl, libio-compress-perl, libwww-perl Suggests: mpv, mplayer, mpg123, vorbis-tools, alsa-utils, gir1.2-webkit2, gir1.2-notify, gir1.2-wnck, gir1.2-poppler Description: very customizable jukebox for large collections of music files The interface is extremely customizable. It has easy access to related songs diff --git a/gmusicbrowser.pl b/gmusicbrowser.pl index 5bbfcf65..c8a9cef7 100755 --- a/gmusicbrowser.pl +++ b/gmusicbrowser.pl @@ -10304,19 +10304,13 @@ sub Start { warn "Downloading '$display_uri' to '$destpath'\n" if $::debug; ::Progress( $progressid, bartext_append=>$display_uri, title=>_"Downloading"); - $self->{waiting}= Simple_http::get_with_cb(url => $uri, cache=>1, progress=>1, cb => sub { $self->Downloaded(@_); }); - $self->{track_progress} ||= Glib::Timeout->add(200, - sub { if (my $w= $self->{waiting}) { my ($p,$s)=$w->progress; ::Progress( $progressid, partial=>$p ) if defined $p; } - else { $self->{track_progress}=0 } - return $self->{track_progress}; - }); + Simple_http::get_with_cb(url => $uri, cb => sub { $self->Downloaded(@_); }); return } } sub Downloaded { my ($self,$content,%content_prop)=@_; - delete $self->{waiting}; my $type=$content_prop{type}; my $params= $self->{current}; my $uri= $params->{uri}; @@ -10404,7 +10398,6 @@ sub Done # file done, if no $self->{newfile} it means the file has been skipped } sub Abort # GMB::DropURI object must not be used after that { my $self=shift; - $self->{waiting}->abort if $self->{waiting}; Glib::Source->remove( $self->{track_progress} ) if $self->{track_progress}; ::Progress( 'DropURI_'.$self, abort=>1 ); $self->{cb_end}() if $self->{cb_end}; diff --git a/plugins/albuminfo.pm b/plugins/albuminfo.pm index dba07eae..94e73a92 100644 --- a/plugins/albuminfo.pm +++ b/plugins/albuminfo.pm @@ -153,7 +153,7 @@ sub download_one { } else { my $url = AMG_SEARCH_URL.::url_escapeall($album); warn "Albuminfo: fetching search results from $url\n" if $::debug; - $self->{waiting} = Simple_http::get_with_cb(url=>$url, cache=>1, cb=>sub {$self->load_search_results($ID,1,\&download_one,@_)}); + Simple_http::get_with_cb(url=>$url, cb=>sub {$self->load_search_results($ID,1,\&download_one,@_)}); } } @@ -512,12 +512,11 @@ sub new_search { $self->cancel(); $self->{treeview}->get_model->clear; warn "Albuminfo: fetching search results from $url.\n" if $::debug; - $self->{waiting} = Simple_http::get_with_cb(cb=>sub {$self->print_results(@_)},url=>$url, cache=>1); + Simple_http::get_with_cb(cb=>sub {$self->print_results(@_)},url=>$url); } sub print_results { my ($self,$html,%prop) = @_; - delete $self->{waiting}; my $result = parse_amg_search_results($html, $prop{type}); # result is a ref to an array of hash refs my $store= $self->{treeview}->get_model; $store->set_sort_column_id(5, 'ascending'); @@ -534,8 +533,8 @@ sub entry_selected_cb { my $url = $store->get($store->get_iter($path),4); warn "Albuminfo: fetching review from $url\n" if $::debug; $self->cancel(); - $self->{waiting} = Simple_http::get_with_cb(cb=>sub {$self->{searchview}->hide(); $self->{infoview}->show(); - $self->load_review(::GetSelID($self),0,undef,$url,@_)}, url=>$url, cache=>1); + Simple_http::get_with_cb(cb=>sub {$self->{searchview}->hide(); $self->{infoview}->show(); + $self->load_review(::GetSelID($self),0,undef,$url,@_)}, url=>$url); } @@ -580,7 +579,7 @@ sub album_changed { } } warn "Albuminfo: fetching search results from $url\n" if $::debug; - $self->{waiting} = Simple_http::get_with_cb(cb=>sub {$self->load_search_results($ID,0,undef,@_)}, url=>$url, cache=>1); + Simple_http::get_with_cb(cb=>sub {$self->load_search_results($ID,0,undef,@_)}, url=>$url); } sub update_titlebox { @@ -600,7 +599,6 @@ sub update_titlebox { sub load_search_results { my ($self,$ID,$md,$cb,$html,%prop) = @_; # $md = 1 if mass_download, 0 otherwise. $cb = callback function if mass_download, undef otherwise. - delete $self->{waiting}; my $result = parse_amg_search_results($html, $prop{type}); # $result[$i] = {url, album, artist, genres, year} my ($artist,$year) = ::Songs::Get($ID, qw/artist year/); my $url; @@ -616,7 +614,7 @@ sub load_search_results { } if ($url) { warn "Albuminfo: fetching review from $url\n" if $::debug; - $self->{waiting} = Simple_http::get_with_cb(cb=>sub {$self->load_review($ID,$md,$cb,$url,@_)}, url=>$url, cache=>1); + Simple_http::get_with_cb(cb=>sub {$self->load_review($ID,$md,$cb,$url,@_)}, url=>$url); } else { $self->{fields} = {}; warn "Albuminfo: album not found in search results\n" if $::debug; @@ -627,7 +625,6 @@ sub load_search_results { sub load_review { my ($self,$ID,$md,$cb,$url,$html,%prop) = @_; - delete $self->{waiting}; $self->{fields} = parse_amg_album_page($url,$html,$prop{type}); $self->print_review() unless $md; save_review($ID, $self->{fields}) if $::Options{OPT.'AutoSave'} || $md; @@ -804,7 +801,6 @@ sub cancel { my $self = shift; delete $::ToDo{'9_load_albuminfo'.$self}; delete $::ToDo{'9_refresh_albuminfo'.$self}; - $self->{waiting}->abort() if $self->{waiting}; ::Progress('albuminfo', abort=>1); $self->{abort}=1; } diff --git a/plugins/artistinfo.pm b/plugins/artistinfo.pm index a89bab85..8512a4f9 100644 --- a/plugins/artistinfo.pm +++ b/plugins/artistinfo.pm @@ -49,7 +49,6 @@ my %menuitem= test => sub {$_[0]{mainfield} eq 'artist'}, #the menu item is displayed if returns true ); my $nowplayingaID; -my $queuewaiting; my %queuemode= ( order=>10, icon=>'gtk-refresh', short=> _"similar-artists", long=> _"Auto-fill queue with similar artists (from last.fm)", changed=>\&QAutofillSimilarArtists, keep=>1,save=>1,autofill=>1, ); @@ -97,7 +96,6 @@ sub Stop { Layout::RegisterWidget(PluginArtistinfo => undef); @::cMenuAA= grep $_!=\%menuitem, @::SongCMenu; delete $::QActions{'autofill-similar-artists'}; ::Update_QueueActionList(); - $queuewaiting->abort if $queuewaiting; $queuewaiting=undef; } sub new @@ -271,7 +269,6 @@ sub destroy_event_cb sub cancel { my $self=shift; delete $::ToDo{'8_artistinfo'.$self}; - $self->{waiting}->abort if $self->{waiting}; } sub prefbox @@ -506,12 +503,11 @@ sub load_url warn "info : loading $url\n" if $::debug; $self->{url}=$url; $self->{sw2}->hide; $self->{sw1}->show; - $self->{waiting}=Simple_http::get_with_cb(cb => sub {$self->loaded(@_)},url => $url, cache => 1); + Simple_http::get_with_cb(cb => sub {$self->loaded(@_)},url => $url); } sub loaded { my ($self,$data,%prop)=@_; - delete $self->{waiting}; my $buffer=$self->{buffer}; my $type=$prop{type}; unless ($data) { $data=_("Loading failed.").qq( )._("retry").''; $type="text/html"; } @@ -669,7 +665,7 @@ sub Save_text } sub QAutofillSimilarArtists -{ $queuewaiting->abort if $queuewaiting; $queuewaiting=undef; +{ return unless $::QueueAction eq 'autofill-similar-artists'; return if $::Options{MaxAutoFill}<=@$::Queue; return unless $::SongID; @@ -679,11 +675,11 @@ sub QAutofillSimilarArtists my $url = GetUrl($sites{similar}[0],$nowplayingaID); return unless $url; - $queuewaiting=Simple_http::get_with_cb(url => $url, cb => \&PopulateQueue ); + Simple_http::get_with_cb(url => $url, cb => \&PopulateQueue ); } sub PopulateQueue -{ $queuewaiting=undef; +{ if ( $nowplayingaID != Songs::Get_gid($::SongID,'artist')) { QAutofillSimilarArtists; return; } my $data = $_[0]; diff --git a/plugins/audioscrobbler.pm b/plugins/audioscrobbler.pm index 4842018f..3411dced 100644 --- a/plugins/audioscrobbler.pm +++ b/plugins/audioscrobbler.pm @@ -27,7 +27,7 @@ our $ignore_current_song; my $self=bless {},__PACKAGE__; my @ToSubmit; my $NowPlaying; my $NowPlayingID; my $unsent_saved=0; -my $interval=5; my ($timeout,$waiting); +my $interval=5; my $timeout; my ($HandshakeOK,$submiturl,$nowplayingurl,$sessionid); my ($Serrors,$Stop); my $Log= Gtk3::ListStore->new('Glib::String'); @@ -43,9 +43,9 @@ sub Start $Serrors=$Stop=undef; } sub Stop -{ $waiting->abort if $waiting; +{ Glib::Source->remove($timeout) if $timeout; - $timeout=$waiting=undef; + $timeout=undef; ::UnWatch($self,$_) for qw/PlayingSong Played Save/; $self->{on}=undef; $interval=5; @@ -86,10 +86,10 @@ sub prefbox sub update_queue_label { my $qbox=shift; my $label= $qbox->{label}; - if (@ToSubmit && (@ToSubmit>1 || (!$waiting && (!$timeout || $interval>10)))) + if (@ToSubmit && (@ToSubmit>1 || (!$timeout || $interval>10))) { $label->set_text(::__n("%d song waiting to be sent","%d songs waiting to be sent", scalar @ToSubmit )); $label->get_parent->show; - $qbox->{button}->set_sensitive(!$waiting); + $qbox->{button}->set_sensitive(); } else { $label->get_parent->hide } } @@ -236,14 +236,14 @@ sub Sleep { #warn "Sleep\n"; return unless $self->{on}; ::QHasChanged('Lastfm_state_change'); - return if $Stop || $waiting || $timeout; + return if $Stop || $timeout; $timeout=Glib::Timeout->add(1000*$interval,\&Awake) if @ToSubmit || $NowPlaying; #warn "Sleeping $interval seconds\n" if $timeout; } sub Awake { #warn "Awoke\n"; $timeout=undef; - return 0 if !$self->{on} || $waiting; + return 0 if !$self->{on}; if ($HandshakeOK) { Submit(); } else { Handshake(); } Sleep(); @@ -253,11 +253,10 @@ sub Send { my ($response_cb,$url,$post)=@_; my $cb=sub { my @response=(defined $_[0])? split "\012",$_[0] : (); - $waiting=undef; &$response_cb(@response); Sleep(); }; - $waiting=Simple_http::get_with_cb(cb => $cb,url => $url,post => $post); + Simple_http::post_with_cb(cb => $cb,url => $url,post => $post); ::QHasChanged('Lastfm_state_change'); } diff --git a/plugins/fetch_cover.pm b/plugins/fetch_cover.pm index b67498b2..fe84f60e 100644 --- a/plugins/fetch_cover.pm +++ b/plugins/fetch_cover.pm @@ -205,11 +205,7 @@ sub NewSearch $self->{url}= $url; $self->{searchcontext}={}; #hash that the parser can use to store data between searches warn "fetchcover : loading $url\n" if $::debug; - $self->{waiting}=Simple_http::get_with_cb - ( cb => sub {$self->searchresults_cb(@_)}, - url => $url, cache=>1, - user_agent => $self->{user_agent}, - ); + Simple_http::get_with_cb(cb => sub {$self->searchresults_cb(@_)}, url => $url); } sub InitPage @@ -410,7 +406,6 @@ sub parse_discogs sub searchresults_cb { my ($self,$result)=@_; - $self->{waiting}=undef; warn "Getting results from $self->{url}\n" if $::Verbose; unless (defined $result) { stop($self,_"connection failed."); return; } my $parse= $Sites{$self->{mainfield}}{$self->{site}}[2]; @@ -429,10 +424,7 @@ sub abort my $results=$self->{results}; for my $r ($self,@$results) { delete $r->{done}; - $r->{waiting}->abort if $r->{waiting}; - delete $r->{waiting}; } - delete $self->{waiting}; delete $::ToDo{'8_FetchCovers'.$self}; } @@ -453,41 +445,33 @@ sub get_next { my $self=shift; my $results=$self->{results}; my $res_id; - my $waiting; my $start= $self->{page} * RES_PER_PAGE; my $end= $start + RES_PER_PAGE -1; if ($#$results<$end && $self->{nexturl}) { #load next page my $url= $self->{url}= delete $self->{nexturl}; - $self->{waiting}=Simple_http::get_with_cb - ( cb => sub {$self->searchresults_cb(@_)}, - url => $url, cache=>1, - user_agent => $self->{user_agent}, - ); + Simple_http::get_with_cb(cb => sub {$self->searchresults_cb(@_)}, url => $url); } elsif ($#$results>=$end) { $self->{Bnext}->set_sensitive(1); } $end=$#$results if $#$results<$end; for my $id ($start .. $end) - { #warn "$id : waiting=".$results->[$id]{waiting}." done=".$results->[$id]{done}; - if ($results->[$id]{waiting}) {$waiting++; next}; + { next if $results->[$id]{done}; $res_id=$id; last; } - unless (defined $res_id || $waiting || $self->{waiting}) + unless (defined $res_id) { $self->stop; return; } return unless defined $res_id; - return if $waiting && $waiting > 3; #no more than 4 pictures at once my $result=$self->{results}[$res_id]; - $result->{waiting}=Simple_http::get_with_cb(url => $result->{url}, referer=>$result->{referer}, cache=>1, cb => + Simple_http::get_with_cb(url => $result->{url}, referer=>$result->{referer}, cb => sub { my $pixdata=$_[0]; - $result->{waiting}=undef; my $loader; $loader= GMB::Picture::LoadPixData($pixdata,PREVIEW_SIZE) if $pixdata; if ($loader) diff --git a/plugins/lyrics.pm b/plugins/lyrics.pm index de808f30..9824707e 100644 --- a/plugins/lyrics.pm +++ b/plugins/lyrics.pm @@ -209,8 +209,7 @@ sub destroy_event_cb sub cancel { my $self=shift; delete $::ToDo{'8_lyrics'.$self}; - $self->{waiting}->abort if $self->{waiting}; - $self->{waiting}=$self->{pixtoload}=undef; + $self->{pixtoload}=undef; } sub prefbox @@ -426,12 +425,11 @@ sub load_url $self->{url}=$url; $self->{post}=$post; $self->{check}=$check; # function to check if lyrics found - $self->{waiting}=Simple_http::get_with_cb(cb => sub {$self->loaded(@_)},url => $url,post => $post); + Simple_http::post_with_cb(cb => sub {$self->loaded(@_)},url => $url,post => $post); } sub loaded #_very_ crude html to gtktextview renderer { my ($self,$data,%data_prop)=@_; - delete $self->{waiting}; my $type=$data_prop{type}; my $buffer=$self->{buffer}; my $encoding; @@ -578,9 +576,9 @@ sub load_pixbuf my $ref=shift @{ $self->{pixtoload} }; return 0 unless $ref; my ($mark,$url,$link)=@$ref; - $self->{waiting}=Simple_http::get_with_cb(url => $self->full_url($url), cache=>1, cb=> + Simple_http::get_with_cb(url => $self->full_url($url), cb=> sub - { $self->{waiting}=undef; + { my $loader; $loader= GMB::Picture::LoadPixData($_[0]) if $_[0]; if ($loader) @@ -597,36 +595,8 @@ sub load_pixbuf } ::IdleDo('8_FetchPix'.$self,100,\&load_pixbuf,$self); #load next }); -#::IdleDo('8_FetchPix'.$self,100,\&load_pixbuf,$self) unless $self->{waiting}; -} - -#sub loaded_old #old method, more crude :) -#{ my $self=shift; -# my $buffer=$self->{buffer}; -# unless ($_[0]) {$buffer->delete($buffer->get_bounds);$buffer->set_text(_"Loading failed.");return;} -# local $_=$_[0]; -# s/[\r\n]//g; -# s#.*?##; -# s#