Merge branch 'sept-2020' into 'master'

Beta 1 bug fixes

See merge request openlp/openlp!249
This commit is contained in:
Tomas Groth 2020-10-04 19:20:11 +00:00
commit 2b927fc7b4
12 changed files with 251 additions and 40 deletions

View File

@ -34,6 +34,7 @@ class Poller(RegistryProperties):
def raw_poll(self): def raw_poll(self):
return { return {
'counter': self.live_controller.slide_count if self.live_controller.slide_count else 0,
'service': self.service_manager.service_id, 'service': self.service_manager.service_id,
'slide': self.live_controller.selected_row or 0, 'slide': self.live_controller.selected_row or 0,
'item': self.live_controller.service_item.unique_identifier if self.live_controller.service_item else '', 'item': self.live_controller.service_item.unique_identifier if self.live_controller.service_item else '',

View File

@ -33,6 +33,7 @@ log = logging.getLogger(__name__)
@service_views.route('/items') @service_views.route('/items')
def service_items(): def service_items():
log.debug('service/v2/items')
live_controller = Registry().get('live_controller') live_controller = Registry().get('live_controller')
service_items = [] service_items = []
if live_controller.service_item: if live_controller.service_item:
@ -61,6 +62,7 @@ def service_items():
@service_views.route('/show/<item_id>', methods=['POST']) @service_views.route('/show/<item_id>', methods=['POST'])
@login_required @login_required
def service_set(item_id=None): def service_set(item_id=None):
log.debug('service/v2/show')
data = request.json data = request.json
item_id = item_id or data.get('id') or data.get('uid') item_id = item_id or data.get('id') or data.get('uid')
if not item_id: if not item_id:
@ -81,6 +83,7 @@ def service_set(item_id=None):
@service_views.route('/progress', methods=['POST']) @service_views.route('/progress', methods=['POST'])
@login_required @login_required
def service_direction(): def service_direction():
log.debug('service/v2/progress')
ALLOWED_ACTIONS = ['next', 'previous'] ALLOWED_ACTIONS = ['next', 'previous']
data = request.json data = request.json
if not data: if not data:
@ -97,5 +100,6 @@ def service_direction():
@service_views.route('/new', methods=['GET']) @service_views.route('/new', methods=['GET'])
@login_required @login_required
def new_service(): def new_service():
log.debug('service/v2/new')
getattr(Registry().get('service_manager'), 'servicemanager_new_file').emit() getattr(Registry().get('service_manager'), 'servicemanager_new_file').emit()
return '', 204 return '', 204

View File

@ -31,7 +31,6 @@ import os
import sys import sys
import time import time
from datetime import datetime from datetime import datetime
from logging.handlers import RotatingFileHandler
from pathlib import Path from pathlib import Path
from shutil import copytree from shutil import copytree
from traceback import format_exception from traceback import format_exception
@ -307,7 +306,7 @@ def set_up_logging(log_path):
""" """
create_paths(log_path, do_not_log=True) create_paths(log_path, do_not_log=True)
file_path = log_path / 'openlp.log' file_path = log_path / 'openlp.log'
logfile = RotatingFileHandler(str(file_path), 'w', encoding='UTF-8', backupCount=2) logfile = logging.FileHandler(file_path, 'w', encoding='UTF-8')
logfile.setFormatter(logging.Formatter('%(asctime)s %(threadName)s %(name)-55s %(levelname)-8s %(message)s')) logfile.setFormatter(logging.Formatter('%(asctime)s %(threadName)s %(name)-55s %(levelname)-8s %(message)s'))
log.addHandler(logfile) log.addHandler(logfile)
if log.isEnabledFor(logging.DEBUG): if log.isEnabledFor(logging.DEBUG):

View File

@ -29,7 +29,7 @@ from openlp.core.common.registry import Registry
DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent', 'drag_enter_event', 'drop_event', 'on_controller_size_changed', DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent', 'drag_enter_event', 'drop_event', 'on_controller_size_changed',
'preview_size_changed', 'resizeEvent', 'eventFilter'] 'preview_size_changed', 'resizeEvent', 'eventFilter', 'tick']
class LogMixin(object): class LogMixin(object):

