some refactoring of the media player code

This commit is contained in:
Robin Appelman 2011-07-26 16:04:57 +02:00
parent 243199859b
commit 0e05a86484
11 changed files with 297 additions and 861 deletions

View File

@ -22,10 +22,9 @@
require_once('apps/media/lib_media.php');
OC_UTIL::addScript('media','music');
OC_UTIL::addScript('media','jquery.jplayer.min');
OC_UTIL::addStyle('media','style');
OC_UTIL::addStyle('media','jplayer');
if(OC_APP::getCurrentApp()=='files'){
OC_UTIL::addScript('media','files');
}
OC_APP::register( array( 'order' => 3, 'id' => 'media', 'name' => 'Media' ));

View File

@ -1,461 +0,0 @@
/*
* Skin for jPlayer Plugin (jQuery JavaScript Library)
* http://www.happyworm.com/jquery/jplayer
*
* Skin Name: Blue Monday
*
* Copyright (c) 2010 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: Silvia Benvenuti
* Skin Version: 3.0 (jPlayer 2.0.0)
* Date: 20th December 2010
*/
div.jp-audio,
div.jp-video {
/* Edit the font-size to counteract inherited font sizing.
* Eg. 1.25em = 1 / 0.8em
*/
font-size:1.25em;
font-family:Verdana, Arial, sans-serif;
line-height:1.6;
color: #000;
}
div.jp-audio {
position:relative;
margin-left:70ex;
margin-right:0px;
top:0px;
margin-top:-30px;
}
div.jp-video-270p {
width:480px;
}
div.jp-video-360p {
width:640px;
}
div.jp-interface {
position: fixed;
z-index:100;
width:25em;
left:201px;
top:-10px;
}
div.jp-type-playlist{
width:100%;
}
div.jp-audio div.jp-type-single div.jp-interface {
height:80px;
border-bottom:none;
}
div.jp-audio div.jp-type-playlist div.jp-interface {
height:80px;
}
div.jp-video div.jp-type-single div.jp-interface {
height:60px;
border-bottom:none;
}
div.jp-video div.jp-type-playlist div.jp-interface {
height:60px;
}
div.jp-interface ul.jp-controls {
list-style-type:none;
padding:0;
}
div.jp-interface ul.jp-controls li {
/* position: absolute; */
display:inline;
}
div.jp-interface ul.jp-controls a {
position: absolute;
overflow:hidden;
text-indent:-9999px;
}
a.jp-play,
a.jp-pause {
width:40px;
height:40px;
z-index:1;
}
div.jp-audio div.jp-type-single a.jp-play,
div.jp-audio div.jp-type-single a.jp-pause {
top:20px;
left:40px;
}
div.jp-audio div.jp-type-playlist a.jp-play,
div.jp-audio div.jp-type-playlist a.jp-pause {
top:20px;
left:48px;
}
div.jp-video a.jp-play,
div.jp-video a.jp-pause {
top:15px;
}
div.jp-video-270p div.jp-type-single a.jp-play,
div.jp-video-270p div.jp-type-single a.jp-pause {
left:195px;
}
div.jp-video-270p div.jp-type-playlist a.jp-play,
div.jp-video-270p div.jp-type-playlist a.jp-pause {
left:220px;
}
div.jp-video-360p div.jp-type-single a.jp-play,
div.jp-video-360p div.jp-type-single a.jp-pause {
left:275px;
}
div.jp-video-360p div.jp-type-playlist a.jp-play,
div.jp-video-360p div.jp-type-playlist a.jp-pause {
left:300px;
}
a.jp-play {
background: url("../img/jplayer.blue.monday.png") 0 0 no-repeat;
}
a.jp-play:hover {
background: url("../img/jplayer.blue.monday.png") -41px 0 no-repeat;
}
a.jp-pause {
background: url("../img/jplayer.blue.monday.png") 0 -42px no-repeat;
display: none;
}
a.jp-pause:hover {
background: url("../img/jplayer.blue.monday.png") -41px -42px no-repeat;
}
div.jp-audio div.jp-type-single a.jp-stop {
top:26px;
left:90px;
}
div.jp-audio div.jp-type-playlist a.jp-stop {
top:26px;
left:126px;
}
div.jp-video a.jp-stop {
top:21px;
}
div.jp-video-270p div.jp-type-single a.jp-stop {
left:245px;
}
div.jp-video-270p div.jp-type-playlist a.jp-stop {
left:298px;
}
div.jp-video-360p div.jp-type-single a.jp-stop {
left:325px;
}
div.jp-video-360p div.jp-type-playlist a.jp-stop {
left:378px;
}
a.jp-stop {
background: url("../img/jplayer.blue.monday.png") 0 -83px no-repeat;
width:28px;
height:28px;
z-index:1;
}
a.jp-stop:hover {
background: url("../img/jplayer.blue.monday.png") -29px -83px no-repeat;
}
div.jp-audio div.jp-type-playlist a.jp-previous {
left:20px;
top:26px;
}
div.jp-video div.jp-type-playlist a.jp-previous {
top:21px;
}
div.jp-video-270p div.jp-type-playlist a.jp-previous {
left:192px;
}
div.jp-video-360p div.jp-type-playlist a.jp-previous {
left:272px;
}
a.jp-previous {
background: url("../img/jplayer.blue.monday.png") 0 -112px no-repeat;
width:28px;
height:28px;
}
a.jp-previous:hover {
background: url("../img/jplayer.blue.monday.png") -29px -112px no-repeat;
}
div.jp-audio div.jp-type-playlist a.jp-next {
left:88px;
top:26px;
}
div.jp-video div.jp-type-playlist a.jp-next {
top:21px;
}
div.jp-video-270p div.jp-type-playlist a.jp-next {
left:260px;
}
div.jp-video-360p div.jp-type-playlist a.jp-next {
left:340px;
}
a.jp-next {
background: url("../img/jplayer.blue.monday.png") 0 -141px no-repeat;
width:28px;
height:28px;
}
a.jp-next:hover {
background: url("../img/jplayer.blue.monday.png") -29px -141px no-repeat;
}
div.jp-progress {
position: absolute;
overflow:hidden;
background-color: #293b51;
}
div.jp-audio div.jp-type-single div.jp-progress {
top:32px;
left:130px;
width:122px;
height:15px;
}
div.jp-audio div.jp-type-playlist div.jp-progress {
top:32px;
left:164px;
width:122px;
height:15px;
}
div.jp-video div.jp-progress {
top:0px;
left:0px;
width:100%;
height:10px;
}
div.jp-seek-bar {
background: url("../img/jplayer.blue.monday.png") 0 -202px repeat-x;
width:0px;
/* height:15px; */
height:100%;
cursor: pointer;
}
div.jp-play-bar {
background: url("../img/jplayer.blue.monday.png") 0 -218px repeat-x ;
width:0px;
/* height:15px; */
height:100%;
}
/* The seeking class is added/removed inside jPlayer */
div.jp-seeking-bg {
background: url("../img/pbar-ani.gif");
}
a.jp-mute,
a.jp-unmute {
width:18px;
height:15px;
}
div.jp-audio div.jp-type-single a.jp-mute,
div.jp-audio div.jp-type-single a.jp-unmute {
top:32px;
left:274px;
}
div.jp-audio div.jp-type-playlist a.jp-mute,
div.jp-audio div.jp-type-playlist a.jp-unmute {
top:32px;
left:296px;
}
div.jp-video a.jp-mute,
div.jp-video a.jp-unmute {
top:27px;
}
div.jp-video-270p div.jp-type-single a.jp-mute,
div.jp-video-270p div.jp-type-single a.jp-unmute {
left:304px;
}
div.jp-video-270p div.jp-type-playlist a.jp-unmute,
div.jp-video-270p div.jp-type-playlist a.jp-mute {
left:363px;
}
div.jp-video-360p div.jp-type-single a.jp-mute,
div.jp-video-360p div.jp-type-single a.jp-unmute {
left:384px;
}
div.jp-video-360p div.jp-type-playlist a.jp-mute,
div.jp-video-360p div.jp-type-playlist a.jp-unmute {
left:443px;
}
a.jp-mute {
background: url("../img/jplayer.blue.monday.png") 0 -186px no-repeat;
}
a.jp-mute:hover {
background: url("../img/jplayer.blue.monday.png") -19px -170px no-repeat;
}
a.jp-unmute {
background: url("../img/jplayer.blue.monday.png") 0 -170px no-repeat;
display: none;
}
a.jp-unmute:hover {
background: url("../img/jplayer.blue.monday.png") -19px -186px no-repeat;
}
div.jp-volume-bar {
position: absolute;
overflow:hidden;
background: url("../img/jplayer.blue.monday.png") 0 -250px repeat-x;
width:46px;
height:5px;
cursor: pointer;
}
div.jp-audio div.jp-type-single div.jp-volume-bar {
top:37px;
left:302px;
}
div.jp-audio div.jp-type-playlist div.jp-volume-bar {
top:37px;
left:324px;
}
div.jp-video div.jp-volume-bar {
top:32px;
}
div.jp-video-270p div.jp-type-single div.jp-volume-bar {
left:332px;
}
div.jp-video-270p div.jp-type-playlist div.jp-volume-bar {
left:391px;
}
div.jp-video-360p div.jp-type-single div.jp-volume-bar {
left:412px;
}
div.jp-video-360p div.jp-type-playlist div.jp-volume-bar {
left:471px;
}
div.jp-volume-bar-value {
background: url("../img/jplayer.blue.monday.png") 0 -256px repeat-x;
width:0px;
height:5px;
}
div.jp-current-time,
div.jp-duration {
position: absolute;
font-size:.64em;
font-style:oblique;
}
div.jp-duration {
text-align: right;
}
div.jp-audio div.jp-type-single div.jp-current-time,
div.jp-audio div.jp-type-single div.jp-duration {
top:49px;
left:130px;
width:122px;
}
div.jp-audio div.jp-type-playlist div.jp-current-time,
div.jp-audio div.jp-type-playlist div.jp-duration {
top:49px;
left:164px;
width:122px;
}
div.jp-video div.jp-current-time,
div.jp-video div.jp-duration {
top:10px;
left:0px;
width:98%;
padding:0 1%;
}
div.jp-playlist {
/* width:418px; */
/* width:400px; */
margin-top:6.3em;
right:0px;
}
div.jp-playlist ul {
list-style-type:none;
margin:0;
padding:0 20px;
/* background-color:#ccc; */
/* border:1px solid #009be3; */
/* border-top:none; */
/* width:378px; */
font-size:.72em;
}
div.jp-type-single div.jp-playlist li {
padding:5px 0 5px 20px;
font-weight:bold;
}
div.jp-type-playlist div.jp-playlist li {
padding:5px 0 4px 20px;
border-bottom:1px solid #eee;
}
/*
d *iv.jp-video div.jp-playlist li {
padding:5px 0 5px 20px;
font-weight:bold;
}
*/
div.jp-type-playlist div.jp-playlist li.jp-playlist-last {
padding:5px 0 5px 20px;
border-bottom:none;
}
div.jp-type-playlist div.jp-playlist li.jp-playlist-current {
list-style-type:square;
list-style-position:inside;
padding-left:8px;
}
div.jp-type-playlist div.jp-playlist a {
color: #666;
text-decoration: none;
}
div.jp-type-playlist div.jp-playlist a:hover {
color:#0d88c1;
}
div.jp-type-playlist div.jp-playlist a.jp-playlist-current {
color:#0d88c1;
}
div.jp-type-playlist div.jp-playlist div.jp-free-media {
display:inline;
margin-left:20px;
}
div.jp-video div.jp-video-play {
background: transparent url("../img/jplayer.blue.monday.video.play.png") no-repeat center;
/* position: relative; */
position: absolute;
cursor:pointer;
z-index:2;
}
div.jp-video div.jp-video-play:hover {
background: transparent url("../img/jplayer.blue.monday.video.play.hover.png") no-repeat center;
}
div.jp-video-270p div.jp-video-play {
top:-270px;
width:480px;
height:270px;
}
div.jp-video-360p div.jp-video-play {
top:-360px;
width:640px;
height:360px;
}
div.jp-jplayer {
width:0px;
height:0px;
}
div.jp-video div.jp-jplayer {
border:1px solid #009be3;
border-bottom:none;
z-index:1;
}
div.jp-video-270p div.jp-jplayer {
width:480px;
height:270px;
}
div.jp-video-360p div.jp-jplayer {
width:640px;
height:360px;
}
div.jp-jplayer {
background-color: #000000;
}
div.jp-playlist ul li button{
display:none;
}
div.jp-playlist ul li:hover button{
display:inline;
}

