<!DOCTYPE HTML>
<html i18n-values="dir:textdirection;">
<head>
<meta charset="utf-8">
<title>Media Player</title>
<style type="text/css">
body {
overflow: hidden;
background: black;
}
.error {
left: 0;
right: 0;
color: white;
bottom: 38px;
position: absolute;
}
.glow {
left: 0;
right: 0;
bottom: 30px;
height: 8px;
opacity: .4;
position: absolute;
background: -webkit-linear-gradient(transparent, white);
}
.audiotitle {
left: 0;
right: 0;
text-align: center;
position: absolute;
color: white;
top: 100px;
}
.progress {
-webkit-appearance: sliderthumb-horizontal;
position: absolute;
background: transparent;
left: 93px;
right: 120px;
bottom: -2px;
height: 30px;
z-index: 99999;
border-left: 1px solid #424242;
}
.playercontrolsbox {
bottom: 0;
left: 0;
height: 30px;
right: 0;
position: absolute;
}
.videocontrols {
top: 0;
left: 0;
z-index: 999;
height: 100%;
opacity: .9;
right: 0;
position: absolute;
background: -webkit-linear-gradient(#323232, #070707);
}
.sliderback {
bottom: 12px;
left: 93px;
right: 120px;
height: 5px;
position: absolute;
border-radius: 3px;
background: -webkit-linear-gradient(#ced9fa, #e8ecf9);
border: 1px solid #ffffff;
}
.sliderplayed {
height: 100%;
width:0;
left: -1px;
top: -1px;
border-radius: 3px;
border: 1px solid #9ca5b7;
position: absolute;
background: -webkit-linear-gradient(#4a5d84, #232c3d);
}
.sliderloaded {
height: 100%;
width:0;
left: -1px;
top: -1px;
border-radius: 3px;
position: absolute;
background: #6a799a;
border: 1px solid #ffffff;
}
.audiocontrols {
top: 0;
left: 0;
z-index: 999;
height: 100%;
opacity: .9;
right: 0;
position: absolute;
background: -webkit-linear-gradient(#323232, #070707);
}
.soundbutton {
position: absolute;
right: 30px;
bottom: 0;
border-left: 1px solid #424242;
border-right: 1px solid black;
}
.soundiconhigh {
background: url('shared/images/mediaplayer_vol_high.png');
}
.soundiconmuted {
background: url('shared/images/mediaplayer_vol_mute.png');
}
.soundiconhigh,
.soundiconmuted {
background-repeat: no-repeat;
background-position: 6px 8px;
}
.volume {
position: absolute;
bottom: 30px;
height: 80px;
width: 30px;
right: 30px;
z-index: 99999;
background: black;
background: -webkit-linear-gradient(#323232, #070707);
}
.fullscreen {
position: absolute;
right: 60px;
bottom: 0;
border-left: 1px solid #424242;
border-right: 1px solid black;
}
.fullscreenicon {
background: url('shared/images/mediaplayer_full_screen.png');
background-repeat: no-repeat;
background-position: 6px 8px;
}
.fullscreenexiticon {
background: url('shared/images/mediaplayer_full_screen_exit.png');
background-repeat: no-repeat;
background-position: 6px 8px;
}
.volumeslider {
-webkit-appearance: slider-vertical;
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
}
.playbutton {
position: absolute;
left: 30px;
bottom: 0;
border-left: 1px solid #424242;
border-right: 1px solid black;
}
.playicon {
background: url('shared/images/mediaplayer_play.png');
background-repeat: no-repeat;
background-position: 9px 8px;
}
.pausebutton {
position: absolute;
left: 30px;
bottom: 0;
border-left: 1px solid #424242;
border-right: 1px solid black;
}
.pauseicon {
background: url('shared/images/mediaplayer_pause.png');
background-repeat: no-repeat;
background-position: 9px 8px;
}
.prevbutton {
position: absolute;
left: 0;
bottom: 0;
border-right: 1px solid black;
}
.previcon {
background: url('shared/images/mediaplayer_prev.png');
background-repeat: no-repeat;
background-position: 6px 8px;
}
.playbackvideoelement {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.duration {
right: 90px;
color: white;
position: absolute;
top: 8.5px;
font-size: .6em;
height: 30px;
}
.playbackaudioelement {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.nextbutton {
position: absolute;
left: 60px;
bottom: 0;
border-left: 1px solid #424242;
border-right: 1px solid black;
}
.nexticon {
background: url('shared/images/mediaplayer_next.png');
background-repeat: no-repeat;
background-position: 6px 8px;
}
.playlistbutton {
position: absolute;
right: 0;
bottom: 0;
border-left: 1px solid #424242;
border-right: 1px solid black;
}
.playlisticon {
background: url('shared/images/mediaplayer_playlist.png');
background-repeat: no-repeat;
background-position: 6px 8px;
}
.controlbutton {
z-index: 9999;
cursor: pointer;
width: 28px;
height: 30px;
}
.controlbutton:hover {
background: -webkit-linear-gradient(#6a7eac, #000);
}
.icon {
width: 100%;
height: 100%;
z-index: 9999;
}
</style>
<script src="shared/js/local_strings.js"></script>
<script src="shared/js/media_common.js"></script>
<script>
function $(o) {
return document.getElementById(o);
}
var videoPlaybackElement = null;
var audioPlaybackElement = null;
var currentPlaylist = null;
var currentItem = -1;
var savedVolumeValue = 0;
var hideVolumeTimerId = 0;
var localStrings;
var fullScreen = false;
///////////////////////////////////////////////////////////////////////////////
// Document Functions:
/**
* Window onload handler, sets up the page.
*/
function load() {
document.body.addEventListener('dragover', function(e) {
if (e.preventDefault) e.preventDefault();
});
document.body.addEventListener('drop', function(e) {
if (e.preventDefault) e.preventDefault();
});
document.body.addEventListener('keydown', onkeydown);
localStrings = new LocalStrings();
chrome.send('getCurrentPlaylist', []);
}
function onMediaProgress() {
var element = getMediaElement();
var current = element.currentTime;
var duration = element.duration;
var progress = $('progress');
progress.value = (current*100)/duration;
var played = $('sliderplayed');
played.style.width = '' + progress.value + '%';
if (progress.value == 100) {
onMediaComplete();
}
}
function onLoadedProgress(e) {
var element = $('sliderloaded');
if (e.lengthComputable) {
element.style.display = 'block';
var percent = (e.loaded * 100) / e.total;
element.style.width = '' + percent + '%';
} else {
element.style.display = 'none';
}
}
function onMediaError(e) {
console.log('Got new error');
console.log(e);
chrome.send('playbackError', ['Error playing back',
currentPlaylist[currentItem].path]);
if (currentPlaylist.length == 1) {
$('error').textContent = localStrings.getString('errorstring');
} else {
chrome.send("showPlaylist", []);
}
onMediaComplete();
}
function onMediaComplete() {
currentItem ++;
if (currentItem >= currentPlaylist.length) {
currentItem -= 1;
var element = getMediaElement();
if (!getMediaElement().error) {
element.currentTime = 0;
element.pause();
onMediaProgress();
}
onMediaPause();
return;
}
var mediaElement = getMediaElement();
mediaElement.removeEventListener("progress", onLoadedProgress, true);
mediaElement.removeEventListener("timeupdate", onMediaProgress, true);
mediaElement.removeEventListener("durationchange", onMetadataAvail, true);
// MediaElement.removeEventListener("ended", onMediaComplete, true);
mediaElement.removeEventListener("play", onMediaPlay, true);
mediaElement.removeEventListener("pause", onMediaPause, true);
mediaElement.onerror = undefined;
chrome.send('currentOffsetChanged', ['' + currentItem]);
playMediaFile(currentPlaylist[currentItem].path);
}
function onMediaPlay() {
var pausebutton = $('pausebutton');
var playbutton = $('playbutton');
pausebutton.style.display = 'block';
playbutton.style.display = 'none';
}
function onMediaPause() {
var pausebutton = $('pausebutton');
var playbutton = $('playbutton');
playbutton.style.display = 'block';
pausebutton.style.display = 'none';
}
function setupMediaEvents(element) {
element.addEventListener("progress", onLoadedProgress, true);
element.addEventListener("timeupdate", onMediaProgress, true);
element.addEventListener("durationchange", onMetadataAvail, true);
// element.addEventListener("ended", onMediaComplete, true);
element.onerror = onMediaError;
element.addEventListener("play", onMediaPlay, true);
element.addEventListener("pause", onMediaPause, true);
element.oncontextmenu = function() {
return false;
};
}
function getMediaElement() {
var mediaElement;
if (videoPlaybackElement) {
mediaElement = videoPlaybackElement;
} else {
mediaElement = audioPlaybackElement;
}
return mediaElement;
}
function playPauseButtonClick() {
var mediaElement = getMediaElement();
if (mediaElement.paused || mediaElement.ended) {
mediaElement.play();
} else {
mediaElement.pause();
}
}
function prevButtonClick() {
var element = getMediaElement();
if (element.currentTime > 6) {
element.currentTime = 0;
return;
}
currentItem --;
if (currentItem < 0) {
currentItem = -1;
return;
}
chrome.send('currentOffsetChanged', ['' + currentItem]);
playMediaFile(currentPlaylist[currentItem].path);
}
function nextButtonClick() {
currentItem ++;
if (currentItem >= currentPlaylist.length) {
currentItem = -1;
return;
}
chrome.send('currentOffsetChanged', ['' + currentItem]);
playMediaFile(currentPlaylist[currentItem].path);
}
function userChangedProgress() {
var val = $('progress').value;
var element = getMediaElement();
if (element.seekable && element.duration) {
var current = (progress.value * element.duration)/100;
element.currentTime = current;
}
}
function changeVolumeVisibility(visible) {
var volume = $('volume');
volume.style.display = visible ? 'block' : 'none';
}
function showVolume() {
if (hideVolumeTimerId) {
clearTimeout(hideVolumeTimerId);
hideVolumeTimerId = 0;
}
changeVolumeVisibility(true);
}
function hideVolume() {
if (!hideVolumeTimerId)
hideVolumeTimerId = setTimeout('changeVolumeVisibility(false)', 500);
}
function volumeChange() {
var volumeslider = $('volumeslider');
var element = getMediaElement();
element.volume = (volumeslider.value/100);
var soundicon = $('soundicon');
soundicon.className = soundicon.className.replace(
/soundicon.*/,
element.volume > 0 ? 'soundiconhigh' : 'soundiconmuted');
}
function muteVolume(mute) {
var volumeslider = $('volumeslider');
var element = getMediaElement();
if (mute) {
savedVolumeValue = volumeslider.value;
volumeslider.value = 0;
volumeChange();
} else {
volumeslider.value = savedVolumeValue;
volumeChange();
}
}
function toggleVolumeMute() {
muteVolume($('volumeslider').value != 0);
}
function getPathAndFilenameForPath(path) {
return path.match(/(.*)[\/\\]([^\/\\]+)\.\w+$/);
}
var hidingControlsAnimation = null;
const INACTIVITY_TIMEOUT = 5000;
const INACTIVITY_CHECK_INTERVAL = 1000;
const ANIMATION_DURATION = 1500;
const ANIMATION_STEP = 50;
function HidingControlsAnimation() {
this.offsetPercent = 0;
this.recentActivity = Date.now();
this.inactivityInterval = setInterval(this.checkInactivity.bind(this),
INACTIVITY_CHECK_INTERVAL);
this.onActivityClosure = this.onActivity.bind(this);
document.body.addEventListener('mousemove', this.onActivityClosure);
document.body.addEventListener('mousedown', this.onActivityClosure);
document.body.addEventListener('keydown', this.onActivityClosure);
}
HidingControlsAnimation.prototype = {
cleanup: function () {
this.stopAnimation();
clearInterval(this.inactivityInterval);
document.body.removeEventListener('mousemove', this.onActivityClosure);
document.body.removeEventListener('mousedown', this.onActivityClosure);
document.body.removeEventListener('keydown', this.onActivityClosure);
},
onActivity: function() {
this.recentActivity = Date.now();
// If not fully visible, start sliding up (or reverse sliding down).
if (this.offsetPercent != 0)
this.startAnimation(-1);
},
checkInactivity: function() {
if ((Date.now() - this.recentActivity) > INACTIVITY_TIMEOUT) {
// If fully visible start sliding down.
if (this.offsetPercent == 0)
this.startAnimation(1);
}
},
startAnimation: function (direction) {
this.direction = direction;
this.startOffset = this.offsetPercent;
this.startTime = Date.now();
if (!this.animationInterval)
this.animationInterval = setInterval(this.doAnimation.bind(this),
ANIMATION_STEP);
},
doAnimation: function () {
var phase = (Date.now() - this.startTime) / ANIMATION_DURATION;
var newOffsetPercent = this.startOffset + this.direction * phase * 100;
if (newOffsetPercent <= 0) {
this.offsetPercent = 0;
this.stopAnimation();
} else if (newOffsetPercent >= 100){
this.offsetPercent = 100;
this.stopAnimation();
} else {
this.offsetPercent = Math.round(newOffsetPercent);
}
$('playercontrols').style.top = this.offsetPercent + '%';
},
stopAnimation: function () {
if (this.animationInterval) {
clearInterval(this.animationInterval);
this.animationInterval = null;
}
}
};
function setupPlaybackControls() {
var element = $('playercontrols');
playercontrols.innerHTML = ''; // clear out other
var controlsclass = '';
if (hidingControlsAnimation) {
hidingControlsAnimation.cleanup();
hidingControlsAnimation = null;
}
if (videoPlaybackElement != null) {
controlsclass = 'video';
element.className = 'videocontrols';
hidingControlsAnimation = new HidingControlsAnimation();
} else if (audioPlaybackElement != null) {
controlsclass = 'audio';
element.className = 'audiocontrols';
}
var playbutton = document.createElement('div');
playbutton.id = 'playbutton';
playbutton.className = controlsclass + ' controlbutton playbutton';
playbutton.onclick = playPauseButtonClick;
var playicon = document.createElement('div');
playicon.className = 'icon playicon';
playbutton.appendChild(playicon);
element.appendChild(playbutton);
var pausebutton = document.createElement('div');
pausebutton.id = 'pausebutton';
pausebutton.className = controlsclass + ' controlbutton pausebutton';
pausebutton.onclick = playPauseButtonClick;
var pauseicon = document.createElement('div');
pauseicon.className = 'icon pauseicon';
pausebutton.appendChild(pauseicon);
element.appendChild(pausebutton);
var nextbutton = document.createElement('div');
nextbutton.id = 'nextbutton';
nextbutton.className = controlsclass + ' controlbutton nextbutton';
nextbutton.onclick = nextButtonClick;
var nexticon = document.createElement('div');
nexticon.className = 'icon nexticon';
nextbutton.appendChild(nexticon);
element.appendChild(nextbutton);
var prevbutton = document.createElement('div');
prevbutton.id = 'prevbutton';
prevbutton.className = controlsclass + ' controlbutton prevbutton';
prevbutton.onclick = prevButtonClick;
var previcon = document.createElement('div');
previcon.className = 'icon previcon';
prevbutton.appendChild(previcon);
element.appendChild(prevbutton);
var playlistbutton = document.createElement('div');
playlistbutton.id = 'playlistbutton';
playlistbutton.className = ' controlbutton playlistbutton';
playlistbutton.onclick = togglePlaylist;
var playlisticon = document.createElement('div');
playlisticon.className = 'icon playlisticon';
playlistbutton.appendChild(playlisticon);
element.appendChild(playlistbutton);
var slider = document.createElement('input');
slider.type = 'range';
slider.id = 'progress';
slider.className = controlsclass + ' progress';
slider.onchange = userChangedProgress;
element.appendChild(slider);
var sliderback = document.createElement('div');
sliderback.className = 'sliderback';
element.appendChild(sliderback);
var loaded = document.createElement('div');
loaded.id = 'sliderloaded';
loaded.className = 'sliderloaded';
sliderback.appendChild(loaded);
var played = document.createElement('div');
played.id = 'sliderplayed';
played.className = 'sliderplayed';
sliderback.appendChild(played);
var soundbutton = document.createElement('div');
soundbutton.id = 'soundbutton';
soundbutton.className = controlsclass + ' controlbutton soundbutton';
soundbutton.onclick = toggleVolumeMute;
soundbutton.onmouseover = showVolume;
soundbutton.onmouseout = hideVolume;
var soundicon = document.createElement('div');
soundicon.id = 'soundicon';
soundicon.className = 'icon soundiconhigh';
soundbutton.appendChild(soundicon);
element.appendChild(soundbutton);
var fullscreen = document.createElement('div');
fullscreen.id = 'fullscreen';
fullscreen.className = controlsclass + ' controlbutton fullscreen';
fullscreen.onclick = toggleFullscreen;
var fullscreenicon = document.createElement('div');
fullscreenicon.id = 'fullscreenicon';
fullscreenicon.className = 'icon fullscreenicon';
fullscreen.appendChild(fullscreenicon);
element.appendChild(fullscreen);
var volume = document.createElement('div');
volume.id = 'volume';
volume.className = controlsclass + ' volume';
volume.style.display = 'none';
volume.onmouseover = showVolume;
volume.onmouseout = hideVolume;
var volumeslider = document.createElement('input');
volumeslider.type = 'range';
volumeslider.id = 'volumeslider';
volumeslider.className = 'volumeslider';
volumeslider.onchange = volumeChange;
volume.appendChild(volumeslider);
document.body.appendChild(volume);
volumeChange();
var duration = document.createElement('div');
duration.id = 'duration';
duration.className = 'duration';
element.appendChild(duration);
}
function playAudioFile(uri) {
if (videoPlaybackElement != null) {
videoPlaybackElement.onerror = undefined;
document.body.removeChild(videoPlaybackElement);
videoPlaybackElement = null;
}
if (audioPlaybackElement == null) {
audioPlaybackElement = document.createElement('audio');
audioPlaybackElement.className = 'playbackaudioelement';
audioPlaybackElement.autoplay = true;
audioPlaybackElement.controls = false;
setupMediaEvents(audioPlaybackElement);
audioPlaybackElement.src = uri;
setupPlaybackControls();
document.body.appendChild(audioPlaybackElement);
var paths = getPathAndFilenameForPath(uri);
$('title').textContent = decodeURI(paths[2]);
} else {
setupMediaEvents(audioPlaybackElement);
audioPlaybackElement.src = uri;
audioPlaybackElement.load();
audioPlaybackElement.play();
var paths = getPathAndFilenameForPath(uri);
$('title').textContent = decodeURI(paths[2]);
}
}
function onkeydown(event) {
const ESCAPE_KEY_CODE = 27;
const SPACE_KEY_CODE = 32;
switch (event.keyCode) {
case ESCAPE_KEY_CODE:
if (fullScreen)
toggleFullscreen();
break;
case SPACE_KEY_CODE:
playPauseButtonClick();
break;
}
}
function toggleFullscreen() {
fullScreen = !fullScreen;
var fullscreenicon = $('fullscreenicon');
if (fullScreen) {
fullscreenicon.classList.remove('fullscreenicon');
fullscreenicon.classList.add('fullscreenexiticon');
}
else {
fullscreenicon.classList.remove('fullscreenexiticon');
fullscreenicon.classList.add('fullscreenicon');
}
chrome.send('toggleFullscreen', ['']);
}
function onMetadataAvail() {
var element = getMediaElement();
var duration = element.duration;
if (duration) {
var durString = '' + Math.floor((duration / 60)) + ':' + (Math.floor(duration) % 60);
var durDiv = $('duration');
durDiv.textContent = durString;
}
}
function playVideoFile(uri) {
if (audioPlaybackElement != null) {
document.body.removeChild(audioPlaybackElement);
audioPlaybackElement = null;
}
if (videoPlaybackElement == null) {
videoPlaybackElement = document.createElement('video');
videoPlaybackElement.className = 'playbackvideoelement';
videoPlaybackElement.autoplay = true;
videoPlaybackElement.controls = false;
setupMediaEvents(videoPlaybackElement);
videoPlaybackElement.src = uri;
videoPlaybackElement.load();
var toggleButton = document.createElement('div');
toggleButton.className = 'fullscreentoggle';
toggleButton.id = 'fullscreentoggle';
toggleButton.onclick = toggleFullscreen;
document.body.appendChild(toggleButton);
setupPlaybackControls();
document.body.appendChild(videoPlaybackElement);
} else {
setupMediaEvents(videoPlaybackElement);
videoPlaybackElement.src = uri;
videoPlaybackElement.load();
videoPlaybackElement.currentTime = 0;
videoPlaybackElement.play();
}
}
function stopAllPlayback() {
var element = getMediaElement();
if (element != null) {
element.pause();
}
}
function playlistChanged(info, playlist) {
if (info.force) {
currentPlaylist = playlist;
stopAllPlayback();
if (playlist.length >= 1) {
if (info.currentOffset) {
currentItem = info.currentOffset;
} else {
currentItem = 0;
}
var item = playlist[currentItem];
chrome.send('currentOffsetChanged', ['' + currentItem]);
playMediaFile(item.path);
}
} else {
var media = getMediaElement();
currentPlaylist = playlist;
// Only need to handle the case where we are not playing
// since if it is currently playing, it will just move
// to the next file when the current is complete.
if (media == null) {
for (var x = 0; x < playlist.length; x++) {
if (playlist[x].path == info.path) {
// found the newly added item.
currentItem = x;
chrome.send('currentOffsetChanged', ['' + currentItem]);
playMediaFile(playlist[x].path);
return;
}
}
if (playlist.length > 0) {
currentItem = 0;
chrome.send('currentOffsetChanged', ['' + currentItem]);
playMediaFile(playlist[0].path);
}
}
}
}
function togglePlaylist() {
chrome.send("togglePlaylist", []);
}
function playMediaFile(url) {
$('error').textContent = '';
console.log('playfile '+url);
$('title').textContent = '';
if (pathIsVideoFile(url) ) {
playVideoFile(url);
} else if(pathIsAudioFile(url)) {
playAudioFile(url);
} else {
alert('file unknown:' + url);
}
}
</script>
<body onload='load();' onselectstart='return false'>
<div id='error' class='error'></div>
<div id='title' class='audiotitle'></div>
<div id='glow' class='glow'></div>
<div class='playercontrolsbox'>
<div id='playercontrols'>
</div>
</div>
</body>
</html>