diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index e7c6c7ddd..62395b4ab 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -66,6 +66,7 @@ body { #image { z-index:2; } +%s #video1 { z-index:3; } @@ -98,97 +99,8 @@ sup { - - - +%s %s
@@ -397,7 +242,7 @@ sup { """ -def build_html(item, screen, alert, islive, background, image=None): +def build_html(item, screen, alert, islive, background, plugins=None, image=None): """ Build the full web paged structure for display @@ -416,6 +261,9 @@ def build_html(item, screen, alert, islive, background, image=None): ``background`` Theme background image - bytes + ``plugins`` + access to the plugins + ``image`` Image media item - bytes """ @@ -434,14 +282,25 @@ def build_html(item, screen, alert, islive, background, image=None): image_src = u'src="data:image/png;base64,%s"' % image else: image_src = u'style="display:none;"' + plugin_css = u'' + plugin_js = u'' + plugin_html = u'' + if plugins: + for plugin in plugins: + plugin_css += plugin.display_css() + plugin_js += plugin.display_javascript() + plugin_html += plugin.display_html() html = HTMLSRC % (build_background_css(item, width, height), width, height, + plugin_css, build_alert_css(alert, width), build_footer_css(item, height), build_lyrics_css(item, webkitvers), u'true' if theme and theme.display_slide_transition and islive \ else u'false', + plugin_js, bgimage_src, image_src, + plugin_html, build_lyrics_html(item, webkitvers)) return html diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index d92464cdc..e81aae46d 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -374,3 +374,21 @@ class Plugin(QtCore.QObject): after this has been set. """ self.textStrings[name] = {u'title': title, u'tooltip': tooltip} + + def display_css(self): + """ + Add css style sheets to htmlbuilder + """ + return u'' + + def display_javascript(self): + """ + Add javascript functions to htmlbuilder + """ + return u'' + + def display_html(self): + """ + Add html code to htmlbuilder + """ + return u'' diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 5987764b6..d054f78bd 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -56,18 +56,22 @@ class Display(QtGui.QGraphicsView): """ Set up and build the preview screen """ +# self.setGeometry(0, 0, +# self.parent().width(), self.parent().height()) self.webView = QtWebKit.QWebView(self) self.webView.setGeometry(0, 0, self.parent().width(), self.parent().height()) - self.webView.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled, True) + self.webView.settings().setAttribute( + QtWebKit.QWebSettings.PluginsEnabled, True) self.page = self.webView.page() self.frame = self.page.mainFrame() screen = {} screen[u'size'] = self.size() serviceItem = ServiceItem() self.webView.setHtml(build_html(serviceItem, screen, - None, None, None)) + None, None, None, self.controller.parent().pluginManager.plugins)) self.webView.hide() + #self.hide() class MainDisplay(QtGui.QGraphicsView): """ @@ -158,7 +162,8 @@ class MainDisplay(QtGui.QGraphicsView): serviceItem = ServiceItem() serviceItem.bg_image_bytes = image_to_byte(self.initialFrame) self.webView.setHtml(build_html(serviceItem, self.screen, - self.alertTab, self.isLive, None)) + self.alertTab, self.isLive, None, + self.controller.parent().pluginManager.plugins)) self.__hideMouse() # To display or not to display? if not self.screen[u'primary']: @@ -350,7 +355,7 @@ class MainDisplay(QtGui.QGraphicsView): else: image_bytes = None html = build_html(self.serviceItem, self.screen, self.alertTab, - self.isLive, background, image_bytes) + self.isLive, background, self.controller.parent().pluginManager.plugins, image_bytes) log.debug(u'buildHtml - pre setHtml') self.webView.setHtml(html) log.debug(u'buildHtml - post setHtml') diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 678f16cf7..e5420f0fe 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -62,7 +62,6 @@ class SlideController(QtGui.QWidget): self.screens = ScreenList.get_instance() self.ratio = float(self.screens.current[u'size'].width()) / \ float(self.screens.current[u'size'].height()) - #self.display = None#MainDisplay(self, self, self.screens, isLive) self.image_manager = self.parent().image_manager self.loopList = [ u'Play Slides Menu', @@ -334,7 +333,7 @@ class SlideController(QtGui.QWidget): def getControlPanel(self): return self.controllerLayout - def sendToPlugins(self, v1=None, v2=None, v3=None, v4=None, v5=None): + def sendToPlugins(self, **kwargs): """ This is the generic function to send signal for control widgets, created from within other plugins @@ -342,7 +341,7 @@ class SlideController(QtGui.QWidget): """ sender = self.sender().objectName() or self.sender().text() controller = self - Receiver.send_message('%s' % sender, [controller, v1, v2, v3, v4, v5]) + Receiver.send_message('%s' % sender, [controller, kwargs]) def setPreviewHotkeys(self, parent=None): self.previousItem.setObjectName(u'previousItemPreview') diff --git a/openlp/plugins/media/lib/__init__.py b/openlp/plugins/media/lib/__init__.py index 8b56a6bc9..1855e4c08 100644 --- a/openlp/plugins/media/lib/__init__.py +++ b/openlp/plugins/media/lib/__init__.py @@ -25,7 +25,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -class MediaAPIs(object): +class MediaAPI(object): """ An enumeration for possible APIs. """ @@ -71,8 +71,10 @@ class MediaAPI(object): Specialiced Media API class to reflect Features of the related API """ - def __init__(self, parent): + def __init__(self, parent, name=u'MediaApi'): self.parent = parent + self.name = name + self.available = self.check_available() self.isActive = False self.canBackground = False self.state = MediaState.Off @@ -80,6 +82,13 @@ class MediaAPI(object): self.audio_extensions_list = [] self.video_extensions_list = [] + def check_available(self): + """ + API is available on this machine + """ + return False + + def setup(self, display): """ Create the related widgets for the current display @@ -164,6 +173,26 @@ class MediaAPI(object): """ pass + def display_css(self): + """ + Add css style sheets to htmlbuilder + """ + return u'' + + + def display_javascript(self): + """ + Add javascript functions to htmlbuilder + """ + return u'' + + + def display_html(self): + """ + Add html code to htmlbuilder + """ + return u'' + from mediaitem import MediaMediaItem from mediatab import MediaTab from mediamanager import MediaManager diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 5aeca1e92..ba6d0b9c6 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -92,7 +92,7 @@ class MediaMediaItem(MediaManagerItem): """ self.resetAction.setVisible(False) Receiver.send_message(u'media_reset', - self.parent.liveController) + self.plugin.liveController) def videobackgroundReplaced(self): """ @@ -112,7 +112,7 @@ class MediaMediaItem(MediaManagerItem): if os.path.exists(filename): (path, name) = os.path.split(filename) Receiver.send_message(u'media_video', - [self.parent.liveController, filename, 0, True]) + [self.plugin.liveController, filename, 0, True]) self.resetAction.setVisible(True) else: critical_error_message_box(UiStrings().LiveBGError, @@ -139,7 +139,7 @@ class MediaMediaItem(MediaManagerItem): ItemCapabilities.AllowsVariableStartTime) service_item.title = unicode(self.plugin.nameStrings[u'singular']) service_item.add_capability(ItemCapabilities.RequiresMedia) - #Receiver.send_message(u'media_video', [self.parent.liveController, filename, False]) + #Receiver.send_message(u'media_video', [self.plugin.liveController, filename, False]) # force a non-existent theme service_item.theme = -1 frame = u':/media/image_clapperboard.png' diff --git a/openlp/plugins/media/lib/mediamanager.py b/openlp/plugins/media/lib/mediamanager.py index 1e9a4c123..3bf4355ae 100644 --- a/openlp/plugins/media/lib/mediamanager.py +++ b/openlp/plugins/media/lib/mediamanager.py @@ -63,13 +63,6 @@ class MediaManager(object): self.APIs = {} self.controller = [] self.curDisplayMediaAPI = {} - #Create API Controllers - if WebkitAPI.is_available(): - self.APIs[u'Webkit'] = WebkitAPI(self) - if PhononAPI.is_available(): - self.APIs[u'Phonon'] = PhononAPI(self) - if VlcAPI.is_available(): - self.APIs[u'Vlc'] = VlcAPI(self) #Timer for video state self.Timer = QtCore.QTimer() self.Timer.setInterval(200) @@ -117,6 +110,33 @@ class MediaManager(object): if not isAnyonePlaying: self.Timer.stop() + def display_css(self): + """ + Add css style sheets to htmlbuilder + """ + css = u''; + for api in self.APIs.values(): + css+= api.display_css() + return css + + def display_javascript(self): + """ + Add javascript functions to htmlbuilder + """ + js = u'' + for api in self.APIs.values(): + js+= api.display_javascript() + return js + + def display_html(self): + """ + Add html code to htmlbuilder + """ + html = u'' + for api in self.APIs.values(): + html+= api.display_html() + return html + def addControllerItems(self, controller, control_panel): self.controller.append(controller) self.setup_generic_controls(controller, control_panel) @@ -133,11 +153,11 @@ class MediaManager(object): controller.sendToPlugins) controller.mediabar.addToolbarButton( u'Media Pause', u':/slides/media_playback_pause.png', - translate('OpenLP.SlideController', 'Start playing media'), + translate('OpenLP.SlideController', 'Pause playing media'), controller.sendToPlugins) controller.mediabar.addToolbarButton( u'Media Stop', u':/slides/media_playback_stop.png', - translate('OpenLP.SlideController', 'Start playing media'), + translate('OpenLP.SlideController', 'Stop playing media'), controller.sendToPlugins) # Build the seekSlider. controller.seekSlider = QtGui.QSlider(QtCore.Qt.Horizontal) diff --git a/openlp/plugins/media/lib/mediatab.py b/openlp/plugins/media/lib/mediatab.py index f0a33130b..97e9c6250 100644 --- a/openlp/plugins/media/lib/mediatab.py +++ b/openlp/plugins/media/lib/mediatab.py @@ -33,23 +33,26 @@ class MediaTab(SettingsTab): """ MediaTab is the Media settings tab in the settings dialog. """ - def __init__(self, parent, title, visible_title, icon_path): + def __init__(self, parent, title, visible_title, apis, icon_path): + self.apis = apis SettingsTab.__init__(self, parent, title, visible_title, icon_path) def setupUi(self): self.setObjectName(u'MediaTab') SettingsTab.setupUi(self) - self.mediaAPIsGroupBox = QtGui.QGroupBox(self.leftColumn) - self.mediaAPIsGroupBox.setObjectName(u'mediaAPIsGroupBox') - self.mediaApiLayout = QtGui.QVBoxLayout(self.mediaAPIsGroupBox) + self.mediaAPIGroupBox = QtGui.QGroupBox(self.leftColumn) + self.mediaAPIGroupBox.setObjectName(u'mediaAPIGroupBox') + self.mediaApiLayout = QtGui.QVBoxLayout(self.mediaAPIGroupBox) self.mediaApiLayout.setObjectName(u'mediaApiLayout') - self.usePhononCheckBox = QtGui.QCheckBox(self.mediaAPIsGroupBox) - self.usePhononCheckBox.setObjectName(u'usePhononCheckBox') - self.mediaApiLayout.addWidget(self.usePhononCheckBox) - self.useVlcCheckBox = QtGui.QCheckBox(self.mediaAPIsGroupBox) - self.useVlcCheckBox.setObjectName(u'useVlcCheckBox') - self.mediaApiLayout.addWidget(self.useVlcCheckBox) - self.leftLayout.addWidget(self.mediaAPIsGroupBox) + self.ApiCheckBoxes = {} + for key in self.apis: + api = self.apis[key] + checkbox = QtGui.QCheckBox(self.mediaAPIGroupBox) + checkbox.setEnabled(api.available) + checkbox.setObjectName(api.name + u'CheckBox') + self.ApiCheckBoxes[api.name] = checkbox + self.mediaApiLayout.addWidget(checkbox) + self.leftLayout.addWidget(self.mediaAPIGroupBox) self.apiOrderGroupBox = QtGui.QGroupBox(self.leftColumn) self.apiOrderGroupBox.setObjectName(u'apiOrderGroupBox') @@ -87,24 +90,30 @@ class MediaTab(SettingsTab): self.leftLayout.addWidget(self.apiOrderGroupBox) self.leftLayout.addStretch() self.rightLayout.addStretch() - QtCore.QObject.connect(self.usePhononCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), - self.onUsePhononCheckBoxChanged) - QtCore.QObject.connect(self.useVlcCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), - self.onUseVlcCheckBoxChanged) + for key in self.apis: + api = self.apis[key] + checkbox = self.ApiCheckBoxes[api.name] + QtCore.QObject.connect(checkbox, + QtCore.SIGNAL(u'stateChanged(int)'), + self.onApiCheckBoxChanged) + QtCore.QObject.connect(self.orderingUpButton, QtCore.SIGNAL(u'pressed()'), self.onOrderingUpButtonPressed) QtCore.QObject.connect(self.orderingDownButton, QtCore.SIGNAL(u'pressed()'), self.onOrderingDownButtonPressed) def retranslateUi(self): - self.mediaAPIsGroupBox.setTitle( + self.mediaAPIGroupBox.setTitle( translate('MediaPlugin.MediaTab', 'Media APIs')) - self.usePhononCheckBox.setText( - translate('MediaPlugin.MediaTab', 'use Phonon')) - self.useVlcCheckBox.setText( - translate('MediaPlugin.MediaTab', 'use Vlc')) + for key in self.apis: + api = self.apis[key] + checkbox = self.ApiCheckBoxes[api.name] + if api.available: + checkbox.setText(api.name) + else: + checkbox.setText( + unicode(translate('MediaPlugin.MediaTab', + '%s (unavailable)')) % api.name) self.apiOrderGroupBox.setTitle( translate('MediaPlugin.MediaTab', 'API Order')) self.orderingDownButton.setText( @@ -112,24 +121,13 @@ class MediaTab(SettingsTab): self.orderingUpButton.setText( translate('MediaPlugin.MediaTab', 'Up')) - def onUsePhononCheckBoxChanged(self, check_state): + def onApiCheckBoxChanged(self, check_state): + api = self.sender().text() if check_state == QtCore.Qt.Checked: - self.usePhonon = True - if u'Phonon' not in self.usedAPIs: - self.usedAPIs.append(u'Phonon') + if api not in self.usedAPIs: + self.usedAPIs.append(api) else: - self.usePhonon = False - self.usedAPIs.takeAt(self.usedAPIs.indexOf(u'Phonon')) - self.updateApiList() - - def onUseVlcCheckBoxChanged(self, check_state): - if check_state == QtCore.Qt.Checked: - self.useVlc = True - if u'Vlc' not in self.usedAPIs: - self.usedAPIs.append(u'Vlc') - else: - self.useVlc = False - self.usedAPIs.takeAt(self.usedAPIs.indexOf(u'Vlc')) + self.usedAPIs.takeAt(self.usedAPIs.indexOf(api)) self.updateApiList() def updateApiList(self): @@ -157,11 +155,11 @@ class MediaTab(SettingsTab): self.usedAPIs = QtCore.QSettings().value( self.settingsSection + u'/apis', QtCore.QVariant(u'Webkit')).toString().split(u',') - self.useWebkit = u'Webkit' in self.usedAPIs - self.usePhonon = u'Phonon' in self.usedAPIs - self.useVlc = u'Vlc' in self.usedAPIs - self.usePhononCheckBox.setChecked(self.usePhonon) - self.useVlcCheckBox.setChecked(self.useVlc) + for key in self.apis: + api = self.apis[key] + checkbox = self.ApiCheckBoxes[api.name] + if api.available and api.name in self.usedAPIs: + checkbox.setChecked(True) self.updateApiList() def save(self): diff --git a/openlp/plugins/media/lib/phononapi.py b/openlp/plugins/media/lib/phononapi.py index 8f1fc8c8c..cc8c70ea3 100644 --- a/openlp/plugins/media/lib/phononapi.py +++ b/openlp/plugins/media/lib/phononapi.py @@ -44,7 +44,7 @@ class PhononAPI(MediaAPI): """ def __init__(self, parent): - MediaAPI.__init__(self, parent) + MediaAPI.__init__(self, parent, u'Phonon') self.parent = parent self.additional_extensions = { u'audio/ac3': [u'.ac3'], @@ -76,7 +76,7 @@ class PhononAPI(MediaAPI): ext = u'*%s' % extension if ext not in list: list.append(ext) - self.parent.parent.serviceManager.supportedSuffixes(extension[1:]) + self.parent.serviceManager.supportedSuffixes(extension[1:]) log.info(u'MediaPlugin: %s extensions: %s' % (mimetype, u' '.join(extensions))) # Add extensions for this mimetype from self.additional_extensions. @@ -87,7 +87,7 @@ class PhononAPI(MediaAPI): ext = u'*%s' % extension if ext not in list: list.append(ext) - self.parent.parent.serviceManager.supportedSuffixes(extension[1:]) + self.parent.serviceManager.supportedSuffixes(extension[1:]) log.info(u'MediaPlugin: %s additional extensions: %s' % (mimetype, u' '.join(self.additional_extensions[mimetype]))) @@ -107,10 +107,7 @@ class PhononAPI(MediaAPI): display.phononWidget.hide() self.hasOwnWidget = True - @staticmethod - def is_available(): -# usePhonon = QtCore.QSettings().value( -# u'media/use phonon', QtCore.QVariant(True)).toBool() + def check_available(self): return True def get_supported_file_types(self): diff --git a/openlp/plugins/media/lib/vlcapi.py b/openlp/plugins/media/lib/vlcapi.py index 7531ba394..94cd067fa 100644 --- a/openlp/plugins/media/lib/vlcapi.py +++ b/openlp/plugins/media/lib/vlcapi.py @@ -30,8 +30,10 @@ import sys, os from datetime import datetime try: import vlc -except: - pass + vlc_available = True +except ImportError: + vlc_available = False + from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver from openlp.plugins.media.lib import MediaAPI, MediaState @@ -44,7 +46,7 @@ class VlcAPI(MediaAPI): to reflect Features of the Vlc API """ def __init__(self, parent): - MediaAPI.__init__(self, parent) + MediaAPI.__init__(self, parent, u'Vlc') self.parent = parent self.video_extensions_list = [ u'*.3gp' @@ -99,13 +101,8 @@ class VlcAPI(MediaAPI): display.vlcMediaPlayer.set_agl(int(display.vlcWidget.winId())) self.hasOwnWidget = True - @staticmethod - def is_available(): - try: - import vlc - return True - except: - return False + def check_available(self): + return vlc_available def get_supported_file_types(self): self.supported_file_types = ['avi'] diff --git a/openlp/plugins/media/lib/webkitapi.py b/openlp/plugins/media/lib/webkitapi.py index 7c2108ea7..ca8d4d1a1 100644 --- a/openlp/plugins/media/lib/webkitapi.py +++ b/openlp/plugins/media/lib/webkitapi.py @@ -41,7 +41,7 @@ class WebkitAPI(MediaAPI): """ def __init__(self, parent): - MediaAPI.__init__(self, parent) + MediaAPI.__init__(self, parent, u'Webkit') self.parent = parent self.canBackground = True self.video_extensions_list = [ @@ -73,12 +73,194 @@ class WebkitAPI(MediaAPI): # no special controls pass + def display_css(self): + """ + Add css style sheets to htmlbuilder + """ + css = u''' + ''' + return css + + + def display_javascript(self): + """ + Add javascript functions to htmlbuilder + """ + js = u''' + var video_timer = null; + var current_video = '1'; + + function show_video(state, path, volume, loop, seekVal){ + // Note, the preferred method for looping would be to use the + // video tag loop attribute. + // But QtWebKit doesn't support this. Neither does it support the + // onended event, hence the setInterval() + // In addition, setting the currentTime attribute to zero to restart + // the video raises an INDEX_SIZE_ERROR: DOM Exception 1 + // To complicate it further, sometimes vid.currentTime stops + // slightly short of vid.duration and vid.ended is intermittent! + // + // Note, currently the background may go black between loops. Not + // desirable. Need to investigate using two