← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~trb143/openlp/background_videos into lp:openlp

 

Tim Bentley has proposed merging lp:~trb143/openlp/background_videos into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~trb143/openlp/background_videos/+merge/293468

Allow themes to have video files so allow for background videos behind text.

lp:~trb143/openlp/background_videos (revision 2689)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/1518/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/1429/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1367/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/1163/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Windows_Interface_Tests/754/
[SUCCESS] https://ci.openlp.io/job/Branch-05a-Code_Analysis/821/
[SUCCESS] https://ci.openlp.io/job/Branch-05b-Test_Coverage/689/

-- 
Your team OpenLP Core is requested to review the proposed merge of lp:~trb143/openlp/background_videos into lp:openlp.
=== modified file 'openlp/core/common/uistrings.py'
--- openlp/core/common/uistrings.py	2016-04-16 19:51:35 +0000
+++ openlp/core/common/uistrings.py	2016-04-30 17:16:06 +0000
@@ -152,3 +152,4 @@
         self.Version = translate('OpenLP.Ui', 'Version')
         self.View = translate('OpenLP.Ui', 'View')
         self.ViewMode = translate('OpenLP.Ui', 'View Mode')
+        self.Video = translate('OpenLP.Ui', 'Video')

=== modified file 'openlp/core/lib/theme.py'
--- openlp/core/lib/theme.py	2015-12-31 22:46:06 +0000
+++ openlp/core/lib/theme.py	2016-04-30 17:16:06 +0000
@@ -44,6 +44,7 @@
     Gradient = 1
     Image = 2
     Transparent = 3
+    Video = 4
 
     @staticmethod
     def to_string(background_type):
@@ -58,6 +59,8 @@
             return 'image'
         elif background_type == BackgroundType.Transparent:
             return 'transparent'
+        elif background_type == BackgroundType.Video:
+            return 'video'
 
     @staticmethod
     def from_string(type_string):
@@ -72,6 +75,8 @@
             return BackgroundType.Image
         elif type_string == 'transparent':
             return BackgroundType.Transparent
+        elif type_string == 'video':
+            return BackgroundType.Video
 
 
 class BackgroundGradientType(object):
@@ -184,7 +189,7 @@
 
         :param path: The path name to be added.
         """
-        if self.background_type == 'image':
+        if self.background_type == 'image' or self.background_type == 'video':
             if self.background_filename and path:
                 self.theme_name = self.theme_name.strip()
                 self.background_filename = self.background_filename.strip()
@@ -255,6 +260,21 @@
         # Create endColor element
         self.child_element(background, 'borderColor', str(border_color))
 
+    def add_background_video(self, filename, border_color):
+        """
+        Add a video background.
+
+        :param filename: The file name of the video.
+        :param border_color:
+        """
+        background = self.theme_xml.createElement('background')
+        background.setAttribute('type', 'video')
+        self.theme.appendChild(background)
+        # Create Filename element
+        self.child_element(background, 'filename', filename)
+        # Create endColor element
+        self.child_element(background, 'borderColor', str(border_color))
+
     def add_font(self, name, color, size, override, fonttype='main', bold='False', italics='False',
                  line_adjustment=0, xpos=0, ypos=0, width=0, height=0, outline='False', outline_color='#ffffff',
                  outline_pixel=2, shadow='False', shadow_color='#ffffff', shadow_pixel=5):
@@ -512,6 +532,9 @@
         elif self.background_type == BackgroundType.to_string(BackgroundType.Image):
             filename = os.path.split(self.background_filename)[1]
             self.add_background_image(filename, self.background_border_color)
+        elif self.background_type == BackgroundType.to_string(BackgroundType.Video):
+            filename = os.path.split(self.background_filename)[1]
+            self.add_background_video(filename, self.background_border_color)
         elif self.background_type == BackgroundType.to_string(BackgroundType.Transparent):
             self.add_background_transparent()
         self.add_font(

=== modified file 'openlp/core/ui/maindisplay.py'
--- openlp/core/ui/maindisplay.py	2016-04-01 02:32:36 +0000
+++ openlp/core/ui/maindisplay.py	2016-04-30 17:16:06 +0000
@@ -31,13 +31,15 @@
 
 import html
 import logging
+import os
 
 from PyQt5 import QtCore, QtWidgets, QtWebKit, QtWebKitWidgets, QtOpenGL, QtGui, QtMultimedia
 
-from openlp.core.common import Registry, RegistryProperties, OpenLPMixin, Settings, translate, is_macosx, is_win
+from openlp.core.common import AppLocation, Registry, RegistryProperties, OpenLPMixin, Settings, translate,\
+    is_macosx, is_win
 from openlp.core.lib import ServiceItem, ImageSource, ScreenList, build_html, expand_tags, image_to_byte
 from openlp.core.lib.theme import BackgroundType
-from openlp.core.ui import HideMode, AlertLocation
+from openlp.core.ui import HideMode, AlertLocation, DisplayControllerType
 
 if is_macosx():
     from ctypes import pythonapi, c_void_p, c_char_p, py_object
@@ -437,6 +439,7 @@
 
         :param service_item: The Service item to be used
         :param image_path: Where the image resides.
+        :param is_love: Are we the live controller assume not.
         """
         self.web_loaded = False
         self.initial_fame = None
