Skip to content
Snippets Groups Projects
Select Git revision
  • b56f4ceca7038f615e27060808cdff1831fac821
  • master default
  • nonce
  • encrypt-ticket
  • apache24
  • libsodium
  • mod-sso-cache
7 results

control

Blame
  • player.js 11.92 KiB
    // player.js
    
    
    // Player
    
    djr.Player = function(backend, selector) {
      this.backend = backend;
      this.player = $(selector);
      this.playlist = new djr.Playlist();
      this.old_songs = [];
      this.cur_song = null;
    
      // Setup the jPlayer interface.
      this.player.jPlayer({
        swfPath: '/static/js',
        ready: function() {
          djr.debug('player ready');
        }
      });
      this.player.bind($.jPlayer.event.ended + '.djr', 
                       function () {djr.state.player.nextSong(); });
      this.player.bind($.jPlayer.event.error + '.djr', 
                       function() {djr.state.player.reportError(); });
    };
    
    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);
      this.savePlaylist();
      $('#chunk_' + chunk_id).remove();
    };
    
    // 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());
    };
    
    // 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();
    };
    
    // Merge all chunks into a single one.
    djr.Player.prototype.mergePlaylistChunks = function() {
      // Reduce the playlist to a single chunk.
      this.playlist = this.playlist.merge();
    
      // 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.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 = [];
        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);
      });
    
    };
    
    // Extend the current playlist with suggestions.
    djr.Player.prototype.extendCurrentPlaylist = function() {
      var player = this;
      var cur_songs = this.playlist.allSongs();
    
      this.backend.moreLikeThese(cur_songs, function(results) {
        player.createChunk(results, 'suggestions');
      });
    };
    
    djr.Player.prototype.createChunk = function(songs, chunk_title) {
      // Create the new chunk, with unique songs.
      var chunk = this.playlist.createUniqueChunk(songs, chunk_title);
      if (!chunk) {
        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();
    
      // Load the HTML fragment for the chunk and display it.  Also,
      // minimize all the other chunks.
      this.backend.getHtmlForSongs(songs, function(songs_html) {
        var chunk_div = 'chunk_' + chunk_id;
        this.hideAllChunks();
        this.setChunkHtml(chunk, chunk_id, songs_html);
      }, this);
    };
    
    // 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);
      });
    };
    
    // 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();
      $('#jp_playlist_1').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() {
      this.play(this.playlist.getNextSong(this.cur_song));
    };
    
    // Activate streaming of the current playlist.
    djr.Player.prototype.streamCurrentPlaylist = function(enable) {
      // Nothing for now.
    };
    
    
    djr.state = {
      backend: null,
      player: null
    };
    
    djr.init = function () {
      djr.state.backend = new djr.Backend();
      djr.state.player = new djr.Player(djr.state.backend, '#djr_player');
    
      // Add onclick hooks to the playlist controls.
      $('#playlistClearBtn').click(function() {
        djr.state.player.clearPlaylist();
      });
      $('#playlistStreamBtn').click(function() {
        djr.state.player.streamCurrentPlaylist();
      });
      $('#playlistExtendBtn').click(function() {
        djr.state.player.extendCurrentPlaylist();
      });
      $('#playlistLast5').click(function() {
        djr.state.player.lastPlaylist(5);
      });
      $('#playlistLast25').click(function() {
        djr.state.player.lastPlaylist(25);
      });
      $('#playlistRandom5').click(function() {
        djr.state.player.randomPlaylist(5);
      });
      $('#playlistRandom25').click(function() {
        djr.state.player.randomPlaylist(25);
      });
      $('#playlistMost5').click(function() {
        djr.state.player.mostPlayedPlaylist(5);
      });
      $('#playlistMost25').click(function() {
        djr.state.player.mostPlayedPlaylist(25);
      });
      $('#playlistNever5').click(function() {
        djr.state.player.neverPlayedPlaylist(5);
      });
      $('#playlistNever25').click(function() {
        djr.state.player.neverPlayedPlaylist(25);
      });
      $('#wikibtn').click(function () {
        var stitle = $('#song_' + djr.state.player.cur_song + ' .artist').text();
        if ( $('#wikipedia').is(':visible') == false ) {
          if ( stitle != "" ) { 
            stitle = stitle.split(' ').join('+');
            $('#wikipedia').show('slow');
            //$('#wikipedia').attr("src", "/ext?url=" + escape("http://en.wikipedia.org/wiki/Special:Search?search=" + stitle + "&go=Go"));
            $('#wikipedia').attr("src", "http://en.m.wikipedia.org/w/index.php?search=" + stitle);
          }
        } else {
            $('#wikipedia').hide('slow')
        }
      });
      $('#lastfmbtn').click(function () {
        var stitle = $('#song_' + djr.state.player.cur_song + ' .title').text();
        var sartist = $('#song_' + djr.state.player.cur_song + ' .artist').text();
        if ( $('#lastfm').is(':visible') == false ) {
          if ( stitle != "" ) { 
            stitle = stitle.split(' ').join('+');
            sartist = sartist.split(' ').join('+');
            $('#lastfm').show('slow');
            //$('#lastfm').attr("src", "/ext?url=" + escape("http://www.lastfm.com/#&q=" + stitle + sartist));
            $('#lastfm').attr("src", "http://m.last.fm/search?q=" + stitle + sartist );
          }
        } else {
            $('#lastfm').hide('slow')
        }
      });
      $('#lyricsbtn').click(function () {
        var stitle = $('#song_' + djr.state.player.cur_song + ' .title').text();
        if ( $('#lyrics').is(':visible') == false ) {
          if ( stitle != "" ) { 
            stitle = stitle.split(' ').join('+');
            $('#lyrics').show('slow');
            //$('#lyrics').attr("src", "/ext?url=" + escape("http://www.lyrics.com/#&q=" + stitle));
            $('#lyrics').attr("src", "http://lyrics.wikia.com/index.php?search=" + stitle + "&fulltext=0" );
          }
        } else {
            $('#lyrics').hide('slow')
        }
      });
    
    
      // Set the album art image to auto-fullscreen on load.
      $('#albumart_fs').load(function() {
        $(this).fullBg();
        $(this).show();
      });
    };
    
    // Export the player for quick onclick access
    djr.player = function() {
      return djr.state.player;
    };
    
    // Debugging.
    djr.debug = function(msg) {
      $('#debug').append(msg + '<br>');
    };
    
    
    
    // ------ OLD --------
    
    /**
    
    // An error has occurred in the player.
    djr.Player.prototype.reportError = function(event) {
      switch(event.jPlayer.error.type) {
      case $.jPlayer.error.URL:
        djr.debug('error downloading song, moving on');
        this.nextSong();
        break;
      case $.jPlayer.error.NO_SOLUTION:
        djr.debug('unexpected error!');
        break;
      }  
    };
    **/
    
    // Fine