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/vlc arguments': '',
'media/video': '', 'media/video': '',
'media/audio': '', 'media/audio': '',
'media/live volume': 50,
'media/preview volume': 0,
'remotes/download version': '0.0', 'remotes/download version': '0.0',
'players/background color': '#000000', 'players/background color': '#000000',
'servicemanager/last directory': None, 'servicemanager/last directory': None,

View File

@ -214,7 +214,6 @@ class ServiceItem(RegistryProperties):
""" """
Render the frames for printing and return them 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: if not self._print_slides:
self._print_slides = [] self._print_slides = []
@ -345,7 +344,11 @@ class ServiceItem(RegistryProperties):
service_data = [slide['title'] for slide in self.slides] service_data = [slide['title'] for slide in self.slides]
elif self.service_item_type == ServiceItemType.Command: elif self.service_item_type == ServiceItemType.Command:
for slide in self.slides: 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']}) 'display_title': slide['display_title'], 'notes': slide['notes']})
return {'header': service_header, 'data': service_data} 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']) self.add_from_command(text_image['path'], text_image['title'], text_image['image'])
elif path: elif path:
self.has_original_files = False 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'], self.add_from_command(path, text_image['title'], text_image['image'],
text_image.get('display_title', ''), text_image.get('notes', '')) text_image.get('display_title', ''), text_image.get('notes', ''))
else: else:
@ -631,7 +636,7 @@ class ServiceItem(RegistryProperties):
""" """
Validates a service item to make sure it is valid 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 self.is_valid = True
for slide in self.slides: for slide in self.slides:
@ -649,7 +654,7 @@ class ServiceItem(RegistryProperties):
self.is_valid = False self.is_valid = False
break break
if suffixes and not self.is_text(): 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: if file_suffix.lower() not in suffixes:
self.is_valid = False self.is_valid = False
break break

View File

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

View File

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

View File

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

View File

