diff --git a/openlp/core/api/poll.py b/openlp/core/api/poll.py index 69f7f05ea..f39969535 100644 --- a/openlp/core/api/poll.py +++ b/openlp/core/api/poll.py @@ -34,6 +34,7 @@ class Poller(RegistryProperties): def raw_poll(self): return { + 'counter': self.live_controller.slide_count if self.live_controller.slide_count else 0, 'service': self.service_manager.service_id, 'slide': self.live_controller.selected_row or 0, 'item': self.live_controller.service_item.unique_identifier if self.live_controller.service_item else '', diff --git a/openlp/core/api/versions/v2/service.py b/openlp/core/api/versions/v2/service.py index 50fba7e70..9b9ecad70 100644 --- a/openlp/core/api/versions/v2/service.py +++ b/openlp/core/api/versions/v2/service.py @@ -33,6 +33,7 @@ log = logging.getLogger(__name__) @service_views.route('/items') def service_items(): + log.debug('service/v2/items') live_controller = Registry().get('live_controller') service_items = [] if live_controller.service_item: @@ -61,6 +62,7 @@ def service_items(): @service_views.route('/show/', methods=['POST']) @login_required def service_set(item_id=None): + log.debug('service/v2/show') data = request.json item_id = item_id or data.get('id') or data.get('uid') if not item_id: @@ -81,6 +83,7 @@ def service_set(item_id=None): @service_views.route('/progress', methods=['POST']) @login_required def service_direction(): + log.debug('service/v2/progress') ALLOWED_ACTIONS = ['next', 'previous'] data = request.json if not data: @@ -97,5 +100,6 @@ def service_direction(): @service_views.route('/new', methods=['GET']) @login_required def new_service(): + log.debug('service/v2/new') getattr(Registry().get('service_manager'), 'servicemanager_new_file').emit() return '', 204 diff --git a/openlp/core/app.py b/openlp/core/app.py index 51c24183e..e0df33ee1 100644 --- a/openlp/core/app.py +++ b/openlp/core/app.py @@ -31,7 +31,6 @@ import os import sys import time from datetime import datetime -from logging.handlers import RotatingFileHandler from pathlib import Path from shutil import copytree from traceback import format_exception @@ -307,7 +306,7 @@ def set_up_logging(log_path): """ create_paths(log_path, do_not_log=True) 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')) log.addHandler(logfile) if log.isEnabledFor(logging.DEBUG): diff --git a/openlp/core/common/mixins.py b/openlp/core/common/mixins.py index 02e58d8e1..ff44d658b 100644 --- a/openlp/core/common/mixins.py +++ b/openlp/core/common/mixins.py @@ -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', - 'preview_size_changed', 'resizeEvent', 'eventFilter'] + 'preview_size_changed', 'resizeEvent', 'eventFilter', 'tick'] class LogMixin(object): diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 754c8f9d3..d72824f9f 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -1001,8 +1001,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert self.application.set_normal_cursor() # 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 - if not self.settings_form.isVisible() and \ - not self.screen_change_timestamp or (datetime.now() - self.screen_change_timestamp).seconds > 5: + if not self.settings_form.isVisible() and not self.screen_change_timestamp or \ + self.screen_change_timestamp and (datetime.now() - self.screen_change_timestamp).seconds > 5: QtWidgets.QMessageBox.warning(self, translate('OpenLP.MainWindow', 'Screen setup has changed'), translate('OpenLP.MainWindow', 'The screen setup has changed. ' diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index 4c6671e3e..245b2d752 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -56,6 +56,11 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): """ 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): self.vlc_player = None @@ -66,8 +71,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): self.preview_timer = QtCore.QTimer() self.preview_timer.setInterval(TICK_TIME) # Signals - self.live_timer.timeout.connect(self.media_state_live) - self.preview_timer.timeout.connect(self.media_state_preview) + self.live_timer.timeout.connect(self._media_state_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) 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')) self.setup_display(self.preview_controller, True) - def display_controllers(self, controller_type): + def _display_controllers(self, controller_type): """ Decides which controller to use. @@ -145,35 +150,35 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): return self.live_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) """ - 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: 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)) + self.tick(self._display_controllers(DisplayControllerType.Live)) if self.current_media_players[DisplayControllerType.Live].get_live_state() is not MediaState.Playing: self.live_timer.stop() else: 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) """ - 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: 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)) + self.tick(self._display_controllers(DisplayControllerType.Preview)) if self.current_media_players[DisplayControllerType.Preview].get_preview_state() is not MediaState.Playing: self.preview_timer.stop() else: 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): """ @@ -218,7 +223,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): :param hidden: The player which is doing the playing """ is_valid = True - controller = self.display_controllers(source) + controller = self._display_controllers(source) # stop running videos self.media_reset(controller) controller.media_info = ItemMediaInfo() @@ -246,27 +251,27 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): if controller.is_live: # if this is an optical device use special handling 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() (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, controller) 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'] controller.media_info.media_type = MediaType.Stream (name, mrl, options) = parse_stream_path(path) controller.media_info.file_info = (mrl, options) is_valid = self._check_file_type(controller, display) 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 is_valid = self._check_file_type(controller, display) controller.media_info.start_time = service_item.start_time controller.media_info.end_time = service_item.end_time elif controller.preview_display: 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() (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, @@ -278,7 +283,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): controller.media_info.file_info = (mrl, options) is_valid = self._check_file_type(controller, display) 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 is_valid = self._check_file_type(controller, display) if not is_valid: @@ -286,7 +291,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'), translate('MediaPlugin.MediaItem', 'Unsupported File')) 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 if service_item.requires_media(): autoplay = True @@ -305,7 +310,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): translate('MediaPlugin.MediaItem', 'Unsupported File')) return False 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 @staticmethod @@ -417,7 +423,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): """ 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): """ @@ -426,6 +432,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): :param controller: The controller to be played :param first_time: """ + self.log_debug(f"media_play with {first_time}") controller.seek_slider.blockSignals(True) controller.volume_slider.blockSignals(True) display = self._define_display(controller) @@ -457,6 +464,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): display.hide_display(HideMode.Screen) controller._set_theme(controller.service_item) display.load_verses([{"verse": "v1", "text": "", "footer": " "}]) + controller.output_has_changed() return True 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. """ - return self.media_pause(Registry().get('live_controller')) + return self.media_pause(self.live_controller) def media_pause(self, controller): """ @@ -515,6 +523,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): controller.mediabar.actions['playbackStop'].setDisabled(False) controller.mediabar.actions['playbackPause'].setVisible(False) controller.media_info.is_playing = False + controller.output_has_changed() return True return False @@ -548,7 +557,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): """ 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): """ @@ -572,6 +581,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): controller.media_timer = 0 display = self._define_display(controller) display.show_display() + controller.output_has_changed() return True return False @@ -592,7 +602,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): :param controller: The Controller to use :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: self.settings.setValue('media/live volume', volume) else: @@ -692,8 +702,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): """ self.live_timer.stop() self.preview_timer.stop() - self.media_reset(self.display_controllers(DisplayControllerType.Live)) - self.media_reset(self.display_controllers(DisplayControllerType.Preview)) + self.media_reset(self._display_controllers(DisplayControllerType.Live)) + self.media_reset(self._display_controllers(DisplayControllerType.Preview)) @staticmethod def _define_display(controller): diff --git a/openlp/core/ui/media/remote.py b/openlp/core/ui/media/remote.py index d725c0452..fa3c84da4 100644 --- a/openlp/core/ui/media/remote.py +++ b/openlp/core/ui/media/remote.py @@ -41,6 +41,7 @@ def media_play(): if live.service_item.name != 'media': abort(400) status = live.mediacontroller_live_play.emit() + log.debug(f'media_play return {status}') if status: return '', 202 abort(400) @@ -54,6 +55,7 @@ def media_pause(): if live.service_item.name != 'media': abort(400) status = live.mediacontroller_live_pause.emit() + log.debug(f'media_pause return {status}') if status: return '', 202 abort(400) @@ -67,6 +69,7 @@ def media_stop(): if live.service_item.name != 'media': abort(400) status = live.mediacontroller_live_stop.emit() + log.debug(f'media_stop return {status}') if status: return '', 202 abort(400) diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py index 9aa8dd9db..7f47f2dd7 100644 --- a/openlp/core/ui/media/vlcplayer.py +++ b/openlp/core/ui/media/vlcplayer.py @@ -171,7 +171,7 @@ class VlcPlayer(MediaPlayer): if not controller.vlc_instance: return False vlc = get_vlc() - log.debug('load vid in Vlc Controller') + log.debug('load video in VLC Controller') path = None if file and not controller.media_info.media_type == MediaType.Stream: path = os.path.normcase(file) diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index b695da97f..262afe3e7 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -129,9 +129,6 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties): tab_widget = self.stacked_layout.widget(tab_index) if tab_widget.tab_title == plugin_name: 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 while self.processes: Registry().execute(self.processes.pop(0)) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 8b76300dc..93a239222 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -204,6 +204,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties): self.update_slide_limits() self.panel = QtWidgets.QWidget(self.main_window.control_splitter) self.slide_list = {} + self.slide_count = 0 self.ignore_toolbar_resize_events = False # Layout for holding 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) else: 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): """ @@ -1462,11 +1470,15 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties): def on_clear(self): """ - Clear the preview bar. + Clear the preview bar and other bits. """ self.preview_widget.clear_list() - self.toolbar.set_widget_visible('editSong', False) - self.toolbar.set_widget_visible('clear', False) + self.service_item = None + 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): """ diff --git a/tests/functional/openlp_core/ui/media/test_mediacontroller.py b/tests/functional/openlp_core/ui/media/test_mediacontroller.py index 7fef46827..6955bf8a2 100644 --- a/tests/functional/openlp_core/ui/media/test_mediacontroller.py +++ b/tests/functional/openlp_core/ui/media/test_mediacontroller.py @@ -219,7 +219,7 @@ def test_on_media_play(media_env): media_env.media_controller.on_media_play() # 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): @@ -265,7 +265,7 @@ def test_display_controllers_live(media_env): Registry().register('preview_controller', mocked_preview_controller) # 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 assert controller is mocked_live_controller @@ -282,7 +282,7 @@ def test_display_controllers_preview(media_env): Registry().register('preview_controller', mocked_preview_controller) # 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 assert controller is mocked_preview_controller diff --git a/tests/functional/openlp_core/ui/media/test_remote.py b/tests/functional/openlp_core/ui/media/test_remote.py new file mode 100644 index 000000000..61dfc346b --- /dev/null +++ b/tests/functional/openlp_core/ui/media/test_remote.py @@ -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 . # +########################################################################## +""" +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'