@@ -457,13 +460,13 @@
                 background = self.image_manager.get_image_bytes(self.override['image'], ImageSource.ImagePlugin)
         self.set_transparency(self.service_item.theme_data.background_type ==
                               BackgroundType.to_string(BackgroundType.Transparent))
-        if self.service_item.theme_data.background_filename:
-            self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(
-                self.service_item.theme_data.background_filename, ImageSource.Theme)
-        if image_path:
-            image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin)
-        else:
-            image_bytes = None
+        image_bytes = None
+        if self.service_item.theme_data.background_type == 'image':
+            if self.service_item.theme_data.background_filename:
+                self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(
+                    self.service_item.theme_data.background_filename, ImageSource.Theme)
+            if image_path:
+                image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin)
         html = build_html(self.service_item, self.screen, self.is_live, background, image_bytes,
                           plugins=self.plugin_manager.plugins)
         self.web_view.setHtml(html)
@@ -475,6 +478,17 @@
                 Registry().execute('slidecontroller_live_unblank')
             else:
                 self.hide_display(self.hide_mode)
+        if self.service_item.theme_data.background_type == 'video' and self.is_live:
+            if self.service_item.theme_data.background_filename:
+                service_item = ServiceItem()
+                service_item.title = 'webkit'
+                service_item.processor = 'webkit'
+                path = os.path.join(AppLocation.get_section_data_path('themes'),
+                                    self.service_item.theme_data.theme_name)
+                service_item.add_from_command(path,
+                                              self.service_item.theme_data.background_filename,
+                                              ':/media/slidecontroller_multimedia.png')
+                self.media_controller.video(DisplayControllerType.Live, service_item, video_behind_text=True)
         self._hide_mouse()
 
     def footer(self, text):

=== modified file 'openlp/core/ui/media/webkitplayer.py'
--- openlp/core/ui/media/webkitplayer.py	2016-02-26 16:00:04 +0000
+++ openlp/core/ui/media/webkitplayer.py	2016-04-30 17:16:06 +0000
@@ -45,7 +45,7 @@
 """
 
 VIDEO_JS = """
