Clean up error handling

This commit is contained in:
Tim Bentley 2018-11-04 17:13:56 +00:00
parent 0694d1b3d0
commit 0540453892
8 changed files with 75 additions and 222 deletions

View File

@ -185,11 +185,14 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties):
if self.has_delete_icon: if self.has_delete_icon:
toolbar_actions.append(['Delete', StringContent.Delete, UiIcons().delete, self.on_delete_click]) toolbar_actions.append(['Delete', StringContent.Delete, UiIcons().delete, self.on_delete_click])
# Preview # 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 # 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 # 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: for action in toolbar_actions:
if action[0] == StringContent.Preview: if action[0] == StringContent.Preview:
self.toolbar.addSeparator() self.toolbar.addSeparator()
@ -467,10 +470,12 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties):
Allows the list click action to be determined dynamically Allows the list click action to be determined dynamically
""" """
if Settings().value('advanced/double click live'): 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'): elif not Settings().value('advanced/single click preview'):
# NOTE: The above check is necessary to prevent bug #1419300 # 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): def on_selection_change(self):
""" """

View File

@ -24,9 +24,12 @@ Provide plugin management
""" """
import os import os
from PyQt5 import QtWidgets
from openlp.core.state import State from openlp.core.state import State
from openlp.core.common import extension_loader from openlp.core.common import extension_loader
from openlp.core.common.applocation import AppLocation 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.mixins import LogMixin, RegistryProperties
from openlp.core.common.registry import RegistryBase from openlp.core.common.registry import RegistryBase
from openlp.core.lib.plugin import Plugin, PluginStatus from openlp.core.lib.plugin import Plugin, PluginStatus
@ -145,7 +148,8 @@ class PluginManager(RegistryBase, LogMixin, RegistryProperties):
if plugin.status is not PluginStatus.Disabled: if plugin.status is not PluginStatus.Disabled:
plugin.add_tools_menu_item(self.main_window.tools_menu) 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. 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. Loop through all the plugins and give them an opportunity to initialise themselves.
""" """
uninitialised_plugins = []
for plugin in State().list_plugins(): for plugin in State().list_plugins():
self.log_info('initialising plugins {plugin} in a {state} state'.format(plugin=plugin.name, self.log_info('initialising plugins {plugin} in a {state} state'.format(plugin=plugin.name,
state=plugin.is_active())) state=plugin.is_active()))
if plugin.is_active(): if plugin.is_active():
plugin.initialise() try:
self.log_info('Initialisation Complete for {plugin}'.format(plugin=plugin.name)) 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): def finalise_plugins(self):
""" """
@ -175,7 +194,8 @@ class PluginManager(RegistryBase, LogMixin, RegistryProperties):
plugin.finalise() plugin.finalise()
self.log_info('Finalisation Complete for {plugin}'.format(plugin=plugin.name)) 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``. Return the plugin which has a name with value ``name``.
""" """
@ -184,7 +204,8 @@ class PluginManager(RegistryBase, LogMixin, RegistryProperties):
return plugin return plugin
return None 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 Loop through all the plugins and give them an opportunity to handle a new service
""" """

View File

@ -45,9 +45,10 @@ class StateModule(LogMixin):
self.order = 0 self.order = 0
self.is_plugin = None self.is_plugin = None
self.status = PluginStatus.Inactive self.status = PluginStatus.Inactive
self.pass_preconditions = True self.pass_preconditions = False
self.requires = None self.requires = None
self.required_by = None self.required_by = None
self.text = None
class State(LogMixin): class State(LogMixin):
@ -91,6 +92,16 @@ class State(LogMixin):
if requires not in self.modules[requires].required_by: if requires not in self.modules[requires].required_by:
self.modules[requires].required_by.append(name) 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): def update_pre_conditions(self, name, status):
""" """
Updates the preconditions state of a module Updates the preconditions state of a module

View File

