Something went wrong on our end
Select Git revision
ai-sso-server.service
player.js 10.51 KiB
// player.js
// Player
djr.Player = function(backend, selector) {
this.backend = backend;
this.playlist = new djr.Playlist();
this.old_songs = [];
this.cur_song = null;
this.auto_extend = true;
// Setup the jPlayer interface.
this.circleplayer = new CirclePlayer(selector, {}, {
supplied: 'mp3',
solution: 'html, flash',
swfPath: '/static/js',
cssSelectorAncestor: '#cp_container',
error: djr.playerError
});
this.player = this.circleplayer.player;
this.player.bind($.jPlayer.event.ended + '.djr',
function () {djr.state.player.nextSong(); });
};
djr.Player.prototype.hideAllChunks = function() {
$('.chunk .chunk_inner').hide();
};
// Callback for removechunk click.
djr.Player.prototype.removeChunk = function(chunk_id) {
this.playlist.removeChunk(chunk_id);
$('#chunk_' + chunk_id).remove();
this.savePlaylist();
// If the playlist is now empty, switch to a new uuid.
if (this.playlist.isEmpty()) {
this.clearPlaylist();
}
};
// Remove a single song.
djr.Player.prototype.removeSong = function(song) {
$('#song_' + song).remove();
var chunk_to_remove = this.playlist.removeSong(song);
this.savePlaylist();
if (chunk_to_remove > 0) {
$('#chunk_' + chunk_to_remove).remove();
}
};
// Save the current playlist.
djr.Player.prototype.savePlaylist = function() {
this.backend.savePlaylist(this.playlist.uuid, '', this.playlist.allSongs());
};
// Save the current playlist.
djr.Player.prototype.savePlaylistWithTitle = function(title) {
this.backend.savePlaylist(djr.generateRandomId(), title, this.playlist.allSongs());
// Merge all existing chunks into one, named as the playlist.
this.mergePlaylistChunks('playlist: ' + title);
};
// Completely clear out the current playlist, and replace it with
// a new empty one.
djr.Player.prototype.clearPlaylist = function() {
this.playlist = new djr.Playlist();
$('#playlistDiv').empty();
djr.debug('new playlist: ' + this.playlist.uuid);
};
// Merge all chunks into a single one.
djr.Player.prototype.mergePlaylistChunks = function(title) {
// Reduce the playlist to a single chunk.
this.playlist = this.playlist.merge(title);
// Shuffle the HTML data around (so we don't have to necessarily
// fetch it again from the server). This is done in a few steps:
// 1) Copy all .chunk_inner data in a temp
var plhtml = [];
$('.chunk .chunk_inner').each(function(idx) {
plhtml.push($(this).html());
});
// 2) Remove all the .chunk divs.
$('#playlistDiv').empty();
// also: $('.chunk').remove();
// 3) Create a new chunk div.
var chunk_id = this.playlist.chunks[0];
var chunk = this.playlist.chunk_map[chunk_id];
this.setChunkHtml(chunk, chunk_id, plhtml.join(''));
};
// Search!
djr.Player.prototype.search = function(query) {
var player = this;
this.backend.search(query, function(results) {
var songs = [];
$.each(results, function(idx, item) {
songs.push(item.sha1);
});
if (songs.length == 0) {
djr.showSearchWarning('No results found.');
djr.debug('No results found.');
return;
}
// Create a chunk of unique new songs.
player.createChunk(songs, query);
});
};
// Request N last uploaded songs
djr.Player.prototype.lastPlaylist = function(num) {
var player = this;
var title = "Last " + num + " Songs Uploaded";
this.backend.lastPlaylist(num, function(results) {
var songs = results;
if (songs.length == 0) {
djr.debug('No results found.');
return;
}
// Create a chunk of unique new songs.
player.createChunk(songs, title);
});
};
djr.Player.prototype.randomPlaylist = function(num) {
var player = this;
var title = "" + num + " Random Songs ";
this.backend.randomPlaylist(num, function(results) {
var songs = results;
if (songs.length == 0) {
djr.debug('No results found.');
return;
}
// Create a chunk of unique new songs.
player.createChunk(songs, title);
});
};
djr.Player.prototype.neverPlayedPlaylist = function(num) {
var player = this;
var title = "" + num + " Never Played Songs";
this.backend.neverPlayedPlaylist(num, function(results) {
var songs = results;
if (songs.length == 0) {
djr.debug('No results found.');
return;
}
// Create a chunk of unique new songs.
player.createChunk(songs, title);
});
};
djr.Player.prototype.mostPlayedPlaylist = function(num) {
var player = this;
var title = "" + num + " Most Played Songs";
this.backend.mostPlayedPlaylist(num, function(results) {
var songs = [];
$.each(results, function(idx, item) {
songs.push(item.sha1);
});
if (songs.length == 0) {
djr.debug('No results found.');
return;
}
// Create a chunk of unique new songs.
player.createChunk(songs, title);
});
};
djr.Player.prototype.loadPlaylist = function(uuid) {
var player = this;
djr.debug('loading playlist: ' + uuid);
this.backend.getPlaylist(uuid, function(plist) {
var chunk_title;
if (!plist.title) {
chunk_title = 'playlist: ' + plist.uuid;
} else {
chunk_title = 'playlist: ' + plist.title;
}
player.clearPlaylist();
player.createChunk(plist.songs, chunk_title);
});
};
// Extend the current playlist with suggestions.
djr.Player.prototype.extendCurrentPlaylist = function() {
var player = this;
var cur_songs = this.playlist.allSongs();
this.backend.moreLikeThese(5, cur_songs, function(results) {
player.createChunk(results, 'suggestions');
});
};
// Automatically extend the current playlist using Markov-based
// suggestions. Invokes callback when done.
djr.Player.prototype.autoExtendCurrentPlaylist = function(callback) {
var player = this;
var cur_songs = this.playlist.allSongs();
this.backend.markovPlaylist(10, cur_songs, function(results) {
player.createChunk(results, 'more...');
callback();
});
};
// Extend the current playlist with the results of a MoreLikeThis
// search based on a single selected song.
djr.Player.prototype.moreLikeThis = function(sha1) {
var player = this;
var songs = [sha1];
this.backend.moreLikeThese(10, songs, function(results) {
player.createChunk(results, 'like that');
});
};
djr.Player.prototype.createChunk = function(songs, chunk_title) {
// Clear any pending error message.
djr.clearSearchWarning();
// Create the new chunk, with unique songs.
var chunk = this.playlist.createUniqueChunk(songs, chunk_title);
if (!chunk) {
djr.showSearchWarning('All results already in playlist.');
djr.debug('All the results are already in the playlist');
return;
}
// If there's more than one chunk in the playlist, merge (that is,
// replace the current playlist with a new, merged one).
if (this.playlist.chunks.length > 1) {
this.mergePlaylistChunks();
}
// Add the new chunk.
var chunk_id = this.playlist.addChunk(chunk);
// Save the current playlist.
this.savePlaylist();
// Set the URL hash fragment to point to the current playlist.
djr.history.save(this.playlist.uuid);
// Load the HTML fragment for the chunk and display it. Also,
// minimize all the other chunks.
var player = this;
this.backend.getHtmlForSongs(songs, function(songs_html) {
var chunk_div = 'chunk_' + chunk_id;
player.hideAllChunks();
player.setChunkHtml(chunk, chunk_id, songs_html);
});
};
// Set the HTML contents of a chunk object, and the related event hooks.
djr.Player.prototype.setChunkHtml = function(chunk, chunk_id, songs_html) {
var inner_html = chunk.wrapHtml(chunk_id, songs_html);
$('#playlistDiv').append(inner_html);
var player = this;
var chunk_div = $('#chunk_' + chunk_id);
// Add onclick handlers to chunk title, song title, song album.
chunk_div.find('.song_a').click(function() {
player.play($(this).attr('id').substr(5));
});
chunk_div.find('.album_a').click(function() {
player.search('(album:\"' + $(this).text() + '\")');
});
chunk_div.find('.chunk_title').click(function() {
chunk_div.find('.chunk_inner').toggle();
});
// Add onclick and hover handlers to the chunk control box.
chunk_div.hover(function() {
$(this).find('.chunk_ctl_wrap .ctlbox').show();
}, function() {
$(this).find('.chunk_ctl_wrap .ctlbox').hide();
});
chunk_div.find('.chunk_ctl_wrap .ctlbox .ctl_remove').click(function() {
djr.debug('removing chunk ' + chunk_id);
player.removeChunk(chunk_id);
});
// Add onclick handlers to the song control boxes.
chunk_div.find('.chunk_inner .song').hover(function() {
$(this).find('.ctlbox').show();
}, function() {
$(this).find('.ctlbox').hide();
});
chunk_div.find('.chunk_inner .ctlbox .ctl_remove').click(function() {
// What a horrible way of finding the song SHA1...
var sha1 = $(this).parent().parent().attr('id').substr(5);
player.removeSong(sha1);
});
chunk_div.find('.chunk_inner .ctlbox .ctl_love').click(function() {
var sha1 = $(this).parent().parent().attr('id').substr(5);
player.moreLikeThis(sha1);
});
};
// Start playing a specific song.
djr.Player.prototype.play = function(song) {
djr.debug('play ' + song);
if (this.cur_song) {
this.old_songs.push(this.cur_song);
if (this.old_songs.length > 5) {
this.old_songs.shift();
}
}
this.cur_song = song;
$('.song').removeClass('playing');
$('#song_' + song).addClass('playing');
var url = '/dl/' + song;
this.player.jPlayer('setMedia',
{mp3: url}).jPlayer('play');
// Load song info in the player UI. We cheat by stealing the data
// from the existing <div> instead than from the server.
var artist = $('#song_' + song + ' .artist').text();
var album = $('#song_' + song + ' .album').text();
$('#songInfoDiv').html(
$('#song_' + song + ' .title').text() + '<br>'
+ artist + '<br>'
+ '<small>' + album + '</small>'
);
// Load album art full-screen.
var album_art_url = '/album_image/' + escape(artist) + '/' + escape(album);
$('#albumart_fs').attr('src', album_art_url);
$('#albumart_fs').fullBg();
$('#albumart_fs').show();
// Report the new song being played.
this.backend.nowPlaying(song, this.old_songs);
};
// Start playing the next song.
djr.Player.prototype.nextSong = function() {
if (this.auto_extend && this.playlist.isLastSong(this.cur_song)) {
var player = this;
// auto-extend!
this.autoExtendCurrentPlaylist(function() {
player.nextSong();
});
} else {
this.play(this.playlist.getNextSong(this.cur_song));
}
};
// Activate streaming of the current playlist.
djr.Player.prototype.streamCurrentPlaylist = function(enable) {
// Nothing for now.
};
// Fine