mopidy-musicbox-webclient/mopidy_musicbox_webclient/static/js/functionsvars.js
2016-02-05 08:19:45 +02:00

561 lines
18 KiB
JavaScript

/**
* @author Wouter van Wijk
*
* all kinds functions and vars
*/
var mopidy;
//values for controls
var play = false;
var random;
var repeat;
var consume;
var single;
var currentVolume = -1;
var mute;
var volumeChanging = false;
var posChanging = false;
var posTimer;
var volumeTimer;
var seekTimer;
var initgui = true;
var currentpos = 0;
var popupData = {};
var songlength = 0;
var artistshtml = '';
var artiststext = '';
var songname = '';
var songdata = {'track': {}, 'tlid': -1};
var newposition = 0;
var playlisttracksScroll;
var playlistslistScroll;
var STREAMS_PLAYLIST_NAME = '[Radio Streams]';
var STREAMS_PLAYLIST_SCHEME = 'm3u';
var uriSchemes = {};
//array of cached playlists (not only user-playlists, also search, artist, album-playlists)
var playlists = {};
var currentplaylist;
var customTracklists = [];
var browseStack = [];
var browseTracks = [];
var ua = navigator.userAgent,
isMobileSafari = /Mac/.test(ua) && /Mobile/.test(ua),
isMobileWebkit = /WebKit/.test(ua) && /Mobile/.test(ua),
isMobile = /Mobile/.test(ua),
isWebkit = /WebKit/.test(ua);
//constants
PROGRAM_NAME = 'MusicBox';
ARTIST_TABLE = '#artiststable';
ALBUM_TABLE = '#albumstable';
PLAYLIST_TABLE = '#playlisttracks';
CURRENT_PLAYLIST_TABLE = '#currenttable';
SEARCH_ALL_TABLE = '#allresulttable';
SEARCH_ALBUM_TABLE = '#albumresulttable';
SEARCH_ARTIST_TABLE = '#artistresulttable';
SEARCH_TRACK_TABLE = '#trackresulttable';
URI_SCHEME = 'mbw';
PLAY_NOW = 0;
PLAY_NEXT = 1;
ADD_THIS_BOTTOM = 2;
ADD_ALL_BOTTOM = 3;
PLAY_ALL = 4;
PLAY_NOW_SEARCH = 5;
MAX_TABLEROWS = 50;
//update track slider timer, milliseconds
TRACK_TIMER = 1000;
//check status timer, every 5 or 10 sec
STATUS_TIMER = 10000;
// the first part of Mopidy extensions which serve radio streams
var radioExtensionsList = ['somafm', 'tunein', 'dirble', 'audioaddict'];
var uriClassList = [
['spotify', 'fa-spotify'],
['spotifytunigo', 'fa-spotify'],
['local', 'fa-file-sound-o'],
['m3u', 'fa-file-sound-o'],
['podcast', 'fa-rss-square'],
['dirble', 'fa-microphone'],
['tunein', 'fa-headphones'],
['soundcloud', 'fa-soundcloud'],
['sc', 'fa-soundcloud'],
['gmusic', 'fa-google'],
['internetarchive', 'fa-university'],
['somafm', 'fa-flask'],
['youtube', 'fa-youtube'],
['yt', 'fa-youtube'],
['audioaddict', 'fa-bullhorn'],
['subsonic', 'fa-folder-open']
];
var uriHumanList = [
['spotify', 'Spotify'],
['spotifytunigo', 'Spotify Browse'],
['local', 'Local Files'],
['m3u', 'Local Playlists'],
['podcast', 'Podcasts'],
['dirble', 'Dirble'],
['tunein', 'TuneIn'],
['soundcloud', 'SoundCloud'],
['gmusic', 'Google Music'],
['internetarchive', 'Internet Archive'],
['somafm', 'Soma FM'],
['youtube', 'YouTube'],
['audioaddict', 'AudioAddict'],
['subsonic', 'Subsonic']
];
function scrollToTop() {
var divtop = 0;
$('body,html').animate({
scrollTop: divtop
}, 250);
}
function scrollToTracklist() {
var divtop = $("#playlisttracksdiv").offset().top - 120;
$('body,html').animate({
scrollTop: divtop
}, 250);
}
//A hack to find the name of the first artist of a playlist. this is not yet returned by mopidy
//does not work wel with multiple artists of course
function getArtist(pl) {
for (var i = 0; i < pl.length; i++) {
for (var j = 0; j < pl[i].artists.length; j++) {
if (pl[i].artists[j].name != '') {
return pl[i].artists[j].name;
}
}
};
}
//A hack to find the first album of a playlist. this is not yet returned by mopidy
function getAlbum(pl) {
for (var i = 0; i < pl.length; i++) {
if (pl[i].album.name != '') {
return pl[i].album.name;
}
};
}
function artistsToString(artists, max) {
var result = '';
max = max || 3;
for (var i = 0; i < artists.length && i < max; i++) {
if (artists[i].name) {
if (i > 0) {
result += ', ';
}
result += artists[i].name;
}
}
return result;
}
/********************************************************
* break up results and put them in album tables
*********************************************************/
function albumTracksToTable(pl, target, uri) {
var tmp = '<ul class="songsOfAlbum table" >';
var liId = '';
var targetmin = target.substr(1);
$(target).empty();
for (var i = 0; i < pl.length; i++) {
popupData[pl[i].uri] = pl[i];
liID = targetmin + '-' + pl[i].uri;
tmp += renderSongLi(pl[i], liID, uri);
};
tmp += '</ul>';
$(target).html(tmp);
$(target).attr('data', uri);
}
function renderSongLi(song, liID, uri) {
var name;
if (!song.name || song.name == '') {
name = uri.split('/');
name = decodeURI(name[name.length - 1]);
} else {
name = song.name;
}
songLi = '<li class="song albumli" id="' + liID + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + song.uri + '\');">' +
'<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" onclick="return playTrackByUri(\'' + song.uri + '\',\'' + uri + '\');">' +
'<h1 class="trackname">' + name + '</h1></a>' +
'</li>';
return songLi;
}
function renderQueueSongLi(song, liID, uri, tlid) {
var name;
if (!song.name || song.name == '') {
name = uri.split('/');
name = decodeURI(name[name.length - 1]);
} else {
name = song.name;
}
songLi = '<li class="song albumli" id="' + liID + '" tlid="' + tlid + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + song.uri + '\',\'' + tlid + '\');">' +
'<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" onclick="return playTrackQueueByTlid(\'' + song.uri + '\',\'' + tlid + '\');">' +
'<h1 class="trackname">' + name + '</h1></a>' +
'</li>';
return songLi;
}
function resultsToTables(results, target, uri) {
if (!results) {
return
}
var tlids = [];
if (target == CURRENT_PLAYLIST_TABLE) {
for (i = 0; i < results.length; i++) {
tlids[i] = results[i].tlid;
results[i] = results[i].track;
}
}
var newalbum = [];
var newtlids = [];
//keep a list of albums for retreiving of covers
var coversList = [];
var nextname = '';
var count = 0;
$(target).html('');
//break into albums and put in tables
var html = '';
var tableid, j, artistname, alburi, name, iconClass;
var targetmin = target.substr(1);
$(target).attr('data', uri);
var length = 0 || results.length;
for (i = 0; i < length; i++) {
//create album if none extists
if (!results[i].album) {
results[i].album = {"__model__": "Album"};
}
//create album uri if there is none
if (!results[i].album.uri) {
results[i].album.uri = 'x';
}
if (!results[i].album.name) {
results[i].album.name = '';
}
//create name if there is no one
if (!results[i].name || results[i].name == '') {
name = results[i].uri.split('/');
results[i].name = decodeURI(name[name.length - 1]) || 'Track ' + String(i);
}
//leave out unplayable items
if (results[i].name.substring(0, 12) == '[unplayable]') continue;
newalbum.push(results[i]);
newtlids.push(tlids[i]);
nextname = '';
if ((i < length - 1) && results[i + 1].album && results[i + 1].album.name) {
nextname = results[i + 1].album.name;
}
if (results[i].length == -1) {
html += '<li class="albumli"><a href="#"><h1><i class="' + iconClass + '"></i> ' + results[i].name + ' [Stream]</h1></a></li>';
newalbum = [];
newtlids = [];
nextname = '';
} else {
if ((results[i].album.name != nextname) || (nextname == '')) {
tableid = 'art' + i;
//render differently if only one track in the album
if (newalbum.length == 1) {
if (i != 0) {
html += '<li class="smalldivider"> &nbsp;</li>';
}
iconClass = getMediaClass(newalbum[0].uri);
var liID = targetmin + '-' + newalbum[0].uri;
if (target == CURRENT_PLAYLIST_TABLE) {
html += '<li class="song albumli" id="' + liID + '" tlid="' + newtlids[0] + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + newalbum[0].uri + '\',\'' + newtlids[0] + '\');">' +
'<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" onclick="return playTrackQueueByTlid(\'' + newalbum[0].uri + '\',\'' + newtlids[0] + '\');">' +
'<h1><i class="' + iconClass + '"></i> ' + newalbum[0].name + "</h1><p>";
} else {
html += '<li class="song albumli" id="' + liID + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + newalbum[0].uri + '\');">' +
'<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" onclick="return playTrackByUri(\'' + newalbum[0].uri + '\',\'' + uri + '\');">' +
'<h1><i class="' + iconClass + '"></i> ' + newalbum[0].name + "</h1><p>";
}
if (newalbum[0].artists) {
for (j = 0; j < newalbum[0].artists.length; j++) {
html += newalbum[0].artists[j].name;
html += (j == newalbum[0].artists.length - 1) ? '' : ' / ';
//stop after 3
if (j > 2) {
html += '...';
break;
}
}
}
if (newalbum[0].album.name != '') {
html += ' / ';
}
html += '<em>' + newalbum[0].album.name + '</em></p>';
html += '</a></li>';
popupData[newalbum[0].uri] = newalbum[0];
newalbum = [];
newtlids = [];
} else { //newalbum length
if (results[i].album.uri && results[i].album.name) {
iconClass = getMediaClass(newalbum[0].uri);
html += '<li class="albumdivider">';
html += '<a href="#" onclick="return showAlbum(\'' + results[i].album.uri + '\');"><img id="' +
targetmin + '-cover-' + i + '" class="artistcover" width="30" height="30" /><h1><i class="' + iconClass + '"></i> ' + results[i].album.name + '</h1><p>';
}
if (results[i].album.artists) {
for (j = 0; j < results[i].album.artists.length; j++) {
html += results[i].album.artists[j].name;
html += (j == results[i].album.artists.length - 1) ? '' : ' / ';
//stop after 3
if (j > 2) {
child += '...';
break;
}
}
}
html += '</p></a></li>';
for (j = 0; j < newalbum.length; j++) {
popupData[newalbum[j].uri] = newalbum[j];
//hERE!
var liID = targetmin + '-' + newalbum[j].uri;
if (target == CURRENT_PLAYLIST_TABLE) {
html += renderQueueSongLi(newalbum[j], liID, uri, newtlids[j]);
} else {
html += renderSongLi(newalbum[j], liID, uri);
}
}
newalbum = [];
newtlids = [];
if (results[i].album) {
coversList.push([results[i].album, i]);
}
} //newalbum length
if (results[i].album) {
coversList.push([results[i].album, i]);
}
} //albums name
}
}
tableid = "#" + tableid;
$(target).html(html);
$(target).attr('data', uri);
//retreive albumcovers
for (i = 0; i < coversList.length; i++) {
getCover(coversList[i][0], target + '-cover-' + coversList[i][1], 'small');
}
}
//process updated playlist to gui
function playlisttotable(pl, target, uri) {
var tmp = '';
$(target).html('');
var targetmin = target.substr(1);
var child = '';
for (var i = 0; i < pl.length; i++) {
if (pl[i]) {
popupData[pl[i].uri] = pl[i];
child = '<li id="' + targetmin + '-' + pl[i].uri + '"><a href="#" onclick="return popupTracks(event, \'' + uri + '\',\'' + pl[i].uri + '\');">';
child += '<h1>' + pl[i].name + "</h1>";
child += '<p>';
child += '<span style="float: right;">' + timeFromSeconds(pl[i].length / 1000) + '</span>';
for (var j = 0; j < pl[i].artists.length; j++) {
if (pl[i].artists[j]) {
child += pl[i].artists[j].name;
child += (j == pl[i].artists.length - 1) ? '' : ' / ';
//stop after 3
if (j > 2) {
child += '...';
break;
}
}
}
child += ' / <em>' + pl[i].album.name + '</em></p>';
child += '</a></li>';
tmp += child;
}
};
$(target).html(tmp);
$(target).attr('data', uri);
}
function getPlaylistTracks(uri) {
if (playlists[uri] && playlists[uri].tracks) {
return Mopidy.when(playlists[uri].tracks);
} else {
showLoading(true);
return mopidy.playlists.getItems({'uri': uri}).then(function(refs) {
return processPlaylistItems({'uri': uri, 'items': refs});
}, console.error);
}
}
function getUris(tracks) {
var results = [];
for (var i = 0; i < tracks.length; i++) {
results.push(tracks[i].uri);
}
return results;
}
function getTracksFromUri(uri, full_track_data) {
var returnTracksOrUris = function(tracks) {
return (full_track_data || false) ? tracks : getUris(tracks);
}
if (customTracklists[uri]) {
return returnTracksOrUris(customTracklists[uri]);
} else if (playlists[uri] && playlists[uri].tracks) {
return returnTracksOrUris(playlists[uri].tracks);
}
return [];
}
//convert time to human readable format
function timeFromSeconds(length) {
var d = Number(length);
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
return ((h > 0 ? h + ":" : "") + (m > 0 ? (h > 0 && m < 10 ? "0" : "") + m + ":" : "0:") + (s < 10 ? "0" : "") + s);
}
/******* Toast ***/
function toast(message, delay, textOnly) {
textOnl = textOnly || false;
message = message || "Loading...";
delay = delay || 1000;
$.mobile.loading('show', {
text: message,
textVisible: true,
theme: 'a',
textonly: textOnl
});
if (delay > 0) {
setTimeout(function() {
$.mobile.loading('hide');
}, delay);
}
}
/******************
* Modal dialogs *
******************/
function showLoading(on) {
if (on) {
$("body").css("cursor", "progress");
$.mobile.loading('show', {
text: 'Loading data from ' + PROGRAM_NAME + '. Please wait...',
textVisible: true,
theme: 'a'
});
} else {
$("body").css("cursor", "default");
$.mobile.loading('hide');
}
}
function showOffline(on) {
if (on) {
$.mobile.loading('show', {
text: 'Trying to reach ' + PROGRAM_NAME + '. Please wait...',
textVisible: true,
theme: 'a'
});
} else {
$.mobile.loading('hide');
}
}
// from http://dzone.com/snippets/validate-url-regexp
function validUri(str) {
var regexp = /^(mms|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
return regexp.test(str);
}
function validServiceUri(str) {
return validUri(str) || isServiceUri(str);
}
function getScheme(uri) {
return uri.split(':')[0].toLowerCase();
}
function isStreamUri(uri) {
var a = validUri(uri);
var b = radioExtensionsList.indexOf(getScheme(uri)) >= 0;
return a || b;
}
function getMediaClass(uri) {
var scheme = getScheme(uri);
for (var i = 0; i < uriClassList.length; i++) {
if (scheme == uriClassList[i][0]) {
return "fa " + uriClassList[i][1];
}
}
return '';
}
function getMediaHuman(uri) {
var scheme = getScheme(uri);
for (var i = 0; i < uriHumanList.length; i++) {
if (scheme == uriHumanList[i][0]) {
return uriHumanList[i][1];
}
}
return '';
}
function isServiceUri(uri) {
var scheme = getScheme(uri);
for (var i = 0; i < uriClassList.length; i++) {
if (scheme == uriClassList[i][0]) {
return true;
}
}
for (var i = 0; i < radioExtensionsList.length; i++) {
if (scheme == radioExtensionsList[i]) {
return true;
}
}
return false;
}
function isFavouritesPlaylist(playlist) {
return (playlist.name == STREAMS_PLAYLIST_NAME &&
getScheme(playlist.uri) == STREAMS_PLAYLIST_SCHEME);
}
function isSpotifyStarredPlaylist(playlist) {
var starredRegex = /spotify:user:.*:starred/g;
return (starredRegex.test(playlist.uri) && playlist.name == 'Starred');
}