@ -148,10 +148,6 @@ class MainDisplay(Display, LogMixin, RegistryProperties):
self.override = {} self.override = {}
self.retranslateUi() self.retranslateUi()
self.media_object = None self.media_object = None
if self.is_live:
self.audio_player = AudioPlayer(self)
else:
self.audio_player = None
self.first_time = True self.first_time = True
self.web_loaded = True self.web_loaded = True
self.setStyleSheet(OPAQUE_STYLESHEET) 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() - 1)
self.web_view.setGeometry(0, 0, self.width(), self.height()) 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()

View File

@ -27,13 +27,12 @@ import datetime
import logging import logging
try: try:
import pymediainfo from pymediainfo import MediaInfo
pymediainfo_available = True pymediainfo_available = True
except ImportError: except ImportError:
pymediainfo_available = False pymediainfo_available = False
from subprocess import check_output from subprocess import check_output
from pathlib import Path
from PyQt5 import QtCore, QtWidgets from PyQt5 import QtCore, QtWidgets
from openlp.core.state import State from openlp.core.state import State
@ -115,7 +114,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
super(MediaController, self).__init__(parent) super(MediaController, self).__init__(parent)
def setup(self): def setup(self):
self.media_players = None self.vlc_player = None
self.display_controllers = {} self.display_controllers = {}
self.current_media_players = {} self.current_media_players = {}
# Timer for video state # Timer for video state
@ -149,56 +148,31 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
""" """
suffix_list = [] suffix_list = []
self.audio_extensions_list = [] self.audio_extensions_list = []
if self.media_players.is_active: if self.vlc_player.is_active:
for item in self.media_players.audio_extensions_list: for item in self.vlc_player.audio_extensions_list:
if item not in self.audio_extensions_list: if item not in self.audio_extensions_list:
self.audio_extensions_list.append(item) self.audio_extensions_list.append(item)
suffix_list.append(item[2:]) suffix_list.append(item[2:])
self.video_extensions_list = [] self.video_extensions_list = []
if self.media_players.is_active: if self.vlc_player.is_active:
for item in self.media_players.video_extensions_list: for item in self.vlc_player.video_extensions_list:
if item not in self.video_extensions_list: if item not in self.video_extensions_list:
self.video_extensions_list.append(item) self.video_extensions_list.append(item)
suffix_list.append(item[2:]) suffix_list.append(item[2:])
self.service_manager.supported_suffixes(suffix_list) 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): def bootstrap_initialise(self):
""" """
Check to see if we have any media Player's available. 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.setup()
self.media_players = VlcPlayer(self) self.vlc_player = VlcPlayer(self)
State().add_service("mediacontroller", 0) State().add_service("mediacontroller", 0)
if get_vlc() and pymediainfo_available: if get_vlc() and pymediainfo_available:
State().update_pre_conditions("mediacontroller", True) 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() self._generate_extensions_lists()
return True return True
@ -236,36 +210,6 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
if self.display_controllers[DisplayControllerType.Preview].media_info.can_loop_playback: if self.display_controllers[DisplayControllerType.Preview].media_info.can_loop_playback:
self.media_play(self.display_controllers[DisplayControllerType.Preview], True) 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): def register_controller(self, controller):
""" """
Registers media controls where the players will be placed to run. Registers media controls where the players will be placed to run.
@ -350,7 +294,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
return return
if preview: if preview:
display.has_audio = False display.has_audio = False
self.media_players.setup(display) self.vlc_player.setup(display)
def set_controls_visible(self, controller, value): 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.. :param media_path: The file path to be checked..
""" """
if pymediainfo.MediaInfo.can_parse(): if MediaInfo.can_parse():
media_data = pymediainfo.MediaInfo.parse(media_path) media_data = MediaInfo.parse(media_path)
else: else:
xml = check_output(['mediainfo', '-f', '--Output=XML', '--Inform=OLDXML', media_path]) xml = check_output(['mediainfo', '-f', '--Output=XML', '--Inform=OLDXML', media_path])
if not xml.startswith(b'<?xml'): if not xml.startswith(b'<?xml'):
xml = check_output(['mediainfo', '-f', '--Output=XML', media_path]) xml = check_output(['mediainfo', '-f', '--Output=XML', media_path])
media_data = pymediainfo.MediaInfo(xml.decode("utf-8")) media_data = MediaInfo(xml.decode("utf-8"))
# duration returns in milli seconds # duration returns in milli seconds
return media_data.tracks[0].duration return media_data.tracks[0].duration
@ -508,9 +452,9 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
# When called from mediaitem display is None # When called from mediaitem display is None
if display is None: if display is None:
display = controller.preview_display display = controller.preview_display
self.media_players.load(display) self.vlc_player.load(display)
self.resize(display, self.media_players) self.resize(display, self.vlc_player)
self.current_media_players[controller.controller_type] = self.media_players self.current_media_players[controller.controller_type] = self.vlc_player
if audio_track == -1 and subtitle_track == -1: if audio_track == -1 and subtitle_track == -1:
controller.media_info.media_type = MediaType.CD controller.media_info.media_type = MediaType.CD
else: else:
@ -524,7 +468,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param service_item: where the information is about the media and required player :param service_item: where the information is about the media and required player
:return: player description :return: player description
""" """
return self.media_players return self.vlc_player
# If no player, we can't play # If no player, we can't play
# if not used_players: # if not used_players:
# return False # return False
@ -548,7 +492,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
for file in controller.media_info.file_info: for file in controller.media_info.file_info:
if file.is_file: if file.is_file:
suffix = '*%s' % file.suffix.lower() suffix = '*%s' % file.suffix.lower()
player = self.media_players player = self.vlc_player
file = str(file) file = str(file)
if suffix in player.video_extensions_list: if suffix in player.video_extensions_list:
if not controller.media_info.is_background or controller.media_info.is_background and \ if not controller.media_info.is_background or controller.media_info.is_background and \
@ -564,7 +508,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.media_info.media_type = MediaType.Audio controller.media_info.media_type = MediaType.Audio
return True return True
else: else:
player = self.media_players player = self.vlc_player
file = str(file) file = str(file)
if player.can_folder: if player.can_folder:
self.resize(display, player) self.resize(display, player)