View File

@ -1001,8 +1001,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
self.application.set_normal_cursor() self.application.set_normal_cursor()
# if a warning has been shown within the last 5 seconds, skip showing again to avoid spamming user, # if a warning has been shown within the last 5 seconds, skip showing again to avoid spamming user,
# also do not show if the settings window is visible # also do not show if the settings window is visible
if not self.settings_form.isVisible() and \ if not self.settings_form.isVisible() and not self.screen_change_timestamp or \
not self.screen_change_timestamp or (datetime.now() - self.screen_change_timestamp).seconds > 5: self.screen_change_timestamp and (datetime.now() - self.screen_change_timestamp).seconds > 5:
QtWidgets.QMessageBox.warning(self, translate('OpenLP.MainWindow', 'Screen setup has changed'), QtWidgets.QMessageBox.warning(self, translate('OpenLP.MainWindow', 'Screen setup has changed'),
translate('OpenLP.MainWindow', translate('OpenLP.MainWindow',
'The screen setup has changed. ' 'The screen setup has changed. '

View File

@ -56,6 +56,11 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
""" """
The implementation of the Media Controller which manages how media is played. The implementation of the Media Controller which manages how media is played.
""" """
def __init__(self, parent=None):
"""
"""
super(MediaController, self).__init__(parent)
self.log_info('MediaController Initialising')
def setup(self): def setup(self):
self.vlc_player = None self.vlc_player = None
@ -66,8 +71,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
self.preview_timer = QtCore.QTimer() self.preview_timer = QtCore.QTimer()
self.preview_timer.setInterval(TICK_TIME) self.preview_timer.setInterval(TICK_TIME)
# Signals # Signals
self.live_timer.timeout.connect(self.media_state_live) self.live_timer.timeout.connect(self._media_state_live)
self.preview_timer.timeout.connect(self.media_state_preview) self.preview_timer.timeout.connect(self._media_state_preview)
Registry().register_function('playbackPlay', self.media_play_msg) Registry().register_function('playbackPlay', self.media_play_msg)
Registry().register_function('playbackPause', self.media_pause_msg) Registry().register_function('playbackPause', self.media_pause_msg)
Registry().register_function('playbackStop', self.media_stop_msg) Registry().register_function('playbackStop', self.media_stop_msg)
@ -135,7 +140,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
'OpenLP.MediaController', 'No Displays have been configured, so Live Media has been disabled')) 'OpenLP.MediaController', 'No Displays have been configured, so Live Media has been disabled'))
self.setup_display(self.preview_controller, True) self.setup_display(self.preview_controller, True)
def display_controllers(self, controller_type): def _display_controllers(self, controller_type):
""" """
Decides which controller to use. Decides which controller to use.
@ -145,35 +150,35 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
return self.live_controller return self.live_controller
return self.preview_controller return self.preview_controller
def media_state_live(self): def _media_state_live(self):
""" """
Check if there is a running Live media Player and do updating stuff (e.g. update the UI) 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)) display = self._define_display(self._display_controllers(DisplayControllerType.Live))
if DisplayControllerType.Live in self.current_media_players: if DisplayControllerType.Live in self.current_media_players:
self.current_media_players[DisplayControllerType.Live].resize(self.live_controller) self.current_media_players[DisplayControllerType.Live].resize(self.live_controller)
self.current_media_players[DisplayControllerType.Live].update_ui(self.live_controller, display) self.current_media_players[DisplayControllerType.Live].update_ui(self.live_controller, display)
self.tick(self.display_controllers(DisplayControllerType.Live)) self.tick(self._display_controllers(DisplayControllerType.Live))
if self.current_media_players[DisplayControllerType.Live].get_live_state() is not MediaState.Playing: if self.current_media_players[DisplayControllerType.Live].get_live_state() is not MediaState.Playing:
self.live_timer.stop() self.live_timer.stop()
else: else:
self.live_timer.stop() self.live_timer.stop()
self.media_stop(self.display_controllers(DisplayControllerType.Live)) self.media_stop(self._display_controllers(DisplayControllerType.Live))
def media_state_preview(self): def _media_state_preview(self):
""" """
Check if there is a running Preview media Player and do updating stuff (e.g. update the UI) 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)) display = self._define_display(self._display_controllers(DisplayControllerType.Preview))
if DisplayControllerType.Preview in self.current_media_players: if DisplayControllerType.Preview in self.current_media_players:
self.current_media_players[DisplayControllerType.Preview].resize(self.live_controller) self.current_media_players[DisplayControllerType.Preview].resize(self.live_controller)
self.current_media_players[DisplayControllerType.Preview].update_ui(self.preview_controller, display) self.current_media_players[DisplayControllerType.Preview].update_ui(self.preview_controller, display)
self.tick(self.display_controllers(DisplayControllerType.Preview)) self.tick(self._display_controllers(DisplayControllerType.Preview))
if self.current_media_players[DisplayControllerType.Preview].get_preview_state() is not MediaState.Playing: if self.current_media_players[DisplayControllerType.Preview].get_preview_state() is not MediaState.Playing:
self.preview_timer.stop() self.preview_timer.stop()
else: else:
self.preview_timer.stop() self.preview_timer.stop()
self.media_stop(self.display_controllers(DisplayControllerType.Preview)) self.media_stop(self._display_controllers(DisplayControllerType.Preview))
def setup_display(self, controller, preview): def setup_display(self, controller, preview):
""" """
@ -218,7 +223,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param hidden: The player which is doing the playing :param hidden: The player which is doing the playing
""" """
is_valid = True is_valid = True
controller = self.display_controllers(source) controller = self._display_controllers(source)
# stop running videos # stop running videos
self.media_reset(controller) self.media_reset(controller)
controller.media_info = ItemMediaInfo() controller.media_info = ItemMediaInfo()
@ -246,27 +251,27 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
if controller.is_live: if controller.is_live:
# if this is an optical device use special handling # if this is an optical device use special handling
if service_item.is_capable(ItemCapabilities.IsOptical): if service_item.is_capable(ItemCapabilities.IsOptical):
log.debug('video is optical and live') self.log_debug('video is optical and live')
path = service_item.get_frame_path() path = service_item.get_frame_path()
(name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path) (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path)
is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display,
controller) controller)
elif service_item.is_capable(ItemCapabilities.CanStream): elif service_item.is_capable(ItemCapabilities.CanStream):
log.debug('video is stream and live') self.log_debug('video is stream and live')
path = service_item.get_frames()[0]['path'] path = service_item.get_frames()[0]['path']
controller.media_info.media_type = MediaType.Stream controller.media_info.media_type = MediaType.Stream
(name, mrl, options) = parse_stream_path(path) (name, mrl, options) = parse_stream_path(path)
controller.media_info.file_info = (mrl, options) controller.media_info.file_info = (mrl, options)
is_valid = self._check_file_type(controller, display) is_valid = self._check_file_type(controller, display)
else: else:
log.debug('video is not optical or stream, but live') self.log_debug('video is not optical or stream, but live')
controller.media_info.length = service_item.media_length controller.media_info.length = service_item.media_length
is_valid = self._check_file_type(controller, display) is_valid = self._check_file_type(controller, display)
controller.media_info.start_time = service_item.start_time controller.media_info.start_time = service_item.start_time
controller.media_info.end_time = service_item.end_time controller.media_info.end_time = service_item.end_time
elif controller.preview_display: elif controller.preview_display:
if service_item.is_capable(ItemCapabilities.IsOptical): if service_item.is_capable(ItemCapabilities.IsOptical):
log.debug('video is optical and preview') self.log_debug('video is optical and preview')
path = service_item.get_frame_path() path = service_item.get_frame_path()
(name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path) (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path)
is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display,
@ -278,7 +283,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.media_info.file_info = (mrl, options) controller.media_info.file_info = (mrl, options)
is_valid = self._check_file_type(controller, display) is_valid = self._check_file_type(controller, display)
else: else:
log.debug('video is not optical or stream, but preview') self.log_debug('video is not optical or stream, but preview')
controller.media_info.length = service_item.media_length controller.media_info.length = service_item.media_length
is_valid = self._check_file_type(controller, display) is_valid = self._check_file_type(controller, display)
if not is_valid: if not is_valid:
@ -286,7 +291,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'), critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'),
translate('MediaPlugin.MediaItem', 'Unsupported File')) translate('MediaPlugin.MediaItem', 'Unsupported File'))
return False return False
log.debug('video media type: {tpe} '.format(tpe=str(controller.media_info.media_type))) self.log_debug('video media type: {tpe} '.format(tpe=str(controller.media_info.media_type)))
autoplay = False autoplay = False
if service_item.requires_media(): if service_item.requires_media():
autoplay = True autoplay = True
@ -305,7 +310,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
translate('MediaPlugin.MediaItem', 'Unsupported File')) translate('MediaPlugin.MediaItem', 'Unsupported File'))
return False return False
self.set_controls_visible(controller, True) self.set_controls_visible(controller, True)
log.debug('use {nm} controller'.format(nm=self.current_media_players[controller.controller_type].display_name)) self.log_debug('use {nm} controller'.
format(nm=self.current_media_players[controller.controller_type].display_name))
return True return True
@staticmethod @staticmethod
@ -417,7 +423,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
""" """
Responds to the request to play a loaded video from the web. Responds to the request to play a loaded video from the web.
""" """
return self.media_play(Registry().get('live_controller'), False) return self.media_play(self.live_controller)
def media_play(self, controller, first_time=True): def media_play(self, controller, first_time=True):
""" """
@ -426,6 +432,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param controller: The controller to be played :param controller: The controller to be played
:param first_time: :param first_time:
""" """
self.log_debug(f"media_play with {first_time}")
controller.seek_slider.blockSignals(True) controller.seek_slider.blockSignals(True)
controller.volume_slider.blockSignals(True) controller.volume_slider.blockSignals(True)
display = self._define_display(controller) display = self._define_display(controller)
@ -457,6 +464,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
display.hide_display(HideMode.Screen) display.hide_display(HideMode.Screen)
controller._set_theme(controller.service_item) controller._set_theme(controller.service_item)
display.load_verses([{"verse": "v1", "text": "", "footer": " "}]) display.load_verses([{"verse": "v1", "text": "", "footer": " "}])
controller.output_has_changed()
return True return True
def tick(self, controller): def tick(self, controller):
@ -501,7 +509,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
""" """
Responds to the request to pause a loaded video from the web. Responds to the request to pause a loaded video from the web.
""" """
return self.media_pause(Registry().get('live_controller')) return self.media_pause(self.live_controller)
def media_pause(self, controller): def media_pause(self, controller):
""" """
@ -515,6 +523,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.mediabar.actions['playbackStop'].setDisabled(False) controller.mediabar.actions['playbackStop'].setDisabled(False)
controller.mediabar.actions['playbackPause'].setVisible(False) controller.mediabar.actions['playbackPause'].setVisible(False)
controller.media_info.is_playing = False controller.media_info.is_playing = False
controller.output_has_changed()
return True return True
return False return False
@ -548,7 +557,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
""" """
Responds to the request to stop a loaded video from the web. Responds to the request to stop a loaded video from the web.
""" """
return self.media_stop(Registry().get('live_controller')) return self.media_stop(self.live_controller)
def media_stop(self, controller): def media_stop(self, controller):
""" """
@ -572,6 +581,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.media_timer = 0 controller.media_timer = 0
display = self._define_display(controller) display = self._define_display(controller)
display.show_display() display.show_display()
controller.output_has_changed()
return True return True
return False return False
@ -592,7 +602,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param controller: The Controller to use :param controller: The Controller to use
:param volume: The volume to be set :param volume: The volume to be set
""" """
log.debug('media_volume {vol}'.format(vol=volume)) self.log_debug(f'media_volume {volume}')
if controller.is_live: if controller.is_live:
self.settings.setValue('media/live volume', volume) self.settings.setValue('media/live volume', volume)
else: else:
@ -692,8 +702,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
""" """
self.live_timer.stop() self.live_timer.stop()
self.preview_timer.stop() self.preview_timer.stop()
self.media_reset(self.display_controllers(DisplayControllerType.Live)) self.media_reset(self._display_controllers(DisplayControllerType.Live))
self.media_reset(self.display_controllers(DisplayControllerType.Preview)) self.media_reset(self._display_controllers(DisplayControllerType.Preview))
@staticmethod @staticmethod
def _define_display(controller): def _define_display(controller):

