add a seekbar into the player + timing informations

This commit is contained in:
bkfox 2016-07-18 21:55:25 +02:00
parent e0edd7fc7d
commit 5a77b4d4ea
5 changed files with 120 additions and 35 deletions

View File

@ -6,14 +6,14 @@
- programs: - programs:
- schedule changes -> update later diffusions according to the new schedule - schedule changes -> update later diffusions according to the new schedule
- stream disable -> remote control on liquidsoap
- users - users
- tests: - tests:
- sound_monitor - sound_monitor
- import_playlist - import_playlist
- liquidsoap: - controllers :
- models to template -> note - models to template -> note
- streamed program disable -> remote control on liquidsoap
- tests: - tests:
- monitor - monitor
- check when a played sound has a temp blank - check when a played sound has a temp blank
@ -29,12 +29,9 @@
-> enhance calendar with possible actions? -> enhance calendar with possible actions?
- website: - website:
- diffusions:
- print program's name in lists / clean up that thing also a bit
- article list with the focus - article list with the focus
- player: - player:
- mixcloud - mixcloud
- seek bar + timer
- remove from playing playlist -> stop - remove from playing playlist -> stop
- date_by_list: - date_by_list:
- sections' url - sections' url
@ -52,7 +49,6 @@
- actions -> noscript case, think of accessibility - actions -> noscript case, think of accessibility
- comments -> remove/edit by the author - comments -> remove/edit by the author
- integrate logs for tracks + in on air - integrate logs for tracks + in on air
- rename controllers.Station into controllers.Streamer -> keep Station for sth else
- get_for "model" -> "models"

View File

@ -23,7 +23,7 @@ class AddToPlaylist(Action):
""" """
@classmethod @classmethod
def make_for_diffusions(cl, request, object): def make_for_diffusion(cl, request, object):
from aircox.website.sections import Player from aircox.website.sections import Player
if object.related.end > tz.make_aware(tz.datetime.now()): if object.related.end > tz.make_aware(tz.datetime.now()):
return return
@ -50,7 +50,7 @@ class AddToPlaylist(Action):
return False return False
if issubclass(type(object), Diffusion): if issubclass(type(object), Diffusion):
return cl.make_for_diffusions(request, object) return cl.make_for_diffusion(request, object)
if issubclass(type(object), Sound): if issubclass(type(object), Sound):
return cl.make_for_sound(request, object) return cl.make_for_sound(request, object)
if hasattr(object, 'sound') and object.sound: if hasattr(object, 'sound') and object.sound:

View File

@ -82,7 +82,6 @@ class Player(sections.Section):
.filter(published = True) \ .filter(published = True) \
.filter(related__end__lte = tz.datetime.now()) \ .filter(related__end__lte = tz.datetime.now()) \
.order_by('-related__end') .order_by('-related__end')
recents = [] recents = []
for post in qs: for post in qs:
archives = post.related.get_archives() archives = post.related.get_archives()

View File

