diff --git a/openlp/core/display/html/display.js b/openlp/core/display/html/display.js
index 639308c67..0a80a93e0 100644
--- a/openlp/core/display/html/display.js
+++ b/openlp/core/display/html/display.js
@@ -1016,9 +1016,6 @@ var Display = {
targetElement.style.cssText = "";
targetElement.setAttribute("data-background", backgroundContent);
targetElement.setAttribute("data-background-size", "cover");
- if (!!backgroundHtml) {
- background.innerHTML = backgroundHtml;
- }
// set up the main area
if (!is_text) {
diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py
index 245b2d752..ca04ac55f 100644
--- a/openlp/core/ui/media/mediacontroller.py
+++ b/openlp/core/ui/media/mediacontroller.py
@@ -41,8 +41,7 @@ from openlp.core.common.registry import Registry, RegistryBase
from openlp.core.lib.serviceitem import ItemCapabilities
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui import DisplayControllerType, HideMode
-from openlp.core.ui.media import MediaState, ItemMediaInfo, MediaType, parse_optical_path, parse_stream_path, \
- VIDEO_EXT, AUDIO_EXT
+from openlp.core.ui.media import MediaState, ItemMediaInfo, MediaType, parse_optical_path, parse_stream_path
from openlp.core.ui.media.remote import register_views
from openlp.core.ui.media.vlcplayer import VlcPlayer, get_vlc
@@ -50,6 +49,7 @@ from openlp.core.ui.media.vlcplayer import VlcPlayer, get_vlc
log = logging.getLogger(__name__)
TICK_TIME = 200
+HIDE_DELAY_TIME = 2500
class MediaController(RegistryBase, LogMixin, RegistryProperties):
@@ -68,10 +68,16 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
# Timer for video state
self.live_timer = QtCore.QTimer()
self.live_timer.setInterval(TICK_TIME)
+ self.live_hide_timer = QtCore.QTimer()
+ self.live_hide_timer.setSingleShot(True)
+ self.live_kill_timer = QtCore.QTimer()
+ self.live_kill_timer.setSingleShot(True)
self.preview_timer = QtCore.QTimer()
self.preview_timer.setInterval(TICK_TIME)
# Signals
self.live_timer.timeout.connect(self._media_state_live)
+ self.live_hide_timer.timeout.connect(self._on_media_hide_live)
+ self.live_kill_timer.timeout.connect(self._on_media_kill_live)
self.preview_timer.timeout.connect(self._media_state_preview)
Registry().register_function('playbackPlay', self.media_play_msg)
Registry().register_function('playbackPause', self.media_pause_msg)
@@ -154,31 +160,29 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
Check if there is a running Live media Player and do updating stuff (e.g. update the UI)
"""
- display = self._define_display(self._display_controllers(DisplayControllerType.Live))
if DisplayControllerType.Live in self.current_media_players:
- self.current_media_players[DisplayControllerType.Live].resize(self.live_controller)
- self.current_media_players[DisplayControllerType.Live].update_ui(self.live_controller, display)
- self.tick(self._display_controllers(DisplayControllerType.Live))
- if self.current_media_players[DisplayControllerType.Live].get_live_state() is not MediaState.Playing:
+ media_player = self.current_media_players[DisplayControllerType.Live]
+ media_player.resize(self.live_controller)
+ media_player.update_ui(self.live_controller, self._define_display(self.live_controller))
+ if not self.tick(self.live_controller):
self.live_timer.stop()
else:
self.live_timer.stop()
- self.media_stop(self._display_controllers(DisplayControllerType.Live))
+ self.media_stop(self.live_controller)
def _media_state_preview(self):
"""
Check if there is a running Preview media Player and do updating stuff (e.g. update the UI)
"""
- display = self._define_display(self._display_controllers(DisplayControllerType.Preview))
if DisplayControllerType.Preview in self.current_media_players:
- self.current_media_players[DisplayControllerType.Preview].resize(self.live_controller)
- self.current_media_players[DisplayControllerType.Preview].update_ui(self.preview_controller, display)
- self.tick(self._display_controllers(DisplayControllerType.Preview))
- if self.current_media_players[DisplayControllerType.Preview].get_preview_state() is not MediaState.Playing:
+ media_player = self.current_media_players[DisplayControllerType.Preview]
+ media_player.resize(self.preview_controller)
+ media_player.update_ui(self.preview_controller, self._define_display(self.preview_controller))
+ if not self.tick(self.preview_controller):
self.preview_timer.stop()
else:
self.preview_timer.stop()
- self.media_stop(self._display_controllers(DisplayControllerType.Preview))
+ self.media_stop(self.preview_controller)
def setup_display(self, controller, preview):
"""
@@ -224,9 +228,11 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
is_valid = True
controller = self._display_controllers(source)
+ log.debug(f'load_video is_live:{controller.is_live}')
# stop running videos
self.media_reset(controller)
controller.media_info = ItemMediaInfo()
+ controller.media_info.media_type = MediaType.Video
if controller.is_live:
controller.media_info.volume = self.settings.value('media/live volume')
else:
@@ -234,6 +240,9 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
# background will always loop video.
if service_item.is_capable(ItemCapabilities.HasBackgroundAudio):
controller.media_info.file_info = service_item.background_audio
+ controller.media_info.media_type = MediaType.Audio
+ # is_background indicates we shouldn't override the normal display
+ controller.media_info.is_background = True
else:
if service_item.is_capable(ItemCapabilities.HasBackgroundStream):
(name, mrl, options) = parse_stream_path(service_item.stream_mrl)
@@ -268,6 +277,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.media_info.length = service_item.media_length
is_valid = self._check_file_type(controller, display)
controller.media_info.start_time = service_item.start_time
+ controller.media_info.timer = service_item.start_time
controller.media_info.end_time = service_item.end_time
elif controller.preview_display:
if service_item.is_capable(ItemCapabilities.IsOptical):
@@ -292,11 +302,21 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
translate('MediaPlugin.MediaItem', 'Unsupported File'))
return False
self.log_debug('video media type: {tpe} '.format(tpe=str(controller.media_info.media_type)))
+ # If both the preview and live view have a stream, make sure only the live view continues streaming
+ if controller.media_info.media_type == MediaType.Stream:
+ if controller.is_live:
+ if self.preview_controller.media_info.media_type == MediaType.Stream:
+ self.log_warning('stream can only be displayed in one instance, killing preview stream')
+ self.preview_controller.on_media_close()
+ else:
+ if self.live_controller.media_info.media_type == MediaType.Stream:
+ self.log_warning('stream cannot be previewed while also streaming live')
+ return
autoplay = False
- if service_item.requires_media():
+ if service_item.requires_media() and hidden == HideMode.Theme:
autoplay = True
# Preview requested
- if not controller.is_live:
+ elif not controller.is_live:
autoplay = True
# Visible or background requested or Service Item wants to autostart
elif not hidden or service_item.will_auto_start:
@@ -355,6 +375,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
else:
controller.media_info.media_type = MediaType.DVD
controller.media_info.start_time = start
+ controller.media_info.timer = start
controller.media_info.end_time = end
controller.media_info.length = (end - start)
controller.media_info.title_track = title
@@ -386,38 +407,23 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
return True
return False
for file in controller.media_info.file_info:
- if file.is_file:
- suffix = '*%s' % file.suffix.lower()
- file = str(file)
- if suffix in VIDEO_EXT:
- self.resize(controller, self.vlc_player)
- if self.vlc_player.load(controller, display, file):
- self.current_media_players[controller.controller_type] = self.vlc_player
- controller.media_info.media_type = MediaType.Video
- return True
- if suffix in AUDIO_EXT:
- if self.vlc_player.load(controller, display, file):
- self.current_media_players[controller.controller_type] = self.vlc_player
- controller.media_info.media_type = MediaType.Audio
- return True
- else:
- file = str(file)
- if self.vlc_player.can_folder:
- self.resize(controller, self.vlc_player)
- if self.vlc_player.load(controller, display, file):
- self.current_media_players[controller.controller_type] = self.vlc_player
- controller.media_info.media_type = MediaType.Video
- return True
+ if not file.is_file and not self.vlc_player.can_folder:
+ return False
+ file = str(file)
+ self.resize(controller, self.vlc_player)
+ if self.vlc_player.load(controller, display, file):
+ self.current_media_players[controller.controller_type] = self.vlc_player
+ return True
return False
- def media_play_msg(self, msg, status=True):
+ def media_play_msg(self, msg):
"""
Responds to the request to play a loaded video
:param msg: First element is the controller which should be used
:param status:
"""
- return self.media_play(msg[0], status)
+ return self.media_play(msg[0])
def on_media_play(self):
"""
@@ -425,14 +431,13 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
return self.media_play(self.live_controller)
- def media_play(self, controller, first_time=True):
+ def media_play(self, controller):
"""
Responds to the request to play a loaded video
:param controller: The controller to be played
- :param first_time:
"""
- self.log_debug(f"media_play with {first_time}")
+ self.log_debug(f'media_play is_live:{controller.is_live}')
controller.seek_slider.blockSignals(True)
controller.volume_slider.blockSignals(True)
display = self._define_display(controller)
@@ -441,25 +446,29 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.volume_slider.blockSignals(False)
return False
self.media_volume(controller, controller.media_info.volume)
- if first_time:
- self.current_media_players[controller.controller_type].set_visible(controller, True)
- controller.mediabar.actions['playbackPlay'].setVisible(False)
- controller.mediabar.actions['playbackPause'].setVisible(True)
- controller.mediabar.actions['playbackStop'].setDisabled(False)
+ self._media_set_visibility(controller, True)
+ controller.mediabar.actions['playbackPlay'].setVisible(False)
+ controller.mediabar.actions['playbackPause'].setVisible(True)
+ controller.mediabar.actions['playbackStop'].setDisabled(False)
+ controller.mediabar.actions['playbackLoop'].setChecked(controller.media_info.is_looping_playback)
+ controller.mediabar.actions['playbackStop'].setVisible(not controller.media_info.is_background or
+ controller.media_info.media_type is MediaType.Audio)
+ controller.mediabar.actions['playbackLoop'].setVisible((not controller.media_info.is_background and
+ controller.media_info.media_type is not MediaType.Stream)
+ or controller.media_info.media_type is MediaType.Audio)
+ # Start Timer for ui updates
if controller.is_live:
- if controller.hide_menu.defaultAction().isChecked():
- controller.hide_menu.defaultAction().trigger()
- # Start Timer for ui updates
if not self.live_timer.isActive():
self.live_timer.start()
else:
- # Start Timer for ui updates
if not self.preview_timer.isActive():
self.preview_timer.start()
controller.seek_slider.blockSignals(False)
controller.volume_slider.blockSignals(False)
controller.media_info.is_playing = True
if not controller.media_info.is_background:
+ if controller.is_live:
+ controller.set_hide_mode(None)
display = self._define_display(controller)
display.hide_display(HideMode.Screen)
controller._set_theme(controller.service_item)
@@ -472,30 +481,35 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
Add a tick while the media is playing but only count if not paused
:param controller: The Controller to be processed
+ :return: Is the video still running?
"""
start_again = False
+ stopped = False
if controller.media_info.is_playing and controller.media_info.length > 0:
- if controller.media_info.timer > controller.media_info.length:
+ if controller.media_info.timer + TICK_TIME >= controller.media_info.length:
if controller.media_info.is_looping_playback:
start_again = True
else:
self.media_stop(controller)
- elif controller.media_info.timer > controller.media_info.length - TICK_TIME * 4:
- if not controller.media_info.is_looping_playback:
- display = self._define_display(controller)
- display.show_display()
+ stopped = True
controller.media_info.timer += TICK_TIME
- seconds = controller.media_info.timer // 1000
- minutes = seconds // 60
- seconds %= 60
- total_seconds = controller.media_info.length // 1000
- total_minutes = total_seconds // 60
- total_seconds %= 60
- controller.position_label.setText(' %02d:%02d / %02d:%02d' %
- (minutes, seconds, total_minutes, total_seconds))
+ self._update_seek_ui(controller)
+ else:
+ stopped = True
+
if start_again:
controller.seek_slider.setSliderPosition(0)
- self.media_play(controller, False)
+ return not stopped
+
+ def _update_seek_ui(self, controller):
+ seconds = controller.media_info.timer // 1000
+ minutes = seconds // 60
+ seconds %= 60
+ total_seconds = controller.media_info.length // 1000
+ total_minutes = total_seconds // 60
+ total_seconds %= 60
+ controller.position_label.setText(' %02d:%02d / %02d:%02d' %
+ (minutes, seconds, total_minutes, total_seconds))
def media_pause_msg(self, msg):
"""
@@ -517,12 +531,16 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param controller: The Controller to be paused
"""
+ self.log_debug(f'media_stop is_live:{controller.is_live}')
if controller.controller_type in self.current_media_players:
self.current_media_players[controller.controller_type].pause(controller)
controller.mediabar.actions['playbackPlay'].setVisible(True)
controller.mediabar.actions['playbackStop'].setDisabled(False)
controller.mediabar.actions['playbackPause'].setVisible(False)
controller.media_info.is_playing = False
+ # Add a tick to the timer to prevent it finishing the video before it can loop back or stop
+ # If the clip finishes, we hit a bug where we cannot start the video
+ controller.media_info.timer += TICK_TIME
controller.output_has_changed()
return True
return False
@@ -565,9 +583,19 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param controller: The controller that needs to be stopped
"""
+ self.log_debug(f'media_stop is_live:{controller.is_live}')
if controller.controller_type in self.current_media_players:
self.current_media_players[controller.controller_type].stop(controller)
- self.current_media_players[controller.controller_type].set_visible(controller, False)
+ if controller.is_live:
+ self.live_hide_timer.start(HIDE_DELAY_TIME)
+ if not controller.media_info.is_background:
+ display = self._define_display(controller)
+ if display.hide_mode == HideMode.Screen:
+ controller.set_hide_mode(HideMode.Blank)
+ else:
+ controller.set_hide_mode(display.hide_mode or HideMode.Blank)
+ else:
+ self._media_set_visibility(controller, False)
controller.seek_slider.setSliderPosition(0)
total_seconds = controller.media_info.length // 1000
total_minutes = total_seconds // 60
@@ -577,10 +605,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.mediabar.actions['playbackStop'].setDisabled(True)
controller.mediabar.actions['playbackPause'].setVisible(False)
controller.media_info.is_playing = False
- controller.media_info.timer = 1000
- controller.media_timer = 0
- display = self._define_display(controller)
- display.show_display()
+ controller.media_info.timer = 0
controller.output_has_changed()
return True
return False
@@ -631,33 +656,76 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
self.current_media_players[controller.controller_type].seek(controller, seek_value)
controller.media_info.timer = seek_value
+ self._update_seek_ui(controller)
- def media_reset(self, controller):
+ def media_reset(self, controller, delayed=False):
"""
Responds to the request to reset a loaded video
:param controller: The controller to use.
+ :param delayed: Should the controller briefly remain visible.
"""
+ self.log_debug('media_reset')
self.set_controls_visible(controller, False)
if controller.controller_type in self.current_media_players:
display = self._define_display(controller)
- display.show_display()
+ hide_mode = controller.get_hide_mode()
+ if hide_mode is None:
+ display.show_display()
+ else:
+ display.hide_display(hide_mode)
self.current_media_players[controller.controller_type].reset(controller)
- self.current_media_players[controller.controller_type].set_visible(controller, False)
- del self.current_media_players[controller.controller_type]
+ if controller.is_live and delayed:
+ self.live_kill_timer.start(HIDE_DELAY_TIME)
+ else:
+ if controller.is_live:
+ self.live_kill_timer.stop()
+ else:
+ self._media_set_visibility(controller, False)
+ del self.current_media_players[controller.controller_type]
- def media_hide(self, msg):
+ def media_hide_msg(self, msg):
"""
Hide the related video Widget
:param msg: First element is the boolean for Live indication
"""
is_live = msg[1]
- if not is_live:
+ self.media_hide(is_live)
+
+ def media_hide(self, is_live, delayed=False):
+ """
+ Pause and hide the related video Widget if is_live
+
+ :param is_live: Live indication
+ :param delayed: Should the controller briefly remain visible.
+ """
+ self.log_debug(f'media_hide is_live:{is_live}')
+ if not is_live or self.live_kill_timer.isActive():
return
if self.live_controller.controller_type in self.current_media_players and \
self.current_media_players[self.live_controller.controller_type].get_live_state() == MediaState.Playing:
- self.media_pause(self.live_controller)
- self.current_media_players[self.live_controller.controller_type].set_visible(self.live_controller, False)
+ if delayed:
+ self.live_hide_timer.start(HIDE_DELAY_TIME)
+ else:
+ self.media_pause(self.live_controller)
+ self._media_set_visibility(self.live_controller, False)
+
+ def _on_media_hide_live(self):
+ self.media_pause(self.live_controller)
+ self._media_set_visibility(self.live_controller, False)
+
+ def _on_media_kill_live(self):
+ self._media_set_visibility(self.live_controller, False)
+ del self.current_media_players[self.live_controller.controller_type]
+
+ def _media_set_visibility(self, controller, visible):
+ """
+ Set the live video Widget visibility
+ """
+ if controller.is_live:
+ self.live_hide_timer.stop()
+ visible = visible and controller.media_info.media_type is not MediaType.Audio
+ self.current_media_players[controller.controller_type].set_visible(controller, visible)
def media_blank(self, msg):
"""
@@ -668,13 +736,30 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
is_live = msg[1]
hide_mode = msg[2]
- if not is_live:
+ self.log_debug(f'media_blank is_live:{is_live}')
+ if not is_live or self.live_controller.controller_type not in self.current_media_players:
return
- Registry().execute('live_display_hide', hide_mode)
- if self.live_controller.controller_type in self.current_media_players and \
- self.current_media_players[self.live_controller.controller_type].get_live_state() == MediaState.Playing:
- self.media_pause(self.live_controller)
- self.current_media_players[self.live_controller.controller_type].set_visible(self.live_controller, False)
+ if self.live_kill_timer.isActive():
+ # If pressing blank when the video is being removed, remove it instantly
+ self._media_set_visibility(self.live_controller, False)
+ self.media_reset(self.live_controller)
+ return
+ if not self.live_controller.media_info.is_background:
+ Registry().execute('live_display_hide', hide_mode)
+ controller_type = self.live_controller.controller_type
+ playing = self.current_media_players[controller_type].get_live_state() == MediaState.Playing
+ if hide_mode == HideMode.Theme:
+ if not playing:
+ self.media_play(self.live_controller)
+ else:
+ self.live_hide_timer.stop()
+ else:
+ if hide_mode == HideMode.Screen:
+ if playing:
+ self.media_pause(self.live_controller)
+ self._media_set_visibility(self.live_controller, False)
+ else:
+ self.live_hide_timer.start(HIDE_DELAY_TIME)
def media_unblank(self, msg):
"""
@@ -683,24 +768,28 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param msg: First element is not relevant in this context
Second element is the boolean for Live indication
"""
- Registry().execute('live_display_show')
is_live = msg[1]
- if not is_live:
+ self.log_debug(f'media_blank is_live:{is_live}')
+ if not is_live or self.live_kill_timer.isActive():
return
- if self.live_controller.controller_type in self.current_media_players and \
- self.current_media_players[self.live_controller.controller_type].get_live_state() != \
- MediaState.Playing:
- if self.media_play(self.live_controller):
- self.current_media_players[self.live_controller.controller_type].set_visible(self.live_controller, True)
- # Start Timer for ui updates
- if not self.live_timer.isActive():
- self.live_timer.start()
+ Registry().execute('live_display_show')
+ if self.live_controller.controller_type in self.current_media_players:
+ if self.current_media_players[self.live_controller.controller_type].get_live_state() != \
+ MediaState.Playing:
+ self.media_play(self.live_controller)
+ else:
+ self._media_set_visibility(self.live_controller, True)
+ if not self.live_controller.media_info.is_background:
+ display = self._define_display(self.live_controller)
+ display.hide_display(HideMode.Screen)
def finalise(self):
"""
Reset all the media controllers when OpenLP shuts down
"""
self.live_timer.stop()
+ self.live_hide_timer.stop()
+ self.live_kill_timer.stop()
self.preview_timer.stop()
self.media_reset(self._display_controllers(DisplayControllerType.Live))
self.media_reset(self._display_controllers(DisplayControllerType.Preview))
diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py
index 7f47f2dd7..ce419947a 100644
--- a/openlp/core/ui/media/vlcplayer.py
+++ b/openlp/core/ui/media/vlcplayer.py
@@ -134,7 +134,6 @@ class VlcPlayer(MediaPlayer):
# creating an empty vlc media player
controller.vlc_media_player = controller.vlc_instance.media_player_new()
controller.vlc_widget.resize(controller.size())
- controller.vlc_widget.raise_()
controller.vlc_widget.hide()
# The media player has to be 'connected' to the QFrame.
# (otherwise a video would be displayed in it's own window)
@@ -245,22 +244,22 @@ class VlcPlayer(MediaPlayer):
start_time = 0
log.debug('vlc play')
if controller.is_live:
- if self.get_live_state() != MediaState.Paused and controller.media_info.start_time > 0:
- start_time = controller.media_info.start_time
+ if self.get_live_state() != MediaState.Paused and controller.media_info.timer > 0:
+ start_time = controller.media_info.timer
else:
- if self.get_preview_state() != MediaState.Paused and controller.media_info.start_time > 0:
- start_time = controller.media_info.start_time
+ if self.get_preview_state() != MediaState.Paused and controller.media_info.timer > 0:
+ start_time = controller.media_info.timer
threading.Thread(target=controller.vlc_media_player.play).start()
if not self.media_state_wait(controller, vlc.State.Playing):
return False
if controller.is_live:
- if self.get_live_state() != MediaState.Paused and controller.media_info.start_time > 0:
+ if self.get_live_state() != MediaState.Paused and controller.media_info.timer > 0:
log.debug('vlc play, start time set')
- start_time = controller.media_info.start_time
+ start_time = controller.media_info.timer
else:
- if self.get_preview_state() != MediaState.Paused and controller.media_info.start_time > 0:
+ if self.get_preview_state() != MediaState.Paused and controller.media_info.timer > 0:
log.debug('vlc play, start time set')
- start_time = controller.media_info.start_time
+ start_time = controller.media_info.timer
log.debug('mediatype: ' + str(controller.media_info.media_type))
# Set tracks for the optical device
if controller.media_info.media_type == MediaType.DVD and \
@@ -278,10 +277,10 @@ class VlcPlayer(MediaPlayer):
if controller.media_info.subtitle_track > 0:
controller.vlc_media_player.video_set_spu(controller.media_info.subtitle_track)
log.debug('vlc play, subtitle_track set: ' + str(controller.media_info.subtitle_track))
- if controller.media_info.start_time > 0:
- log.debug('vlc play, starttime set: ' + str(controller.media_info.start_time))
- start_time = controller.media_info.start_time
- controller.media_info.length = controller.media_info.end_time - controller.media_info.start_time
+ if controller.media_info.timer > 0:
+ log.debug('vlc play, starttime set: ' + str(controller.media_info.timer))
+ start_time = controller.media_info.timer
+ controller.media_info.length = controller.media_info.end_time - controller.media_info.timer
self.volume(controller, controller.media_info.volume)
if start_time > 0 and controller.vlc_media_player.is_seekable():
controller.vlc_media_player.set_time(int(start_time))
@@ -343,7 +342,6 @@ class VlcPlayer(MediaPlayer):
:param controller: The controller where the media is
"""
controller.vlc_media_player.stop()
- controller.vlc_widget.setVisible(False)
self.set_state(MediaState.Off, controller)
def set_visible(self, controller, status):
@@ -362,14 +360,6 @@ class VlcPlayer(MediaPlayer):
:param controller: Which Controller is running the show.
:param output_display: The display where the media is
"""
- vlc = get_vlc()
- # Stop video if playback is finished.
- if controller.vlc_media.get_state() == vlc.State.Ended:
- self.stop(controller)
- if controller.media_info.end_time > 0:
- if controller.vlc_media_player.get_time() > controller.media_info.end_time:
- self.stop(controller)
- self.set_visible(controller, False)
if not controller.seek_slider.isSliderDown():
controller.seek_slider.blockSignals(True)
if controller.media_info.media_type == MediaType.CD \
diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py
index 93a239222..6fdced0b1 100644
--- a/openlp/core/ui/slidecontroller.py
+++ b/openlp/core/ui/slidecontroller.py
@@ -525,6 +525,10 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
self.song_menu.setPopupMode(QtWidgets.QToolButton.InstantPopup)
self.song_menu.setMenu(QtWidgets.QMenu(translate('OpenLP.SlideController', 'Go To'), self.toolbar))
+ def _raise_displays(self):
+ for display in self.displays:
+ display.raise_()
+
def _slide_shortcut_activated(self):
"""
Called, when a shortcut has been activated to jump to a chorus, verse, etc.
@@ -946,8 +950,12 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
self._reset_blank(self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay))
self.info_label.setText(self.service_item.title)
self.slide_list = {}
- if old_item and old_item.requires_media():
- self.on_media_close()
+ if old_item:
+ # Close the old item if it's not to be used by the new sevice item
+ if not self.service_item.is_media() and not self.service_item.requires_media():
+ self.on_media_close()
+ if old_item.is_command() and not old_item.is_media():
+ Registry().execute('{name}_stop'.format(name=old_item.name.lower()), [old_item, self.is_live])
row = 0
width = self.main_window.control_splitter.sizes()[self.split]
if self.service_item.is_text():
@@ -989,26 +997,15 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
if self.service_item.is_command():
self.preview_display.load_verses(media_empty_song, True)
self.on_media_start(self.service_item)
- # Let media window init, then put webengine back on top
- self.application.process_events()
- for display in self.displays:
- display.raise_()
+ # Try to get display back on top of media window asap. If the media window
+ # is not loaded by the time _raise_displays is run, lyrics (web display)
+ # will be under the media window (not good).
+ QtCore.QTimer.singleShot(100, self._raise_displays)
+ QtCore.QTimer.singleShot(500, self._raise_displays)
+ QtCore.QTimer.singleShot(1000, self._raise_displays)
self.slide_selected(True)
if self.service_item.from_service:
self.preview_widget.setFocus()
- if old_item:
- # Close the old item after the new one is opened
- # This avoids the service theme/desktop flashing on screen
- # However opening a new item of the same type will automatically
- # close the previous, so make sure we don't close the new one.
- if old_item.is_command() and not self.service_item.is_command() or \
- old_item.is_command() and not old_item.is_media() and self.service_item.is_media():
- if old_item.is_media():
- self.on_media_close()
- else:
- Registry().execute('{name}_stop'.format(name=old_item.name.lower()), [old_item, self.is_live])
- if old_item.is_media() and not self.service_item.is_media():
- self.on_media_close()
if self.is_live:
Registry().execute('slidecontroller_{item}_started'.format(item=self.type_prefix), [self.service_item])
# Need to process events four times to get correct controller width
@@ -1528,7 +1525,9 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
:param item: The service item to be processed
"""
if State().check_preconditions('media'):
- if self.is_live and self.get_hide_mode() == HideMode.Theme:
+ if self.is_live and not item.is_media() and item.requires_media():
+ self.media_controller.load_video(self.controller_type, item, self.get_hide_mode())
+ elif self.is_live and self.get_hide_mode() == HideMode.Theme:
self.media_controller.load_video(self.controller_type, item, HideMode.Blank)
self.set_hide_mode(HideMode.Blank)
elif self.is_live or item.is_media():
@@ -1542,7 +1541,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
Respond to a request to close the Video if we have media
"""
if State().check_preconditions('media'):
- self.media_controller.media_reset(self)
+ self.media_controller.media_reset(self, delayed=True)
def _reset_blank(self, no_theme):
"""
diff --git a/openlp/core/ui/starttimeform.py b/openlp/core/ui/starttimeform.py
index ec9157e94..f1ee883c9 100644
--- a/openlp/core/ui/starttimeform.py
+++ b/openlp/core/ui/starttimeform.py
@@ -68,7 +68,7 @@ class StartTimeForm(QtWidgets.QDialog, Ui_StartTimeDialog, RegistryProperties):
start = self.hour_spin_box.value() * 3600 + self.minute_spin_box.value() * 60 + self.second_spin_box.value()
end = self.hour_finish_spin_box.value() * 3600 + \
self.minute_finish_spin_box.value() * 60 + self.second_finish_spin_box.value()
- if end > self.item['service_item'].media_length:
+ if end > self.item['service_item'].media_length // 1000:
critical_error_message_box(title=translate('OpenLP.StartTime_form', 'Time Validation Error'),
message=translate('OpenLP.StartTime_form',
'Finish time is set after the end of the media item'))
@@ -78,14 +78,15 @@ class StartTimeForm(QtWidgets.QDialog, Ui_StartTimeDialog, RegistryProperties):
message=translate('OpenLP.StartTime_form',
'Start time is after the finish time of the media item'))
return
- self.item['service_item'].start_time = start
- self.item['service_item'].end_time = end
+ self.item['service_item'].start_time = start * 1000
+ self.item['service_item'].end_time = end * 1000
return QtWidgets.QDialog.accept(self)
- def _time_split(self, seconds):
+ def _time_split(self, milliseconds):
"""
- Split time up into hours minutes and seconds from seconds
+ Split time up into hours minutes and seconds from milliseconds
"""
+ seconds = milliseconds // 1000
hours = seconds // 3600
seconds -= 3600 * hours
minutes = seconds // 60
diff --git a/tests/functional/openlp_core/ui/media/test_mediacontroller.py b/tests/functional/openlp_core/ui/media/test_mediacontroller.py
index 6955bf8a2..0a24ffbef 100644
--- a/tests/functional/openlp_core/ui/media/test_mediacontroller.py
+++ b/tests/functional/openlp_core/ui/media/test_mediacontroller.py
@@ -26,9 +26,9 @@ import pytest
from unittest.mock import MagicMock, patch
from openlp.core.common.registry import Registry
-from openlp.core.ui import DisplayControllerType
+from openlp.core.ui import DisplayControllerType, HideMode
from openlp.core.ui.media.mediacontroller import MediaController
-from openlp.core.ui.media import ItemMediaInfo
+from openlp.core.ui.media import ItemMediaInfo, MediaState
from tests.utils.constants import RESOURCE_PATH
@@ -60,6 +60,36 @@ def test_resize(media_env):
mocked_player.resize.assert_called_with(mocked_display)
+def test_load_video(media_env, settings):
+ """
+ Test that the load_video runs correctly
+ """
+ # GIVEN: A media controller and a service item
+ mocked_slide_controller = MagicMock()
+ mocked_service_item = MagicMock()
+ mocked_service_item.is_capable.return_value = False
+ settings.setValue('media/live volume', 1)
+ media_env.media_controller.current_media_players = MagicMock()
+ media_env.media_controller._check_file_type = MagicMock(return_value=True)
+ media_env.media_controller._display_controllers = MagicMock(return_value=mocked_slide_controller)
+ media_env.media_controller._define_display = MagicMock()
+ media_env.media_controller.media_reset = MagicMock()
+ media_env.media_controller.media_play = MagicMock()
+ media_env.media_controller.set_controls_visible = MagicMock()
+
+ # WHEN: load_video() is called
+ media_env.media_controller.load_video(DisplayControllerType.Live, mocked_service_item)
+
+ # THEN: The current controller's media should be reset
+ # The volume should be set from the settings
+ # The video should have autoplayed
+ # The controls should have been made visible
+ media_env.media_controller.media_reset.assert_called_once_with(mocked_slide_controller)
+ assert mocked_slide_controller.media_info.volume == 1
+ media_env.media_controller.media_play.assert_called_once_with(mocked_slide_controller)
+ media_env.media_controller.set_controls_visible.assert_called_once_with(mocked_slide_controller, True)
+
+
def test_check_file_type_null(media_env):
"""
Test that we don't try to play media when no players available
@@ -125,10 +155,10 @@ def test_media_play_msg(media_env):
# WHEN: media_play_msg() is called
with patch.object(media_env.media_controller, u'media_play') as mocked_media_play:
- media_env.media_controller.media_play_msg(message, False)
+ media_env.media_controller.media_play_msg(message)
# THEN: The underlying method is called
- mocked_media_play.assert_called_with(1, False)
+ mocked_media_play.assert_called_with(1)
def test_media_pause_msg(media_env):
@@ -161,6 +191,33 @@ def test_media_stop_msg(media_env):
mocked_media_stop.assert_called_with(1)
+def test_media_stop(media_env):
+ """
+ Test that the media controller takes the correct actions when stopping media
+ """
+ # GIVEN: A live media controller and a message with two elements
+ mocked_slide_controller = MagicMock()
+ mocked_media_player = MagicMock()
+ mocked_display = MagicMock(hide_mode=None)
+ mocked_slide_controller.controller_type = 'media player'
+ mocked_slide_controller.media_info = MagicMock(is_background=False)
+ mocked_slide_controller.set_hide_mode = MagicMock()
+ mocked_slide_controller.is_live = True
+ media_env.media_controller.current_media_players = {'media player': mocked_media_player}
+ media_env.media_controller.live_hide_timer = MagicMock()
+ media_env.media_controller._define_display = MagicMock(return_value=mocked_display)
+
+ # WHEN: media_stop() is called
+ result = media_env.media_controller.media_stop(mocked_slide_controller)
+
+ # THEN: Result should be successful, media player should be stopped and the hide timer should have started
+ # The controller's hide mode should be set to Blank
+ assert result is True
+ mocked_media_player.stop.assert_called_once_with(mocked_slide_controller)
+ media_env.media_controller.live_hide_timer.start.assert_called_once()
+ mocked_slide_controller.set_hide_mode.assert_called_once_with(HideMode.Blank)
+
+
def test_media_volume_msg(media_env):
"""
Test that the media controller responds to the request to change the volume
@@ -191,6 +248,59 @@ def test_media_seek_msg(media_env):
mocked_media_seek.assert_called_with(1, 800)
+def test_media_reset(media_env):
+ """
+ Test that the media controller conducts the correct actions when resetting
+ """
+ # GIVEN: A media controller, mocked slide controller, mocked media player and mocked display
+ mocked_slide_controller = MagicMock()
+ mocked_media_player = MagicMock()
+ mocked_display = MagicMock(hide_mode=None)
+ mocked_slide_controller.controller_type = 'media player'
+ mocked_slide_controller.media_info = MagicMock(is_background=False)
+ mocked_slide_controller.get_hide_mode = MagicMock(return_value=None)
+ mocked_slide_controller.is_live = False
+ media_env.media_controller.current_media_players = {'media player': mocked_media_player}
+ media_env.media_controller.live_hide_timer = MagicMock()
+ media_env.media_controller._define_display = MagicMock(return_value=mocked_display)
+ media_env.media_controller._media_set_visibility = MagicMock()
+
+ # WHEN: media_reset() is called
+ media_env.media_controller.media_reset(mocked_slide_controller)
+
+ # THEN: The display should be shown, media should be hidden and removed
+ mocked_display.show_display.assert_called_once_with()
+ media_env.media_controller._media_set_visibility.assert_called_once_with(mocked_slide_controller, False)
+ assert 'media player' not in media_env.media_controller.current_media_players
+
+
+def test_media_hide(media_env, registry):
+ """
+ Test that the media controller conducts the correct actions when hiding
+ """
+ # GIVEN: A media controller, mocked slide controller, mocked media player and mocked display
+ mocked_slide_controller = MagicMock()
+ mocked_media_player = MagicMock()
+ mocked_media_player.get_live_state.return_value = MediaState.Playing
+ mocked_slide_controller.controller_type = 'media player'
+ mocked_slide_controller.media_info = MagicMock(is_background=False)
+ mocked_slide_controller.get_hide_mode = MagicMock(return_value=None)
+ mocked_slide_controller.is_live = False
+ Registry().register('live_controller', mocked_slide_controller)
+ media_env.media_controller.current_media_players = {'media player': mocked_media_player}
+ media_env.media_controller.live_kill_timer = MagicMock(isActive=MagicMock(return_value=False))
+ media_env.media_controller._media_set_visibility = MagicMock()
+ media_env.media_controller.media_pause = MagicMock()
+
+ # WHEN: media_hide() is called
+ media_env.media_controller.media_hide(is_live=True)
+
+ # THEN: media should be paused and hidden, but the player should still exist
+ media_env.media_controller.media_pause.assert_called_once_with(mocked_slide_controller)
+ media_env.media_controller._media_set_visibility.assert_called_once_with(mocked_slide_controller, False)
+ assert 'media player' in media_env.media_controller.current_media_players
+
+
def test_media_length(media_env):
"""
Test the Media Info basic functionality
@@ -334,6 +444,7 @@ def test_media_play(media_env):
media_env.current_media_players = MagicMock()
Registry().register('settings', MagicMock())
media_env.live_timer = MagicMock()
+ media_env.live_hide_timer = MagicMock()
mocked_controller = MagicMock()
mocked_controller.media_info.is_background = False
@@ -343,4 +454,5 @@ def test_media_play(media_env):
# THEN: The web display should become transparent (only tests that the theme is reset here)
# And the function should return true to indicate success
assert result is True
+ media_env.live_hide_timer.stop.assert_called_once_with()
mocked_controller._set_theme.assert_called_once()
diff --git a/tests/functional/openlp_core/ui/media/test_vlcplayer.py b/tests/functional/openlp_core/ui/media/test_vlcplayer.py
index f11c67d47..03392c78d 100644
--- a/tests/functional/openlp_core/ui/media/test_vlcplayer.py
+++ b/tests/functional/openlp_core/ui/media/test_vlcplayer.py
@@ -122,7 +122,6 @@ def test_setup(MockedQtWidgets, mocked_get_vlc, mocked_is_macosx, mocked_is_win,
assert mocked_output_display.vlc_media_player == mocked_media_player_new
mocked_output_display.size.assert_called_with()
mocked_qframe.resize.assert_called_with((10, 10))
- mocked_qframe.raise_.assert_called_with()
mocked_qframe.hide.assert_called_with()
mocked_media_player_new.set_xwindow.assert_called_with(2)
assert vlc_player.has_own_widget is True
@@ -848,7 +847,7 @@ def test_reset():
# THEN: The media should be stopped and invisible
mocked_display.vlc_media_player.stop.assert_called_with()
- mocked_display.vlc_widget.setVisible.assert_called_with(False)
+ mocked_display.vlc_widget.setVisible.assert_not_called()
assert MediaState.Off == vlc_player.get_live_state()
@@ -886,15 +885,10 @@ def test_update_ui(mocked_get_vlc):
vlc_player = VlcPlayer(None)
# WHEN: update_ui() is called
- with patch.object(vlc_player, 'stop') as mocked_stop, \
- patch.object(vlc_player, 'set_visible') as mocked_set_visible:
- vlc_player.update_ui(mocked_controller, mocked_display)
+ vlc_player.update_ui(mocked_controller, mocked_display)
# THEN: Certain methods should be called
- mocked_stop.assert_called_with(mocked_controller)
- assert 2 == mocked_stop.call_count
mocked_controller.vlc_media_player.get_time.assert_called_with()
- mocked_set_visible.assert_called_with(mocked_controller, False)
mocked_controller.seek_slider.setSliderPosition.assert_called_with(400000)
expected_calls = [call(True), call(False)]
assert expected_calls == mocked_controller.seek_slider.blockSignals.call_args_list
@@ -921,12 +915,9 @@ def test_update_ui_dvd(mocked_get_vlc):
vlc_player = VlcPlayer(None)
# WHEN: update_ui() is called
- with patch.object(vlc_player, 'stop') as mocked_stop:
- vlc_player.update_ui(mocked_controller, mocked_display)
+ vlc_player.update_ui(mocked_controller, mocked_display)
# THEN: Certain methods should be called
- mocked_stop.assert_called_with(mocked_controller)
- assert 1 == mocked_stop.call_count
mocked_controller.vlc_media_player.get_time.assert_called_with()
mocked_controller.seek_slider.setSliderPosition.assert_called_with(200)
expected_calls = [call(True), call(False)]
diff --git a/tests/functional/openlp_core/ui/test_slidecontroller.py b/tests/functional/openlp_core/ui/test_slidecontroller.py
index 7a35ee61c..22dbdbf8c 100644
--- a/tests/functional/openlp_core/ui/test_slidecontroller.py
+++ b/tests/functional/openlp_core/ui/test_slidecontroller.py
@@ -899,11 +899,137 @@ def test_process_item(mocked_execute, registry, state_media):
slide_controller._process_item(mocked_media_item, 0)
# THEN: Registry.execute should have been called to stop the presentation
- assert 1 == mocked_execute.call_count, 'Execute should have been called 2 times'
+ assert 1 == mocked_execute.call_count, 'Execute should have been called once'
assert 'mocked_presentation_item_stop' == mocked_execute.call_args_list[0][0][0], \
'The presentation should have been stopped.'
+@patch.object(Registry, 'execute')
+def test_process_item_transition(mocked_execute, registry, state_media):
+ """
+ Test that the correct actions are taken when a media service-item is closed followed by a image service-item
+ """
+ # GIVEN: A mocked presentation service item, a mocked media service item, a mocked Registry.execute
+ # and a slide controller with many mocks.
+ # and the setting 'themes/item transitions' = True
+ mocked_pres_item = MagicMock()
+ mocked_pres_item.name = 'mocked_image_item'
+ mocked_pres_item.is_command.return_value = True
+ mocked_pres_item.is_media.return_value = True
+ mocked_pres_item.is_image.return_value = False
+ mocked_pres_item.from_service = False
+ mocked_pres_item.get_frames.return_value = []
+ mocked_media_item = MagicMock()
+ mocked_media_item.name = 'mocked_media_item'
+ mocked_media_item.get_transition_delay.return_value = 0
+ mocked_media_item.is_text.return_value = False
+ mocked_media_item.is_command.return_value = False
+ mocked_media_item.is_media.return_value = False
+ mocked_media_item.requires_media.return_value = False
+ mocked_media_item.is_image.return_value = True
+ mocked_media_item.from_service = False
+ mocked_media_item.get_frames.return_value = []
+ mocked_settings = MagicMock()
+ mocked_settings.value.return_value = True
+ mocked_main_window = MagicMock()
+ Registry().register('main_window', mocked_main_window)
+ Registry().register('media_controller', MagicMock())
+ Registry().register('application', MagicMock())
+ Registry().register('settings', mocked_settings)
+ slide_controller = SlideController(None)
+ slide_controller.service_item = mocked_pres_item
+ slide_controller.is_live = True
+ slide_controller._reset_blank = MagicMock()
+ slide_controller.preview_widget = MagicMock()
+ slide_controller.preview_display = MagicMock()
+ slide_controller.enable_tool_bar = MagicMock()
+ slide_controller.on_controller_size_changed = MagicMock()
+ slide_controller.on_media_start = MagicMock()
+ slide_controller.on_media_close = MagicMock()
+ slide_controller.slide_selected = MagicMock()
+ slide_controller.new_song_menu = MagicMock()
+ slide_controller.on_stop_loop = MagicMock()
+ slide_controller.info_label = MagicMock()
+ slide_controller.song_menu = MagicMock()
+ slide_controller.displays = [MagicMock()]
+ slide_controller.toolbar = MagicMock()
+ slide_controller.split = 0
+ slide_controller.type_prefix = 'test'
+ slide_controller.screen_capture = 'old_capture'
+
+ # WHEN: _process_item is called
+ slide_controller._process_item(mocked_media_item, 0)
+
+ # THEN: Registry.execute should have been called to start the live item
+ # Media should be closed
+ # Controller size change should be called (because it's a live item and the interface might have changed)
+ # The screen capture should have been reset to none
+ assert 1 == mocked_execute.call_count, 'Execute should have been called once'
+ slide_controller.on_media_close.assert_called_once_with()
+ slide_controller.on_controller_size_changed.assert_called_once()
+ assert slide_controller.screen_capture is None
+
+
+@patch.object(Registry, 'execute')
+def test_process_item_text(mocked_execute, registry, state_media):
+ """
+ Test that the correct actions are taken a text item is processed
+ """
+ # GIVEN: A mocked presentation service item, a mocked media service item, a mocked Registry.execute
+ # and a slide controller with many mocks.
+ # and the setting 'themes/item transitions' = True
+ mocked_media_item = MagicMock()
+ mocked_media_item.name = 'mocked_media_item'
+ mocked_media_item.get_transition_delay.return_value = 0
+ mocked_media_item.is_text.return_value = True
+ mocked_media_item.is_command.return_value = False
+ mocked_media_item.is_media.return_value = False
+ mocked_media_item.requires_media.return_value = False
+ mocked_media_item.is_image.return_value = False
+ mocked_media_item.from_service = False
+ mocked_media_item.get_frames.return_value = []
+ mocked_media_item.display_slides = [{'verse': 'Verse name'}]
+ mocked_settings = MagicMock()
+ mocked_settings.value.return_value = True
+ mocked_main_window = MagicMock()
+ Registry().register('main_window', mocked_main_window)
+ Registry().register('media_controller', MagicMock())
+ Registry().register('application', MagicMock())
+ Registry().register('settings', mocked_settings)
+ slide_controller = SlideController(None)
+ slide_controller.service_item = None
+ slide_controller.is_live = True
+ slide_controller._reset_blank = MagicMock()
+ slide_controller.preview_widget = MagicMock()
+ slide_controller.preview_display = MagicMock()
+ slide_controller.enable_tool_bar = MagicMock()
+ slide_controller.on_controller_size_changed = MagicMock()
+ slide_controller.on_media_start = MagicMock()
+ slide_controller.on_media_close = MagicMock()
+ slide_controller.slide_selected = MagicMock()
+ slide_controller.new_song_menu = MagicMock()
+ slide_controller.on_stop_loop = MagicMock()
+ slide_controller.info_label = MagicMock()
+ slide_controller.song_menu = MagicMock()
+ slide_controller.displays = [MagicMock()]
+ slide_controller.toolbar = MagicMock()
+ slide_controller.split = 0
+ slide_controller.type_prefix = 'test'
+ slide_controller.screen_capture = 'old_capture'
+
+ # WHEN: _process_item is called
+ slide_controller._process_item(mocked_media_item, 0)
+
+ # THEN: Registry.execute should have been called to start the live item
+ # Controller size change should be called (because it's a live item and the interface might have changed)
+ # The screen capture should have been reset to none
+ # The slide should have been added to the slide list with the correct index
+ assert 1 == mocked_execute.call_count, 'Execute should have been called once'
+ slide_controller.on_controller_size_changed.assert_called_once()
+ assert slide_controller.screen_capture is None
+ assert slide_controller.slide_list['Verse name'] == 0
+
+
@patch.object(Registry, 'execute')
def test_process_item_song_vlc(mocked_execute, registry, state_media):
"""
diff --git a/tests/interfaces/openlp_core/ui/test_starttimedialog.py b/tests/interfaces/openlp_core/ui/test_starttimedialog.py
index 0653ac8c5..20954a06e 100644
--- a/tests/interfaces/openlp_core/ui/test_starttimedialog.py
+++ b/tests/interfaces/openlp_core/ui/test_starttimedialog.py
@@ -65,9 +65,9 @@ def test_time_display(form):
"""
# GIVEN: A service item with with time
mocked_serviceitem = MagicMock()
- mocked_serviceitem.start_time = 61
- mocked_serviceitem.end_time = 3701
- mocked_serviceitem.media_length = 3701
+ mocked_serviceitem.start_time = 61000
+ mocked_serviceitem.end_time = 3701000
+ mocked_serviceitem.media_length = 3701000
# WHEN displaying the UI and pressing enter
form.item = {'service_item': mocked_serviceitem}
@@ -80,7 +80,7 @@ def test_time_display(form):
assert form.hour_spin_box.value() == 0
assert form.minute_spin_box.value() == 1
assert form.second_spin_box.value() == 1
- assert form.item['service_item'].start_time == 61, 'The start time should stay the same'
+ assert form.item['service_item'].start_time == 61000, 'The start time should stay the same'
# WHEN displaying the UI, changing the time to 2min 3secs and pressing enter
form.item = {'service_item': mocked_serviceitem}
@@ -95,4 +95,4 @@ def test_time_display(form):
assert form.hour_spin_box.value() == 0
assert form.minute_spin_box.value() == 2
assert form.second_spin_box.value() == 3
- assert form.item['service_item'].start_time == 123, 'The start time should have changed'
+ assert form.item['service_item'].start_time == 123000, 'The start time should have changed'