Stop media crashing

This commit is contained in:
Tim Bentley 2018-11-01 20:51:42 +00:00
parent 26a9b2430d
commit 0694d1b3d0
6 changed files with 121 additions and 119 deletions

View File

@ -616,6 +616,10 @@ class ServiceItem(RegistryProperties):
path_from = frame['path']
else:
path_from = os.path.join(frame['path'], frame['title'])
if isinstance(path_from, str):
# Handle service files prior to OpenLP 3.0
# Windows can handle both forward and backward slashes, so we use ntpath to get the basename
path_from = Path(path_from)
return path_from
def remove_frame(self, frame):

View File

@ -24,7 +24,7 @@ The :mod:`~openlp.core.loader` module provides a bootstrap for the singleton cla
"""
from openlp.core.state import State
from openlp.core.ui.media import MediaController
from openlp.core.ui.media.mediacontroller import MediaController
from openlp.core.lib.pluginmanager import PluginManager
from openlp.core.display.renderer import Renderer
from openlp.core.lib.imagemanager import ImageManager

View File

@ -33,7 +33,7 @@ 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
@ -81,7 +81,6 @@ class MediaSlider(QtWidgets.QSlider):
def mousePressEvent(self, event):
"""
Mouse Press event no new functionality
:param event: The triggering event
"""
QtWidgets.QSlider.mousePressEvent(self, event)
@ -385,7 +384,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param hidden: The player which is doing the playing
:param video_behind_text: Is the video to be played behind text.
"""
is_valid = False
is_valid = True
controller = self.display_controllers[source]
# stop running videos
self.media_reset(controller)
@ -397,7 +396,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
if service_item.is_capable(ItemCapabilities.HasBackgroundAudio):
controller.media_info.file_info = service_item.background_audio
else:
controller.media_info.file_info = [QtCore.QFileInfo(service_item.get_frame_path())]
controller.media_info.file_info = [service_item.get_frame_path()]
display = self._define_display(controller)
if controller.is_live:
# if this is an optical device use special handling
@ -465,18 +464,14 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
Uses Media Info to obtain the media length
:param service_item: The ServiceItem containing the details to be played.
:param media_path: The file path to be checked..
"""
media_info = MediaInfo()
media_info.volume = 0
media_info.file_info = media_path
filename = media_path
if pymediainfo.MediaInfo.can_parse():
media_data = pymediainfo.MediaInfo.parse(filename)
media_data = pymediainfo.MediaInfo.parse(media_path)
else:
xml = check_output(['mediainfo', '-f', '--Output=XML', '--Inform=OLDXML', filename])
xml = check_output(['mediainfo', '-f', '--Output=XML', '--Inform=OLDXML', media_path])
if not xml.startswith(b'<?xml'):
xml = check_output(['mediainfo', '-f', '--Output=XML', filename])
xml = check_output(['mediainfo', '-f', '--Output=XML', media_path])
media_data = pymediainfo.MediaInfo(xml.decode("utf-8"))
# duration returns in milli seconds
return media_data.tracks[0].duration
@ -550,30 +545,33 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param display: Which display to use
:param service_item: The ServiceItem containing the details to be played.
"""
if controller.media_info.file_info.isFile():
suffix = '*.%s' % controller.media_info.file_info.suffix().lower()
player = self.media_players
if suffix in player.video_extensions_list:
if not controller.media_info.is_background or controller.media_info.is_background and \
player.can_background:
for file in controller.media_info.file_info:
if file.is_file:
suffix = '*%s' % file.suffix.lower()
player = self.media_players
file = str(file)
if suffix in player.video_extensions_list:
if not controller.media_info.is_background or controller.media_info.is_background and \
player.can_background:
self.resize(display, player)
if player.load(display, file):
self.current_media_players[controller.controller_type] = player
controller.media_info.media_type = MediaType.Video
return True
if suffix in player.audio_extensions_list:
if player.load(display, file):
self.current_media_players[controller.controller_type] = player
controller.media_info.media_type = MediaType.Audio
return True
else:
player = self.media_players
file = str(file)
if player.can_folder:
self.resize(display, player)
if player.load(display):
if player.load(display, file):
self.current_media_players[controller.controller_type] = player
controller.media_info.media_type = MediaType.Video
return True
if suffix in player.audio_extensions_list:
if player.load(display):
self.current_media_players[controller.controller_type] = player
controller.media_info.media_type = MediaType.Audio
return True
else:
player = self.media_players
if player.can_folder:
self.resize(display, player)
if player.load(display):
self.current_media_players[controller.controller_type] = player
controller.media_info.media_type = MediaType.Video
return True
# no valid player found
return False

