fox:Automatic style changes applied by running eslint --fix

This commit is contained in:
jcass 2016-03-05 15:11:48 +02:00
parent 785d923fcf
commit 168f2c549b
7 changed files with 1441 additions and 1441 deletions

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -2,91 +2,91 @@
* @author Wouter van Wijk * @author Wouter van Wijk
*/ */
API_KEY = 'b6d34c3af91d62ab0ae00ab1b6fa8733'; API_KEY = 'b6d34c3af91d62ab0ae00ab1b6fa8733'
API_SECRET = '2c631802c2285d5d5d1502462fe42a2b'; API_SECRET = '2c631802c2285d5d5d1502462fe42a2b'
var fmcache; var fmcache
var lastfm; var lastfm
$(window).load(function () { $(window).load(function () {
// create a Cache object // create a Cache object
fmcache = new LastFMCache(); fmcache = new LastFMCache()
// create a LastFM object // create a LastFM object
lastfm = new LastFM({ lastfm = new LastFM({
apiKey : API_KEY, apiKey : API_KEY,
apiSecret : API_SECRET, apiSecret : API_SECRET,
cache : fmcache cache : fmcache
}); })
}); })
function getCover(uri, images, size) { function getCover (uri, images, size) {
var defUrl = 'images/default_cover.png'; var defUrl = 'images/default_cover.png'
$(images).attr('src', defUrl); $(images).attr('src', defUrl)
if (!uri) { if (!uri) {
return; return
} }
mopidy.library.getImages({'uris': [uri]}).then(function(imageResults) { mopidy.library.getImages({'uris': [uri]}).then(function (imageResults) {
var uri = Object.keys(imageResults)[0]; var uri = Object.keys(imageResults)[0]
if (imageResults[uri].length > 0) { if (imageResults[uri].length > 0) {
$(images).attr('src', imageResults[uri][0].uri); $(images).attr('src', imageResults[uri][0].uri)
} else { } else {
// Also check deprecated 'album.images' in case backend does not // Also check deprecated 'album.images' in case backend does not
// implement mopidy.library.getImages yet... // implement mopidy.library.getImages yet...
getCoverFromAlbum(uri, images, size); getCoverFromAlbum(uri, images, size)
} }
}); })
} }
// Note that this approach has been deprecated in Mopidy // Note that this approach has been deprecated in Mopidy
// TODO: Remove when Mopidy no longer supports getting images // TODO: Remove when Mopidy no longer supports getting images
// with 'album.images'. // with 'album.images'.
function getCoverFromAlbum(uri, images, size) { function getCoverFromAlbum (uri, images, size) {
mopidy.library.lookup({'uris': [uri]}).then(function(resultDict) { mopidy.library.lookup({'uris': [uri]}).then(function (resultDict) {
var uri = Object.keys(resultDict)[0]; var uri = Object.keys(resultDict)[0]
var track = resultDict[uri][0]; var track = resultDict[uri][0]
if (track.album && track.album.images && (track.album.images.length > 0) ) { if (track.album && track.album.images && (track.album.images.length > 0)) {
$(images).attr('src', track.album.images[0]); $(images).attr('src', track.album.images[0])
} else { } else {
// Fallback to last.fm // Fallback to last.fm
getCoverFromLastFm(track, images, size); getCoverFromLastFm(track, images, size)
} }
}); })
} }
function getCoverFromLastFm(track, images, size) { function getCoverFromLastFm (track, images, size) {
var defUrl = 'images/default_cover.png'; var defUrl = 'images/default_cover.png'
if (!(track.album || track.artist)) { if (!(track.album || track.artist)) {
return; return
} }
var albumname = track.album.name || ''; var albumname = track.album.name || ''
var artistname = ''; var artistname = ''
if ( track.album.artists && (track.album.artists.length > 0) ) { if (track.album.artists && (track.album.artists.length > 0)) {
// First look for the artist in the album // First look for the artist in the album
artistname = track.album.artists[0].name; artistname = track.album.artists[0].name
} else if (track.artists && (track.artists.length > 0) ) { } else if (track.artists && (track.artists.length > 0)) {
// Fallback to using artists for specific track // Fallback to using artists for specific track
artistname = track.artists[0].name; artistname = track.artists[0].name
} }
lastfm.album.getInfo( {artist: artistname, album: albumname}, lastfm.album.getInfo({artist: artistname, album: albumname},
{ success: function(data) { { success: function (data) {
for (var i = 0; i < data.album.image.length; i++) { for (var i = 0; i < data.album.image.length; i++) {
if ( data.album.image[i].size == size) { if (data.album.image[i].size == size) {
$(images).attr('src', data.album.image[i]['#text'] || defUrl); $(images).attr('src', data.album.image[i]['#text'] || defUrl)
} }
} }
} }
}); })
} }
function getArtistImage(nwartist, image, size) { function getArtistImage (nwartist, image, size) {
var defUrl = 'images/user_24x32.png'; var defUrl = 'images/user_24x32.png'
lastfm.artist.getInfo({artist: nwartist}, {success: function(data){ lastfm.artist.getInfo({artist: nwartist}, {success: function (data) {
for (var i = 0; i < data.artist.image.length; i++) { for (var i = 0; i < data.artist.image.length; i++) {
if ( data.artist.image[i].size == size) { if (data.artist.image[i].size == size) {
$(image).attr('src', data.artist.image[i]['#text'] || defUrl); $(image).attr('src', data.artist.image[i]['#text'] || defUrl)
} }
} }
}}); }})
} }

View File

