From b7a32ebbb2875064473827fe7aa1d0600cd8819f Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Sat, 30 Apr 2016 11:05:10 +0200 Subject: [PATCH 1/6] Added support for using the new mutool in mudraw mode --- openlp/plugins/media/mediaplugin.py | 1 - .../presentations/lib/pdfcontroller.py | 42 +++++++++++++++---- .../presentations/lib/presentationtab.py | 2 +- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index 1d5529084..e258b5809 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -160,7 +160,6 @@ def process_check_binary(program_path): """ program_type = None 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 48150a9f2..9bfc25eb1 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -77,6 +77,12 @@ class PdfController(PresentationController): if found_mudraw: program_type = 'mudraw' break + found_mutool = re.search('usage: mutool.*', decoded_line, re.IGNORECASE) + if found_mutool: + # Test that mutool contains mudraw + if re.search('draw\s+--\s+convert document.*', runlog.decode(), re.IGNORECASE | re.MULTILINE): + program_type = 'mutool' + break found_gs = re.search('GPL Ghostscript.*', decoded_line, re.IGNORECASE) if found_gs: program_type = 'gs' @@ -101,6 +107,7 @@ class PdfController(PresentationController): """ log.debug('check_installed Pdf') self.mudrawbin = '' + self.mutoolbin = '' self.gsbin = '' self.also_supports = [] # Use the user defined program if given @@ -111,27 +118,36 @@ class PdfController(PresentationController): self.gsbin = pdf_program elif program_type == 'mudraw': self.mudrawbin = pdf_program + elif program_type == 'mutool': + self.mutoolbin = 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 + # for windows we only accept mudraw.exe or mutool.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') + elif os.path.isfile(os.path.join(application_path, 'mutool.exe')): + self.mutoolbin = os.path.join(application_path, 'mutool.exe') else: DEVNULL = open(os.devnull, 'wb') - # First try to find mupdf + # First try to find mudraw self.mudrawbin = which('mudraw') - # if mupdf isn't installed, fallback to ghostscript + # if mudraw isn't installed, try mutool 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: + self.mutoolbin = which('mutool') + # Check we got a working mutool + if not self.mutoolbin or self.process_check_binary(self.mutoolbin) != 'mutool': + self.gsbin = which('gs') + # Last option: check if mudraw or mutool is placed in OpenLP base folder + if not self.mudrawbin and not self.mutoolbin 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: + if os.path.isfile(os.path.join(application_path, 'mudraw.exe')): + self.mudrawbin = os.path.join(application_path, 'mudraw.exe') + elif os.path.isfile(os.path.join(application_path, 'mutool.exe')): + self.mutoolbin = os.path.join(application_path, 'mutool.exe') + if self.mudrawbin or self.mutoolbin: self.also_supports = ['xps', 'oxps'] return True elif self.gsbin: @@ -238,10 +254,18 @@ class PdfDocument(PresentationDocument): if not os.path.isdir(self.get_temp_folder()): os.makedirs(self.get_temp_folder()) if self.controller.mudrawbin: + log.debug('loading presentation using mudraw') runlog = check_output([self.controller.mudrawbin, '-w', str(size.width()), '-h', str(size.height()), '-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path], startupinfo=self.startupinfo) + elif self.controller.mutoolbin: + log.debug('loading presentation using mutool') + runlog = check_output([self.controller.mutoolbin, 'draw', '-w', str(size.width()), '-h', + str(size.height()), + '-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path], + startupinfo=self.startupinfo) elif self.controller.gsbin: + log.debug('loading presentation using gs') resolution = self.gs_get_resolution(size) runlog = check_output([self.controller.gsbin, '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m', '-r' + str(resolution), '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4', diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index cbe881853..8076b33fe 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -235,7 +235,7 @@ class PresentationTab(SettingsTab): self, translate('PresentationPlugin.PresentationTab', 'Select mudraw or ghostscript binary.'), self.pdf_program_path.text()) if filename: - program_type = PdfController.check_binary(filename) + program_type = PdfController.process_check_binary(filename) if not program_type: critical_error_message_box(UiStrings().Error, translate('PresentationPlugin.PresentationTab', From 17fa45b1dd584c06541a79169d7b5cbe05017939 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Wed, 4 May 2016 22:58:44 +0200 Subject: [PATCH 2/6] Added tests. --- .../presentations/test_pdfcontroller.py | 73 ++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py b/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py index 79b907230..f73655dc7 100644 --- a/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py @@ -29,7 +29,7 @@ from tempfile import mkdtemp from PyQt5 import QtCore, QtGui from openlp.plugins.presentations.lib.pdfcontroller import PdfController, PdfDocument -from tests.functional import MagicMock +from tests.functional import MagicMock, patch from openlp.core.common import Settings from openlp.core.lib import ScreenList from tests.utils.constants import TEST_RESOURCES_PATH @@ -137,3 +137,74 @@ class TestPdfController(TestCase, TestMixin): else: self.assertEqual(768, image.height(), 'The height should be 768') self.assertEqual(543, image.width(), 'The width should be 543') + + @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') + def process_check_binary_mudraw_test(self, mocked_check_binary_exists): + """ + Test that the correct output from mudraw is detected + """ + # GIVEN: A mocked check_binary_exists that returns mudraw output + mudraw_output = (b'usage: mudraw [options] input [pages]\n\t-o -\toutput filename (%d for page number)n\t\tsupp' + b'orted formats: pgm, ppm, pam, png, pbmn\t-p -\tpasswordn\t-r -\tresolution in dpi (default: ' + b'72)n\t-w -\twidth (in pixels) (maximum width if -r is specified)n\t-h -\theight (in pixels) ' + b'(maximum height if -r is specified)') + mocked_check_binary_exists.return_value = mudraw_output + + # WHEN: Calling process_check_binary + ret = PdfController.process_check_binary('test') + + # THEN: mudraw should be detected + self.assertEqual('mudraw', ret, 'mudraw should have been detected') + + @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') + def process_check_binary_new_motool_test(self, mocked_check_binary_exists): + """ + Test that the correct output from the new mutool is detected + """ + # GIVEN: A mocked check_binary_exists that returns new mutool output + new_mutool_output = (b'usage: mutool [options]\n\tdraw\t-- convert document\n\trun\t-- run javascript' + b'\n\tclean\t-- rewrite pdf file\n\textract\t-- extract font and image resources\n\tinfo\t' + b'-- show information about pdf resources\n\tpages\t-- show information about pdf pages\n' + b'\tposter\t-- split large page into many tiles\n\tshow\t-- show internal pdf objects\n\t' + b'create\t-- create pdf document\n\tmerge\t-- merge pages from multiple pdf sources into a' + b'new pdf\n') + mocked_check_binary_exists.return_value = new_mutool_output + + # WHEN: Calling process_check_binary + ret = PdfController.process_check_binary('test') + + # THEN: mutool should be detected + self.assertEqual('mutool', ret, 'mutool should have been detected') + + @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') + def process_check_binary_old_motool_test(self, mocked_check_binary_exists): + """ + Test that the output from the old mutool is not accepted + """ + # GIVEN: A mocked check_binary_exists that returns old mutool output + old_mutool_output = (b'usage: mutool [options]\n\tclean\t-- rewrite pdf file\n\textract\t-- extract ' + b'font and image resources\n\tinfo\t-- show information about pdf resources\n\tposter\t-- ' + b'split large page into many tiles\n\tshow\t-- show internal pdf objects') + mocked_check_binary_exists.return_value = old_mutool_output + + # WHEN: Calling process_check_binary + ret = PdfController.process_check_binary('test') + + # THEN: mutool should be detected + self.assertIsNone(ret, 'old mutool should not be accepted!') + + @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') + def process_check_binary_gs_test(self, mocked_check_binary_exists): + """ + Test that the correct output from gs is detected + """ + # GIVEN: A mocked check_binary_exists that returns gs output + gs_output = (b'GPL Ghostscript 9.19 (2016-03-23)\nCopyright (C) 2016 Artifex Software, Inc. All rights reserv' + b'ed.\nUsage: gs [switches] [file1.ps file2.ps ...]') + mocked_check_binary_exists.return_value = gs_output + + # WHEN: Calling process_check_binary + ret = PdfController.process_check_binary('test') + + # THEN: mutool should be detected + self.assertEqual('gs', ret, 'mutool should have been detected') From 907282d3cd5207df0e7ea0f7c6b66417d13f7194 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 5 May 2016 20:14:33 +0200 Subject: [PATCH 3/6] make mudraw/mutool detection work on mac --- openlp/plugins/presentations/lib/pdfcontroller.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py index 9bfc25eb1..cf89d8d32 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -143,10 +143,10 @@ class PdfController(PresentationController): # Last option: check if mudraw or mutool is placed in OpenLP base folder if not self.mudrawbin and not self.mutoolbin and not self.gsbin: 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') - elif os.path.isfile(os.path.join(application_path, 'mutool.exe')): - self.mutoolbin = os.path.join(application_path, 'mutool.exe') + if os.path.isfile(os.path.join(application_path, 'mudraw')): + self.mudrawbin = os.path.join(application_path, 'mudraw') + elif os.path.isfile(os.path.join(application_path, 'mutool')): + self.mutoolbin = os.path.join(application_path, 'mutool') if self.mudrawbin or self.mutoolbin: self.also_supports = ['xps', 'oxps'] return True From 26e72a1fecf1ea0e7ffc35d11bd279eef44109b9 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 5 May 2016 20:17:45 +0200 Subject: [PATCH 4/6] make mediainfo detection work on win and mac. --- openlp/plugins/media/mediaplugin.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index e258b5809..f9874c57b 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -71,8 +71,12 @@ class MediaPlugin(Plugin): :return: true or false """ log.debug('check_installed Mediainfo') - # Use the user defined program if given - return process_check_binary('mediainfo') + # Try to find mediainfo in the path + exists = process_check_binary('mediainfo') + # If mediainfo is not in the path, try to find it in the application folder + if not exists: + exists = process_check_binary(os.path.join(AppLocation.get_directory(AppLocation.AppDir), 'mediainfo')) + return exists def app_startup(self): """ From 7ee0af01b263126fc941d31588a363b58bce48b8 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 5 May 2016 22:30:00 +0200 Subject: [PATCH 5/6] fix traceback if bible list download fails. --- openlp/plugins/bibles/forms/bibleimportform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index 66ba252fc..3289e66e9 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -577,7 +577,7 @@ class BibleImportForm(OpenLPWizard): :param index: The index of the combo box. """ self.web_translation_combo_box.clear() - if self.web_bible_list: + if self.web_bible_list and index in self.web_bible_list: bibles = list(self.web_bible_list[index].keys()) bibles.sort(key=get_locale_key) self.web_translation_combo_box.addItems(bibles) From fa9a29d30301040bb555e07c79fdfe6dc04aeba7 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 6 May 2016 07:33:43 +0200 Subject: [PATCH 6/6] Fix crosswalk bible list download --- openlp/plugins/bibles/lib/http.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 4398688ee..2076bec87 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -520,7 +520,7 @@ class CWExtract(RegistryProperties): returns a list in the form [(biblename, biblekey, language_code)] """ log.debug('CWExtract.get_bibles_from_http') - bible_url = 'http://www.biblestudytools.com/search/bible-search.part/' + bible_url = 'http://www.biblestudytools.com/' soup = get_soup_for_bible_ref(bible_url) if not soup: return None @@ -528,7 +528,7 @@ class CWExtract(RegistryProperties): if not bible_select: log.debug('No select tags found - did site change?') return None - option_tags = bible_select.find_all('option') + option_tags = bible_select.find_all('option', {'class': 'log-translation'}) if not option_tags: log.debug('No option tags found - did site change?') return None