Merge branch 'master' of gitlab.com:openlp/openlp

This commit is contained in:
Tim 2019-11-03 21:28:11 +00:00
commit 820bf131c5
No known key found for this signature in database
GPG Key ID: 3D454289AF831A6D
16 changed files with 352 additions and 401 deletions

View File

@ -212,6 +212,8 @@ class Settings(QtCore.QSettings):
'media/vlc arguments': '',
'media/video': '',
'media/audio': '',
'media/live volume': 50,
'media/preview volume': 0,
'remotes/download version': '0.0',
'players/background color': '#000000',
'servicemanager/last directory': None,

View File

@ -214,7 +214,6 @@ class ServiceItem(RegistryProperties):
"""
Render the frames for printing and return them
:param can_render_chords: bool Whether or not to render the chords
"""
if not self._print_slides:
self._print_slides = []
@ -345,7 +344,11 @@ class ServiceItem(RegistryProperties):
service_data = [slide['title'] for slide in self.slides]
elif self.service_item_type == ServiceItemType.Command:
for slide in self.slides:
service_data.append({'title': slide['title'], 'image': slide['image'], 'path': slide['path'],
if isinstance(slide['image'], QtGui.QIcon):
image = "clapperboard"
else:
image = slide['image']
service_data.append({'title': slide['title'], 'image': image, 'path': slide['path'],
'display_title': slide['display_title'], 'notes': slide['notes']})
return {'header': service_header, 'data': service_data}
@ -425,6 +428,8 @@ class ServiceItem(RegistryProperties):
self.add_from_command(text_image['path'], text_image['title'], text_image['image'])
elif path:
self.has_original_files = False
if text_image['image'] == "clapperboard":
text_image['image'] = UiIcons().clapperboard
self.add_from_command(path, text_image['title'], text_image['image'],
text_image.get('display_title', ''), text_image.get('notes', ''))
else:
@ -631,7 +636,7 @@ class ServiceItem(RegistryProperties):
"""
Validates a service item to make sure it is valid
:param set[str] suffixes: A set of vaild suffixes
:param set[str] suffixes: A set of valid suffixes
"""
self.is_valid = True
for slide in self.slides:
@ -649,7 +654,7 @@ class ServiceItem(RegistryProperties):
self.is_valid = False
break
if suffixes and not self.is_text():
file_suffix = slide['title'].split('.')[-1]
file_suffix = "*.{suffx}".format(suffx=slide['title'].split('.')[-1])
if file_suffix.lower() not in suffixes:
self.is_valid = False
break

View File

@ -70,7 +70,7 @@ class ItemMediaInfo(object):
file_info = None
volume = 100
is_background = False
can_loop_playback = False
is_looping_playback = False
length = 0
start_time = 0
end_time = 0
@ -91,7 +91,7 @@ def parse_optical_path(input_string):
"""
log.debug('parse_optical_path, about to parse: "{text}"'.format(text=input_string))
clip_info = input_string.split(sep=':')
title = int(clip_info[1])
title = str(clip_info[1])
audio_track = int(clip_info[2])
subtitle_track = int(clip_info[3])
start = float(clip_info[4])

View File

@ -64,6 +64,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
self.live_timer.setInterval(TICK_TIME)
self.preview_timer = QtCore.QTimer()
self.preview_timer.setInterval(TICK_TIME)
self.settings = Settings()
# Signals
self.live_timer.timeout.connect(self.media_state_live)
self.preview_timer.timeout.connect(self.media_state_preview)
@ -116,13 +117,13 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
if State().check_preconditions('mediacontroller'):
try:
self.setup_display(self.live_controller.display, False)
self.setup_display(self.live_controller, False)
except AttributeError:
State().update_pre_conditions('media_live', False)
State().missing_text('media_live', translate(
'OpenLP.MediaController',
'No Displays have been configured, so Live Media has been disabled'))
self.setup_display(self.preview_controller.preview_display, True)
self.setup_display(self.preview_controller, True)
def display_controllers(self, controller_type):
"""
@ -140,7 +141,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
display = self._define_display(self.display_controllers(DisplayControllerType.Live))
if DisplayControllerType.Live in self.current_media_players:
self.current_media_players[DisplayControllerType.Live].resize(display)
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))
if self.current_media_players[DisplayControllerType.Live].get_live_state() is not MediaState.Playing:
@ -148,8 +149,6 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
else:
self.live_timer.stop()
self.media_stop(self.display_controllers(DisplayControllerType.Live))
if self.display_controllers(DisplayControllerType.Live).media_info.can_loop_playback:
self.media_play(self.display_controllers(DisplayControllerType.Live), True)
def media_state_preview(self):
"""
@ -157,7 +156,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
display = self._define_display(self.display_controllers(DisplayControllerType.Preview))
if DisplayControllerType.Preview in self.current_media_players:
self.current_media_players[DisplayControllerType.Preview].resize(display)
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))
if self.current_media_players[DisplayControllerType.Preview].get_preview_state() is not MediaState.Playing:
@ -165,23 +164,19 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
else:
self.preview_timer.stop()
self.media_stop(self.display_controllers(DisplayControllerType.Preview))
if self.display_controllers(DisplayControllerType.Preview).media_info.can_loop_playback:
self.media_play(self.display_controllers(DisplayControllerType.Preview), True)
def setup_display(self, display, preview):
def setup_display(self, controller, preview):
"""
After a new display is configured, all media related widgets will be created too
:param display: Display on which the output is to be played
:param controller: Display on which the output is to be played
:param preview: Whether the display is a main or preview display
"""
display.media_info = ItemMediaInfo()
display.has_audio = True
# if display.is_live and preview:
# return
controller.media_info = ItemMediaInfo()
controller.has_audio = True
if preview:
display.has_audio = False
self.vlc_player.setup(display, preview)
controller.has_audio = False
self.vlc_player.setup(controller, self._define_display(controller), preview)
@staticmethod
def set_controls_visible(controller, value):
@ -195,33 +190,33 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.mediabar.setVisible(value)
@staticmethod
def resize(display, player):
def resize(controller, player):
"""
After Mainwindow changes or Splitter moved all related media widgets have to be resized
:param display: The display on which output is playing.
:param controller: The display on which output is playing.
:param player: The player which is doing the playing.
"""
player.resize(display)
player.resize(controller)
def load_video(self, source, service_item, hidden=False, video_behind_text=False):
def load_video(self, source, service_item, hidden=False):
"""
Loads and starts a video to run with the option of sound
Loads and starts a video to run and sets the stored sound value.
:param source: Where the call originated form
:param service_item: The player which is doing the playing
:param hidden: The player which is doing the playing
:param video_behind_text: Is the video to be played behind text.
"""
is_valid = True
controller = self.display_controllers(source)
# stop running videos
self.media_reset(controller)
controller.media_info = ItemMediaInfo()
controller.media_info.volume = controller.volume_slider.value()
controller.media_info.is_background = video_behind_text
if controller.is_live:
controller.media_info.volume = self.settings.value('media/live volume')
else:
controller.media_info.volume = self.settings.value('media/preview volume')
# background will always loop video.
controller.media_info.can_loop_playback = video_behind_text
if service_item.is_capable(ItemCapabilities.HasBackgroundAudio):
controller.media_info.file_info = service_item.background_audio
else:
@ -242,13 +237,6 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
log.debug('video is not optical and live')
controller.media_info.length = service_item.media_length
is_valid = self._check_file_type(controller, display)
# display.override['theme'] = ''
# display.override['video'] = True
if controller.media_info.is_background:
# ignore start/end time
controller.media_info.start_time = 0
controller.media_info.end_time = 0
else:
controller.media_info.start_time = service_item.start_time
controller.media_info.end_time = service_item.end_time
elif controller.preview_display:
@ -280,10 +268,10 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
if not controller.is_live:
autoplay = True
# Visible or background requested or Service Item wants to autostart
elif not hidden or controller.media_info.is_background or service_item.will_auto_start:
elif not hidden or service_item.will_auto_start:
autoplay = True
# Unblank on load set
elif Settings().value('core/auto unblank'):
elif self.settings.value('core/auto unblank'):
autoplay = True
if autoplay:
if not self.media_play(controller):
@ -344,7 +332,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
if display is None:
display = controller.preview_display
self.vlc_player.load(display, filename)
self.resize(display, self.vlc_player)
self.resize(controller, 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
@ -361,9 +349,9 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param stream: Are we streaming or not
"""
if stream:
self.resize(display, self.vlc_player)
display.media_info.media_type = MediaType.Stream
if self.vlc_player.load(display, None):
self.resize(controller, self.vlc_player)
controller.media_info.media_type = MediaType.Stream
if self.vlc_player.load(controller, display, None):
self.current_media_players[controller.controller_type] = self.vlc_player
return True
return True
@ -372,23 +360,21 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
suffix = '*%s' % file.suffix.lower()
file = str(file)
if suffix in VIDEO_EXT:
if not controller.media_info.is_background or controller.media_info.is_background and \
self.vlc_player.can_background:
self.resize(display, self.vlc_player)
if self.vlc_player.load(display, file):
self.resize(controller, self.vlc_player)
if self.vlc_player.load(controller, display, file):
self.current_media_players[controller.controller_type] = self.vlc_player
controller.media_info.media_type = MediaType.Video
return True
if suffix in AUDIO_EXT:
if self.vlc_player.load(display, file):
if self.vlc_player.load(controller, display, file):
self.current_media_players[controller.controller_type] = self.vlc_player
controller.media_info.media_type = MediaType.Audio
return True
else:
file = str(file)
if self.vlc_player.can_folder:
self.resize(display, self.vlc_player)
if self.vlc_player.load(display, file):
self.resize(controller, self.vlc_player)
if self.vlc_player.load(controller, display, file):
self.current_media_players[controller.controller_type] = self.vlc_player
controller.media_info.media_type = MediaType.Video
return True
@ -423,19 +409,14 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.seek_slider.blockSignals(False)
controller.volume_slider.blockSignals(False)
return False
if controller.media_info.is_background:
self.media_volume(controller, 0)
else:
self.media_volume(controller, controller.media_info.volume)
if first_time:
# if not controller.media_info.is_background:
# display.frame.runJavaScript('show_blank("desktop");')
self.current_media_players[controller.controller_type].set_visible(display, True)
self.current_media_players[controller.controller_type].set_visible(controller, True)
controller.mediabar.actions['playbackPlay'].setVisible(False)
controller.mediabar.actions['playbackPause'].setVisible(True)
controller.mediabar.actions['playbackStop'].setDisabled(False)
if controller.is_live:
if controller.hide_menu.defaultAction().isChecked() and not controller.media_info.is_background:
if controller.hide_menu.defaultAction().isChecked():
controller.hide_menu.defaultAction().trigger()
# Start Timer for ui updates
if not self.live_timer.isActive():
@ -448,6 +429,10 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.volume_slider.blockSignals(False)
controller.media_info.is_playing = True
display = self._define_display(controller)
if controller.is_live:
display.setVisible(False)
controller.preview_display.hide()
else:
display.setVisible(True)
return True
@ -460,8 +445,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
start_again = False
if controller.media_info.is_playing and controller.media_info.length > 0:
if controller.media_info.timer > controller.media_info.length:
self.media_stop(controller, True)
if controller.media_info.can_loop_playback:
self.media_stop(controller)
if controller.media_info.is_looping_playback:
start_again = True
controller.media_info.timer += TICK_TIME
seconds = controller.media_info.timer // 1000
@ -495,9 +480,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param controller: The Controller to be paused
"""
display = self._define_display(controller)
if controller.controller_type in self.current_media_players:
self.current_media_players[controller.controller_type].pause(display)
self.current_media_players[controller.controller_type].pause(controller)
controller.mediabar.actions['playbackPlay'].setVisible(True)
controller.mediabar.actions['playbackStop'].setDisabled(False)
controller.mediabar.actions['playbackPause'].setVisible(False)
@ -518,8 +502,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param controller: The controller that needs to be stopped
"""
controller.media_info.can_loop_playback = not controller.media_info.can_loop_playback
controller.mediabar.actions['playbackLoop'].setChecked(controller.media_info.can_loop_playback)
controller.media_info.is_looping_playback = not controller.media_info.is_looping_playback
controller.mediabar.actions['playbackLoop'].setChecked(controller.media_info.is_looping_playback)
def media_stop_msg(self, msg):
"""
@ -535,19 +519,16 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
self.media_stop(Registry().get('live_controller'))
def media_stop(self, controller, looping_background=False):
def media_stop(self, controller):
"""
Responds to the request to stop a loaded video
:param controller: The controller that needs to be stopped
:param looping_background: The background is looping so do not blank.
"""
display = self._define_display(controller)
if controller.controller_type in self.current_media_players:
# if not looping_background:
# display.frame.runJavaScript('show_blank("black");')
self.current_media_players[controller.controller_type].stop(display)
self.current_media_players[controller.controller_type].set_visible(display, False)
self.current_media_players[controller.controller_type].stop(controller)
self.current_media_players[controller.controller_type].set_visible(controller, False)
controller.preview_display.hide()
controller.seek_slider.setSliderPosition(0)
total_seconds = controller.media_info.length // 1000
total_minutes = total_seconds // 60
@ -578,8 +559,12 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param volume: The volume to be set
"""
log.debug('media_volume {vol}'.format(vol=volume))
display = self._define_display(controller)
self.current_media_players[controller.controller_type].volume(display, volume)
if controller.is_live:
self.settings.setValue('media/live volume', volume)
else:
self.settings.setValue('media/preview volume', volume)
controller.media_info.volume = volume
self.current_media_players[controller.controller_type].volume(controller, volume)
controller.volume_slider.setValue(volume)
def media_seek_msg(self, msg):
@ -600,8 +585,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param controller: The controller to use.
:param seek_value: The value to set.
"""
display = self._define_display(controller)
self.current_media_players[controller.controller_type].seek(display, seek_value)
self.current_media_players[controller.controller_type].seek(controller, seek_value)
controller.media_info.timer = seek_value
def media_reset(self, controller):
@ -610,12 +594,9 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param controller: The controller to use.
"""
self.set_controls_visible(controller, False)
display = self._define_display(controller)
if controller.controller_type in self.current_media_players:
display.override = {}
self.current_media_players[controller.controller_type].reset(display)
self.current_media_players[controller.controller_type].set_visible(display, False)
# display.frame.runJavaScript('show_video("setBackBoard", null, null, "hidden");')
self.current_media_players[controller.controller_type].reset(controller)
self.current_media_players[controller.controller_type].set_visible(controller, False)
del self.current_media_players[controller.controller_type]
def media_hide(self, msg):
@ -631,7 +612,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
if self.live_controller.controller_type in self.current_media_players and \
self.current_media_players[self.live_controller.controller_type].get_live_state() == MediaState.Playing:
self.media_pause(display.controller)
self.current_media_players[self.live_controller.controller_type].set_visible(display, False)
self.current_media_players[self.live_controller.controller_type].set_visible(self.live_controller, False)
def media_blank(self, msg):
"""
@ -649,7 +630,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
if self.live_controller.controller_type in self.current_media_players and \
self.current_media_players[self.live_controller.controller_type].get_live_state() == MediaState.Playing:
self.media_pause(display.controller)
self.current_media_players[self.live_controller.controller_type].set_visible(display, False)
self.current_media_players[self.live_controller.controller_type].set_visible(self.live_controller, False)
def media_unblank(self, msg):
"""
@ -667,7 +648,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
self.current_media_players[self.live_controller.controller_type].get_live_state() != \
MediaState.Playing:
if self.media_play(display.controller):
self.current_media_players[self.live_controller.controller_type].set_visible(display, True)
self.current_media_players[self.live_controller.controller_type].set_visible(self.live_controller, True)
# Start Timer for ui updates
if not self.live_timer.isActive():
self.live_timer.start()