View File

@ -41,6 +41,7 @@ def media_play():
if live.service_item.name != 'media': if live.service_item.name != 'media':
abort(400) abort(400)
status = live.mediacontroller_live_play.emit() status = live.mediacontroller_live_play.emit()
log.debug(f'media_play return {status}')
if status: if status:
return '', 202 return '', 202
abort(400) abort(400)
@ -54,6 +55,7 @@ def media_pause():
if live.service_item.name != 'media': if live.service_item.name != 'media':
abort(400) abort(400)
status = live.mediacontroller_live_pause.emit() status = live.mediacontroller_live_pause.emit()
log.debug(f'media_pause return {status}')
if status: if status:
return '', 202 return '', 202
abort(400) abort(400)
@ -67,6 +69,7 @@ def media_stop():
if live.service_item.name != 'media': if live.service_item.name != 'media':
abort(400) abort(400)
status = live.mediacontroller_live_stop.emit() status = live.mediacontroller_live_stop.emit()
log.debug(f'media_stop return {status}')
if status: if status:
return '', 202 return '', 202
abort(400) abort(400)

View File

@ -171,7 +171,7 @@ class VlcPlayer(MediaPlayer):
if not controller.vlc_instance: if not controller.vlc_instance:
return False return False
vlc = get_vlc() vlc = get_vlc()
log.debug('load vid in Vlc Controller') log.debug('load video in VLC Controller')
path = None path = None
if file and not controller.media_info.media_type == MediaType.Stream: if file and not controller.media_info.media_type == MediaType.Stream:
path = os.path.normcase(file) path = os.path.normcase(file)