View File

@ -196,19 +196,19 @@ class VlcPlayer(MediaPlayer):
"""
return get_vlc() is not None
def load(self, display):
def load(self, display, file):
"""
Load a video into VLC
:param display: The display where the media is
:param file: file to be played
:return:
"""
vlc = get_vlc()
log.debug('load vid in Vlc Controller')
controller = display.controller
volume = controller.media_info.volume
file_path = str(controller.media_info.file_info.absoluteFilePath())
path = os.path.normcase(file_path)
path = os.path.normcase(file)
# create the media
if controller.media_info.media_type == MediaType.CD:
if is_win():

View File

@ -48,13 +48,13 @@ from openlp.core.widgets.views import ListPreviewWidget
# Threshold which has to be trespassed to toggle.
HIDE_MENU_THRESHOLD = 27
AUDIO_TIME_LABEL_STYLESHEET = 'background-color: palette(background); ' \
'border-top-color: palette(shadow); ' \
'border-left-color: palette(shadow); ' \
'border-bottom-color: palette(light); ' \
'border-right-color: palette(light); ' \
'border-radius: 3px; border-style: inset; ' \
'border-width: 1; font-family: monospace; margin: 2px;'
# AUDIO_TIME_LABEL_STYLESHEET = 'background-color: palette(background); ' \
# 'border-top-color: palette(shadow); ' \
# 'border-left-color: palette(shadow); ' \
# 'border-bottom-color: palette(light); ' \
# 'border-right-color: palette(light); ' \
# 'border-radius: 3px; border-style: inset; ' \
# 'border-width: 1; font-family: monospace; margin: 2px;'
NARROW_MENU = [
'hide_menu'
@ -64,10 +64,10 @@ LOOP_LIST = [
'loop_separator',
'delay_spin_box'
]
AUDIO_LIST = [
'audioPauseItem',
'audio_time_label'
]
# AUDIO_LIST = [
# 'audioPauseItem',
# 'audio_time_label'
# ]
WIDE_MENU = [
'blank_screen_button',
'theme_screen_button',
@ -84,6 +84,7 @@ class DisplayController(QtWidgets.QWidget):
"""
Controller is a general display controller widget.
"""
def __init__(self, *args, **kwargs):
"""
Set up the general Controller.
@ -140,6 +141,7 @@ class SlideController(DisplayController, LogMixin, RegistryProperties):
SlideController is the slide controller widget. This widget is what the
user uses to control the displaying of verses/slides/etc on the screen.
"""
def __init__(self, *args, **kwargs):
"""
Set up the Slide Controller.
@ -371,7 +373,7 @@ class SlideController(DisplayController, LogMixin, RegistryProperties):
self.preview_frame.setMinimumHeight(100)
self.preview_frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored,
QtWidgets.QSizePolicy.Ignored,
QtWidgets.QSizePolicy.Label))
QtWidgets.QSizePolicy.Label))
self.preview_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.preview_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
self.preview_frame.setObjectName('preview_frame')
@ -409,7 +411,7 @@ class SlideController(DisplayController, LogMixin, RegistryProperties):
{'key': 'C', 'configurable': True, 'text': translate('OpenLP.SlideController', 'Go to "Chorus"')},
{'key': 'B', 'configurable': True, 'text': translate('OpenLP.SlideController', 'Go to "Bridge"')},
{'key': 'P', 'configurable': True,
'text': translate('OpenLP.SlideController', 'Go to "Pre-Chorus"')},
'text': translate('OpenLP.SlideController', 'Go to "Pre-Chorus"')},
{'key': 'I', 'configurable': True, 'text': translate('OpenLP.SlideController', 'Go to "Intro"')},
{'key': 'E', 'configurable': True, 'text': translate('OpenLP.SlideController', 'Go to "Ending"')},
{'key': 'O', 'configurable': True, 'text': translate('OpenLP.SlideController', 'Go to "Other"')}
@ -475,6 +477,7 @@ class SlideController(DisplayController, LogMixin, RegistryProperties):
This empty class is mostly just to satisfy Python, PEP8 and PyCharm
"""
pass
is_songs_plugin_available = False
sender_name = self.sender().objectName()
verse_type = sender_name[15:] if sender_name[:15] == 'shortcutAction_' else ''
@ -597,8 +600,8 @@ class SlideController(DisplayController, LogMixin, RegistryProperties):
self.display.setup()
if self.is_live:
self.__add_actions_to_widget(self.display)
if self.display.audio_player:
self.display.audio_player.position_changed.connect(self.on_audio_time_remaining)
# if self.display.audio_player:
# self.display.audio_player.position_changed.connect(self.on_audio_time_remaining)
# The SlidePreview's ratio.
try:
self.ratio = self.screens.current['size'].width() / self.screens.current['size'].height()
@ -610,7 +613,7 @@ class SlideController(DisplayController, LogMixin, RegistryProperties):
self.preview_display.setup()
service_item = ServiceItem()
self.preview_display.web_view.setHtml(build_html(service_item, self.preview_display.screen, None, self.is_live,
plugins=self.plugin_manager.plugins))
plugins=self.plugin_manager.plugins))
self.media_controller.setup_display(self.preview_display, True)
if self.service_item:
self.refresh_service_item()
@ -871,29 +874,29 @@ class SlideController(DisplayController, LogMixin, RegistryProperties):
self.slide_list = {}
if self.is_live:
self.song_menu.menu().clear()
if self.display.audio_player:
self.display.audio_player.reset()
self.set_audio_items_visibility(False)
# self.audio_pause_item.setChecked(False)
# If the current item has background audio
if self.service_item.is_capable(ItemCapabilities.HasBackgroundAudio):
self.on_media_start(service_item)
#self.log_debug('Starting to play...')
#self.display.audio_player.add_to_playlist(self.service_item.background_audio)
#self.track_menu.clear()
#for counter in range(len(self.service_item.background_audio)):
# action = self.track_menu.addAction(
# os.path.basename(str(self.service_item.background_audio[counter])))
# action.setData(counter)
# action.triggered.connect(self.on_track_triggered)
#self.display.audio_player.repeat = \
# Settings().value(self.main_window.general_settings_section + '/audio repeat list')
#if Settings().value(self.main_window.general_settings_section + '/audio start paused'):
# self.audio_pause_item.setChecked(True)
# self.display.audio_player.pause()
#else:
# self.display.audio_player.play()
self.set_audio_items_visibility(True)
# if self.display.audio_player:
# self.display.audio_player.reset()
# self.set_audio_items_visibility(False)
# self.audio_pause_item.setChecked(False)
# If the current item has background audio
if self.service_item.is_capable(ItemCapabilities.HasBackgroundAudio):
self.on_media_start(service_item)
# self.log_debug('Starting to play...')
# self.display.audio_player.add_to_playlist(self.service_item.background_audio)
# self.track_menu.clear()
# for counter in range(len(self.service_item.background_audio)):
# action = self.track_menu.addAction(
# os.path.basename(str(self.service_item.background_audio[counter])))
# action.setData(counter)
# action.triggered.connect(self.on_track_triggered)
# self.display.audio_player.repeat = \
# Settings().value(self.main_window.general_settings_section + '/audio repeat list')
# if Settings().value(self.main_window.general_settings_section + '/audio start paused'):
# self.audio_pause_item.setChecked(True)
# self.display.audio_player.pause()
# else:
# self.display.audio_player.play()
# self.set_audio_items_visibility(True)
row = 0
width = self.main_window.control_splitter.sizes()[self.split]
for frame_number, frame in enumerate(self.service_item.get_frames()):
@ -1355,24 +1358,24 @@ class SlideController(DisplayController, LogMixin, RegistryProperties):
self.play_slides_once.setText(UiStrings().PlaySlidesToEnd)
self.on_toggle_loop()
def set_audio_items_visibility(self, visible):
"""
Set the visibility of the audio stuff
"""
self.toolbar.set_widget_visible(AUDIO_LIST, visible)
# def set_audio_items_visibility(self, visible):
# """
# Set the visibility of the audio stuff
# """
# self.toolbar.set_widget_visible(AUDIO_LIST, visible)
def set_audio_pause_clicked(self, checked):
"""
Pause the audio player
# def set_audio_pause_clicked(self, checked):
# """
# Pause the audio player
:param checked: is the check box checked.
"""
if not self.audio_pause_item.isVisible():
return
if checked:
self.display.audio_player.pause()
else:
self.display.audio_player.play()
# :param checked: is the check box checked.
# """
# if not self.audio_pause_item.isVisible():
# return
# if checked:
# self.display.audio_player.pause()
# else:
# self.display.audio_player.play()
def timerEvent(self, event):
"""
@ -1509,29 +1512,29 @@ class SlideController(DisplayController, LogMixin, RegistryProperties):
else:
return None
def on_next_track_clicked(self):
"""
Go to the next track when next is clicked
"""
self.display.audio_player.next()
def on_audio_time_remaining(self, time):
"""
Update how much time is remaining
:param time: the time remaining
"""
seconds = (self.display.audio_player.player.duration() - self.display.audio_player.player.position()) // 1000
minutes = seconds // 60
seconds %= 60
self.audio_time_label.setText(' %02d:%02d ' % (minutes, seconds))
def on_track_triggered(self, field=None):
"""
Start playing a track
"""
action = self.sender()
self.display.audio_player.go_to(action.data())
# def on_next_track_clicked(self):
# """
# Go to the next track when next is clicked
# """
# self.display.audio_player.next()
#
# def on_audio_time_remaining(self, time):
# """
# Update how much time is remaining
#
# :param time: the time remaining
# """
# seconds = (self.display.audio_player.player.duration() - self.display.audio_player.player.position()) // 1000
# minutes = seconds // 60
# seconds %= 60
# self.audio_time_label.setText(' %02d:%02d ' % (minutes, seconds))
#
# def on_track_triggered(self, field=None):
# """
# Start playing a track
# """
# action = self.sender()
# self.display.audio_player.go_to(action.data())
class PreviewController(RegistryBase, SlideController):

View File

@ -179,8 +179,6 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
:param remote: Triggered from remote
:param context: Why is it being generated
"""
if State().check_active_dependency():
a=1
if item is None:
item = self.list_view.currentItem()
if item is None:
@ -197,7 +195,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
translate('MediaPlugin.MediaItem',
'The optical disc {name} is no longer available.').format(name=name))
return False
service_item.processor = self.display_type_combo_box.currentText()
service_item.processor = 'vlc'
service_item.add_from_command(filename, name, CLAPPERBOARD)
service_item.title = clip_name
# Set the length
@ -218,8 +216,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
service_item.processor = 'vlc'
service_item.add_from_command(path, name, CLAPPERBOARD)
# Only get start and end times if going to a service
if not self.media_controller.media_length(service_item):
return False
service_item.set_media_length(self.media_controller.media_length(filename))
service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
service_item.add_capability(ItemCapabilities.CanEditTitle)
service_item.add_capability(ItemCapabilities.RequiresMedia)