From b8bbb4391c367c8546e156c8f53995a83a84bc94 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 16 Apr 2016 14:51:42 +0100 Subject: [PATCH 1/5] move code from presentations --- openlp/core/common/__init__.py | 32 +++++++++ openlp/plugins/media/mediaplugin.py | 72 ++++++++++++++++++- .../presentations/lib/pdfcontroller.py | 28 ++------ 3 files changed, 109 insertions(+), 23 deletions(-) diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py index b8a1a4d2e..a1ce05abd 100644 --- a/openlp/core/common/__init__.py +++ b/openlp/core/common/__init__.py @@ -24,6 +24,7 @@ The :mod:`common` module contains most of the components and libraries that make OpenLP work. """ import hashlib + import logging import os import re @@ -31,6 +32,7 @@ import sys import traceback from ipaddress import IPv4Address, IPv6Address, AddressValueError from shutil import which +from subprocess import check_output, CalledProcessError, STDOUT from PyQt5 import QtCore, QtGui from PyQt5.QtCore import QCryptographicHash as QHash @@ -247,6 +249,10 @@ from .applocation import AppLocation from .actions import ActionList from .languagemanager import LanguageManager +if is_win(): + from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW + + def add_actions(target, actions): """ @@ -371,3 +377,29 @@ def clean_filename(filename): if not isinstance(filename, str): filename = str(filename, 'utf-8') return INVALID_FILE_CHARS.sub('_', CONTROL_CHARS.sub('', filename)) + + +def check_binary(program_path): + """ + Function that checks whether a binary exists. + + :param program_path:The full path to the binary to check. + :return: program output to be parsed + """ + log.debug('testing program_path: %s', program_path) + try: + # Setup startupinfo options for check_output to avoid console popping up on windows + if is_win(): + startupinfo = STARTUPINFO() + startupinfo.dwFlags |= STARTF_USESHOWWINDOW + else: + startupinfo = None + runlog = check_output([program_path, '--help'], stderr=STDOUT, startupinfo=startupinfo) + except CalledProcessError as e: + runlog = e.output + except Exception: + trace_error_handler(log) + runlog = '' + log.debug('check_output returned: %s' % runlog) + return runlog + diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index daeb4dc2c..73b631831 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -27,7 +27,7 @@ import logging from PyQt5 import QtCore -from openlp.core.common import Settings, translate +from openlp.core.common import Settings, translate, check_binary from openlp.core.lib import Plugin, StringContent, build_icon from openlp.plugins.media.lib import MediaMediaItem, MediaTab @@ -62,6 +62,51 @@ class MediaPlugin(Plugin): """ super().initialise() + def check_pre_conditions(self): + """ + Check it we have a valid environment. + :return: true or false + """ + log.debug('check_installed Pdf') + self.mudrawbin = '' + self.gsbin = '' + self.also_supports = [] + # Use the user defined program if given + if Settings().value('presentations/enable_pdf_program'): + pdf_program = Settings().value('presentations/pdf_program') + program_type = self.check_binary('mediainfo') + if program_type == 'gs': + self.gsbin = pdf_program + elif program_type == 'mudraw': + self.mudrawbin = pdf_program + else: + # Fallback to autodetection + application_path = AppLocation.get_directory(AppLocation.AppDir) + if is_win(): + # for windows we only accept mudraw.exe in the base folder + application_path = AppLocation.get_directory(AppLocation.AppDir) + if os.path.isfile(os.path.join(application_path, 'mudraw.exe')): + self.mudrawbin = os.path.join(application_path, 'mudraw.exe') + else: + DEVNULL = open(os.devnull, 'wb') + # First try to find mupdf + self.mudrawbin = which('mudraw') + # if mupdf isn't installed, fallback to ghostscript + if not self.mudrawbin: + self.gsbin = which('gs') + # Last option: check if mudraw is placed in OpenLP base folder + if not self.mudrawbin and not self.gsbin: + application_path = AppLocation.get_directory(AppLocation.AppDir) + if os.path.isfile(os.path.join(application_path, 'mudraw')): + self.mudrawbin = os.path.join(application_path, 'mudraw') + if self.mudrawbin: + self.also_supports = ['xps', 'oxps'] + return True + elif self.gsbin: + return True + else: + return False + def app_startup(self): """ Override app_startup() in order to do nothing @@ -137,3 +182,28 @@ class MediaPlugin(Plugin): Add html code to htmlbuilder. """ return self.media_controller.get_media_display_html() + + +def process_check_binary(program_path): + """ + Function that checks whether a binary is either ghostscript or mudraw or neither. + Is also used from presentationtab.py + + :param program_path:The full path to the binary to check. + :return: Type of the binary, 'gs' if ghostscript, 'mudraw' if mudraw, None if invalid. + """ + program_type = None + runlog = check_binary(program_path) + # Analyse the output to see it the program is mudraw, ghostscript or neither + for line in runlog.splitlines(): + decoded_line = line.decode() + found_mudraw = re.search('usage: mudraw.*', decoded_line, re.IGNORECASE) + if found_mudraw: + program_type = 'mudraw' + break + found_gs = re.search('GPL Ghostscript.*', decoded_line, re.IGNORECASE) + if found_gs: + program_type = 'gs' + break + log.debug('in check_binary, found: %s', program_type) + return program_type diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py index dbea84327..0ef9cb29b 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -22,13 +22,12 @@ import os import logging -from tempfile import NamedTemporaryFile import re from shutil import which -from subprocess import check_output, CalledProcessError, STDOUT +from subprocess import check_output, CalledProcessError -from openlp.core.common import AppLocation -from openlp.core.common import Settings, is_win, trace_error_handler +from openlp.core.common import AppLocation, check_binary +from openlp.core.common import Settings, is_win from openlp.core.lib import ScreenList from .presentationcontroller import PresentationController, PresentationDocument @@ -61,7 +60,7 @@ class PdfController(PresentationController): self.check_installed() @staticmethod - def check_binary(program_path): + def process_check_binary(program_path): """ Function that checks whether a binary is either ghostscript or mudraw or neither. Is also used from presentationtab.py @@ -70,22 +69,7 @@ class PdfController(PresentationController): :return: Type of the binary, 'gs' if ghostscript, 'mudraw' if mudraw, None if invalid. """ program_type = None - runlog = '' - log.debug('testing program_path: %s', program_path) - try: - # Setup startupinfo options for check_output to avoid console popping up on windows - if is_win(): - startupinfo = STARTUPINFO() - startupinfo.dwFlags |= STARTF_USESHOWWINDOW - else: - startupinfo = None - runlog = check_output([program_path, '--help'], stderr=STDOUT, startupinfo=startupinfo) - except CalledProcessError as e: - runlog = e.output - except Exception: - trace_error_handler(log) - runlog = '' - log.debug('check_output returned: %s' % runlog) + runlog = check_binary(program_path) # Analyse the output to see it the program is mudraw, ghostscript or neither for line in runlog.splitlines(): decoded_line = line.decode() @@ -122,7 +106,7 @@ class PdfController(PresentationController): # Use the user defined program if given if Settings().value('presentations/enable_pdf_program'): pdf_program = Settings().value('presentations/pdf_program') - program_type = self.check_binary(pdf_program) + program_type = self.process_check_binary(pdf_program) if program_type == 'gs': self.gsbin = pdf_program elif program_type == 'mudraw': From 40981701e97cd15818a178cb74d3e4b29777d4b3 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 16 Apr 2016 15:43:31 +0100 Subject: [PATCH 2/5] fix checks --- openlp/core/ui/media/mediacontroller.py | 2 +- openlp/plugins/media/mediaplugin.py | 61 +++++-------------------- 2 files changed, 12 insertions(+), 51 deletions(-) diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index cf116e861..71e0f1903 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -296,7 +296,7 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties): tooltip=translate('OpenLP.SlideController', 'Stop playing media.'), triggers=controller.send_to_plugins) controller.mediabar.add_toolbar_action('playbackLoop', text='media_playback_loop', - icon=':/slides/media_playback_stop.png', checked=False, + icon=':/media/media_repeat.png', checked=False, tooltip=translate('OpenLP.SlideController', 'Loop playing media.'), triggers=controller.send_to_plugins) controller.position_label = QtWidgets.QLabel() diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index 73b631831..4f9c4a0b1 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -24,10 +24,13 @@ The Media plugin """ import logging +import os +import re +from shutil import which from PyQt5 import QtCore -from openlp.core.common import Settings, translate, check_binary +from openlp.core.common import AppLocation, Settings, translate, check_binary, is_win from openlp.core.lib import Plugin, StringContent, build_icon from openlp.plugins.media.lib import MediaMediaItem, MediaTab @@ -67,45 +70,9 @@ class MediaPlugin(Plugin): Check it we have a valid environment. :return: true or false """ - log.debug('check_installed Pdf') - self.mudrawbin = '' - self.gsbin = '' - self.also_supports = [] + log.debug('check_installed Mediainfo') # Use the user defined program if given - if Settings().value('presentations/enable_pdf_program'): - pdf_program = Settings().value('presentations/pdf_program') - program_type = self.check_binary('mediainfo') - if program_type == 'gs': - self.gsbin = pdf_program - elif program_type == 'mudraw': - self.mudrawbin = pdf_program - else: - # Fallback to autodetection - application_path = AppLocation.get_directory(AppLocation.AppDir) - if is_win(): - # for windows we only accept mudraw.exe in the base folder - application_path = AppLocation.get_directory(AppLocation.AppDir) - if os.path.isfile(os.path.join(application_path, 'mudraw.exe')): - self.mudrawbin = os.path.join(application_path, 'mudraw.exe') - else: - DEVNULL = open(os.devnull, 'wb') - # First try to find mupdf - self.mudrawbin = which('mudraw') - # if mupdf isn't installed, fallback to ghostscript - if not self.mudrawbin: - self.gsbin = which('gs') - # Last option: check if mudraw is placed in OpenLP base folder - if not self.mudrawbin and not self.gsbin: - application_path = AppLocation.get_directory(AppLocation.AppDir) - if os.path.isfile(os.path.join(application_path, 'mudraw')): - self.mudrawbin = os.path.join(application_path, 'mudraw') - if self.mudrawbin: - self.also_supports = ['xps', 'oxps'] - return True - elif self.gsbin: - return True - else: - return False + return process_check_binary('mediainfo') def app_startup(self): """ @@ -194,16 +161,10 @@ def process_check_binary(program_path): """ program_type = None runlog = check_binary(program_path) - # Analyse the output to see it the program is mudraw, ghostscript or neither + print(runlog) + # Analyse the output to see it the program is mediainfo for line in runlog.splitlines(): decoded_line = line.decode() - found_mudraw = re.search('usage: mudraw.*', decoded_line, re.IGNORECASE) - if found_mudraw: - program_type = 'mudraw' - break - found_gs = re.search('GPL Ghostscript.*', decoded_line, re.IGNORECASE) - if found_gs: - program_type = 'gs' - break - log.debug('in check_binary, found: %s', program_type) - return program_type + if re.search('MediaInfo Command line', decoded_line, re.IGNORECASE): + return True + return False From f2537981e4e9287fa4e5b5aae3a369060013a019 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 20 Apr 2016 17:36:37 +0100 Subject: [PATCH 3/5] update --- openlp/core/common/__init__.py | 1 - openlp/plugins/media/mediaplugin.py | 5 ++-- .../openlp_plugins/media/test_mediaplugin.py | 24 ++++++++++++++++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py index a1ce05abd..2c32a75d0 100644 --- a/openlp/core/common/__init__.py +++ b/openlp/core/common/__init__.py @@ -253,7 +253,6 @@ if is_win(): from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW - def add_actions(target, actions): """ Adds multiple actions to a menu or toolbar in one command. diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index 4f9c4a0b1..5f3f4f3ef 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -153,11 +153,10 @@ class MediaPlugin(Plugin): def process_check_binary(program_path): """ - Function that checks whether a binary is either ghostscript or mudraw or neither. - Is also used from presentationtab.py + Function that checks whether a binary MediaInfo is present :param program_path:The full path to the binary to check. - :return: Type of the binary, 'gs' if ghostscript, 'mudraw' if mudraw, None if invalid. + :return: If exists or not """ program_type = None runlog = check_binary(program_path) diff --git a/tests/functional/openlp_plugins/media/test_mediaplugin.py b/tests/functional/openlp_plugins/media/test_mediaplugin.py index 1e11de4fa..e7852fb0c 100644 --- a/tests/functional/openlp_plugins/media/test_mediaplugin.py +++ b/tests/functional/openlp_plugins/media/test_mediaplugin.py @@ -25,7 +25,7 @@ Test the media plugin from unittest import TestCase from openlp.core import Registry -from openlp.plugins.media.mediaplugin import MediaPlugin +from openlp.plugins.media.mediaplugin import MediaPlugin, process_check_binary from tests.functional import MagicMock, patch from tests.helpers.testmixin import TestMixin @@ -63,3 +63,25 @@ class MediaPluginTest(TestCase, TestMixin): self.assertIsInstance(MediaPlugin.about(), str) # THEN: about() should return a non-empty string self.assertNotEquals(len(MediaPlugin.about()), 0) + + def process_check_binary_pass_test(self): + """ + Test that the Process check returns true if found + """ + # GIVEN: A media plugin instance + # WHEN: function is called with the correct name + result = process_check_binary("MediaInfo") + + # THEN: The the result should be True + self.assertFalse(result, "Media info should have been found") + + def process_check_binary_fail_test(self): + """ + Test that the Process check returns false if not found + """ + # GIVEN: A media plugin instance + # WHEN: function is called with the wrong name + result = process_check_binary("MediaInfo1") + + # THEN: The the result should be True + self.assertTrue(result, "Media info should not have been found") From bd8ddf75064904c98b1c022559656e4cb4fffd7b Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Thu, 21 Apr 2016 17:26:34 +0100 Subject: [PATCH 4/5] fix tests --- openlp/core/common/__init__.py | 2 +- openlp/plugins/media/mediaplugin.py | 6 +++--- openlp/plugins/presentations/lib/pdfcontroller.py | 4 ++-- .../openlp_plugins/media/test_mediaplugin.py | 14 +++++++++----- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py index 2c32a75d0..2384252fc 100644 --- a/openlp/core/common/__init__.py +++ b/openlp/core/common/__init__.py @@ -378,7 +378,7 @@ def clean_filename(filename): return INVALID_FILE_CHARS.sub('_', CONTROL_CHARS.sub('', filename)) -def check_binary(program_path): +def check_binary_exists(program_path): """ Function that checks whether a binary exists. diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index 5f3f4f3ef..1d5529084 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -30,7 +30,7 @@ from shutil import which from PyQt5 import QtCore -from openlp.core.common import AppLocation, Settings, translate, check_binary, is_win +from openlp.core.common import AppLocation, Settings, translate, check_binary_exists, is_win from openlp.core.lib import Plugin, StringContent, build_icon from openlp.plugins.media.lib import MediaMediaItem, MediaTab @@ -159,8 +159,8 @@ def process_check_binary(program_path): :return: If exists or not """ program_type = None - runlog = check_binary(program_path) - print(runlog) + runlog = check_binary_exists(program_path) + print(runlog, type(runlog)) # Analyse the output to see it the program is mediainfo for line in runlog.splitlines(): decoded_line = line.decode() diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py index 0ef9cb29b..48150a9f2 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -26,7 +26,7 @@ import re from shutil import which from subprocess import check_output, CalledProcessError -from openlp.core.common import AppLocation, check_binary +from openlp.core.common import AppLocation, check_binary_exists from openlp.core.common import Settings, is_win from openlp.core.lib import ScreenList from .presentationcontroller import PresentationController, PresentationDocument @@ -69,7 +69,7 @@ class PdfController(PresentationController): :return: Type of the binary, 'gs' if ghostscript, 'mudraw' if mudraw, None if invalid. """ program_type = None - runlog = check_binary(program_path) + runlog = check_binary_exists(program_path) # Analyse the output to see it the program is mudraw, ghostscript or neither for line in runlog.splitlines(): decoded_line = line.decode() diff --git a/tests/functional/openlp_plugins/media/test_mediaplugin.py b/tests/functional/openlp_plugins/media/test_mediaplugin.py index e7852fb0c..c49cdbaa4 100644 --- a/tests/functional/openlp_plugins/media/test_mediaplugin.py +++ b/tests/functional/openlp_plugins/media/test_mediaplugin.py @@ -64,24 +64,28 @@ class MediaPluginTest(TestCase, TestMixin): # THEN: about() should return a non-empty string self.assertNotEquals(len(MediaPlugin.about()), 0) - def process_check_binary_pass_test(self): + @patch('openlp.plugins.media.mediaplugin.check_binary_exists') + def process_check_binary_pass_test(self, mocked_checked_binary_exists): """ Test that the Process check returns true if found """ # GIVEN: A media plugin instance # WHEN: function is called with the correct name - result = process_check_binary("MediaInfo") + mocked_checked_binary_exists.return_value = str.encode('MediaInfo Command line') + result = process_check_binary('MediaInfo') # THEN: The the result should be True - self.assertFalse(result, "Media info should have been found") + self.assertTrue(result, 'Mediainfo should have been found') - def process_check_binary_fail_test(self): + @patch('openlp.plugins.media.mediaplugin.check_binary_exists') + def process_check_binary_fail_test(self, mocked_checked_binary_exists): """ Test that the Process check returns false if not found """ # GIVEN: A media plugin instance # WHEN: function is called with the wrong name + mocked_checked_binary_exists.return_value = str.encode('MediaInfo1 Command line') result = process_check_binary("MediaInfo1") # THEN: The the result should be True - self.assertTrue(result, "Media info should not have been found") + self.assertFalse(result, "Mediainfo should not have been found") From 20acc909515dd101ecafa14a17c42863c888b8d2 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Fri, 22 Apr 2016 17:37:21 +0100 Subject: [PATCH 5/5] Pep8 --- openlp/core/common/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py index 2384252fc..f3076a86f 100644 --- a/openlp/core/common/__init__.py +++ b/openlp/core/common/__init__.py @@ -401,4 +401,3 @@ def check_binary_exists(program_path): runlog = '' log.debug('check_output returned: %s' % runlog) return runlog -