View File

@ -129,9 +129,6 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties):
tab_widget = self.stacked_layout.widget(tab_index) tab_widget = self.stacked_layout.widget(tab_index)
if tab_widget.tab_title == plugin_name: if tab_widget.tab_title == plugin_name:
tab_widget.save() tab_widget.save()
# if the image background has been changed we need to regenerate the image cache
if 'images_config_updated' in self.processes or 'config_screen_changed' in self.processes:
self.register_post_process('images_regenerate')
# Now lets process all the post save handlers # Now lets process all the post save handlers
while self.processes: while self.processes:
Registry().execute(self.processes.pop(0)) Registry().execute(self.processes.pop(0))

View File

@ -204,6 +204,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
self.update_slide_limits() self.update_slide_limits()
self.panel = QtWidgets.QWidget(self.main_window.control_splitter) self.panel = QtWidgets.QWidget(self.main_window.control_splitter)
self.slide_list = {} self.slide_list = {}
self.slide_count = 0
self.ignore_toolbar_resize_events = False self.ignore_toolbar_resize_events = False
# Layout for holding panel # Layout for holding panel
self.panel_layout = QtWidgets.QVBoxLayout(self.panel) self.panel_layout = QtWidgets.QVBoxLayout(self.panel)
@ -1242,6 +1243,13 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
self.preview_display.set_single_image('#000', image_path) self.preview_display.set_single_image('#000', image_path)
else: else:
self.preview_display.go_to_slide(self.selected_row) self.preview_display.go_to_slide(self.selected_row)
self.output_has_changed()
def output_has_changed(self):
"""
The output has changed so we need to poke to POLL Websocket.
"""
self.slide_count += 1
def display_maindisplay(self): def display_maindisplay(self):
""" """
@ -1462,11 +1470,15 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
def on_clear(self): def on_clear(self):
""" """
Clear the preview bar. Clear the preview bar and other bits.
""" """
self.preview_widget.clear_list() self.preview_widget.clear_list()
self.toolbar.set_widget_visible('editSong', False) self.service_item = None
self.toolbar.set_widget_visible('clear', False) if self.is_live:
self.mediabar.setVisible(False)
else:
self.toolbar.set_widget_visible('editSong', False)
self.toolbar.set_widget_visible('clear', False)
def on_preview_add_to_service(self): def on_preview_add_to_service(self):
""" """