9
apps/media/css/music.css Normal file
View File

@ -0,0 +1,9 @@
#folderlist li{list-style-type:none;margin-bottom:10px;}
#folderlist button.prettybutton{font-size:1em;width:10ex;}
li button.right.prettybutton{font-size:1em;}
#collection{padding-top:1em;position:relative;width:70ex;float:left;}
#collection li.album,#collection li.song{margin-left:3ex;}
#playlist{margin-left:72ex;}
#playlist li.current{background-color:#ccc;}
#collection li button{float:right;}
#collection li,#playlist li{list-style-type:none;}

29
apps/media/css/player.css Normal file
View File

@ -0,0 +1,29 @@
#jp-interface{position:fixed;z-index:100;width:25em;left:201px;top:-10px;height:80px;border-bottom:none;}
#jp-interface.player{display:hidden;}
#jp-interface ul.jp-controls{list-style-type:none;padding:0;}
#jp-interface ul.jp-controls li{display:inline;}
#jp-interface ul.jp-controls a{position:absolute;overflow:hidden;text-indent:-9999px;}
a.jp-play,a.jp-pause{width:40px;height:40px;z-index:1;top:20px;left:48px;}
a.jp-play{background:url("../img/jplayer.blue.monday.png") 0 0 no-repeat;}
a.jp-play:hover{background:url("../img/jplayer.blue.monday.png") -41px 0 no-repeat;}
a.jp-pause{background:url("../img/jplayer.blue.monday.png") 0 -42px no-repeat;display:none;}
a.jp-pause:hover{background:url("../img/jplayer.blue.monday.png") -41px -42px no-repeat;}
a.jp-stop{top:26px;left:126px;background:url("../img/jplayer.blue.monday.png") 0 -83px no-repeat;width:28px;height:28px;z-index:1;}
a.jp-stop:hover{background:url("../img/jplayer.blue.monday.png") -29px -83px no-repeat;}
a.jp-previous{left:20px;top:26px;background:url("../img/jplayer.blue.monday.png") 0 -112px no-repeat;width:28px;height:28px;}
a.jp-previous:hover{background:url("../img/jplayer.blue.monday.png") -29px -112px no-repeat;}
a.jp-next{left:88px;top:26px;background:url("../img/jplayer.blue.monday.png") 0 -141px no-repeat;width:28px;height:28px;}
a.jp-next:hover{background:url("../img/jplayer.blue.monday.png") -29px -141px no-repeat;}
div.jp-progress{position:absolute;overflow:hidden;background-color:#293b51;top:32px;left:164px;width:122px;height:15px;}
div.jp-seek-bar{background:url("../img/jplayer.blue.monday.png") 0 -202px repeat-x;width:0;height:100%;cursor:pointer;}
div.jp-play-bar{background:url("../img/jplayer.blue.monday.png") 0 -218px repeat-x;width:0;height:100%;}
div.jp-seeking-bg{background:url("../img/pbar-ani.gif");}
a.jp-mute,a.jp-unmute{height:15px;width:18px;top:32px;left:296px;}
a.jp-mute{background:url("../img/jplayer.blue.monday.png") 0 -186px no-repeat;}
a.jp-mute:hover{background:url("../img/jplayer.blue.monday.png") -19px -170px no-repeat;}
a.jp-unmute{background:url("../img/jplayer.blue.monday.png") 0 -170px no-repeat;display:none;}
a.jp-unmute:hover{background:url("../img/jplayer.blue.monday.png") -19px -186px no-repeat;}
div.jp-volume-bar{position:absolute;overflow:hidden;background:url("../img/jplayer.blue.monday.png") 0 -250px repeat-x;width:46px;height:5px;cursor:pointer;top:37px;left:324px;}
div.jp-volume-bar-value{background:url("../img/jplayer.blue.monday.png") 0 -256px repeat-x;width:0;height:5px;}
div.jp-current-time,div.jp-duration{position:absolute;font-size:.64em;font-style:oblique;top:49px;left:164px;width:122px;}
div.jp-duration{text-align:right;}

View File

@ -1,36 +0,0 @@
.right{
float:right;
}
#folderlist li{
list-style-type:none;
margin-bottom:10px;
}
#folderlist button.prettybutton{
font-size:1em;
width:10ex;
}
li button.right.prettybutton{
font-size:1em;
}
#collection{
padding-top:1em;
position:relative;
width:70ex;
float:left;
}
#collection li{
list-style-type:none;
}
#collection li button{
float:right;
}
#collection li.album, #collection li.song{
margin-left:3ex;
}

