diff --git a/.bzrignore b/.bzrignore
index 2b43ce13a..9ae23569f 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -15,6 +15,7 @@ documentation/build/html
*.e4*
*eric[1-9]project
.git
+env
# Git files
.gitignore
htmlcov
diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py
index 1539a059c..1b404c543 100644
--- a/openlp/core/common/settings.py
+++ b/openlp/core/common/settings.py
@@ -129,6 +129,9 @@ class Settings(QtCore.QSettings):
``advanced/slide limits`` to ``SlideLimits.Wrap``. **NOTE**, this means that the rules have to cover all cases!
So, if the type of the old value is bool, then there must be two rules.
"""
+ on_monitor_default = True
+ if log.isEnabledFor(logging.DEBUG):
+ on_monitor_default = False
__default_settings__ = {
'settings/version': 0,
'advanced/add page break': False,
@@ -185,6 +188,7 @@ class Settings(QtCore.QSettings):
'core/click live slide to unblank': False,
'core/blank warning': False,
'core/ccli number': '',
+ 'core/experimental': False,
'core/has run wizard': False,
'core/language': '[en]',
'core/last version test': '',
@@ -202,13 +206,13 @@ class Settings(QtCore.QSettings):
'core/view mode': 'default',
# The other display settings (display position and dimensions) are defined in the ScreenList class due to a
# circular dependency.
- 'core/display on monitor': True,
+ 'core/display on monitor': on_monitor_default,
'core/override position': False,
'core/monitor': {},
'core/application version': '0.0',
'images/background color': '#000000',
- 'media/players': 'system,webkit',
- 'media/override player': QtCore.Qt.Unchecked,
+ 'media/media auto start': QtCore.Qt.Unchecked,
+ 'media/stream command': '',
'remotes/download version': '0.0',
'players/background color': '#000000',
'servicemanager/last directory': None,
@@ -311,7 +315,9 @@ class Settings(QtCore.QSettings):
('bibles/proxy name', '', []), # Just remove these bible proxy settings. They weren't used in 2.4!
('bibles/proxy address', '', []),
('bibles/proxy username', '', []),
- ('bibles/proxy password', '', [])
+ ('bibles/proxy password', '', []),
+ ('media/players', '', []),
+ ('media/override player', '', [])
]
@staticmethod
diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py
index 110eccd39..9c8696736 100644
--- a/openlp/core/lib/theme.py
+++ b/openlp/core/lib/theme.py
@@ -46,6 +46,7 @@ class BackgroundType(object):
Image = 2
Transparent = 3
Video = 4
+ Stream = 5
@staticmethod
def to_string(background_type):
@@ -62,6 +63,8 @@ class BackgroundType(object):
return 'transparent'
elif background_type == BackgroundType.Video:
return 'video'
+ elif background_type == BackgroundType.Stream:
+ return 'stream'
@staticmethod
def from_string(type_string):
@@ -78,6 +81,8 @@ class BackgroundType(object):
return BackgroundType.Transparent
elif type_string == 'video':
return BackgroundType.Video
+ elif type_string == 'stream':
+ return BackgroundType.Stream
class BackgroundGradientType(object):
diff --git a/openlp/core/ui/media/__init__.py b/openlp/core/ui/media/__init__.py
index 4e38cc122..1e3ba9b16 100644
--- a/openlp/core/ui/media/__init__.py
+++ b/openlp/core/ui/media/__init__.py
@@ -48,6 +48,7 @@ class MediaType(object):
CD = 3
DVD = 4
Folder = 5
+ Stream = 6
class ItemMediaInfo(object):
diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py
index 475d7f09f..073023359 100644
--- a/openlp/core/ui/media/mediacontroller.py
+++ b/openlp/core/ui/media/mediacontroller.py
@@ -23,7 +23,6 @@
The :mod:`~openlp.core.ui.media.mediacontroller` module contains a base class for media components and other widgets
related to playing media, such as sliders.
"""
-import datetime
import logging
try:
@@ -33,7 +32,7 @@ except ImportError:
pymediainfo_available = False
from subprocess import check_output
-from PyQt5 import QtCore, QtWidgets
+from PyQt5 import QtCore
from openlp.core.state import State
from openlp.core.api.http import register_endpoint
@@ -44,11 +43,9 @@ from openlp.core.common.settings import Settings
from openlp.core.lib.serviceitem import ItemCapabilities
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui import DisplayControllerType
-from openlp.core.ui.icons import UiIcons
from openlp.core.ui.media import MediaState, ItemMediaInfo, MediaType, parse_optical_path
from openlp.core.ui.media.endpoint import media_endpoint
from openlp.core.ui.media.vlcplayer import VlcPlayer, get_vlc
-from openlp.core.widgets.toolbar import OpenLPToolbar
log = logging.getLogger(__name__)
@@ -56,45 +53,6 @@ log = logging.getLogger(__name__)
TICK_TIME = 200
-class MediaSlider(QtWidgets.QSlider):
- """
- Allows the mouse events of a slider to be overridden and extra functionality added
- """
- def __init__(self, direction, manager, controller):
- """
- Constructor
- """
- super(MediaSlider, self).__init__(direction)
- self.manager = manager
- self.controller = controller
-
- def mouseMoveEvent(self, event):
- """
- Override event to allow hover time to be displayed.
-
- :param event: The triggering event
- """
- time_value = QtWidgets.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), event.x(), self.width())
- self.setToolTip('%s' % datetime.timedelta(seconds=int(time_value / 1000)))
- QtWidgets.QSlider.mouseMoveEvent(self, event)
-
- def mousePressEvent(self, event):
- """
- Mouse Press event no new functionality
- :param event: The triggering event
- """
- QtWidgets.QSlider.mousePressEvent(self, event)
-
- def mouseReleaseEvent(self, event):
- """
- Set the slider position when the mouse is clicked and released on the slider.
-
- :param event: The triggering event
- """
- self.setValue(QtWidgets.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), event.x(), self.width()))
- QtWidgets.QSlider.mouseReleaseEvent(self, event)
-
-
class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
The implementation of the Media Controller. The Media Controller adds an own class for every Player.
@@ -116,7 +74,6 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
def setup(self):
self.vlc_player = None
- self.display_controllers = {}
self.current_media_players = {}
# Timer for video state
self.live_timer = QtCore.QTimer()
@@ -168,117 +125,71 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
self.setup()
self.vlc_player = VlcPlayer(self)
State().add_service("mediacontroller", 0)
+ State().add_service("media_live", 0, requires="mediacontroller")
if get_vlc() and pymediainfo_available:
State().update_pre_conditions("mediacontroller", True)
+ State().update_pre_conditions('media_live', True)
else:
State().missing_text("mediacontroller", translate('OpenLP.SlideController',
"VLC or pymediainfo are missing, so you are unable to play any media"))
self._generate_extensions_lists()
return True
+ def bootstrap_post_set_up(self):
+ """
+ Set up the controllers.
+ :return:
+ """
+ try:
+ self.setup_display(self.live_controller.display, False)
+ except AttributeError:
+ State().update_pre_conditions('media_live', False)
+ self.setup_display(self.preview_controller.preview_display, True)
+
+ def display_controllers(self, controller_type):
+ """
+ Decides which controller to use.
+
+ :param controller_type: The controller type where a player will be placed
+ """
+ if controller_type == DisplayControllerType.Live:
+ return self.live_controller
+ else:
+ return self.preview_controller
+
def media_state_live(self):
"""
Check if there is a running Live media Player and do updating stuff (e.g. update the UI)
"""
- 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:
self.current_media_players[DisplayControllerType.Live].resize(display)
- self.current_media_players[DisplayControllerType.Live].update_ui(display)
- self.tick(self.display_controllers[DisplayControllerType.Live])
+ self.current_media_players[DisplayControllerType.Live].update_ui(self.live_controller, display)
+ self.tick(self.display_controllers(DisplayControllerType.Live))
if self.current_media_players[DisplayControllerType.Live].get_live_state() is not MediaState.Playing:
self.live_timer.stop()
else:
self.live_timer.stop()
- self.media_stop(self.display_controllers[DisplayControllerType.Live])
- if self.display_controllers[DisplayControllerType.Live].media_info.can_loop_playback:
- self.media_play(self.display_controllers[DisplayControllerType.Live], True)
+ 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):
"""
Check if there is a running Preview media Player and do updating stuff (e.g. update the UI)
"""
- 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:
self.current_media_players[DisplayControllerType.Preview].resize(display)
- self.current_media_players[DisplayControllerType.Preview].update_ui(display)
- self.tick(self.display_controllers[DisplayControllerType.Preview])
+ self.current_media_players[DisplayControllerType.Preview].update_ui(self.preview_controller, display)
+ self.tick(self.display_controllers(DisplayControllerType.Preview))
if self.current_media_players[DisplayControllerType.Preview].get_preview_state() is not MediaState.Playing:
self.preview_timer.stop()
else:
self.preview_timer.stop()
- self.media_stop(self.display_controllers[DisplayControllerType.Preview])
- if self.display_controllers[DisplayControllerType.Preview].media_info.can_loop_playback:
- self.media_play(self.display_controllers[DisplayControllerType.Preview], True)
-
- def register_controller(self, controller):
- """
- Registers media controls where the players will be placed to run.
-
- :param controller: The controller where a player will be placed
- """
- self.display_controllers[controller.controller_type] = controller
- self.setup_generic_controls(controller)
-
- def setup_generic_controls(self, controller):
- """
- Set up controls on the control_panel for a given controller
-
- :param controller: First element is the controller which should be used
- """
- controller.media_info = ItemMediaInfo()
- # Build a Media ToolBar
- controller.mediabar = OpenLPToolbar(controller)
- controller.mediabar.add_toolbar_action('playbackPlay', text='media_playback_play',
- icon=UiIcons().play,
- tooltip=translate('OpenLP.SlideController', 'Start playing media.'),
- triggers=controller.send_to_plugins)
- controller.mediabar.add_toolbar_action('playbackPause', text='media_playback_pause',
- icon=UiIcons().pause,
- tooltip=translate('OpenLP.SlideController', 'Pause playing media.'),
- triggers=controller.send_to_plugins)
- controller.mediabar.add_toolbar_action('playbackStop', text='media_playback_stop',
- icon=UiIcons().stop,
- tooltip=translate('OpenLP.SlideController', 'Stop playing media.'),
- triggers=controller.send_to_plugins)
- controller.mediabar.add_toolbar_action('playbackLoop', text='media_playback_loop',
- icon=UiIcons().repeat, checked=False,
- tooltip=translate('OpenLP.SlideController', 'Loop playing media.'),
- triggers=controller.send_to_plugins)
- controller.position_label = QtWidgets.QLabel()
- controller.position_label.setText(' 00:00 / 00:00')
- controller.position_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
- controller.position_label.setToolTip(translate('OpenLP.SlideController', 'Video timer.'))
- controller.position_label.setMinimumSize(90, 0)
- controller.position_label.setObjectName('position_label')
- controller.mediabar.add_toolbar_widget(controller.position_label)
- # Build the seek_slider.
- controller.seek_slider = MediaSlider(QtCore.Qt.Horizontal, self, controller)
- controller.seek_slider.setMaximum(1000)
- controller.seek_slider.setTracking(True)
- controller.seek_slider.setMouseTracking(True)
- controller.seek_slider.setToolTip(translate('OpenLP.SlideController', 'Video position.'))
- controller.seek_slider.setGeometry(QtCore.QRect(90, 260, 221, 24))
- controller.seek_slider.setObjectName('seek_slider')
- controller.mediabar.add_toolbar_widget(controller.seek_slider)
- # Build the volume_slider.
- controller.volume_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
- controller.volume_slider.setTickInterval(10)
- controller.volume_slider.setTickPosition(QtWidgets.QSlider.TicksAbove)
- controller.volume_slider.setMinimum(0)
- controller.volume_slider.setMaximum(100)
- controller.volume_slider.setTracking(True)
- controller.volume_slider.setToolTip(translate('OpenLP.SlideController', 'Audio Volume.'))
- controller.volume_slider.setValue(controller.media_info.volume)
- controller.volume_slider.setGeometry(QtCore.QRect(90, 160, 221, 24))
- controller.volume_slider.setObjectName('volume_slider')
- controller.mediabar.add_toolbar_widget(controller.volume_slider)
- controller.controller_layout.addWidget(controller.mediabar)
- controller.mediabar.setVisible(False)
- if not controller.is_live:
- controller.volume_slider.setEnabled(False)
- # Signals
- controller.seek_slider.valueChanged.connect(controller.send_to_plugins)
- controller.volume_slider.valueChanged.connect(controller.send_to_plugins)
+ 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):
"""
@@ -287,14 +198,13 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param display: Display on which the output is to be played
:param preview: Whether the display is a main or preview display
"""
- # clean up possible running old media files
- self.finalise()
+ display.media_info = ItemMediaInfo()
display.has_audio = True
- if display.is_live and preview:
- return
+ # if display.is_live and preview:
+ # return
if preview:
display.has_audio = False
- self.vlc_player.setup(display)
+ self.vlc_player.setup(display, preview)
def set_controls_visible(self, controller, value):
"""
@@ -305,9 +215,9 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
# Generic controls
controller.mediabar.setVisible(value)
- if controller.is_live and controller.display:
- if self.current_media_players and value:
- controller.display.set_transparency(False)
+ # if controller.is_live and controller.display:
+ # if self.current_media_players and value:
+ # controller.display.set_transparency(False)
@staticmethod
def resize(display, player):
@@ -319,7 +229,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
player.resize(display)
- def video(self, source, service_item, hidden=False, video_behind_text=False):
+ def load_video(self, source, service_item, hidden=False, video_behind_text=False):
"""
Loads and starts a video to run with the option of sound
@@ -329,7 +239,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
:param video_behind_text: Is the video to be played behind text.
"""
is_valid = True
- controller = self.display_controllers[source]
+ controller = self.display_controllers(source)
# stop running videos
self.media_reset(controller)
controller.media_info = ItemMediaInfo()
@@ -354,8 +264,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
log.debug('video is not optical and live')
controller.media_info.length = service_item.media_length
is_valid = self._check_file_type(controller, display)
- display.override['theme'] = ''
- display.override['video'] = True
+ # display.override['theme'] = ''
+ # display.override['video'] = True
if controller.media_info.is_background:
# ignore start/end time
controller.media_info.start_time = 0
@@ -379,10 +289,10 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'),
translate('MediaPlugin.MediaItem', 'Unsupported File'))
return False
- log.debug('video mediatype: ' + str(controller.media_info.media_type))
+ log.debug('video media type: ' + str(controller.media_info.media_type))
# dont care about actual theme, set a black background
- if controller.is_live and not controller.media_info.is_background:
- display.frame.runJavaScript('show_video("setBackBoard", null, null,"visible");')
+ # if controller.is_live and not controller.media_info.is_background:
+ # display.frame.runJavaScript('show_video("setBackBoard", null, null,"visible");')
# now start playing - Preview is autoplay!
autoplay = False
# Preview requested
@@ -471,28 +381,26 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
for file in controller.media_info.file_info:
if file.is_file:
suffix = '*%s' % file.suffix.lower()
- player = self.vlc_player
file = str(file)
- if suffix in player.video_extensions_list:
+ if suffix in self.vlc_player.video_extensions_list:
if not controller.media_info.is_background or controller.media_info.is_background and \
- player.can_background:
- self.resize(display, player)
- if player.load(display, file):
- self.current_media_players[controller.controller_type] = player
+ self.vlc_player.can_background:
+ self.resize(display, self.vlc_player)
+ if self.vlc_player.load(display, file):
+ self.current_media_players[controller.controller_type] = self.vlc_player
controller.media_info.media_type = MediaType.Video
return True
- if suffix in player.audio_extensions_list:
- if player.load(display, file):
- self.current_media_players[controller.controller_type] = player
+ if suffix in self.vlc_player.audio_extensions_list:
+ if self.vlc_player.load(display, file):
+ self.current_media_players[controller.controller_type] = self.vlc_player
controller.media_info.media_type = MediaType.Audio
return True
else:
- player = self.vlc_player
file = str(file)
- if player.can_folder:
- self.resize(display, player)
- if player.load(display, file):
- self.current_media_players[controller.controller_type] = player
+ if self.vlc_player.can_folder:
+ self.resize(display, self.vlc_player)
+ if self.vlc_player.load(display, file):
+ self.current_media_players[controller.controller_type] = self.vlc_player
controller.media_info.media_type = MediaType.Video
return True
return False
@@ -509,8 +417,6 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
def on_media_play(self):
"""
Responds to the request to play a loaded video from the web.
-
- :param msg: First element is the controller which should be used
"""
self.media_play(Registry().get('live_controller'), False)
@@ -524,7 +430,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.seek_slider.blockSignals(True)
controller.volume_slider.blockSignals(True)
display = self._define_display(controller)
- if not self.current_media_players[controller.controller_type].play(display):
+ if not self.current_media_players[controller.controller_type].play(controller, display):
controller.seek_slider.blockSignals(False)
controller.volume_slider.blockSignals(False)
return False
@@ -533,8 +439,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
else:
self.media_volume(controller, controller.media_info.volume)
if first_time:
- if not controller.media_info.is_background:
- display.frame.runJavaScript('show_blank("desktop");')
+ # if not controller.media_info.is_background:
+ # 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['playbackPause'].setVisible(True)
@@ -591,8 +497,6 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
def on_media_pause(self):
"""
Responds to the request to pause a loaded video from the web.
-
- :param msg: First element is the controller which should be used
"""
self.media_pause(Registry().get('live_controller'))
@@ -639,8 +543,6 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
def on_media_stop(self):
"""
Responds to the request to stop a loaded video from the web.
-
- :param msg: First element is the controller which should be used
"""
self.media_stop(Registry().get('live_controller'))
@@ -653,8 +555,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
display = self._define_display(controller)
if controller.controller_type in self.current_media_players:
- if not looping_background:
- display.frame.runJavaScript('show_blank("black");')
+ # if not looping_background:
+ # display.frame.runJavaScript('show_blank("black");')
self.current_media_players[controller.controller_type].stop(display)
self.current_media_players[controller.controller_type].set_visible(display, False)
controller.seek_slider.setSliderPosition(0)
@@ -725,7 +627,7 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
display.override = {}
self.current_media_players[controller.controller_type].reset(display)
self.current_media_players[controller.controller_type].set_visible(display, False)
- display.frame.runJavaScript('show_video("setBackBoard", null, null, "hidden");')
+ # display.frame.runJavaScript('show_video("setBackBoard", null, null, "hidden");')
del self.current_media_players[controller.controller_type]
def media_hide(self, msg):
@@ -788,8 +690,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
self.live_timer.stop()
self.preview_timer.stop()
- for controller in self.display_controllers:
- self.media_reset(self.display_controllers[controller])
+ self.media_reset(self.display_controllers(DisplayControllerType.Live))
+ self.media_reset(self.display_controllers(DisplayControllerType.Preview))
@staticmethod
def _define_display(controller):
diff --git a/openlp/core/ui/media/mediaplayer.py b/openlp/core/ui/media/mediaplayer.py
index 7ee128cbc..36d5ef13f 100644
--- a/openlp/core/ui/media/mediaplayer.py
+++ b/openlp/core/ui/media/mediaplayer.py
@@ -52,11 +52,12 @@ class MediaPlayer(RegistryProperties):
"""
return False
- def setup(self, display):
+ def setup(self, display, live_display):
"""
Create the related widgets for the current display
:param display: The display to be updated.
+ :param live_display: Is the display a live one.
"""
pass
@@ -78,10 +79,11 @@ class MediaPlayer(RegistryProperties):
"""
pass
- def play(self, display):
+ def play(self, controller, display):
"""
Starts playing of current Media File
+ :param controller: Which Controller is running the show.
:param display: The display to be updated.
"""
pass
@@ -206,7 +208,7 @@ class MediaPlayer(RegistryProperties):
:param display: Identify the Display type
:return: None
"""
- if display.controller.is_live:
+ if display.is_display:
self.set_live_state(state)
else:
self.set_preview_state(state)
diff --git a/openlp/core/ui/media/mediatab.py b/openlp/core/ui/media/mediatab.py
new file mode 100644
index 000000000..82130df1e
--- /dev/null
+++ b/openlp/core/ui/media/mediatab.py
@@ -0,0 +1,148 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2019 OpenLP Developers #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+"""
+The :mod:`~openlp.core.ui.media.playertab` module holds the configuration tab for the media stuff.
+"""
+
+from PyQt5 import QtWidgets
+# from PyQt5.QtMultimedia import QCameraInfo, QAudioDeviceInfo, QAudio
+
+from openlp.core.common import is_linux, is_win
+from openlp.core.common.i18n import translate
+from openlp.core.common.settings import Settings
+from openlp.core.lib.settingstab import SettingsTab
+from openlp.core.ui.icons import UiIcons
+
+LINUX_STREAM = 'v4l2:///dev/video0'
+WIN_STREAM = 'dshow:// :dshow-vdev='
+
+
+class MediaTab(SettingsTab):
+ """
+ MediaTab is the Media settings tab in the settings dialog.
+ """
+ def __init__(self, parent):
+ """
+ Constructor
+ """
+ # self.media_players = Registry().get('media_controller').media_players
+ # self.saved_used_players = None
+ self.icon_path = UiIcons().video
+ player_translated = translate('OpenLP.MediaTab', 'Media')
+ super(MediaTab, self).__init__(parent, 'Media', player_translated)
+
+ def setup_ui(self):
+ """
+ Set up the UI
+ """
+ self.setObjectName('MediaTab')
+ super(MediaTab, self).setup_ui()
+ self.live_media_group_box = QtWidgets.QGroupBox(self.left_column)
+ self.live_media_group_box.setObjectName('live_media_group_box')
+ self.media_layout = QtWidgets.QVBoxLayout(self.live_media_group_box)
+ self.media_layout.setObjectName('live_media_layout')
+ self.auto_start_check_box = QtWidgets.QCheckBox(self.live_media_group_box)
+ self.auto_start_check_box.setObjectName('auto_start_check_box')
+ self.media_layout.addWidget(self.auto_start_check_box)
+ self.left_layout.addWidget(self.live_media_group_box)
+ self.stream_media_group_box = QtWidgets.QGroupBox(self.left_column)
+ self.stream_media_group_box.setObjectName('stream_media_group_box')
+ self.stream_media_layout = QtWidgets.QHBoxLayout(self.stream_media_group_box)
+ self.stream_media_layout.setObjectName('live_media_layout')
+ self.stream_media_layout.setContentsMargins(0, 0, 0, 0)
+ self.stream_edit = QtWidgets.QPlainTextEdit(self)
+ self.stream_media_layout.addWidget(self.stream_edit)
+ self.browse_button = QtWidgets.QToolButton(self)
+ self.browse_button.setIcon(UiIcons().undo)
+ self.stream_media_layout.addWidget(self.browse_button)
+ self.left_layout.addWidget(self.stream_media_group_box)
+ self.left_layout.addWidget(self.stream_media_group_box)
+ self.left_layout.addStretch()
+ self.right_layout.addStretch()
+ # # Signals and slots
+ self.browse_button.clicked.connect(self.on_revert)
+
+ def retranslateUi(self):
+ """
+ Translate the UI on the fly
+ """
+ self.live_media_group_box.setTitle(translate('MediaPlugin.MediaTab', 'Live Media'))
+ self.stream_media_group_box.setTitle(translate('MediaPlugin.MediaTab', 'Stream Media Command'))
+ self.auto_start_check_box.setText(translate('MediaPlugin.MediaTab', 'Start automatically'))
+
+ def load(self):
+ """
+ Load the settings
+ """
+ self.auto_start_check_box.setChecked(Settings().value(self.settings_section + '/media auto start'))
+ self.stream_edit.setPlainText(Settings().value(self.settings_section + '/stream command'))
+ if not self.stream_edit.toPlainText():
+ if is_linux:
+ self.stream_edit.setPlainText(LINUX_STREAM)
+ elif is_win:
+ self.stream_edit.setPlainText(WIN_STREAM)
+
+ def save(self):
+ """
+ Save the settings
+ """
+ setting_key = self.settings_section + '/media auto start'
+ if Settings().value(setting_key) != self.auto_start_check_box.checkState():
+ Settings().setValue(setting_key, self.auto_start_check_box.checkState())
+ # settings = Settings()
+ # settings.beginGroup(self.settings_section)
+ # settings.setValue('background color', self.background_color)
+ # settings.endGroup()
+ # old_players, override_player = get_media_players()
+ # if self.used_players != old_players:
+ # # clean old Media stuff
+ # set_media_players(self.used_players, override_player)
+ # self.settings_form.register_post_process('mediaitem_suffix_reset')
+ # self.settings_form.register_post_process('mediaitem_media_rebuild')
+ # self.settings_form.register_post_process('config_screen_changed')
+
+ def post_set_up(self, post_update=False):
+ """
+ Late setup for players as the MediaController has to be initialised first.
+
+ :param post_update: Indicates if called before or after updates.
+ """
+ pass
+ # for key, player in self.media_players.items():
+ # player = self.media_players[key]
+ # checkbox = MediaQCheckBox(self.media_player_group_box)
+ # checkbox.setEnabled(player.available)
+ # checkbox.setObjectName(player.name + '_check_box')
+ # checkbox.setToolTip(player.get_info())
+ # checkbox.set_player_name(player.name)
+ # self.player_check_boxes[player.name] = checkbox
+ # checkbox.stateChanged.connect(self.on_player_check_box_changed)
+ # self.media_player_layout.addWidget(checkbox)
+ # if player.available and player.name in self.used_players:
+ # checkbox.setChecked(True)
+ # else:
+ # checkbox.setChecked(False)
+ # self.update_player_list()
+ # self.retranslate_players()
+
+ def on_revert(self):
+ pass
diff --git a/openlp/core/ui/media/playertab.py b/openlp/core/ui/media/playertab.py
deleted file mode 100644
index ea0895ca2..000000000
--- a/openlp/core/ui/media/playertab.py
+++ /dev/null
@@ -1,269 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2019 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-"""
-The :mod:`~openlp.core.ui.media.playertab` module holds the configuration tab for the media stuff.
-"""
-import platform
-
-from PyQt5 import QtCore, QtWidgets
-
-from openlp.core.common.i18n import UiStrings, translate
-# from openlp.core.common.registry import Registry
-from openlp.core.common.settings import Settings
-from openlp.core.lib.settingstab import SettingsTab
-from openlp.core.lib.ui import create_button
-from openlp.core.ui.icons import UiIcons
-from openlp.core.widgets.buttons import ColorButton
-
-
-class MediaQCheckBox(QtWidgets.QCheckBox):
- """
- MediaQCheckBox adds an extra property, player_name to the QCheckBox class.
- """
- def set_player_name(self, name):
- """
- Set the player name
- """
- self.player_name = name
-
-
-class PlayerTab(SettingsTab):
- """
- MediaTab is the Media settings tab in the settings dialog.
- """
- def __init__(self, parent):
- """
- Constructor
- """
- # self.media_players = Registry().get('media_controller').media_players
- self.saved_used_players = None
- self.icon_path = UiIcons().player
- player_translated = translate('OpenLP.PlayerTab', 'Players')
- super(PlayerTab, self).__init__(parent, 'Players', player_translated)
-
- def setup_ui(self):
- """
- Set up the UI
- """
- self.setObjectName('MediaTab')
- super(PlayerTab, self).setup_ui()
- self.background_color_group_box = QtWidgets.QGroupBox(self.left_column)
- self.background_color_group_box.setObjectName('background_color_group_box')
- self.form_layout = QtWidgets.QFormLayout(self.background_color_group_box)
- self.form_layout.setObjectName('form_layout')
- self.color_layout = QtWidgets.QHBoxLayout()
- self.background_color_label = QtWidgets.QLabel(self.background_color_group_box)
- self.background_color_label.setObjectName('background_color_label')
- self.color_layout.addWidget(self.background_color_label)
- self.background_color_button = ColorButton(self.background_color_group_box)
- self.background_color_button.setObjectName('background_color_button')
- self.color_layout.addWidget(self.background_color_button)
- self.form_layout.addRow(self.color_layout)
- self.information_label = QtWidgets.QLabel(self.background_color_group_box)
- self.information_label.setObjectName('information_label')
- self.information_label.setWordWrap(True)
- self.form_layout.addRow(self.information_label)
- self.left_layout.addWidget(self.background_color_group_box)
- self.right_column.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
- self.media_player_group_box = QtWidgets.QGroupBox(self.left_column)
- self.media_player_group_box.setObjectName('media_player_group_box')
- self.media_player_layout = QtWidgets.QVBoxLayout(self.media_player_group_box)
- self.media_player_layout.setObjectName('media_player_layout')
- self.player_check_boxes = {}
- self.left_layout.addWidget(self.media_player_group_box)
- self.player_order_group_box = QtWidgets.QGroupBox(self.left_column)
- self.player_order_group_box.setObjectName('player_order_group_box')
- self.player_order_layout = QtWidgets.QHBoxLayout(self.player_order_group_box)
- self.player_order_layout.setObjectName('player_order_layout')
- self.player_order_list_widget = QtWidgets.QListWidget(self.player_order_group_box)
- size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- size_policy.setHorizontalStretch(0)
- size_policy.setVerticalStretch(0)
- size_policy.setHeightForWidth(self.player_order_list_widget.sizePolicy().hasHeightForWidth())
- self.player_order_list_widget.setSizePolicy(size_policy)
- self.player_order_list_widget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
- self.player_order_list_widget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
- self.player_order_list_widget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
- self.player_order_list_widget.setObjectName('player_order_list_widget')
- self.player_order_layout.addWidget(self.player_order_list_widget)
- self.ordering_button_layout = QtWidgets.QVBoxLayout()
- self.ordering_button_layout.setObjectName('ordering_button_layout')
- self.ordering_button_layout.addStretch(1)
- self.ordering_up_button = create_button(self, 'ordering_up_button', role='up',
- click=self.on_up_button_clicked)
- self.ordering_down_button = create_button(self, 'ordering_down_button', role='down',
- click=self.on_down_button_clicked)
- self.ordering_button_layout.addWidget(self.ordering_up_button)
- self.ordering_button_layout.addWidget(self.ordering_down_button)
- self.ordering_button_layout.addStretch(1)
- self.player_order_layout.addLayout(self.ordering_button_layout)
- self.left_layout.addWidget(self.player_order_group_box)
- self.left_layout.addStretch()
- self.right_layout.addStretch()
- # Signals and slots
- self.background_color_button.colorChanged.connect(self.on_background_color_changed)
-
- def retranslate_ui(self):
- """
- Translate the UI on the fly
- """
- self.media_player_group_box.setTitle(translate('OpenLP.PlayerTab', 'Available Media Players'))
- self.player_order_group_box.setTitle(translate('OpenLP.PlayerTab', 'Player Search Order'))
- self.background_color_group_box.setTitle(UiStrings().BackgroundColor)
- self.background_color_label.setText(UiStrings().BackgroundColorColon)
- self.information_label.setText(translate('OpenLP.PlayerTab',
- 'Visible background for videos with aspect ratio different to screen.'))
- self.retranslate_players()
-
- def on_background_color_changed(self, color):
- """
- Set the background color
-
- :param color: The color to be set.
- """
- self.background_color = color
-
- def on_player_check_box_changed(self, check_state):
- """
- Add or remove players depending on their status
-
- :param check_state: The requested status.
- """
- player = self.sender().player_name
- if check_state == QtCore.Qt.Checked:
- if player not in self.used_players:
- self.used_players.append(player)
- else:
- if player in self.used_players:
- self.used_players.remove(player)
- self.update_player_list()
-
- def update_player_list(self):
- """
- Update the list of media players
- """
- self.player_order_list_widget.clear()
- for player in self.used_players:
- if player in list(self.player_check_boxes.keys()):
- if len(self.used_players) == 1:
- # At least one media player has to stay active
- self.player_check_boxes['%s' % player].setEnabled(False)
- else:
- self.player_check_boxes['%s' % player].setEnabled(True)
- self.player_order_list_widget.addItem(self.media_players[str(player)].original_name)
-
- def on_up_button_clicked(self):
- """
- Move a media player up in the order
- """
- row = self.player_order_list_widget.currentRow()
- if row <= 0:
- return
- item = self.player_order_list_widget.takeItem(row)
- self.player_order_list_widget.insertItem(row - 1, item)
- self.player_order_list_widget.setCurrentRow(row - 1)
- self.used_players.insert(row - 1, self.used_players.pop(row))
-
- def on_down_button_clicked(self):
- """
- Move a media player down in the order
- """
- row = self.player_order_list_widget.currentRow()
- if row == -1 or row > self.player_order_list_widget.count() - 1:
- return
- item = self.player_order_list_widget.takeItem(row)
- self.player_order_list_widget.insertItem(row + 1, item)
- self.player_order_list_widget.setCurrentRow(row + 1)
- self.used_players.insert(row + 1, self.used_players.pop(row))
-
- def load(self):
- """
- Load the settings
- """
- if self.saved_used_players:
- self.used_players = self.saved_used_players
- # self.used_players = get_media_players()[0]
- self.saved_used_players = self.used_players
- settings = Settings()
- settings.beginGroup(self.settings_section)
- self.update_player_list()
- self.background_color = settings.value('background color')
- self.initial_color = self.background_color
- settings.endGroup()
- self.background_color_button.color = self.background_color
-
- def save(self):
- """
- Save the settings
- """
- settings = Settings()
- settings.beginGroup(self.settings_section)
- settings.setValue('background color', self.background_color)
- settings.endGroup()
- # old_players, override_player = get_media_players()
- # if self.used_players != old_players:
- # # clean old Media stuff
- # set_media_players(self.used_players, override_player)
- # self.settings_form.register_post_process('mediaitem_suffix_reset')
- # self.settings_form.register_post_process('mediaitem_media_rebuild')
- # self.settings_form.register_post_process('config_screen_changed')
-
- def post_set_up(self, post_update=False):
- """
- Late setup for players as the MediaController has to be initialised first.
-
- :param post_update: Indicates if called before or after updates.
- """
- for key, player in self.media_players.items():
- player = self.media_players[key]
- checkbox = MediaQCheckBox(self.media_player_group_box)
- checkbox.setEnabled(player.available)
- checkbox.setObjectName(player.name + '_check_box')
- checkbox.setToolTip(player.get_info())
- checkbox.set_player_name(player.name)
- self.player_check_boxes[player.name] = checkbox
- checkbox.stateChanged.connect(self.on_player_check_box_changed)
- self.media_player_layout.addWidget(checkbox)
- if player.available and player.name in self.used_players:
- checkbox.setChecked(True)
- else:
- checkbox.setChecked(False)
- self.update_player_list()
- self.retranslate_players()
-
- def retranslate_players(self):
- """
- Translations for players is dependent on their setup as well
- """
- for key in self.media_players and self.player_check_boxes:
- player = self.media_players[key]
- checkbox = self.player_check_boxes[player.name]
- checkbox.set_player_name(player.name)
- if player.available:
- checkbox.setText(player.display_name)
- else:
- checkbox_text = translate('OpenLP.PlayerTab', '%s (unavailable)') % player.display_name
- if player.name == 'vlc':
- checkbox_text += ' ' + translate('OpenLP.PlayerTab',
- 'NOTE: To use VLC you must install the %s version',
- 'Will insert "32bit" or "64bit"') % platform.architecture()[0]
- checkbox.setText(checkbox_text)
diff --git a/openlp/core/ui/media/systemplayer.py b/openlp/core/ui/media/systemplayer.py
deleted file mode 100644
index f81893147..000000000
--- a/openlp/core/ui/media/systemplayer.py
+++ /dev/null
@@ -1,332 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2019 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-"""
-The :mod:`~openlp.core.ui.media.systemplayer` contains the system (aka QtMultimedia) player component.
-"""
-import functools
-import logging
-import mimetypes
-
-from PyQt5 import QtCore, QtMultimedia, QtMultimediaWidgets
-
-from openlp.core.common.i18n import translate
-from openlp.core.threading import ThreadWorker, is_thread_finished, run_thread
-from openlp.core.ui.media import MediaState
-from openlp.core.ui.media.mediaplayer import MediaPlayer
-
-
-log = logging.getLogger(__name__)
-
-ADDITIONAL_EXT = {
- 'audio/ac3': ['.ac3'],
- 'audio/flac': ['.flac'],
- 'audio/x-m4a': ['.m4a'],
- 'audio/midi': ['.mid', '.midi'],
- 'audio/x-mp3': ['.mp3'],
- 'audio/mpeg': ['.mp3', '.mp2', '.mpga', '.mpega', '.m4a'],
- 'audio/qcelp': ['.qcp'],
- 'audio/x-wma': ['.wma'],
- 'audio/x-ms-wma': ['.wma'],
- 'video/x-flv': ['.flv'],
- 'video/x-matroska': ['.mpv', '.mkv'],
- 'video/x-wmv': ['.wmv'],
- 'video/x-mpg': ['.mpg'],
- 'video/mpeg': ['.mp4', '.mts', '.mov'],
- 'video/x-ms-wmv': ['.wmv']
-}
-
-
-class SystemPlayer(MediaPlayer):
- """
- A specialised version of the MediaPlayer class, which provides a QtMultimedia display.
- """
-
- def __init__(self, parent):
- """
- Constructor
- """
- super(SystemPlayer, self).__init__(parent, 'system')
- self.original_name = 'System'
- self.display_name = '&System'
- self.parent = parent
- self.additional_extensions = ADDITIONAL_EXT
- self.media_player = QtMultimedia.QMediaPlayer(None, QtMultimedia.QMediaPlayer.VideoSurface)
- mimetypes.init()
- media_service = self.media_player.service()
- log.info(media_service.__class__.__name__)
- # supportedMimeTypes doesn't return anything on Linux and Windows and
- # the mimetypes it returns on Mac OS X may not be playable.
- supported_codecs = self.media_player.supportedMimeTypes()
- for mime_type in supported_codecs:
- mime_type = str(mime_type)
- log.info(mime_type)
- if mime_type.startswith('audio/'):
- self._add_to_list(self.audio_extensions_list, mime_type)
- elif mime_type.startswith('video/'):
- self._add_to_list(self.video_extensions_list, mime_type)
-
- def _add_to_list(self, mime_type_list, mime_type):
- """
- Add mimetypes to the provided list
- """
- # Add all extensions which mimetypes provides us for supported types.
- extensions = mimetypes.guess_all_extensions(mime_type)
- for extension in extensions:
- ext = '*%s' % extension
- if ext not in mime_type_list:
- mime_type_list.append(ext)
- log.info('MediaPlugin: %s extensions: %s', mime_type, ' '.join(extensions))
-
- def disconnect_slots(self, signal):
- """
- Safely disconnect the slots from `signal`
- """
- try:
- signal.disconnect()
- except TypeError:
- # If disconnect() is called on a signal without slots, it throws a TypeError
- pass
-
- def setup(self, display):
- """
- Set up the player widgets
- :param display:
- """
- display.video_widget = QtMultimediaWidgets.QVideoWidget(display)
- display.video_widget.resize(display.size())
- display.media_player = QtMultimedia.QMediaPlayer(display)
- display.media_player.setVideoOutput(display.video_widget)
- display.video_widget.raise_()
- display.video_widget.hide()
- self.has_own_widget = True
-
- def check_available(self):
- """
- Check if the player is available
- """
- return True
-
- def load(self, display):
- """
- Load a video into the display
-
- :param display: The display where the media is
- """
- log.debug('load vid in System Controller')
- controller = display.controller
- volume = controller.media_info.volume
- path = controller.media_info.file_info.absoluteFilePath()
- # Check if file is playable due to mimetype filters being nonexistent on Linux and Windows
- if self.check_media(path):
- display.media_player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(path)))
- self.volume(display, volume)
- return True
- else:
- return False
-
- def resize(self, display):
- """
- Resize the display
-
- :param display: The display where the media is
- """
- display.video_widget.resize(display.size())
-
- def play(self, display):
- """
- Play the current media item
-
- :param display: The display where the media is
- """
- log.info('Play the current item')
- controller = display.controller
- start_time = 0
- if display.controller.is_live:
- if self.get_live_state() != QtMultimedia.QMediaPlayer.PausedState and controller.media_info.start_time > 0:
- start_time = controller.media_info.start_time
- else:
- if self.get_preview_state() != QtMultimedia.QMediaPlayer.PausedState and \
- controller.media_info.start_time > 0:
- start_time = controller.media_info.start_time
- display.media_player.play()
- if start_time > 0:
- self.seek(display, controller.media_info.start_time * 1000)
- self.volume(display, controller.media_info.volume)
- self.disconnect_slots(display.media_player.durationChanged)
- display.media_player.durationChanged.connect(functools.partial(self.set_duration, controller))
- self.set_state(MediaState.Playing, display)
- display.video_widget.raise_()
- return True
-
- def pause(self, display):
- """
- Pause the current media item
-
- :param display: The display where the media is
- """
- display.media_player.pause()
- if display.controller.is_live:
- if self.get_live_state() == QtMultimedia.QMediaPlayer.PausedState:
- self.set_state(MediaState.Paused, display)
- else:
- if self.get_preview_state() == QtMultimedia.QMediaPlayer.PausedState:
- self.set_state(MediaState.Paused, display)
-
- def stop(self, display):
- """
- Stop the current media item
-
- :param display: The display where the media is
- """
- display.media_player.stop()
- self.set_visible(display, False)
- self.set_state(MediaState.Stopped, display)
-
- def volume(self, display, volume):
- """
- Set the volume
-
- :param display: The display where the media is
- :param volume: The volume to be set
- """
- if display.has_audio:
- display.media_player.setVolume(volume)
-
- def seek(self, display, seek_value):
- """
- Go to a particular point in the current media item
-
- :param display: The display where the media is
- :param seek_value: The where to seek to
- """
- display.media_player.setPosition(seek_value)
-
- def reset(self, display):
- """
- Reset the media player
-
- :param display: The display where the media is
- """
- display.media_player.stop()
- display.media_player.setMedia(QtMultimedia.QMediaContent())
- self.set_visible(display, False)
- display.video_widget.setVisible(False)
- self.set_state(MediaState.Off, display)
-
- def set_visible(self, display, status):
- """
- Set the visibility of the widget
-
- :param display: The display where the media is
- :param status: The visibility status to be set
- """
- if self.has_own_widget:
- display.video_widget.setVisible(status)
-
- @staticmethod
- def set_duration(controller, duration):
- """
-
- :param controller: the controller displaying the media
- :param duration: how long is the media
- :return:
- """
- controller.seek_slider.setMaximum(controller.media_info.length)
-
- def update_ui(self, display):
- """
- Update the UI
-
- :param display: The display where the media is
- """
- if display.media_player.state() == QtMultimedia.QMediaPlayer.PausedState and self.state != MediaState.Paused:
- self.pause(display)
- controller = display.controller
- if controller.media_info.end_time > 0:
- if display.media_player.position() > controller.media_info.end_time:
- self.stop(display)
- self.set_visible(display, False)
- if not controller.seek_slider.isSliderDown():
- controller.seek_slider.blockSignals(True)
- controller.seek_slider.setSliderPosition(display.media_player.position())
- controller.seek_slider.blockSignals(False)
-
- def get_media_display_css(self):
- """
- Add css style sheets to htmlbuilder
- """
- return ''
-
- def get_info(self):
- """
- Return some info about this player
- """
- return (translate('Media.player', 'This media player uses your operating system '
- 'to provide media capabilities.') +
- '
' + translate('Media.player', 'Audio') +
- '
' + str(self.audio_extensions_list) +
- '
' + translate('Media.player', 'Video') +
- '
' + str(self.video_extensions_list) + '
')
-
- def check_media(self, path):
- """
- Check if a file can be played
- Uses a separate QMediaPlayer in a thread
-
- :param path: Path to file to be checked
- :return: True if file can be played otherwise False
- """
- check_media_worker = CheckMediaWorker(path)
- check_media_worker.setVolume(0)
- run_thread(check_media_worker, 'check_media')
- while not is_thread_finished('check_media'):
- self.application.processEvents()
- return check_media_worker.result
-
-
-class CheckMediaWorker(QtMultimedia.QMediaPlayer, ThreadWorker):
- """
- Class used to check if a media file is playable
- """
- def __init__(self, path):
- super(CheckMediaWorker, self).__init__(None, QtMultimedia.QMediaPlayer.VideoSurface)
- self.path = path
-
- def start(self):
- """
- Start the thread worker
- """
- self.result = None
- self.error.connect(functools.partial(self.signals, 'error'))
- self.mediaStatusChanged.connect(functools.partial(self.signals, 'media'))
- self.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(self.path)))
- self.play()
-
- def signals(self, origin, status):
- if origin == 'media' and status == self.BufferedMedia:
- self.result = True
- self.stop()
- self.quit.emit()
- elif origin == 'error' and status != self.NoError:
- self.result = False
- self.stop()
- self.quit.emit()
diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py
index 0cadc8837..bf2030b9a 100644
--- a/openlp/core/ui/media/vlcplayer.py
+++ b/openlp/core/ui/media/vlcplayer.py
@@ -152,43 +152,42 @@ class VlcPlayer(MediaPlayer):
self.audio_extensions_list = AUDIO_EXT
self.video_extensions_list = VIDEO_EXT
- def setup(self, display):
+ def setup(self, output_display, live_display):
"""
Set up the media player
- :param display: The display where the media is
+ :param output_display: The display where the media is
+ :param live_display: Is the display a live one.
:return:
"""
vlc = get_vlc()
- display.vlc_widget = QtWidgets.QFrame(display)
- display.vlc_widget.setFrameStyle(QtWidgets.QFrame.NoFrame)
+ output_display.vlc_widget = QtWidgets.QFrame(output_display)
+ output_display.vlc_widget.setFrameStyle(QtWidgets.QFrame.NoFrame)
# creating a basic vlc instance
command_line_options = '--no-video-title-show'
- if not display.has_audio:
- command_line_options += ' --no-audio --no-video-title-show'
- if Settings().value('advanced/hide mouse') and display.controller.is_live:
+ if Settings().value('advanced/hide mouse') and live_display:
command_line_options += ' --mouse-hide-timeout=0'
- display.vlc_instance = vlc.Instance(command_line_options)
+ output_display.vlc_instance = vlc.Instance(command_line_options)
# creating an empty vlc media player
- display.vlc_media_player = display.vlc_instance.media_player_new()
- display.vlc_widget.resize(display.size())
- display.vlc_widget.raise_()
- display.vlc_widget.hide()
+ output_display.vlc_media_player = output_display.vlc_instance.media_player_new()
+ output_display.vlc_widget.resize(output_display.size())
+ output_display.vlc_widget.raise_()
+ output_display.vlc_widget.hide()
# The media player has to be 'connected' to the QFrame.
# (otherwise a video would be displayed in it's own window)
# This is platform specific!
# You have to give the id of the QFrame (or similar object)
# to vlc, different platforms have different functions for this.
- win_id = int(display.vlc_widget.winId())
+ win_id = int(output_display.vlc_widget.winId())
if is_win():
- display.vlc_media_player.set_hwnd(win_id)
+ output_display.vlc_media_player.set_hwnd(win_id)
elif is_macosx():
# We have to use 'set_nsobject' since Qt5 on OSX uses Cocoa
# framework and not the old Carbon.
- display.vlc_media_player.set_nsobject(win_id)
+ output_display.vlc_media_player.set_nsobject(win_id)
else:
# for Linux/*BSD using the X Server
- display.vlc_media_player.set_xwindow(win_id)
+ output_display.vlc_media_player.set_xwindow(win_id)
self.has_own_widget = True
def check_available(self):
@@ -197,43 +196,45 @@ class VlcPlayer(MediaPlayer):
"""
return get_vlc() is not None
- def load(self, display, file):
+ def load(self, output_display, file):
"""
Load a video into VLC
- :param display: The display where the media is
+ :param output_display: The display where the media is
:param file: file to be played
:return:
"""
vlc = get_vlc()
log.debug('load vid in Vlc Controller')
- controller = display.controller
+ controller = output_display
volume = controller.media_info.volume
path = os.path.normcase(file)
# create the media
if controller.media_info.media_type == MediaType.CD:
if is_win():
path = '/' + path
- display.vlc_media = display.vlc_instance.media_new_location('cdda://' + path)
- display.vlc_media_player.set_media(display.vlc_media)
- display.vlc_media_player.play()
+ output_display.vlc_media = output_display.vlc_instance.media_new_location('cdda://' + path)
+ output_display.vlc_media_player.set_media(output_display.vlc_media)
+ output_display.vlc_media_player.play()
# Wait for media to start playing. In this case VLC actually returns an error.
- self.media_state_wait(display, vlc.State.Playing)
+ self.media_state_wait(output_display, vlc.State.Playing)
# If subitems exists, this is a CD
- audio_cd_tracks = display.vlc_media.subitems()
+ audio_cd_tracks = output_display.vlc_media.subitems()
if not audio_cd_tracks or audio_cd_tracks.count() < 1:
return False
- display.vlc_media = audio_cd_tracks.item_at_index(controller.media_info.title_track)
+ output_display.vlc_media = audio_cd_tracks.item_at_index(controller.media_info.title_track)
+ elif controller.media_info.media_type == MediaType.Stream:
+ output_display.vlc_media = output_display.vlc_instance.media_new_location('ZZZZZZ')
else:
- display.vlc_media = display.vlc_instance.media_new_path(path)
+ output_display.vlc_media = output_display.vlc_instance.media_new_path(path)
# put the media in the media player
- display.vlc_media_player.set_media(display.vlc_media)
+ output_display.vlc_media_player.set_media(output_display.vlc_media)
# parse the metadata of the file
- display.vlc_media.parse()
- self.volume(display, volume)
+ output_display.vlc_media.parse()
+ self.volume(output_display, volume)
return True
- def media_state_wait(self, display, media_state):
+ def media_state_wait(self, output_display, media_state):
"""
Wait for the video to change its state
Wait no longer than 60 seconds. (loading an iso file needs a long time)
@@ -244,171 +245,171 @@ class VlcPlayer(MediaPlayer):
"""
vlc = get_vlc()
start = datetime.now()
- while media_state != display.vlc_media.get_state():
- if display.vlc_media.get_state() == vlc.State.Error:
+ while media_state != output_display.vlc_media.get_state():
+ if output_display.vlc_media.get_state() == vlc.State.Error:
return False
self.application.process_events()
if (datetime.now() - start).seconds > 60:
return False
return True
- def resize(self, display):
+ def resize(self, output_display):
"""
Resize the player
- :param display: The display where the media is
+ :param output_display: The display where the media is
:return:
"""
- display.vlc_widget.resize(display.size())
+ output_display.vlc_widget.resize(output_display.size())
- def play(self, display):
+ def play(self, controller, output_display):
"""
Play the current item
- :param display: The display where the media is
+ :param controller: Which Controller is running the show.
+ :param output_display: The display where the media is
:return:
"""
vlc = get_vlc()
- controller = display.controller
start_time = 0
log.debug('vlc play')
- if display.controller.is_live:
- if self.get_live_state() != MediaState.Paused and controller.media_info.start_time > 0:
- start_time = controller.media_info.start_time
+ if output_display.is_display:
+ if self.get_live_state() != MediaState.Paused and output_display.media_info.start_time > 0:
+ start_time = output_display.media_info.start_time
else:
- if self.get_preview_state() != MediaState.Paused and controller.media_info.start_time > 0:
- start_time = controller.media_info.start_time
- threading.Thread(target=display.vlc_media_player.play).start()
- if not self.media_state_wait(display, vlc.State.Playing):
+ if self.get_preview_state() != MediaState.Paused and output_display.media_info.start_time > 0:
+ start_time = output_display.media_info.start_time
+ threading.Thread(target=output_display.vlc_media_player.play).start()
+ if not self.media_state_wait(output_display, vlc.State.Playing):
return False
- if display.controller.is_live:
- if self.get_live_state() != MediaState.Paused and controller.media_info.start_time > 0:
+ if output_display.is_display:
+ if self.get_live_state() != MediaState.Paused and output_display.media_info.start_time > 0:
log.debug('vlc play, start time set')
- start_time = controller.media_info.start_time
+ start_time = output_display.media_info.start_time
else:
- if self.get_preview_state() != MediaState.Paused and controller.media_info.start_time > 0:
+ if self.get_preview_state() != MediaState.Paused and output_display.media_info.start_time > 0:
log.debug('vlc play, start time set')
- start_time = controller.media_info.start_time
- log.debug('mediatype: ' + str(controller.media_info.media_type))
+ start_time = output_display.media_info.start_time
+ log.debug('mediatype: ' + str(output_display.media_info.media_type))
# Set tracks for the optical device
- if controller.media_info.media_type == MediaType.DVD and \
+ if output_display.media_info.media_type == MediaType.DVD and \
self.get_live_state() != MediaState.Paused and self.get_preview_state() != MediaState.Paused:
log.debug('vlc play, playing started')
- if controller.media_info.title_track > 0:
- log.debug('vlc play, title_track set: ' + str(controller.media_info.title_track))
- display.vlc_media_player.set_title(controller.media_info.title_track)
- display.vlc_media_player.play()
- if not self.media_state_wait(display, vlc.State.Playing):
+ if output_display.media_info.title_track > 0:
+ log.debug('vlc play, title_track set: ' + str(output_display.media_info.title_track))
+ output_display.vlc_media_player.set_title(output_display.media_info.title_track)
+ output_display.vlc_media_player.play()
+ if not self.media_state_wait(output_display, vlc.State.Playing):
return False
- if controller.media_info.audio_track > 0:
- display.vlc_media_player.audio_set_track(controller.media_info.audio_track)
- log.debug('vlc play, audio_track set: ' + str(controller.media_info.audio_track))
- if controller.media_info.subtitle_track > 0:
- display.vlc_media_player.video_set_spu(controller.media_info.subtitle_track)
- log.debug('vlc play, subtitle_track set: ' + str(controller.media_info.subtitle_track))
- if controller.media_info.start_time > 0:
- log.debug('vlc play, starttime set: ' + str(controller.media_info.start_time))
- start_time = controller.media_info.start_time
- controller.media_info.length = controller.media_info.end_time - controller.media_info.start_time
- self.volume(display, controller.media_info.volume)
- if start_time > 0 and display.vlc_media_player.is_seekable():
- display.vlc_media_player.set_time(int(start_time))
- controller.seek_slider.setMaximum(controller.media_info.length)
- self.set_state(MediaState.Playing, display)
- display.vlc_widget.raise_()
+ if output_display.media_info.audio_track > 0:
+ output_display.vlc_media_player.audio_set_track(output_display.media_info.audio_track)
+ log.debug('vlc play, audio_track set: ' + str(output_display.media_info.audio_track))
+ if output_display.media_info.subtitle_track > 0:
+ output_display.vlc_media_player.video_set_spu(output_display.media_info.subtitle_track)
+ log.debug('vlc play, subtitle_track set: ' + str(output_display.media_info.subtitle_track))
+ if output_display.media_info.start_time > 0:
+ log.debug('vlc play, starttime set: ' + str(output_display.media_info.start_time))
+ start_time = output_display.media_info.start_time
+ output_display.media_info.length = output_display.media_info.end_time - output_display.media_info.start_time
+ self.volume(output_display, output_display.media_info.volume)
+ if start_time > 0 and output_display.vlc_media_player.is_seekable():
+ output_display.vlc_media_player.set_time(int(start_time))
+ controller.seek_slider.setMaximum(output_display.media_info.length)
+ self.set_state(MediaState.Playing, output_display)
+ output_display.vlc_widget.raise_()
return True
- def pause(self, display):
+ def pause(self, output_display):
"""
Pause the current item
- :param display: The display where the media is
+ :param output_display: The display where the media is
:return:
"""
vlc = get_vlc()
- if display.vlc_media.get_state() != vlc.State.Playing:
+ if output_display.vlc_media.get_state() != vlc.State.Playing:
return
- display.vlc_media_player.pause()
- if self.media_state_wait(display, vlc.State.Paused):
- self.set_state(MediaState.Paused, display)
+ output_display.vlc_media_player.pause()
+ if self.media_state_wait(output_display, vlc.State.Paused):
+ self.set_state(MediaState.Paused, output_display)
- def stop(self, display):
+ def stop(self, output_display):
"""
Stop the current item
- :param display: The display where the media is
+ :param output_display: The display where the media is
:return:
"""
- threading.Thread(target=display.vlc_media_player.stop).start()
- self.set_state(MediaState.Stopped, display)
+ threading.Thread(target=output_display.vlc_media_player.stop).start()
+ self.set_state(MediaState.Stopped, output_display)
- def volume(self, display, vol):
+ def volume(self, output_display, vol):
"""
Set the volume
:param vol: The volume to be sets
- :param display: The display where the media is
+ :param output_display: The display where the media is
:return:
"""
- if display.has_audio:
- display.vlc_media_player.audio_set_volume(vol)
+ if output_display.has_audio:
+ output_display.vlc_media_player.audio_set_volume(vol)
- def seek(self, display, seek_value):
+ def seek(self, output_display, seek_value):
"""
Go to a particular position
:param seek_value: The position of where a seek goes to
- :param display: The display where the media is
+ :param output_display: The display where the media is
"""
- if display.controller.media_info.media_type == MediaType.CD \
- or display.controller.media_info.media_type == MediaType.DVD:
- seek_value += int(display.controller.media_info.start_time)
- if display.vlc_media_player.is_seekable():
- display.vlc_media_player.set_time(seek_value)
+ if output_display.controller.media_info.media_type == MediaType.CD \
+ or output_display.controller.media_info.media_type == MediaType.DVD:
+ seek_value += int(output_display.controller.media_info.start_time)
+ if output_display.vlc_media_player.is_seekable():
+ output_display.vlc_media_player.set_time(seek_value)
- def reset(self, display):
+ def reset(self, output_display):
"""
Reset the player
- :param display: The display where the media is
+ :param output_display: The display where the media is
"""
- display.vlc_media_player.stop()
- display.vlc_widget.setVisible(False)
- self.set_state(MediaState.Off, display)
+ output_display.vlc_media_player.stop()
+ output_display.vlc_widget.setVisible(False)
+ self.set_state(MediaState.Off, output_display)
- def set_visible(self, display, status):
+ def set_visible(self, output_display, status):
"""
Set the visibility
- :param display: The display where the media is
+ :param output_display: The display where the media is
:param status: The visibility status
"""
if self.has_own_widget:
- display.vlc_widget.setVisible(status)
+ output_display.vlc_widget.setVisible(status)
- def update_ui(self, display):
+ def update_ui(self, controller, output_display):
"""
Update the UI
- :param display: The display where the media is
+ :param controller: Which Controller is running the show.
+ :param output_display: The display where the media is
"""
vlc = get_vlc()
# Stop video if playback is finished.
- if display.vlc_media.get_state() == vlc.State.Ended:
- self.stop(display)
- controller = display.controller
+ if output_display.vlc_media.get_state() == vlc.State.Ended:
+ self.stop(output_display)
if controller.media_info.end_time > 0:
- if display.vlc_media_player.get_time() > controller.media_info.end_time:
- self.stop(display)
- self.set_visible(display, False)
+ if output_display.vlc_media_player.get_time() > controller.media_info.end_time:
+ self.stop(output_display)
+ self.set_visible(output_display, False)
if not controller.seek_slider.isSliderDown():
controller.seek_slider.blockSignals(True)
- if display.controller.media_info.media_type == MediaType.CD \
- or display.controller.media_info.media_type == MediaType.DVD:
+ if controller.media_info.media_type == MediaType.CD \
+ or controller.media_info.media_type == MediaType.DVD:
controller.seek_slider.setSliderPosition(
- display.vlc_media_player.get_time() - int(display.controller.media_info.start_time))
+ output_display.vlc_media_player.get_time() - int(output_display.controller.media_info.start_time))
else:
- controller.seek_slider.setSliderPosition(display.vlc_media_player.get_time())
+ controller.seek_slider.setSliderPosition(output_display.vlc_media_player.get_time())
controller.seek_slider.blockSignals(False)
def get_info(self):
diff --git a/openlp/core/ui/screenstab.py b/openlp/core/ui/screenstab.py
index 37c817b72..c39045d43 100644
--- a/openlp/core/ui/screenstab.py
+++ b/openlp/core/ui/screenstab.py
@@ -41,7 +41,7 @@ class ScreensTab(SettingsTab):
"""
Initialise the screen settings tab
"""
- self.icon_path = UiIcons().settings
+ self.icon_path = UiIcons().desktop
screens_translated = translate('OpenLP.ScreensTab', 'Screens')
super(ScreensTab, self).__init__(parent, 'Screens', screens_translated)
self.settings_section = 'core'
diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py
index 2962b2399..d4f0ac30b 100644
--- a/openlp/core/ui/settingsform.py
+++ b/openlp/core/ui/settingsform.py
@@ -30,13 +30,14 @@ from openlp.core.state import State
from openlp.core.api.tab import ApiTab
from openlp.core.common.mixins import RegistryProperties
from openlp.core.common.registry import Registry
+from openlp.core.common.settings import Settings
from openlp.core.lib import build_icon
from openlp.core.projectors.tab import ProjectorTab
from openlp.core.ui.advancedtab import AdvancedTab
from openlp.core.ui.generaltab import GeneralTab
from openlp.core.ui.screenstab import ScreensTab
from openlp.core.ui.themestab import ThemesTab
-# from openlp.core.ui.media.playertab import PlayerTab
+from openlp.core.ui.media.mediatab import MediaTab
from openlp.core.ui.settingsdialog import Ui_SettingsDialog
@@ -78,8 +79,8 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties):
self.insert_tab(self.advanced_tab)
self.insert_tab(self.screens_tab)
self.insert_tab(self.themes_tab)
- self.insert_tab(self.advanced_tab)
- # self.insert_tab(self.player_tab)
+ if Settings().value('core/experimental'):
+ self.insert_tab(self.player_tab)
self.insert_tab(self.projector_tab)
self.insert_tab(self.api_tab)
for plugin in State().list_plugins():
@@ -160,15 +161,17 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties):
self.themes_tab = ThemesTab(self)
self.projector_tab = ProjectorTab(self)
self.advanced_tab = AdvancedTab(self)
- # self.player_tab = PlayerTab(self)
+ if Settings().value('core/experimental'):
+ self.player_tab = MediaTab(self)
self.api_tab = ApiTab(self)
self.screens_tab = ScreensTab(self)
except Exception as e:
print(e)
- # Post setup
self.general_tab.post_set_up()
self.themes_tab.post_set_up()
self.advanced_tab.post_set_up()
+ if Settings().value('core/experimental'):
+ self.player_tab.post_set_up()
self.api_tab.post_set_up()
for plugin in State().list_plugins():
if plugin.settings_tab:
diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py
index 3de015e97..146c060f6 100644
--- a/openlp/core/ui/slidecontroller.py
+++ b/openlp/core/ui/slidecontroller.py
@@ -23,6 +23,7 @@
The :mod:`slidecontroller` module contains the most important part of OpenLP - the slide controller
"""
import copy
+import datetime
from collections import deque
from threading import Lock
@@ -70,6 +71,45 @@ NON_TEXT_MENU = [
]
+class MediaSlider(QtWidgets.QSlider):
+ """
+ Allows the mouse events of a slider to be overridden and extra functionality added
+ """
+ def __init__(self, direction, manager, controller):
+ """
+ Constructor
+ """
+ super(MediaSlider, self).__init__(direction)
+ self.manager = manager
+ self.controller = controller
+
+ def mouseMoveEvent(self, event):
+ """
+ Override event to allow hover time to be displayed.
+
+ :param event: The triggering event
+ """
+ time_value = QtWidgets.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), event.x(), self.width())
+ self.setToolTip('%s' % datetime.timedelta(seconds=int(time_value / 1000)))
+ QtWidgets.QSlider.mouseMoveEvent(self, event)
+
+ def mousePressEvent(self, event):
+ """
+ Mouse Press event no new functionality
+ :param event: The triggering event
+ """
+ QtWidgets.QSlider.mousePressEvent(self, event)
+
+ def mouseReleaseEvent(self, event):
+ """
+ Set the slider position when the mouse is clicked and released on the slider.
+
+ :param event: The triggering event
+ """
+ self.setValue(QtWidgets.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), event.x(), self.width()))
+ QtWidgets.QSlider.mouseReleaseEvent(self, event)
+
+
class InfoLabel(QtWidgets.QLabel):
"""
InfoLabel is a subclassed QLabel. Created to provide the ablilty to add a ellipsis if the text is cut off. Original
@@ -316,8 +356,59 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
'Clear'),
triggers=self.on_clear)
self.controller_layout.addWidget(self.toolbar)
- # Build the Media Toolbar
- self.media_controller.register_controller(self)
+ # Build a Media ToolBar
+ self.mediabar = OpenLPToolbar(self)
+ self.mediabar.add_toolbar_action('playbackPlay', text='media_playback_play',
+ icon=UiIcons().play,
+ tooltip=translate('OpenLP.SlideController', 'Start playing media.'),
+ triggers=self.send_to_plugins)
+ self.mediabar.add_toolbar_action('playbackPause', text='media_playback_pause',
+ icon=UiIcons().pause,
+ tooltip=translate('OpenLP.SlideController', 'Pause playing media.'),
+ triggers=self.send_to_plugins)
+ self.mediabar.add_toolbar_action('playbackStop', text='media_playback_stop',
+ icon=UiIcons().stop,
+ tooltip=translate('OpenLP.SlideController', 'Stop playing media.'),
+ triggers=self.send_to_plugins)
+ self.mediabar.add_toolbar_action('playbackLoop', text='media_playback_loop',
+ icon=UiIcons().repeat, checked=False,
+ tooltip=translate('OpenLP.SlideController', 'Loop playing media.'),
+ triggers=self.send_to_plugins)
+ self.position_label = QtWidgets.QLabel()
+ self.position_label.setText(' 00:00 / 00:00')
+ self.position_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
+ self.position_label.setToolTip(translate('OpenLP.SlideController', 'Video timer.'))
+ self.position_label.setMinimumSize(90, 0)
+ self.position_label.setObjectName('position_label')
+ self.mediabar.add_toolbar_widget(self.position_label)
+ # Build the seek_slider.
+ self.seek_slider = MediaSlider(QtCore.Qt.Horizontal, self, self)
+ self.seek_slider.setMaximum(1000)
+ self.seek_slider.setTracking(True)
+ self.seek_slider.setMouseTracking(True)
+ self.seek_slider.setToolTip(translate('OpenLP.SlideController', 'Video position.'))
+ self.seek_slider.setGeometry(QtCore.QRect(90, 260, 221, 24))
+ self.seek_slider.setObjectName('seek_slider')
+ self.mediabar.add_toolbar_widget(self.seek_slider)
+ # Build the volume_slider.
+ self.volume_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
+ self.volume_slider.setTickInterval(10)
+ self.volume_slider.setTickPosition(QtWidgets.QSlider.TicksAbove)
+ self.volume_slider.setMinimum(0)
+ self.volume_slider.setMaximum(100)
+ self.volume_slider.setTracking(True)
+ self.volume_slider.setToolTip(translate('OpenLP.SlideController', 'Audio Volume.'))
+ # self.volume_slider.setValue(self.media_info.volume)
+ self.volume_slider.setGeometry(QtCore.QRect(90, 160, 221, 24))
+ self.volume_slider.setObjectName('volume_slider')
+ self.mediabar.add_toolbar_widget(self.volume_slider)
+ self.controller_layout.addWidget(self.mediabar)
+ self.mediabar.setVisible(False)
+ if not self.is_live:
+ self.volume_slider.setEnabled(False)
+ # Signals
+ self.seek_slider.valueChanged.connect(self.send_to_plugins)
+ self.volume_slider.valueChanged.connect(self.send_to_plugins)
if self.is_live:
# Build the Song Toolbar
self.song_menu = QtWidgets.QToolButton(self.toolbar)
@@ -556,8 +647,6 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
# self.__add_actions_to_widget(self.display)
# The SlidePreview's ratio.
- # TODO: Need to basically update everything
-
def __add_actions_to_widget(self, widget):
"""
Add actions to the widget specified by `widget`
@@ -1398,10 +1487,10 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
:param item: The service item to be processed
"""
if self.is_live and self.hide_mode() == HideMode.Theme:
- self.media_controller.video(self.controller_type, item, HideMode.Blank)
+ self.media_controller.load_video(self.controller_type, item, HideMode.Blank)
self.on_blank_display(True)
else:
- self.media_controller.video(self.controller_type, item, self.hide_mode())
+ self.media_controller.load_video(self.controller_type, item, self.hide_mode())
if not self.is_live:
self.preview_display.show()
@@ -1491,7 +1580,7 @@ class PreviewController(RegistryBase, SlideController):
self.type_prefix = 'preview'
self.category = 'Preview Toolbar'
- def bootstrap_post_set_up(self):
+ def bootstrap_initialise(self):
"""
process the bootstrap post setup request
"""
@@ -1523,7 +1612,7 @@ class LiveController(RegistryBase, SlideController):
self.category = UiStrings().LiveToolbar
ActionList.get_instance().add_category(str(self.category), CategoryOrder.standard_toolbar)
- def bootstrap_post_set_up(self):
+ def bootstrap_initialise(self):
"""
process the bootstrap post setup request
"""
diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py
index a3349bf14..c38cabfad 100644
--- a/openlp/core/ui/themeform.py
+++ b/openlp/core/ui/themeform.py
@@ -330,6 +330,8 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
self.video_color_button.color = self.theme.background_border_color
self.video_path_edit.path = self.theme.background_filename
self.setField('background_type', 4)
+ elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Stream):
+ self.setField('background_type', 5)
elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Transparent):
self.setField('background_type', 3)
if self.theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.Horizontal):
diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py
index 799586b95..c8cb0eb18 100644
--- a/openlp/core/ui/themewizard.py
+++ b/openlp/core/ui/themewizard.py
@@ -64,7 +64,7 @@ class Ui_ThemeWizard(object):
self.background_label = QtWidgets.QLabel(self.background_page)
self.background_label.setObjectName('background_label')
self.background_combo_box = QtWidgets.QComboBox(self.background_page)
- self.background_combo_box.addItems(['', '', '', '', ''])
+ self.background_combo_box.addItems(['', '', '', '', '', ''])
self.background_combo_box.setObjectName('background_combo_box')
self.background_type_layout.addRow(self.background_label, self.background_combo_box)
self.background_type_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
@@ -410,6 +410,8 @@ class Ui_ThemeWizard(object):
self.background_combo_box.setItemText(BackgroundType.Video, UiStrings().Video)
self.background_combo_box.setItemText(BackgroundType.Transparent,
translate('OpenLP.ThemeWizard', 'Transparent'))
+ self.background_combo_box.setItemText(BackgroundType.Stream,
+ translate('OpenLP.ThemeWizard', 'Live Stream'))
self.color_label.setText(translate('OpenLP.ThemeWizard', 'color:'))
self.gradient_start_label.setText(translate('OpenLP.ThemeWizard', 'Starting color:'))
self.gradient_end_label.setText(translate('OpenLP.ThemeWizard', 'Ending color:'))
diff --git a/openlp/core/widgets/views.py b/openlp/core/widgets/views.py
index 20da9402d..acbf2f915 100644
--- a/openlp/core/widgets/views.py
+++ b/openlp/core/widgets/views.py
@@ -203,7 +203,10 @@ class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties):
if self.service_item.is_capable(ItemCapabilities.HasThumbnails):
pixmap = QtGui.QPixmap(remove_url_prefix(slide['thumbnail']))
else:
- pixmap = QtGui.QPixmap(remove_url_prefix(slide['image']))
+ if isinstance(slide['image'], QtGui.QIcon):
+ pixmap = slide['image'].pixmap(QtCore.QSize(32, 32))
+ else:
+ pixmap = QtGui.QPixmap(remove_url_prefix(slide['image']))
else:
pixmap = QtGui.QPixmap(remove_url_prefix(slide['path']))
label.setPixmap(pixmap)
diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py
index 2ebacc0ae..97ff56c93 100644
--- a/openlp/plugins/media/lib/mediaitem.py
+++ b/openlp/plugins/media/lib/mediaitem.py
@@ -116,6 +116,8 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
self.can_preview = False
self.can_make_live = False
self.can_add_to_service = False
+ if State().check_preconditions('media_live'):
+ self.can_make_live = False
def add_list_view_to_toolbar(self):
"""
@@ -264,7 +266,8 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
:param media: The media
:param target_group:
"""
- media.sort(key=lambda file_path: get_natural_key(file_path.name))
+ # TODO needs to be fixed as no idea why this fails
+ # media.sort(key=lambda file_path: get_natural_key(file_path.name))
for track in media:
track_info = QtCore.QFileInfo(track)
item_name = None
diff --git a/openlp/plugins/media/lib/mediatab.py b/openlp/plugins/media/lib/mediatab.py
deleted file mode 100644
index c4f823250..000000000
--- a/openlp/plugins/media/lib/mediatab.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2019 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-
-from PyQt5 import QtWidgets
-
-from openlp.core.common.i18n import UiStrings, translate
-from openlp.core.common.settings import Settings
-from openlp.core.lib.settingstab import SettingsTab
-
-
-class MediaTab(SettingsTab):
- """
- MediaTab is the Media settings tab in the settings dialog.
- """
- def __init__(self, parent, title, visible_title, icon_path):
- self.parent = parent
- super(MediaTab, self).__init__(parent, title, visible_title, icon_path)
-
- def setup_ui(self):
- self.setObjectName('MediaTab')
- super(MediaTab, self).setup_ui()
- self.advanced_group_box = QtWidgets.QGroupBox(self.left_column)
- self.advanced_group_box.setObjectName('advanced_group_box')
- self.advanced_layout = QtWidgets.QVBoxLayout(self.advanced_group_box)
- self.advanced_layout.setObjectName('advanced_layout')
- self.override_player_check_box = QtWidgets.QCheckBox(self.advanced_group_box)
- self.override_player_check_box.setObjectName('override_player_check_box')
- self.advanced_layout.addWidget(self.override_player_check_box)
- self.auto_start_check_box = QtWidgets.QCheckBox(self.advanced_group_box)
- self.auto_start_check_box.setObjectName('auto_start_check_box')
- self.advanced_layout.addWidget(self.auto_start_check_box)
- self.left_layout.addWidget(self.advanced_group_box)
- self.left_layout.addStretch()
- self.right_layout.addStretch()
-
- def retranslate_ui(self):
- self.advanced_group_box.setTitle(UiStrings().Advanced)
- self.override_player_check_box.setText(translate('MediaPlugin.MediaTab', 'Allow media player to be overridden'))
- self.auto_start_check_box.setText(translate('MediaPlugin.MediaTab', 'Start new Live media automatically'))
-
- def load(self):
- self.override_player_check_box.setChecked(Settings().value(self.settings_section + '/override player'))
- self.auto_start_check_box.setChecked(Settings().value(self.settings_section + '/media auto start'))
-
- def save(self):
- setting_key = self.settings_section + '/override player'
- if Settings().value(setting_key) != self.override_player_check_box.checkState():
- Settings().setValue(setting_key, self.override_player_check_box.checkState())
- self.settings_form.register_post_process('mediaitem_suffix_reset')
- self.settings_form.register_post_process('mediaitem_media_rebuild')
- self.settings_form.register_post_process('mediaitem_suffixes')
- setting_key = self.settings_section + '/media auto start'
- if Settings().value(setting_key) != self.auto_start_check_box.checkState():
- Settings().setValue(setting_key, self.auto_start_check_box.checkState())
diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py
index 4b9bb366b..42acda051 100644
--- a/openlp/plugins/media/mediaplugin.py
+++ b/openlp/plugins/media/mediaplugin.py
@@ -24,8 +24,6 @@ The Media plugin
"""
import logging
-from PyQt5 import QtCore
-
from openlp.core.state import State
from openlp.core.api.http import register_endpoint
from openlp.core.common.i18n import translate
@@ -34,7 +32,6 @@ from openlp.core.lib import build_icon
from openlp.core.lib.plugin import Plugin, StringContent
from openlp.plugins.media.endpoint import api_media_endpoint, media_endpoint
from openlp.plugins.media.lib.mediaitem import MediaMediaItem
-from openlp.plugins.media.lib.mediatab import MediaTab
log = logging.getLogger(__name__)
@@ -42,7 +39,6 @@ log = logging.getLogger(__name__)
# Some settings starting with "media" are in core, because they are needed for core functionality.
__default_settings__ = {
- 'media/media auto start': QtCore.Qt.Unchecked,
'media/media files': [],
'media/last directory': None
}
@@ -78,15 +74,6 @@ class MediaPlugin(Plugin):
"""
pass
- def create_settings_tab(self, parent):
- """
- Create the settings Tab
-
- :param parent:
- """
- visible_name = self.get_string(StringContent.VisibleName)
- self.settings_tab = MediaTab(parent, self.name, visible_name['title'], self.icon_path)
-
@staticmethod
def about():
"""
diff --git a/tests/functional/openlp_core/common/test_common.py b/tests/functional/openlp_core/common/test_common.py
index 7c90c0176..03ca2ac33 100644
--- a/tests/functional/openlp_core/common/test_common.py
+++ b/tests/functional/openlp_core/common/test_common.py
@@ -139,13 +139,13 @@ class TestCommonFunctions(TestCase):
Test `path_to_module` when supplied with a `Path` object
"""
# GIVEN: A `Path` object
- path = Path('core', 'ui', 'media', 'webkitplayer.py')
+ path = Path('core', 'ui', 'media', 'vlcplayer.py')
# WHEN: Calling path_to_module with the `Path` object
result = path_to_module(path)
# THEN: path_to_module should return the module name
- assert result == 'openlp.core.ui.media.webkitplayer'
+ assert result == 'openlp.core.ui.media.vlcplayer'
def test_trace_error_handler(self):
"""
diff --git a/tests/functional/openlp_core/ui/media/test_systemplayer.py b/tests/functional/openlp_core/ui/media/test_systemplayer.py
deleted file mode 100644
index 7d447c220..000000000
--- a/tests/functional/openlp_core/ui/media/test_systemplayer.py
+++ /dev/null
@@ -1,567 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2019 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-"""
-Package to test the openlp.core.ui.media.systemplayer package.
-"""
-from unittest import TestCase
-from unittest.mock import MagicMock, call, patch
-
-from PyQt5 import QtCore, QtMultimedia
-
-from openlp.core.common.registry import Registry
-from openlp.core.ui.media import MediaState
-from openlp.core.ui.media.systemplayer import ADDITIONAL_EXT, CheckMediaWorker, SystemPlayer
-
-
-class TestSystemPlayer(TestCase):
- """
- Test the system media player
- """
- @patch('openlp.core.ui.media.systemplayer.mimetypes')
- @patch('openlp.core.ui.media.systemplayer.QtMultimedia.QMediaPlayer')
- def test_constructor(self, MockQMediaPlayer, mocked_mimetypes):
- """
- Test the SystemPlayer constructor
- """
- # GIVEN: The SystemPlayer class and a mockedQMediaPlayer
- mocked_media_player = MagicMock()
- mocked_media_player.supportedMimeTypes.return_value = [
- 'application/postscript',
- 'audio/aiff',
- 'audio/x-aiff',
- 'text/html',
- 'video/animaflex',
- 'video/x-ms-asf'
- ]
- mocked_mimetypes.guess_all_extensions.side_effect = [
- ['.aiff'],
- ['.aiff'],
- ['.afl'],
- ['.asf']
- ]
- MockQMediaPlayer.return_value = mocked_media_player
-
- # WHEN: An object is created from it
- player = SystemPlayer(self)
-
- # THEN: The correct initial values should be set up
- assert 'system' == player.name
- assert 'System' == player.original_name
- assert '&System' == player.display_name
- assert self == player.parent
- assert ADDITIONAL_EXT == player.additional_extensions
- MockQMediaPlayer.assert_called_once_with(None, QtMultimedia.QMediaPlayer.VideoSurface)
- mocked_mimetypes.init.assert_called_once_with()
- mocked_media_player.service.assert_called_once_with()
- mocked_media_player.supportedMimeTypes.assert_called_once_with()
- assert ['*.aiff'] == player.audio_extensions_list
- assert ['*.afl', '*.asf'] == player.video_extensions_list
-
- @patch('openlp.core.ui.media.systemplayer.QtMultimediaWidgets.QVideoWidget')
- @patch('openlp.core.ui.media.systemplayer.QtMultimedia.QMediaPlayer')
- def test_setup(self, MockQMediaPlayer, MockQVideoWidget):
- """
- Test the setup() method of SystemPlayer
- """
- # GIVEN: A SystemPlayer instance and a mock display
- player = SystemPlayer(self)
- mocked_display = MagicMock()
- mocked_display.size.return_value = [1, 2, 3, 4]
- mocked_video_widget = MagicMock()
- mocked_media_player = MagicMock()
- MockQVideoWidget.return_value = mocked_video_widget
- MockQMediaPlayer.return_value = mocked_media_player
-
- # WHEN: setup() is run
- player.setup(mocked_display)
-
- # THEN: The player should have a display widget
- MockQVideoWidget.assert_called_once_with(mocked_display)
- assert mocked_video_widget == mocked_display.video_widget
- mocked_display.size.assert_called_once_with()
- mocked_video_widget.resize.assert_called_once_with([1, 2, 3, 4])
- MockQMediaPlayer.assert_called_with(mocked_display)
- assert mocked_media_player == mocked_display.media_player
- mocked_media_player.setVideoOutput.assert_called_once_with(mocked_video_widget)
- mocked_video_widget.raise_.assert_called_once_with()
- mocked_video_widget.hide.assert_called_once_with()
- assert player.has_own_widget is True
-
- def test_disconnect_slots(self):
- """
- Test that we the disconnect slots method catches the TypeError
- """
- # GIVEN: A SystemPlayer class and a signal that throws a TypeError
- player = SystemPlayer(self)
- mocked_signal = MagicMock()
- mocked_signal.disconnect.side_effect = \
- TypeError('disconnect() failed between \'durationChanged\' and all its connections')
-
- # WHEN: disconnect_slots() is called
- player.disconnect_slots(mocked_signal)
-
- # THEN: disconnect should have been called and the exception should have been ignored
- mocked_signal.disconnect.assert_called_once_with()
-
- def test_check_available(self):
- """
- Test the check_available() method on SystemPlayer
- """
- # GIVEN: A SystemPlayer instance
- player = SystemPlayer(self)
-
- # WHEN: check_available is run
- result = player.check_available()
-
- # THEN: it should be available
- assert result is True
-
- def test_load_valid_media(self):
- """
- Test the load() method of SystemPlayer with a valid media file
- """
- # GIVEN: A SystemPlayer instance and a mocked display
- player = SystemPlayer(self)
- mocked_display = MagicMock()
- mocked_display.controller.media_info.volume = 1
- mocked_display.controller.media_info.file_info.absoluteFilePath.return_value = '/path/to/file'
-
- # WHEN: The load() method is run
- with patch.object(player, 'check_media') as mocked_check_media, \
- patch.object(player, 'volume') as mocked_volume:
- mocked_check_media.return_value = True
- result = player.load(mocked_display)
-
- # THEN: the file is sent to the video widget
- mocked_display.controller.media_info.file_info.absoluteFilePath.assert_called_once_with()
- mocked_check_media.assert_called_once_with('/path/to/file')
- mocked_display.media_player.setMedia.assert_called_once_with(
- QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile('/path/to/file')))
- mocked_volume.assert_called_once_with(mocked_display, 1)
- assert result is True
-
- def test_load_invalid_media(self):
- """
- Test the load() method of SystemPlayer with an invalid media file
- """
- # GIVEN: A SystemPlayer instance and a mocked display
- player = SystemPlayer(self)
- mocked_display = MagicMock()
- mocked_display.controller.media_info.volume = 1
- mocked_display.controller.media_info.file_info.absoluteFilePath.return_value = '/path/to/file'
-
- # WHEN: The load() method is run
- with patch.object(player, 'check_media') as mocked_check_media, \
- patch.object(player, 'volume'):
- mocked_check_media.return_value = False
- result = player.load(mocked_display)
-
- # THEN: stuff
- mocked_display.controller.media_info.file_info.absoluteFilePath.assert_called_once_with()
- mocked_check_media.assert_called_once_with('/path/to/file')
- assert result is False
-
- def test_resize(self):
- """
- Test the resize() method of the SystemPlayer
- """
- # GIVEN: A SystemPlayer instance and a mocked display
- player = SystemPlayer(self)
- mocked_display = MagicMock()
- mocked_display.size.return_value = [1, 2, 3, 4]
-
- # WHEN: The resize() method is called
- player.resize(mocked_display)
-
- # THEN: The player is resized
- mocked_display.size.assert_called_once_with()
- mocked_display.video_widget.resize.assert_called_once_with([1, 2, 3, 4])
-
- @patch('openlp.core.ui.media.systemplayer.functools')
- def test_play_is_live(self, mocked_functools):
- """
- Test the play() method of the SystemPlayer on the live display
- """
- # GIVEN: A SystemPlayer instance and a mocked display
- mocked_functools.partial.return_value = 'function'
- player = SystemPlayer(self)
- mocked_display = MagicMock()
- mocked_display.controller.is_live = True
- mocked_display.controller.media_info.start_time = 1
- mocked_display.controller.media_info.volume = 1
-
- # WHEN: play() is called
- with patch.object(player, 'get_live_state') as mocked_get_live_state, \
- patch.object(player, 'seek') as mocked_seek, \
- patch.object(player, 'volume') as mocked_volume, \
- patch.object(player, 'set_state') as mocked_set_state, \
- patch.object(player, 'disconnect_slots') as mocked_disconnect_slots:
- mocked_get_live_state.return_value = QtMultimedia.QMediaPlayer.PlayingState
- result = player.play(mocked_display)
-
- # THEN: the media file is played
- mocked_get_live_state.assert_called_once_with()
- mocked_display.media_player.play.assert_called_once_with()
- mocked_seek.assert_called_once_with(mocked_display, 1000)
- mocked_volume.assert_called_once_with(mocked_display, 1)
- mocked_disconnect_slots.assert_called_once_with(mocked_display.media_player.durationChanged)
- mocked_display.media_player.durationChanged.connect.assert_called_once_with('function')
- mocked_set_state.assert_called_once_with(MediaState.Playing, mocked_display)
- mocked_display.video_widget.raise_.assert_called_once_with()
- assert result is True
-
- @patch('openlp.core.ui.media.systemplayer.functools')
- def test_play_is_preview(self, mocked_functools):
- """
- Test the play() method of the SystemPlayer on the preview display
- """
- # GIVEN: A SystemPlayer instance and a mocked display
- mocked_functools.partial.return_value = 'function'
- player = SystemPlayer(self)
- mocked_display = MagicMock()
- mocked_display.controller.is_live = False
- mocked_display.controller.media_info.start_time = 1
- mocked_display.controller.media_info.volume = 1
-
- # WHEN: play() is called
- with patch.object(player, 'get_preview_state') as mocked_get_preview_state, \
- patch.object(player, 'seek') as mocked_seek, \
- patch.object(player, 'volume') as mocked_volume, \
- patch.object(player, 'set_state') as mocked_set_state:
- mocked_get_preview_state.return_value = QtMultimedia.QMediaPlayer.PlayingState
- result = player.play(mocked_display)
-
- # THEN: the media file is played
- mocked_get_preview_state.assert_called_once_with()
- mocked_display.media_player.play.assert_called_once_with()
- mocked_seek.assert_called_once_with(mocked_display, 1000)
- mocked_volume.assert_called_once_with(mocked_display, 1)
- mocked_display.media_player.durationChanged.connect.assert_called_once_with('function')
- mocked_set_state.assert_called_once_with(MediaState.Playing, mocked_display)
- mocked_display.video_widget.raise_.assert_called_once_with()
- assert result is True
-
- def test_pause_is_live(self):
- """
- Test the pause() method of the SystemPlayer on the live display
- """
- # GIVEN: A SystemPlayer instance
- player = SystemPlayer(self)
- mocked_display = MagicMock()
- mocked_display.controller.is_live = True
-
- # WHEN: The pause method is called
- with patch.object(player, 'get_live_state') as mocked_get_live_state, \
- patch.object(player, 'set_state') as mocked_set_state:
- mocked_get_live_state.return_value = QtMultimedia.QMediaPlayer.PausedState
- player.pause(mocked_display)
-
- # THEN: The video is paused
- mocked_display.media_player.pause.assert_called_once_with()
- mocked_get_live_state.assert_called_once_with()
- mocked_set_state.assert_called_once_with(MediaState.Paused, mocked_display)
-
- def test_pause_is_preview(self):
- """
- Test the pause() method of the SystemPlayer on the preview display
- """
- # GIVEN: A SystemPlayer instance
- player = SystemPlayer(self)
- mocked_display = MagicMock()
- mocked_display.controller.is_live = False
-
- # WHEN: The pause method is called
- with patch.object(player, 'get_preview_state') as mocked_get_preview_state, \
- patch.object(player, 'set_state') as mocked_set_state:
- mocked_get_preview_state.return_value = QtMultimedia.QMediaPlayer.PausedState
- player.pause(mocked_display)
-
- # THEN: The video is paused
- mocked_display.media_player.pause.assert_called_once_with()
- mocked_get_preview_state.assert_called_once_with()
- mocked_set_state.assert_called_once_with(MediaState.Paused, mocked_display)
-
- def test_stop(self):
- """
- Test the stop() method of the SystemPlayer
- """
- # GIVEN: A SystemPlayer instance
- player = SystemPlayer(self)
- mocked_display = MagicMock()
-
- # WHEN: The stop method is called
- with patch.object(player, 'set_visible') as mocked_set_visible, \
- patch.object(player, 'set_state') as mocked_set_state:
- player.stop(mocked_display)
-
- # THEN: The video is stopped
- mocked_display.media_player.stop.assert_called_once_with()
- mocked_set_visible.assert_called_once_with(mocked_display, False)
- mocked_set_state.assert_called_once_with(MediaState.Stopped, mocked_display)
-
- def test_volume(self):
- """
- Test the volume() method of the SystemPlayer
- """
- # GIVEN: A SystemPlayer instance
- player = SystemPlayer(self)
- mocked_display = MagicMock()
- mocked_display.has_audio = True
-
- # WHEN: The stop method is called
- player.volume(mocked_display, 2)
-
- # THEN: The video is stopped
- mocked_display.media_player.setVolume.assert_called_once_with(2)
-
- def test_seek(self):
- """
- Test the seek() method of the SystemPlayer
- """
- # GIVEN: A SystemPlayer instance
- player = SystemPlayer(self)
- mocked_display = MagicMock()
-
- # WHEN: The stop method is called
- player.seek(mocked_display, 2)
-
- # THEN: The video is stopped
- mocked_display.media_player.setPosition.assert_called_once_with(2)
-
- def test_reset(self):
- """
- Test the reset() method of the SystemPlayer
- """
- # GIVEN: A SystemPlayer instance
- player = SystemPlayer(self)
- mocked_display = MagicMock()
-
- # WHEN: reset() is called
- with patch.object(player, 'set_state') as mocked_set_state, \
- patch.object(player, 'set_visible') as mocked_set_visible:
- player.reset(mocked_display)
-
- # THEN: The media player is reset
- mocked_display.media_player.stop()
- mocked_display.media_player.setMedia.assert_called_once_with(QtMultimedia.QMediaContent())
- mocked_set_visible.assert_called_once_with(mocked_display, False)
- mocked_display.video_widget.setVisible.assert_called_once_with(False)
- mocked_set_state.assert_called_once_with(MediaState.Off, mocked_display)
-
- def test_set_visible(self):
- """
- Test the set_visible() method on the SystemPlayer
- """
- # GIVEN: A SystemPlayer instance and a mocked display
- player = SystemPlayer(self)
- player.has_own_widget = True
- mocked_display = MagicMock()
-
- # WHEN: set_visible() is called
- player.set_visible(mocked_display, True)
-
- # THEN: The widget should be visible
- mocked_display.video_widget.setVisible.assert_called_once_with(True)
-
- def test_set_duration(self):
- """
- Test the set_duration() method of the SystemPlayer
- """
- # GIVEN: a mocked controller
- mocked_controller = MagicMock()
- mocked_controller.media_info.length = 5
-
- # WHEN: The set_duration() is called. NB: the 10 here is ignored by the code
- SystemPlayer.set_duration(mocked_controller, 10)
-
- # THEN: The maximum length of the slider should be set
- mocked_controller.seek_slider.setMaximum.assert_called_once_with(5)
-
- def test_update_ui(self):
- """
- Test the update_ui() method on the SystemPlayer
- """
- # GIVEN: A SystemPlayer instance
- player = SystemPlayer(self)
- player.state = [MediaState.Playing, MediaState.Playing]
- mocked_display = MagicMock()
- mocked_display.media_player.state.return_value = QtMultimedia.QMediaPlayer.PausedState
- mocked_display.controller.media_info.end_time = 1
- mocked_display.media_player.position.return_value = 2
- mocked_display.controller.seek_slider.isSliderDown.return_value = False
-
- # WHEN: update_ui() is called
- with patch.object(player, 'stop') as mocked_stop, \
- patch.object(player, 'set_visible') as mocked_set_visible:
- player.update_ui(mocked_display)
-
- # THEN: The UI is updated
- expected_stop_calls = [call(mocked_display)]
- expected_position_calls = [call(), call()]
- expected_block_signals_calls = [call(True), call(False)]
- mocked_display.media_player.state.assert_called_once_with()
- assert 1 == mocked_stop.call_count
- assert expected_stop_calls == mocked_stop.call_args_list
- assert 2 == mocked_display.media_player.position.call_count
- assert expected_position_calls == mocked_display.media_player.position.call_args_list
- mocked_set_visible.assert_called_once_with(mocked_display, False)
- mocked_display.controller.seek_slider.isSliderDown.assert_called_once_with()
- assert expected_block_signals_calls == mocked_display.controller.seek_slider.blockSignals.call_args_list
- mocked_display.controller.seek_slider.setSliderPosition.assert_called_once_with(2)
-
- def test_get_media_display_css(self):
- """
- Test the get_media_display_css() method of the SystemPlayer
- """
- # GIVEN: A SystemPlayer instance
- player = SystemPlayer(self)
-
- # WHEN: get_media_display_css() is called
- result = player.get_media_display_css()
-
- # THEN: The css should be empty
- assert '' == result
-
- @patch('openlp.core.ui.media.systemplayer.QtMultimedia.QMediaPlayer')
- def test_get_info(self, MockQMediaPlayer):
- """
- Test the get_info() method of the SystemPlayer
- """
- # GIVEN: A SystemPlayer instance
- mocked_media_player = MagicMock()
- mocked_media_player.supportedMimeTypes.return_value = []
- MockQMediaPlayer.return_value = mocked_media_player
- player = SystemPlayer(self)
-
- # WHEN: get_info() is called
- result = player.get_info()
-
- # THEN: The info should be correct
- expected_info = 'This media player uses your operating system to provide media capabilities.
' \
- 'Audio
[]
Video
[]
'
- assert expected_info == result
-
- @patch('openlp.core.ui.media.systemplayer.CheckMediaWorker')
- @patch('openlp.core.ui.media.systemplayer.run_thread')
- @patch('openlp.core.ui.media.systemplayer.is_thread_finished')
- def test_check_media(self, mocked_is_thread_finished, mocked_run_thread, MockCheckMediaWorker):
- """
- Test the check_media() method of the SystemPlayer
- """
- # GIVEN: A SystemPlayer instance and a mocked thread
- valid_file = '/path/to/video.ogv'
- mocked_application = MagicMock()
- Registry().create()
- Registry().register('application', mocked_application)
- player = SystemPlayer(self)
- mocked_is_thread_finished.side_effect = [False, True]
- mocked_check_media_worker = MagicMock()
- mocked_check_media_worker.result = True
- MockCheckMediaWorker.return_value = mocked_check_media_worker
-
- # WHEN: check_media() is called with a valid media file
- result = player.check_media(valid_file)
-
- # THEN: It should return True
- MockCheckMediaWorker.assert_called_once_with(valid_file)
- mocked_check_media_worker.setVolume.assert_called_once_with(0)
- mocked_run_thread.assert_called_once_with(mocked_check_media_worker, 'check_media')
- mocked_is_thread_finished.assert_called_with('check_media')
- assert mocked_is_thread_finished.call_count == 2, 'is_thread_finished() should have been called twice'
- mocked_application.processEvents.assert_called_once_with()
- assert result is True
-
-
-class TestCheckMediaWorker(TestCase):
- """
- Test the CheckMediaWorker class
- """
- def test_constructor(self):
- """
- Test the constructor of the CheckMediaWorker class
- """
- # GIVEN: A file path
- path = 'file.ogv'
-
- # WHEN: The CheckMediaWorker object is instantiated
- worker = CheckMediaWorker(path)
-
- # THEN: The correct values should be set up
- assert worker is not None
-
- @patch('openlp.core.ui.media.systemplayer.functools.partial')
- @patch('openlp.core.ui.media.systemplayer.QtMultimedia.QMediaContent')
- def test_start(self, MockQMediaContent, mocked_partial):
- """
- Test the start method
- """
- # GIVEN: A CheckMediaWorker instance
- worker = CheckMediaWorker('file.ogv')
- MockQMediaContent.side_effect = lambda x: x
- mocked_partial.side_effect = lambda x, y: y
-
- # WHEN: start() is called
- with patch.object(worker, 'error') as mocked_error, \
- patch.object(worker, 'mediaStatusChanged') as mocked_status_change, \
- patch.object(worker, 'setMedia') as mocked_set_media, \
- patch.object(worker, 'play') as mocked_play:
- worker.start()
-
- # THEN: The correct methods should be called
- mocked_error.connect.assert_called_once_with('error')
- mocked_status_change.connect.assert_called_once_with('media')
- mocked_set_media.assert_called_once_with(QtCore.QUrl('file:file.ogv'))
- mocked_play.assert_called_once_with()
-
- def test_signals_media(self):
- """
- Test the signals() signal of the CheckMediaWorker class with a "media" origin
- """
- # GIVEN: A CheckMediaWorker instance
- worker = CheckMediaWorker('file.ogv')
-
- # WHEN: signals() is called with media and BufferedMedia
- with patch.object(worker, 'stop') as mocked_stop, \
- patch.object(worker, 'quit') as mocked_quit:
- worker.signals('media', worker.BufferedMedia)
-
- # THEN: The worker should exit and the result should be True
- mocked_stop.assert_called_once_with()
- mocked_quit.emit.assert_called_once_with()
- assert worker.result is True
-
- def test_signals_error(self):
- """
- Test the signals() signal of the CheckMediaWorker class with a "error" origin
- """
- # GIVEN: A CheckMediaWorker instance
- worker = CheckMediaWorker('file.ogv')
-
- # WHEN: signals() is called with error and BufferedMedia
- with patch.object(worker, 'stop') as mocked_stop, \
- patch.object(worker, 'quit') as mocked_quit:
- worker.signals('error', None)
-
- # THEN: The worker should exit and the result should be True
- mocked_stop.assert_called_once_with()
- mocked_quit.emit.assert_called_once_with()
- assert worker.result is False
diff --git a/tests/functional/openlp_core/ui/media/test_vlcplayer.py b/tests/functional/openlp_core/ui/media/test_vlcplayer.py
index b9026ffea..1ae05da52 100644
--- a/tests/functional/openlp_core/ui/media/test_vlcplayer.py
+++ b/tests/functional/openlp_core/ui/media/test_vlcplayer.py
@@ -138,25 +138,24 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_vlc.Instance.return_value = mocked_instance
mocked_get_vlc.return_value = mocked_vlc
- mocked_display = MagicMock()
- mocked_display.has_audio = False
- mocked_display.controller.is_live = True
- mocked_display.size.return_value = (10, 10)
+ mocked_output_display = MagicMock()
+ mocked_controller = MagicMock()
+ mocked_controller.is_live = True
+ mocked_output_display.size.return_value = (10, 10)
vlc_player = VlcPlayer(None)
# WHEN: setup() is run
- vlc_player.setup(mocked_display)
+ vlc_player.setup(mocked_output_display, mocked_controller)
# THEN: The VLC widget should be set up correctly
- assert mocked_display.vlc_widget == mocked_qframe
+ assert mocked_output_display.vlc_widget == mocked_qframe
mocked_qframe.setFrameStyle.assert_called_with(1)
mocked_settings.value.assert_called_with('advanced/hide mouse')
- mocked_vlc.Instance.assert_called_with('--no-video-title-show --no-audio --no-video-title-show '
- '--mouse-hide-timeout=0')
- assert mocked_display.vlc_instance == mocked_instance
+ mocked_vlc.Instance.assert_called_with('--no-video-title-show --mouse-hide-timeout=0')
+ assert mocked_output_display.vlc_instance == mocked_instance
mocked_instance.media_player_new.assert_called_with()
- assert mocked_display.vlc_media_player == mocked_media_player_new
- mocked_display.size.assert_called_with()
+ assert mocked_output_display.vlc_media_player == mocked_media_player_new
+ mocked_output_display.size.assert_called_with()
mocked_qframe.resize.assert_called_with((10, 10))
mocked_qframe.raise_.assert_called_with()
mocked_qframe.hide.assert_called_with()
@@ -188,14 +187,14 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_vlc.Instance.return_value = mocked_instance
mocked_get_vlc.return_value = mocked_vlc
- mocked_display = MagicMock()
- mocked_display.has_audio = True
- mocked_display.controller.is_live = True
- mocked_display.size.return_value = (10, 10)
+ mocked_output_display = MagicMock()
+ mocked_controller = MagicMock()
+ mocked_controller.is_live = True
+ mocked_output_display.size.return_value = (10, 10)
vlc_player = VlcPlayer(None)
# WHEN: setup() is run
- vlc_player.setup(mocked_display)
+ vlc_player.setup(mocked_output_display, mocked_controller)
# THEN: The VLC instance should be created with the correct options
mocked_vlc.Instance.assert_called_with('--no-video-title-show --mouse-hide-timeout=0')
@@ -226,17 +225,17 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_vlc.Instance.return_value = mocked_instance
mocked_get_vlc.return_value = mocked_vlc
- mocked_display = MagicMock()
- mocked_display.has_audio = False
- mocked_display.controller.is_live = True
- mocked_display.size.return_value = (10, 10)
+ mocked_output_display = MagicMock()
+ mocked_controller = MagicMock()
+ mocked_controller.is_live = True
+ mocked_output_display.size.return_value = (10, 10)
vlc_player = VlcPlayer(None)
# WHEN: setup() is run
- vlc_player.setup(mocked_display)
+ vlc_player.setup(mocked_output_display, mocked_controller)
# THEN: The VLC instance should be created with the correct options
- mocked_vlc.Instance.assert_called_with('--no-video-title-show --no-audio --no-video-title-show')
+ mocked_vlc.Instance.assert_called_with('--no-video-title-show')
@patch('openlp.core.ui.media.vlcplayer.is_win')
@patch('openlp.core.ui.media.vlcplayer.is_macosx')
@@ -263,14 +262,14 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_vlc.Instance.return_value = mocked_instance
mocked_get_vlc.return_value = mocked_vlc
- mocked_display = MagicMock()
- mocked_display.has_audio = False
- mocked_display.controller.is_live = True
- mocked_display.size.return_value = (10, 10)
+ mocked_output_display = MagicMock()
+ mocked_controller = MagicMock()
+ mocked_controller.is_live = True
+ mocked_output_display.size.return_value = (10, 10)
vlc_player = VlcPlayer(None)
# WHEN: setup() is run
- vlc_player.setup(mocked_display)
+ vlc_player.setup(mocked_output_display, mocked_controller)
# THEN: set_hwnd should be called
mocked_media_player_new.set_hwnd.assert_called_with(2)
@@ -300,14 +299,14 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_vlc.Instance.return_value = mocked_instance
mocked_get_vlc.return_value = mocked_vlc
- mocked_display = MagicMock()
- mocked_display.has_audio = False
- mocked_display.controller.is_live = True
- mocked_display.size.return_value = (10, 10)
+ mocked_output_display = MagicMock()
+ mocked_controller = MagicMock()
+ mocked_controller.is_live = True
+ mocked_output_display.size.return_value = (10, 10)
vlc_player = VlcPlayer(None)
# WHEN: setup() is run
- vlc_player.setup(mocked_display)
+ vlc_player.setup(mocked_output_display, mocked_controller)
# THEN: set_nsobject should be called
mocked_media_player_new.set_nsobject.assert_called_with(2)
@@ -353,15 +352,13 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_normcase.side_effect = lambda x: x
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
- mocked_controller = MagicMock()
- mocked_controller.media_info.volume = 100
- mocked_controller.media_info.media_type = MediaType.Video
- mocked_controller.media_info.file_info.absoluteFilePath.return_value = media_path
+ mocked_display = MagicMock()
+ mocked_display.media_info.volume = 100
+ mocked_display.media_info.media_type = MediaType.Video
+ mocked_display.media_info.file_info.absoluteFilePath.return_value = media_path
mocked_vlc_media = MagicMock()
mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000
- mocked_display = MagicMock()
- mocked_display.controller = mocked_controller
mocked_display.vlc_instance.media_new_path.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media
vlc_player = VlcPlayer(None)
@@ -392,16 +389,13 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_normcase.side_effect = lambda x: x
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
- mocked_controller = MagicMock()
- mocked_controller.media_info.volume = 100
- mocked_controller.media_info.media_type = MediaType.CD
- mocked_controller.media_info.file_info.absoluteFilePath.return_value = media_path
- mocked_controller.media_info.title_track = 1
+ mocked_display = MagicMock()
+ mocked_display.media_info.volume = 100
+ mocked_display.media_info.media_type = MediaType.CD
+ mocked_display.media_info.title_track = 1
mocked_vlc_media = MagicMock()
mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000
- mocked_display = MagicMock()
- mocked_display.controller = mocked_controller
mocked_display.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media
mocked_subitems = MagicMock()
@@ -437,16 +431,14 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_normcase.side_effect = lambda x: x
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
- mocked_controller = MagicMock()
- mocked_controller.media_info.volume = 100
- mocked_controller.media_info.media_type = MediaType.CD
- mocked_controller.media_info.file_info.absoluteFilePath.return_value = media_path
- mocked_controller.media_info.title_track = 1
+ mocked_display = MagicMock()
+ mocked_display.media_info.volume = 100
+ mocked_display.media_info.media_type = MediaType.CD
+ mocked_display.media_info.file_info.absoluteFilePath.return_value = media_path
+ mocked_display.media_info.title_track = 1
mocked_vlc_media = MagicMock()
mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000
- mocked_display = MagicMock()
- mocked_display.controller = mocked_controller
mocked_display.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media
mocked_subitems = MagicMock()
@@ -482,16 +474,14 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_normcase.side_effect = lambda x: x
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
- mocked_controller = MagicMock()
- mocked_controller.media_info.volume = 100
- mocked_controller.media_info.media_type = MediaType.CD
- mocked_controller.media_info.file_info.absoluteFilePath.return_value = media_path
- mocked_controller.media_info.title_track = 1
+ mocked_display = MagicMock()
+ mocked_display.media_info.volume = 100
+ mocked_display.media_info.media_type = MediaType.CD
+ mocked_display.media_info.file_info.absoluteFilePath.return_value = media_path
+ mocked_display.media_info.title_track = 1
mocked_vlc_media = MagicMock()
mocked_media = MagicMock()
mocked_media.get_duration.return_value = 10000
- mocked_display = MagicMock()
- mocked_display.controller = mocked_controller
mocked_display.vlc_instance.media_new_location.return_value = mocked_vlc_media
mocked_display.vlc_media_player.get_media.return_value = mocked_media
mocked_subitems = MagicMock()
@@ -611,29 +601,28 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_threading.Thread.return_value = mocked_thread
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
- mocked_controller = MagicMock()
- mocked_controller.media_info.start_time = 0
- mocked_controller.media_info.media_type = MediaType.Video
- mocked_controller.media_info.volume = 100
+ mocked_display = MagicMock()
mocked_media = MagicMock()
mocked_media.get_duration.return_value = 50000
- mocked_display = MagicMock()
- mocked_display.controller = mocked_controller
- mocked_display.vlc_media_player.get_media.return_value = mocked_media
+ mocked_output_display = MagicMock()
+ mocked_output_display.media_info.start_time = 0
+ mocked_output_display.media_info.media_type = MediaType.Video
+ mocked_output_display.media_info.volume = 100
+ mocked_output_display.vlc_media_player.get_media.return_value = mocked_media
vlc_player = VlcPlayer(None)
- vlc_player.set_state(MediaState.Paused, mocked_display)
+ vlc_player.set_state(MediaState.Paused, mocked_output_display)
# WHEN: play() is called
with patch.object(vlc_player, 'media_state_wait') as mocked_media_state_wait, \
patch.object(vlc_player, 'volume') as mocked_volume:
mocked_media_state_wait.return_value = True
- result = vlc_player.play(mocked_display)
+ result = vlc_player.play(mocked_display, mocked_output_display)
# THEN: A bunch of things should happen to play the media
mocked_thread.start.assert_called_with()
- mocked_volume.assert_called_with(mocked_display, 100)
+ mocked_volume.assert_called_with(mocked_output_display, 100)
assert MediaState.Playing == vlc_player.get_live_state()
- mocked_display.vlc_widget.raise_.assert_called_with()
+ mocked_output_display.vlc_widget.raise_.assert_called_with()
assert result is True, 'The value returned from play() should be True'
@patch('openlp.core.ui.media.vlcplayer.threading')
@@ -649,16 +638,15 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_get_vlc.return_value = mocked_vlc
mocked_controller = MagicMock()
mocked_controller.media_info.start_time = 0
- mocked_display = MagicMock()
- mocked_display.controller = mocked_controller
+ mocked_output_display = MagicMock()
vlc_player = VlcPlayer(None)
- vlc_player.set_state(MediaState.Paused, mocked_display)
+ vlc_player.set_state(MediaState.Paused, mocked_output_display)
# WHEN: play() is called
with patch.object(vlc_player, 'media_state_wait') as mocked_media_state_wait, \
patch.object(vlc_player, 'volume'):
mocked_media_state_wait.return_value = False
- result = vlc_player.play(mocked_display)
+ result = vlc_player.play(mocked_controller, mocked_output_display)
# THEN: A thread should be started, but the method should return False
mocked_thread.start.assert_called_with()
@@ -676,33 +664,32 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_vlc = MagicMock()
mocked_get_vlc.return_value = mocked_vlc
mocked_controller = MagicMock()
- mocked_controller.media_info.start_time = 0
- mocked_controller.media_info.end_time = 50
- mocked_controller.media_info.media_type = MediaType.DVD
- mocked_controller.media_info.volume = 100
- mocked_controller.media_info.title_track = 1
- mocked_controller.media_info.audio_track = 1
- mocked_controller.media_info.subtitle_track = 1
- mocked_display = MagicMock()
- mocked_display.controller = mocked_controller
+ mocked_output_display = MagicMock()
+ mocked_output_display.media_info.start_time = 0
+ mocked_output_display.media_info.end_time = 50
+ mocked_output_display.media_info.media_type = MediaType.DVD
+ mocked_output_display.media_info.volume = 100
+ mocked_output_display.media_info.title_track = 1
+ mocked_output_display.media_info.audio_track = 1
+ mocked_output_display.media_info.subtitle_track = 1
vlc_player = VlcPlayer(None)
- vlc_player.set_state(MediaState.Paused, mocked_display)
+ vlc_player.set_state(MediaState.Paused, mocked_output_display)
# WHEN: play() is called
with patch.object(vlc_player, 'media_state_wait', return_value=True), \
patch.object(vlc_player, 'volume') as mocked_volume, \
patch.object(vlc_player, 'get_live_state', return_value=MediaState.Loaded):
- result = vlc_player.play(mocked_display)
+ result = vlc_player.play(mocked_controller, mocked_output_display)
# THEN: A bunch of things should happen to play the media
mocked_thread.start.assert_called_with()
- mocked_display.vlc_media_player.set_title.assert_called_with(1)
- mocked_display.vlc_media_player.play.assert_called_with()
- mocked_display.vlc_media_player.audio_set_track.assert_called_with(1)
- mocked_display.vlc_media_player.video_set_spu.assert_called_with(1)
- mocked_volume.assert_called_with(mocked_display, 100)
+ mocked_output_display.vlc_media_player.set_title.assert_called_with(1)
+ mocked_output_display.vlc_media_player.play.assert_called_with()
+ mocked_output_display.vlc_media_player.audio_set_track.assert_called_with(1)
+ mocked_output_display.vlc_media_player.video_set_spu.assert_called_with(1)
+ mocked_volume.assert_called_with(mocked_output_display, 100)
assert MediaState.Playing == vlc_player.get_live_state()
- mocked_display.vlc_widget.raise_.assert_called_with()
+ mocked_output_display.vlc_widget.raise_.assert_called_with()
assert result is True, 'The value returned from play() should be True'
@patch('openlp.core.ui.media.vlcplayer.get_vlc')
@@ -937,7 +924,6 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_controller.media_info.end_time = 300
mocked_controller.seek_slider.isSliderDown.return_value = False
mocked_display = MagicMock()
- mocked_display.controller = mocked_controller
mocked_display.vlc_media.get_state.return_value = 1
mocked_display.vlc_media_player.get_time.return_value = 400000
vlc_player = VlcPlayer(None)
@@ -945,7 +931,7 @@ class TestVLCPlayer(TestCase, TestMixin):
# WHEN: update_ui() is called
with patch.object(vlc_player, 'stop') as mocked_stop, \
patch.object(vlc_player, 'set_visible') as mocked_set_visible:
- vlc_player.update_ui(mocked_display)
+ vlc_player.update_ui(mocked_controller, mocked_display)
# THEN: Certain methods should be called
mocked_stop.assert_called_with(mocked_display)
@@ -970,22 +956,19 @@ class TestVLCPlayer(TestCase, TestMixin):
mocked_controller.media_info.end_time = 300
mocked_controller.seek_slider.isSliderDown.return_value = False
mocked_display = MagicMock()
- mocked_display.controller = mocked_controller
mocked_display.vlc_media.get_state.return_value = 1
- mocked_display.vlc_media_player.get_time.return_value = 400
+ mocked_display.vlc_media_player.get_time.return_value = 300
mocked_display.controller.media_info.media_type = MediaType.DVD
vlc_player = VlcPlayer(None)
# WHEN: update_ui() is called
- with patch.object(vlc_player, 'stop') as mocked_stop, \
- patch.object(vlc_player, 'set_visible') as mocked_set_visible:
- vlc_player.update_ui(mocked_display)
+ with patch.object(vlc_player, 'stop') as mocked_stop:
+ vlc_player.update_ui(mocked_controller, mocked_display)
# THEN: Certain methods should be called
mocked_stop.assert_called_with(mocked_display)
- assert 2 == mocked_stop.call_count
+ assert 1 == mocked_stop.call_count
mocked_display.vlc_media_player.get_time.assert_called_with()
- mocked_set_visible.assert_called_with(mocked_display, False)
mocked_controller.seek_slider.setSliderPosition.assert_called_with(300)
expected_calls = [call(True), call(False)]
assert expected_calls == mocked_controller.seek_slider.blockSignals.call_args_list