View File

@ -48,7 +48,7 @@ class MediaPlayer(RegistryProperties):
"""
return False
def setup(self, display, live_display):
def setup(self, controller, display, live_display):
"""
Create the related widgets for the current display
@ -57,10 +57,10 @@ class MediaPlayer(RegistryProperties):
"""
pass
def load(self, display, file):
def load(self, controller, display, file):
"""
Load a new media file and check if it is valid
:param controller: Which Controller is running the show.
:param display: The display to be updated.
:param file: The file to be loaded
"""
@ -70,7 +70,6 @@ class MediaPlayer(RegistryProperties):
"""
If the main display size or position is changed, the media widgets
should also resized
:param display: The display to be updated.
"""
pass
@ -192,14 +191,14 @@ class MediaPlayer(RegistryProperties):
"""
self.state[1] = state
def set_state(self, state, display):
def set_state(self, state, controller):
"""
Set the State based on the display being processed
Set the State based on the display being processed within the controller
:param state: State to be set
:param display: Identify the Display type
:param controller: Identify the Display type
:return: None
"""
if display.is_display:
if controller.is_live:
self.set_live_state(state)
else:
self.set_preview_state(state)

View File

@ -27,6 +27,7 @@ import os
import sys
import threading
from datetime import datetime
from time import sleep
from PyQt5 import QtCore, QtWidgets
@ -95,50 +96,49 @@ class VlcPlayer(MediaPlayer):
self.parent = parent
self.can_folder = True
def setup(self, output_display, live_display):
def setup(self, controller, display, live_display):
"""
Set up the media player
:param output_display: The display where the media is
:param controller: The display where the media is
:param live_display: Is the display a live one.
:return:
"""
vlc = get_vlc()
if output_display.is_display:
output_display.vlc_widget = QtWidgets.QFrame()
output_display.vlc_widget.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool |
if controller.is_live:
controller.vlc_widget = QtWidgets.QFrame()
controller.vlc_widget.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool |
QtCore.Qt.WindowStaysOnTopHint)
else:
output_display.vlc_widget = QtWidgets.QFrame(output_display)
output_display.vlc_widget.setFrameStyle(QtWidgets.QFrame.NoFrame)
controller.vlc_widget = QtWidgets.QFrame(display)
controller.vlc_widget.setFrameStyle(QtWidgets.QFrame.NoFrame)
# creating a basic vlc instance
command_line_options = '--no-video-title-show '
if Settings().value('advanced/hide mouse') and live_display:
command_line_options += '--mouse-hide-timeout=0 '
if Settings().value('media/vlc arguments'):
command_line_options += Settings().value('media/vlc arguments')
output_display.vlc_instance = vlc.Instance(command_line_options)
controller.vlc_instance = vlc.Instance(command_line_options)
# creating an empty vlc media player
output_display.vlc_media_player = output_display.vlc_instance.media_player_new()
output_display.vlc_widget.resize(output_display.size())
output_display.vlc_widget.raise_()
output_display.vlc_widget.hide()
controller.vlc_media_player = controller.vlc_instance.media_player_new()
controller.vlc_widget.resize(controller.size())
controller.vlc_widget.raise_()
controller.vlc_widget.hide()
# The media player has to be 'connected' to the QFrame.
# (otherwise a video would be displayed in it's own window)
# This is platform specific!
# You have to give the id of the QFrame (or similar object)
# to vlc, different platforms have different functions for this.
win_id = int(output_display.vlc_widget.winId())
win_id = int(controller.vlc_widget.winId())
if is_win():
output_display.vlc_media_player.set_hwnd(win_id)
controller.vlc_media_player.set_hwnd(win_id)
elif is_macosx():
# We have to use 'set_nsobject' since Qt5 on OSX uses Cocoa
# framework and not the old Carbon.
output_display.vlc_media_player.set_nsobject(win_id)
controller.vlc_media_player.set_nsobject(win_id)
else:
# for Linux/*BSD using the X Server
output_display.vlc_media_player.set_xwindow(win_id)
controller.vlc_media_player.set_xwindow(win_id)
self.has_own_widget = True
def check_available(self):
@ -147,74 +147,77 @@ class VlcPlayer(MediaPlayer):
"""
return get_vlc() is not None
def load(self, output_display, file):
def load(self, controller, output_display, file):
"""
Load a video into VLC
:param controller: The controller where the media is
:param output_display: The display where the media is
:param file: file to be played or None for live streaming
:return:
"""
vlc = get_vlc()
log.debug('load vid in Vlc Controller')
path = None
if file:
path = os.path.normcase(file)
# create the media
if output_display.media_info.media_type == MediaType.CD:
if controller.media_info.media_type == MediaType.CD:
if is_win():
path = '/' + path
output_display.vlc_media = output_display.vlc_instance.media_new_location('cdda://' + path)
output_display.vlc_media_player.set_media(output_display.vlc_media)
output_display.vlc_media_player.play()
controller.vlc_media = controller.vlc_instance.media_new_location('cdda://' + path)
controller.vlc_media_player.set_media(controller.vlc_media)
controller.vlc_media_player.play()
# Wait for media to start playing. In this case VLC actually returns an error.
self.media_state_wait(output_display, vlc.State.Playing)
# If subitems exists, this is a CD
audio_cd_tracks = output_display.vlc_media.subitems()
audio_cd_tracks = controller.vlc_media.subitems()
if not audio_cd_tracks or audio_cd_tracks.count() < 1:
return False
output_display.vlc_media = audio_cd_tracks.item_at_index(output_display.media_info.title_track)
elif output_display.media_info.media_type == MediaType.Stream:
controller.vlc_media_player = audio_cd_tracks.item_at_index(controller.media_info.title_track)
elif controller.media_info.media_type == MediaType.Stream:
stream_cmd = Settings().value('media/stream command')
output_display.vlc_media = output_display.vlc_instance.media_new_location(stream_cmd)
controller.vlc_media = controller.vlc_instance.media_new_location(stream_cmd)
else:
output_display.vlc_media = output_display.vlc_instance.media_new_path(path)
controller.vlc_media = controller.vlc_instance.media_new_path(path)
# put the media in the media player
output_display.vlc_media_player.set_media(output_display.vlc_media)
controller.vlc_media_player.set_media(controller.vlc_media)
# parse the metadata of the file
output_display.vlc_media.parse()
self.volume(output_display, output_display.media_info.volume)
controller.vlc_media.parse()
self.volume(controller, controller.media_info.volume)
return True
def media_state_wait(self, output_display, media_state):
def media_state_wait(self, controller, media_state):
"""
Wait for the video to change its state
Wait no longer than 60 seconds. (loading an iso file needs a long time)
:param media_state: The state of the playing media
:param output_display: The display where the media is
:param controller: The controller where the media is
:return:
"""
vlc = get_vlc()
start = datetime.now()
while media_state != output_display.vlc_media.get_state():
if output_display.vlc_media.get_state() == vlc.State.Error:
while media_state != controller.vlc_media.get_state():
sleep(0.1)
if controller.vlc_media.get_state() == vlc.State.Error:
return False
self.application.process_events()
if (datetime.now() - start).seconds > 60:
return False
return True
def resize(self, output_display):
def resize(self, controller):
"""
Resize the player
:param output_display: The display where the media is
:param controller: The display where the media is stored within the controller.
:return:
"""
if output_display.is_display:
output_display.vlc_widget.setGeometry(ScreenList().current.display_geometry)
if controller.is_live:
controller.vlc_widget.setGeometry(ScreenList().current.display_geometry)
else:
output_display.vlc_widget.resize(output_display.size())
controller.vlc_widget.resize(controller.preview_display.size())
def play(self, controller, output_display):
"""
@ -227,119 +230,117 @@ class VlcPlayer(MediaPlayer):
vlc = get_vlc()
start_time = 0
log.debug('vlc play')
if output_display.is_display:
if self.get_live_state() != MediaState.Paused and output_display.media_info.start_time > 0:
start_time = output_display.media_info.start_time
if controller.is_live:
if self.get_live_state() != MediaState.Paused and controller.media_info.start_time > 0:
start_time = controller.media_info.start_time
else:
if self.get_preview_state() != MediaState.Paused and output_display.media_info.start_time > 0:
start_time = output_display.media_info.start_time
threading.Thread(target=output_display.vlc_media_player.play).start()
if not self.media_state_wait(output_display, vlc.State.Playing):
if self.get_preview_state() != MediaState.Paused and controller.media_info.start_time > 0:
start_time = controller.media_info.start_time
threading.Thread(target=controller.vlc_media_player.play).start()
if not self.media_state_wait(controller, vlc.State.Playing):
return False
if output_display.is_display:
if self.get_live_state() != MediaState.Paused and output_display.media_info.start_time > 0:
if controller.is_live:
if self.get_live_state() != MediaState.Paused and controller.media_info.start_time > 0:
log.debug('vlc play, start time set')
start_time = output_display.media_info.start_time
start_time = controller.media_info.start_time
else:
if self.get_preview_state() != MediaState.Paused and output_display.media_info.start_time > 0:
if self.get_preview_state() != MediaState.Paused and controller.media_info.start_time > 0:
log.debug('vlc play, start time set')
start_time = output_display.media_info.start_time
log.debug('mediatype: ' + str(output_display.media_info.media_type))
start_time = controller.media_info.start_time
log.debug('mediatype: ' + str(controller.media_info.media_type))
# Set tracks for the optical device
if output_display.media_info.media_type == MediaType.DVD and \
if controller.media_info.media_type == MediaType.DVD and \
self.get_live_state() != MediaState.Paused and self.get_preview_state() != MediaState.Paused:
log.debug('vlc play, playing started')
if output_display.media_info.title_track > 0:
log.debug('vlc play, title_track set: ' + str(output_display.media_info.title_track))
output_display.vlc_media_player.set_title(output_display.media_info.title_track)
output_display.vlc_media_player.play()
if not self.media_state_wait(output_display, vlc.State.Playing):
if controller.media_info.title_track > 0:
log.debug('vlc play, title_track set: ' + str(controller.media_info.title_track))
controller.vlc_media_player.set_title(controller.media_info.title_track)
controller.vlc_media_player.play()
if not self.media_state_wait(controller, vlc.State.Playing):
return False
if output_display.media_info.audio_track > 0:
output_display.vlc_media_player.audio_set_track(output_display.media_info.audio_track)
log.debug('vlc play, audio_track set: ' + str(output_display.media_info.audio_track))
if output_display.media_info.subtitle_track > 0:
output_display.vlc_media_player.video_set_spu(output_display.media_info.subtitle_track)
log.debug('vlc play, subtitle_track set: ' + str(output_display.media_info.subtitle_track))
if output_display.media_info.start_time > 0:
log.debug('vlc play, starttime set: ' + str(output_display.media_info.start_time))
start_time = output_display.media_info.start_time
output_display.media_info.length = output_display.media_info.end_time - output_display.media_info.start_time
self.volume(output_display, output_display.media_info.volume)
if start_time > 0 and output_display.vlc_media_player.is_seekable():
output_display.vlc_media_player.set_time(int(start_time))
if controller.media_info.audio_track > 0:
controller.vlc_media_player.audio_set_track(controller.media_info.audio_track)
log.debug('vlc play, audio_track set: ' + str(controller.media_info.audio_track))
if controller.media_info.subtitle_track > 0:
controller.vlc_media_player.video_set_spu(controller.media_info.subtitle_track)
log.debug('vlc play, subtitle_track set: ' + str(controller.media_info.subtitle_track))
if controller.media_info.start_time > 0:
log.debug('vlc play, starttime set: ' + str(controller.media_info.start_time))
start_time = controller.media_info.start_time
controller.media_info.length = controller.media_info.end_time - controller.media_info.start_time
self.volume(controller, controller.media_info.volume)
if start_time > 0 and controller.vlc_media_player.is_seekable():
controller.vlc_media_player.set_time(int(start_time))
controller.seek_slider.setMaximum(controller.media_info.length)
self.set_state(MediaState.Playing, output_display)
output_display.vlc_widget.raise_()
self.set_state(MediaState.Playing, controller)
controller.vlc_widget.raise_()
return True
def pause(self, output_display):
def pause(self, controller):
"""
Pause the current item
:param output_display: The display where the media is
:param controller: The controller which is managing the display
:return:
"""
vlc = get_vlc()
if output_display.vlc_media.get_state() != vlc.State.Playing:
if controller.vlc_media.get_state() != vlc.State.Playing:
return
output_display.vlc_media_player.pause()
if self.media_state_wait(output_display, vlc.State.Paused):
self.set_state(MediaState.Paused, output_display)
controller.vlc_media_player.pause()
if self.media_state_wait(controller, vlc.State.Paused):
self.set_state(MediaState.Paused, controller)
def stop(self, output_display):
def stop(self, controller):
"""
Stop the current item
:param output_display: The display where the media is
:param controller: The controller where the media is
:return:
"""
threading.Thread(target=output_display.vlc_media_player.stop).start()
self.set_state(MediaState.Stopped, output_display)
threading.Thread(target=controller.vlc_media_player.stop).start()
self.set_state(MediaState.Stopped, controller)
def volume(self, output_display, vol):
def volume(self, controller, vol):
"""
Set the volume
:param vol: The volume to be sets
:param output_display: The display where the media is
:param controller: The controller where the media is
:return:
"""
if output_display.has_audio:
output_display.vlc_media_player.audio_set_volume(vol)
controller.vlc_media_player.audio_set_volume(vol)
def seek(self, output_display, seek_value):
def seek(self, controller, seek_value):
"""
Go to a particular position
:param seek_value: The position of where a seek goes to
:param output_display: The display where the media is
:param controller: The controller where the media is
"""
if output_display.media_info.media_type == MediaType.CD \
or output_display.media_info.media_type == MediaType.DVD:
seek_value += int(output_display.media_info.start_time)
if output_display.vlc_media_player.is_seekable():
output_display.vlc_media_player.set_time(seek_value)
if controller.media_info.media_type == MediaType.CD \
or controller.media_info.media_type == MediaType.DVD:
seek_value += int(controller.media_info.start_time)
if controller.vlc_media_player.is_seekable():
controller.vlc_media_player.set_time(seek_value)
def reset(self, output_display):
def reset(self, controller):
"""
Reset the player
:param output_display: The display where the media is
:param controller: The controller where the media is
"""
output_display.vlc_media_player.stop()
output_display.vlc_widget.setVisible(False)
self.set_state(MediaState.Off, output_display)
controller.vlc_media_player.stop()
controller.vlc_widget.setVisible(False)
self.set_state(MediaState.Off, controller)
def set_visible(self, output_display, status):
def set_visible(self, controller, status):
"""
Set the visibility
:param output_display: The display where the media is
:param controller: The controller where the media display is
:param status: The visibility status
"""
if self.has_own_widget:
output_display.vlc_widget.setVisible(status)
controller.vlc_widget.setVisible(status)
def update_ui(self, controller, output_display):
"""
@ -350,18 +351,18 @@ class VlcPlayer(MediaPlayer):
"""
vlc = get_vlc()
# Stop video if playback is finished.
if output_display.vlc_media.get_state() == vlc.State.Ended:
self.stop(output_display)
if controller.vlc_media.get_state() == vlc.State.Ended:
self.stop(controller)
if controller.media_info.end_time > 0:
if output_display.vlc_media_player.get_time() > controller.media_info.end_time:
self.stop(output_display)
self.set_visible(output_display, False)
if controller.vlc_media_player.get_time() > controller.media_info.end_time:
self.stop(controller)
self.set_visible(controller, False)
if not controller.seek_slider.isSliderDown():
controller.seek_slider.blockSignals(True)
if controller.media_info.media_type == MediaType.CD \
or controller.media_info.media_type == MediaType.DVD:
controller.seek_slider.setSliderPosition(
output_display.vlc_media_player.get_time() - int(output_display.controller.media_info.start_time))
controller.vlc_media_player.get_time() - int(controller.media_info.start_time))
else:
controller.seek_slider.setSliderPosition(output_display.vlc_media_player.get_time())
controller.seek_slider.setSliderPosition(controller.vlc_media_player.get_time())
controller.seek_slider.blockSignals(False)