View File

@ -219,7 +219,7 @@ def test_on_media_play(media_env):
media_env.media_controller.on_media_play() media_env.media_controller.on_media_play()
# The mocked live controller should be called # The mocked live controller should be called
media_env.media_controller.media_play.assert_called_once_with(mocked_live_controller, False) media_env.media_controller.media_play.assert_called_once_with(mocked_live_controller)
def test_on_media_pause(media_env): def test_on_media_pause(media_env):
@ -265,7 +265,7 @@ def test_display_controllers_live(media_env):
Registry().register('preview_controller', mocked_preview_controller) Registry().register('preview_controller', mocked_preview_controller)
# WHEN: display_controllers() is called with DisplayControllerType.Live # WHEN: display_controllers() is called with DisplayControllerType.Live
controller = media_env.media_controller.display_controllers(DisplayControllerType.Live) controller = media_env.media_controller._display_controllers(DisplayControllerType.Live)
# THEN: the controller should be the live controller # THEN: the controller should be the live controller
assert controller is mocked_live_controller assert controller is mocked_live_controller
@ -282,7 +282,7 @@ def test_display_controllers_preview(media_env):
Registry().register('preview_controller', mocked_preview_controller) Registry().register('preview_controller', mocked_preview_controller)
# WHEN: display_controllers() is called with DisplayControllerType.Preview # WHEN: display_controllers() is called with DisplayControllerType.Preview
controller = media_env.media_controller.display_controllers(DisplayControllerType.Preview) controller = media_env.media_controller._display_controllers(DisplayControllerType.Preview)
# THEN: the controller should be the live controller # THEN: the controller should be the live controller
assert controller is mocked_preview_controller assert controller is mocked_preview_controller

