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:
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):
"""

View File

@ -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
"""

View File

@ -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

View File

@ -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()

View File

@ -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'<?xml'):
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
return media_data.tracks[0].duration
@ -508,9 +452,9 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
# When called from mediaitem display is None
if display is None:
display = controller.preview_display
self.media_players.load(display)
self.resize(display, self.media_players)
self.current_media_players[controller.controller_type] = self.media_players
self.vlc_player.load(display)
self.resize(display, self.vlc_player)
self.current_media_players[controller.controller_type] = self.vlc_player
if audio_track == -1 and subtitle_track == -1:
controller.media_info.media_type = MediaType.CD
else:
@ -524,7 +468,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param service_item: where the information is about the media and required player
:return: player description
"""
return self.media_players
return self.vlc_player
# If no player, we can't play
# if not used_players:
# return False
@ -548,7 +492,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
for file in controller.media_info.file_info:
if file.is_file:
suffix = '*%s' % file.suffix.lower()
player = self.media_players
player = self.vlc_player
file = str(file)
if suffix in player.video_extensions_list:
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
return True
else:
player = self.media_players
player = self.vlc_player
file = str(file)
if player.can_folder:
self.resize(display, player)

View File

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

View File

@ -128,15 +128,13 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
"""
Adds buttons to the start of the header bar.
"""
disable_optical_button_text = False
optical_button_text = 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,
text=optical_button_text,
tooltip=optical_button_tooltip,
triggers=self.on_load_optical)
if disable_optical_button_text:
self.load_optical.setDisabled(True)
if State().check_preconditions('media'):
optical_button_text = 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,
text=optical_button_text,
tooltip=optical_button_tooltip,
triggers=self.on_load_optical)
def add_end_header_bar(self):
"""

View File

@ -132,21 +132,3 @@ class MediaPlugin(Plugin):
log.info('Media Finalising')
self.media_controller.finalise()
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()