CC-3395: Play preview for playlists and timelines for shows should show a list under the pop-up player which will play the entire playlist.

- Updated jplayer so it now shows a list view under the player which shows details of the track being played, and for playlists the entire playlist list.
- Also enabled playing playlists from the library.
This commit is contained in:
Daniel 2012-03-09 18:47:08 -05:00
parent 709e117f41
commit 470cf0dbf8
11 changed files with 704 additions and 106 deletions

View File

@ -148,7 +148,7 @@ class ApiController extends Zend_Controller_Action
header('Content-Disposition: inline; filename="'.$file_base_name.'"');
}
$this->smartReadFile($filepath, $ext);
$this->smartReadFile($filepath, 'audio/'.$ext);
exit;
}else{
header ("HTTP/1.1 404 Not Found");
@ -170,7 +170,7 @@ class ApiController extends Zend_Controller_Action
* @link https://groups.google.com/d/msg/jplayer/nSM2UmnSKKA/Hu76jDZS4xcJ
* @link http://php.net/manual/en/function.readfile.php#86244
*/
function smartReadFile($location, $mimeType = 'audio/mpeg')
function smartReadFile($location, $mimeType = 'audio/mp3')
{
$size= filesize($location);
$time= date('r', filemtime($location));

View File

@ -58,7 +58,7 @@ class LibraryController extends Zend_Controller_Action
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/buttons/buttons.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/library.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/main_library.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/media_library.css?'.$CC_CONFIG['airtime_version']);
$this->view->headLink()->appendStylesheet($baseUrl.'/css/jquery.contextMenu.css?'.$CC_CONFIG['airtime_version']);
$this->view->headLink()->appendStylesheet($baseUrl.'/css/datatables/css/ColVis.css?'.$CC_CONFIG['airtime_version']);
@ -88,8 +88,7 @@ class LibraryController extends Zend_Controller_Action
if (isset($this->pl_sess->id) && $screen == "playlist") {
$menu["pl_add"] = array("name"=> "Add to Playlist", "icon" => "copy");
}
//Open a jPlayer window and play the audio clip.
$menu["play"] = array("name"=> "Play", "icon" => "big_play");
$menu["edit"] = array("name"=> "Edit Metadata", "icon" => "edit", "url" => "/library/edit-file-md/id/{$id}");
@ -134,6 +133,9 @@ class LibraryController extends Zend_Controller_Action
$menu["del"] = array("name"=> "Delete", "icon" => "delete", "url" => "/library/delete");
}
//Open a jPlayer window and play the audio clip.
$menu["play"] = array("name"=> "Play", "icon" => "big_play");
$this->view->items = $menu;
}

View File

