Some much needed interface work on the media player

This commit is contained in:
Robin Appelman 2011-07-29 23:53:22 +02:00
parent bafd684eb6
commit 94e25ecb0c
13 changed files with 393 additions and 123 deletions

View File

@ -67,7 +67,6 @@ if($arguments['action']){
$artists=OC_MEDIA_COLLECTION::getArtists(); $artists=OC_MEDIA_COLLECTION::getArtists();
foreach($artists as &$artist){ foreach($artists as &$artist){
$artist['albums']=OC_MEDIA_COLLECTION::getAlbums($artist['artist_id']); $artist['albums']=OC_MEDIA_COLLECTION::getAlbums($artist['artist_id']);
$artistHasSongs=false;
foreach($artist['albums'] as &$album){ foreach($artist['albums'] as &$album){
$album['songs']=OC_MEDIA_COLLECTION::getSongs($artist['artist_id'],$album['album_id']); $album['songs']=OC_MEDIA_COLLECTION::getSongs($artist['artist_id'],$album['album_id']);
} }

View File

@ -28,6 +28,36 @@ if(OC_App::getCurrentApp()=='files'){
OC_App::register( array( 'order' => 3, 'id' => 'media', 'name' => 'Media' )); OC_App::register( array( 'order' => 3, 'id' => 'media', 'name' => 'Media' ));
OC_App::addNavigationEntry( array( 'id' => 'media_index', 'order' => 2, 'href' => OC_Helper::linkTo( 'media', 'index.php' ), 'icon' => OC_Helper::imagePath( 'media', 'media.png' ), 'name' => 'Media' )); OC_APP::addNavigationEntry( array( 'id' => 'media_index', 'order' => 2, 'href' => OC_HELPER::linkTo( 'media', 'index.php' ), 'icon' => OC_HELPER::imagePath( 'media', 'media.png' ), 'name' => 'Media' ));
OC_App::addSettingsPage( array( 'id' => 'media_settings', 'order' => 5, 'href' => OC_Helper::linkTo( 'media', 'settings.php' ), 'name' => 'Media', 'icon' => OC_Helper::imagePath( 'media', 'media.png' ))); OC_APP::addSettingsPage( array( 'id' => 'media_settings', 'order' => 5, 'href' => OC_HELPER::linkTo( 'media', 'settings.php' ), 'name' => 'Media', 'icon' => OC_HELPER::imagePath( 'media', 'media.png' )));
// add subnavigations
$entry = array(
'id' => "media_playlist",
'order'=>1,
'href' => '#playlist',
'name' => 'Playlist'
);
OC_APP::addNavigationSubEntry( "media_index", $entry);
$entry = array(
'id' => "media_collection",
'order'=>1,
'href' => '#collection',
'name' => 'Collection'
);
OC_APP::addNavigationSubEntry( "media_index", $entry);
$entry = array(
'id' => "media_recent",
'order'=>1,
'href' => '#recent',
'name' => 'Most Recent'
);
OC_APP::addNavigationSubEntry( "media_index", $entry);
$entry = array(
'id' => "media_mostplayer",
'order'=>1,
'href' => '#mostplayed',
'name' => 'Most Played'
);
OC_APP::addNavigationSubEntry( "media_index", $entry);
?> ?>

View File

@ -3,7 +3,15 @@
li button.right.prettybutton{font-size:1em;} li button.right.prettybutton{font-size:1em;}
#collection{padding-top:1em;position:relative;width:70ex;float:left;} #collection{padding-top:1em;position:relative;width:70ex;float:left;}
#collection li.album,#collection li.song{margin-left:3ex;} #collection li.album,#collection li.song{margin-left:3ex;}
#playlist{margin-left:72ex;} #playlist{width:100%;border-spacing:0;}
#playlist li.current{background-color:#ccc;} #playlist th{background-color:#ccc; text-align:left; font-size:1.2em; padding:0.2em}
#playlist tr.selected{background-color:#eee;}
#playlist tr.current{background-color:#ccc;}
#playlist td.time, #playlist th.time{text-align:right; padding-right:1em;}
#collection li button{float:right;} #collection li button{float:right;}
#collection li,#playlist li{list-style-type:none;} #collection li,#playlist li{list-style-type:none;}
.template{display:none}
#collection{display:none}/*hide the collection initially*/
#collection li{padding-right:10px;}
img.remove{float:right;};

View File

@ -1,4 +1,4 @@
#jp-interface{position:fixed;z-index:100;width:25em;left:201px;top:-20px;height:80px;border-bottom:none;} #jp-interface{position:fixed;z-index:100;width:25em;left:201px;top:-20px;height:60px;border-bottom:none;}
#jp-interface div.player{height:0px} #jp-interface div.player{height:0px}
#jp-interface ul.jp-controls{list-style-type:none;padding:0;} #jp-interface ul.jp-controls{list-style-type:none;padding:0;}
#jp-interface ul.jp-controls li{display:inline;} #jp-interface ul.jp-controls li{display:inline;}

View File

@ -33,18 +33,26 @@ if( !OC_User::isLoggedIn()){
require_once('lib_collection.php'); require_once('lib_collection.php');
require_once('lib_scanner.php'); require_once('lib_scanner.php');
OC_Util::addScript('media','player'); OC_UTIL::addScript('media','player');
OC_Util::addScript('media','music'); OC_UTIL::addScript('media','music');
OC_Util::addScript('media','jquery.jplayer.min'); OC_UTIL::addScript('media','playlist');
OC_Util::addStyle('media','player'); OC_UTIL::addScript('media','collection');
OC_Util::addStyle('media','music'); OC_UTIL::addScript('media','jquery.jplayer.min');
OC_UTIL::addStyle('media','player');
OC_UTIL::addStyle('media','playlist');
OC_UTIL::addStyle('media','music');
OC_App::setActiveNavigationEntry( 'media_index' ); OC_APP::setActiveNavigationEntry( 'media_playlist' );
$tmpl = new OC_Template( 'media', 'music', 'user' ); $tmpl = new OC_Template( 'media', 'music', 'user' );
$player = new OC_Template( 'media', 'player'); $player = new OC_TEMPLATE( 'media', 'player');
$playlist = new OC_TEMPLATE( 'media', 'playlist');
$collection= new OC_TEMPLATE( 'media', 'collection');
$tmpl->assign('player',$player->fetchPage()); $tmpl->assign('player',$player->fetchPage());
$tmpl->assign('playlist',$playlist->fetchPage());
$tmpl->assign('collection',$collection->fetchPage());
$tmpl->printPage(); $tmpl->printPage();
?> ?>

126
apps/media/js/collection.js Normal file
View File

@ -0,0 +1,126 @@
Collection={
artists:[],
loaded:false,
loading:false,
loadedListeners:[],
load:function(ready){
if(ready){
Collection.loadedListeners.push(ready);
}
if(!Collection.loading){
Collection.loading=true;
$.ajax({
url: OC.linkTo('media','ajax/api.php')+'?action=get_collection',
dataType: 'json',
success: function(collection){
Collection.artists=collection;
//set the album and artist fieds for the songs
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 w=0;w<album.songs.length;w++){
album.songs[w].album_name=album.album_name;
album.songs[w].artist_name=artist.artist_name;
album.songs[w].artist_name=artist.artist_name;
}
}
}
Collection.loaded=true;
Collection.loading=false;
for(var i=0;i<Collection.loadedListeners.length;i++){
Collection.loadedListeners[i]();
}
}
});
}
},
display:function(){
if(Collection.parent){
Collection.parent.show();
}
if(!Collection.loaded){
Collection.load(Collection.display)
}else{
if(Collection.parent){
Collection.parent.children('li.artist').remove();
var template=Collection.parent.children('li.template');
for(var i=0;i<Collection.artists.length;i++){
var artist=Collection.artists[i];
var li=template.clone();
li.data('artist',artist);
li.removeClass('template');
li.addClass('artist');
li.children('span').text(artist.artist_name);
li.children('button').click(function(){
PlayList.add($(this).parent().data('artist'));
})
Collection.parent.append(li);
}
}
}
},
parent:null,
hide:function(){
if(Collection.parent){
Collection.parent.hide();
}
},
showAlbums:function(artistLi){
$('ul.albums').parent().removeClass('active');
$('ul.albums').remove();
var artist=artistLi.data('artist');
if(artist){
var template=Collection.parent.children('li.template');
var ul=$('<ul class="albums"></ul>');
for(var i=0;i<artist.albums.length;i++){
var li=template.clone();
var album=artist.albums[i];
li.removeClass('template');
li.addClass('album');
li.data('album',album);
li.children('span').text(album.album_name);
li.children('button').click(function(){
PlayList.add($(this).parent().data('album'));
})
ul.append(li);
}
artistLi.append(ul);
}
},
showSongs:function(albumLi){
$('ul.songs').parent().removeClass('active');
$('ul.songs').remove();
var album=albumLi.data('album');
var template=Collection.parent.children('li.template');
var ul=$('<ul class="songs"></ul>');
for(var i=0;i<album.songs.length;i++){
var li=template.clone();
var song=album.songs[i];
li.removeClass('template');
li.addClass('song',song);
li.children('span').text(song.song_name);
li.children('button').click(function(){
PlayList.add($(this).parent().data('span'));
})
ul.append(li);
}
albumLi.append(ul);
}
}
$(document).ready(function(){
Collection.parent=$('#collection');
Collection.load();
$('#collection li.artist>span').live('click',function(){
$(this).parent().toggleClass('active');
Collection.showAlbums($(this).parent());
});
$('#collection li.album>span').live('click',function(){
$(this).parent().toggleClass('active');
Collection.showSongs($(this).parent());
});
});

View File

@ -1,85 +1,20 @@
$(document).ready(function(){ $(document).ready(function(){
//load the collection //load the collection
$.ajax({ $('#plugins a[href="#collection"]').click(function(){
url: OC.linkTo('media','ajax/api.php')+'?action=get_collection', $('#plugins li.subentry a.active').removeClass('active');
dataType: 'json', $(this).addClass('active');
success: function(collection){ PlayList.hide();
displayCollection(collection); Collection.display();
} });
$('#plugins a[href="#playlist"]').click(function(){
$('#plugins li.subentry a.active').removeClass('active');
$(this).addClass('active');
PlayList.render();
Collection.hide();
}); });
}); });
function displayCollection(collection){
$('#collection').data('collection',collection);
$.each(collection,function(index,artist){
var artistNode=$('<li class="artist">'+artist.artist_name+'<button class="add">Add</button><ul/></li>');
artistNode.data('name',artist.artist_name);
artistNode.data('stuff',artist);
$('#collection>ul').append(artistNode);
$.each(artist.albums,function(index,album){
var albumNode=$('<li class="album">'+album.album_name+'<button class="add">Add</button><ul/></li>');
albumNode.data('name',album.album_name);
albumNode.data('stuff',album);
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);
});
});
});
$('li.album').hide();
$('li.song').hide();
$('li.artist').click(function(){
$(this).children().children().slideToggle();
return false;
});
$('li.album').click(function(){
$(this).children().children().slideToggle();
return false;
});
$('li.song').click(function(){
return false;
});
$('li>button.add').click(function(){
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(){ function getUrlVars(){
var vars = [], hash; var vars = [], hash;
@ -94,7 +29,7 @@ function getUrlVars(){
} }
function musicTypeFromFile(file){ function musicTypeFromFile(file){
var extention=file.substr(file.indexOf('.')+1); var extention=file.split('.').pop();
if(extention=='ogg'){ if(extention=='ogg'){
return 'oga' return 'oga'
} }

View File

@ -3,13 +3,13 @@ var PlayList={
current:-1, current:-1,
items:[], items:[],
player:null, player:null,
parent:null,
next:function(){ next:function(){
var next=PlayList.current+1; var next=PlayList.current+1;
if(next>=PlayList.items.length){ if(next>=PlayList.items.length){
next=0; next=0;
} }
PlayList.play(next); PlayList.play(next);
PlayList.render();
}, },
previous:function(){ previous:function(){
var next=PlayList.current-1; var next=PlayList.current-1;
@ -17,6 +17,7 @@ var PlayList={
next=PlayList.items.length-1; next=PlayList.items.length-1;
} }
PlayList.play(next); PlayList.play(next);
PlayList.render();
}, },
play:function(index){ play:function(index){
if(index==null){ if(index==null){
@ -66,6 +67,9 @@ var PlayList={
}); });
}, },
add:function(song){ add:function(song){
if(!song){
return;
}
if(song.substr){//we are passed a string, asume it's a url to a song if(song.substr){//we are passed a string, asume it's a url to a song
PlayList.addFile(song); PlayList.addFile(song);
} }
@ -81,7 +85,7 @@ var PlayList={
} }
if(song.song_name){ if(song.song_name){
var type=musicTypeFromFile(song.song_path); var type=musicTypeFromFile(song.song_path);
var item={name:song.song_name,type:type,artist:song.artist_name,album:song.album_name}; var item={name:song.song_name,type:type,artist:song.artist_name,album:song.album_name,length:song.song_length,playcount:song.song_playcount};
item[type]=PlayList.urlBase+encodeURIComponent(song.song_path); item[type]=PlayList.urlBase+encodeURIComponent(song.song_path);
PlayList.items.push(item); PlayList.items.push(item);
} }
@ -92,30 +96,9 @@ var PlayList={
item[type]=PlayList.urlBase+encodeURIComponent(path); item[type]=PlayList.urlBase+encodeURIComponent(path);
PlayList.items.push(item); PlayList.items.push(item);
}, },
render:function(parent){//parent should be an ul element remove:function(index){
if(parent){ PlayList.items.splice(index,1);
PlayList.parent=parent; PlayList.render();
}else{ },
parent=PlayList.parent; render:function(){}
}
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);
}
}
}
} }

