Display more detailed instructions when VLC and pymediainfo are missing

- On Fedora, mention the need for RPMFusion
- on macOS, reference the VLC website
- On other systems, just display a generic message
- Don't try to load the VLC path on macOS
This commit is contained in:
Raoul Snyman 2019-12-07 11:41:30 +00:00 committed by Tim Bentley
parent ddc53eccb3
commit d5fc4c5b88
3 changed files with 149 additions and 21 deletions

View File

@ -385,17 +385,12 @@ def main():
application.setApplicationName('OpenLP')
set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
# Set the libvlc environment variable if we're frozen
if getattr(sys, 'frozen', False):
if is_macosx():
vlc_lib = 'libvlc.dylib'
elif is_win():
vlc_lib = 'libvlc.dll'
# Path to libvlc
os.environ['PYTHON_VLC_LIB_PATH'] = str(AppLocation.get_directory(AppLocation.AppDir) / 'vlc' / vlc_lib)
log.debug('VLC Path: {}'.format(os.environ['PYTHON_VLC_LIB_PATH']))
# Path to VLC directory containing VLC's "plugins" directory
if getattr(sys, 'frozen', False) and is_win():
# Path to libvlc and the plugins
os.environ['PYTHON_VLC_LIB_PATH'] = str(AppLocation.get_directory(AppLocation.AppDir) / 'vlc' / 'libvlc.dll')
os.environ['PYTHON_VLC_MODULE_PATH'] = str(AppLocation.get_directory(AppLocation.AppDir) / 'vlc')
log.debug('VLC Path: {}'.format(os.environ['PYTHON_VLC_LIB_PATH']))
log.debug('VLC Plugins Path: {}'.format(os.environ['PYTHON_VLC_MODULE_PATH']))
# Initialise the Registry
Registry.create()
Registry().register('application', application)

View File

@ -34,6 +34,7 @@ from PyQt5 import QtCore
from openlp.core.state import State
from openlp.core.api.http import register_endpoint
from openlp.core.common import is_linux, is_macosx
from openlp.core.common.i18n import translate
from openlp.core.common.mixins import LogMixin, RegistryProperties
from openlp.core.common.registry import Registry, RegistryBase
@ -89,23 +90,35 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
self.vlc_player = VlcPlayer(self)
State().add_service('mediacontroller', 0)
State().add_service('media_live', 0)
getvlc = get_vlc()
if getvlc and pymediainfo_available:
has_vlc = get_vlc()
if has_vlc and pymediainfo_available:
State().update_pre_conditions('mediacontroller', True)
State().update_pre_conditions('media_live', True)
else:
if hasattr(self.main_window, 'splash') and self.main_window.splash.isVisible():
self.main_window.splash.hide()
text_vlc = translate('OpenLP.MediaController',
'The media integration library is missing (python - vlc is not installed)')
text_info = translate('OpenLP.MediaController',
'The media integration library is missing (python - pymediainfo is not installed)')
if not getvlc and not pymediainfo_available:
State().missing_text('media_live', "{text}\n{base}".format(text=text_vlc, base=text_info))
if getvlc and not pymediainfo_available:
State().missing_text('media_live', "{text}".format(text=text_info))
if not getvlc and pymediainfo_available:
State().missing_text('media_live', "{text}".format(text=text_vlc))
generic_message = translate('OpenLP.MediaController',
'OpenLP requires the following libraries in order to show videos and other '
'media, but they are not installed. Please install these libraries to enable '
'media playback in OpenLP.')
fedora_rpmfusion = translate('OpenLP.MediaController',
'To install these libraries, you will need to enable the RPMFusion '
'repository: https://rpmfusion.org/')
message = ''
if is_macosx():
message = translate('OpenLP.MediaController',
'macOS is missing VLC. Please download and install from the VLC web site: '
'https://www.videolan.org/vlc/')
else:
packages = []
if not has_vlc:
packages.append('python3-vlc')
if not pymediainfo_available:
packages.append('python3-pymediainfo')
message = generic_message + '\n\n' + ', '.join(packages)
if not has_vlc and is_linux(distro='fedora'):
message += '\n\n' + fedora_rpmfusion
State().missing_text('media_live', message)
return True
def bootstrap_post_set_up(self):

View File