View File

@ -0,0 +1,185 @@
# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2020 OpenLP Developers #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
Package to test the openlp.core.ui.media.remote package.
"""
import pytest
from unittest.mock import MagicMock
from openlp.core.api import app as flask_app
from openlp.core.common.registry import Registry
from openlp.core.ui.media.remote import media_play, media_pause, media_stop, register_views
def test_media_play_valid(settings):
# GIVEN: A loaded service with media set up
settings.setValue('api/authentication enabled', False)
service_item = MagicMock()
service_item.name = 'media'
live_controller = MagicMock()
live_controller.service_item = service_item
Registry().register('live_controller', live_controller)
# WHEN: Play is pressed
ret = media_play()
# THEN: We should have a successful outcome
assert live_controller.mediacontroller_live_play.emit.call_count == 1, 'Should have be called once'
assert ret[1] == 202, 'Should be a valid call'
def test_media_play_not_media(settings):
# GIVEN: A loaded service with songs not media
settings.setValue('api/authentication enabled', False)
service_item = MagicMock()
service_item.name = 'songs'
live_controller = MagicMock()
live_controller.service_item = service_item
Registry().register('live_controller', live_controller)
# WHEN: Play is pressed
with pytest.raises(Exception) as e:
_ = media_play()
# THEN: We should have a rejected outcome
assert e.value.code == 400, 'Should be an invalid call'
assert live_controller.mediacontroller_live_play.emit.call_count == 0, 'Should have be not have been called'
def test_media_play_call_fail(settings):
# GIVEN: A loaded service with no media_controller
settings.setValue('api/authentication enabled', False)
service_item = MagicMock()
service_item.name = 'media'
live_controller = MagicMock()
live_controller.service_item = service_item
live_controller.mediacontroller_live_play.emit.return_value = False
Registry().register('live_controller', live_controller)
# WHEN: Play is pressed
with pytest.raises(Exception) as e:
_ = media_play()
# THEN: We should have a rejected outcome
assert e.value.code == 400, 'Should be an invalid call'
assert live_controller.mediacontroller_live_play.emit.call_count == 1, 'Should have be called once'
def test_media_pause_valid(settings):
# GIVEN: A loaded service with media set up
settings.setValue('api/authentication enabled', False)
service_item = MagicMock()
service_item.name = 'media'
live_controller = MagicMock()
live_controller.service_item = service_item
Registry().register('live_controller', live_controller)
# WHEN: Pause is pressed
ret = media_pause()
# THEN: We should have a successful outcome
assert live_controller.mediacontroller_live_pause.emit.call_count == 1, 'Should have be called once'
assert ret[1] == 202, 'Should be a valid call'
def test_media_pause_not_media(settings):
# GIVEN: A loaded service with songs not media
settings.setValue('api/authentication enabled', False)
service_item = MagicMock()
service_item.name = 'songs'
live_controller = MagicMock()
live_controller.service_item = service_item
Registry().register('live_controller', live_controller)
# WHEN: Pause is pressed
with pytest.raises(Exception) as e:
_ = media_pause()
# THEN: We should have a rejected outcome
assert e.value.code == 400, 'Should be an invalid call'
assert live_controller.mediacontroller_live_pause.emit.call_count == 0, 'Should have be not have been called'
def test_media_pause_call_fail(settings):
# GIVEN: A loaded service with no media_controller
settings.setValue('api/authentication enabled', False)
service_item = MagicMock()
service_item.name = 'media'
live_controller = MagicMock()
live_controller.service_item = service_item
live_controller.mediacontroller_live_pause.emit.return_value = False
Registry().register('live_controller', live_controller)
# WHEN: Pause is pressed
with pytest.raises(Exception) as e:
_ = media_pause()
# THEN: We should have a rejected outcome
assert e.value.code == 400, 'Should be an invalid call'
assert live_controller.mediacontroller_live_pause.emit.call_count == 1, 'Should have be called once'
def test_media_stop_valid(settings):
# GIVEN: A loaded service with media set up
settings.setValue('api/authentication enabled', False)
service_item = MagicMock()
service_item.name = 'media'
live_controller = MagicMock()
live_controller.service_item = service_item
Registry().register('live_controller', live_controller)
# WHEN: Stop is pressed
ret = media_stop()
# THEN: We should have a successful outcome
assert live_controller.mediacontroller_live_stop.emit.call_count == 1, 'Should have be called once'
assert ret[1] == 202, 'Should be a valid call'
def test_media_stop_not_media(settings):
# GIVEN: A loaded service with songs not media
settings.setValue('api/authentication enabled', False)
service_item = MagicMock()
service_item.name = 'songs'
live_controller = MagicMock()
live_controller.service_item = service_item
Registry().register('live_controller', live_controller)
# WHEN: Stop is pressed
with pytest.raises(Exception) as e:
_ = media_stop()
# THEN: We should have a rejected outcome
assert e.value.code == 400, 'Should be an invalid call'
assert live_controller.mediacontroller_live_stop.emit.call_count == 0, 'Should have be not have been called'
def test_media_stop_call_fail(settings):
# GIVEN: A loaded service with no media_controller
settings.setValue('api/authentication enabled', False)
service_item = MagicMock()
service_item.name = 'media'
live_controller = MagicMock()
live_controller.service_item = service_item
live_controller.mediacontroller_live_stop.emit.return_value = False
Registry().register('live_controller', live_controller)
# WHEN: Stop is pressed
with pytest.raises(Exception) as e:
_ = media_stop()
# THEN: We should have a rejected outcome
assert e.value.code == 400, 'Should be an invalid call'
assert live_controller.mediacontroller_live_stop.emit.call_count == 1, 'Should have be called once'
def test_register():
# GIVEN: A blank setup
# WHEN: I register the views for media
register_views()
# THEN: The following elements should have been defined.
assert len(flask_app.blueprints['v2-media-controller'].deferred_functions) == 3, \
'we should have 3 functions defined'
assert 'v2-media-controller.media_play' in flask_app.view_functions, 'we should the play defined'
assert 'v2-media-controller.media_pause' in flask_app.view_functions, 'we should the pause defined'
assert 'v2-media-controller.media_stop' in flask_app.view_functions, 'we should the stop defined'