From 4415fb4c42da8bbc3b9a677621b5ba97ac23af20 Mon Sep 17 00:00:00 2001 From: Peter Fogg Date: Thu, 6 Jun 2013 10:29:24 -0400 Subject: [PATCH 01/28] Started removing XML from video editor. TODO: This breaks the 1.5x and .75x speeds. I'm still looking into why. TODO: VideoDescriptor inherits from RawDescriptor in order to use the from_xml and export_to_xml methods. This seems really ugly, though; I'd rather find a better way to do this. --- .../features/video-editor.feature | 2 +- .../contentstore/features/video-editor.py | 14 +- .../xmodule/js/src/video/display.coffee | 11 +- common/lib/xmodule/xmodule/video_module.py | 158 ++++++++++-------- lms/templates/video.html | 12 +- 5 files changed, 116 insertions(+), 81 deletions(-) diff --git a/cms/djangoapps/contentstore/features/video-editor.feature b/cms/djangoapps/contentstore/features/video-editor.feature index 4c2a460042..9f2d44442b 100644 --- a/cms/djangoapps/contentstore/features/video-editor.feature +++ b/cms/djangoapps/contentstore/features/video-editor.feature @@ -4,7 +4,7 @@ Feature: Video Component Editor Scenario: User can view metadata Given I have created a Video component And I edit and select Settings - Then I see only the Video display name setting + Then I see the correct settings and default values Scenario: User can modify display name Given I have created a Video component diff --git a/cms/djangoapps/contentstore/features/video-editor.py b/cms/djangoapps/contentstore/features/video-editor.py index 27423575c3..124bb4f68a 100644 --- a/cms/djangoapps/contentstore/features/video-editor.py +++ b/cms/djangoapps/contentstore/features/video-editor.py @@ -4,6 +4,14 @@ from lettuce import world, step -@step('I see only the video display name setting$') -def i_see_only_the_video_display_name(step): - world.verify_all_setting_entries([['Display Name', "default", True]]) +@step('I see the correct settings and default values$') +def i_see_the_correct_settings_and_values(step): + world.verify_all_setting_entries([['.75x', 'JMD_ifUUfsU', False], + ['1.25x', 'AKqURZnYqpk', False], + ['1.5x', 'DYpADpL7jAY', False], + ['Display Name', "default", True], + ['External Source', '', False], + ['External Track', '', False], + ['Normal Speed', 'OEoXaMPEzfM', False], + ['Show Captions', 'True', False], + ]) diff --git a/common/lib/xmodule/xmodule/js/src/video/display.coffee b/common/lib/xmodule/xmodule/js/src/video/display.coffee index aadafbc8d0..79460a4e24 100644 --- a/common/lib/xmodule/xmodule/js/src/video/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/video/display.coffee @@ -8,7 +8,7 @@ class @Video @show_captions = @el.data('show-captions') == "true" window.player = null @el = $("#video_#{@id}") - @parseVideos @el.data('streams') + @parseVideos() @fetchMetadata() @parseSpeed() $("#video_#{@id}").data('video', this).addClass('video-load-complete') @@ -27,10 +27,11 @@ class @Video parseVideos: (videos) -> @videos = {} - $.each videos.split(/,/), (index, video) => - video = video.split(/:/) - speed = parseFloat(video[0]).toFixed(2).replace /\.00$/, '.0' - @videos[speed] = video[1] + @videos['.75'] = @el.data('youtube-id-0-75') + @videos['1.0'] = @el.data('normal-speed-video-id') + @videos['1.25'] = @el.data('youtube-id-1-25') + @videos['1.5'] = @el.data('youtube-id-1-5') + alert @videos['1.5'] parseSpeed: -> @setSpeed($.cookie('video_speed')) diff --git a/common/lib/xmodule/xmodule/video_module.py b/common/lib/xmodule/xmodule/video_module.py index f902a9665b..5b3913160f 100644 --- a/common/lib/xmodule/xmodule/video_module.py +++ b/common/lib/xmodule/xmodule/video_module.py @@ -8,18 +8,25 @@ from django.http import Http404 from xmodule.x_module import XModule from xmodule.raw_module import RawDescriptor -from xmodule.contentstore.content import StaticContent -from xblock.core import Integer, Scope, String - -import datetime -import time +from xmodule.editing_module import MetadataOnlyEditingDescriptor +from xblock.core import Integer, Scope, String, Boolean, Float log = logging.getLogger(__name__) +YOUTUBE_SPEEDS = ['.75', '1.0', '1.25', '1.5'] + class VideoFields(object): - data = String(help="XML data for the problem", scope=Scope.content) position = Integer(help="Current position in the video", scope=Scope.user_state, default=0) + show_captions = Boolean(help="Whether or not captions are shown", display_name="Show Captions", scope=Scope.settings, default=True) + youtube_id_1_0 = String(help="Youtube ID for normal speed video", display_name="Normal Speed", scope=Scope.settings, default="OEoXaMPEzfM") + youtube_id_0_75 = String(help="Youtube ID for .75x speed video", display_name=".75x", scope=Scope.settings, default="JMD_ifUUfsU") + youtube_id_1_25 = String(help="Youtube ID for 1.25x speed video", display_name="1.25x", scope=Scope.settings, default="AKqURZnYqpk") + youtube_id_1_5 = String(help="Youtube ID for 1.5x speed video", display_name="1.5x", scope=Scope.settings, default="DYpADpL7jAY") + start_time = Float(help="Time the video starts", display_name="Start Time", scope=Scope.settings, default=0.0) + end_time = Float(help="Time the video ends", display_name="End Time", scope=Scope.settings, default=0.0) + source = String(help="External source to download video", display_name="External Source", scope=Scope.settings, default="") + track = String(help="External source to download subtitle strack", display_name="External Track", scope=Scope.settings, default="") class VideoModule(VideoFields, XModule): @@ -39,52 +46,6 @@ class VideoModule(VideoFields, XModule): def __init__(self, *args, **kwargs): XModule.__init__(self, *args, **kwargs) - xmltree = etree.fromstring(self.data) - self.youtube = xmltree.get('youtube') - self.show_captions = xmltree.get('show_captions', 'true') - self.source = self._get_source(xmltree) - self.track = self._get_track(xmltree) - self.start_time, self.end_time = self._get_timeframe(xmltree) - - def _get_source(self, xmltree): - # find the first valid source - return self._get_first_external(xmltree, 'source') - - def _get_track(self, xmltree): - # find the first valid track - return self._get_first_external(xmltree, 'track') - - def _get_first_external(self, xmltree, tag): - """ - Will return the first valid element - of the given tag. - 'valid' means has a non-empty 'src' attribute - """ - result = None - for element in xmltree.findall(tag): - src = element.get('src') - if src: - result = src - break - return result - - def _get_timeframe(self, xmltree): - """ Converts 'from' and 'to' parameters in video tag to seconds. - If there are no parameters, returns empty string. """ - - def parse_time(s): - """Converts s in '12:34:45' format to seconds. If s is - None, returns empty string""" - if s is None: - return '' - else: - x = time.strptime(s, '%H:%M:%S') - return datetime.timedelta(hours=x.tm_hour, - minutes=x.tm_min, - seconds=x.tm_sec).total_seconds() - - return parse_time(xmltree.get('from')), parse_time(xmltree.get('to')) - def handle_ajax(self, dispatch, get): ''' Handle ajax calls to this video. @@ -113,37 +74,92 @@ class VideoModule(VideoFields, XModule): #log.debug(u"STATE POSITION {0}".format(self.position)) return json.dumps({'position': self.position}) - def video_list(self): - return self.youtube - def get_html(self): - # We normally let JS parse this, but in the case that we need a hacked - # out player because YouTube has broken their