142
apps/media/js/playlist.js Normal file
View File

@ -0,0 +1,142 @@
PlayList.render=function(){
$('#playlist').show();
PlayList.parent.empty();
for(var i=0;i<PlayList.items.length;i++){
var tr=PlayList.template.clone();
var item=PlayList.items[i];
if(i==PlayList.current){
tr.addClass('current');
}
tr.removeClass('template');
tr.data('name',item.name);
tr.data('artist',item.artist);
tr.data('album',item.album);
tr.data('time',item.length);
tr.data('plays',item.playcount);
tr.children('td.name').children('span').text(item.name);
tr.children('td.artist').text(item.artist);
tr.children('td.album').text(item.album);
var secconds=(item.length%60);
if(secconds<10){
secconds='0'+secconds;
}
var length=Math.floor(item.length/60)+':'+secconds;
tr.children('td.time').text(length);
tr.children('td.plays').text(item.playcount);
tr.data('index',i);
tr.click(function(){
PlayList.play($(this).data('index'));
PlayList.parent.children('tr').removeClass('current');
$(this).addClass('current');
});
tr.hover(function(){
var button=$('<img class="remove" title="Remove"/>');
button.attr('src',OC.imagePath('core','actions/delete'));
$(this).children().last().append(button);
button.click(function(event){
event.stopPropagation();
event.preventDefault();
var index=$(this).parent().parent().data('index');
PlayList.remove(index);
});
},function(){
$(this).children().last().children('img.remove').remove();
});
tr.children('td.name').children('input').click(function(event){
event.stopPropagation();
if($(this).attr('checked')){
$(this).parent().parent().addClass('selected');
if($('td.name input:checkbox').length==$('td.name input:checkbox:checked').length){
$('#selectAll').attr('checked',true);
}
}else{
$(this).parent().parent().removeClass('selected');
$('#selectAll').attr('checked',false);
}
procesSelection();
});
PlayList.parent.append(tr);
}
}
PlayList.getSelected=function(){
return $('td.name input:checkbox:checked').parent().parent();
}
PlayList.hide=function(){
$('#playlist').hide();
}
$(document).ready(function(){
PlayList.parent=$('#playlist tbody');
PlayList.template=$('#playlist tr.template');
$('#selectAll').click(function(){
if($(this).attr('checked')){
// Check all
$('td.name input:checkbox').attr('checked', true);
$('td.name input:checkbox').parent().parent().addClass('selected');
}else{
// Uncheck all
$('td.name input:checkbox').attr('checked', false);
$('td.name input:checkbox').parent().parent().removeClass('selected');
}
procesSelection();
});
});
function procesSelection(){
var selected=PlayList.getSelected();
if(selected.length==0){
$('th.name span').text('Name');
$('th.artist').text('Artist');
$('th.album').text('Album');
$('th.time').text('Time');
$('th.plays').empty();
$('th.plays').text('Plays');
}else{
var name=selected.length+' selected';
var artist=$(selected[0]).data('artist');
var album=$(selected[0]).data('album');
var time=$(selected[0]).data('time');
var plays=$(selected[0]).data('plays');
for(var i=1;i<selected.length;i++){
var item=$(selected[i]);
if(artist!='mixed' && item.data('artist')!==artist){
artist='mixed'
}
if(album!='mixed' && item.data('album')!==album){
album='mixed'
}
if(time!='mixed' && item.data('time')!==time){
time='mixed'
}
if(plays!='mixed' && item.data('plays')!==plays){
plays='mixed'
}
}
$('th.name span').text(name);
$('th.artist').text(artist);
$('th.album').text(album);
if(time!='mixed'){
var secconds=(time%60);
if(secconds<10){
secconds='0'+secconds;
}
var time=Math.floor(time/60)+':'+secconds;
}
$('th.time').text(time);
$('th.plays').text(plays);
var button=$('<img class="remove" title="Remove"/>');
button.attr('src',OC.imagePath('core','actions/delete'));
$('th.plays').append(button);
button.click(function(event){
event.stopPropagation();
event.preventDefault();
PlayList.getSelected().each(function(index,element){
var index=$(element).data('index');
PlayList.items[index]=null;
});
PlayList.items=PlayList.items.filter(function(item){return item!==null});
PlayList.render();
procesSelection();
});
}
}

