/*****************************************************
*
* Copyright 2010 Adobe Systems Incorporated. All Rights Reserved.
*
*****************************************************
* The contents of this file are subject to the Berkeley Software Distribution (BSD) Licence
* (the "License"); you may not use this file except in
* compliance with the License.
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
*
* The Initial Developer of the Original Code is Adobe Systems Incorporated.
* Portions created by Adobe Systems Incorporated are Copyright (C) 2010 Adobe Systems
* Incorporated. All Rights Reserved.
*
*****************************************************/
/**
*
*/
(function($, undefined){
/**
*
*/
var StrobeMediaPlaybackChrome = function(element, options){
this.$window = $(window);
this.$document = $(document);
this.element = element;
this.$element = $(element);
this.options = $.extend({}, $.fn.strobemediaplaybackchrome.defaults, options);
};
var strobeMediaPlaybackChromeMethods = {
initialize: function(){
if (!this.options.javascriptControls) {
this.$element.find(".strobeMediaPlaybackControlBar,.smp-error,.playoverlay").hide();
return;
}
this.$player = this.$element; //$("#" + this.options.id)
this.player = this.element; //this.$player.get(0);
//409 // TODO: Encapsulate this in a dedicated class
//410 if (!this.options.useHTML5) {
//411
//412 this.monitor = new VideoElementMonitor(this.$player);
//413 this.$player.data("videoElement", this.monitor.$videoElement);
//414 this.player = this.monitor.videoElement;
//415 this.$player = this.monitor.$videoElement;
//416 org.strobemediaplayback.proxied[this.options.id] = this.monitor;
//417 monitorChanges(this.monitor);
//418 }
this.sliding = false;
this.$element = $("#strobemediaplayback");
this.playOverlay = this.$element.find('.playoverlay');
this.play = this.$element.find('.smp.play');
this.mute = this.$element.find('.smp.volume');
this.time = this.$element.find('.time');
this.currentTimeLabel = this.$element.find('.currentTime');
this.durationLabel = this.$element.find('.duration');
this.errorOverlay = this.$element.find('.smp-error');
this.fullscreen = this.$element.find('.fullscreen');
this.play.bind('click', this, this.onPlayClick);
this.playOverlay.bind('click', this, this.onPlayClick);
this.mute.bind('click', this, this.onMuteClick);
this.fullscreen.bind('click', this, this.onFullScreenClick);
this.$player.bind("play", this, this.onPlay);
this.$player.bind("pause", this, this.onPause);
this.$player.bind("volumechange", this, this.onVolumeChange);
this.$player.bind("durationchange", this, this.onDurationChange);
this.$player.bind("timeupdate", this, this.onTimeUpdate);
this.$player.bind("waiting", this, this.onWaiting);
this.$player.bind("seeking", this, this.onSeeking);
this.$player.bind("seeked", this, this.onSeeked);
this.$player.bind("ended", this, this.onPause);
this.$player.bind("error", this, this.onError);
this.$player.bind("progress", this, this.onProgress);
this.timeTrack = this.$element.find(".video-track");
this.slider = this.$element.find(".slider");
this.played = this.$element.find(".played");
this.buffered = this.$element.find(".buffered");
this.slider.bind("mousedown", this, this.onSliderMouseDown);
this.slider.bind("touchstart", this, this.onSliderMouseDown);
// Keep here for further experimentation
//this.slider.bind("touchmove", this, this.onTouchMove);
this.timeTrack.bind('mousedown', this, this.onTimeTrackClick);
this.$window.bind("orientationchange", this, this.onOrinetationChangeOrResize);
this.$window.bind("resize", this, this.onOrinetationChangeOrResize);
if (options.disabledControls) {
this.$element.find(options.disabledControls).addClass("disabled");
}
this.isFullScreen = false;
this.layoutControlBar(this.options.width, this.options.height);
},
onSliderMouseDown: function(event){
var duration, time, player;
if (!event.data.sliding) {
event.preventDefault();
// TODO: Move the sliding code into a special widget
player = event.data.player;
event.data.sliding = true;
duration = player.duration;
event.data.onProgress(event);
var timeTrack = event.data.timeTrack;
var slider = event.data.slider;
var moveTarget = event.data.$document;
moveTarget.bind("mousemove", event.data, onMouseMove);
moveTarget.bind("touchmove", event.data, onMouseMove);
moveTarget.bind("mouseup", event.data, onMouseUp);
moveTarget.bind("touchend", event.data, onMouseUp);
moveTarget.bind("touchcancel", event.data, onTouchCancel);
}
function onMouseMove(event){
event.preventDefault();
var timeTrackWidth = event.data.timeTrack.outerWidth();
var offsetLeft = event.data.timeTrack.offset().left;
var x = event.clientX;
var originalEvent = event.originalEvent;
if (typeof x == 'undefined' && originalEvent && originalEvent.touches && originalEvent.touches.length > 0) {
x = originalEvent.touches[0].pageX;
}
var relativePosition = (x - offsetLeft) / (timeTrackWidth);
time = duration * relativePosition;
if (time < duration && time > 0) {
var timePercent = (Math.max(0, time) / duration * 100);
event.data.slider.css({
"left": timePercent + "%"
});
event.data.played.css({
"width": timePercent + "%"
});
event.data.seekTime = time;
event.data.onProgress(event);
}
};
function onMouseUp(event){
moveTarget.unbind("mousemove");
moveTarget.unbind("touchmove");
moveTarget.unbind("mouseup");
moveTarget.unbind("touchend");
if (time > 0) {
event.data.seekTime = 0;
player.currentTime = time;
}
event.data.sliding = false;
};
function onTouchCancel(event){
event.data.seekTime = 0;
event.data.sliding = false;
};
},
onOrinetationChangeOrResize: function(event){
event.data.layoutControlBar(event.data.options.width, event.data.options.height);
},
onPlayClick: function(event){
var player = event.data.player;
if (player.paused) {
player.play();
}
else {
player.pause();
}
},
onMuteClick: function(event){
var player = event.data.player;
player.muted = !player.muted;
},
onFullScreenClick: function(event){
event.data.$element.parent().toggleClass("fullscreen-mode");
},
onTimeTrackClick: function(event){
var duration = event.data.player.duration;
var timeTrackWidth = event.data.timeTrack.outerWidth();
var offsetLeft = event.data.timeTrack.offset().left;
var relativePosition = (event.clientX - offsetLeft) / (timeTrackWidth);
var time = duration * relativePosition;
if (time > 0) {
event.data.player.currentTime = time;
}
$("#seekDebug").html("clientX=" + event.clientX + " width=" + timeTrackWidth + " duration=" + duration + " time=" + time);
},
onPlay: function(event){
event.data.errorOverlay.hide();
event.data.play.removeClass("play").addClass("pause");
if (event.data.useHTML5 &&
event.data.options.hasOwnProperty("playButtonOverlay") &&
event.data.options.playButtonOverlay) {
event.data.playOverlay.fadeOut(600);
}
},
onPause: function(event){
event.data.play.removeClass("pause").addClass("play");
if (event.data.useHTML5 && event.data.options.playButtonOverlay) {
event.data.playOverlay.fadeIn(600);
}
},
onWaiting: function(event){
// $("#debug").append("BUFFERING");
event.data.buffered.css({
"width": 0
});
},
onError: function(event){
//$("#debug").append("ERROR" + event.data.player.error.code);
if (event.data.useHTML5) {
var message;
switch (event.target.error.code) {
case event.target.error.MEDIA_ERR_ABORTED:
message = 'You aborted the video playback.';
break;
case event.target.error.MEDIA_ERR_NETWORK:
message = 'A network error caused the video download to fail part-way.';
break;
case event.target.error.MEDIA_ERR_DECODE:
message = 'The video playback was aborted due to a corruption problem or because the video used features your browser did not support.';
break;
case event.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
message = 'The video could not be loaded, either because the server or network failed or because the format is not supported.';
break;
default:
message = 'An unknown error occurred.';
break;
}
//$("#debug").append(message);
event.data.errorOverlay.html(message);
event.data.errorOverlay.show();
}
},
onSeeking: function(event){
// $("#debug").append("SEEKING");
},
onSeeked: function(event){
event.data.onProgress(event);
},
onVolumeChange: function(event){
if (event.data.player.muted) {
event.data.mute.addClass("mute");
}
else {
event.data.mute.removeClass("mute");
}
},
onDurationChange: function(event){
var duration = event.data.player.duration;
var currentTime = event.data.player.currentTime;
var timeDuration = formatTimeStatus(currentTime, duration);
event.data.currentTimeLabel.html(timeDuration[0]);
event.data.durationLabel.html(timeDuration[1]);
},
onTimeUpdate: function(event){
if (event.data.sliding) {
return;
}
var duration = event.data.player.duration;
var currentTime = event.data.player.currentTime;
var timeDuration = formatTimeStatus(currentTime, duration);
event.data.currentTimeLabel.html(timeDuration[0]);
event.data.durationLabel.html(timeDuration[1]);
var timePercent = (Math.max(0, currentTime) / duration * 100);
event.data.slider.css({
"left": timePercent + "%"
});
event.data.played.css({
"width": timePercent + "%"
});
event.data.onProgress(event);
},
onProgress: function(event){
var bufferedPercent = 0;
if (!event.data.player.seeking) {
var buffered = event.data.player.buffered;
var time = event.data.seekTime || Math.max(0, event.data.player.currentTime);
//$("#debug").append(buffered.length + "-" + buffered.end(buffered.length - 1));
var timePercent = time / event.data.player.duration * 100;
if (buffered) {
var lastBuffered = buffered.end(buffered.length - 1);
bufferedPercent = (lastBuffered / event.data.player.duration) * 100;
bufferedPercent -= timePercent;
//$("#debug").append(bufferedPercent);
}
if (timePercent + bufferedPercent > 100) {
bufferedPercent = 100 - timePercent;
}
}
var css = {
"left": timePercent + "%",
"width": bufferedPercent + "%"
}
if (bufferedPercent + timePercent > 99) {
event.data.buffered.addClass("done")
}
else {
event.data.buffered.removeClass("done")
}
event.data.buffered.css(css);
},
layoutControlBar: function(newWidth, newHeight){
if (this.useHTML5 && this.options.playButtonOverlay) {
this.playOverlay.fadeIn(600);
this.playOverlay.css({
"left": (newWidth / 2 - this.playOverlay.width() / 2) + "px",
"top": (newHeight / 2 - this.playOverlay.height() / 2) + "px"
});
}
$('.video-progress2').css({
"width": (newWidth - 200) + "px"
});
//$('.strobeMediaPlaybackControlBar').fadeIn(600);
$('.strobeMediaPlaybackControlBar').css({
"width": newWidth - 6 + "px"
});
}
}
StrobeMediaPlaybackChrome.prototype = strobeMediaPlaybackChromeMethods;
/**
* jQuery plugin hook
*/
$.fn.strobemediaplaybackchrome = function(options){
var instances = [], i;
var result = this.each(function(){
instances.push(new StrobeMediaPlaybackChrome(this, options));
});
for (i = 0; i < instances.length; i++) {
instances[i].initialize();
}
return result;
};
/**
* jQuery plugin defaults
*/
$.fn.strobemediaplaybackchrome.defaults = {
javascriptControls: false
};
// Internals, private functions
function onMouseMove(event){
showControlBar();
}
function formatTimeStatus(currentPosition, totalDuration){
var h;
var m;
var s;
function prettyPrintSeconds(seconds, leadingMinutes, leadingHours){
seconds = Math.floor(isNaN(seconds) ? 0 : Math.max(0, seconds));
h = Math.floor(seconds / 3600);
m = Math.floor(seconds % 3600 / 60);
s = seconds % 60;
return ((h > 0 || leadingHours) ? (h + ":") : "") +
(((h > 0 || leadingMinutes) && m < 10) ? "0" : "") +
m +
":" +
(s < 10 ? "0" : "") +
s;
}
var totalDurationString = prettyPrintSeconds(totalDuration);
var currentPositionString = prettyPrintSeconds(currentPosition, h > 0 || m > 9, h > 0);
return [currentPositionString, totalDurationString];
}
})(jQuery);