Commit 78e9692a by Valera Rozuvan

Adding HTML5Video class and modifying coffee sources to use it when video…

Adding HTML5Video class and modifying coffee sources to use it when video sources are provided instead of YouTube IDs.
parent 156da20c
*.js # Please do not ignore *.js files. Some xmodules are written in JS.
class @Video class @VideoAlpha
constructor: (element) -> constructor: (element) ->
@el = $(element).find('.video') @el = $(element).find('.video')
@id = @el.attr('id').replace(/video_/, '') @id = @el.attr('id').replace(/video_/, '')
...@@ -9,40 +9,77 @@ class @Video ...@@ -9,40 +9,77 @@ class @Video
@show_captions = @el.data('show-captions') == "true" @show_captions = @el.data('show-captions') == "true"
window.player = null window.player = null
@el = $("#video_#{@id}") @el = $("#video_#{@id}")
@parseVideos @el.data('streams')
if @parseVideos(@el.data("streams")) is true
@videoType = "youtube"
@fetchMetadata() @fetchMetadata()
@parseSpeed() @parseSpeed()
else
@videoType = "html5"
@parseVideoSources @el.data("mp4-source"), @el.data("webm-source"), @el.data("ogg-source")
@speeds = ["0.75", "1.0", "1.25", "1.5"]
@setSpeed($.cookie('video_speed'))
$("#video_#{@id}").data('video', this).addClass('video-load-complete') $("#video_#{@id}").data('video', this).addClass('video-load-complete')
@hide_captions = $.cookie('hide_captions') == 'true' @hide_captions = $.cookie('hide_captions') == 'true'
if YT.Player if ((@videoType is "youtube") and (YT.Player)) or ((@videoType is "html5") and (HTML5Video.Player))
console.log 'one'
@embed() @embed()
else else
window.onYouTubePlayerAPIReady = => console.log 'two'
@el.each -> if @videoType is "youtube"
$(this).data('video').embed() console.log 'three'
window.onYouTubePlayerAPIReady = ->
_this.embed()
else if @videoType is "html5"
console.log 'four'
console.log @videoType
console.log HTML5Video.Player
window.onHTML5PlayerAPIReady = ->
_this.embed()
youtubeId: (speed)-> youtubeId: (speed)->
@videos[speed || @speed] @videos[speed || @speed]
parseVideos: (videos) -> VideoAlpha::parseVideos = (videos) ->
return false if (typeof videos isnt "string") or (videos.length is 0)
console.log 'We got this far'
console.log videos
@videos = {} @videos = {}
$.each videos.split(/,/), (index, video) => _this = this
$.each videos.split(/,/), (index, video) ->
speed = undefined
video = video.split(/:/) video = video.split(/:/)
speed = parseFloat(video[0]).toFixed(2).replace /\.00$/, '.0' speed = parseFloat(video[0]).toFixed(2).replace(/\.00$/, ".0")
@videos[speed] = video[1] _this.videos[speed] = video[1]
true
VideoAlpha::parseVideoSources = (mp4Source, webmSource, oggSource) ->
@html5Sources =
mp4: null
webm: null
ogg: null
@html5Sources.mp4 = mp4Source if (typeof mp4Source is "string") and (mp4Source.length > 0)
@html5Sources.webm = webmSource if (typeof webmSource is "string") and (webmSource.length > 0)
@html5Sources.ogg = oggSource if (typeof oggSource is "string") and (oggSource.length > 0)
parseSpeed: -> parseSpeed: ->
@setSpeed($.cookie('video_speed'))
@speeds = ($.map @videos, (url, speed) -> speed).sort() @speeds = ($.map @videos, (url, speed) -> speed).sort()
@setSpeed($.cookie('video_speed'))
setSpeed: (newSpeed) -> VideoAlpha::setSpeed = (newSpeed) ->
if @videos[newSpeed] != undefined if @speeds.indexOf(newSpeed) isnt -1
@speed = newSpeed @speed = newSpeed
$.cookie('video_speed', "#{newSpeed}", expires: 3650, path: '/') $.cookie "video_speed", "" + newSpeed,
expires: 3650
path: "/"
else else
@speed = '1.0' @speed = "1.0"
embed: -> embed: ->
@player = new VideoPlayer video: this @player = new VideoPlayer video: this
...@@ -55,9 +92,14 @@ class @Video ...@@ -55,9 +92,14 @@ class @Video
getDuration: -> getDuration: ->
@metadata[@youtubeId()].duration @metadata[@youtubeId()].duration
log: (eventName) -> VideoAlpha::log = (eventName) ->
Logger.log eventName, logInfo =
id: @id id: @id
code: @youtubeId() code: @youtubeId()
currentTime: @player.currentTime currentTime: @player.currentTime
speed: @speed speed: @speed
if @videoType is "youtube"
logInfo.code = @youtubeId()
else logInfo.code = "html5" if @videoType is "html5"
Logger.log eventName, logInfo
console.log('We are in "html5_video.js" script.');
this.HTML5Video = (function () {
var HTML5Video = {};
HTML5Video.Player = (function () {
/*
* Constructor function for HTML5 Video player.
*
* @el - A DOM element where the HTML5 player will be inserted (as returned by jQuery(selector) function),
* or a selector string which will be used to select an element. This is a required parameter.
*
* @config - An object whose properties will be used as configuration options for the HTML5 video
* player. This is an optional parameter. In the case if this parameter is missing, or some of the config
* object's properties are missing, defaults will be used. The available options (and their defaults) are as
* follows:
*
* config = {
* 'width': 640,
*
* 'height': 390,
*
* 'videoSources': null, // An object of with properties being video sources. The property name is the
* // video format of the source. Supported video formats are: 'mp4', 'webm', and
* // 'ogg'. By default videoSources property is null. This means that the
* // player will initialize, and not play anything. If you do not provide a
* // 'videoSource' option, you can later call loadVideoBySource() method to load
* // a video and start playing it.
*
* 'playerVars': { // Object's properties identify player parameters.
*
* 'controls': 1, // Possible values: 0, or 1. Value of 1 will enable the default browser video
* // controls.
*
* 'start': null, // Possible values: positive integer. Position from which to start playing the
* // video. Measured in seconds. If value is null, or 'start' property is not
* // specified, the video will start playing from the beginning.
*
* 'end': null // Possible values: positive integer. Position when to stop playing the
* // video. Measured in seconds. If value is null, or 'end' property is not
* // specified, the video will end playing at the end.
*
* },
*
* 'events': { // Object's properties identify the events that the API fires, and the
* // functions (event listeners) that the API will call when those events occur.
* // If value is null, or property is not specified, then no callback will be
* // called for that event.
*
* 'onReady': null,
* 'onStateChange': null,
* 'onPlaybackQualityChange': null
* }
* }
*/
function Player(el, config) {
console.log('We are inside HTML5Video.Player constructor.');
if (typeof el === 'string') {
this.el = $(el);
} else if ($.isPlainObject(el) === true) {
this.el = el;
} else {
// Error. el parameter is required.
// TODO: Make sure that nothing breaks if one of the methods available via this object's prototype
// is called after we return.
return;
}
console.log('We got a proper DOM element.');
if ($.isPlainObject(config) === true) {
this.config = config;
} else {
this.config = {
'width': 640,
'height': 390,
'videoSource': '',
'playerVars': {
'controls': 1,
'start': null,
'end': null
},
'events': {
'onReady': null,
'onStateChange': null,
'onPlaybackQualityChange': null
}
};
}
console.log('The config is:');
console.log(this.config);
}
/*
* This function returns the quality of the video. Possible return values are (type String)
*
* highres
* hd1080
* hd720
* large
* medium
* small
*
* It returns undefined if there is no current video.
*
* If there is a current video, but it is impossible to determine it's quality, the function will return
* 'medium'.
*/
Player.prototype.getPlayBackQuality = function () {
if (this.config.videoSource === '') {
return undefined;
}
// TODO: Figure out if we can get the quality of a video from a source (when it is loaded by the browser).
return 'medium';
};
/*
* The original YouTube API function player.setPlayBackQuality changed (if it was possible) the quality of the
* played video. In our case, this function will not do anything because we can't change the quality of HTML5
* video since we only get one source of video with one quality.
*/
Player.prototype.setPlayBackQuality = function (value) {
};
Player.prototype.pauseVideo = function () {
};
Player.prototype.sekkTo = function () {
};
// YouTube API has player.loadVideoById, but since we are working with a video source, we will rename this
// function accordingly.
Player.prototype.loadVideoBySource = function () {
};
// YouTube API has player.cueVideoById, but since we are working with a video source, we will rename this
// function accordingly.
Player.prototype.cueVideoBySource = function () {
};
Player.prototype.setVolume = function () {
};
Player.prototype.getCurrentTime = function () {
};
Player.prototype.playVideo = function () {
};
Player.prototype.getPlayerState = function () {
};
Player.prototype.pauseVideo = function () {
};
Player.prototype.setVolume = function () {
};
Player.prototype.getVolume = function () {
};
return Player;
}());
HTML5Video.PlayerState = {
'UNSTARTED': -1,
'ENDED': 0,
'PLAYING': 1,
'PAUSED': 2,
'BUFFERING': 3,
'CUED': 5
};
return HTML5Video;
}());
console.log(HTML5Video);
class @VideoPlayer extends Subview class @VideoPlayer extends Subview
initialize: -> initialize: ->
if @video.videoType is 'youtube'
# Define a missing constant of Youtube API # Define a missing constant of Youtube API
YT.PlayerState.UNSTARTED = -1 YT.PlayerState.UNSTARTED = -1
...@@ -25,6 +26,7 @@ class @VideoPlayer extends Subview ...@@ -25,6 +26,7 @@ class @VideoPlayer extends Subview
@toggleFullScreen(event) @toggleFullScreen(event)
render: -> render: ->
console.log '1.1'
@control = new VideoControl el: @$('.video-controls') @control = new VideoControl el: @$('.video-controls')
@qualityControl = new VideoQualityControl el: @$('.secondary-controls') @qualityControl = new VideoQualityControl el: @$('.secondary-controls')
@caption = new VideoCaption @caption = new VideoCaption
...@@ -34,6 +36,7 @@ class @VideoPlayer extends Subview ...@@ -34,6 +36,7 @@ class @VideoPlayer extends Subview
captionAssetPath: @video.caption_asset_path captionAssetPath: @video.caption_asset_path
unless onTouchBasedDevice() unless onTouchBasedDevice()
@volumeControl = new VideoVolumeControl el: @$('.secondary-controls') @volumeControl = new VideoVolumeControl el: @$('.secondary-controls')
console.log '1.2'
@speedControl = new VideoSpeedControl el: @$('.secondary-controls'), speeds: @video.speeds, currentSpeed: @currentSpeed() @speedControl = new VideoSpeedControl el: @$('.secondary-controls'), speeds: @video.speeds, currentSpeed: @currentSpeed()
@progressSlider = new VideoProgressSlider el: @$('.slider') @progressSlider = new VideoProgressSlider el: @$('.slider')
@playerVars = @playerVars =
...@@ -43,13 +46,24 @@ class @VideoPlayer extends Subview ...@@ -43,13 +46,24 @@ class @VideoPlayer extends Subview
showinfo: 0 showinfo: 0
enablejsapi: 1 enablejsapi: 1
modestbranding: 1 modestbranding: 1
console.log '1.3'
if @video.start if @video.start
@playerVars.start = @video.start @playerVars.start = @video.start
@playerVars.wmode = 'window' @playerVars.wmode = 'window'
if @video.end if @video.end
# work in AS3, not HMLT5. but iframe use AS3 # work in AS3, not HMLT5. but iframe use AS3
@playerVars.end = @video.end @playerVars.end = @video.end
console.log '1.4'
if @video.videoType is 'html5'
@player = new HTML5Video.Player @video.id,
playerVars: @playerVars,
videoSources: @video.html5Sources,
events:
onReady: @onReady
onStateChange: @onStateChange
onPlaybackQualityChange: @onPlaybackQualityChange
else if @video.videoType is 'youtube'
@player = new YT.Player @video.id, @player = new YT.Player @video.id,
playerVars: @playerVars playerVars: @playerVars
videoId: @video.youtubeId() videoId: @video.youtubeId()
......
...@@ -19,11 +19,13 @@ import time ...@@ -19,11 +19,13 @@ import time
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class VideoModule(XModule): class VideoAlphaModule(XModule):
video_time = 0 video_time = 0
icon_class = 'video' icon_class = 'video'
js = {'coffee': js = {
'js': [resource_string(__name__, 'js/src/videoalpha/display/html5_video.js')],
'coffee':
[resource_string(__name__, 'js/src/time.coffee'), [resource_string(__name__, 'js/src/time.coffee'),
resource_string(__name__, 'js/src/videoalpha/display.coffee')] + resource_string(__name__, 'js/src/videoalpha/display.coffee')] +
[resource_string(__name__, 'js/src/videoalpha/display/' + filename) [resource_string(__name__, 'js/src/videoalpha/display/' + filename)
...@@ -31,7 +33,7 @@ class VideoModule(XModule): ...@@ -31,7 +33,7 @@ class VideoModule(XModule):
in sorted(resource_listdir(__name__, 'js/src/videoalpha/display')) in sorted(resource_listdir(__name__, 'js/src/videoalpha/display'))
if filename.endswith('.coffee')]} if filename.endswith('.coffee')]}
css = {'scss': [resource_string(__name__, 'css/videoalpha/display.scss')]} css = {'scss': [resource_string(__name__, 'css/videoalpha/display.scss')]}
js_module_name = "Video" js_module_name = "VideoAlpha"
def __init__(self, system, location, definition, descriptor, def __init__(self, system, location, definition, descriptor,
instance_state=None, shared_state=None, **kwargs): instance_state=None, shared_state=None, **kwargs):
...@@ -145,6 +147,6 @@ class VideoModule(XModule): ...@@ -145,6 +147,6 @@ class VideoModule(XModule):
class VideoAlphaDescriptor(RawDescriptor): class VideoAlphaDescriptor(RawDescriptor):
module_class = VideoModule module_class = VideoAlphaModule
stores_state = True stores_state = True
template_dir_name = "videoalpha" template_dir_name = "videoalpha"
...@@ -2,11 +2,24 @@ ...@@ -2,11 +2,24 @@
<h2> ${display_name} </h2> <h2> ${display_name} </h2>
% endif % endif
<!-- data-streams="0.75:WL7anegEjsU,1.0:NUmLa2vBBLo,1.25:TygItMr4wY4,1.5:kctQ6liQdAE"-->
%if settings.MITX_FEATURES['STUB_VIDEO_FOR_TESTING']: %if settings.MITX_FEATURES['STUB_VIDEO_FOR_TESTING']:
<div id="stub_out_video_for_testing"></div> <div id="stub_out_video_for_testing"></div>
%else: %else:
<div id="video_${id}" class="video" data-streams="${streams}" data-caption-data-dir="${data_dir}" data-show-captions="${show_captions}" data-start="${start}" data-end="${end}" data-caption-asset-path="${caption_asset_path}"> <div
id="video_${id}"
class="video"
data-streams=""
data-mp4-source="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4"
data-webm-source="http://clips.vorwaerts-gmbh.de/VfE_html5.webm"
data-ogg-source="http://clips.vorwaerts-gmbh.de/VfE_html5.ogv"
data-caption-data-dir="${data_dir}"
data-show-captions="${show_captions}"
data-start="${start}"
data-end="${end}"
data-caption-asset-path="${caption_asset_path}"
>
<div class="tc-wrapper"> <div class="tc-wrapper">
<article class="video-wrapper"> <article class="video-wrapper">
<section class="video-player"> <section class="video-player">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment