Skip to content

Commit

Permalink
Merge pull request #20 from philippe44/move-to-LMS-8.x
Browse files Browse the repository at this point in the history
  • Loading branch information
danielvijge authored Apr 22, 2021
2 parents 7e7bb73 + c03fa3c commit ab29aed
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 51 deletions.
32 changes: 19 additions & 13 deletions Buffered.pm
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,41 @@ use File::Temp;
use Slim::Utils::Errno;
use Slim::Utils::Log;
use Slim::Utils::Prefs;
use Slim::Utils::Misc;

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

sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
my $v = ${*$self}{'_mixcloud'} = {};

# 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() );
$v->{'fh'} = File::Temp->new( DIR => Slim::Utils::Misc::getTempDir() );
} else {
${*$self}{'_fh'} = File::Temp->new;
$v->{'fh'} = File::Temp->new;
}
open ${*$self}{'_rfh'}, '<', ${*$self}{'_fh'}->filename;
binmode(${*$self}{'_rfh'});
open $v->{'rfh'}, '<', $v->{'fh'}->filename;
binmode($v->{'rfh'});

main::INFOLOG && $log->info("Using Mixcloud's own Buffered service for $_[0]->{'url'}");

return $self;
}

sub close {
my $self = shift;
my $v = ${*$self}{'_mixcloud'};

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

$self->SUPER::close(@_);
}
Expand All @@ -47,17 +52,17 @@ sub close {
# see http://modernperlbooks.com/mt/2009/09/when-super-isnt.html
sub _sysread {
my $self = $_[0];
my $rfh = ${*$self}{'_rfh'};
my $v = ${*$self}{'_mixcloud'};

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

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

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

# empty file but not done yet, try to read directly
$readLength = $self->SUPER::_sysread($_[1], $_[2], $_[3]);
Expand All @@ -76,15 +81,16 @@ sub _sysread {

sub saveStream {
my $self = shift;
my $v = ${*$self}{'_mixcloud'};

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

if ($bytes) {
syswrite(${*$self}{'_fh'}, $data);
${*$self}{'_rfh'}->seek(0, 1);
syswrite($v->{'fh'}, $data);
$v->{'rfh'}->seek(0, 1);
} else {
Slim::Networking::Select::removeRead($self);
${*$self}{_done} = 1;
$v->{'done'} = 1;
}
}
29 changes: 15 additions & 14 deletions HTML/EN/plugins/MixCloud/settings/basic.html
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
[% PROCESS settings/header.html %]

[% WRAPPER setting title="PLUGIN_MIXCLOUD_APIKEY" desc="PLUGIN_MIXCLOUD_APIKEY_DESC" %]
<div class="prefDesc">
<input type="text" class="stdedit" name="pref_apiKey" value="[% prefs.apiKey %]" size="40" />
<br/>
<a target="_blank" href="http://danielvijge.github.io/lms_mixcloud/app.html">Get your apiKey for Mixcloud at mixcloud.com</a>
</div>

<a target="_blank" href="https://danielvijge.github.io/lms_mixcloud/app.html">Get your apiKey for Mixcloud at mixcloud.com</a>
[% END %]

<!--
[% WRAPPER setting title="PLUGIN_MIXCLOUD_PLAYMETHOD" desc="PLUGIN_MIXCLOUD_PLAYMETHOD_DESC" %]
<div class="prefDesc">
<select name="pref_playformat" class="stdedit">
<option[% IF prefs.playformat == 'mp4' %] selected[% END %] value="mp4">Always use MP4 format</option>
<option[% IF prefs.playformat == 'mp3' %] selected[% END %] value="mp3">Use MP3 format if available</option>
</select>
</div>
[% IF prefs.exists('pref_playformat') %]
[% WRAPPER setting title="PLUGIN_MIXCLOUD_PLAYMETHOD" desc="PLUGIN_MIXCLOUD_PLAYMETHOD_DESC" %]
<select name="pref_playformat" class="stdedit">
<option[% IF prefs.playformat == 'mp4' %] selected[% END %] value="mp4">Always use MP4 format</option>
<option[% IF prefs.playformat == 'mp3' %] selected[% END %] value="mp3">Use MP3 format if available</option>
</select>
[% END %]
[% END %]

[% END %]
-->

[% IF prefs.exists('pref_useBuffered') %]
[% WRAPPER setting title="PLUGIN_MIXCLOUD_USEBUFFERED" desc="PLUGIN_MIXCLOUD_USEBUFFERED_DESC" %]
<input type="checkbox" [% IF prefs.pref_useBuffered %]checked="1" [% END %] class="stdedit" name="pref_useBuffered" id="useBuffered" value="1" />
[% END %]
[% END %]

[% PROCESS settings/footer.html %]
4 changes: 2 additions & 2 deletions Plugin.pm
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ my $log = Slim::Utils::Log->addLogCategory({
'description' => string('PLUGIN_MIXCLOUD'),
});

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

sub getToken {
my ($callback) = shift;
Expand Down Expand Up @@ -213,7 +213,7 @@ sub urlHandler {
$url =~ s/www /www./;
$url =~ s/http:\/\/ /https:\/\//;
my ($id) = $url =~ m{^https://(?:www|m).mixcloud.com/(.*)$};
my $queryUrl = "http://api.mixcloud.com/" . $id ;
my $queryUrl = "https://api.mixcloud.com/" . $id ;
return unless $id;

$log->debug("fetching $queryUrl");
Expand Down
38 changes: 21 additions & 17 deletions ProtocolHandler.pm
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,7 @@ package Plugins::MixCloud::ProtocolHandler;
use strict;

use vars qw(@ISA);

BEGIN {
if (eval { require Slim::Player::Protocols::Buffered }) {
push @ISA, qw(Slim::Player::Protocols::Buffered);
} else {
require Plugins::MixCloud::Buffered;
push @ISA, qw(Plugins::MixCloud::Buffered);
}
}
use base qw(Slim::Player::Protocols::HTTPS);

use List::Util qw(min max);
use HTML::Parser;
Expand All @@ -43,10 +35,12 @@ my $cache = Slim::Utils::Cache->new;

Slim::Player::ProtocolHandlers->registerURLHandler(PAGE_URL_REGEXP, __PACKAGE__);

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

sub isPlaylistURL { 0 }
sub canDirectStream { 0 };

sub canDirectStream {
return 0 if $prefs->get('useBuffered') && !Slim::Player::Protocols::HTTP->can('response');
return shift->SUPER::canDirectStream(@_);
}

sub scanUrl {
my ($class, $url, $args) = @_;
Expand All @@ -67,15 +61,25 @@ sub new {
my $song = $args->{song};
my $streamUrl = $song->streamUrl() || return;
my $track = $song->pluginData();

$log->info( 'Remote streaming Mixcloud track: ' . $streamUrl );

my $self = $class->SUPER::new({
url => $streamUrl,
my $params = {
url => $streamUrl,
song => $song,
client => $client,
});
};

return $self;
# this may be a bit dangerous if another track is streaming...
if (Slim::Player::Protocols::HTTP->can('canEnhanceHTTP') || !$prefs->get('useBuffered')) {
require Slim::Player::Protocols::HTTPS;
@ISA = qw(Slim::Player::Protocols::HTTPS);
} else {
require Plugins::MixCloud::Buffered;
@ISA = qw(Plugins::MixCloud::Buffered);
}

return $class->SUPER::new($params);
}

# Tweak user-agent for mixcloud to accept our request
Expand Down Expand Up @@ -221,7 +225,7 @@ sub fetchTrackDetails {
icon => __PACKAGE__->getIcon,
} if $client && $client->master->pluginData('fetchingMeta');

my $fetchURL = "http://api.mixcloud.com/$id";
my $fetchURL = "https://api.mixcloud.com/$id";
$client->master->pluginData( fetchingMeta => 1 ) if $client;
$log->info("Getting track details for $url", dump($item));

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ Press the _Apply_ button and restart LMS.
After installation, you can configure the Plugin under _Settings_ > _Advanced_ > _Mixcloud_

The plugin is included as a default third party resource. It is distributed via my
[personal repository](http://server.vijge.net/squeezebox/) This third party repository
[personal repository](https://server.vijge.net/squeezebox/) This third party repository
is synced with the repository XML files on GitHub. It is also possible to directly include
the repository XML from GitHub. For the release version, include

http://danielvijge.github.io/lms_mixcloud/public.xml
https://danielvijge.github.io/lms_mixcloud/public.xml

For the development version (updated with every commit), include

http://danielvijge.github.io/lms_mixcloud/public-dev.xml
https://danielvijge.github.io/lms_mixcloud/public-dev.xml

This Plugin is in Alpha stage and build from the SqueezeCloud Plugin (thanks to the developers), because the documentation
of the LMS Server is very bad and Perl still sucks.
Expand Down
12 changes: 11 additions & 1 deletion Settings.pm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,17 @@ sub page {
}

sub prefs {
return (preferences('plugin.mixcloud'), qw(apiKey playformat));
my $class = shift;
# playformat not used for now
my @prefs = ( preferences('plugin.mixcloud'), qw(apiKey) );
push @prefs, qw(useBuffered) unless Slim::Player::Protocols::HTTP->can('canEnhanceHTTP');
return @prefs;
}

sub handler {
my ($class, $client, $params) = @_;
$params->{"pref_useBuffered"} = 0 unless defined $params->{"pref_useBuffered"};
return $class->SUPER::handler( $client, $params );
}

1;
2 changes: 1 addition & 1 deletion public.template.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<plugin name="MixCloud" version="{{ env['VERSION'] }}" minTarget="8.1" maxTarget="*">
<title lang="EN">Mixcloud</title>
<desc lang="EN">Play music from Mixcloud</desc>
<url>http://danielvijge.github.io/lms_mixcloud/{{ env['FOLDER'] }}/lms_mixcloud-{{ env['VERSION'] }}.zip</url>
<url>https://danielvijge.github.io/lms_mixcloud/{{ env['FOLDER'] }}/lms_mixcloud-{{ env['VERSION'] }}.zip</url>
<link>https://github.com/danielvijge/lms_mixcloud</link>
<sha>{{ env['SHA'] }}</sha>
<creator>Christian Mueller, Daniel Vijge</creator>
Expand Down
6 changes: 6 additions & 0 deletions strings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,11 @@ PLUGIN_MIXCLOUD_PLAYMETHOD
PLUGIN_MIXCLOUD_PLAYMETHOD_DESC
EN All tracks are available in MP4 format, and selecting a track is fast. However, MP4 does not work natively on old Squeezebox models, and must be transcoded for those players. MP3 has a better sound quality, but loading a track takes a long time, and not all tracks are available in MP3 format.

PLUGIN_MIXCLOUD_USEBUFFERED
EN Buffer streams in system's temp directory

PLUGIN_MIXCLOUD_USEBUFFERED_DESC
EN MixCloud server does not like very long streaming sessions. This option downloads the file as quickly as possible in the system's temp directory and closes the connection. Used disk spaced is released when songs end.

PLUGIN_MIXCLOUD_STREAM_FAILED
EN Connection error

0 comments on commit ab29aed

Please sign in to comment.