View File

@ -1241,7 +1241,7 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi
child = QtWidgets.QTreeWidgetItem(tree_widget_item)
# prefer to use a display_title
if service_item_from_item.is_capable(ItemCapabilities.HasDisplayTitle) or \
service_item_from_item.service_item_type == ServiceItemType.Image:
service_item_from_item.service_item_type is not ServiceItemType.Text:
text = slide['title'].replace('\n', ' ')
else:
text = service_item_from_item.get_rendered_frame(slide_index)

View File

@ -402,8 +402,6 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
self.mediabar.add_toolbar_widget(self.volume_slider)
self.controller_layout.addWidget(self.mediabar)
self.mediabar.setVisible(False)
if not self.is_live:
self.volume_slider.setEnabled(False)
# Signals
self.seek_slider.valueChanged.connect(self.send_to_plugins)
self.volume_slider.valueChanged.connect(self.send_to_plugins)
@ -885,6 +883,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
width = self.main_window.control_splitter.sizes()[self.split]
if self.service_item.is_text():
self.preview_display.load_verses(service_item.rendered_slides)
self.preview_display.show()
for display in self.displays:
display.load_verses(service_item.rendered_slides)
for slide_index, slide in enumerate(self.service_item.display_slides):
@ -909,17 +908,8 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
for slide_index, slide in enumerate(self.service_item.slides):
row += 1
self.slide_list[str(row)] = row - 1
# If current slide set background to image
# if not self.service_item.is_command() and slide_index == slide_no:
# self.service_item.bg_image_bytes = \
# self.image_manager.get_image_bytes(slide['filename'], ImageSource.ImagePlugin)
self.preview_widget.replace_service_item(self.service_item, width, slide_no)
self.enable_tool_bar(self.service_item)
# Pass to display for viewing.
# Postpone image build, we need to do this later to avoid the theme
# flashing on the screen
# if not self.service_item.is_image():
# self.display.build_html(self.service_item)
if self.service_item.is_media():
self.on_media_start(self.service_item)
self.slide_selected(True)
@ -1397,25 +1387,6 @@ class SlideController(QtWidgets.QWidget, 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_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()
def timerEvent(self, event):
"""
If the timer event is for this window select next slide
@ -1511,12 +1482,10 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
Respond to a request to close the Video
"""
self.media_controller.media_reset(self)
self.preview_display.hide()
def _reset_blank(self, no_theme):
"""
Used by command items which provide their own displays to reset the
screen hide attributes
Used by command items which provide their own displays to reset the screen hide attributes
:param no_theme: Does the new item support theme-blanking.
"""
@ -1549,30 +1518,6 @@ class SlideController(QtWidgets.QWidget, 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())
class PreviewController(RegistryBase, SlideController):
"""

View File

@ -71,7 +71,7 @@ class Ui_ThemeWizard(object):
self.background_label = QtWidgets.QLabel(self.background_page)
self.background_label.setObjectName('background_label')
self.background_combo_box = QtWidgets.QComboBox(self.background_page)
self.background_combo_box.addItems(['', '', '', '', '', ''])
self.background_combo_box.addItems(['', '', '', ''])
self.background_combo_box.setObjectName('background_combo_box')
self.background_type_layout.addRow(self.background_label, self.background_combo_box)
self.background_type_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
@ -421,11 +421,8 @@ class Ui_ThemeWizard(object):
self.background_combo_box.setItemText(BackgroundType.Solid, translate('OpenLP.ThemeWizard', 'Solid color'))
self.background_combo_box.setItemText(BackgroundType.Gradient, translate('OpenLP.ThemeWizard', 'Gradient'))
self.background_combo_box.setItemText(BackgroundType.Image, UiStrings().Image)
self.background_combo_box.setItemText(BackgroundType.Video, UiStrings().Video)
self.background_combo_box.setItemText(BackgroundType.Transparent,
translate('OpenLP.ThemeWizard', 'Transparent'))
self.background_combo_box.setItemText(BackgroundType.Stream,
translate('OpenLP.ThemeWizard', 'Live Stream'))
self.color_label.setText(translate('OpenLP.ThemeWizard', 'color:'))
self.gradient_start_label.setText(translate('OpenLP.ThemeWizard', 'Starting color:'))
self.gradient_end_label.setText(translate('OpenLP.ThemeWizard', 'Ending color:'))

View File

@ -256,7 +256,7 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro
titles = self.vlc_media_player.video_get_title_description()
self.titles_combo_box.clear()
for title in titles:
self.titles_combo_box.addItem(title[1].decode(), title[0])
self.titles_combo_box.addItem(title.name.decode(), title.id)
# Re-enable signals
self.blockSignals(False)
# Main title is usually title #1
@ -626,6 +626,7 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro
vlc = get_vlc()
start = datetime.now()
while media_state != self.vlc_media_player.get_state():
sleep(0.1)
if self.vlc_media_player.get_state() == vlc.State.Error:
return False
if (datetime.now() - start).seconds > 15:

View File

@ -240,7 +240,10 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
track_str = str(track)
track_info = QtCore.QFileInfo(track_str)
item_name = None
if track_str.startswith('optical:'):
# Dont add the live stream in when reloading the UI.
if track_str == UiStrings().LiveStream:
continue
elif track_str.startswith('optical:'):
# Handle optical based item
(file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track_str)
item_name = QtWidgets.QListWidgetItem(clip_name)

View File

@ -152,7 +152,7 @@ class ImpressController(PresentationController):
self.toggle_presentation_screen(False)
return desktop
except Exception:
log.warning('Failed to get UNO desktop')
log.exception('Failed to get UNO desktop')
return None
def get_com_desktop(self):
@ -232,7 +232,7 @@ class ImpressController(PresentationController):
self.conf_provider = self.manager.createInstanceWithContext(
'com.sun.star.configuration.ConfigurationProvider', uno.getComponentContext())
# Setup lookup properties to get Impress settings
properties = tuple(self.create_property('nodepath', 'org.openoffice.Office.Impress'))
properties = (self.create_property('nodepath', 'org.openoffice.Office.Impress'),)
try:
# Get an updateable configuration view
impress_conf_props = self.conf_provider.createInstanceWithArguments(
@ -308,7 +308,7 @@ class ImpressDocument(PresentationDocument):
if desktop is None:
return False
self.desktop = desktop
properties = tuple(self.controller.create_property('Hidden', True))
properties = (self.controller.create_property('Hidden', True),)
try:
self.document = desktop.loadComponentFromURL(url, '_blank', 0, properties)
except Exception:
@ -333,7 +333,7 @@ class ImpressDocument(PresentationDocument):
return
temp_folder_path = self.get_temp_folder()
thumb_dir_url = temp_folder_path.as_uri()
properties = tuple(self.controller.create_property('FilterName', 'impress_png_Export'))
properties = (self.controller.create_property('FilterName', 'impress_png_Export'),)
doc = self.document
pages = doc.getDrawPages()
if not pages:

View File

@ -144,7 +144,7 @@ class OpenOfficeImport(SongImport):
"""
self.file_path = file_path
url = file_path.as_uri()
properties = tuple(self.create_property('Hidden', True))
properties = (self.create_property('Hidden', True),)
try:
self.document = self.desktop.loadComponentFromURL(url, '_blank', 0, properties)
if not self.document.supportsService("com.sun.star.presentation.PresentationDocument") and not \

View File

@ -138,9 +138,9 @@ class TestMedia(TestCase, TestMixin):
(device_path, title_track, audio_track, subtitle_track, start, end, name) = parse_optical_path(path)
# THEN: The return values should match the original values
assert org_title_track == title_track, 'Returned title_track should match the original'
assert org_title_track == int(title_track), 'Returned title_track should match the original'
assert org_audio_track == audio_track, 'Returned audio_track should match the original'
assert org_subtitle_track == subtitle_track, 'Returned subtitle_track should match the original'
assert org_subtitle_track == int(subtitle_track), 'Returned subtitle_track should match the original'
assert org_start == start, 'Returned start should match the original'
assert org_end == end, 'Returned end should match the original'
assert org_name == name, 'Returned end should match the original'
@ -166,9 +166,9 @@ class TestMedia(TestCase, TestMixin):
(device_path, title_track, audio_track, subtitle_track, start, end, name) = parse_optical_path(path)
# THEN: The return values should match the original values
assert org_title_track == title_track, 'Returned title_track should match the original'
assert org_title_track == int(title_track), 'Returned title_track should match the original'
assert org_audio_track == audio_track, 'Returned audio_track should match the original'
assert org_subtitle_track == subtitle_track, 'Returned subtitle_track should match the original'
assert org_subtitle_track == int(subtitle_track), 'Returned subtitle_track should match the original'
assert org_start == start, 'Returned start should match the original'
assert org_end == end, 'Returned end should match the original'
assert org_name == name, 'Returned end should match the original'

View File

@ -28,7 +28,7 @@ from unittest import TestCase, skip
from unittest.mock import MagicMock, call, patch
from openlp.core.common.registry import Registry
from openlp.core.ui.media import MediaState, MediaType
from openlp.core.ui.media import ItemMediaInfo, MediaState, MediaType
from openlp.core.ui.media.vlcplayer import VlcPlayer, get_vlc
from tests.helpers import MockDateTime
from tests.helpers.testmixin import TestMixin
@ -127,7 +127,7 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player = VlcPlayer(None)
# WHEN: setup() is run
vlc_player.setup(mocked_output_display, mocked_controller)
vlc_player.setup(mocked_output_display, mocked_controller, True)
# THEN: The VLC widget should be set up correctly
assert mocked_output_display.vlc_widget == mocked_qframe
@ -177,7 +177,7 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player = VlcPlayer(None)
# WHEN: setup() is run
vlc_player.setup(mocked_output_display, mocked_controller)
vlc_player.setup(mocked_output_display, mocked_controller, True)
# THEN: The VLC instance should be created with the correct options
mocked_vlc.Instance.assert_called_with('--no-video-title-show ')
@ -215,7 +215,7 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player = VlcPlayer(None)
# WHEN: setup() is run
vlc_player.setup(mocked_output_display, mocked_controller)
vlc_player.setup(mocked_output_display, mocked_controller, True)
# THEN: The VLC instance should be created with the correct options
mocked_vlc.Instance.assert_called_with('--no-video-title-show ')
@ -252,7 +252,7 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player = VlcPlayer(None)
# WHEN: setup() is run
vlc_player.setup(mocked_output_display, mocked_controller)
vlc_player.setup(mocked_output_display, mocked_controller, True)
# THEN: set_hwnd should be called
mocked_media_player_new.set_hwnd.assert_called_with(2)
@ -289,7 +289,7 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player = VlcPlayer(None)
# WHEN: setup() is run
vlc_player.setup(mocked_output_display, mocked_controller)
vlc_player.setup(mocked_output_display, mocked_controller, True)
# THEN: set_nsobject should be called
mocked_media_player_new.set_nsobject.assert_called_with(2)
@ -336,27 +336,28 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
mocked_display = MagicMock()
mocked_display.media_info.volume = 100
mocked_display.media_info.media_type = MediaType.Video
mocked_display.media_info.file_info.absoluteFilePath.return_value = media_path
mocked_controller = MagicMock()
mocked_controller.media_info.volume = 100
mocked_controller.media_info.media_type = MediaType.Video
mocked_controller.media_info.file_info.absoluteFilePath.return_value = media_path
mocked_vlc_media = MagicMock()
mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000
mocked_display.vlc_instance.media_new_path.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media
mocked_controller.vlc_instance.media_new_path.return_value = mocked_vlc_media
mocked_controller.vlc_media_player.get_media.return_value = mocked_media
vlc_player = VlcPlayer(None)
# WHEN: A video is loaded into VLC
with patch.object(vlc_player, 'volume') as mocked_volume:
result = vlc_player.load(mocked_display, media_path)
result = vlc_player.load(mocked_controller, mocked_display, media_path)
# THEN: The video should be loaded
mocked_normcase.assert_called_with(media_path)
mocked_display.vlc_instance.media_new_path.assert_called_with(media_path)
assert mocked_vlc_media == mocked_display.vlc_media
mocked_display.vlc_media_player.set_media.assert_called_with(mocked_vlc_media)
mocked_controller.vlc_instance.media_new_path.assert_called_with(media_path)
assert mocked_vlc_media == mocked_controller.vlc_media
mocked_controller.vlc_media_player.set_media.assert_called_with(mocked_vlc_media)
mocked_vlc_media.parse.assert_called_with()
mocked_volume.assert_called_with(mocked_display, 100)
mocked_volume.assert_called_with(mocked_controller, 100)
assert result is True
@patch('openlp.core.ui.media.vlcplayer.is_win')
@ -373,14 +374,15 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
mocked_display = MagicMock()
mocked_display.media_info.volume = 100
mocked_display.media_info.media_type = MediaType.CD
mocked_display.media_info.title_track = 1
mocked_controller = MagicMock()
mocked_controller.media_info.volume = 100
mocked_controller.media_info.media_type = MediaType.CD
mocked_controller.media_info.title_track = 1
mocked_vlc_media = MagicMock()
mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000
mocked_display.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media
mocked_controller.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_controller.vlc_media_player.get_media.return_value = mocked_media
mocked_subitems = MagicMock()
mocked_subitems.count.return_value = 1
mocked_subitems.item_at_index.return_value = mocked_vlc_media
@ -390,15 +392,15 @@ class TestVLCPlayer(TestCase, TestMixin):
# WHEN: An audio CD is loaded into VLC
with patch.object(vlc_player, 'volume') as mocked_volume, \
patch.object(vlc_player, 'media_state_wait'):
result = vlc_player.load(mocked_display, media_path)
result = vlc_player.load(mocked_controller, mocked_display, media_path)
# THEN: The video should be loaded
mocked_normcase.assert_called_with(media_path)
mocked_display.vlc_instance.media_new_location.assert_called_with('cdda://' + media_path)
assert mocked_vlc_media == mocked_display.vlc_media
mocked_display.vlc_media_player.set_media.assert_called_with(mocked_vlc_media)
mocked_controller.vlc_instance.media_new_location.assert_called_with('cdda://' + media_path)
assert mocked_vlc_media == mocked_controller.vlc_media
mocked_controller.vlc_media_player.set_media.assert_called_with(mocked_vlc_media)
mocked_vlc_media.parse.assert_called_with()
mocked_volume.assert_called_with(mocked_display, 100)
mocked_volume.assert_called_with(mocked_controller, 100)
assert result is True
@patch('openlp.core.ui.media.vlcplayer.is_win')
@ -415,15 +417,16 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
mocked_display = MagicMock()
mocked_display.media_info.volume = 100
mocked_display.media_info.media_type = MediaType.CD
mocked_display.media_info.file_info.absoluteFilePath.return_value = media_path
mocked_display.media_info.title_track = 1
mocked_controller = MagicMock()
mocked_controller.media_info.volume = 100
mocked_controller.media_info.media_type = MediaType.CD
mocked_controller.media_info.file_info.absoluteFilePath.return_value = media_path
mocked_controller.media_info.title_track = 1
mocked_vlc_media = MagicMock()
mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000
mocked_display.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media
mocked_controller.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_controller.vlc_media_player.get_media.return_value = mocked_media
mocked_subitems = MagicMock()
mocked_subitems.count.return_value = 1
mocked_subitems.item_at_index.return_value = mocked_vlc_media
@ -433,15 +436,15 @@ class TestVLCPlayer(TestCase, TestMixin):
# WHEN: An audio CD is loaded into VLC
with patch.object(vlc_player, 'volume') as mocked_volume, \
patch.object(vlc_player, 'media_state_wait'):
result = vlc_player.load(mocked_display, media_path)
result = vlc_player.load(mocked_controller, mocked_display, media_path)
# THEN: The video should be loaded
mocked_normcase.assert_called_with(media_path)
mocked_display.vlc_instance.media_new_location.assert_called_with('cdda:///' + media_path)
assert mocked_vlc_media == mocked_display.vlc_media
mocked_display.vlc_media_player.set_media.assert_called_with(mocked_vlc_media)
mocked_controller.vlc_instance.media_new_location.assert_called_with('cdda:///' + media_path)
assert mocked_vlc_media == mocked_controller.vlc_media
mocked_controller.vlc_media_player.set_media.assert_called_with(mocked_vlc_media)
mocked_vlc_media.parse.assert_called_with()
mocked_volume.assert_called_with(mocked_display, 100)
mocked_volume.assert_called_with(mocked_controller, 100)
assert result is True
@patch('openlp.core.ui.media.vlcplayer.is_win')
@ -458,15 +461,19 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
mocked_display = MagicMock()
mocked_display.media_info.volume = 100
mocked_display.media_info.media_type = MediaType.CD
mocked_display.media_info.file_info.absoluteFilePath.return_value = media_path
mocked_display.media_info.title_track = 1
mocked_controller = MagicMock()
mocked_controller.media_info.volume = 100
mocked_controller.media_info.media_type = MediaType.CD
mocked_controller.media_info.file_info.absoluteFilePath.return_value = media_path
mocked_controller.media_info.title_track = 1
mocked_vlc_media = MagicMock()
mocked_vlc_media_player = MagicMock()
mocked_controller.vlc_media = mocked_vlc_media
mocked_controller.vlc_media_player = mocked_vlc_media_player
mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000
mocked_display.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media
mocked_controller.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_controller.vlc_media_player.get_media.return_value = mocked_media
mocked_subitems = MagicMock()
mocked_subitems.count.return_value = 0
mocked_subitems.item_at_index.return_value = mocked_vlc_media
@ -475,14 +482,14 @@ class TestVLCPlayer(TestCase, TestMixin):
# WHEN: An audio CD is loaded into VLC
with patch.object(vlc_player, 'volume'), patch.object(vlc_player, 'media_state_wait'):
result = vlc_player.load(mocked_display, media_path)
result = vlc_player.load(mocked_controller, mocked_display, media_path)
# THEN: The video should be loaded
mocked_normcase.assert_called_with(media_path)
mocked_display.vlc_instance.media_new_location.assert_called_with('cdda://' + media_path)
assert mocked_vlc_media == mocked_display.vlc_media
mocked_controller.vlc_instance.media_new_location.assert_called_with('cdda://' + media_path)
assert mocked_vlc_media == mocked_controller.vlc_media
assert 0 == mocked_subitems.item_at_index.call_count
mocked_display.vlc_media_player.set_media.assert_called_with(mocked_vlc_media)
mocked_controller.vlc_media_player.set_media.assert_called_with(mocked_vlc_media)
assert 0 == mocked_vlc_media.parse.call_count
assert result is False
@ -562,17 +569,17 @@ class TestVLCPlayer(TestCase, TestMixin):
Test resizing the player
"""
# GIVEN: A display object and a VlcPlayer instance
mocked_display = MagicMock()
mocked_display.size.return_value = (10, 10)
mocked_display.is_display = False
mocked_controller = MagicMock()
mocked_controller.preview_display.size.return_value = (10, 10)
mocked_controller.is_live = False
vlc_player = VlcPlayer(None)
# WHEN: resize is called
vlc_player.resize(mocked_display)
vlc_player.resize(mocked_controller)
# THEN: The right methods should have been called
mocked_display.size.assert_called_with()
mocked_display.vlc_widget.resize.assert_called_with((10, 10))
mocked_controller.preview_display.size.assert_called_with()
mocked_controller.vlc_widget.resize.assert_called_with((10, 10))
@patch('openlp.core.ui.media.vlcplayer.threading')
@patch('openlp.core.ui.media.vlcplayer.get_vlc')
@ -586,27 +593,27 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
mocked_display = MagicMock()
mocked_controller = MagicMock()
mocked_media = MagicMock()
mocked_media.get_duration.return_value = 50000
mocked_output_display = MagicMock()
mocked_output_display.media_info.start_time = 0
mocked_output_display.media_info.media_type = MediaType.Video
mocked_output_display.media_info.volume = 100
mocked_output_display.vlc_media_player.get_media.return_value = mocked_media
mocked_controller.media_info.start_time = 0
mocked_controller.media_info.media_type = MediaType.Video
mocked_controller.media_info.volume = 100
mocked_controller.vlc_media_player.get_media.return_value = mocked_media
vlc_player = VlcPlayer(None)
vlc_player.set_state(MediaState.Paused, mocked_output_display)
vlc_player.set_state(MediaState.Paused, mocked_controller)
# WHEN: play() is called
with patch.object(vlc_player, 'media_state_wait') as mocked_media_state_wait, \
patch.object(vlc_player, 'volume') as mocked_volume:
mocked_media_state_wait.return_value = True
result = vlc_player.play(mocked_display, mocked_output_display)
result = vlc_player.play(mocked_controller, mocked_display)
# THEN: A bunch of things should happen to play the media
mocked_thread.start.assert_called_with()
mocked_volume.assert_called_with(mocked_output_display, 100)
mocked_volume.assert_called_with(mocked_controller, 100)
assert MediaState.Playing == vlc_player.get_live_state()
mocked_output_display.vlc_widget.raise_.assert_called_with()
mocked_controller.vlc_widget.raise_.assert_called_with()
assert result is True, 'The value returned from play() should be True'
@patch('openlp.core.ui.media.vlcplayer.threading')
@ -649,13 +656,14 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_get_vlc.return_value = mocked_vlc
mocked_controller = MagicMock()
mocked_output_display = MagicMock()
mocked_output_display.media_info.start_time = 0
mocked_output_display.media_info.end_time = 50
mocked_output_display.media_info.media_type = MediaType.DVD
mocked_output_display.media_info.volume = 100
mocked_output_display.media_info.title_track = 1
mocked_output_display.media_info.audio_track = 1
mocked_output_display.media_info.subtitle_track = 1
mocked_controller.media_info = ItemMediaInfo()
mocked_controller.media_info.start_time = 0
mocked_controller.media_info.end_time = 50
mocked_controller.media_info.media_type = MediaType.DVD
mocked_controller.media_info.volume = 100
mocked_controller.media_info.title_track = 1
mocked_controller.media_info.audio_track = 1
mocked_controller.media_info.subtitle_track = 1
vlc_player = VlcPlayer(None)
vlc_player.set_state(MediaState.Paused, mocked_output_display)
@ -667,13 +675,13 @@ class TestVLCPlayer(TestCase, TestMixin):
# THEN: A bunch of things should happen to play the media
mocked_thread.start.assert_called_with()
mocked_output_display.vlc_media_player.set_title.assert_called_with(1)
mocked_output_display.vlc_media_player.play.assert_called_with()
mocked_output_display.vlc_media_player.audio_set_track.assert_called_with(1)
mocked_output_display.vlc_media_player.video_set_spu.assert_called_with(1)
mocked_volume.assert_called_with(mocked_output_display, 100)
mocked_controller.vlc_media_player.set_title.assert_called_with(1)
mocked_controller.vlc_media_player.play.assert_called_with()
mocked_controller.vlc_media_player.audio_set_track.assert_called_with(1)
mocked_controller.vlc_media_player.video_set_spu.assert_called_with(1)
mocked_volume.assert_called_with(mocked_controller, 100)
assert MediaState.Playing == vlc_player.get_live_state()
mocked_output_display.vlc_widget.raise_.assert_called_with()
mocked_controller.vlc_widget.raise_.assert_called_with()
assert result is True, 'The value returned from play() should be True'
@patch('openlp.core.ui.media.vlcplayer.get_vlc')
@ -782,21 +790,6 @@ class TestVLCPlayer(TestCase, TestMixin):
# THEN: The volume should have been set
mocked_display.vlc_media_player.audio_set_volume.assert_called_with(10)
def test_volume_no_audio(self):
"""
Test setting the volume when there's no audio
"""
# GIVEN: A display object and a VlcPlayer instance
mocked_display = MagicMock()
mocked_display.has_audio = False
vlc_player = VlcPlayer(None)
# WHEN: The volume is set
vlc_player.volume(mocked_display, 10)
# THEN: The volume should NOT have been set
assert 0 == mocked_display.vlc_media_player.audio_set_volume.call_count
def test_seek_unseekable_media(self):
"""
Test seeking something that can't be seeked
@ -880,21 +873,6 @@ class TestVLCPlayer(TestCase, TestMixin):
# THEN: The media should be stopped and invsibile
mocked_display.vlc_widget.setVisible.assert_called_with(True)
def test_set_visible_no_widget(self):
"""
Test the set_visible() method when the player doesn't have a widget
"""
# GIVEN: Some mocked out stuff
mocked_display = MagicMock()
vlc_player = VlcPlayer(None)
vlc_player.has_own_widget = False
# WHEN: reset() is called
vlc_player.set_visible(mocked_display, True)
# THEN: The media should be stopped and invsibile
assert 0 == mocked_display.vlc_widget.setVisible.call_count
@patch('openlp.core.ui.media.vlcplayer.get_vlc')
def test_update_ui(self, mocked_get_vlc):
"""
@ -908,8 +886,8 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_controller.media_info.end_time = 300
mocked_controller.seek_slider.isSliderDown.return_value = False
mocked_display = MagicMock()
mocked_display.vlc_media.get_state.return_value = 1
mocked_display.vlc_media_player.get_time.return_value = 400000
mocked_controller.vlc_media.get_state.return_value = 1
mocked_controller.vlc_media_player.get_time.return_value = 400000
vlc_player = VlcPlayer(None)
# WHEN: update_ui() is called
@ -918,10 +896,10 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player.update_ui(mocked_controller, mocked_display)
# THEN: Certain methods should be called
mocked_stop.assert_called_with(mocked_display)
mocked_stop.assert_called_with(mocked_controller)
assert 2 == mocked_stop.call_count
mocked_display.vlc_media_player.get_time.assert_called_with()
mocked_set_visible.assert_called_with(mocked_display, False)
mocked_controller.vlc_media_player.get_time.assert_called_with()
mocked_set_visible.assert_called_with(mocked_controller, False)
mocked_controller.seek_slider.setSliderPosition.assert_called_with(400000)
expected_calls = [call(True), call(False)]
assert expected_calls == mocked_controller.seek_slider.blockSignals.call_args_list
@ -936,13 +914,14 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc.State.Ended = 1
mocked_get_vlc.return_value = mocked_vlc
mocked_controller = MagicMock()
mocked_controller.media_info = ItemMediaInfo()
mocked_controller.media_info.start_time = 100
mocked_controller.media_info.end_time = 300
mocked_controller.seek_slider.isSliderDown.return_value = False
mocked_display = MagicMock()
mocked_display.vlc_media.get_state.return_value = 1
mocked_display.vlc_media_player.get_time.return_value = 300
mocked_display.controller.media_info.media_type = MediaType.DVD
mocked_controller.vlc_media.get_state.return_value = 1
mocked_controller.vlc_media_player.get_time.return_value = 300
mocked_controller.media_info.media_type = MediaType.DVD
vlc_player = VlcPlayer(None)
# WHEN: update_ui() is called
@ -950,9 +929,9 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player.update_ui(mocked_controller, mocked_display)
# THEN: Certain methods should be called
mocked_stop.assert_called_with(mocked_display)
mocked_stop.assert_called_with(mocked_controller)
assert 1 == mocked_stop.call_count
mocked_display.vlc_media_player.get_time.assert_called_with()
mocked_controller.seek_slider.setSliderPosition.assert_called_with(300)
mocked_controller.vlc_media_player.get_time.assert_called_with()
mocked_controller.seek_slider.setSliderPosition.assert_called_with(200)
expected_calls = [call(True), call(False)]
assert expected_calls == mocked_controller.seek_slider.blockSignals.call_args_list

View File

@ -24,7 +24,7 @@ Functional tests to test the Impress class and related methods.
import shutil
from tempfile import mkdtemp
from unittest import TestCase
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock, call, patch
from openlp.core.common.settings import Settings
from openlp.plugins.presentations.lib.impresscontroller import ImpressController, ImpressDocument, TextType
@ -86,7 +86,7 @@ class TestImpressController(TestCase, TestMixin):
assert result is False
@patch('openlp.plugins.presentations.lib.impresscontroller.log')
def test_check_available1(self, mocked_log):
def test_check_available_on_windows(self, mocked_log):
"""
Test `ImpressController.check_available` on Windows
"""
@ -106,7 +106,7 @@ class TestImpressController(TestCase, TestMixin):
@patch('openlp.plugins.presentations.lib.impresscontroller.log')
@patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=False)
def test_check_available2(self, mocked_is_win, mocked_log):
def test_check_available_on_linux(self, mocked_is_win, mocked_log):
"""
Test `ImpressController.check_available` when not on Windows
"""
@ -122,6 +122,44 @@ class TestImpressController(TestCase, TestMixin):
assert mocked_get_com_servicemanager.called is False
assert result is True
@patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=True)
def test_start_process_on_windows(self, mocked_is_win):
"""
Test that start_process() on Windows starts the process
"""
# GIVEN: An ImpressController object
controller = ImpressController(plugin=self.mock_plugin)
controller.get_com_servicemanager = MagicMock(return_value=MagicMock())
# WHEN: start_process() is called
controller.start_process()
# THEN: The correct methods should have been called
controller.get_com_servicemanager.assert_called_once()
assert controller.manager._FlagAsMethod.call_args_list == [call('Bridge_GetStruct'),
call('Bridge_GetValueObject')]
@patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=False)
@patch('openlp.plugins.presentations.lib.impresscontroller.get_uno_command', return_value='libreoffice')
@patch('openlp.plugins.presentations.lib.impresscontroller.QtCore.QProcess')
def test_start_process_on_linux(self, MockQProcess, mocked_get_uno_command, mocked_is_win):
"""
Test that start_process() on Linux starts the process
"""
# GIVEN: An ImpressController object
mocked_process = MagicMock()
MockQProcess.return_value = mocked_process
controller = ImpressController(plugin=self.mock_plugin)
# WHEN: start_process() is called
controller.start_process()
# THEN: The correct methods should have been called
mocked_get_uno_command.assert_called_once()
MockQProcess.assert_called_once()
assert controller.process is mocked_process
mocked_process.startDetached.assert_called_once_with('libreoffice')
class TestImpressDocument(TestCase):
"""