View File

@ -23,7 +23,6 @@
The :mod:`slidecontroller` module contains the most important part of OpenLP - the slide controller The :mod:`slidecontroller` module contains the most important part of OpenLP - the slide controller
""" """
import copy import copy
import os
from collections import deque from collections import deque
from threading import Lock from threading import Lock

View File

@ -128,15 +128,13 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
""" """
Adds buttons to the start of the header bar. Adds buttons to the start of the header bar.
""" """
disable_optical_button_text = False if State().check_preconditions('media'):
optical_button_text = translate('MediaPlugin.MediaItem', 'Load CD/DVD') optical_button_text = translate('MediaPlugin.MediaItem', 'Load CD/DVD')
optical_button_tooltip = translate('MediaPlugin.MediaItem', 'Load CD/DVD') optical_button_tooltip = translate('MediaPlugin.MediaItem', 'Load CD/DVD')
self.load_optical = self.toolbar.add_toolbar_action('load_optical', icon=UiIcons().optical, self.load_optical = self.toolbar.add_toolbar_action('load_optical', icon=UiIcons().optical,
text=optical_button_text, text=optical_button_text,
tooltip=optical_button_tooltip, tooltip=optical_button_tooltip,
triggers=self.on_load_optical) triggers=self.on_load_optical)
if disable_optical_button_text:
self.load_optical.setDisabled(True)
def add_end_header_bar(self): def add_end_header_bar(self):
""" """

View File

@ -132,21 +132,3 @@ class MediaPlugin(Plugin):
log.info('Media Finalising') log.info('Media Finalising')
self.media_controller.finalise() self.media_controller.finalise()
Plugin.finalise(self) Plugin.finalise(self)
# def get_display_css(self):
# """
# Add css style sheets to htmlbuilder.
# """
# return self.media_controller.get_media_display_css()
#
# def get_display_javascript(self):
# """
# Add javascript functions to htmlbuilder.
# """
# return self.media_controller.get_media_display_javascript()
#
# def get_display_html(self):
# """
# Add html code to htmlbuilder.
# """
# return self.media_controller.get_media_display_html()