@ -20,6 +20,8 @@ class PlaylistController extends Zend_Controller_Action
->addActionContext('get-playlist-fades', 'json')
->addActionContext('set-playlist-name', 'json')
->addActionContext('set-playlist-description', 'json')
->addActionContext('playlist-preview', 'json')
->addActionContext('get-playlist', 'json')
->initContext();
$this->pl_sess = new Zend_Session_Namespace(UI_PLAYLIST_SESSNAME);
@ -196,17 +198,25 @@ class PlaylistController extends Zend_Controller_Action
}
}
public function audioPreviewPlayerAction()
public function playlistPreviewAction()
{
$fileID = $this->_getParam('fileID');
$playlistIndex = $this->_getParam('index');
$audioFileID = $this->_getParam('audioFileID');
$audioFileArtist = $this->_getParam('audioFileArtist');
$audioFileTitle = $this->_getParam('audioFileTitle');
$playlistIndex = $this->_getParam('playlistIndex');
$playlistID = $this->_getParam('playlistID');
Logging::log($audioFileID);
Logging::log($audioFileArtist);
Logging::log($audioFileTitle);
Logging::log($playlistIndex);
Logging::log($playlistID);
$request = $this->getRequest();
$baseUrl = $request->getBaseUrl();
$baseDir = dirname($_SERVER['SCRIPT_FILENAME']);
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/preview_jplayer.js?'.filemtime($baseDir.'/js/airtime/library/preview_jplayer.js'),'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/jplayer/jquery.jplayer.min.js?'.filemtime($baseDir.'/js/jplayer/jquery.jplayer.min.js'),'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/jplayer/preview_jplayer.js?'.filemtime($baseDir.'/js/jplayer/preview_jplayer.js'),'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/jplayer/jplayer.playlist.min.js?'.filemtime($baseDir.'/js/jplayer/jplayer.playlist.min.js'),'text/javascript');
$this->view->headLink()->appendStylesheet($baseUrl.'/js/jplayer/skin/jplayer.audio-preview.blue.monday.css?'.filemtime($baseDir.'/js/jplayer/skin/jplayer.audio-preview.blue.monday.css'));
$this->_helper->layout->setLayout('audioPlayer');
@ -216,11 +226,43 @@ class PlaylistController extends Zend_Controller_Action
} else {
$this->view->logo = "$baseUrl/css/images/airtime_logo_jp.png";
}
$this->view->fileName = $fileID;
Logging::log("The play list index is $playlistIndex");
$this->view->audioFileID = $audioFileID;
$this->view->audioFileArtist = $audioFileArtist;
$this->view->audioFileTitle = $audioFileTitle;
$this->view->playlistIndex= $playlistIndex;
$this->view->playlistID = $playlistID;
}
public function getPlaylistAction(){
// disable the view and the layout
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$playlistID = $this->_getParam('playlistID');
if (!isset($playlistID)){
return;
}
$pl = new Application_Model_Playlist($playlistID);
$result = Array();
foreach ( $pl->getContents() as $track ){
$trackMap = array( 'title' => isset($track['CcFiles']['track_title'])?$track['CcFiles']['track_title']:"",
'artist' => isset($track['CcFiles']['artist_name'])?$track['CcFiles']['artist_name']:"",
'mp3' => '/api/get-media/fileID/'.$track['CcFiles']['gunid'].'.'.pathinfo($track['CcFiles']['filepath'], PATHINFO_EXTENSION),
'id' => isset($track['id'])?$track['id']:"",
'position' => isset($track['position'])?$track['position']:"",
);
$result[] = $trackMap;
}
$this->_helper->json($result);
}
public function addItemsAction()
{
$ids = $this->_getParam('ids', array());

View File

@ -1,33 +0,0 @@
<div id="content" class="jp-container">
<span class='fileID'><?php echo "$this->fileName" ?></span>
<div id="jquery_jplayer_1" class="jp-jplayer"></div>
<div id="jp_container_1" class="jp-audio">
<div class="jp-type-single">
<div class="jp-gui jp-interface">
<ul class="jp-controls">
<li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
<li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
<li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
<li><a href="javascript:;" class="jp-mute" tabindex="1" title="mute">mute</a></li>
<li><a href="javascript:;" class="jp-unmute" tabindex="1" title="unmute">unmute</a></li>
<li><a href="javascript:;" class="jp-volume-max" tabindex="1" title="max volume">max volume</a></li>
</ul>
<div class="jp-progress">
<div class="jp-seek-bar">
<div class="jp-play-bar"></div>
</div>
</div>
<div class="jp-volume-bar">
<div class="jp-volume-bar-value"></div>
</div>
<div class="jp-time-holder">
<div class="jp-current-time"></div>
<div class="jp-duration"></div>
<ul class="jp-toggles">
<li><a href="javascript:;" class="jp-repeat" tabindex="1" title="repeat">repeat</a></li>
<li><a href="javascript:;" class="jp-repeat-off" tabindex="1" title="repeat off">repeat off</a></li>
</ul>
</div>
</div>
</div>

View File

@ -0,0 +1,50 @@
<div id="jquery_jplayer_1" class="jp-jplayer"></div>
<div id="jp_container_1" class="jp-audio">
<span class='audioFileID'><?php echo "$this->audioFileID" ?></span>
<span class='audioFileTitle'><?php echo "$this->audioFileTitle" ?></span>
<span class='audioFileArtist'><?php echo "$this->audioFileArtist" ?></span>
<span class='playlistID'><?php echo "$this->playlistID" ?></span>
<span class='playlistIndex'><?php echo "$this->playlistIndex" ?></span>
<div class="jp-type-playlist">
<div class="jp-gui jp-interface">
<ul class="jp-controls">
<li><a href="" class="jp-previous" tabindex="1">previous</a></li>
<li><a href="" class="jp-play" tabindex="1">play</a></li>
<li><a href="" class="jp-pause" tabindex="1">pause</a></li>
<li><a href="" class="jp-next" tabindex="1">next</a></li>
<li><a href="" class="jp-stop" tabindex="1">stop</a></li>
<li><a href="" class="jp-mute" tabindex="1" title="mute">mute</a></li>
<li><a href="" class="jp-unmute" tabindex="1" title="unmute">unmute</a></li>
<li><a href="" class="jp-volume-max" tabindex="1" title="max volume">max volume</a></li>
</ul>
<div class="jp-progress">
<div class="jp-seek-bar">
<div class="jp-play-bar"></div>
</div>
</div>
<div class="jp-volume-bar">
<div class="jp-volume-bar-value"></div>
</div>
<div class="jp-time-holder">
<div class="jp-current-time"></div>
<div class="jp-duration"></div>
</div>
<ul class="jp-toggles">
<li><a href="" class="jp-shuffle" tabindex="1" title="shuffle">shuffle</a></li>
<li><a href="" class="jp-shuffle-off" tabindex="1" title="shuffle off">shuffle off</a></li>
<li><a href="" class="jp-repeat" tabindex="1" title="repeat">repeat</a></li>
<li><a href="" class="jp-repeat-off" tabindex="1" title="repeat off">repeat off</a></li>
</ul>
</div>
<div class="jp-playlist">
<ul>
<li></li>
</ul>
</div>
<div class="jp-no-solution">
<span>Update Required</span>
To play the media you will need to either update your browser to a recent version or update your <a href="http://get.adobe.com/flashplayer/" target="_blank">Flash plugin</a>.
</div>
</div>
</div>

View File

@ -160,7 +160,12 @@
//add the play function to the library_type td
$(nRow).find('td.library_type').click(function(){
open_audio_preview(aData.audioFile, aData.id);
if (aData.ftype === 'playlist' && aData.length !== '0.0'){
playlistIndex = $(this).parent().attr('id').substring(3); //remove the pl_
open_playlist_preview(aData.audioFile, "", "", playlistIndex, 0);
} else if (aData.ftype === 'audioclip') {
open_playlist_preview(aData.audioFile, aData.track_title, aData.artist_name);
}
return false;
});
@ -360,7 +365,12 @@
//define a play callback.
if (oItems.play !== undefined) {
callback = function() {
open_audio_preview(data.audioFile, data.id);
if (data.ftype === 'playlist' && data.length !== '0.0'){
playlistIndex = $(this).parent().attr('id').substring(3); //remove the pl_
open_playlist_preview(data.audioFile, "", "", playlistIndex, 0);
} else if (data.ftype === 'audioclip') {
open_playlist_preview(data.audioFile, data.track_title, data.artist_name);
}
};
oItems.play.callback = callback;
}
@ -634,24 +644,37 @@
});
}
});
}
var audio_preview_window = null;
var preview_window = null;
function open_audio_preview(fileID, index) {
url = 'Playlist/audio-preview-player/fileID/'+fileID+'/index/'+index;
function openAudioPreview(event) {
event.stopPropagation();
var audioFileID = $(this).attr('audioFile');
var playlistID = $('#pl_id:first').attr('value');
var playlistIndex = $(this).parent().parent().attr('id');
playlistIndex = playlistIndex.substring(4); //remove the spl_
open_playlist_preview(audioFileID, "", "", playlistID, playlistIndex);
}
function open_playlist_preview(audioFileID, audioFileTitle, audioFileArtist, playlistID, playlistIndex) {
if (playlistIndex != undefined)
url = 'Playlist/playlist-preview/audioFileID/'+audioFileID+'/playlistIndex/'+playlistIndex+'/playlistID/'+playlistID;
else
url = 'Playlist/playlist-preview/audioFileID/'+audioFileID+'/audioFileArtist/'+audioFileArtist+'/audioFileTitle/'+audioFileTitle;
//$.post(baseUri+'Playlist/audio-preview-player', {fileName: fileName, cueIn: cueIn, cueOut: cueOut, fadeIn: fadeIn, fadeInFileName: fadeInFileName, fadeOut: fadeOut, fadeOutFileName: fadeOutFileName})
if (audio_preview_window == null || audio_preview_window.closed){
audio_preview_window = window.open(url, 'Audio Player', 'width=400,height=95');
} else if (!audio_preview_window.closed) {
audio_preview_window.play(fileID);
} else {
console.log("something else : "+baseUrl+url);
if (preview_window == null || preview_window.closed || playlistIndex === undefined){
preview_window = window.open(url, 'Audio Player', 'width=450,height=800');
} else if (!preview_window.closed) {
preview_window.playAll(playlistID, playlistIndex);
}
//Set the play button to pause.
//var elemID = "spl_"+elemIndexString;
//$('#'+elemID+' div.list-item-container a span').attr("class", "ui-icon ui-icon-pause");
return false;
}
return false;
}

View File

@ -1,35 +0,0 @@
$(document).ready(function(){
var fileID = $(".fileID").text();
play(fileID);
});
function play(fileID){
var uri = "/api/get-media/fileID/" + fileID;
var ext = getFileExt(fileID);
var media;
var supplied;
if (ext == "ogg"){
media = {oga:uri};
supplied = "oga";
} else {
media = {mp3:uri};
supplied = "mp3";
}
$("#jquery_jplayer_1").jPlayer("destroy");
$.jPlayer.timeFormat.showHour = true;
$("#jquery_jplayer_1").jPlayer({
ready: function () {
$(this).jPlayer("setMedia", media).jPlayer("play");
},
swfPath: "/js/jplayer",
cssSelectorAncestor: '#jp_container_1',
wmode: "window"
});
}

View File

@ -244,15 +244,6 @@ var AIRTIME = (function(AIRTIME){
highlightActive(icon);
}
}
function openAudioPreview(event) {
event.stopPropagation();
var audioFile = $(this).attr('audioFile');
var id = "";
open_audio_preview(audioFile, id);
}
function editName() {
var nameElement = $(this),

View File

@ -0,0 +1,452 @@
/*
* Playlist Object for the jPlayer Plugin
* http://www.jplayer.org
*
* Copyright (c) 2009 - 2011 Happyworm Ltd
* Dual licensed under the MIT and GPL licenses.
* - http://www.opensource.org/licenses/mit-license.php
* - http://www.gnu.org/copyleft/gpl.html
*
* Author: Mark J Panaghiston
* Version: 2.1.0 (jPlayer 2.1.0)
* Date: 1st September 2011
*/
/* Code verified using http://www.jshint.com/ */
/*jshint asi:false, bitwise:false, boss:false, browser:true, curly:true, debug:false, eqeqeq:true, eqnull:false, evil:false, forin:false, immed:false, jquery:true, laxbreak:false, newcap:true, noarg:true, noempty:true, nonew:true, nomem:false, onevar:false, passfail:false, plusplus:false, regexp:false, undef:true, sub:false, strict:false, white:false */
/*global jPlayerPlaylist: true, jQuery:false, alert:false */
(function($, undefined) {
jPlayerPlaylist = function(cssSelector, playlist, options) {
var self = this;
this.current = 0;
this.loop = false; // Flag used with the jPlayer repeat event
this.shuffled = false;
this.removing = false; // Flag is true during remove animation, disabling the remove() method until complete.
this.cssSelector = $.extend({}, this._cssSelector, cssSelector); // Object: Containing the css selectors for jPlayer and its cssSelectorAncestor
this.options = $.extend(true, {}, this._options, options); // Object: The jPlayer constructor options for this playlist and the playlist options
this.playlist = []; // Array of Objects: The current playlist displayed (Un-shuffled or Shuffled)
this.original = []; // Array of Objects: The original playlist
this._initPlaylist(playlist); // Copies playlist to this.original. Then mirrors this.original to this.playlist. Creating two arrays, where the element pointers match. (Enables pointer comparison.)
// Setup the css selectors for the extra interface items used by the playlist.
this.cssSelector.title = this.cssSelector.cssSelectorAncestor + " .jp-title"; // Note that the text is written to the decendant li node.
this.cssSelector.playlist = this.cssSelector.cssSelectorAncestor + " .jp-playlist";
this.cssSelector.next = this.cssSelector.cssSelectorAncestor + " .jp-next";
this.cssSelector.previous = this.cssSelector.cssSelectorAncestor + " .jp-previous";
this.cssSelector.shuffle = this.cssSelector.cssSelectorAncestor + " .jp-shuffle";
this.cssSelector.shuffleOff = this.cssSelector.cssSelectorAncestor + " .jp-shuffle-off";
// Override the cssSelectorAncestor given in options
this.options.cssSelectorAncestor = this.cssSelector.cssSelectorAncestor;
// Override the default repeat event handler
this.options.repeat = function(event) {
self.loop = event.jPlayer.options.loop;
};
// Create a ready event handler to initialize the playlist
$(this.cssSelector.jPlayer).bind($.jPlayer.event.ready, function(event) {
self._init();
});
// Create an ended event handler to move to the next item
$(this.cssSelector.jPlayer).bind($.jPlayer.event.ended, function(event) {
self.next();
});
// Create a play event handler to pause other instances
$(this.cssSelector.jPlayer).bind($.jPlayer.event.play, function(event) {
$(this).jPlayer("pauseOthers");
});
// Create a resize event handler to show the title in full screen mode.
$(this.cssSelector.jPlayer).bind($.jPlayer.event.resize, function(event) {
if(event.jPlayer.options.fullScreen) {
$(self.cssSelector.title).show();
} else {
$(self.cssSelector.title).hide();
}
});
// Create click handlers for the extra buttons that do playlist functions.
$(this.cssSelector.previous).click(function() {
self.previous();
$(this).blur();
return false;
});
$(this.cssSelector.next).click(function() {
self.next();
$(this).blur();
return false;
});
$(this.cssSelector.shuffle).click(function() {
self.shuffle(true);
return false;
});
$(this.cssSelector.shuffleOff).click(function() {
self.shuffle(false);
return false;
}).hide();
// Put the title in its initial display state
if(!this.options.fullScreen) {
$(this.cssSelector.title).hide();
}
// Remove the empty <li> from the page HTML. Allows page to be valid HTML, while not interfereing with display animations
$(this.cssSelector.playlist + " ul").empty();
// Create .live() handlers for the playlist items along with the free media and remove controls.
this._createItemHandlers();
// Instance jPlayer
$(this.cssSelector.jPlayer).jPlayer(this.options);
};
jPlayerPlaylist.prototype = {
_cssSelector: { // static object, instanced in constructor
jPlayer: "#jquery_jplayer_1",
cssSelectorAncestor: "#jp_container_1"
},
_options: { // static object, instanced in constructor
playlistOptions: {
autoPlay: false,
loopOnPrevious: false,
shuffleOnLoop: true,
enableRemoveControls: false,
displayTime: 'slow',
addTime: 'fast',
removeTime: 'fast',
shuffleTime: 'slow',
itemClass: "jp-playlist-item",
freeGroupClass: "jp-free-media",
freeItemClass: "jp-playlist-item-free",
removeItemClass: "jp-playlist-item-remove"
}
},
option: function(option, value) { // For changing playlist options only
if(value === undefined) {
return this.options.playlistOptions[option];
}
this.options.playlistOptions[option] = value;
switch(option) {
case "enableRemoveControls":
this._updateControls();
break;
case "itemClass":
case "freeGroupClass":
case "freeItemClass":
case "removeItemClass":
this._refresh(true); // Instant
this._createItemHandlers();
break;
}
return this;
},
_init: function() {
var self = this;
this._refresh(function() {
if(self.options.playlistOptions.autoPlay) {
self.play(self.current);
} else {
self.select(self.current);
}
});
},
_initPlaylist: function(playlist) {
this.current = 0;
this.shuffled = false;
this.removing = false;
this.original = $.extend(true, [], playlist); // Copy the Array of Objects
this._originalPlaylist();
},
_originalPlaylist: function() {
var self = this;
this.playlist = [];
// Make both arrays point to the same object elements. Gives us 2 different arrays, each pointing to the same actual object. ie., Not copies of the object.
$.each(this.original, function(i,v) {
self.playlist[i] = self.original[i];
});
},
_refresh: function(instant) {
/* instant: Can be undefined, true or a function.
* undefined -> use animation timings
* true -> no animation
* function -> use animation timings and excute function at half way point.
*/
var self = this;
if(instant && !$.isFunction(instant)) {
$(this.cssSelector.playlist + " ul").empty();
$.each(this.playlist, function(i,v) {
$(self.cssSelector.playlist + " ul").append(self._createListItem(self.playlist[i]));
});
this._updateControls();
} else {
var displayTime = $(this.cssSelector.playlist + " ul").children().length ? this.options.playlistOptions.displayTime : 0;
$(this.cssSelector.playlist + " ul").slideUp(displayTime, function() {
var $this = $(this);
$(this).empty();
$.each(self.playlist, function(i,v) {
$this.append(self._createListItem(self.playlist[i]));
});
self._updateControls();
if($.isFunction(instant)) {
instant();
}
if(self.playlist.length) {
$(this).slideDown(self.options.playlistOptions.displayTime);
} else {
$(this).show();
}
});
}
},
_createListItem: function(media) {
var self = this;
// Wrap the <li> contents in a <div>
var listItem = "<li><div>";
// Create remove control
listItem += "<a href='javascript:;' class='" + this.options.playlistOptions.removeItemClass + "'>&times;</a>";
// Create links to free media
if(media.free) {
var first = true;
listItem += "<span class='" + this.options.playlistOptions.freeGroupClass + "'>(";
$.each(media, function(property,value) {
if($.jPlayer.prototype.format[property]) { // Check property is a media format.
if(first) {
first = false;
} else {
listItem += " | ";
}
listItem += "<a class='" + self.options.playlistOptions.freeItemClass + "' href='" + value + "' tabindex='1'>" + property + "</a>";
}
});
listItem += ")</span>";
}
// The title is given next in the HTML otherwise the float:right on the free media corrupts in IE6/7
listItem += "<a href='javascript:;' class='" + this.options.playlistOptions.itemClass + "' tabindex='1'>" + media.title + (media.artist ? " <span class='jp-artist'>by " + media.artist + "</span>" : "") + "</a>";
listItem += "</div></li>";
return listItem;
},
_createItemHandlers: function() {
var self = this;
// Create .live() handlers for the playlist items
$(this.cssSelector.playlist + " a." + this.options.playlistOptions.itemClass).die("click").live("click", function() {
var index = $(this).parent().parent().index();
if(self.current !== index) {
self.play(index);
} else {
$(self.cssSelector.jPlayer).jPlayer("play");
}
$(this).blur();
return false;
});
// Create .live() handlers that disable free media links to force access via right click
$(self.cssSelector.playlist + " a." + this.options.playlistOptions.freeItemClass).die("click").live("click", function() {
$(this).parent().parent().find("." + self.options.playlistOptions.itemClass).click();
$(this).blur();
return false;
});
// Create .live() handlers for the remove controls
$(self.cssSelector.playlist + " a." + this.options.playlistOptions.removeItemClass).die("click").live("click", function() {
var index = $(this).parent().parent().index();
self.remove(index);
$(this).blur();
return false;
});
},
_updateControls: function() {
if(this.options.playlistOptions.enableRemoveControls) {
$(this.cssSelector.playlist + " ." + this.options.playlistOptions.removeItemClass).show();
} else {
$(this.cssSelector.playlist + " ." + this.options.playlistOptions.removeItemClass).hide();
}
if(this.shuffled) {
$(this.cssSelector.shuffleOff).show();
$(this.cssSelector.shuffle).hide();
} else {
$(this.cssSelector.shuffleOff).hide();
$(this.cssSelector.shuffle).show();
}
},
_highlight: function(index) {
if(this.playlist.length && index !== undefined) {
$(this.cssSelector.playlist + " .jp-playlist-current").removeClass("jp-playlist-current");
$(this.cssSelector.playlist + " li:nth-child(" + (index + 1) + ")").addClass("jp-playlist-current").find(".jp-playlist-item").addClass("jp-playlist-current");
$(this.cssSelector.title + " li").html(this.playlist[index].title + (this.playlist[index].artist ? " <span class='jp-artist'>by " + this.playlist[index].artist + "</span>" : ""));
}
},
setPlaylist: function(playlist) {
this._initPlaylist(playlist);
this._init();
},
add: function(media, playNow) {
$(this.cssSelector.playlist + " ul").append(this._createListItem(media)).find("li:last-child").hide().slideDown(this.options.playlistOptions.addTime);
this._updateControls();
this.original.push(media);
this.playlist.push(media); // Both array elements share the same object pointer. Comforms with _initPlaylist(p) system.
if(playNow) {
this.play(this.playlist.length - 1);
} else {
if(this.original.length === 1) {
this.select(0);
}
}
},
remove: function(index) {
var self = this;
if(index === undefined) {
this._initPlaylist([]);
this._refresh(function() {
$(self.cssSelector.jPlayer).jPlayer("clearMedia");
});
return true;
} else {
if(this.removing) {
return false;
} else {
index = (index < 0) ? self.original.length + index : index; // Negative index relates to end of array.
if(0 <= index && index < this.playlist.length) {
this.removing = true;
$(this.cssSelector.playlist + " li:nth-child(" + (index + 1) + ")").slideUp(this.options.playlistOptions.removeTime, function() {
$(this).remove();
if(self.shuffled) {
var item = self.playlist[index];
$.each(self.original, function(i,v) {
if(self.original[i] === item) {
self.original.splice(i, 1);
return false; // Exit $.each
}
});
self.playlist.splice(index, 1);
} else {
self.original.splice(index, 1);
self.playlist.splice(index, 1);
}
if(self.original.length) {
if(index === self.current) {
self.current = (index < self.original.length) ? self.current : self.original.length - 1; // To cope when last element being selected when it was removed
self.select(self.current);
} else if(index < self.current) {
self.current--;
}
} else {
$(self.cssSelector.jPlayer).jPlayer("clearMedia");
self.current = 0;
self.shuffled = false;
self._updateControls();
}
self.removing = false;
});
}
return true;
}
}
},
select: function(index) {
index = (index < 0) ? this.original.length + index : index; // Negative index relates to end of array.
if(0 <= index && index < this.playlist.length) {
this.current = index;
this._highlight(index);
$(this.cssSelector.jPlayer).jPlayer("setMedia", this.playlist[this.current]);
} else {
this.current = 0;
}
},
play: function(index) {
index = (index < 0) ? this.original.length + index : index; // Negative index relates to end of array.
if(0 <= index && index < this.playlist.length) {
if(this.playlist.length) {
this.select(index);
$(this.cssSelector.jPlayer).jPlayer("play");
}
} else if(index === undefined) {
$(this.cssSelector.jPlayer).jPlayer("play");
}
},
pause: function() {
$(this.cssSelector.jPlayer).jPlayer("pause");
},
next: function() {
var index = (this.current + 1 < this.playlist.length) ? this.current + 1 : 0;
if(this.loop) {
// See if we need to shuffle before looping to start, and only shuffle if more than 1 item.
if(index === 0 && this.shuffled && this.options.playlistOptions.shuffleOnLoop && this.playlist.length > 1) {
this.shuffle(true, true); // playNow
} else {
this.play(index);
}
} else {
// The index will be zero if it just looped round
if(index > 0) {
this.play(index);
}
}
},
previous: function() {
var index = (this.current - 1 >= 0) ? this.current - 1 : this.playlist.length - 1;
if(this.loop && this.options.playlistOptions.loopOnPrevious || index < this.playlist.length - 1) {
this.play(index);
}
},
shuffle: function(shuffled, playNow) {
var self = this;
if(shuffled === undefined) {
shuffled = !this.shuffled;
}
if(shuffled || shuffled !== this.shuffled) {
$(this.cssSelector.playlist + " ul").slideUp(this.options.playlistOptions.shuffleTime, function() {
self.shuffled = shuffled;
if(shuffled) {
self.playlist.sort(function() {
return 0.5 - Math.random();
});
} else {
self._originalPlaylist();
}
self._refresh(true); // Instant
if(playNow || !$(self.cssSelector.jPlayer).data("jPlayer").status.paused) {
self.play(0);
} else {
self.select(0);
}
$(this).slideDown(self.options.playlistOptions.shuffleTime);
});
}
}
};
})(jQuery);

View File

@ -0,0 +1,93 @@
var playlist_jplayer;
var idToPostionLookUp;
$(document).ready(function(){
var audioFileID = $('.audioFileID').text();
var playlistID = $('.playlistID').text();
var playlistIndex = $('.playlistIndex').text();
console.log('in the ready');
playlist_jplayer = new jPlayerPlaylist({
jPlayer: "#jquery_jplayer_1",
cssSelectorAncestor: "#jp_container_1"
},[], //array of songs will be filled with below's json call
{
swfPath: "/js/jplayer",
supplied: "mp3, oga",
wmode: "window"
});
$.jPlayer.timeFormat.showHour = true;
if (playlistID != undefined && playlistID !== "")
playAll(playlistID, playlistIndex);
else
playOne(audioFileID);
});
/**
* Sets up the jPlayerPlaylist to play.
* - Get the playlist info based on the playlistID give.
* - Update the playlistIndex to the position in the pllist to start playing.
* - Select the element played from and start playing. If playlist is null then start at index 0.
**/
function playAll(playlistID, playlistIndex) {
var viewsPlaylistID = $('.playlistID').text();
if ( idToPostionLookUp !== undefined && viewsPlaylistID == playlistID ) {
play(playlistIndex);
}else {
idToPostionLookUp = Array();
$.getJSON("/playlist/get-playlist/playlistID/"+playlistID, function(data){ // get the JSON array produced by my PHP
var myPlaylist = new Array();
var media;
var index;
for(index in data){
if (data[index]['mp3'] != 'undefined'){
media = {title: data[index]['title'],
artist: data[index]['artist'],
mp3:data[index]['mp3']
};
}else if (data[index]['ogg'] != 'undefined') {
media = {title: data[index]['title'],
artist: data[index]['artist'],
oga:data[index]['ogg']
};
}
myPlaylist[index] = media;
idToPostionLookUp[data[index]['id']] = data[index]['position'];
}
playlist_jplayer.setPlaylist(myPlaylist);
playlist_jplayer.option("autoPlay", true);
play(playlistIndex);
});
}
}
function play(playlistIndex){
playlistIndex = idToPostionLookUp[playlistIndex];
playlist_jplayer.play(playlistIndex);
}
function playOne(audioFileID) {
var playlist = new Array();
var fileExtensioin = audioFileID.split('.').pop();
if (fileExtensioin === 'mp3') {
media = {title: $('.audioFileTitle').text() !== 'null' ?$('.audioFileTitle').text():"",
artist: $('.audioFileArtist').text() !== 'null' ?$('.audioFileArtist').text():"",
mp3:"/api/get-media/fileID/"+audioFileID
};
}else if (fileExtensioin === 'ogg' ) {
media = {title: $('.audioFileTitle').text() != 'null' ?$('.audioFileTitle').text():"",
artist: $('.audioFileArtist').text() != 'null' ?$('.audioFileArtist').text():"",
oga:"/api/get-media/fileID/"+audioFileID
};
}
playlist[0] = media;
playlist_jplayer.setPlaylist(playlist);
playlist_jplayer.option("autoPlay", true);
playlist_jplayer.play(0);
}

View File

@ -30,6 +30,7 @@ div.jp-video {
background-color:#eee;
position:relative;
}
div.jp-audio {
width:420px;
}
@ -88,8 +89,20 @@ div.jp-video div.jp-interface {
border-top:1px solid #009be3;
}
/* Used to hide the filename field **/
span.fileID {
/* Used to hide non-ui fields **/
span.audioFileID {
display:none;
}
span.audioFileTitle {
display:none;
}
span.audioFileArtist {
display:none;
}
span.playlistID {
display:none;
}
span.playlistIndex {
display:none;
}