View File

@ -34,9 +34,18 @@ require_once('lib_collection.php');
require_once('lib_scanner.php');
require_once('template.php');
OC_UTIL::addScript('media','player');
OC_UTIL::addScript('media','music');
OC_UTIL::addScript('media','jquery.jplayer.min');
OC_UTIL::addStyle('media','player');
OC_UTIL::addStyle('media','music');
OC_APP::setActiveNavigationEntry( 'media_index' );
$tmpl = new OC_TEMPLATE( 'media', 'music', 'user' );
$player = new OC_TEMPLATE( 'media', 'player');
$tmpl->assign('player',$player->fetchPage());
$tmpl->printPage();
?>

50
apps/media/js/files.js Normal file
View File

@ -0,0 +1,50 @@
function musicTypeFromFile(file){
var extention=file.substr(file.indexOf('.')+1);
if(extention=='ogg'){
return 'oga'
}
//TODO check for more specific cases
return extention;
}
function playAudio(filename){
loadPlayer(musicTypeFromFile(filename),function(){
PlayList.add($('#dir').val()+'/'+filename);
PlayList.play(PlayList.items.length-1);
});
}
function addAudio(filename){
loadPlayer(musicTypeFromFile(filename),function(){
PlayList.add($('#dir').val()+'/'+filename);
});
}
function loadPlayer(type,ready){
if(!loadPlayer.done){
OC.addScript('media','jquery.jplayer.min',function(){
OC.addScript('media','player',function(){
$('body').append($('<div id="playerPlaceholder"/>'))
$('#playerPlaceholder').append($('<div/>')).load(OC.filePath('media','templates','player.php'),function(){
loadPlayer.done=true;
PlayList.init(type,ready);
});
});
});
OC.addStyle('media','player');
}else{
ready();
}
}
$(document).ready(function() {
loadPlayer.done=false
FileActions.register('audio','Add to playlist',addAudio);
FileActions.register('application/ogg','Add to playlist',addAudio);
FileActions.register('audio','Play',playAudio);
FileActions.register('application/ogg','Play',playAudio);
FileActions.setDefault('audio','Play');
FileActions.setDefault('application/ogg','Play');
});