@ -25,6 +25,7 @@ from unittest import TestCase
from unittest.mock import MagicMock, patch
from openlp.core.common.registry import Registry
from openlp.core.ui import DisplayControllerType
from openlp.core.ui.media.mediacontroller import MediaController
from openlp.core.ui.media import ItemMediaInfo
from tests.helpers.testmixin import TestMixin
@ -202,3 +203,122 @@ class TestMediaController(TestCase, TestMixin):
# THEN you can determine the run time
assert results == test_data[1], 'The correct duration is returned for ' + test_data[0]
def test_on_media_play(self):
"""
Test the on_media_play method
"""
# GIVEN: A mocked live controller and a mocked media_play() method
mocked_live_controller = MagicMock()
Registry().register('live_controller', mocked_live_controller)
media_controller = MediaController()
media_controller.media_play = MagicMock()
# WHEN: the on_media_play() method is called
media_controller.on_media_play()
# The mocked live controller should be called
media_controller.media_play.assert_called_once_with(mocked_live_controller, False)
def test_on_media_pause(self):
"""
Test the on_media_pause method
"""
# GIVEN: A mocked live controller and a mocked media_pause() method
mocked_live_controller = MagicMock()
Registry().register('live_controller', mocked_live_controller)
media_controller = MediaController()
media_controller.media_pause = MagicMock()
# WHEN: the on_media_pause() method is called
media_controller.on_media_pause()
# The mocked live controller should be called
media_controller.media_pause.assert_called_once_with(mocked_live_controller)
def test_on_media_stop(self):
"""
Test the on_media_stop method
"""
# GIVEN: A mocked live controller and a mocked media_stop() method
mocked_live_controller = MagicMock()
Registry().register('live_controller', mocked_live_controller)
media_controller = MediaController()
media_controller.media_stop = MagicMock()
# WHEN: the on_media_stop() method is called
media_controller.on_media_stop()
# The mocked live controller should be called
media_controller.media_stop.assert_called_once_with(mocked_live_controller)
def test_display_controllers_live(self):
"""
Test that the display_controllers() method returns the live controller when requested
"""
# GIVEN: A mocked live controller
media_controller = MediaController()
mocked_live_controller = MagicMock()
mocked_preview_controller = MagicMock()
Registry().register('live_controller', mocked_live_controller)
Registry().register('preview_controller', mocked_preview_controller)
# WHEN: display_controllers() is called with DisplayControllerType.Live
controller = media_controller.display_controllers(DisplayControllerType.Live)
# THEN: the controller should be the live controller
assert controller is mocked_live_controller
def test_display_controllers_preview(self):
"""
Test that the display_controllers() method returns the preview controller when requested
"""
# GIVEN: A mocked live controller
media_controller = MediaController()
mocked_live_controller = MagicMock()
mocked_preview_controller = MagicMock()
Registry().register('live_controller', mocked_live_controller)
Registry().register('preview_controller', mocked_preview_controller)
# WHEN: display_controllers() is called with DisplayControllerType.Preview
controller = media_controller.display_controllers(DisplayControllerType.Preview)
# THEN: the controller should be the live controller
assert controller is mocked_preview_controller
def test_set_controls_visible(self):
"""
Test that "set_controls_visible" sets the media controls on the controller to be visible or not
"""
# GIVEN: A mocked controller
mocked_controller = MagicMock()
# WHEN: Set to visible
MediaController.set_controls_visible(mocked_controller, True)
# THEN: The media controls should have been set to visible
mocked_controller.mediabar.setVisible.assert_called_once_with(True)
@patch('openlp.core.ui.media.mediacontroller.ItemMediaInfo')
def test_setup_display(self, MockItemMediaInfo):
"""
Test that the display/controllers are set up correctly
"""
# GIVEN: A media controller object and some mocks
mocked_media_info = MagicMock()
MockItemMediaInfo.return_value = mocked_media_info
media_controller = MediaController()
media_controller.vlc_player = MagicMock()
mocked_display = MagicMock()
media_controller._define_display = MagicMock(return_value=mocked_display)
media_controller.vlc_player = MagicMock()
controller = MagicMock()
# WHEN: setup_display() is called
media_controller.setup_display(controller, True)
# THEN: The right calls should have been made
assert controller.media_info == mocked_media_info
assert controller.has_audio is False
media_controller._define_display.assert_called_once_with(controller)
media_controller.vlc_player.setup(controller, mocked_display, False)