Skip to content

Commit

Permalink
Merge pull request #13 from philippe44/move-to-LMS-8.x
Browse files Browse the repository at this point in the history
  • Loading branch information
danielvijge authored Apr 21, 2021
2 parents 09dacdf + 63ac2df commit d639bf7
Show file tree
Hide file tree
Showing 11 changed files with 316 additions and 5,446 deletions.
90 changes: 90 additions & 0 deletions Buffered.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package Plugins::MixCloud::Buffered;

use strict;
use base qw(Slim::Player::Protocols::HTTPS);

use File::Temp;

use Slim::Utils::Errno;
use Slim::Utils::Log;
use Slim::Utils::Prefs;

my $log = logger('plugin.mixcloud');
my $prefs = preferences('plugin.mixcloud');

sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);

# HTTP headers have now been acquired in a blocking way by the above, we can
# now enable fast download of body to a file from which we'll read further data
# but the switch of socket handler can only be done within _sysread otherwise
# we will timeout when there is a pipeline with a callback
if (Slim::Utils::Misc->can('getTempDir')) {
${*$self}{'_fh'} = File::Temp->new( DIR => Slim::Utils::Misc::getTempDir );
} else {
${*$self}{'_fh'} = File::Temp->new;
}
open ${*$self}{'_rfh'}, '<', ${*$self}{'_fh'}->filename;
binmode(${*$self}{'_rfh'});

return $self;
}

sub close {
my $self = shift;

# clean buffer file and all handlers
Slim::Networking::Select::removeRead($self);
${*$self}{'_rfh'}->close;
delete ${*$self}{'_fh'};

$self->SUPER::close(@_);
}

# we need that call structure to make sure that SUPER calls the
# object's parent, not the package's parent
# see http://modernperlbooks.com/mt/2009/09/when-super-isnt.html
sub _sysread {
my $self = $_[0];
my $rfh = ${*$self}{'_rfh'};

# we are not ready to read body yet, read socket directly
return $self->SUPER::_sysread($_[1], $_[2], $_[3]) unless $rfh;

# first, try to read from buffer file
my $readLength = $rfh->read($_[1], $_[2], $_[3]);
return $readLength if $readLength;

# assume that close() will be called for cleanup
return 0 if ${*$self}{_done};

# empty file but not done yet, try to read directly
$readLength = $self->SUPER::_sysread($_[1], $_[2], $_[3]);

# if we now have data pending, likely we have been removed from the reading loop
# so we have to re-insert ourselves (no need to store fresh data in buffer)
if ($readLength) {
Slim::Networking::Select::addRead($self, \&saveStream);
return $readLength;
}

# use EINTR because EWOULDBLOCK (although faster) may overwrite our addRead()
$! = EINTR;
return undef;
}

sub saveStream {
my $self = shift;

my $bytes = $self->SUPER::_sysread(my $data, 32768);
return unless defined $bytes;

if ($bytes) {
syswrite(${*$self}{'_fh'}, $data);
${*$self}{'_rfh'}->seek(0, 1);
} else {
Slim::Networking::Select::removeRead($self);
${*$self}{_done} = 1;
}
}
2 changes: 2 additions & 0 deletions HTML/EN/plugins/MixCloud/settings/basic.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

[% END %]

<!--
[% WRAPPER setting title="PLUGIN_MIXCLOUD_PLAYMETHOD" desc="PLUGIN_MIXCLOUD_PLAYMETHOD_DESC" %]
<div class="prefDesc">
<select name="pref_playformat" class="stdedit">
Expand All @@ -18,5 +19,6 @@
</div>
[% END %]
-->

[% PROCESS settings/footer.html %]
127 changes: 17 additions & 110 deletions Plugin.pm
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,30 @@ package Plugins::MixCloud::Plugin;
# See file LICENSE for full license details

use strict;
use utf8;

use vars qw(@ISA);
use base qw(Slim::Plugin::OPMLBased);
use utf8;

use URI::Escape;
use JSON::XS::VersionOneAndTwo;
use LWP::Simple;
use LWP::UserAgent;

use File::Spec::Functions qw(:ALL);
use List::Util qw(min max);
use Date::Parse;

use Slim::Utils::Strings qw(string);
use Slim::Utils::Prefs;
use Slim::Utils::Log;
use Date::Parse;

use Data::Dumper;
use Slim::Plugin::OPMLBased;

use Plugins::MixCloud::ProtocolHandler;

my $log;
my $compat;
my $CLIENT_ID = "2aB9WjPEAButp4HSxY";
my $CLIENT_SECRET = "scDXfRbbTyDHHGgDhhSccHpNgYUa7QAW";
my $token = "";

BEGIN {
$log = Slim::Utils::Log->addLogCategory({
'category' => 'plugin.mixcloud',
'defaultLevel' => 'WARN',
'description' => string('PLUGIN_MIXCLOUD'),
});

if (exists &Slim::Control::XMLBrowser::findAction) {
$log->info("using server XMLBrowser");
require Slim::Plugin::OPMLBased;
push @ISA, 'Slim::Plugin::OPMLBased';
} else {
$log->info("using packaged XMLBrowser: Slim76Compat");
require Slim76Compat::Plugin::OPMLBased;
push @ISA, 'Slim76Compat::Plugin::OPMLBased';
$compat = 1;
}
}

