some refactoring of the media player code
This commit is contained in:
parent
243199859b
commit
0e05a86484
|
@ -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' ));
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;}
|
|
@ -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;}
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
?>
|
||||
|
||||
|
|
|
@ -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');
|
||||
});
|
|
@ -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(){
|
||||
|
@ -376,3 +92,12 @@ function getUrlVars(){
|
|||
}
|
||||
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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"/>
|
|
@ -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>
|
Loading…
Reference in New Issue