-    function show_video(state, path, volume, loop, variable_value){
+    function show_video(state, path, volume, variable_value){
         // Sometimes  video.currentTime stops slightly short of video.duration and video.ended is intermittent!
 
         var video = document.getElementById('video');
@@ -55,9 +55,6 @@
         switch(state){
             case 'load':
                 video.src = 'file:///' + path;
-                if(loop == true) {
-                    video.loop = true;
-                }
                 video.load();
                 break;
             case 'play':
@@ -180,12 +177,8 @@
         else:
             vol = 0
         path = controller.media_info.file_info.absoluteFilePath()
-        if controller.media_info.is_background:
-            loop = 'true'
-        else:
-            loop = 'false'
         display.web_view.setVisible(True)
-        js = 'show_video("load", "%s", %s, %s);' % (path.replace('\\', '\\\\'), str(vol), loop)
+        js = 'show_video("load", "%s", %s, %s);' % (path.replace('\\', '\\\\'), str(vol))
         display.frame.evaluateJavaScript(js)
         return True
 

=== modified file 'openlp/core/ui/themeform.py'
--- openlp/core/ui/themeform.py	2016-04-17 18:57:03 +0000
+++ openlp/core/ui/themeform.py	2016-04-30 17:16:06 +0000
@@ -31,7 +31,7 @@
 from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
 from openlp.core.lib.ui import critical_error_message_box
 from openlp.core.ui import ThemeLayoutForm
-from openlp.core.ui.lib.colorbutton import ColorButton
+from openlp.core.ui.media.webkitplayer import VIDEO_EXT
 from .themewizard import Ui_ThemeWizard
 
 log = logging.getLogger(__name__)
@@ -66,10 +66,13 @@
         self.gradient_combo_box.currentIndexChanged.connect(self.on_gradient_combo_box_current_index_changed)
         self.color_button.colorChanged.connect(self.on_color_changed)
         self.image_color_button.colorChanged.connect(self.on_image_color_changed)
+        self.video_color_button.colorChanged.connect(self.on_video_color_changed)
         self.gradient_start_button.colorChanged.connect(self.on_gradient_start_color_changed)
         self.gradient_end_button.colorChanged.connect(self.on_gradient_end_color_changed)
         self.image_browse_button.clicked.connect(self.on_image_browse_button_clicked)
         self.image_file_edit.editingFinished.connect(self.on_image_file_edit_editing_finished)
+        self.video_browse_button.clicked.connect(self.on_video_browse_button_clicked)
+        self.video_file_edit.editingFinished.connect(self.on_video_file_edit_editing_finished)
         self.main_color_button.colorChanged.connect(self.on_main_color_changed)
         self.outline_color_button.colorChanged.connect(self.on_outline_color_changed)
         self.shadow_color_button.colorChanged.connect(self.on_shadow_color_changed)
@@ -307,6 +310,10 @@
             self.image_color_button.color = self.theme.background_border_color
             self.image_file_edit.setText(self.theme.background_filename)
             self.setField('background_type', 2)
+        elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Video):
+            self.video_color_button.color = self.theme.background_border_color
+            self.video_file_edit.setText(self.theme.background_filename)
+            self.setField('background_type', 4)
         elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Transparent):
             self.setField('background_type', 3)
         if self.theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.Horizontal):
@@ -384,10 +391,12 @@
         if self.update_theme_allowed:
             self.theme.background_type = BackgroundType.to_string(index)
             if self.theme.background_type != BackgroundType.to_string(BackgroundType.Image) and \
+                    self.theme.background_type != BackgroundType.to_string(BackgroundType.Video) and \
                     self.temp_background_filename == '':
                 self.temp_background_filename = self.theme.background_filename
                 self.theme.background_filename = ''
-            if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) and \
+            if (self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or
+                    self.theme.background_type != BackgroundType.to_string(BackgroundType.Video)) and \
                     self.temp_background_filename != '':
                 self.theme.background_filename = self.temp_background_filename
                 self.temp_background_filename = ''
@@ -413,6 +422,12 @@
         """
         self.theme.background_border_color = color
 
+    def on_video_color_changed(self, color):
+        """
+        Background / Gradient 1 _color button pushed.
+        """
+        self.theme.background_border_color = color
+
     def on_gradient_start_color_changed(self, color):
         """
         Gradient 2 _color button pushed.
