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

Proposed by Tim Bentley
Status: Superseded
Proposed branch: lp:~trb143/openlp/background_videos
Merge into: lp:openlp
Diff against target: 470 lines (+184/-32)
9 files modified
openlp/core/common/uistrings.py (+1/-0)
openlp/core/lib/theme.py (+24/-1)
openlp/core/ui/maindisplay.py (+22/-9)
openlp/core/ui/media/webkitplayer.py (+2/-9)
openlp/core/ui/themeform.py (+41/-3)
openlp/core/ui/thememanager.py (+2/-2)
openlp/core/ui/themewizard.py (+30/-5)
scripts/translation_utils.py (+2/-2)
tests/functional/openlp_core_ui/test_maindisplay.py (+60/-1)
To merge this branch: bzr merge lp:~trb143/openlp/background_videos
Reviewer Review Type Date Requested Status
OpenLP Core Pending
Review via email: mp+293469@code.launchpad.net

This proposal supersedes a proposal from 2016-04-30.

This proposal has been superseded by a proposal from 2016-05-02.

To post a comment you must log in.
lp:~trb143/openlp/background_videos updated
2691. By Tim Bentley

head

2692. By Tim Bentley

fix strings

2693. By Tim Bentley

change net to com

2694. By Tim Bentley

remove rogue print

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/common/uistrings.py'
2--- openlp/core/common/uistrings.py 2016-04-16 19:51:35 +0000
3+++ openlp/core/common/uistrings.py 2016-05-02 08:12:54 +0000
4@@ -152,3 +152,4 @@
5 self.Version = translate('OpenLP.Ui', 'Version')
6 self.View = translate('OpenLP.Ui', 'View')
7 self.ViewMode = translate('OpenLP.Ui', 'View Mode')
8+ self.Video = translate('OpenLP.Ui', 'Video')
9
10=== modified file 'openlp/core/lib/theme.py'
11--- openlp/core/lib/theme.py 2015-12-31 22:46:06 +0000
12+++ openlp/core/lib/theme.py 2016-05-02 08:12:54 +0000
13@@ -44,6 +44,7 @@
14 Gradient = 1
15 Image = 2
16 Transparent = 3
17+ Video = 4
18
19 @staticmethod
20 def to_string(background_type):
21@@ -58,6 +59,8 @@
22 return 'image'
23 elif background_type == BackgroundType.Transparent:
24 return 'transparent'
25+ elif background_type == BackgroundType.Video:
26+ return 'video'
27
28 @staticmethod
29 def from_string(type_string):
30@@ -72,6 +75,8 @@
31 return BackgroundType.Image
32 elif type_string == 'transparent':
33 return BackgroundType.Transparent
34+ elif type_string == 'video':
35+ return BackgroundType.Video
36
37
38 class BackgroundGradientType(object):
39@@ -184,7 +189,7 @@
40
41 :param path: The path name to be added.
42 """
43- if self.background_type == 'image':
44+ if self.background_type == 'image' or self.background_type == 'video':
45 if self.background_filename and path:
46 self.theme_name = self.theme_name.strip()
47 self.background_filename = self.background_filename.strip()
48@@ -255,6 +260,21 @@
49 # Create endColor element
50 self.child_element(background, 'borderColor', str(border_color))
51
52+ def add_background_video(self, filename, border_color):
53+ """
54+ Add a video background.
55+
56+ :param filename: The file name of the video.
57+ :param border_color:
58+ """
59+ background = self.theme_xml.createElement('background')
60+ background.setAttribute('type', 'video')
61+ self.theme.appendChild(background)
62+ # Create Filename element
63+ self.child_element(background, 'filename', filename)
64+ # Create endColor element
65+ self.child_element(background, 'borderColor', str(border_color))
66+
67 def add_font(self, name, color, size, override, fonttype='main', bold='False', italics='False',
68 line_adjustment=0, xpos=0, ypos=0, width=0, height=0, outline='False', outline_color='#ffffff',
69 outline_pixel=2, shadow='False', shadow_color='#ffffff', shadow_pixel=5):
70@@ -512,6 +532,9 @@
71 elif self.background_type == BackgroundType.to_string(BackgroundType.Image):
72 filename = os.path.split(self.background_filename)[1]
73 self.add_background_image(filename, self.background_border_color)
74+ elif self.background_type == BackgroundType.to_string(BackgroundType.Video):
75+ filename = os.path.split(self.background_filename)[1]
76+ self.add_background_video(filename, self.background_border_color)
77 elif self.background_type == BackgroundType.to_string(BackgroundType.Transparent):
78 self.add_background_transparent()
79 self.add_font(
80
81=== modified file 'openlp/core/ui/maindisplay.py'
82--- openlp/core/ui/maindisplay.py 2016-04-29 20:25:12 +0000
83+++ openlp/core/ui/maindisplay.py 2016-05-02 08:12:54 +0000
84@@ -31,13 +31,15 @@
85
86 import html
87 import logging
88+import os
89
90 from PyQt5 import QtCore, QtWidgets, QtWebKit, QtWebKitWidgets, QtOpenGL, QtGui, QtMultimedia
91
92-from openlp.core.common import Registry, RegistryProperties, OpenLPMixin, Settings, translate, is_macosx, is_win
93+from openlp.core.common import AppLocation, Registry, RegistryProperties, OpenLPMixin, Settings, translate,\
94+ is_macosx, is_win
95 from openlp.core.lib import ServiceItem, ImageSource, ScreenList, build_html, expand_tags, image_to_byte
96 from openlp.core.lib.theme import BackgroundType
97-from openlp.core.ui import HideMode, AlertLocation
98+from openlp.core.ui import HideMode, AlertLocation, DisplayControllerType
99
100 if is_macosx():
101 from ctypes import pythonapi, c_void_p, c_char_p, py_object
102@@ -459,13 +461,13 @@
103 background = self.image_manager.get_image_bytes(self.override['image'], ImageSource.ImagePlugin)
104 self.set_transparency(self.service_item.theme_data.background_type ==
105 BackgroundType.to_string(BackgroundType.Transparent))
106- if self.service_item.theme_data.background_filename:
107- self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(
108- self.service_item.theme_data.background_filename, ImageSource.Theme)
109- if image_path:
110- image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin)
111- else:
112- image_bytes = None
113+ image_bytes = None
114+ if self.service_item.theme_data.background_type == 'image':
115+ if self.service_item.theme_data.background_filename:
116+ self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(
117+ self.service_item.theme_data.background_filename, ImageSource.Theme)
118+ if image_path:
119+ image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin)
120 html = build_html(self.service_item, self.screen, self.is_live, background, image_bytes,
121 plugins=self.plugin_manager.plugins)
122 self.web_view.setHtml(html)
123@@ -477,6 +479,17 @@
124 Registry().execute('slidecontroller_live_unblank')
125 else:
126 self.hide_display(self.hide_mode)
127+ if self.service_item.theme_data.background_type == 'video' and self.is_live:
128+ if self.service_item.theme_data.background_filename:
129+ service_item = ServiceItem()
130+ service_item.title = 'webkit'
131+ service_item.processor = 'webkit'
132+ path = os.path.join(AppLocation.get_section_data_path('themes'),
133+ self.service_item.theme_data.theme_name)
134+ service_item.add_from_command(path,
135+ self.service_item.theme_data.background_filename,
136+ ':/media/slidecontroller_multimedia.png')
137+ self.media_controller.video(DisplayControllerType.Live, service_item, video_behind_text=True)
138 self._hide_mouse()
139
140 def footer(self, text):
141
142=== modified file 'openlp/core/ui/media/webkitplayer.py'
143--- openlp/core/ui/media/webkitplayer.py 2016-02-26 16:00:04 +0000
144+++ openlp/core/ui/media/webkitplayer.py 2016-05-02 08:12:54 +0000
145@@ -45,7 +45,7 @@
146 """
147
148 VIDEO_JS = """
149- function show_video(state, path, volume, loop, variable_value){
150+ function show_video(state, path, volume, variable_value){
151 // Sometimes video.currentTime stops slightly short of video.duration and video.ended is intermittent!
152
153 var video = document.getElementById('video');
154@@ -55,9 +55,6 @@
155 switch(state){
156 case 'load':
157 video.src = 'file:///' + path;
158- if(loop == true) {
159- video.loop = true;
160- }
161 video.load();
162 break;
163 case 'play':
164@@ -180,12 +177,8 @@
165 else:
166 vol = 0
167 path = controller.media_info.file_info.absoluteFilePath()
168- if controller.media_info.is_background:
169- loop = 'true'
170- else:
171- loop = 'false'
172 display.web_view.setVisible(True)
173- js = 'show_video("load", "%s", %s, %s);' % (path.replace('\\', '\\\\'), str(vol), loop)
174+ js = 'show_video("load", "{path}", {vol});'.format(path=path.replace('\\', '\\\\'), vol=str(vol))
175 display.frame.evaluateJavaScript(js)
176 return True
177
178
179=== modified file 'openlp/core/ui/themeform.py'
180--- openlp/core/ui/themeform.py 2016-04-17 18:57:03 +0000
181+++ openlp/core/ui/themeform.py 2016-05-02 08:12:54 +0000
182@@ -31,7 +31,7 @@
183 from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
184 from openlp.core.lib.ui import critical_error_message_box
185 from openlp.core.ui import ThemeLayoutForm
186-from openlp.core.ui.lib.colorbutton import ColorButton
187+from openlp.core.ui.media.webkitplayer import VIDEO_EXT
188 from .themewizard import Ui_ThemeWizard
189
190 log = logging.getLogger(__name__)
191@@ -66,10 +66,13 @@
192 self.gradient_combo_box.currentIndexChanged.connect(self.on_gradient_combo_box_current_index_changed)
193 self.color_button.colorChanged.connect(self.on_color_changed)
194 self.image_color_button.colorChanged.connect(self.on_image_color_changed)
195+ self.video_color_button.colorChanged.connect(self.on_video_color_changed)
196 self.gradient_start_button.colorChanged.connect(self.on_gradient_start_color_changed)
197 self.gradient_end_button.colorChanged.connect(self.on_gradient_end_color_changed)
198 self.image_browse_button.clicked.connect(self.on_image_browse_button_clicked)
199 self.image_file_edit.editingFinished.connect(self.on_image_file_edit_editing_finished)
200+ self.video_browse_button.clicked.connect(self.on_video_browse_button_clicked)
201+ self.video_file_edit.editingFinished.connect(self.on_video_file_edit_editing_finished)
202 self.main_color_button.colorChanged.connect(self.on_main_color_changed)
203 self.outline_color_button.colorChanged.connect(self.on_outline_color_changed)
204 self.shadow_color_button.colorChanged.connect(self.on_shadow_color_changed)
205@@ -307,6 +310,10 @@
206 self.image_color_button.color = self.theme.background_border_color
207 self.image_file_edit.setText(self.theme.background_filename)
208 self.setField('background_type', 2)
209+ elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Video):
210+ self.video_color_button.color = self.theme.background_border_color
211+ self.video_file_edit.setText(self.theme.background_filename)
212+ self.setField('background_type', 4)
213 elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Transparent):
214 self.setField('background_type', 3)
215 if self.theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.Horizontal):
216@@ -384,10 +391,12 @@
217 if self.update_theme_allowed:
218 self.theme.background_type = BackgroundType.to_string(index)
219 if self.theme.background_type != BackgroundType.to_string(BackgroundType.Image) and \
220+ self.theme.background_type != BackgroundType.to_string(BackgroundType.Video) and \
221 self.temp_background_filename == '':
222 self.temp_background_filename = self.theme.background_filename
223 self.theme.background_filename = ''
224- if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) and \
225+ if (self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or
226+ self.theme.background_type != BackgroundType.to_string(BackgroundType.Video)) and \
227 self.temp_background_filename != '':
228 self.theme.background_filename = self.temp_background_filename
229 self.temp_background_filename = ''
230@@ -413,6 +422,12 @@
231 """
232 self.theme.background_border_color = color
233
234+ def on_video_color_changed(self, color):
235+ """
236+ Background / Gradient 1 _color button pushed.
237+ """
238+ self.theme.background_border_color = color
239+
240 def on_gradient_start_color_changed(self, color):
241 """
242 Gradient 2 _color button pushed.
243@@ -444,6 +459,28 @@
244 """
245 self.theme.background_filename = str(self.image_file_edit.text())
246
247+ def on_video_browse_button_clicked(self):
248+ """
249+ Background video button pushed.
250+ """
251+ visible_formats = '(%s)' % '; '.join(VIDEO_EXT)
252+ actual_formats = '(%s)' % ' '.join(VIDEO_EXT)
253+ video_filter = '{trans} {visible} {actual}'.format(trans=translate('OpenLP', 'Video Files'),
254+ visible=visible_formats, actual=actual_formats)
255+ video_filter = '{video};;{ui} (*.*)'.format(video=video_filter, ui=UiStrings().AllFiles)
256+ filename, filter_used = QtWidgets.QFileDialog.getOpenFileName(
257+ self, translate('OpenLP.ThemeWizard', 'Select Video'),
258+ self.video_file_edit.text(), video_filter)
259+ if filename:
260+ self.theme.background_filename = filename
261+ self.set_background_page_values()
262+
263+ def on_video_file_edit_editing_finished(self):
264+ """
265+ Background video path edited
266+ """
267+ self.theme.background_filename = str(self.image_file_edit.text())
268+
269 def on_main_color_changed(self, color):
270 """
271 Set the main colour value
272@@ -519,7 +556,8 @@
273 return
274 save_from = None
275 save_to = None
276- if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image):
277+ if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or \
278+ self.theme.background_type == BackgroundType.to_string(BackgroundType.Video):
279 filename = os.path.split(str(self.theme.background_filename))[1]
280 save_to = os.path.join(self.path, self.theme.theme_name, filename)
281 save_from = self.theme.background_filename
282
283=== modified file 'openlp/core/ui/thememanager.py'
284--- openlp/core/ui/thememanager.py 2016-04-17 19:32:15 +0000
285+++ openlp/core/ui/thememanager.py 2016-05-02 08:12:54 +0000
286@@ -300,7 +300,7 @@
287 """
288 save_to = None
289 save_from = None
290- if theme_data.background_type == 'image':
291+ if theme_data.background_type == 'image' or theme_data.background_type == 'video':
292 save_to = os.path.join(self.path, new_theme_name, os.path.split(str(theme_data.background_filename))[1])
293 save_from = theme_data.background_filename
294 theme_data.theme_name = new_theme_name
295@@ -318,7 +318,7 @@
296 translate('OpenLP.ThemeManager', 'You must select a theme to edit.')):
297 item = self.theme_list_widget.currentItem()
298 theme = self.get_theme_data(item.data(QtCore.Qt.UserRole))
299- if theme.background_type == 'image':
300+ if theme.background_type == 'image' or theme.background_type == 'video':
301 self.old_background_image = theme.background_filename
302 self.theme_form.theme = theme
303 self.theme_form.exec(True)
304
305=== modified file 'openlp/core/ui/themewizard.py'
306--- openlp/core/ui/themewizard.py 2016-04-17 18:57:03 +0000
307+++ openlp/core/ui/themewizard.py 2016-05-02 08:12:54 +0000
308@@ -62,7 +62,7 @@
309 self.background_label = QtWidgets.QLabel(self.background_page)
310 self.background_label.setObjectName('background_label')
311 self.background_combo_box = QtWidgets.QComboBox(self.background_page)
312- self.background_combo_box.addItems(['', '', '', ''])
313+ self.background_combo_box.addItems(['', '', '', '', ''])
314 self.background_combo_box.setObjectName('background_combo_box')
315 self.background_type_layout.addRow(self.background_label, self.background_combo_box)
316 self.background_type_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
317@@ -135,6 +135,30 @@
318 self.transparent_layout.setObjectName('Transparent_layout')
319 self.background_stack.addWidget(self.transparent_widget)
320 self.background_layout.addLayout(self.background_stack)
321+ self.video_widget = QtWidgets.QWidget(self.background_page)
322+ self.video_widget.setObjectName('video_widget')
323+ self.video_layout = QtWidgets.QFormLayout(self.video_widget)
324+ self.video_layout.setContentsMargins(0, 0, 0, 0)
325+ self.video_layout.setObjectName('video_layout')
326+ self.video_color_label = QtWidgets.QLabel(self.color_widget)
327+ self.video_color_label.setObjectName('video_color_label')
328+ self.video_color_button = ColorButton(self.color_widget)
329+ self.video_color_button.setObjectName('video_color_button')
330+ self.video_layout.addRow(self.video_color_label, self.video_color_button)
331+ self.video_label = QtWidgets.QLabel(self.video_widget)
332+ self.video_label.setObjectName('video_label')
333+ self.video_file_layout = QtWidgets.QHBoxLayout()
334+ self.video_file_layout.setObjectName('video_file_layout')
335+ self.video_file_edit = QtWidgets.QLineEdit(self.video_widget)
336+ self.video_file_edit.setObjectName('video_file_edit')
337+ self.video_file_layout.addWidget(self.video_file_edit)
338+ self.video_browse_button = QtWidgets.QToolButton(self.video_widget)
339+ self.video_browse_button.setObjectName('video_browse_button')
340+ self.video_browse_button.setIcon(build_icon(':/general/general_open.png'))
341+ self.video_file_layout.addWidget(self.video_browse_button)
342+ self.video_layout.addRow(self.video_label, self.video_file_layout)
343+ self.video_layout.setItem(2, QtWidgets.QFormLayout.LabelRole, self.spacer)
344+ self.background_stack.addWidget(self.video_widget)
345 theme_wizard.addPage(self.background_page)
346 # Main Area Page
347 self.main_area_page = QtWidgets.QWizardPage()
348@@ -390,11 +414,10 @@
349 self.background_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Set up your theme\'s background '
350 'according to the parameters below.'))
351 self.background_label.setText(translate('OpenLP.ThemeWizard', 'Background type:'))
352- self.background_combo_box.setItemText(BackgroundType.Solid,
353- translate('OpenLP.ThemeWizard', 'Solid color'))
354- self.background_combo_box.setItemText(BackgroundType.Gradient,
355- translate('OpenLP.ThemeWizard', 'Gradient'))
356+ self.background_combo_box.setItemText(BackgroundType.Solid, translate('OpenLP.ThemeWizard', 'Solid color'))
357+ self.background_combo_box.setItemText(BackgroundType.Gradient, translate('OpenLP.ThemeWizard', 'Gradient'))
358 self.background_combo_box.setItemText(BackgroundType.Image, UiStrings().Image)
359+ self.background_combo_box.setItemText(BackgroundType.Video, UiStrings().Video)
360 self.background_combo_box.setItemText(BackgroundType.Transparent,
361 translate('OpenLP.ThemeWizard', 'Transparent'))
362 self.color_label.setText(translate('OpenLP.ThemeWizard', 'color:'))
363@@ -413,6 +436,8 @@
364 translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right'))
365 self.image_color_label.setText(translate('OpenLP.ThemeWizard', 'Background color:'))
366 self.image_label.setText('%s:' % UiStrings().Image)
367+ self.video_color_label.setText(translate('OpenLP.ThemeWizard', 'Background color:'))
368+ self.video_label.setText('%s:' % UiStrings().Video)
369 self.main_area_page.setTitle(translate('OpenLP.ThemeWizard', 'Main Area Font Details'))
370 self.main_area_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Define the font and display '
371 'characteristics for the Display text'))
372
373=== modified file 'scripts/translation_utils.py'
374--- scripts/translation_utils.py 2015-12-31 22:46:06 +0000
375+++ scripts/translation_utils.py 2016-05-02 08:12:54 +0000
376@@ -60,7 +60,7 @@
377 from PyQt5 import QtCore
378 from lxml import etree, objectify
379
380-SERVER_URL = 'http://www.transifex.net/api/2/project/openlp/resource/openlp-24x/'
381+SERVER_URL = 'http://www.transifex.net/api/2/project/openlp/resource/openlp-26x/'
382 IGNORED_PATHS = ['scripts']
383 IGNORED_FILES = ['setup.py']
384
385@@ -270,7 +270,7 @@
386 return
387 else:
388 os.chdir(os.path.abspath('..'))
389- run('pylupdate4 -verbose -noobsolete openlp.pro')
390+ run('pylupdate5 -verbose -noobsolete openlp.pro')
391 os.chdir(os.path.abspath('scripts'))
392
393
394
395=== modified file 'tests/functional/openlp_core_ui/test_maindisplay.py'
396--- tests/functional/openlp_core_ui/test_maindisplay.py 2016-03-31 20:35:04 +0000
397+++ tests/functional/openlp_core_ui/test_maindisplay.py 2016-05-02 08:12:54 +0000
398@@ -27,8 +27,9 @@
399 from PyQt5 import QtCore
400
401 from openlp.core.common import Registry, is_macosx, Settings
402-from openlp.core.lib import ScreenList
403+from openlp.core.lib import ScreenList, PluginManager
404 from openlp.core.ui import MainDisplay
405+from openlp.core.ui.media import MediaController
406 from openlp.core.ui.maindisplay import TRANSPARENT_STYLESHEET, OPAQUE_STYLESHEET
407
408 from tests.helpers.testmixin import TestMixin
409@@ -223,3 +224,61 @@
410
411 # THEN: setVisible should had not been called
412 main_display.setVisible.assert_not_called()
413+
414+ @patch(u'openlp.core.ui.maindisplay.Settings')
415+ @patch(u'openlp.core.ui.maindisplay.build_html')
416+ def build_html_no_video_test(self, MockedSettings, Mocked_build_html):
417+ # GIVEN: Mocked display
418+ display = MagicMock()
419+ mocked_media_controller = MagicMock()
420+ Registry.create()
421+ Registry().register('media_controller', mocked_media_controller)
422+ main_display = MainDisplay(display)
423+ main_display.frame = MagicMock()
424+ mocked_settings = MagicMock()
425+ mocked_settings.value.return_value = False
426+ MockedSettings.return_value = mocked_settings
427+ main_display.shake_web_view = MagicMock()
428+ service_item = MagicMock()
429+ mocked_plugin = MagicMock()
430+ display.plugin_manager = PluginManager()
431+ display.plugin_manager.plugins = [mocked_plugin]
432+ main_display.web_view = MagicMock()
433+
434+ # WHEN: build_html is called with a normal service item and a non video theme.
435+ main_display.build_html(service_item)
436+
437+ # THEN: the following should had not been called
438+ self.assertEquals(main_display.web_view.setHtml.call_count, 1, 'setHTML should be called once')
439+ self.assertEquals(main_display.media_controller.video.call_count, 0,
440+ 'Media Controller video should not have been called')
441+
442+ @patch(u'openlp.core.ui.maindisplay.Settings')
443+ @patch(u'openlp.core.ui.maindisplay.build_html')
444+ def build_html_video_test(self, MockedSettings, Mocked_build_html):
445+ # GIVEN: Mocked display
446+ display = MagicMock()
447+ mocked_media_controller = MagicMock()
448+ Registry.create()
449+ Registry().register('media_controller', mocked_media_controller)
450+ main_display = MainDisplay(display)
451+ main_display.frame = MagicMock()
452+ mocked_settings = MagicMock()
453+ mocked_settings.value.return_value = False
454+ MockedSettings.return_value = mocked_settings
455+ main_display.shake_web_view = MagicMock()
456+ service_item = MagicMock()
457+ service_item.theme_data = MagicMock()
458+ service_item.theme_data.background_type = 'video'
459+ mocked_plugin = MagicMock()
460+ display.plugin_manager = PluginManager()
461+ display.plugin_manager.plugins = [mocked_plugin]
462+ main_display.web_view = MagicMock()
463+
464+ # WHEN: build_html is called with a normal service item and a video theme.
465+ main_display.build_html(service_item)
466+
467+ # THEN: the following should had not been called
468+ self.assertEquals(main_display.web_view.setHtml.call_count, 1, 'setHTML should be called once')
469+ self.assertEquals(main_display.media_controller.video.call_count, 1,
470+ 'Media Controller video should have been called once')