From 0540453892a153b7eb0439b68d2aada8b9f086fe Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 4 Nov 2018 17:13:56 +0000 Subject: [PATCH] Clean up error handling --- openlp/core/lib/mediamanageritem.py | 15 ++-- openlp/core/lib/pluginmanager.py | 31 +++++-- openlp/core/state.py | 13 ++- openlp/core/ui/maindisplay.py | 107 ------------------------ openlp/core/ui/media/mediacontroller.py | 96 +++++---------------- openlp/core/ui/slidecontroller.py | 1 - openlp/plugins/media/lib/mediaitem.py | 16 ++-- openlp/plugins/media/mediaplugin.py | 18 ---- 8 files changed, 75 insertions(+), 222 deletions(-) diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 7b6a50376..93ffed46b 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -185,11 +185,14 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): if self.has_delete_icon: toolbar_actions.append(['Delete', StringContent.Delete, UiIcons().delete, self.on_delete_click]) # Preview - toolbar_actions.append(['Preview', StringContent.Preview, UiIcons().preview, self.on_preview_click]) + if self.can_preview: + toolbar_actions.append(['Preview', StringContent.Preview, UiIcons().preview, self.on_preview_click]) # Live Button - toolbar_actions.append(['Live', StringContent.Live, UiIcons().live, self.on_live_click]) + if self.can_make_live: + toolbar_actions.append(['Live', StringContent.Live, UiIcons().live, self.on_live_click]) # Add to service Button - toolbar_actions.append(['Service', StringContent.Service, UiIcons().add, self.on_add_click]) + if self.can_add_to_service: + toolbar_actions.append(['Service', StringContent.Service, UiIcons().add, self.on_add_click]) for action in toolbar_actions: if action[0] == StringContent.Preview: self.toolbar.addSeparator() @@ -467,10 +470,12 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): Allows the list click action to be determined dynamically """ if Settings().value('advanced/double click live'): - self.on_live_click() + if self.can_make_live: + self.on_live_click() elif not Settings().value('advanced/single click preview'): # NOTE: The above check is necessary to prevent bug #1419300 - self.on_preview_click() + if self.can_preview: + self.on_preview_click() def on_selection_change(self): """ diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index 95b470b07..d9078f7cf 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -24,9 +24,12 @@ Provide plugin management """ import os +from PyQt5 import QtWidgets + from openlp.core.state import State from openlp.core.common import extension_loader from openlp.core.common.applocation import AppLocation +from openlp.core.common.i18n import translate, UiStrings from openlp.core.common.mixins import LogMixin, RegistryProperties from openlp.core.common.registry import RegistryBase from openlp.core.lib.plugin import Plugin, PluginStatus @@ -145,7 +148,8 @@ class PluginManager(RegistryBase, LogMixin, RegistryProperties): if plugin.status is not PluginStatus.Disabled: plugin.add_tools_menu_item(self.main_window.tools_menu) - def hook_upgrade_plugin_settings(self, settings): + @staticmethod + def hook_upgrade_plugin_settings(settings): """ Loop through all the plugins and give them an opportunity to upgrade their settings. @@ -159,12 +163,27 @@ class PluginManager(RegistryBase, LogMixin, RegistryProperties): """ Loop through all the plugins and give them an opportunity to initialise themselves. """ + uninitialised_plugins = [] for plugin in State().list_plugins(): self.log_info('initialising plugins {plugin} in a {state} state'.format(plugin=plugin.name, state=plugin.is_active())) if plugin.is_active(): - plugin.initialise() - self.log_info('Initialisation Complete for {plugin}'.format(plugin=plugin.name)) + try: + plugin.initialise() + self.log_info('Initialisation Complete for {plugin}'.format(plugin=plugin.name)) + except Exception: + uninitialised_plugins.append(plugin.name.title()) + self.log_exception('Unable to initialise plugin {plugin}'.format(plugin=plugin.name)) + display_text = None + if uninitialised_plugins: + display_text = translate('OpenLP.PluginManager', + 'Unable to initialise the following plugins:') + \ + '\n\n'.join(uninitialised_plugins) + '\n\n' + if display_text: + display_text = display_text + \ + translate('OpenLP.PluginManager', 'See the log file for more details') + QtWidgets.QMessageBox.critical(None, UiStrings().Error, display_text, + QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok)) def finalise_plugins(self): """ @@ -175,7 +194,8 @@ class PluginManager(RegistryBase, LogMixin, RegistryProperties): plugin.finalise() self.log_info('Finalisation Complete for {plugin}'.format(plugin=plugin.name)) - def get_plugin_by_name(self, name): + @staticmethod + def get_plugin_by_name(name): """ Return the plugin which has a name with value ``name``. """ @@ -184,7 +204,8 @@ class PluginManager(RegistryBase, LogMixin, RegistryProperties): return plugin return None - def new_service_created(self): + @staticmethod + def new_service_created(): """ Loop through all the plugins and give them an opportunity to handle a new service """ diff --git a/openlp/core/state.py b/openlp/core/state.py index b8d4acf8e..c5bd58236 100644 --- a/openlp/core/state.py +++ b/openlp/core/state.py @@ -45,9 +45,10 @@ class StateModule(LogMixin): self.order = 0 self.is_plugin = None self.status = PluginStatus.Inactive - self.pass_preconditions = True + self.pass_preconditions = False self.requires = None self.required_by = None + self.text = None class State(LogMixin): @@ -91,6 +92,16 @@ class State(LogMixin): if requires not in self.modules[requires].required_by: self.modules[requires].required_by.append(name) + def missing_text(self, name, text): + """ + Updates the preconditions state of a module + + :param name: Module name + :param text: Module missing text + :return: + """ + self.modules[name].text = text + def update_pre_conditions(self, name, status): """ Updates the preconditions state of a module diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 996e69836..57c87d588 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -148,10 +148,6 @@ class MainDisplay(Display, LogMixin, RegistryProperties): self.override = {} self.retranslateUi() self.media_object = None - if self.is_live: - self.audio_player = AudioPlayer(self) - else: - self.audio_player = None self.first_time = True self.web_loaded = True self.setStyleSheet(OPAQUE_STYLESHEET) @@ -604,106 +600,3 @@ class MainDisplay(Display, LogMixin, RegistryProperties): """ self.web_view.setGeometry(0, 0, self.width(), self.height() - 1) self.web_view.setGeometry(0, 0, self.width(), self.height()) - - -class AudioPlayer(LogMixin, QtCore.QObject): - """ - This Class will play audio only allowing components to work with a soundtrack independent of the user interface. - """ - position_changed = QtCore.pyqtSignal(int) - - def __init__(self, parent): - """ - The constructor for the display form. - - :param parent: The parent widget. - """ - super(AudioPlayer, self).__init__(parent) - self.player = QtMultimedia.QMediaPlayer() - self.playlist = QtMultimedia.QMediaPlaylist(self.player) - self.volume_slider = None - self.player.setPlaylist(self.playlist) - self.player.positionChanged.connect(self._on_position_changed) - - def __del__(self): - """ - Shutting down so clean up connections - """ - self.stop() - - def _on_position_changed(self, position): - """ - Emit a signal when the position of the media player updates - """ - self.position_changed.emit(position) - - def set_volume_slider(self, slider): - """ - Connect the volume slider to the media player - :param slider: - """ - self.volume_slider = slider - self.volume_slider.setMinimum(0) - self.volume_slider.setMaximum(100) - self.volume_slider.setValue(self.player.volume()) - self.volume_slider.valueChanged.connect(self.set_volume) - - def set_volume(self, volume): - """ - Set the volume of the media player - - :param volume: - """ - self.player.setVolume(volume) - - def reset(self): - """ - Reset the audio player, clearing the playlist and the queue. - """ - self.stop() - self.playlist.clear() - - def play(self): - """ - We want to play the file so start it - """ - self.player.play() - - def pause(self): - """ - Pause the Audio - """ - self.player.pause() - - def stop(self): - """ - Stop the Audio and clean up - """ - self.player.stop() - - def add_to_playlist(self, file_names): - """ - Add another file to the playlist. - - :param file_names: A list with files to be added to the playlist. - """ - if not isinstance(file_names, list): - file_names = [file_names] - for file_name in file_names: - self.playlist.addMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(str(file_name)))) - - def next(self): - """ - Skip forward to the next track in the list - """ - self.playlist.next() - - def go_to(self, index): - """ - Go to a particular track in the list - - :param index: The track to go to - """ - self.playlist.setCurrentIndex(index) - if self.player.state() == QtMultimedia.QMediaPlayer.PlayingState: - self.player.play() diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index 45fb48f40..9e2b7fffe 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -27,13 +27,12 @@ import datetime import logging try: - import pymediainfo + from pymediainfo import MediaInfo pymediainfo_available = True except ImportError: pymediainfo_available = False from subprocess import check_output -from pathlib import Path from PyQt5 import QtCore, QtWidgets from openlp.core.state import State @@ -115,7 +114,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): super(MediaController, self).__init__(parent) def setup(self): - self.media_players = None + self.vlc_player = None self.display_controllers = {} self.current_media_players = {} # Timer for video state @@ -149,56 +148,31 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): """ suffix_list = [] self.audio_extensions_list = [] - if self.media_players.is_active: - for item in self.media_players.audio_extensions_list: + if self.vlc_player.is_active: + for item in self.vlc_player.audio_extensions_list: if item not in self.audio_extensions_list: self.audio_extensions_list.append(item) suffix_list.append(item[2:]) self.video_extensions_list = [] - if self.media_players.is_active: - for item in self.media_players.video_extensions_list: + if self.vlc_player.is_active: + for item in self.vlc_player.video_extensions_list: if item not in self.video_extensions_list: self.video_extensions_list.append(item) suffix_list.append(item[2:]) self.service_manager.supported_suffixes(suffix_list) - # def register_players(self): - # """ - # Register each media Player (Webkit, Phonon, etc) and store - # for later use - # - # :param player: Individual player class which has been enabled - # """ - # self.media_players = VlcPlayer(self) - def bootstrap_initialise(self): """ Check to see if we have any media Player's available. """ - # controller_dir = os.path.join('core', 'ui', 'media') - # # Find all files that do not begin with '.' (lp:#1738047) and end with player.py - # glob_pattern = os.path.join(controller_dir, '[!.]*player.py') - # extension_loader(glob_pattern, ['mediaplayer.py']) - # player_classes = MediaPlayer.__subclasses__() - # for player_class in player_classes: - # self.register_players(player_class(self)) - # if not self.media_players: - # return False - # saved_players, overridden_player = get_media_players() - # invalid_media_players = \ - # [media_player for media_player in saved_players if media_player not in self.media_players or - # not self.media_players[media_player].check_available()] - # if invalid_media_players: - # for invalidPlayer in invalid_media_players: - # saved_players.remove(invalidPlayer) - # set_media_players(saved_players, overridden_player) - # self._set_active_players() - # self.register_players() self.setup() - self.media_players = VlcPlayer(self) + self.vlc_player = VlcPlayer(self) State().add_service("mediacontroller", 0) if get_vlc() and pymediainfo_available: State().update_pre_conditions("mediacontroller", True) + else: + State().missing_text("mediacontroller", translate('OpenLP.SlideController', + "VLC or pymediainfo are missing so you are unable to play any media")) self._generate_extensions_lists() return True @@ -236,36 +210,6 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): if self.display_controllers[DisplayControllerType.Preview].media_info.can_loop_playback: self.media_play(self.display_controllers[DisplayControllerType.Preview], True) - # def get_media_display_css(self): - # """ - # Add css style sheets to htmlbuilder - # """ - # css = '' - # for player in list(self.media_players.values()): - # if player.is_active: - # css += player.get_media_display_css() - # return css - # - # def get_media_display_javascript(self): - # """ - # Add javascript functions to htmlbuilder - # """ - # js = '' - # for player in list(self.media_players.values()): - # if player.is_active: - # js += player.get_media_display_javascript() - # return js - # - # def get_media_display_html(self): - # """ - # Add html code to htmlbuilder - # """ - # html = '' - # for player in list(self.media_players.values()): - # if player.is_active: - # html += player.get_media_display_html() - # return html - def register_controller(self, controller): """ Registers media controls where the players will be placed to run. @@ -350,7 +294,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): return if preview: display.has_audio = False - self.media_players.setup(display) + self.vlc_player.setup(display) def set_controls_visible(self, controller, value): """ @@ -466,13 +410,13 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): :param media_path: The file path to be checked.. """ - if pymediainfo.MediaInfo.can_parse(): - media_data = pymediainfo.MediaInfo.parse(media_path) + if MediaInfo.can_parse(): + media_data = MediaInfo.parse(media_path) else: xml = check_output(['mediainfo', '-f', '--Output=XML', '--Inform=OLDXML', media_path]) if not xml.startswith(b'