my $prefs = preferences('plugin.mixcloud');
my $log = logger('plugin.mixcloud');

$prefs->init({ apiKey => "", playformat => "mp4" });

Expand Down Expand Up @@ -81,82 +59,16 @@ sub getToken {
}
}

sub _makeMetadata {
my ($json) = shift;

my $icon = "";
if (defined $json->{'pictures'}->{'large'}) {
$icon = $json->{'pictures'}->{'large'};
}else{
if (defined $json->{'pictures'}->{'medium'}) {
$icon = $json->{'pictures'}->{'medium'};
}
}

my $DATA = {
duration => $json->{'audio_length'},
name => $json->{'name'},
title => $json->{'name'},
artist => $json->{'user'}->{'username'},
album => " ",
play => "mixcloud:/" . $json->{'key'},
bitrate => '320kbps/70kbps',
type => 'MP3/MP4 (Mixcloud)',
passthrough => [ { key => $json->{'key'}} ],
icon => $icon,
image => $icon,
cover => $icon,
on_select => 'play',
};

# Already set meta cache here, so that playlist does not have to
# query each track individually
my $cache = Slim::Utils::Cache->new;
$log->debug("setting ". 'mixcloud_meta_' . $DATA->{'play'});
$cache->set( 'mixcloud_meta_' . $DATA->{'play'}, $DATA, 3600 );

return $DATA;
}

sub _fetchMeta {
my ($client, $callback, $args, $passDict) = @_;

my $cache = Slim::Utils::Cache->new;
$log->debug("getting ". 'mixcloud_meta_mixcloud:/' . $passDict->{"key"});
my $meta = $cache->get( 'mixcloud_meta_mixcloud:/' . $passDict->{"key"} );

return $meta if $meta;

my $fetchURL = "http://api.mixcloud.com" . $passDict->{"key"} ;
$log->info("Fetching meta data for $fetchURL");
Slim::Networking::SimpleAsyncHTTP->new(

sub {
my $track = eval { from_json($_[0]->content) };
if ($@) {
$log->warn($@);
}
$log->debug("Got meta data for $fetchURL");
my $meta ={name => "hallo"};# _makeMetadata($track);
#$meta->{'name'} = "hallo";
#%meta{"items"} = [_makeMetadata($track)];
$callback->(_makeMetadata($track));
},

sub {
$log->warn("Error: Cannot fetch track data for $_[1]");
},

{ timeout => 35 },

)->get($fetchURL);
sub _provider {
my ($client, $url) = @_;
return Plugins::MixCloud::ProtocolHandler::fetchTrackDetail($client, $url);
}

sub _parseTracks {
my ($json, $menu) = @_;
my $data = $json->{'data'};
for my $entry (@$data) {
push @$menu, _makeMetadata($entry);
push @$menu, Plugins::MixCloud::ProtocolHandler::makeCacheItem($entry);
}
}

Expand Down Expand Up @@ -231,7 +143,6 @@ sub tracksHandler {
}

my $queryUrl = "$method://api.mixcloud.com/$resource?offset=$i&limit=$quantity&" . $params;
#$queryUrl= "http://192.168.56.1/json/cloudcasts.json";
$log->info("Fetching $queryUrl");

Slim::Networking::SimpleAsyncHTTP->new(
Expand Down Expand Up @@ -297,20 +208,19 @@ sub urlHandler {
$url =~ s/ com/.com/;
$url =~ s/www /www./;
$url =~ s/http:\/\/ /https:\/\//;
my ($subdomain, $trackhome) = $url =~ m{^https://(www|m).mixcloud.com/(.*)$};
my $queryUrl = "http://api.mixcloud.com/" . $trackhome ;
my ($id) = $url =~ m{^https://(?:www|m).mixcloud.com/(.*)$};
my $queryUrl = "http://api.mixcloud.com/" . $id ;
return unless $id;

$log->debug("fetching $queryUrl");

my $fetch = sub {
Slim::Networking::SimpleAsyncHTTP->new(
sub {
my $http = shift;
my $json = eval { from_json($http->content) };

$callback->({
items => [ _makeMetadata($json) ]
});
my $item = eval { from_json($http->content) };
$log->warn($@) if $@;
$callback->( { items => [ Plugins::MixCloud::ProtocolHandler::makeCacheItem($item) ] } );
},
sub {
$log->error("error: $_[1]");
Expand Down Expand Up @@ -447,7 +357,7 @@ sub initPlugin {

Slim::Formats::RemoteMetadata->registerProvider(
match => qr/mixcloud/,
func => \&_fetchMeta,
func => \&_provider,
);

Slim::Player::ProtocolHandlers->registerHandler(
Expand Down Expand Up @@ -487,9 +397,6 @@ sub toplevel {
$callback->($searchcallbacks);
}, passthrough => [ { type => 'search' } ], }
];




getToken(
sub{
Expand Down
Loading

0 comments on commit d639bf7

Please sign in to comment.