@ -1,167 +1,167 @@
/********************************* /** *******************************
* Search * Search
*********************************/ *********************************/
function searchPressed(key) { function searchPressed (key) {
var value = $('#searchinput').val(); var value = $('#searchinput').val()
switchContent('search'); switchContent('search')
if (key == 13) { if (key == 13) {
initSearch(); initSearch()
return false; return false
} }
return true; return true
} }
//init search // init search
function initSearch() { function initSearch () {
var value = $('#searchinput').val(); var value = $('#searchinput').val()
var searchService = $('#selectSearchService').val(); var searchService = $('#selectSearchService').val()
if ((value.length < 100) && (value.length > 0)) { if ((value.length < 100) && (value.length > 0)) {
showLoading(true); showLoading(true)
//hide ios/android keyboard // hide ios/android keyboard
document.activeElement.blur(); document.activeElement.blur()
$("input").blur(); $('input').blur()
delete customTracklists[URI_SCHEME+':allresultscache']; delete customTracklists[URI_SCHEME + ':allresultscache']
delete customTracklists[URI_SCHEME+':artistresultscache']; delete customTracklists[URI_SCHEME + ':artistresultscache']
delete customTracklists[URI_SCHEME+':albumresultscache']; delete customTracklists[URI_SCHEME + ':albumresultscache']
delete customTracklists[URI_SCHEME+':trackresultscache']; delete customTracklists[URI_SCHEME + ':trackresultscache']
$("#searchartists").hide(); $('#searchartists').hide()
$("#searchalbums").hide(); $('#searchalbums').hide()
$("#searchtracks").hide(); $('#searchtracks').hide()
if (searchService != 'all') { if (searchService != 'all') {
mopidy.library.search({'query': {any:[value]}, 'uris': [searchService + ':']}).then(processSearchResults, console.error); mopidy.library.search({'query': {any:[value]}, 'uris': [searchService + ':']}).then(processSearchResults, console.error)
} else { } else {
mopidy.getUriSchemes().then(function (schemes) { mopidy.getUriSchemes().then(function (schemes) {
var query = {}, var query = {},
uris = []; uris = []
var regexp = $.map(schemes, function (scheme) { var regexp = $.map(schemes, function (scheme) {
return '^' + scheme + ':'; return '^' + scheme + ':'
}).join('|'); }).join('|')
var match = value.match(regexp); var match = value.match(regexp)
if (match) { if (match) {
var scheme = match[0]; var scheme = match[0]
query = {uri: [value]}; query = {uri: [value]}
uris = [scheme]; uris = [scheme]
} else { } else {
query = {any: [value]}; query = {any: [value]}
} }
mopidy.library.search({'query': query, 'uris': uris}).then(processSearchResults, console.error); mopidy.library.search({'query': query, 'uris': uris}).then(processSearchResults, console.error)
}); })
} }
} }
} }
/******************************************************** /** ******************************************************
* process results of a search * process results of a search
*********************************************************/ *********************************************************/
//# speed clone http://jsperf.com/cloning-an-object/2 // # speed clone http://jsperf.com/cloning-an-object/2
function clone(obj) { function clone (obj) {
var target = {}; var target = {}
for (var i in obj) { for (var i in obj) {
if (obj.hasOwnProperty(i)) { if (obj.hasOwnProperty(i)) {
target[i] = obj[i]; target[i] = obj[i]
} }
} }
return target; return target
} }
function processSearchResults(resultArr) { function processSearchResults (resultArr) {
$(SEARCH_TRACK_TABLE).empty(); $(SEARCH_TRACK_TABLE).empty()
$(SEARCH_ARTIST_TABLE).empty(); $(SEARCH_ARTIST_TABLE).empty()
$(SEARCH_ALBUM_TABLE).empty(); $(SEARCH_ALBUM_TABLE).empty()
// Merge results from different backends. // Merge results from different backends.
// TODO should of coures have multiple tables // TODO should of coures have multiple tables
var results = {'tracks': [], 'artists': [], 'albums': []}; var results = {'tracks': [], 'artists': [], 'albums': []}
var j, emptyResult = true; var j, emptyResult = true
for (var i = 0; i < resultArr.length; i++) { for (var i = 0; i < resultArr.length; i++) {
if (resultArr[i].tracks) { if (resultArr[i].tracks) {
for (j = 0; j < resultArr[i].tracks.length; j++) { for (j = 0; j < resultArr[i].tracks.length; j++) {
results.tracks.push(resultArr[i].tracks[j]); results.tracks.push(resultArr[i].tracks[j])
emptyResult = false; emptyResult = false
} }
} }
if (resultArr[i].artists) { if (resultArr[i].artists) {
for (j = 0; j < resultArr[i].artists.length; j++) { for (j = 0; j < resultArr[i].artists.length; j++) {
results.artists.push(resultArr[i].artists[j]); results.artists.push(resultArr[i].artists[j])
emptyResult = false; emptyResult = false
} }
} }
if (resultArr[i].albums) { if (resultArr[i].albums) {
for (j = 0; j < resultArr[i].albums.length; j++) { for (j = 0; j < resultArr[i].albums.length; j++) {
results.albums.push(resultArr[i].albums[j]); results.albums.push(resultArr[i].albums[j])
emptyResult = false; emptyResult = false
} }
} }
} }
customTracklists[URI_SCHEME+':trackresultscache'] = results.tracks; customTracklists[URI_SCHEME + ':trackresultscache'] = results.tracks
if (emptyResult) { if (emptyResult) {
toast('No results'); toast('No results')
showLoading(false); showLoading(false)
return false; return false
} }
if (results.artists.length > 0) { if (results.artists.length > 0) {
$("#searchartists").show(); $('#searchartists').show()
} }
if (results.albums.length > 0) { if (results.albums.length > 0) {
$("#searchalbums").show(); $('#searchalbums').show()
} }
if (results.tracks.length > 0) { if (results.tracks.length > 0) {
$("#searchtracks").show(); $('#searchtracks').show()
} }
// Returns a string where {x} in template is replaced by tokens[x]. // Returns a string where {x} in template is replaced by tokens[x].
function theme(template, tokens) { function theme (template, tokens) {
return template.replace(/{[^}]+}/g, function(match) { return template.replace(/{[^}]+}/g, function (match) {
return tokens[match.slice(1,-1)]; return tokens[match.slice(1, -1)]
}); })
} }
// 'Show more' pattern // 'Show more' pattern
var showMorePattern = '<li onclick="$(this).hide().siblings().show(); return false;"><a>Show {count} more</a></li>'; var showMorePattern = '<li onclick="$(this).hide().siblings().show(); return false;"><a>Show {count} more</a></li>'
// Artist results // Artist results
var child = ''; var child = ''
var pattern = '<li><a href="#" onclick="return showArtist(this.id)" id={id}><i class="{class}"></i> <strong>{name}</strong></a></li>'; var pattern = '<li><a href="#" onclick="return showArtist(this.id)" id={id}><i class="{class}"></i> <strong>{name}</strong></a></li>'
var tokens; var tokens
for (var i = 0; i < results.artists.length; i++) { for (var i = 0; i < results.artists.length; i++) {
tokens = { tokens = {
'id': results.artists[i].uri, 'id': results.artists[i].uri,
'name': results.artists[i].name, 'name': results.artists[i].name,
'class': getMediaClass(results.artists[i].uri) 'class': getMediaClass(results.artists[i].uri)
}; }
// Add 'Show all' item after a certain number of hits. // Add 'Show all' item after a certain number of hits.
if (i == 4 && results.artists.length > 5) { if (i == 4 && results.artists.length > 5) {
child += theme(showMorePattern, {'count': results.artists.length - i}); child += theme(showMorePattern, {'count': results.artists.length - i})
pattern = pattern.replace('<li>', '<li class="overflow">'); pattern = pattern.replace('<li>', '<li class="overflow">')
} }
child += theme(pattern, tokens); child += theme(pattern, tokens)
} }
// Inject list items, refresh listview and hide superfluous items. // Inject list items, refresh listview and hide superfluous items.
$(SEARCH_ARTIST_TABLE).html(child).listview('refresh').find('.overflow').hide(); $(SEARCH_ARTIST_TABLE).html(child).listview('refresh').find('.overflow').hide()
// Album results // Album results
child = ''; child = ''
pattern = '<li><a href="#" onclick="return showAlbum(this.id)" id="{albumId}">'; pattern = '<li><a href="#" onclick="return showAlbum(this.id)" id="{albumId}">'
pattern += '<h5 data-role="heading"><i class="{class}"></i> {albumName}</h5>'; pattern += '<h5 data-role="heading"><i class="{class}"></i> {albumName}</h5>'
pattern += '<p data-role="desc">{artistName}</p>'; pattern += '<p data-role="desc">{artistName}</p>'
pattern += '</a></li>'; pattern += '</a></li>'
for (var i = 0; i < results.albums.length; i++) { for (var i = 0; i < results.albums.length; i++) {
tokens = { tokens = {
@ -170,175 +170,175 @@ function processSearchResults(resultArr) {
'artistName': '', 'artistName': '',
'albumYear': results.albums[i].date, 'albumYear': results.albums[i].date,
'class': getMediaClass(results.albums[i].uri) 'class': getMediaClass(results.albums[i].uri)
}; }
if (results.albums[i].artists) { if (results.albums[i].artists) {
for (var j = 0; j < results.albums[i].artists.length; j++) { for (var j = 0; j < results.albums[i].artists.length; j++) {
if (results.albums[i].artists[j].name) { if (results.albums[i].artists[j].name) {
tokens.artistName += results.albums[i].artists[j].name + ' '; tokens.artistName += results.albums[i].artists[j].name + ' '
} }
} }
} }
if (tokens.albumYear) { if (tokens.albumYear) {
tokens.artistName += '(' + tokens.albumYear + ')'; tokens.artistName += '(' + tokens.albumYear + ')'
} }
// Add 'Show all' item after a certain number of hits. // Add 'Show all' item after a certain number of hits.
if (i == 4 && results.albums.length > 5) { if (i == 4 && results.albums.length > 5) {
child += theme(showMorePattern, {'count': results.albums.length - i}); child += theme(showMorePattern, {'count': results.albums.length - i})
pattern = pattern.replace('<li>', '<li class="overflow">'); pattern = pattern.replace('<li>', '<li class="overflow">')
} }
child += theme(pattern, tokens); child += theme(pattern, tokens)
} }
// Inject list items, refresh listview and hide superfluous items. // Inject list items, refresh listview and hide superfluous items.
$(SEARCH_ALBUM_TABLE).html(child).listview('refresh').find('.overflow').hide(); $(SEARCH_ALBUM_TABLE).html(child).listview('refresh').find('.overflow').hide()
$('#expandsearch').show(); $('#expandsearch').show()
// Track results // Track results
resultsToTables(results.tracks, SEARCH_TRACK_TABLE, URI_SCHEME+':trackresultscache'); resultsToTables(results.tracks, SEARCH_TRACK_TABLE, URI_SCHEME + ':trackresultscache')
showLoading(false); showLoading(false)
} }
function toggleSearch() { function toggleSearch () {
$("#albumresulttable tr").removeClass('hidden'); $('#albumresulttable tr').removeClass('hidden')
$("#artistresulttable tr").removeClass('hidden'); $('#artistresulttable tr').removeClass('hidden')
} }
/********************************* /** *******************************
* Playlists & Browse * Playlists & Browse
*********************************/ *********************************/
function getPlaylists() { function getPlaylists () {
// get playlists without tracks // get playlists without tracks
mopidy.playlists.asList().then(processGetPlaylists, console.error); mopidy.playlists.asList().then(processGetPlaylists, console.error)
} }
function getBrowseDir(rootdir) { function getBrowseDir (rootdir) {
// get directory to browse // get directory to browse
showLoading(true); showLoading(true)
if (!rootdir) { if (!rootdir) {
browseStack.pop(); browseStack.pop()
rootdir = browseStack[browseStack.length - 1]; rootdir = browseStack[browseStack.length - 1]
} else { } else {
browseStack.push(rootdir); browseStack.push(rootdir)
} }
if (!rootdir) { if (!rootdir) {
rootdir = null; rootdir = null
} }
mopidy.library.browse({'uri': rootdir}).then(processBrowseDir, console.error); mopidy.library.browse({'uri': rootdir}).then(processBrowseDir, console.error)
} }
function getCurrentPlaylist() { function getCurrentPlaylist () {
mopidy.tracklist.getTlTracks().then(processCurrentPlaylist, console.error); mopidy.tracklist.getTlTracks().then(processCurrentPlaylist, console.error)
} }
/******************************************************** /** ******************************************************
* Show tracks of playlist * Show tracks of playlist
********************************************************/ ********************************************************/
function togglePlaylists() { function togglePlaylists () {
if ($(window).width() <= 960) { if ($(window).width() <= 960) {
$('#playlisttracksdiv').toggle(); $('#playlisttracksdiv').toggle();
//Hide other div // Hide other div
($('#playlisttracksdiv').is(":visible")) ? $('#playlistslistdiv').hide() : $('#playlistslistdiv').show(); ($('#playlisttracksdiv').is(':visible')) ? $('#playlistslistdiv').hide() : $('#playlistslistdiv').show()
} else { } else {
$('#playlisttracksdiv').show(); $('#playlisttracksdiv').show()
$('#playlistslistdiv').show(); $('#playlistslistdiv').show()
} }
return true; return true
} }
function showTracklist(uri) { function showTracklist (uri) {
$(PLAYLIST_TABLE).empty(); $(PLAYLIST_TABLE).empty()
togglePlaylists(); togglePlaylists()
var tracks = getPlaylistTracks(uri).then(function(tracks) { var tracks = getPlaylistTracks(uri).then(function (tracks) {
resultsToTables(tracks, PLAYLIST_TABLE, uri); resultsToTables(tracks, PLAYLIST_TABLE, uri)
}); })
showLoading(false); showLoading(false)
updatePlayIcons(uri); updatePlayIcons(uri)
$('#playlistslist li a').each(function() { $('#playlistslist li a').each(function () {
$(this).removeClass("playlistactive"); $(this).removeClass('playlistactive')
if (this.id == uri) { if (this.id == uri) {
$(this).addClass('playlistactive'); $(this).addClass('playlistactive')
} }
}); })
return false; return false
} }
/****** /** ****
* Lookups * Lookups
*/ */
function showArtist(nwuri) { function showArtist (nwuri) {
$('#popupQueue').popup('close'); $('#popupQueue').popup('close')
$('#popupTracks').popup('close'); $('#popupTracks').popup('close')
$('#controlsmodal').popup('close'); $('#controlsmodal').popup('close')
$(ARTIST_TABLE).empty(); $(ARTIST_TABLE).empty()
//TODO cache // TODO cache
$('#h_artistname').html(''); $('#h_artistname').html('')
showLoading(true); showLoading(true)
mopidy.library.lookup({'uris': [nwuri]}).then(function(resultDict) { mopidy.library.lookup({'uris': [nwuri]}).then(function (resultDict) {
var resultArr = resultDict[nwuri]; var resultArr = resultDict[nwuri]
resultArr.uri = nwuri; resultArr.uri = nwuri
processArtistResults(resultArr); processArtistResults(resultArr)
}, console.error); }, console.error)
switchContent('artists', nwuri); switchContent('artists', nwuri)
scrollToTop(); scrollToTop()
return false; return false
} }
function showAlbum(uri) { function showAlbum (uri) {
$('#popupQueue').popup('close'); $('#popupQueue').popup('close')
$('#popupTracks').popup('close'); $('#popupTracks').popup('close')
$('#controlsmodal').popup('close'); $('#controlsmodal').popup('close')
$(ALBUM_TABLE).empty(); $(ALBUM_TABLE).empty()
//fill from cache // fill from cache
var pl = getTracksFromUri(uri, true); var pl = getTracksFromUri(uri, true)
if (pl.length>0) { if (pl.length > 0) {
albumTracksToTable(pl, ALBUM_TABLE, uri); albumTracksToTable(pl, ALBUM_TABLE, uri)
var albumname = getAlbum(pl); var albumname = getAlbum(pl)
var artistname = getArtist(pl); var artistname = getArtist(pl)
$('#h_albumname').html(albumname); $('#h_albumname').html(albumname)
$('#h_albumartist').html(artistname); $('#h_albumartist').html(artistname)
$('#coverpopupalbumname').html(albumname); $('#coverpopupalbumname').html(albumname)
$('#coverpopupartist').html(artistname); $('#coverpopupartist').html(artistname)
showLoading(false); showLoading(false)
mopidy.library.lookup({'uris': [uri]}).then(function(resultDict) { mopidy.library.lookup({'uris': [uri]}).then(function (resultDict) {
var resultArr = resultDict[uri]; var resultArr = resultDict[uri]
resultArr.uri = uri; resultArr.uri = uri
processAlbumResults(resultArr); processAlbumResults(resultArr)
}, console.error); }, console.error)
} else { } else {
showLoading(true); showLoading(true)
$('#h_albumname').html(''); $('#h_albumname').html('')
$('#h_albumartist').html(''); $('#h_albumartist').html('')
mopidy.library.lookup({'uris': [uri]}).then(function(resultDict) { mopidy.library.lookup({'uris': [uri]}).then(function (resultDict) {
var resultArr = resultDict[uri]; var resultArr = resultDict[uri]
resultArr.uri = uri; resultArr.uri = uri
processAlbumResults(resultArr); processAlbumResults(resultArr)
}, console.error); }, console.error)
} }
//show page // show page
switchContent('albums', uri); switchContent('albums', uri)
scrollToTop(); scrollToTop()
return false; return false
} }
function getSearchSchemes() { function getSearchSchemes () {
mopidy.getUriSchemes().then( mopidy.getUriSchemes().then(
function(schemesArray) { function (schemesArray) {
var humanIndex; var humanIndex
$("#selectSearchService").children().remove().end(); $('#selectSearchService').children().remove().end()
$("#selectSearchService").append(new Option('All services', 'all')); $('#selectSearchService').append(new Option('All services', 'all'))
for (var i = 0; i < schemesArray.length; i++) { for (var i = 0; i < schemesArray.length; i++) {
for (var j = 0; j < uriHumanList.length; j++) { for (var j = 0; j < uriHumanList.length; j++) {
if (uriHumanList[j][0] == schemesArray[i].toLowerCase() ) { if (uriHumanList[j][0] == schemesArray[i].toLowerCase()) {
$("#selectSearchService").append(new Option(uriHumanList[j][1], schemesArray[i])); $('#selectSearchService').append(new Option(uriHumanList[j][1], schemesArray[i]))
} }
} }
} }
$("#selectSearchService").selectmenu( "refresh", true ); $('#selectSearchService').selectmenu( 'refresh', true)
}, console.error }, console.error
); )
} }