@ -56,16 +56,34 @@
float: right; float: right;
} }
#player .info {
float: right;
}
.playlists {
#player progress {
background: none;
border: none;
width: 100%;
height: 0.8em;
cursor: pointer;
display: none;
} }
.playlists ul:not([selected]) { #player[seekable]:hover progress {
display: block;
}
#player .playlists {
}
#player .playlists ul:not([selected]) {
display: none; display: none;
} }
.playlists nav > a.close, #player .playlists nav > a.close,
.playlists nav > label { #player .playlists nav > label {
float: right; float: right;
} }
@ -73,33 +91,29 @@
content:"{% trans "single mode" %}"; content:"{% trans "single mode" %}";
} }
.playlist {
#player .playlist {
margin: 0; margin: 0;
padding: 0; padding: 0;
height: 15em; height: 15em;
/*overflow-y: auto;*/ /*overflow-y: auto;*/
} }
.playlist .item > *:not(.actions) { #player .playlist .item > *:not(.actions) {
display: inline; display: inline;
margin: 0.2em; margin: 0.2em;
vertical-align: middle; vertical-align: middle;
} }
.playlist .item .info { #player .playlist .actions {
float: right;
}
.playlist .actions {
float: right; float: right;
} }
.playlist .actions a.action { #player .playlist .actions a.action {
display: inline; display: inline;
} }
.playlist .actions label, #player .playlist .actions label,
#playlist-live .actions, #playlist-live .actions,
#playlist-recents .actions a.action[action="remove"], #playlist-recents .actions a.action[action="remove"],
#playlist-favorites .actions a.action[action="sound.mark"], #playlist-favorites .actions a.action[action="sound.mark"],
@ -109,7 +123,7 @@
display: none; display: none;
} }
.playlist .action[action="remove"] { #player .playlist .action[action="remove"] {
float: right; float: right;
} }
</style> </style>
@ -137,7 +151,10 @@
title="{% trans "play/pause" %}"></span> title="{% trans "play/pause" %}"></span>
<h3 class="title"></h3> <h3 class="title"></h3>
<div class="progress info"></div>
</div> </div>
<progress value="0" max="1"></progress>
</div> </div>
<div class="playlists"> <div class="playlists">
<nav> <nav>
@ -380,6 +397,71 @@ Playlist.prototype = {
} }
function PlayerProgress(player) {
this.player = player;
this.progress = player.player.querySelector('progress');
this.info = player.player.querySelector('.progress.info');
var self = this;
// events
player.audio.addEventListener('timeupdate', function(evt) {
self.update();
}, false);
this.progress.addEventListener('click', function(evt) {
player.audio.currentTime = self.time_from_event(evt);
}, false);
this.progress.addEventListener('mouseout', function(evt) {
self.update();
}, false);
this.progress.addEventListener('mousemove', function(evt) {
if(self.player.audio.duration == Infinity)
return;
var pos = self.time_from_event(evt);
self.info.innerHTML = self.secs_to_str(pos);
}, false);
}
PlayerProgress.prototype = {
update: function() {
if( //!this.player.item.seekable ||
this.player.audio.duration == Infinity) {
this.info.innerHTML = '';
this.progress.value = 0;
return;
}
var pos = this.player.audio.currentTime;
this.progress.value = pos;
this.progress.max = this.player.audio.duration;
this.info.innerHTML = this.secs_to_str(pos);
},
secs_to_str: function(seconds) {
seconds = Math.floor(seconds);
var hours = Math.floor(seconds / 3600);
seconds -= hours;
var minutes = Math.floor(seconds / 60);
seconds -= minutes;
var str = hours ? (hours < 10 ? '0' + hours : hours) + ':' : '';
str += (minutes < 10 ? '0' + minutes : minutes) + ':';
str += (seconds < 10 ? '0' + seconds : seconds);
return str;
},
time_from_event: function(evt) {
bounding = this.progress.getBoundingClientRect()
offset = (evt.clientX - bounding.left);
return offset * this.player.audio.duration / bounding.width;
},
}
Player = { Player = {
/// main container of the Player /// main container of the Player
player: undefined, player: undefined,
@ -400,6 +482,7 @@ Player = {
this.__init_audio(); this.__init_audio();
this.__init_playlists(); this.__init_playlists();
this.progress = new PlayerProgress(this);
this.load(); this.load();
}, },
@ -422,9 +505,11 @@ Player = {
}, false); }, false);
this.audio.addEventListener('timeupdate', function() { this.audio.addEventListener('timeupdate', function() {
if(self.audio.seekable.length) if(!self.item.seekable)
return;
PlayerStore.set('stream.' + self.item.stream + '.pos', PlayerStore.set('stream.' + self.item.stream + '.pos',
self.audio.currentTime) self.audio.currentTime);
}, false); }, false);
this.audio.addEventListener('ended', function() { this.audio.addEventListener('ended', function() {
@ -538,6 +623,11 @@ Player = {
player.querySelectorAll('#simple-player .title')[0] player.querySelectorAll('#simple-player .title')[0]
.innerHTML = item.title; .innerHTML = item.title;
if(this.item.seekable)
player.setAttribute('seekable', true);
else
player.removeAttribute('seekable', true);
if(play) { if(play) {
this.__ask_to_seek(item); this.__ask_to_seek(item);
this.play(); this.play();