View File

@ -128,7 +128,7 @@ class OC_MEDIA_COLLECTION{
$artists=$query->execute(array($search,OC_User::getUser()))->fetchAll(); $artists=$query->execute(array($search,OC_User::getUser()))->fetchAll();
$result=array(); $result=array();
foreach($artists as $artist){ foreach($artists as $artist){
$result[$artist['id']]=array('artist_name'=>$artist['name'],'artist_id'=>$artist['id']); $result[]=array('artist_name'=>$artist['name'],'artist_id'=>$artist['id']);
} }
return $result; return $result;
} }
@ -179,7 +179,7 @@ class OC_MEDIA_COLLECTION{
$result=array(); $result=array();
foreach($albums as $album){ foreach($albums as $album){
if(count(self::getSongs($album['album_artist'],$album['album_id']))){ if(count(self::getSongs($album['album_artist'],$album['album_id']))){
$result[$album['album_id']]=$album; $result[]=$album;
} }
} }
return $result; return $result;

View File

@ -0,0 +1,9 @@
<ul id='collection'>
<li class='artist'>
<img src="<?php echo image_path('files','loading.gif') ?>" alt='loading'/>Loading Collection...
</li>
<li class='template'>
<span></span>
<button>Add</button>
</li>
</ul>

View File

@ -1,3 +1,3 @@
<?php echo $_['player'];?> <?php echo $_['player'];?>
<div id='collection'><ul/></div> <?php echo $_['collection'];?>
<ul id="playlist"/> <?php echo $_['playlist'];?>

View File

@ -0,0 +1,30 @@
<table id='playlist'>
<thead>
<tr>
<th class='name'><input id='selectAll' type='checkbox'>Name</th>
<th class='artist'>Artist</th>
<th class='album'>Album</th>
<th class='time'>Time</th>
<th class='plays'>Plays</th>
</tr>
</thead>
<tbody>
<tr>
<td>
The playlist is empty
</td>
</tr>
</tbody>
<tfoot>
<tr class='template'>
<td class='name'>
<input type='checkbox'>
<span></span>
</td>
<td class='artist'></td>
<td class='album'></td>
<td class='time'></td>
<td class='plays'></td>
</tr>
</tfoot>
</table>