View File

@ -5,249 +5,249 @@
* *
*/ */
/******************************************************** /** ******************************************************
* process results of a (new) currently playing track * process results of a (new) currently playing track
*********************************************************/ *********************************************************/
function processCurrenttrack(data) { function processCurrenttrack (data) {
setSongInfo(data); setSongInfo(data)
} }
/******************************************************** /** ******************************************************
* process results of volume * process results of volume
*********************************************************/ *********************************************************/
function processVolume(data) { function processVolume (data) {
setVolume(data); setVolume(data)
} }
/******************************************************** /** ******************************************************
* process results of mute * process results of mute
*********************************************************/ *********************************************************/
function processMute(data) { function processMute (data) {
setMute(data); setMute(data)
} }
/******************************************************** /** ******************************************************
* process results of a repeat * process results of a repeat
*********************************************************/ *********************************************************/
function processRepeat(data) { function processRepeat (data) {
setRepeat(data); setRepeat(data)
} }
/******************************************************** /** ******************************************************
* process results of random * process results of random
*********************************************************/ *********************************************************/
function processRandom(data) { function processRandom (data) {
setRandom(data); setRandom(data)
} }
/******************************************************** /** ******************************************************
* process results of consume * process results of consume
*********************************************************/ *********************************************************/
function processConsume(data) { function processConsume (data) {
setConsume(data); setConsume(data)
} }
/******************************************************** /** ******************************************************
* process results of single * process results of single
*********************************************************/ *********************************************************/
function processSingle(data) { function processSingle (data) {
setSingle(data); setSingle(data)
} }
/******************************************************** /** ******************************************************
* process results of current position * process results of current position
*********************************************************/ *********************************************************/
function processCurrentposition(data) { function processCurrentposition (data) {
setPosition(parseInt(data)); setPosition(parseInt(data))
} }
/******************************************************** /** ******************************************************
* process results playstate * process results playstate
*********************************************************/ *********************************************************/
function processPlaystate(data) { function processPlaystate (data) {
if (data == 'playing') { if (data == 'playing') {
setPlayState(true); setPlayState(true)
} else { } else {
setPlayState(false); setPlayState(false)
} }
} }
/******************************************************** /** ******************************************************
* process results of a browse list * process results of a browse list
*********************************************************/ *********************************************************/
function processBrowseDir(resultArr) { function processBrowseDir (resultArr) {
var backHtml = '<li style="background-color:#ccc"><a href="#" onclick="return getBrowseDir();"><h1 class="trackname"><i class="fa fa-arrow-circle-left"></i> Back</h1></a></li>'; var backHtml = '<li style="background-color:#ccc"><a href="#" onclick="return getBrowseDir();"><h1 class="trackname"><i class="fa fa-arrow-circle-left"></i> Back</h1></a></li>'
if ( (!resultArr) || (resultArr === '') || (resultArr.length === 0) ) { if ((!resultArr) || (resultArr === '') || (resultArr.length === 0)) {
$('#browsepath').html('No tracks found...'); $('#browsepath').html('No tracks found...')
$('#browselist').html(backHtml); $('#browselist').html(backHtml)
showLoading(false); showLoading(false)
return; return
} }
$('#browselist').empty(); $('#browselist').empty()
var child = "", rooturi = "", uri = resultArr[0].uri; var child = '', rooturi = '', uri = resultArr[0].uri
//check root uri // check root uri
//find last : or / (spltting the result) // find last : or / (spltting the result)
//do it twice, since. // do it twice, since.
var colonindex = uri.lastIndexOf(':'); var colonindex = uri.lastIndexOf(':')
var slashindex = uri.lastIndexOf('/'); var slashindex = uri.lastIndexOf('/')
var lastindex = (colonindex > slashindex) ? colonindex : slashindex; var lastindex = (colonindex > slashindex) ? colonindex : slashindex
rooturi = uri.slice(0, lastindex); rooturi = uri.slice(0, lastindex)
if (resultArr[0].type == 'track' ) { if (resultArr[0].type == 'track') {
rooturi = rooturi.replace(":track:", ":directory:"); rooturi = rooturi.replace(':track:', ':directory:')
} }
colonindex = rooturi.lastIndexOf(':'); colonindex = rooturi.lastIndexOf(':')
slashindex = rooturi.lastIndexOf('/'); slashindex = rooturi.lastIndexOf('/')
lastindex = (colonindex > slashindex) ? colonindex : slashindex; lastindex = (colonindex > slashindex) ? colonindex : slashindex
rooturi = rooturi.slice(0, lastindex); rooturi = rooturi.slice(0, lastindex)
if (browseStack.length > 0) { if (browseStack.length > 0) {
child += backHtml; child += backHtml
} }
browseTracks = []; browseTracks = []
for (var i = 0, index = 0; i < resultArr.length; i++) { for (var i = 0, index = 0; i < resultArr.length; i++) {
iconClass = getMediaClass(resultArr[i].uri); iconClass = getMediaClass(resultArr[i].uri)
if (resultArr[i].type == 'track') { if (resultArr[i].type == 'track') {
//console.log(resultArr[i]); // console.log(resultArr[i]);
mopidy.library.lookup({'uris': [resultArr[i].uri]}).then(function (resultDict) { mopidy.library.lookup({'uris': [resultArr[i].uri]}).then(function (resultDict) {
var lookupUri = Object.keys(resultDict)[0]; var lookupUri = Object.keys(resultDict)[0]
popupData[lookupUri] = resultDict[lookupUri][0]; popupData[lookupUri] = resultDict[lookupUri][0]
browseTracks.push(resultDict[lookupUri][0]); browseTracks.push(resultDict[lookupUri][0])
}, console.error); }, console.error)
child += '<li class="song albumli" id="browselisttracks-' + resultArr[i].uri + '">' + child += '<li class="song albumli" id="browselisttracks-' + resultArr[i].uri + '">' +
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\', \'' + resultArr[i].uri + '\', \'' + index + '\');">' + '<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\', \'' + resultArr[i].uri + '\', \'' + index + '\');">' +
'<i class="fa fa-ellipsis-v"></i></a>' + '<i class="fa fa-ellipsis-v"></i></a>' +
'<a href="#" class="browsetrack" onclick="return playBrowsedTracks(PLAY_ALL, ' + index + ');" id="' + resultArr[i].uri + '<a href="#" class="browsetrack" onclick="return playBrowsedTracks(PLAY_ALL, ' + index + ');" id="' + resultArr[i].uri +
'"><h1 class="trackname"><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>'; '"><h1 class="trackname"><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>'
index++; index++
} else { } else {
if (browseStack.length > 0) { if (browseStack.length > 0) {
iconClass="fa fa-folder-o"; iconClass = "fa fa-folder-o"
} }
child += '<li><a href="#" onclick="return getBrowseDir(this.id);" id="' + resultArr[i].uri + child += '<li><a href="#" onclick="return getBrowseDir(this.id);" id="' + resultArr[i].uri +
'""><h1 class="trackname"><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>'; '""><h1 class="trackname"><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>'
} }
} }
$('#browselist').html(child); $('#browselist').html(child)
if (browseStack.length > 0 ) { if (browseStack.length > 0) {
child = getMediaHuman(uri); child = getMediaHuman(uri)
iconClass = getMediaClass(uri); iconClass = getMediaClass(uri)
$('#browsepath').html('<i class="' + iconClass + '"></i> ' + child); $('#browsepath').html('<i class="' + iconClass + '"></i> ' + child)
} else { } else {
$('#browsepath').html(''); $('#browsepath').html('')
} }
updatePlayIcons(songdata.track.uri, songdata.tlid); updatePlayIcons(songdata.track.uri, songdata.tlid)
showLoading(false); showLoading(false)
} }
/******************************************************** /** ******************************************************
* process results of list of playlists of the user * process results of list of playlists of the user
*********************************************************/ *********************************************************/
function processGetPlaylists(resultArr) { function processGetPlaylists (resultArr) {
if ((!resultArr) || (resultArr === '')) { if ((!resultArr) || (resultArr === '')) {
$('#playlistslist').empty(); $('#playlistslist').empty()
return; return
} }
var tmp = '', favourites = '', starred = ''; var tmp = '', favourites = '', starred = ''
for (var i = 0; i < resultArr.length; i++) { for (var i = 0; i < resultArr.length; i++) {
var li_html = '<li><a href="#" onclick="return showTracklist(this.id);" id="' + resultArr[i].uri + '">'; var li_html = '<li><a href="#" onclick="return showTracklist(this.id);" id="' + resultArr[i].uri + '">'
if(isSpotifyStarredPlaylist(resultArr[i])) { if (isSpotifyStarredPlaylist(resultArr[i])) {
starred = li_html + '&#9733; Spotify Starred Tracks</a></li>' + tmp; starred = li_html + '&#9733; Spotify Starred Tracks</a></li>' + tmp
} else if (isFavouritesPlaylist(resultArr[i])) { } else if (isFavouritesPlaylist(resultArr[i])) {
favourites = li_html + '&hearts; Musicbox Favourites</a></li>'; favourites = li_html + '&hearts; Musicbox Favourites</a></li>'
} else { } else {
tmp = tmp + li_html + '<i class="' + getMediaClass(resultArr[i].uri) + '"></i> ' + resultArr[i].name + '</a></li>'; tmp = tmp + li_html + '<i class="' + getMediaClass(resultArr[i].uri) + '"></i> ' + resultArr[i].name + '</a></li>'
} }
} }
// Prepend the user's Spotify "Starred" playlist and favourites to the results. (like Spotify official client). // Prepend the user's Spotify "Starred" playlist and favourites to the results. (like Spotify official client).
tmp = favourites + starred + tmp; tmp = favourites + starred + tmp
$('#playlistslist').html(tmp); $('#playlistslist').html(tmp)
scrollToTracklist(); scrollToTracklist()
showLoading(false); showLoading(false)
} }
/******************************************************** /** ******************************************************
* process results of a returned list of playlist track refs * process results of a returned list of playlist track refs
*********************************************************/ *********************************************************/
function processPlaylistItems(resultDict) { function processPlaylistItems (resultDict) {
if (resultDict.items.length === 0) { if (resultDict.items.length === 0) {
console.log('Playlist', resultDict.uri, 'is empty'); console.log('Playlist', resultDict.uri, 'is empty')
showLoading(false); showLoading(false)
return; return
} }
var trackUris = []; var trackUris = []
for (i = 0; i < resultDict.items.length; i++) { for (i = 0; i < resultDict.items.length; i++) {
trackUris.push(resultDict.items[i].uri); trackUris.push(resultDict.items[i].uri)
} }
return mopidy.library.lookup({'uris': trackUris}).then(function(tracks) { return mopidy.library.lookup({'uris': trackUris}).then(function (tracks) {
// Transform from dict to list and cache result // Transform from dict to list and cache result
var newplaylisturi = resultDict.uri; var newplaylisturi = resultDict.uri
playlists[newplaylisturi] = {'uri':newplaylisturi, 'tracks':[]}; playlists[newplaylisturi] = {'uri':newplaylisturi, 'tracks':[]}
for (i = 0; i < trackUris.length; i++) { for (i = 0; i < trackUris.length; i++) {
playlists[newplaylisturi].tracks.push(tracks[trackUris[i]][0]); playlists[newplaylisturi].tracks.push(tracks[trackUris[i]][0])
} }
showLoading(false); showLoading(false)
return playlists[newplaylisturi].tracks; return playlists[newplaylisturi].tracks
}); })
} }
/******************************************************** /** ******************************************************
* process results of the queue, the current playlist * process results of the queue, the current playlist
*********************************************************/ *********************************************************/
function processCurrentPlaylist(resultArr) { function processCurrentPlaylist (resultArr) {
currentplaylist = resultArr; currentplaylist = resultArr
resultsToTables(currentplaylist, CURRENT_PLAYLIST_TABLE); resultsToTables(currentplaylist, CURRENT_PLAYLIST_TABLE)
mopidy.playback.getCurrentTlTrack().then(processCurrenttrack, console.error); mopidy.playback.getCurrentTlTrack().then(processCurrenttrack, console.error)
updatePlayIcons(songdata.track.uri, songdata.tlid); updatePlayIcons(songdata.track.uri, songdata.tlid)
} }
/******************************************************** /** ******************************************************
* process results of an artist lookup * process results of an artist lookup
*********************************************************/ *********************************************************/
function processArtistResults(resultArr) { function processArtistResults (resultArr) {
if (!resultArr || (resultArr.length === 0)) { if (!resultArr || (resultArr.length === 0)) {
$('#h_artistname').text('Artist not found...'); $('#h_artistname').text('Artist not found...')
getCover('', '#artistviewimage, #artistpopupimage', 'extralarge'); getCover('', '#artistviewimage, #artistpopupimage', 'extralarge')
showLoading(false); showLoading(false)
return; return
} }
customTracklists[resultArr.uri] = resultArr; customTracklists[resultArr.uri] = resultArr
resultsToTables(resultArr, ARTIST_TABLE, resultArr.uri); resultsToTables(resultArr, ARTIST_TABLE, resultArr.uri)
var artistname = getArtist(resultArr); var artistname = getArtist(resultArr)
$('#h_artistname, #artistpopupname').html(artistname); $('#h_artistname, #artistpopupname').html(artistname)
getArtistImage(artistname, '#artistviewimage, #artistpopupimage', 'extralarge'); getArtistImage(artistname, '#artistviewimage, #artistpopupimage', 'extralarge')
showLoading(false); showLoading(false)
} }
/******************************************************** /** ******************************************************
* process results of an album lookup * process results of an album lookup
*********************************************************/ *********************************************************/
function processAlbumResults(resultArr) { function processAlbumResults (resultArr) {
if (!resultArr || (resultArr.length === 0)) { if (!resultArr || (resultArr.length === 0)) {
$('#h_albumname').text('Album not found...'); $('#h_albumname').text('Album not found...')
getCover('', '#albumviewcover, #coverpopupimage', 'extralarge'); getCover('', '#albumviewcover, #coverpopupimage', 'extralarge')
showLoading(false); showLoading(false)
return; return
} }
customTracklists[resultArr.uri] = resultArr; customTracklists[resultArr.uri] = resultArr
albumTracksToTable(resultArr, ALBUM_TABLE, resultArr.uri); albumTracksToTable(resultArr, ALBUM_TABLE, resultArr.uri)
var albumname = getAlbum(resultArr); var albumname = getAlbum(resultArr)
var artistname = getArtist(resultArr); var artistname = getArtist(resultArr)
$('#h_albumname').html(albumname); $('#h_albumname').html(albumname)
$('#h_albumartist').html(artistname); $('#h_albumartist').html(artistname)
$('#coverpopupalbumname').html(albumname); $('#coverpopupalbumname').html(albumname)
$('#coverpopupartist').html(artistname); $('#coverpopupartist').html(artistname)
getCover(resultArr[0].uri, '#albumviewcover, #coverpopupimage', 'extralarge'); getCover(resultArr[0].uri, '#albumviewcover, #coverpopupimage', 'extralarge')
showLoading(false); showLoading(false)
} }

