Fix song flash

This commit is contained in:
robbie jackson 2021-11-07 00:52:53 +00:00 committed by Raoul Snyman
parent 59f625bd8f
commit aff97c0e27
4 changed files with 78 additions and 16 deletions

View File

@ -262,6 +262,7 @@ var Display = {
_animationState: AnimationState.NoAnimation,
_doTransitions: false,
_doItemTransitions: false,
_skipNextTransition: false,
_themeApplied: true,
_revealConfig: {
margin: 0.0,
@ -365,7 +366,7 @@ var Display = {
Display.applyTheme(new_slides, is_text);
Display._slidesContainer.prepend(new_slides);
var currentSlide = Reveal.getIndices();
if (Display._doItemTransitions && Display._slidesContainer.children.length >= 2) {
if (Display._doItemTransitions && Display._slidesContainer.children.length >= 2 && !Display._skipNextTransition) {
// Set the slide one section ahead so we'll stay on the old slide after reinit
Reveal.slide(1, currentSlide.v);
Display.reinit();
@ -375,6 +376,7 @@ var Display = {
Reveal.slide(0, currentSlide.v);
Reveal.sync();
Display._removeLastSection();
Display._skipNextTransition = false;
}
},
/**
@ -1121,6 +1123,18 @@ var Display = {
}
}
},
/**
* Called whenever openlp wants to finish completely with the current text/image slides
* because a different window (eg presentation or vlc) is going to be displaying the next item
* and we don't want any flashbacks to the current slide contents
*/
finishWithCurrentItem: function () {
Display.setTextSlide('');
var documentBody = $("body")[0];
documentBody.style.opacity = 1;
Display._skipNextTransition = true;
displayWatcher.pleaseRepaint();
},
/**
* Return the video types supported by the video tag
*/

View File

@ -51,6 +51,10 @@ class DisplayWatcher(QtCore.QObject):
"""
initialised = QtCore.pyqtSignal(bool)
def __init__(self, parent):
super().__init__()
self._display_window = parent
@QtCore.pyqtSlot(bool)
def setInitialised(self, is_initialised):
"""
@ -59,6 +63,13 @@ class DisplayWatcher(QtCore.QObject):
log.info('Display is initialised: {init}'.format(init=is_initialised))
self.initialised.emit(is_initialised)
@QtCore.pyqtSlot()
def pleaseRepaint(self):
"""
Called from the js in the webengine view when it's requesting a repaint by Qt
"""
self._display_window.webview.update()
class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin):
"""
@ -451,6 +462,16 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin):
if self.is_display and self.hide_mode == HideMode.Screen:
self.setVisible(False)
def finish_with_current_item(self):
"""
This is called whenever the song/image display is followed by eg a presentation or video which
has its own display.
This function ensures that the current item won't flash momentarily when the webengineview
is displayed for a subsequent song or image.
"""
self.run_javascript('Display.finishWithCurrentItem();', True)
self.webview.update()
def set_scale(self, scale):
"""
Set the HTML scale

View File

@ -945,23 +945,19 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
[self.service_item, self.is_live, self._current_hide_mode, slide_no])
else:
self._set_theme(self.service_item)
# Reset blanking if needed
if old_item and self.is_live and (old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay) or
self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay)):
self._reset_blank(self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay))
self.info_label.setText(self.service_item.title)
self.slide_list = {}
if old_item:
# Close the old item if it's not to be used by the new service 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])
# if the old item was media which hid the main display then need to reset it if new service item uses it
if self.is_live and self._current_hide_mode is None and old_item.is_media() and not \
old_item.requires_media() and not self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay):
for display in self.displays:
display.show_display()
# if the old item was text or images (ie doesn't provide its own display) and the new item provides its own
# display then clear out the old item so that it doesn't flash momentarily when next showing text/image
# An item provides its own display if the capability ProvidesOwnDisplay is set or if it's a media item
old_item_provides_own_display = old_item and (old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay) or
old_item.is_media())
new_item_provides_own_display = (self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay) or
self.service_item.is_media())
if self.is_live and not old_item_provides_own_display and new_item_provides_own_display:
for display in self.displays:
display.finish_with_current_item()
# Prepare the new slides for text / image items
row = 0
width = self.main_window.control_splitter.sizes()[self.split]
if self.service_item.is_text():
@ -997,7 +993,23 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
row += 1
self.slide_list[str(row)] = row - 1
self.preview_widget.replace_service_item(self.service_item, width, slide_no)
# Tidy up aspects associated with the old item
if old_item:
# Close the old item if it's not to be used by the new service 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])
# if the old item was media which hid the main display then need to reset it if new service item uses it
if self.is_live and self._current_hide_mode is None and old_item.is_media() and not \
old_item.requires_media() and not self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay):
for display in self.displays:
display.show_display()
self.enable_tool_bar(self.service_item)
# Reset blanking if needed
if old_item and self.is_live and (old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay) or
self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay)):
self._reset_blank(self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay))
if self.service_item.is_media() or self.service_item.requires_media():
self._set_theme(self.service_item)
if self.service_item.is_command():

View File

@ -622,3 +622,18 @@ def test_display_watcher_set_initialised():
# THEN: initialised should have been emitted
mocked_initialised.emit.assert_called_once_with(True)
def test_display_watcher_please_repaint(display_window_env, mock_settings):
"""
Test that the repaint is initiated
"""
# GIVEN: A DisplayWindow instance with mocked out webview
display_window = DisplayWindow()
display_window.webview = MagicMock()
# WHEN: pleaseRepaint is called on the DisplayWatcher
display_window.display_watcher.pleaseRepaint()
# THEN: Qt update for the webview should have been triggered
assert display_window.webview.update.call_count == 1