@@ -444,6 +459,27 @@
         """
         self.theme.background_filename = str(self.image_file_edit.text())
 
+    def on_video_browse_button_clicked(self):
+        """
+        Background video button pushed.
+        """
+        visible_formats = '(%s)' % '; '.join(VIDEO_EXT)
+        actual_formats = '(%s)' % ' '.join(VIDEO_EXT)
+        video_filter = '%s %s %s' % (translate('OpenLP', 'Video Files'), visible_formats, actual_formats)
+        video_filter = '%s;;%s (*.*)' % (video_filter, UiStrings().AllFiles)
+        filename, filter_used = QtWidgets.QFileDialog.getOpenFileName(
+            self, translate('OpenLP.ThemeWizard', 'Select Video'),
+            self.video_file_edit.text(), video_filter)
+        if filename:
+            self.theme.background_filename = filename
+        self.set_background_page_values()
+
+    def on_video_file_edit_editing_finished(self):
+        """
+        Background video path edited
+        """
+        self.theme.background_filename = str(self.image_file_edit.text())
+
     def on_main_color_changed(self, color):
         """
         Set the main colour value
@@ -519,7 +555,8 @@
             return
         save_from = None
         save_to = None
-        if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image):
+        if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or \
+           self.theme.background_type == BackgroundType.to_string(BackgroundType.Video):
             filename = os.path.split(str(self.theme.background_filename))[1]
             save_to = os.path.join(self.path, self.theme.theme_name, filename)
             save_from = self.theme.background_filename