View File

@ -1,26 +1,26 @@
var progressTimer; var progressTimer
var progressElement = document.getElementById('trackslider'); var progressElement = document.getElementById('trackslider')
var positionNode = document.createTextNode(''); var positionNode = document.createTextNode('')
var durationNode = document.createTextNode(''); var durationNode = document.createTextNode('')
var START_BEATS = 5; // 0.5 seconds, needs to be less than 1s to prevent unwanted updates. var START_BEATS = 5 // 0.5 seconds, needs to be less than 1s to prevent unwanted updates.
var RUN_BEATS = 300; // 30 seconds assuming default timer update rate of 100ms var RUN_BEATS = 300 // 30 seconds assuming default timer update rate of 100ms
var callbackHeartbeats = 0; // Timer will check syncs on every n-number of calls. var callbackHeartbeats = 0 // Timer will check syncs on every n-number of calls.
var targetPosition = null; var targetPosition = null
var MAX_SYNCS = 5; // Maximum number of consecutive successful syncs to perform. var MAX_SYNCS = 5 // Maximum number of consecutive successful syncs to perform.
var syncsLeft = MAX_SYNCS; var syncsLeft = MAX_SYNCS
var synced = false; var synced = false
var consecutiveSyncs = 0; var consecutiveSyncs = 0
document.getElementById('songelapsed').appendChild(positionNode); document.getElementById('songelapsed').appendChild(positionNode)
document.getElementById('songlength').appendChild(durationNode); document.getElementById('songlength').appendChild(durationNode)
function timerCallback(position, duration, isRunning) { function timerCallback (position, duration, isRunning) {
updateTimers(position, duration, isRunning); updateTimers(position, duration, isRunning)
if (callbackHeartbeats === 0) { if (callbackHeartbeats === 0) {
callbackHeartbeats = getHeartbeat(); callbackHeartbeats = getHeartbeat()
} }
if (mopidy && position > 0) { if (mopidy && position > 0) {
@ -29,102 +29,102 @@ function timerCallback(position, duration, isRunning) {
// Get time position from Mopidy on every nth callback until // Get time position from Mopidy on every nth callback until
// synced. // synced.
mopidy.playback.getTimePosition().then( mopidy.playback.getTimePosition().then(
function(mopidy_position) { function (mopidy_position) {
syncTimer(position, mopidy_position); syncTimer(position, mopidy_position)
} }
); )
} }
} }
} }
function updateTimers(position, duration, isRunning) { function updateTimers (position, duration, isRunning) {
var ready = !(duration == Infinity && position === 0 && !isRunning); // Timer has been properly initialized. var ready = !(duration == Infinity && position === 0 && !isRunning) // Timer has been properly initialized.
var streaming = (duration == Infinity && position > 0); // Playing a stream. var streaming = (duration == Infinity && position > 0) // Playing a stream.
var ok = synced && isRunning; // Normal operation. var ok = synced && isRunning // Normal operation.
var syncing = !synced && isRunning; // Busy syncing. var syncing = !synced && isRunning // Busy syncing.
if (!ready) { if (!ready) {
//Make sure that default values are displayed while the timer is being initialized. // Make sure that default values are displayed while the timer is being initialized.
positionNode.nodeValue = ''; positionNode.nodeValue = ''
durationNode.nodeValue = ''; durationNode.nodeValue = ''
$("#trackslider").val(0).slider('refresh'); $('#trackslider').val(0).slider('refresh')
} else { } else {
durationNode.nodeValue = format(duration || Infinity); durationNode.nodeValue = format(duration || Infinity)
if (syncing) { if (syncing) {
if (!targetPosition) { if (!targetPosition) {
// Waiting for Mopidy to provide a target position. // Waiting for Mopidy to provide a target position.
positionNode.nodeValue = '(wait)'; positionNode.nodeValue = '(wait)'
} else { } else {
// Busy seeking to new target position. // Busy seeking to new target position.
positionNode.nodeValue = '(sync)'; positionNode.nodeValue = '(sync)'
} }
} else if (synced || streaming) { } else if (synced || streaming) {
positionNode.nodeValue = format(position); positionNode.nodeValue = format(position)
} }
} }
if (ok) { if (ok) {
// Don't update the track slider unless it is synced and running. // Don't update the track slider unless it is synced and running.
// (prevents awkward 'jitter' animation). // (prevents awkward 'jitter' animation).
$("#trackslider").val(position).slider('refresh'); $('#trackslider').val(position).slider('refresh')
} }
} }
function getHeartbeat() { function getHeartbeat () {
if (syncsLeft > 0 && callbackHeartbeats === 0) { if (syncsLeft > 0 && callbackHeartbeats === 0) {
// Step back exponentially while increasing heartbeat. // Step back exponentially while increasing heartbeat.
return Math.round(delay_exponential(5, 2, MAX_SYNCS - syncsLeft)); return Math.round(delay_exponential(5, 2, MAX_SYNCS - syncsLeft))
} else if (syncsLeft === 0 && callbackHeartbeats === 0) { } else if (syncsLeft === 0 && callbackHeartbeats === 0) {
// Sync completed, keep checking using maximum number of heartbeats. // Sync completed, keep checking using maximum number of heartbeats.
return RUN_BEATS; return RUN_BEATS
} else { } else {
return START_BEATS; return START_BEATS
} }
} }
function syncTimer(current, target) { function syncTimer (current, target) {
if (target) { if (target) {
var drift = Math.abs(target - current); var drift = Math.abs(target - current)
if (drift <= 500) { if (drift <= 500) {
syncsLeft--; syncsLeft--
// Less than 500ms == in sync. // Less than 500ms == in sync.
if (++consecutiveSyncs == 2) { if (++consecutiveSyncs == 2) {
// Need at least two consecutive syncs to know that Mopidy // Need at least two consecutive syncs to know that Mopidy
// is progressing playback and we are in sync. // is progressing playback and we are in sync.
synced = true; synced = true
targetPosition = null; targetPosition = null
consecutiveSyncs = 0; consecutiveSyncs = 0
} }
} else { } else {
// Drift is too large, re-sync with Mopidy. // Drift is too large, re-sync with Mopidy.
reset(); reset()
targetPosition = target; targetPosition = target
progressTimer.set(targetPosition); progressTimer.set(targetPosition)
} }
} }
} }
function toInt(value) { function toInt (value) {
return value.match(/^\w*\d+\w*$/) ? parseInt(value) : null; return value.match(/^\w*\d+\w*$/) ? parseInt(value) : null
} }
function format(milliseconds) { function format (milliseconds) {
if (milliseconds === Infinity) { if (milliseconds === Infinity) {
return '(n/a)'; return '(n/a)'
} else if (milliseconds === 0) { } else if (milliseconds === 0) {
return '0:00'; return '0:00'
} }
var seconds = Math.floor(milliseconds / 1000); var seconds = Math.floor(milliseconds / 1000)
var minutes = Math.floor(seconds / 60); var minutes = Math.floor(seconds / 60)
seconds = seconds % 60; seconds = seconds % 60
seconds = seconds < 10 ? '0' + seconds : seconds; seconds = seconds < 10 ? '0' + seconds : seconds
return minutes + ':' + seconds; return minutes + ':' + seconds
} }
function delay_exponential(base, growthFactor, attempts) { function delay_exponential (base, growthFactor, attempts) {
/*Calculate number of beats between syncs based on exponential function. /* Calculate number of beats between syncs based on exponential function.
The format is:: The format is::
base * growthFactor ^ (attempts - 1) base * growthFactor ^ (attempts - 1)
@ -134,43 +134,43 @@ function delay_exponential(base, growthFactor, attempts) {
Base must be greater than 0. Base must be greater than 0.
*/ */
if (base == 'rand') { if (base == 'rand') {
base = Math.random(); base = Math.random()
} }
beats = base * (Math.pow(growthFactor, (attempts - 1))); beats = base * (Math.pow(growthFactor, (attempts - 1)))
return beats; return beats
} }
function reset() { function reset () {
synced = false; synced = false
consecutiveSyncs = 0; consecutiveSyncs = 0
syncsLeft = MAX_SYNCS; syncsLeft = MAX_SYNCS
callbackHeartbeats = START_BEATS; callbackHeartbeats = START_BEATS
targetPosition = null; targetPosition = null
} }
function setProgressTimer(pos) { function setProgressTimer (pos) {
reset(); reset()
targetPosition = pos; targetPosition = pos
progressTimer.set(pos); progressTimer.set(pos)
if (!play) { if (!play) {
// Set lapsed time and slider position directly as timer callback is not currently // Set lapsed time and slider position directly as timer callback is not currently
// running. // running.
positionNode.nodeValue = format(pos); positionNode.nodeValue = format(pos)
$("#trackslider").val(pos).slider('refresh'); $('#trackslider').val(pos).slider('refresh')
} }
} }
function updatePosition(pos) { function updatePosition (pos) {
positionNode.nodeValue = format(pos); positionNode.nodeValue = format(pos)
} }
function startProgressTimer() { function startProgressTimer () {
reset(); reset()
progressTimer.start(); progressTimer.start()
} }
function resetProgressTimer() { function resetProgressTimer () {
progressTimer.reset(); progressTimer.reset()
reset(); reset()
targetPosition = 0; targetPosition = 0
} }