@ -27,6 +27,7 @@ import os
import sys import sys
import threading import threading
from datetime import datetime from datetime import datetime
from time import sleep
from PyQt5 import QtCore, QtWidgets from PyQt5 import QtCore, QtWidgets
@ -95,50 +96,49 @@ class VlcPlayer(MediaPlayer):
self.parent = parent self.parent = parent
self.can_folder = True self.can_folder = True
def setup(self, output_display, live_display): def setup(self, controller, display, live_display):
""" """
Set up the media player 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. :param live_display: Is the display a live one.
:return: :return:
""" """
vlc = get_vlc() vlc = get_vlc()
if output_display.is_display: if controller.is_live:
output_display.vlc_widget = QtWidgets.QFrame() controller.vlc_widget = QtWidgets.QFrame()
output_display.vlc_widget.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | controller.vlc_widget.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool |
QtCore.Qt.WindowStaysOnTopHint) QtCore.Qt.WindowStaysOnTopHint)
else: else:
output_display.vlc_widget = QtWidgets.QFrame(output_display) controller.vlc_widget = QtWidgets.QFrame(display)
output_display.vlc_widget.setFrameStyle(QtWidgets.QFrame.NoFrame) controller.vlc_widget.setFrameStyle(QtWidgets.QFrame.NoFrame)
# creating a basic vlc instance # creating a basic vlc instance
command_line_options = '--no-video-title-show ' command_line_options = '--no-video-title-show '
if Settings().value('advanced/hide mouse') and live_display: if Settings().value('advanced/hide mouse') and live_display:
command_line_options += '--mouse-hide-timeout=0 ' command_line_options += '--mouse-hide-timeout=0 '
if Settings().value('media/vlc arguments'): if Settings().value('media/vlc arguments'):
command_line_options += 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 # creating an empty vlc media player
output_display.vlc_media_player = output_display.vlc_instance.media_player_new() controller.vlc_media_player = controller.vlc_instance.media_player_new()
output_display.vlc_widget.resize(output_display.size()) controller.vlc_widget.resize(controller.size())
output_display.vlc_widget.raise_() controller.vlc_widget.raise_()
output_display.vlc_widget.hide() controller.vlc_widget.hide()
# The media player has to be 'connected' to the QFrame. # The media player has to be 'connected' to the QFrame.
# (otherwise a video would be displayed in it's own window) # (otherwise a video would be displayed in it's own window)
# This is platform specific! # This is platform specific!
# You have to give the id of the QFrame (or similar object) # You have to give the id of the QFrame (or similar object)
# to vlc, different platforms have different functions for this. # 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(): if is_win():
output_display.vlc_media_player.set_hwnd(win_id) controller.vlc_media_player.set_hwnd(win_id)
elif is_macosx(): elif is_macosx():
# We have to use 'set_nsobject' since Qt5 on OSX uses Cocoa # We have to use 'set_nsobject' since Qt5 on OSX uses Cocoa
# framework and not the old Carbon. # framework and not the old Carbon.
output_display.vlc_media_player.set_nsobject(win_id) controller.vlc_media_player.set_nsobject(win_id)
else: else:
# for Linux/*BSD using the X Server # 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 self.has_own_widget = True
def check_available(self): def check_available(self):
@ -147,74 +147,77 @@ class VlcPlayer(MediaPlayer):
""" """
return get_vlc() is not None return get_vlc() is not None
def load(self, output_display, file): def load(self, controller, output_display, file):
""" """
Load a video into VLC Load a video into VLC
:param controller: The controller where the media is
:param output_display: The display where the media is :param output_display: The display where the media is
:param file: file to be played or None for live streaming :param file: file to be played or None for live streaming
:return: :return:
""" """
vlc = get_vlc() vlc = get_vlc()
log.debug('load vid in Vlc Controller') log.debug('load vid in Vlc Controller')
path = None
if file: if file:
path = os.path.normcase(file) path = os.path.normcase(file)
# create the media # create the media
if output_display.media_info.media_type == MediaType.CD: if controller.media_info.media_type == MediaType.CD:
if is_win(): if is_win():
path = '/' + path path = '/' + path
output_display.vlc_media = output_display.vlc_instance.media_new_location('cdda://' + path) controller.vlc_media = controller.vlc_instance.media_new_location('cdda://' + path)
output_display.vlc_media_player.set_media(output_display.vlc_media) controller.vlc_media_player.set_media(controller.vlc_media)
output_display.vlc_media_player.play() controller.vlc_media_player.play()
# Wait for media to start playing. In this case VLC actually returns an error. # Wait for media to start playing. In this case VLC actually returns an error.
self.media_state_wait(output_display, vlc.State.Playing) self.media_state_wait(output_display, vlc.State.Playing)
# If subitems exists, this is a CD # 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: if not audio_cd_tracks or audio_cd_tracks.count() < 1:
return False return False
output_display.vlc_media = audio_cd_tracks.item_at_index(output_display.media_info.title_track) controller.vlc_media_player = audio_cd_tracks.item_at_index(controller.media_info.title_track)
elif output_display.media_info.media_type == MediaType.Stream: elif controller.media_info.media_type == MediaType.Stream:
stream_cmd = Settings().value('media/stream command') 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: 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 # 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 # parse the metadata of the file
output_display.vlc_media.parse() controller.vlc_media.parse()
self.volume(output_display, output_display.media_info.volume) self.volume(controller, controller.media_info.volume)
return True 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 for the video to change its state
Wait no longer than 60 seconds. (loading an iso file needs a long time) Wait no longer than 60 seconds. (loading an iso file needs a long time)
:param media_state: The state of the playing media :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: :return:
""" """
vlc = get_vlc() vlc = get_vlc()
start = datetime.now() start = datetime.now()
while media_state != output_display.vlc_media.get_state(): while media_state != controller.vlc_media.get_state():
if output_display.vlc_media.get_state() == vlc.State.Error: sleep(0.1)
if controller.vlc_media.get_state() == vlc.State.Error:
return False return False
self.application.process_events() self.application.process_events()
if (datetime.now() - start).seconds > 60: if (datetime.now() - start).seconds > 60:
return False return False
return True return True
def resize(self, output_display): def resize(self, controller):
""" """
Resize the player 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: :return:
""" """
if output_display.is_display: if controller.is_live:
output_display.vlc_widget.setGeometry(ScreenList().current.display_geometry) controller.vlc_widget.setGeometry(ScreenList().current.display_geometry)
else: else:
output_display.vlc_widget.resize(output_display.size()) controller.vlc_widget.resize(controller.preview_display.size())
def play(self, controller, output_display): def play(self, controller, output_display):
""" """
@ -227,119 +230,117 @@ class VlcPlayer(MediaPlayer):
vlc = get_vlc() vlc = get_vlc()
start_time = 0 start_time = 0
log.debug('vlc play') log.debug('vlc play')
if output_display.is_display: if controller.is_live:
if self.get_live_state() != MediaState.Paused and output_display.media_info.start_time > 0: if self.get_live_state() != MediaState.Paused and controller.media_info.start_time > 0:
start_time = output_display.media_info.start_time start_time = controller.media_info.start_time
else: 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:
start_time = output_display.media_info.start_time start_time = controller.media_info.start_time
threading.Thread(target=output_display.vlc_media_player.play).start() threading.Thread(target=controller.vlc_media_player.play).start()
if not self.media_state_wait(output_display, vlc.State.Playing): if not self.media_state_wait(controller, vlc.State.Playing):
return False return False
if output_display.is_display: if controller.is_live:
if self.get_live_state() != MediaState.Paused and output_display.media_info.start_time > 0: if self.get_live_state() != MediaState.Paused and controller.media_info.start_time > 0:
log.debug('vlc play, start time set') log.debug('vlc play, start time set')
start_time = output_display.media_info.start_time start_time = controller.media_info.start_time
else: 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') log.debug('vlc play, start time set')
start_time = output_display.media_info.start_time start_time = controller.media_info.start_time
log.debug('mediatype: ' + str(output_display.media_info.media_type)) log.debug('mediatype: ' + str(controller.media_info.media_type))
# Set tracks for the optical device # 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: self.get_live_state() != MediaState.Paused and self.get_preview_state() != MediaState.Paused:
log.debug('vlc play, playing started') log.debug('vlc play, playing started')
if output_display.media_info.title_track > 0: if controller.media_info.title_track > 0:
log.debug('vlc play, title_track set: ' + str(output_display.media_info.title_track)) log.debug('vlc play, title_track set: ' + str(controller.media_info.title_track))
output_display.vlc_media_player.set_title(output_display.media_info.title_track) controller.vlc_media_player.set_title(controller.media_info.title_track)
output_display.vlc_media_player.play() controller.vlc_media_player.play()
if not self.media_state_wait(output_display, vlc.State.Playing): if not self.media_state_wait(controller, vlc.State.Playing):
return False return False
if output_display.media_info.audio_track > 0: if controller.media_info.audio_track > 0:
output_display.vlc_media_player.audio_set_track(output_display.media_info.audio_track) controller.vlc_media_player.audio_set_track(controller.media_info.audio_track)
log.debug('vlc play, audio_track set: ' + str(output_display.media_info.audio_track)) log.debug('vlc play, audio_track set: ' + str(controller.media_info.audio_track))
if output_display.media_info.subtitle_track > 0: if controller.media_info.subtitle_track > 0:
output_display.vlc_media_player.video_set_spu(output_display.media_info.subtitle_track) controller.vlc_media_player.video_set_spu(controller.media_info.subtitle_track)
log.debug('vlc play, subtitle_track set: ' + str(output_display.media_info.subtitle_track)) log.debug('vlc play, subtitle_track set: ' + str(controller.media_info.subtitle_track))
if output_display.media_info.start_time > 0: if controller.media_info.start_time > 0:
log.debug('vlc play, starttime set: ' + str(output_display.media_info.start_time)) log.debug('vlc play, starttime set: ' + str(controller.media_info.start_time))
start_time = output_display.media_info.start_time start_time = controller.media_info.start_time
output_display.media_info.length = output_display.media_info.end_time - output_display.media_info.start_time controller.media_info.length = controller.media_info.end_time - controller.media_info.start_time
self.volume(output_display, output_display.media_info.volume) self.volume(controller, controller.media_info.volume)
if start_time > 0 and output_display.vlc_media_player.is_seekable(): if start_time > 0 and controller.vlc_media_player.is_seekable():
output_display.vlc_media_player.set_time(int(start_time)) controller.vlc_media_player.set_time(int(start_time))
controller.seek_slider.setMaximum(controller.media_info.length) controller.seek_slider.setMaximum(controller.media_info.length)
self.set_state(MediaState.Playing, output_display) self.set_state(MediaState.Playing, controller)
output_display.vlc_widget.raise_() controller.vlc_widget.raise_()
return True return True
def pause(self, output_display): def pause(self, controller):
""" """
Pause the current item Pause the current item
:param output_display: The display where the media is :param controller: The controller which is managing the display
:return: :return:
""" """
vlc = get_vlc() vlc = get_vlc()
if output_display.vlc_media.get_state() != vlc.State.Playing: if controller.vlc_media.get_state() != vlc.State.Playing:
return return
output_display.vlc_media_player.pause() controller.vlc_media_player.pause()
if self.media_state_wait(output_display, vlc.State.Paused): if self.media_state_wait(controller, vlc.State.Paused):
self.set_state(MediaState.Paused, output_display) self.set_state(MediaState.Paused, controller)
def stop(self, output_display): def stop(self, controller):
""" """
Stop the current item Stop the current item
:param output_display: The display where the media is :param controller: The controller where the media is
:return: :return:
""" """
threading.Thread(target=output_display.vlc_media_player.stop).start() threading.Thread(target=controller.vlc_media_player.stop).start()
self.set_state(MediaState.Stopped, output_display) self.set_state(MediaState.Stopped, controller)
def volume(self, output_display, vol): def volume(self, controller, vol):
""" """
Set the volume Set the volume
:param vol: The volume to be sets :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: :return:
""" """
if output_display.has_audio: controller.vlc_media_player.audio_set_volume(vol)
output_display.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 Go to a particular position
:param seek_value: The position of where a seek goes to :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 \ if controller.media_info.media_type == MediaType.CD \
or output_display.media_info.media_type == MediaType.DVD: or controller.media_info.media_type == MediaType.DVD:
seek_value += int(output_display.media_info.start_time) seek_value += int(controller.media_info.start_time)
if output_display.vlc_media_player.is_seekable(): if controller.vlc_media_player.is_seekable():
output_display.vlc_media_player.set_time(seek_value) controller.vlc_media_player.set_time(seek_value)
def reset(self, output_display): def reset(self, controller):
""" """
Reset the player 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() controller.vlc_media_player.stop()
output_display.vlc_widget.setVisible(False) controller.vlc_widget.setVisible(False)
self.set_state(MediaState.Off, output_display) self.set_state(MediaState.Off, controller)
def set_visible(self, output_display, status): def set_visible(self, controller, status):
""" """
Set the visibility 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 :param status: The visibility status
""" """
if self.has_own_widget: controller.vlc_widget.setVisible(status)
output_display.vlc_widget.setVisible(status)
def update_ui(self, controller, output_display): def update_ui(self, controller, output_display):
""" """
@ -350,18 +351,18 @@ class VlcPlayer(MediaPlayer):
""" """
vlc = get_vlc() vlc = get_vlc()
# Stop video if playback is finished. # Stop video if playback is finished.
if output_display.vlc_media.get_state() == vlc.State.Ended: if controller.vlc_media.get_state() == vlc.State.Ended:
self.stop(output_display) self.stop(controller)
if controller.media_info.end_time > 0: if controller.media_info.end_time > 0:
if output_display.vlc_media_player.get_time() > controller.media_info.end_time: if controller.vlc_media_player.get_time() > controller.media_info.end_time:
self.stop(output_display) self.stop(controller)
self.set_visible(output_display, False) self.set_visible(controller, False)
if not controller.seek_slider.isSliderDown(): if not controller.seek_slider.isSliderDown():
controller.seek_slider.blockSignals(True) controller.seek_slider.blockSignals(True)
if controller.media_info.media_type == MediaType.CD \ if controller.media_info.media_type == MediaType.CD \
or controller.media_info.media_type == MediaType.DVD: or controller.media_info.media_type == MediaType.DVD:
controller.seek_slider.setSliderPosition( 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: 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) 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) child = QtWidgets.QTreeWidgetItem(tree_widget_item)
# prefer to use a display_title # prefer to use a display_title
if service_item_from_item.is_capable(ItemCapabilities.HasDisplayTitle) or \ 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', ' ') text = slide['title'].replace('\n', ' ')
else: else:
text = service_item_from_item.get_rendered_frame(slide_index) 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.mediabar.add_toolbar_widget(self.volume_slider)
self.controller_layout.addWidget(self.mediabar) self.controller_layout.addWidget(self.mediabar)
self.mediabar.setVisible(False) self.mediabar.setVisible(False)
if not self.is_live:
self.volume_slider.setEnabled(False)
# Signals # Signals
self.seek_slider.valueChanged.connect(self.send_to_plugins) self.seek_slider.valueChanged.connect(self.send_to_plugins)
self.volume_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] width = self.main_window.control_splitter.sizes()[self.split]
if self.service_item.is_text(): if self.service_item.is_text():
self.preview_display.load_verses(service_item.rendered_slides) self.preview_display.load_verses(service_item.rendered_slides)
self.preview_display.show()
for display in self.displays: for display in self.displays:
display.load_verses(service_item.rendered_slides) display.load_verses(service_item.rendered_slides)
for slide_index, slide in enumerate(self.service_item.display_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): for slide_index, slide in enumerate(self.service_item.slides):
row += 1 row += 1
self.slide_list[str(row)] = 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.preview_widget.replace_service_item(self.service_item, width, slide_no)
self.enable_tool_bar(self.service_item) 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(): if self.service_item.is_media():
self.on_media_start(self.service_item) self.on_media_start(self.service_item)
self.slide_selected(True) self.slide_selected(True)
@ -1397,25 +1387,6 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
self.play_slides_once.setText(UiStrings().PlaySlidesToEnd) self.play_slides_once.setText(UiStrings().PlaySlidesToEnd)
self.on_toggle_loop() 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): def timerEvent(self, event):
""" """
If the timer event is for this window select next slide 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 Respond to a request to close the Video
""" """
self.media_controller.media_reset(self) self.media_controller.media_reset(self)
self.preview_display.hide()
def _reset_blank(self, no_theme): def _reset_blank(self, no_theme):
""" """
Used by command items which provide their own displays to reset the Used by command items which provide their own displays to reset the screen hide attributes
screen hide attributes
:param no_theme: Does the new item support theme-blanking. :param no_theme: Does the new item support theme-blanking.
""" """
@ -1549,30 +1518,6 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
else: else:
return None 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): 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 = QtWidgets.QLabel(self.background_page)
self.background_label.setObjectName('background_label') self.background_label.setObjectName('background_label')
self.background_combo_box = QtWidgets.QComboBox(self.background_page) 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_combo_box.setObjectName('background_combo_box')
self.background_type_layout.addRow(self.background_label, self.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) 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.Solid, translate('OpenLP.ThemeWizard', 'Solid color'))
self.background_combo_box.setItemText(BackgroundType.Gradient, translate('OpenLP.ThemeWizard', 'Gradient')) 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.Image, UiStrings().Image)
self.background_combo_box.setItemText(BackgroundType.Video, UiStrings().Video)
self.background_combo_box.setItemText(BackgroundType.Transparent, self.background_combo_box.setItemText(BackgroundType.Transparent,
translate('OpenLP.ThemeWizard', '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.color_label.setText(translate('OpenLP.ThemeWizard', 'color:'))
self.gradient_start_label.setText(translate('OpenLP.ThemeWizard', 'Starting color:')) self.gradient_start_label.setText(translate('OpenLP.ThemeWizard', 'Starting color:'))
self.gradient_end_label.setText(translate('OpenLP.ThemeWizard', 'Ending 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() titles = self.vlc_media_player.video_get_title_description()
self.titles_combo_box.clear() self.titles_combo_box.clear()
for title in titles: 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 # Re-enable signals
self.blockSignals(False) self.blockSignals(False)
# Main title is usually title #1 # Main title is usually title #1
@ -626,6 +626,7 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro
vlc = get_vlc() vlc = get_vlc()
start = datetime.now() start = datetime.now()
while media_state != self.vlc_media_player.get_state(): while media_state != self.vlc_media_player.get_state():
sleep(0.1)
if self.vlc_media_player.get_state() == vlc.State.Error: if self.vlc_media_player.get_state() == vlc.State.Error:
return False return False
if (datetime.now() - start).seconds > 15: if (datetime.now() - start).seconds > 15:

View File

@ -240,7 +240,10 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
track_str = str(track) track_str = str(track)
track_info = QtCore.QFileInfo(track_str) track_info = QtCore.QFileInfo(track_str)
item_name = None 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 # Handle optical based item
(file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track_str) (file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track_str)
item_name = QtWidgets.QListWidgetItem(clip_name) item_name = QtWidgets.QListWidgetItem(clip_name)

View File

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

View File

@ -144,7 +144,7 @@ class OpenOfficeImport(SongImport):
""" """
self.file_path = file_path self.file_path = file_path
url = file_path.as_uri() url = file_path.as_uri()
properties = tuple(self.create_property('Hidden', True)) properties = (self.create_property('Hidden', True),)
try: try:
self.document = self.desktop.loadComponentFromURL(url, '_blank', 0, properties) self.document = self.desktop.loadComponentFromURL(url, '_blank', 0, properties)
if not self.document.supportsService("com.sun.star.presentation.PresentationDocument") and not \ 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) (device_path, title_track, audio_track, subtitle_track, start, end, name) = parse_optical_path(path)
# THEN: The return values should match the original values # 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_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_start == start, 'Returned start should match the original'
assert org_end == end, 'Returned end should match the original' assert org_end == end, 'Returned end should match the original'
assert org_name == name, '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) (device_path, title_track, audio_track, subtitle_track, start, end, name) = parse_optical_path(path)
# THEN: The return values should match the original values # 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_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_start == start, 'Returned start should match the original'
assert org_end == end, 'Returned end should match the original' assert org_end == end, 'Returned end should match the original'
assert org_name == name, '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 unittest.mock import MagicMock, call, patch
from openlp.core.common.registry import Registry 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 openlp.core.ui.media.vlcplayer import VlcPlayer, get_vlc
from tests.helpers import MockDateTime from tests.helpers import MockDateTime
from tests.helpers.testmixin import TestMixin from tests.helpers.testmixin import TestMixin
@ -127,7 +127,7 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player = VlcPlayer(None) vlc_player = VlcPlayer(None)
# WHEN: setup() is run # 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 # THEN: The VLC widget should be set up correctly
assert mocked_output_display.vlc_widget == mocked_qframe assert mocked_output_display.vlc_widget == mocked_qframe
@ -177,7 +177,7 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player = VlcPlayer(None) vlc_player = VlcPlayer(None)
# WHEN: setup() is run # 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 # THEN: The VLC instance should be created with the correct options
mocked_vlc.Instance.assert_called_with('--no-video-title-show ') mocked_vlc.Instance.assert_called_with('--no-video-title-show ')
@ -215,7 +215,7 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player = VlcPlayer(None) vlc_player = VlcPlayer(None)
# WHEN: setup() is run # 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 # THEN: The VLC instance should be created with the correct options
mocked_vlc.Instance.assert_called_with('--no-video-title-show ') mocked_vlc.Instance.assert_called_with('--no-video-title-show ')
@ -252,7 +252,7 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player = VlcPlayer(None) vlc_player = VlcPlayer(None)
# WHEN: setup() is run # 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 # THEN: set_hwnd should be called
mocked_media_player_new.set_hwnd.assert_called_with(2) mocked_media_player_new.set_hwnd.assert_called_with(2)
@ -289,7 +289,7 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player = VlcPlayer(None) vlc_player = VlcPlayer(None)
# WHEN: setup() is run # 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 # THEN: set_nsobject should be called
mocked_media_player_new.set_nsobject.assert_called_with(2) mocked_media_player_new.set_nsobject.assert_called_with(2)
@ -336,27 +336,28 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock() mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc mocked_get_vlc.return_value = mocked_vlc
mocked_display = MagicMock() mocked_display = MagicMock()
mocked_display.media_info.volume = 100 mocked_controller = MagicMock()
mocked_display.media_info.media_type = MediaType.Video mocked_controller.media_info.volume = 100
mocked_display.media_info.file_info.absoluteFilePath.return_value = media_path mocked_controller.media_info.media_type = MediaType.Video
mocked_controller.media_info.file_info.absoluteFilePath.return_value = media_path
mocked_vlc_media = MagicMock() mocked_vlc_media = MagicMock()
mocked_media = MagicMock() mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000 mocked_media.get_duration.return_value = 10000
mocked_display.vlc_instance.media_new_path.return_value = mocked_vlc_media mocked_controller.vlc_instance.media_new_path.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media mocked_controller.vlc_media_player.get_media.return_value = mocked_media
vlc_player = VlcPlayer(None) vlc_player = VlcPlayer(None)
# WHEN: A video is loaded into VLC # WHEN: A video is loaded into VLC
with patch.object(vlc_player, 'volume') as mocked_volume: 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 # THEN: The video should be loaded
mocked_normcase.assert_called_with(media_path) mocked_normcase.assert_called_with(media_path)
mocked_display.vlc_instance.media_new_path.assert_called_with(media_path) mocked_controller.vlc_instance.media_new_path.assert_called_with(media_path)
assert mocked_vlc_media == mocked_display.vlc_media assert mocked_vlc_media == mocked_controller.vlc_media
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)
mocked_vlc_media.parse.assert_called_with() 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 assert result is True
@patch('openlp.core.ui.media.vlcplayer.is_win') @patch('openlp.core.ui.media.vlcplayer.is_win')
@ -373,14 +374,15 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock() mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc mocked_get_vlc.return_value = mocked_vlc
mocked_display = MagicMock() mocked_display = MagicMock()
mocked_display.media_info.volume = 100 mocked_controller = MagicMock()
mocked_display.media_info.media_type = MediaType.CD mocked_controller.media_info.volume = 100
mocked_display.media_info.title_track = 1 mocked_controller.media_info.media_type = MediaType.CD
mocked_controller.media_info.title_track = 1
mocked_vlc_media = MagicMock() mocked_vlc_media = MagicMock()
mocked_media = MagicMock() mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000 mocked_media.get_duration.return_value = 10000
mocked_display.vlc_instance.media_new_location.return_value = mocked_vlc_media mocked_controller.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media mocked_controller.vlc_media_player.get_media.return_value = mocked_media
mocked_subitems = MagicMock() mocked_subitems = MagicMock()
mocked_subitems.count.return_value = 1 mocked_subitems.count.return_value = 1
mocked_subitems.item_at_index.return_value = mocked_vlc_media 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 # WHEN: An audio CD is loaded into VLC
with patch.object(vlc_player, 'volume') as mocked_volume, \ with patch.object(vlc_player, 'volume') as mocked_volume, \
patch.object(vlc_player, 'media_state_wait'): 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 # THEN: The video should be loaded
mocked_normcase.assert_called_with(media_path) mocked_normcase.assert_called_with(media_path)
mocked_display.vlc_instance.media_new_location.assert_called_with('cdda://' + media_path) mocked_controller.vlc_instance.media_new_location.assert_called_with('cdda://' + media_path)
assert mocked_vlc_media == mocked_display.vlc_media assert mocked_vlc_media == mocked_controller.vlc_media
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)
mocked_vlc_media.parse.assert_called_with() 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 assert result is True
@patch('openlp.core.ui.media.vlcplayer.is_win') @patch('openlp.core.ui.media.vlcplayer.is_win')
@ -415,15 +417,16 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock() mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc mocked_get_vlc.return_value = mocked_vlc
mocked_display = MagicMock() mocked_display = MagicMock()
mocked_display.media_info.volume = 100 mocked_controller = MagicMock()
mocked_display.media_info.media_type = MediaType.CD mocked_controller.media_info.volume = 100
mocked_display.media_info.file_info.absoluteFilePath.return_value = media_path mocked_controller.media_info.media_type = MediaType.CD
mocked_display.media_info.title_track = 1 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 = MagicMock()
mocked_media = MagicMock() mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000 mocked_media.get_duration.return_value = 10000
mocked_display.vlc_instance.media_new_location.return_value = mocked_vlc_media mocked_controller.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media mocked_controller.vlc_media_player.get_media.return_value = mocked_media
mocked_subitems = MagicMock() mocked_subitems = MagicMock()
mocked_subitems.count.return_value = 1 mocked_subitems.count.return_value = 1
mocked_subitems.item_at_index.return_value = mocked_vlc_media 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 # WHEN: An audio CD is loaded into VLC
with patch.object(vlc_player, 'volume') as mocked_volume, \ with patch.object(vlc_player, 'volume') as mocked_volume, \
patch.object(vlc_player, 'media_state_wait'): 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 # THEN: The video should be loaded
mocked_normcase.assert_called_with(media_path) mocked_normcase.assert_called_with(media_path)
mocked_display.vlc_instance.media_new_location.assert_called_with('cdda:///' + media_path) mocked_controller.vlc_instance.media_new_location.assert_called_with('cdda:///' + media_path)
assert mocked_vlc_media == mocked_display.vlc_media assert mocked_vlc_media == mocked_controller.vlc_media
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)
mocked_vlc_media.parse.assert_called_with() 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 assert result is True
@patch('openlp.core.ui.media.vlcplayer.is_win') @patch('openlp.core.ui.media.vlcplayer.is_win')
@ -458,15 +461,19 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock() mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc mocked_get_vlc.return_value = mocked_vlc
mocked_display = MagicMock() mocked_display = MagicMock()
mocked_display.media_info.volume = 100 mocked_controller = MagicMock()
mocked_display.media_info.media_type = MediaType.CD mocked_controller.media_info.volume = 100
mocked_display.media_info.file_info.absoluteFilePath.return_value = media_path mocked_controller.media_info.media_type = MediaType.CD
mocked_display.media_info.title_track = 1 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 = 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 = MagicMock()
mocked_media.get_duration.return_value = 10000 mocked_media.get_duration.return_value = 10000
mocked_display.vlc_instance.media_new_location.return_value = mocked_vlc_media mocked_controller.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media mocked_controller.vlc_media_player.get_media.return_value = mocked_media
mocked_subitems = MagicMock() mocked_subitems = MagicMock()
mocked_subitems.count.return_value = 0 mocked_subitems.count.return_value = 0
mocked_subitems.item_at_index.return_value = mocked_vlc_media 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 # WHEN: An audio CD is loaded into VLC
with patch.object(vlc_player, 'volume'), patch.object(vlc_player, 'media_state_wait'): 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 # THEN: The video should be loaded
mocked_normcase.assert_called_with(media_path) mocked_normcase.assert_called_with(media_path)
mocked_display.vlc_instance.media_new_location.assert_called_with('cdda://' + media_path) mocked_controller.vlc_instance.media_new_location.assert_called_with('cdda://' + media_path)
assert mocked_vlc_media == mocked_display.vlc_media assert mocked_vlc_media == mocked_controller.vlc_media
assert 0 == mocked_subitems.item_at_index.call_count 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 0 == mocked_vlc_media.parse.call_count
assert result is False assert result is False
@ -562,17 +569,17 @@ class TestVLCPlayer(TestCase, TestMixin):
Test resizing the player Test resizing the player
""" """
# GIVEN: A display object and a VlcPlayer instance # GIVEN: A display object and a VlcPlayer instance
mocked_display = MagicMock() mocked_controller = MagicMock()
mocked_display.size.return_value = (10, 10) mocked_controller.preview_display.size.return_value = (10, 10)
mocked_display.is_display = False mocked_controller.is_live = False
vlc_player = VlcPlayer(None) vlc_player = VlcPlayer(None)
# WHEN: resize is called # WHEN: resize is called
vlc_player.resize(mocked_display) vlc_player.resize(mocked_controller)
# THEN: The right methods should have been called # THEN: The right methods should have been called
mocked_display.size.assert_called_with() mocked_controller.preview_display.size.assert_called_with()
mocked_display.vlc_widget.resize.assert_called_with((10, 10)) mocked_controller.vlc_widget.resize.assert_called_with((10, 10))
@patch('openlp.core.ui.media.vlcplayer.threading') @patch('openlp.core.ui.media.vlcplayer.threading')
@patch('openlp.core.ui.media.vlcplayer.get_vlc') @patch('openlp.core.ui.media.vlcplayer.get_vlc')
@ -586,27 +593,27 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock() mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc mocked_get_vlc.return_value = mocked_vlc
mocked_display = MagicMock() mocked_display = MagicMock()
mocked_controller = MagicMock()
mocked_media = MagicMock() mocked_media = MagicMock()
mocked_media.get_duration.return_value = 50000 mocked_media.get_duration.return_value = 50000
mocked_output_display = MagicMock() mocked_controller.media_info.start_time = 0
mocked_output_display.media_info.start_time = 0 mocked_controller.media_info.media_type = MediaType.Video
mocked_output_display.media_info.media_type = MediaType.Video mocked_controller.media_info.volume = 100
mocked_output_display.media_info.volume = 100 mocked_controller.vlc_media_player.get_media.return_value = mocked_media
mocked_output_display.vlc_media_player.get_media.return_value = mocked_media
vlc_player = VlcPlayer(None) 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 # WHEN: play() is called
with patch.object(vlc_player, 'media_state_wait') as mocked_media_state_wait, \ with patch.object(vlc_player, 'media_state_wait') as mocked_media_state_wait, \
patch.object(vlc_player, 'volume') as mocked_volume: patch.object(vlc_player, 'volume') as mocked_volume:
mocked_media_state_wait.return_value = True 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 # THEN: A bunch of things should happen to play the media
mocked_thread.start.assert_called_with() 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() 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' assert result is True, 'The value returned from play() should be True'
@patch('openlp.core.ui.media.vlcplayer.threading') @patch('openlp.core.ui.media.vlcplayer.threading')
@ -649,13 +656,14 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_get_vlc.return_value = mocked_vlc mocked_get_vlc.return_value = mocked_vlc
mocked_controller = MagicMock() mocked_controller = MagicMock()
mocked_output_display = MagicMock() mocked_output_display = MagicMock()
mocked_output_display.media_info.start_time = 0 mocked_controller.media_info = ItemMediaInfo()
mocked_output_display.media_info.end_time = 50 mocked_controller.media_info.start_time = 0
mocked_output_display.media_info.media_type = MediaType.DVD mocked_controller.media_info.end_time = 50
mocked_output_display.media_info.volume = 100 mocked_controller.media_info.media_type = MediaType.DVD
mocked_output_display.media_info.title_track = 1 mocked_controller.media_info.volume = 100
mocked_output_display.media_info.audio_track = 1 mocked_controller.media_info.title_track = 1
mocked_output_display.media_info.subtitle_track = 1 mocked_controller.media_info.audio_track = 1
mocked_controller.media_info.subtitle_track = 1
vlc_player = VlcPlayer(None) vlc_player = VlcPlayer(None)
vlc_player.set_state(MediaState.Paused, mocked_output_display) 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 # THEN: A bunch of things should happen to play the media
mocked_thread.start.assert_called_with() mocked_thread.start.assert_called_with()
mocked_output_display.vlc_media_player.set_title.assert_called_with(1) mocked_controller.vlc_media_player.set_title.assert_called_with(1)
mocked_output_display.vlc_media_player.play.assert_called_with() mocked_controller.vlc_media_player.play.assert_called_with()
mocked_output_display.vlc_media_player.audio_set_track.assert_called_with(1) mocked_controller.vlc_media_player.audio_set_track.assert_called_with(1)
mocked_output_display.vlc_media_player.video_set_spu.assert_called_with(1) mocked_controller.vlc_media_player.video_set_spu.assert_called_with(1)
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() 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' assert result is True, 'The value returned from play() should be True'
@patch('openlp.core.ui.media.vlcplayer.get_vlc') @patch('openlp.core.ui.media.vlcplayer.get_vlc')
@ -782,21 +790,6 @@ class TestVLCPlayer(TestCase, TestMixin):
# THEN: The volume should have been set # THEN: The volume should have been set
mocked_display.vlc_media_player.audio_set_volume.assert_called_with(10) 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): def test_seek_unseekable_media(self):
""" """
Test seeking something that can't be seeked Test seeking something that can't be seeked
@ -880,21 +873,6 @@ class TestVLCPlayer(TestCase, TestMixin):
# THEN: The media should be stopped and invsibile # THEN: The media should be stopped and invsibile
mocked_display.vlc_widget.setVisible.assert_called_with(True) 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') @patch('openlp.core.ui.media.vlcplayer.get_vlc')
def test_update_ui(self, mocked_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.media_info.end_time = 300
mocked_controller.seek_slider.isSliderDown.return_value = False mocked_controller.seek_slider.isSliderDown.return_value = False
mocked_display = MagicMock() mocked_display = MagicMock()
mocked_display.vlc_media.get_state.return_value = 1 mocked_controller.vlc_media.get_state.return_value = 1
mocked_display.vlc_media_player.get_time.return_value = 400000 mocked_controller.vlc_media_player.get_time.return_value = 400000
vlc_player = VlcPlayer(None) vlc_player = VlcPlayer(None)
# WHEN: update_ui() is called # WHEN: update_ui() is called
@ -918,10 +896,10 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player.update_ui(mocked_controller, mocked_display) vlc_player.update_ui(mocked_controller, mocked_display)
# THEN: Certain methods should be called # 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 assert 2 == mocked_stop.call_count
mocked_display.vlc_media_player.get_time.assert_called_with() mocked_controller.vlc_media_player.get_time.assert_called_with()
mocked_set_visible.assert_called_with(mocked_display, False) mocked_set_visible.assert_called_with(mocked_controller, False)
mocked_controller.seek_slider.setSliderPosition.assert_called_with(400000) mocked_controller.seek_slider.setSliderPosition.assert_called_with(400000)
expected_calls = [call(True), call(False)] expected_calls = [call(True), call(False)]
assert expected_calls == mocked_controller.seek_slider.blockSignals.call_args_list 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_vlc.State.Ended = 1
mocked_get_vlc.return_value = mocked_vlc mocked_get_vlc.return_value = mocked_vlc
mocked_controller = MagicMock() mocked_controller = MagicMock()
mocked_controller.media_info = ItemMediaInfo()
mocked_controller.media_info.start_time = 100 mocked_controller.media_info.start_time = 100
mocked_controller.media_info.end_time = 300 mocked_controller.media_info.end_time = 300
mocked_controller.seek_slider.isSliderDown.return_value = False mocked_controller.seek_slider.isSliderDown.return_value = False
mocked_display = MagicMock() mocked_display = MagicMock()
mocked_display.vlc_media.get_state.return_value = 1 mocked_controller.vlc_media.get_state.return_value = 1
mocked_display.vlc_media_player.get_time.return_value = 300 mocked_controller.vlc_media_player.get_time.return_value = 300
mocked_display.controller.media_info.media_type = MediaType.DVD mocked_controller.media_info.media_type = MediaType.DVD
vlc_player = VlcPlayer(None) vlc_player = VlcPlayer(None)
# WHEN: update_ui() is called # WHEN: update_ui() is called
@ -950,9 +929,9 @@ class TestVLCPlayer(TestCase, TestMixin):
vlc_player.update_ui(mocked_controller, mocked_display) vlc_player.update_ui(mocked_controller, mocked_display)
# THEN: Certain methods should be called # 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 assert 1 == mocked_stop.call_count
mocked_display.vlc_media_player.get_time.assert_called_with() mocked_controller.vlc_media_player.get_time.assert_called_with()
mocked_controller.seek_slider.setSliderPosition.assert_called_with(300) mocked_controller.seek_slider.setSliderPosition.assert_called_with(200)
expected_calls = [call(True), call(False)] expected_calls = [call(True), call(False)]
assert expected_calls == mocked_controller.seek_slider.blockSignals.call_args_list 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 import shutil
from tempfile import mkdtemp from tempfile import mkdtemp
from unittest import TestCase 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.core.common.settings import Settings
from openlp.plugins.presentations.lib.impresscontroller import ImpressController, ImpressDocument, TextType from openlp.plugins.presentations.lib.impresscontroller import ImpressController, ImpressDocument, TextType
@ -86,7 +86,7 @@ class TestImpressController(TestCase, TestMixin):
assert result is False assert result is False
@patch('openlp.plugins.presentations.lib.impresscontroller.log') @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 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.log')
@patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=False) @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 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 mocked_get_com_servicemanager.called is False
assert result is True 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): class TestImpressDocument(TestCase):
""" """