=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py	2016-04-17 19:32:15 +0000
+++ openlp/core/ui/thememanager.py	2016-04-30 17:16:06 +0000
@@ -300,7 +300,7 @@
         """
         save_to = None
         save_from = None
-        if theme_data.background_type == 'image':
+        if theme_data.background_type == 'image' or theme_data.background_type == 'video':
             save_to = os.path.join(self.path, new_theme_name, os.path.split(str(theme_data.background_filename))[1])
             save_from = theme_data.background_filename
         theme_data.theme_name = new_theme_name
@@ -318,7 +318,7 @@
                                translate('OpenLP.ThemeManager', 'You must select a theme to edit.')):
             item = self.theme_list_widget.currentItem()
             theme = self.get_theme_data(item.data(QtCore.Qt.UserRole))
-            if theme.background_type == 'image':
+            if theme.background_type == 'image' or theme.background_type == 'video':
                 self.old_background_image = theme.background_filename
             self.theme_form.theme = theme
             self.theme_form.exec(True)

=== modified file 'openlp/core/ui/themewizard.py'
--- openlp/core/ui/themewizard.py	2016-04-17 18:57:03 +0000
+++ openlp/core/ui/themewizard.py	2016-04-30 17:16:06 +0000
@@ -62,7 +62,7 @@
         self.background_label = QtWidgets.QLabel(self.background_page)
         self.background_label.setObjectName('background_label')
         self.background_combo_box = QtWidgets.QComboBox(self.background_page)
-        self.background_combo_box.addItems(['', '', '', ''])
+        self.background_combo_box.addItems(['', '', '', '', ''])
         self.background_combo_box.setObjectName('background_combo_box')
         self.background_type_layout.addRow(self.background_label, self.background_combo_box)
         self.background_type_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
@@ -135,6 +135,32 @@
         self.transparent_layout.setObjectName('Transparent_layout')
         self.background_stack.addWidget(self.transparent_widget)
         self.background_layout.addLayout(self.background_stack)
+
+        self.video_widget = QtWidgets.QWidget(self.background_page)
+        self.video_widget.setObjectName('video_widget')
+        self.video_layout = QtWidgets.QFormLayout(self.video_widget)
+        self.video_layout.setContentsMargins(0, 0, 0, 0)
+        self.video_layout.setObjectName('video_layout')
+        self.video_color_label = QtWidgets.QLabel(self.color_widget)
+        self.video_color_label.setObjectName('video_color_label')
+        self.video_color_button = ColorButton(self.color_widget)
+        self.video_color_button.setObjectName('video_color_button')
+        self.video_layout.addRow(self.video_color_label, self.video_color_button)
+        self.video_label = QtWidgets.QLabel(self.video_widget)
+        self.video_label.setObjectName('video_label')
+        self.video_file_layout = QtWidgets.QHBoxLayout()
+        self.video_file_layout.setObjectName('video_file_layout')
+        self.video_file_edit = QtWidgets.QLineEdit(self.video_widget)
+        self.video_file_edit.setObjectName('video_file_edit')
+        self.video_file_layout.addWidget(self.video_file_edit)
+        self.video_browse_button = QtWidgets.QToolButton(self.video_widget)
+        self.video_browse_button.setObjectName('video_browse_button')
+        self.video_browse_button.setIcon(build_icon(':/general/general_open.png'))
+        self.video_file_layout.addWidget(self.video_browse_button)
+        self.video_layout.addRow(self.video_label, self.video_file_layout)
+        self.video_layout.setItem(2, QtWidgets.QFormLayout.LabelRole, self.spacer)
+        self.background_stack.addWidget(self.video_widget)
+
         theme_wizard.addPage(self.background_page)
         # Main Area Page
         self.main_area_page = QtWidgets.QWizardPage()
@@ -390,11 +416,10 @@
         self.background_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Set up your theme\'s background '
                                          'according to the parameters below.'))
         self.background_label.setText(translate('OpenLP.ThemeWizard', 'Background type:'))
-        self.background_combo_box.setItemText(BackgroundType.Solid,
-                                              translate('OpenLP.ThemeWizard', 'Solid color'))
-        self.background_combo_box.setItemText(BackgroundType.Gradient,
-                                              translate('OpenLP.ThemeWizard', 'Gradient'))
+        self.background_combo_box.setItemText(BackgroundType.Solid, translate('OpenLP.ThemeWizard', 'Solid color'))
+        self.background_combo_box.setItemText(BackgroundType.Gradient, translate('OpenLP.ThemeWizard', 'Gradient'))
         self.background_combo_box.setItemText(BackgroundType.Image, UiStrings().Image)
+        self.background_combo_box.setItemText(BackgroundType.Video, UiStrings().Video)
         self.background_combo_box.setItemText(BackgroundType.Transparent,
                                               translate('OpenLP.ThemeWizard', 'Transparent'))
         self.color_label.setText(translate('OpenLP.ThemeWizard', 'color:'))
@@ -413,6 +438,8 @@
                                             translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right'))
         self.image_color_label.setText(translate('OpenLP.ThemeWizard', 'Background color:'))
         self.image_label.setText('%s:' % UiStrings().Image)
+        self.video_color_label.setText(translate('OpenLP.ThemeWizard', 'Background color:'))
+        self.video_label.setText('%s:' % UiStrings().Video)
         self.main_area_page.setTitle(translate('OpenLP.ThemeWizard', 'Main Area Font Details'))
         self.main_area_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Define the font and display '
                                                   'characteristics for the Display text'))

=== modified file 'scripts/translation_utils.py'
--- scripts/translation_utils.py	2015-12-31 22:46:06 +0000
+++ scripts/translation_utils.py	2016-04-30 17:16:06 +0000
@@ -60,7 +60,7 @@
 from PyQt5 import QtCore
 from lxml import etree, objectify
 
-SERVER_URL = 'http://www.transifex.net/api/2/project/openlp/resource/openlp-24x/'
+SERVER_URL = 'http://www.transifex.net/api/2/project/openlp/resource/openlp-26x/'
 IGNORED_PATHS = ['scripts']
 IGNORED_FILES = ['setup.py']
 
@@ -270,7 +270,7 @@
         return
     else:
         os.chdir(os.path.abspath('..'))
-        run('pylupdate4 -verbose -noobsolete openlp.pro')
+        run('pylupdate5 -verbose -noobsolete openlp.pro')
         os.chdir(os.path.abspath('scripts'))
 
 

=== modified file 'tests/functional/openlp_core_ui/test_maindisplay.py'
--- tests/functional/openlp_core_ui/test_maindisplay.py	2016-03-31 20:35:04 +0000
+++ tests/functional/openlp_core_ui/test_maindisplay.py	2016-04-30 17:16:06 +0000
@@ -27,8 +27,9 @@
 from PyQt5 import QtCore
 
 from openlp.core.common import Registry, is_macosx, Settings
-from openlp.core.lib import ScreenList
+from openlp.core.lib import ScreenList, PluginManager
 from openlp.core.ui import MainDisplay
+from openlp.core.ui.media import MediaController
 from openlp.core.ui.maindisplay import TRANSPARENT_STYLESHEET, OPAQUE_STYLESHEET
 
 from tests.helpers.testmixin import TestMixin
@@ -223,3 +224,61 @@
 
         # THEN: setVisible should had not been called
         main_display.setVisible.assert_not_called()
+
+    @patch(u'openlp.core.ui.maindisplay.Settings')
+    @patch(u'openlp.core.ui.maindisplay.build_html')
+    def build_html_no_video_test(self, MockedSettings, Mocked_build_html):
+        # GIVEN: Mocked display
+        display = MagicMock()
+        mocked_media_controller = MagicMock()
+        Registry.create()
+        Registry().register('media_controller', mocked_media_controller)
+        main_display = MainDisplay(display)
+        main_display.frame = MagicMock()
+        mocked_settings = MagicMock()
+        mocked_settings.value.return_value = False
+        MockedSettings.return_value = mocked_settings
+        main_display.shake_web_view = MagicMock()
+        service_item = MagicMock()
+        mocked_plugin = MagicMock()
+        display.plugin_manager = PluginManager()
+        display.plugin_manager.plugins = [mocked_plugin]
+        main_display.web_view = MagicMock()
+
+        # WHEN: build_html is called with a normal service item and a non video theme.
+        main_display.build_html(service_item)
+
+        # THEN: the following should had not been called
+        self.assertEquals(main_display.web_view.setHtml.call_count, 1, 'setHTML should be called once')
+        self.assertEquals(main_display.media_controller.video.call_count, 0,
+                          'Media Controller video should not have been called')
+
+    @patch(u'openlp.core.ui.maindisplay.Settings')
+    @patch(u'openlp.core.ui.maindisplay.build_html')
+    def build_html_video_test(self, MockedSettings, Mocked_build_html):
+        # GIVEN: Mocked display
+        display = MagicMock()
+        mocked_media_controller = MagicMock()
+        Registry.create()
+        Registry().register('media_controller', mocked_media_controller)
+        main_display = MainDisplay(display)
+        main_display.frame = MagicMock()
+        mocked_settings = MagicMock()
+        mocked_settings.value.return_value = False
+        MockedSettings.return_value = mocked_settings
+        main_display.shake_web_view = MagicMock()
+        service_item = MagicMock()
+        service_item.theme_data = MagicMock()
+        service_item.theme_data.background_type = 'video'
+        mocked_plugin = MagicMock()
+        display.plugin_manager = PluginManager()
+        display.plugin_manager.plugins = [mocked_plugin]
+        main_display.web_view = MagicMock()
+
+        # WHEN: build_html is called with a normal service item and a video theme.
+        main_display.build_html(service_item)
+
+        # THEN: the following should had not been called
+        self.assertEquals(main_display.web_view.setHtml.call_count, 1, 'setHTML should be called once')
+        self.assertEquals(main_display.media_controller.video.call_count, 1,
+                          'Media Controller video should have been called once')


Follow ups