View File

@ -1,330 +1,13 @@
var audioPlaylist;
var URLBASE='ajax/api.php?action=play&path=';
$(document).ready(function() {
if(typeof FileActions!=='undefined'){
URLBASE='../apps/media/ajax/api.php?action=play&path=';
var playerLoaded=false;
function playFile(filename){
audioPlaylist.playlist=[];
audioPlaylist.addToPlaylist({
song_name:filename,
song_path:$('#dir').val()+'/'+filename
},true);
audioPlaylist.playlistChange(audioPlaylist.playlist.length-1);
$(document).ready(function(){
//load the collection
$.ajax({
url: OC.linkTo('media','ajax/api.php')+'?action=get_collection',
dataType: 'json',
success: function(collection){
displayCollection(collection);
}
function playAudio(filename){
if(!playerLoaded){
var parent=$('body').append('<div id="media_container"/>');
$('#media_container').load('../apps/media/templates/music.php',function(){
playerLoaded=true;
//remove playlist and collection view
$('#jp_playlist_1').remove();
$('collection').remove();
//init the audio player
audioPlaylist =initPlayList(false,false,function(){
//play the file
playFile(filename);
});
});
}else{
playFile(filename);
}
}
FileActions.register('audio','Play',playAudio);
FileActions.register('application/ogg','Play',playAudio);
FileActions.setDefault('audio','Play');
FileActions.setDefault('application/ogg','Play');
}
Playlist = function(instance, playlist, options) {
var self = this;
this.instance = instance; // String: To associate specific HTML with this playlist
this.playlist = playlist; // Array of Objects: The playlist
this.options = options; // Object: The jPlayer constructor options for this playlist
this.current = -1;
this.cssId = {
jPlayer: "jplayer_",
interface: "jp_interface_",
playlist: "jp_playlist_"
};
this.cssSelector = {};
$.each(this.cssId, function(entity, id) {
self.cssSelector[entity] = "#" + id + self.instance;
});
if(!this.options.cssSelectorAncestor) {
this.options.cssSelectorAncestor = this.cssSelector.interface;
}
$(this.cssSelector.jPlayer).jPlayer(this.options);
$(this.cssSelector.interface + " .jp-previous").click(function() {
self.playlistPrev();
$(this).blur();
return false;
});
$(this.cssSelector.interface + " .jp-next").click(function() {
self.playlistNext();
$(this).blur();
return false;
});
};
Playlist.prototype = {
displayPlaylist: function() {
var self = this;
$(this.cssSelector.playlist + " ul").empty();
for (i=0; i < this.playlist.length; i++) {
var listItem = (i === this.playlist.length-1) ? "<li class='jp-playlist-last'>" : "<li>";
listItem += "<a href='#' id='" + this.cssId.playlist + this.instance + "_item_" + i +"' tabindex='1'>"+ this.playlist[i].name +"</a>";
// Create links to free media
if(this.playlist[i].free) {
var first = true;
listItem += "<div class='jp-free-media'>(";
$.each(this.playlist[i], function(property,value) {
if($.jPlayer.prototype.format[property]) { // Check property is a media format.
if(first) {
first = false;
} else {
listItem += " | ";
}
listItem += "<a id='" + self.cssId.playlist + self.instance + "_item_" + i + "_" + property + "' href='" + value + "' tabindex='1'>" + property + "</a>";
}
});
listItem += ")</span>";
}
listItem += "<button class='right prettybutton remove'>Remove</button>";
listItem += "</li>";
// Associate playlist items with their media
$(this.cssSelector.playlist + " ul").append(listItem);
$(this.cssSelector.playlist + "_item_" + i).data("index", i).click(function() {
var index = $(this).data("index");
if(self.current !== index) {
self.playlistChange(index);
} else {
$(self.cssSelector.jPlayer).jPlayer("play");
}
$(this).blur();
return false;
});
$(this.cssSelector.playlist + "_item_" + i).parent().children('button').data("index", i).click(function() {
var index = $(this).data("index");
self.removeFromPlaylist(index);
});
// Disable free media links to force access via right click
if(this.playlist[i].free) {
$.each(this.playlist[i], function(property,value) {
if($.jPlayer.prototype.format[property]) { // Check property is a media format.
$(self.cssSelector.playlist + "_item_" + i + "_" + property).data("index", i).click(function() {
var index = $(this).data("index");
$(self.cssSelector.playlist + "_item_" + index).click();
$(this).blur();
return false;
});
}
});
}
}
},
playlistInit: function(autoplay) {
if(autoplay) {
this.playlistChange(this.current);
} else {
this.playlistConfig(this.current);
}
},
playlistConfig: function(index,play) {
$(this.cssSelector.playlist + "_item_" + this.current).removeClass("jp-playlist-current").parent().removeClass("jp-playlist-current");
$(this.cssSelector.playlist + "_item_" + index).addClass("jp-playlist-current").parent().addClass("jp-playlist-current");
this.current = index;
var that=this;
if(this.playlist[this.current]){
if($(this.cssSelector.jPlayer).data('jPlayer').options.supplied!=this.playlist[this.current].type){//the the audio type changes we need to reinitialize jplayer
$(this.cssSelector.jPlayer).jPlayer("destroy");
$(this.cssSelector.jPlayer).jPlayer({
ended:this.options.ended,
play:this.options.play,
supplied:this.playlist[this.current].type,
ready:function(){
that.playlistConfig(index);
if(play){
$(that.cssSelector.jPlayer).jPlayer("play");
}
}
});
}else{
$(this.cssSelector.jPlayer).jPlayer("setMedia", this.playlist[this.current]);
}
}
},
playlistChange: function(index) {
this.playlistConfig(index,true);
$(this.cssSelector.jPlayer).jPlayer("play");
},
playlistNext: function() {
var index = (this.current + 1 < this.playlist.length) ? this.current + 1 : 0;
this.playlistChange(index);
},
playlistPrev: function() {
var index = (this.current - 1 >= 0) ? this.current - 1 : this.playlist.length - 1;
this.playlistChange(index);
},
removeFromPlaylist: function(index){
this.playlist.splice(index,1);
this.displayPlaylist();
if(index==this.current){
this.playlistConfig((index<this.playlist.length)?index:0);
}else{
$(this.cssSelector.playlist + "_item_" + this.current).addClass("jp-playlist-current").parent().addClass("jp-playlist-current");
}
},
addToPlaylist : function(stuff,dontRedraw){
var self=this;
if(!stuff){
return;
}
if(stuff.artist_name){
$.each(stuff.albums,function(index,album){
self.addToPlaylist(album,true);
});
}
if(stuff.album_name){
$.each(stuff.songs,function(index,song){
self.addToPlaylist(song,true);
});
}
if(stuff.song_name){
var extention=stuff.song_path.split('.').pop();
var type=musicTypeFromExtention(extention);
var item={name:stuff.song_name,type:type};
item[type]=URLBASE+stuff.song_path;
this.playlist.push(item);
}
if(!dontRedraw){
this.displayPlaylist();
}
}
};
if($('#jp-audio')){//only do this when we're actually in the media player
//load the collection
$.ajax({
url: 'ajax/api.php?action=get_collection',
dataType: 'json',
success: function(collection){
var playlist=[];
var types=[];
for(var i=0;i<collection.length;i++){
var artist=collection[i];
for(var j=0;j<artist.albums.length;j++){
var album=artist.albums[j];
for(var n=0;n<album.songs.length;n++){
var song=album.songs[n];
var extention=song.song_path.split('.').pop();
var type=musicTypeFromExtention(extention);
if(types.indexOf(type)==-1){
types.push(type);
}
}
}
}
displayCollection(collection);
audioPlaylist =initPlayList(true,true);
}
});
}
});
function initPlayList(display,enableAutoPlay,ready){
return new Playlist('1', [],{
ready: function() {
if(display){
audioPlaylist.displayPlaylist();
}
if(enableAutoPlay){
if(window.location.href.indexOf('#')>-1){//autoplay passed arist/album/song
var vars=getUrlVars();
var play;
if(vars['artist']){
$.each(collection,function(index,artist){
if(artist.artist_name==vars['artist']){
play=artist;
if(vars['album']){
$.each(artist.albums,function(index,album){
if(album.album_name==vars['album']){
play=album;
if(vars['song']){
$.each(album.songs,function(index,song){
if(song.song_name==vars['song']){
play=song;
}
});
}
}
});
}
}
});
}
audioPlaylist.addToPlaylist(play);
audioPlaylist.playlistInit(true);
}else{
audioPlaylist.playlistInit(false); // Parameter is a boolean for autoplay.
}
}else{
audioPlaylist.playlistInit(false);
}
if(ready){
ready();
}
},
ended: function() {
audioPlaylist.playlistNext();
},
play: function() {
$(this).jPlayer("pauseOthers");
},
});
}
function musicTypeFromExtention(extention){
if(extention=='ogg'){
return 'oga'
}
//TODO check for more specific cases
return extention;
}
// indexOf implemententation for browsers that don't support it
if (!Array.prototype.indexOf){
Array.prototype.indexOf = function(elt /*, from*/) {
var len = this.length;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
});
function displayCollection(collection){
$('#collection').data('collection',collection);
@ -340,6 +23,8 @@ function displayCollection(collection){
artistNode.children('ul').append(albumNode);
$.each(album.songs,function(index,song){
var songNode=$('<li class="song">'+song.song_name+'<button class="add">Add</button></li>');
song.artist_name=artist.artist_name;
song.album_name=album.album_name;
songNode.data('name',song.song_name);
songNode.data('stuff',song);
albumNode.children('ul').append(songNode);
@ -360,9 +45,40 @@ function displayCollection(collection){
return false;
});
$('li>button.add').click(function(){
audioPlaylist.addToPlaylist($(this).parent().data('stuff'));
PlayList.add($(this).parent().data('stuff'));
PlayList.render($('#playlist'));
return false;
})
});
if(window.location.href.indexOf('#')>-1){//autoplay passed arist/album/song
var vars=getUrlVars();
var play;
if(vars['artist']){
$.each(collection,function(index,artist){
if(artist.artist_name==vars['artist']){
play=artist;
if(vars['album']){
$.each(artist.albums,function(index,album){
if(album.album_name==vars['album']){
play=album;
if(vars['song']){
$.each(album.songs,function(index,song){
if(song.song_name==vars['song']){
play=song;
}
});
}
}
});
}
}
});
}
PlayList.add(play);
PlayList.play();
}else{
PlayList.init();
}
}
function getUrlVars(){
@ -375,4 +91,13 @@ function getUrlVars(){
vars[hash[0]] = decodeURIComponent(hash[1]).replace(/\+/g,' ');
}
return vars;
}
function musicTypeFromFile(file){
var extention=file.substr(file.indexOf('.')+1);
if(extention=='ogg'){
return 'oga'
}
//TODO check for more specific cases
return extention;
}

120
apps/media/js/player.js Normal file
View File

@ -0,0 +1,120 @@
var PlayList={
urlBase:OC.linkTo('media','ajax/api.php')+'?action=play&path=',
current:-1,
items:[],
player:null,
parent:null,
next:function(){
var next=PlayList.current+1;
if(next>=PlayList.items.length){
next=0;
}
PlayList.play(next);
},
previous:function(){
var next=PlayList.current-1;
if(next<0){
next=PlayList.items.length-1;
}
PlayList.play(next);
},
play:function(index){
if(index==null){
index=PlayList.current;
}
if(index>-1 && index<PlayList.items.length){
PlayList.current=index;
if(PlayList.player){
if(PlayList.player.data('jPlayer').options.supplied!=PlayList.items[index].type){//the the audio type changes we need to reinitialize jplayer
PlayList.player.jPlayer("destroy");
PlayList.init(PlayList.items[index].type,PlayList.play);
}else{
PlayList.player.jPlayer("setMedia", PlayList.items[PlayList.current]);
PlayList.player.jPlayer("play");
}
}else{
PlayList.init(PlayList.items[index].type,PlayList.play);
}
}
},
init:function(type,ready){
if(!PlayList.player){
$(".jp-previous").click(function() {
PlayList.previous();
$(this).blur();
PlayList.render();
return false;
});
$(".jp-next").click(function() {
PlayList.next();
$(this).blur();
PlayList.render();
return false;
});
PlayList.player=$('#jp-interface div.player');
}
$(PlayList.player).jPlayer({
ended:PlayList.next,
supplied:type,
ready:function(){
if(ready){
ready();
}
},
cssSelectorAncestor:'#jp-interface',
});
},
add:function(song){
if(song.substr){//we are passed a string, asume it's a url to a song
PlayList.addFile(song);
}
if(song.albums){//a artist object was passed, add all albums inside it
$.each(song.albums,function(index,album){
PlayList.add(album);
});
}
if(song.songs){//a album object was passed, add all songs inside it
$.each(song.songs,function(index,song){
PlayList.add(song);
});
}
if(song.song_name){
var type=musicTypeFromFile(song.song_path);
var item={name:song.song_name,type:type,artist:song.artist_name,album:song.album_name};
item[type]=PlayList.urlBase+encodeURIComponent(song.song_path);
PlayList.items.push(item);
}
},
addFile:function(path){
var type=musicTypeFromFile(path);
var item={name:'unknown',artist:'unknown',album:'unknwon',type:type};//todo get song data
item[type]=PlayList.urlBase+encodeURIComponent(path);
PlayList.items.push(item);
},
render:function(parent){//parent should be an ul element
if(parent){
PlayList.parent=parent;
}else{
parent=PlayList.parent;
}
if(parent){
parent.empty();
for(var i=0;i<PlayList.items.length;i++){
var song=PlayList.items[i];
var item=$('<li>'+song.artist+' - '+song.album+' - '+song.name+'</li>');
item.data('artist',song.artist);
item.data('album',song.album);
item.data('name',song.name);
item.data('index',i);
item.click(function(){
PlayList.play($(this).data('index'));
PlayList.render();
});
if(i==PlayList.current){
item.addClass('current');
}
parent.append(item);
}
}
}
}

View File

@ -1,34 +1,3 @@
<div id='jplayer_1'></div>
<?php echo $_['player'];?>
<div id='collection'><ul/></div>
<div class="jp-audio">
<div class="jp-type-playlist">
<div id="jp_interface_1" class="jp-interface">
<ul class="jp-controls">
<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-stop" tabindex="1">stop</a></li>
<li><a href="#" class="jp-mute" tabindex="1">mute</a></li>
<li><a href="#" class="jp-unmute" tabindex="1">unmute</a></li>
<li><a href="#" class="jp-previous" tabindex="1">previous</a></li>
<li><a href="#" class="jp-next" tabindex="1">next</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-current-time"></div>
<div class="jp-current-time"></div>
<div class="jp-duration"></div>
</div>
<div id="jp_playlist_1" class="jp-playlist">
<ul>
<!-- The method Playlist.displayPlaylist() uses this unordered list -->
<li></li>
</ul>
</div>
</div>
</div>
<ul id="playlist"/>

View File

@ -0,0 +1,23 @@
<div id="jp-interface">
<ul class="jp-controls">
<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-stop" tabindex="1">stop</a></li>
<li><a href="#" class="jp-mute" tabindex="1">mute</a></li>
<li><a href="#" class="jp-unmute" tabindex="1">unmute</a></li>
<li><a href="#" class="jp-previous" tabindex="1">previous</a></li>
<li><a href="#" class="jp-next" tabindex="1">next</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-current-time"></div>
<div class="jp-current-time"></div>
<div class="jp-duration"></div>
<div class='player'></div>
</div>