function playerController() {
var self = this;
var updatetimer = null;
var progresstimer = null;
var safetytimer = 500;
var previoussongid = -1;
var AlanPartridge = 0;
var plversion = null;
var openpl = null;
var oldplname;
var thenowplayinghack = false;
var lastsearchcmd = "search";
var stateChangeCallbacks = new Array();
function updateStreamInfo() {
// When playing a stream, mpd returns 'Title' in its status field.
// This usually has the form artist - track. We poll this so we know when
// the track has changed (note, we rely on radio stations setting their
// metadata reliably)
// Note that mopidy doesn't quite work this way. It sets Title and possibly Name
// - I fixed that bug once but it got broke again
if (playlist.getCurrent('type') == "stream") {
// debug.trace('STREAMHANDLER','Playlist:',playlist.getCurrent('Title'),playlist.getCurrent('Album'),playlist.getCurrent('trackartist'));
var temp = playlist.getCurrentTrack();
if (player.status.Title) {
var parts = player.status.Title.split(" - ");
if (parts[0] && parts[1]) {
temp.trackartist = parts.shift();
temp.Title = parts.join(" - ");
temp.metadata.artists = [{name: temp.trackartist, musicbrainz_id: ""}];
temp.metadata.track = {name: temp.Title, musicbrainz_id: ""};
} else if (player.status.Title && player.status.Artist) {
temp.trackartist = player.status.Artist;
temp.Title = player.status.Title;
temp.metadata.artists = [{name: temp.trackartist, musicbrainz_id: ""}];
temp.metadata.track = {name: temp.Title, musicbrainz_id: ""};
}
}
if (player.status.Name && !player.status.Name.match(/^\//) && temp.Album == rompr_unknown_stream) {
// NOTE: 'Name' is returned by MPD - it's the station name as read from the station's stream metadata
debug.shout('STREAMHANDLER',"Checking For Stream Name Update");
checkForUpdateToUnknownStream(playlist.getCurrent('StreamIndex'), player.status.Name);
temp.Album = player.status.Name;
temp.metadata.album = {name: temp.Album, musicbrainz_id: ""};
}
// debug.trace('STREAMHANDLER','Current:',temp.Title,temp.Album,temp.trackartist);
if (playlist.getCurrent('Title') != temp.Title ||
playlist.getCurrent('Album') != temp.Album ||
playlist.getCurrent('trackartist') != temp.trackartist)
{
debug.log("STREAMHANDLER","Detected change of track",temp);
var aa = new albumart_translator('');
temp.key = aa.getKey('stream', '', temp.Album);
playlist.setCurrent({Title: temp.Title, Album: temp.Album, trackartist: temp.trackartist });
nowplaying.newTrack(temp, true);
}
}
}
function checkForUpdateToUnknownStream(streamid, name) {
// If our playlist for this station has 'Unknown Internet Stream' as the
// station name, let's see if we can update it from the metadata.
debug.log("STREAMHANDLER","Checking For Update to Stream",streamid,name, name);
var m = playlist.getCurrent('Album');
if (m.match(/^Unknown Internet Stream/)) {
debug.shout("PLAYLIST","Updating Stream",name);
yourRadioPlugin.updateStreamName(streamid, name, playlist.getCurrent('file'), playlist.repopulate);
}
}
function setTheClock(callback, timeout) {
clearProgressTimer();
progresstimer = setTimeout(callback, timeout);
}
function initialised(data) {
for(var i =0; i < data.length; i++) {
var h = data[i].replace(/\:\/\/$/,'');
debug.log("PLAYER","URL Handler : ",h);
player.urischemes[h] = true;
}
if (!player.canPlay('spotify')) {
$('div.textcentre.textunderline:contains("Music From Spotify")').remove();
}
checkSearchDomains();
doMopidyCollectionOptions();
playlist.radioManager.init();
// Need to call this with a callback when we start up so that checkprogress doesn't get called
// before the playlist has repopulated.
self.do_command_list([],self.ready);
if (!player.collectionLoaded) {
debug.log("MPD", "Checking Collection");
collectionHelper.checkCollection(false, false);
}
}
this.initialise = function() {
$.ajax({
type: 'GET',
url: 'player/mpd/geturlhandlers.php',
dataType: 'json'
})
.done(initialised)
.fail(function(data) {
debug.error("MPD","Failed to get URL Handlers",data);
infobar.permerror(language.gettext('error_noplayer'));
});
}
this.ready = function() {
debug.mark("MPD","Player is ready");
var t = "Connected to "+getCookie('currenthost')+" ("+prefs.player_backend.capitalize() +
" at " + player_ip + ")";
infobar.notify(t);
self.reloadPlaylists();
}
this.do_command_list = function(list, callback) {
// Note, if you call this with a callback, your callback MUST call player.controller.checkProgress
$.ajax({
type: 'POST',
url: 'player/mpd/postcommand.php',
data: JSON.stringify(list),
// contentType of false prevents jQuery from re-encoding our data, where it
// converts %20 to +, which seems to be a bug in jQuery 3.0
contentType: false,
dataType: 'json',
timeout: 30000
})
.done(function(data) {
if (data) {
debug.debug("PLAYER",data);
if (data.state) {
// Clone the object so as not to leave this closure in memory
player.status = cloneObject(data);
['radiomode', 'radioparam', 'radiomaster', 'radioconsume'].forEach(function(e) {
prefs[e] = player.status[e];
});
if (player.status.playlist !== plversion) {
debug.blurt("PLAYER","Player has marked playlist as changed");
plversion = player.status.playlist;
playlist.repopulate();
}
infobar.setStartTime(player.status.elapsed);
checkStateChange();
}
}
})
.fail(function(jqXHR, textStatus, errorThrown) {
debug.error("MPD","Command List Failed",list,textStatus,errorThrown);
if (list.length > 0) {
infobar.error(language.gettext('error_sendingcommands', [prefs.player_backend]));
}
})
.always(function() {
post_command_list(callback);
});
}
function post_command_list(callback) {
if (callback) {
callback();
} else {
self.checkProgress();
}
infobar.updateWindowValues();
}
this.isConnected = function() {
return true;
}
this.addStateChangeCallback = function(sc) {
if (player.status.state == sc.state) {
sc.callback();
} else {
stateChangeCallbacks.push(sc);
}
}
function checkStateChange() {
for (var i = 0; i < stateChangeCallbacks.length ; i++) {
if (stateChangeCallbacks[i].state == player.status.state) {
// If we're looking for a state change to play, check that elapsed > 5. This works around Mopidy's
// buffering issue where playback can take a long time to start with streams and ends up starting a
// long time after we've started ramping the alarm clock volume
debug.log('PLAYER', 'State Change Check. State is',player.status.state,'Elapsed is',player.status.elapsed);
if (player.status.state != 'play' || player.status.elapsed > 5) {
debug.mark('PLAYER', 'Calling state change callback for state',player.status.state);
stateChangeCallbacks[i].callback();
stateChangeCallbacks.splice(i, 1);
i--;
}
}
}
}
this.reloadPlaylists = function() {
var openplaylists = [];
$('#storedplaylists').find('i.menu.openmenu.playlist.icon-toggle-open').each(function() {
openplaylists.push($(this).attr('name'));
})
$.get("player/mpd/loadplaylists.php", function(data) {
$("#storedplaylists").html(data);
layoutProcessor.postAlbumActions();
$('b:contains("'+language.gettext('button_loadplaylist')+'")').parent('.configtitle').append('');
for (var i in openplaylists) {
$('i.menu.openmenu.playlist.icon-toggle-closed[name="'+openplaylists[i]+'"]').click();
}
if (openplaylists.length > 0) {
infobar.markCurrentTrack();
}
$('#addtoplaylistmenu').load('player/mpd/loadplaylists.php?addtoplaylistmenu');
});
}
this.loadPlaylist = function(name) {
self.do_command_list([['load', name]]);
return false;
}
this.loadPlaylistURL = function(name) {
if (name == '') {
return false;
}
var data = {url: encodeURIComponent(name)};
$.ajax({
type: "GET",
url: "utils/getUserPlaylist.php",
cache: false,
data: data,
dataType: "xml"
})
.done(function() {
self.reloadPlaylists();
self.addTracks([{type: 'remoteplaylist', name: name}], null, null);
})
.fail(function(data, status) {
playlist.repopulate();
debug.error("MPD","Failed to save user playlist URL");
});
return false;
}
this.deletePlaylist = function(name, callback) {
openpl = null;
name = decodeURIComponent(name);
if (callback) {
self.do_command_list([['rm',name]], callback);
} else {
self.do_command_list([['rm',name]], function() {
self.reloadPlaylists();
if (typeof(playlistManager) != 'undefined') {
playlistManager.reloadAll();
}
});
}
}
this.deleteUserPlaylist = function(name) {
openpl = null;
var data = {del: encodeURIComponent(name)};
$.ajax({
type: "GET",
url: "utils/getUserPlaylist.php",
cache: false,
data: data,
dataType: "xml"
})
.done(self.reloadPlaylists)
.fail(function(data, status) {
debug.error("MPD","Failed to delete user playlist",name);
});
}
this.renamePlaylist = function(name, e, callback) {
openpl = null;
oldplname = name;
debug.log("MPD","Renaming Playlist",name,e);
var fnarkle = new popup({
css: {
width: 400,
height: 300
},
title: language.gettext("label_renameplaylist"),
atmousepos: true,
mousevent: e
});
var mywin = fnarkle.create();
var d = $('
',{class: 'containerbox'}).appendTo(mywin);
var e = $('
',{class: 'expand'}).appendTo(d);
var i = $('',{class: 'enter', id: 'newplname', type: 'text', size: '200'}).appendTo(e);
var b = $('