From 942fe8a1413c43a1ac79d773bbb73e93fe75880a Mon Sep 17 00:00:00 2001 From: "rimach crichter@web.de" Date: Tue, 19 Apr 2011 14:03:36 +0200 Subject: [PATCH] further changes --- openlp/core/ui/maindisplay.py | 130 ------------------ openlp/core/ui/slidecontroller.py | 7 - openlp/plugins/media/lib/__init__.py | 26 ++-- openlp/plugins/media/lib/mediacontroller.py | 137 +++++++++++-------- openlp/plugins/media/lib/mediaitem.py | 4 +- openlp/plugins/media/lib/phononcontroller.py | 31 +++-- openlp/plugins/media/lib/vlccontroller.py | 12 +- openlp/plugins/media/lib/webkitcontroller.py | 12 +- 8 files changed, 140 insertions(+), 219 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 63e1c8282..36372c17c 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -99,25 +99,6 @@ class MainDisplay(DisplayWidget): self.screen = self.screens.current self.setVisible(False) self.setGeometry(self.screen[u'size']) -# self.videoWidget = Phonon.VideoWidget(self) -# self.videoWidget.setVisible(False) -# self.videoWidget.setGeometry(QtCore.QRect(0, 0, -# self.screen[u'size'].width(), self.screen[u'size'].height())) -# log.debug(u'Setup Phonon for monitor %s' % self.screens.monitor_number) -# self.mediaObject = Phonon.MediaObject(self) -# self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject) -# Phonon.createPath(self.mediaObject, self.videoWidget) -# Phonon.createPath(self.mediaObject, self.audio) -# QtCore.QObject.connect(self.mediaObject, -# QtCore.SIGNAL(u'stateChanged(Phonon::State, Phonon::State)'), -# self.videoState) -# QtCore.QObject.connect(self.mediaObject, -# QtCore.SIGNAL(u'finished()'), -# self.videoFinished) -# QtCore.QObject.connect(self.mediaObject, -# QtCore.SIGNAL(u'tick(qint64)'), -# self.videoTick) - log.debug(u'Setup webView for monitor %s' % self.screens.monitor_number) self.webView = QtWebKit.QWebView(self) self.webView.setGeometry(0, 0, @@ -179,13 +160,6 @@ class MainDisplay(DisplayWidget): log.debug( u'Finished setup for monitor %s' % self.screens.monitor_number) - def videoHelper(self, newState, oldState): - """ - Start the video at a predetermined point. - """ - if type(newState) == Phonon.State: - print "Phonon State alt:%d, neu:%d" % (oldState, newState) - def text(self, slide): """ Add the slide text from slideController @@ -292,107 +266,6 @@ class MainDisplay(DisplayWidget): if self.isLive: Receiver.send_message(u'maindisplay_active') -# def resetVideo(self): -# """ -# Used after Video plugin has changed the background -# """ -# log.debug(u'resetVideo') -# if self.phononActive: -# self.mediaObject.stop() -# self.mediaObject.clearQueue() -# self.webView.setVisible(True) -# self.videoWidget.setVisible(False) -# self.phononActive = False -# else: -# self.frame.evaluateJavaScript(u'show_video("close");') -# self.override = {} -# # Update the preview frame. -# if self.isLive: -# Receiver.send_message(u'maindisplay_active') -# -# def videoPlay(self): -# """ -# Responds to the request to play a loaded video -# """ -# log.debug(u'videoPlay') -# self.frame.evaluateJavaScript(u'show_flash("play","");') -# self.frame.evaluateJavaScript(u'show_video("stop");') -# return -# if self.phononActive: -# self.mediaObject.play() -# else: -# self.frame.evaluateJavaScript(u'show_video("play");') -# # show screen -# if self.isLive: -# self.setVisible(True) -# -# def videoPause(self): -# """ -# Responds to the request to pause a loaded video -# """ -# log.debug(u'videoPause') -# if self.phononActive: -# self.mediaObject.pause() -# else: -# self.frame.evaluateJavaScript(u'show_video("pause");') -# -# def videoStop(self): -# """ -# Responds to the request to stop a loaded video -# """ -# log.debug(u'videoStop') -# if self.phononActive: -# self.mediaObject.stop() -# else: -# self.frame.evaluateJavaScript(u'show_video("stop");') -# -# def videoVolume(self, volume): -# """ -# Changes the volume of a running video -# """ -# log.debug(u'videoVolume %d' % volume) -# vol = float(volume) / float(10) -# if self.phononActive: -# self.audio.setVolume(vol) -# else: -# self.frame.evaluateJavaScript(u'show_video(null, null, %s);' % -# str(vol)) -# -# def video(self, videoPath, volume, isBackground=False): -# """ -# Loads and starts a video to run with the option of sound -# """ -# log.debug(u'video') -# Receiver.send_message(u'media_video', [self, videoPath, volume, isBackground]) -# return self.preview() -# -# def videoState(self, newState, oldState): -# """ -# Start the video at a predetermined point. -# """ -# if newState == Phonon.PlayingState \ -# and oldState != Phonon.PausedState \ -# and self.serviceItem.start_time > 0: -# # set start time in milliseconds -# self.mediaObject.seek(self.serviceItem.start_time * 1000) -# -# def videoFinished(self): -# """ -# Blank the Video when it has finished so the final frame is not left -# hanging -# """ -# self.videoStop() -# self.hideDisplay(HideMode.Blank) -# self.phononActive = False -# self.videoHide = True -# -# def videoTick(self, tick): -# """ -# Triggered on video tick every 200 milli seconds -# """ -# if tick > self.serviceItem.end_time * 1000: -# self.videoFinished() -# def isWebLoaded(self): """ Called by webView event to show display is fully loaded @@ -503,8 +376,6 @@ class MainDisplay(DisplayWidget): Store the images so they can be replaced when required """ log.debug(u'hideDisplay mode = %d', mode) -# if self.phononActive: -# self.videoPause() Receiver.send_message(u'media_pause', self) if mode == HideMode.Screen: self.frame.evaluateJavaScript(u'show_blank("desktop");') @@ -532,7 +403,6 @@ class MainDisplay(DisplayWidget): self.setVisible(True) if self.phononActive: self.webView.setVisible(False) - #self.videoPlay() Receiver.send_message(u'media_play', self) self.hideMode = None # Trigger actions when display is active again diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 1984cecc9..90f9f07ee 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -1034,7 +1034,6 @@ class SlideController(QtGui.QWidget): log.debug(u'SlideController onMediaStart') file = os.path.join(item.get_frame_path(), item.get_frame_title()) if self.isLive: - #self.display.video(file, self.volume) Receiver.send_message(u'media_video', [self.display, file, self.volume, False]) self.volumeSlider.setValue(self.volume) else: @@ -1051,7 +1050,6 @@ class SlideController(QtGui.QWidget): """ log.debug(u'SlideController mediaSeek') self.seekPos = self.seekSlider.value() - #self.display.videoVolume(self.volume) Receiver.send_message(u'media_seek', [self.display, self.seekPos]) def mediaVolume(self): @@ -1060,7 +1058,6 @@ class SlideController(QtGui.QWidget): """ log.debug(u'SlideController mediaVolume') self.volume = self.volumeSlider.value() - #self.display.videoVolume(self.volume) Receiver.send_message(u'media_volume', [self.display, self.volume]) @@ -1070,7 +1067,6 @@ class SlideController(QtGui.QWidget): """ log.debug(u'SlideController onMediaPause') if self.isLive: - #self.display.videoPause() Receiver.send_message(u'media_pause', self.display) else: self.mediaObject.pause() @@ -1082,7 +1078,6 @@ class SlideController(QtGui.QWidget): log.debug(u'SlideController onMediaPlay') if self.isLive: Receiver.send_message(u'media_play', self.display) - #self.display.videoPlay() else: self.slidePreview.hide() self.video.show() @@ -1094,7 +1089,6 @@ class SlideController(QtGui.QWidget): """ log.debug(u'SlideController onMediaStop') if self.isLive: - #self.display.videoStop() Receiver.send_message(u'media_stop', self.display) else: self.mediaObject.stop() @@ -1108,7 +1102,6 @@ class SlideController(QtGui.QWidget): """ log.debug(u'SlideController onMediaClose') if self.isLive: - #self.display.resetVideo() Receiver.send_message(u'media_reset', self.display) else: self.mediaObject.stop() diff --git a/openlp/plugins/media/lib/__init__.py b/openlp/plugins/media/lib/__init__.py index 3a2385ded..5e078763d 100644 --- a/openlp/plugins/media/lib/__init__.py +++ b/openlp/plugins/media/lib/__init__.py @@ -24,8 +24,6 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore - class MediaBackends(object): """ An enumeration for possible Backends. @@ -34,16 +32,25 @@ class MediaBackends(object): Phonon = 1 Vlc = 2 +class MediaStates(object): + """ + An enumeratioin for possible States of the Media Player + (copied from Phonon::State + """ + LoadingState = 0 + StoppedState = 1 + PlayingState = 2 + PausedState = 4 + OffState = 6 + class MediaController(object): """ + Specialiced MediaController class + to reflect Features of the related backend """ def __init__(self, parent): self.parent = parent - self.state = 0 - self.Timer = QtCore.QTimer() - QtCore.QObject.connect(self.Timer, - QtCore.SIGNAL("timeout()"), self.updatePlayer) - + self.state = MediaStates.OffState def load(self, display, path, volume): pass @@ -63,7 +70,10 @@ class MediaController(object): def reset(self, display): pass - def updatePlayer(self): + def updateUI(self, display): + pass + + def getSupportedFileTypes(self): pass from mediaitem import MediaMediaItem diff --git a/openlp/plugins/media/lib/mediacontroller.py b/openlp/plugins/media/lib/mediacontroller.py index 7595a80b3..31d9f37cf 100644 --- a/openlp/plugins/media/lib/mediacontroller.py +++ b/openlp/plugins/media/lib/mediacontroller.py @@ -35,7 +35,7 @@ from PyQt4 import QtCore, QtGui from PyQt4.phonon import Phonon from openlp.core.lib import Receiver -from openlp.plugins.media.lib import MediaBackends +from openlp.plugins.media.lib import MediaBackends, MediaStates from webkitcontroller import WebkitController from phononcontroller import PhononController @@ -43,6 +43,45 @@ log = logging.getLogger(__name__) class MediaManager(object): """ + The implementation of a Media Manager + The idea is to separate the media related implementation into the plugin files + and unify the access from other parts of code + The media manager adds an own class for every type of backend + Currently these are QtWebkit, Phonon and planed Vlc. + On the other hand currently the previewController display only use phonon for media output. + So I would suggest to rename the maindisplay.py to display.py and modify the code, + so that the display class can be used for the maindisplay as well as for the previewController display. + + Workflow idea: + - OpenLP is starting + - Live display and preview display are call setup + - Live display and preview display send signal with a pointer to their own to the media controller ('media_set_display') + - media controller register all available displays and create for each display all types of media backends (see setDisplay) + - in the OpenLP configuration dialog the user no longe will decide between using Webkit OR Phonon. + - instead of this there is a list widget with all available backends and the user can switch off/on the backends + and change the priority order + (this is necessary, because of not all backends can play all media files and text over video is currently only with QtWebkit possible) + - later on, if the user add a new media service item the signal ('media_video') will be send + - as a result of this the media manager checks which controller is needed for this filetyp + and assign the related backend controller to the right display + - Now all related media stuff (play, pause, ...) will be routed to the related backend controller and there processed + - if one or more medias loaded a generic 200ms Timer will be started peridiodically to refresh the UI + - Signal ('media_reset') will close the related video and disconnect the backend from the display + + Advantages: + - clean and easy interface from other parts of code (slidecontroller and display classes) + - more and better configuration possibilities inside the special backend controllers + - same handling for preview and live display (or later on other additionally displays with their slide controllers) + + Disadvantages: + - because of there will be display widgets created outside of the maindisplay.py file it is more complicate to read the code + - some more signals are send arround the system + + Notices: + - the flash support uses the flash plugin from Mozilla. So there is a js-check that this plugin is installed. + - maybe there would be the installed flashplugin of the IE possible could also used, but I'm not sure about this? + - I would suggest to not hide the main toolbar in case of media, instead of this the media toolbar should be + visible as second toolbar (so the screen can be blanked also during a running video, ...) """ def __init__(self, parent): self.parent = parent @@ -56,6 +95,11 @@ class MediaManager(object): self.displayPhononController = PhononController(self) #self.displayVlcController = VlcController(self) + self.Timer = QtCore.QTimer() + self.Timer.setInterval(200) + + QtCore.QObject.connect(self.Timer, + QtCore.SIGNAL("timeout()"), self.videoState) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_set_display'), self.setDisplay) QtCore.QObject.connect(Receiver.get_receiver(), @@ -73,9 +117,23 @@ class MediaManager(object): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_reset'), self.videoReset) + def videoState(self): + """ + check if there is an assigned media backend and do some + updating stuff (e.g. update the UI) + """ + isAnyonePlaying = False + if len(self.curDisplayMediaController.keys()) == 0: + self.Timer.stop() + else: + for display in self.curDisplayMediaController.keys(): + self.curDisplayMediaController[display].updateUI(display) + if self.curDisplayMediaController[display].state == MediaStates.PlayingState: + isAnyonePlaying = True + if not isAnyonePlaying: + self.Timer.stop() def setDisplay(self, display): - print display #self.setupVlcController(display) self.setupPhononController(display) self.setupWebkitController(display) @@ -95,18 +153,6 @@ class MediaManager(object): Phonon.createPath(display.mediaObject, display.phononWidget) Phonon.createPath(display.mediaObject, display.audio) display.phononWidget.raise_() - QtCore.QObject.connect(display.mediaObject, - QtCore.SIGNAL(u'stateChanged(Phonon::State, Phonon::State)'), - display.videoHelper) -# display.mediaObject.stateChanged.connect(self.videoState) -# QtCore.QObject.connect(display.mediaObject, -# QtCore.SIGNAL(u'finished()'), -# self.videoFinished) -# QtCore.QObject.connect(display.mediaObject, -# QtCore.SIGNAL(u'tick(qint64)'), -# self.videoTick) - - #self.displayPhononController[display] = display.mediaObject def setupVlcController(self, display): display.vlcWidget = QtGui.QWidget(display) @@ -128,7 +174,6 @@ class MediaManager(object): display.vlcWidget.setGeometry(QtCore.QRect(0, 0, display.screen[u'size'].width(), display.screen[u'size'].height())) display.vlcWidget.raise_() - #self.displayVlcController[display] = player def video(self, msg): """ @@ -146,46 +191,30 @@ class MediaManager(object): display.override[u'theme'] = u'' display.override[u'video'] = True vol = float(volume) / float(10) + self.checkFileType(display, videoPath, isBackground) + self.curDisplayMediaController[display].load(display, videoPath, volume) + if display.isLive: + Receiver.send_message(u'maindisplay_active') + + def checkFileType(self, display, videoPath, isBackground): + """ + Used to choose the right media backend type + from the prioritized backend list + """ usePhonon = QtCore.QSettings().value( u'media/use phonon', QtCore.QVariant(True)).toBool() - if usePhonon: + if usePhonon and not isBackground: self.curDisplayMediaController[display] = self.displayPhononController display.phononWidget.setVisible(True) display.webView.setVisible(False) - else: self.curDisplayMediaController[display] = self.displayWebkitController display.phononWidget.setVisible(False) display.webView.setVisible(True) + if len(self.curDisplayMediaController) > 0: + if not self.Timer.isActive(): + self.Timer.start() - self.curDisplayMediaController[display].load(display, videoPath, volume) - if display.isLive: - Receiver.send_message(u'maindisplay_active') - return - if isBackground or not display.usePhonon: - if videoPath.endswith(u'.swf'): - js = u'show_flash("load","%s");' % \ - (videoPath.replace(u'\\', u'\\\\')) - else: - js = u'show_video("init", "%s", %s, true); show_video("play");' % \ - (videoPath.replace(u'\\', u'\\\\'), str(vol)) - display.frame.evaluateJavaScript(js) - else: - display.phononActive = True - display.mediaObject.stop() - display.mediaObject.clearQueue() - display.mediaObject.setCurrentSource(Phonon.MediaSource(videoPath)) - # Need the timer to trigger set the trigger to 200ms - # Value taken from web documentation. - if display.serviceItem.end_time != 0: - display.mediaObject.setTickInterval(200) - display.mediaObject.play() - display.webView.setVisible(False) - display.phononWidget.setVisible(True) - display.audio.setVolume(vol) - # Update the preview frame. - if display.isLive: - Receiver.send_message(u'maindisplay_active') def resetVideo(self): """ @@ -200,6 +229,7 @@ class MediaManager(object): display.phononActive = False else: display.frame.evaluateJavaScript(u'show_video("close");') + display.frame.evaluateJavaScript(u'show_flash("close");') display.override = {} # Update the preview frame. if display.isLive: @@ -213,6 +243,8 @@ class MediaManager(object): self.curDisplayMediaController[display].play(display) # show screen if display.isLive: + if not self.Timer.isActive(): + self.Timer.start() display.setVisible(True) def videoPause(self, display): @@ -229,10 +261,8 @@ class MediaManager(object): Responds to the request to stop a loaded video """ log.debug(u'videoStop') - print type(display) if type(display) is types.ListType: return - print display, self.curDisplayMediaController if display in self.curDisplayMediaController: self.curDisplayMediaController[display].stop(display) if display.isLive: @@ -253,17 +283,6 @@ class MediaManager(object): display.frame.evaluateJavaScript(u'show_video(null, null, %s);' % str(vol)) - def videoState(self, newState, oldState): - """ - Start the video at a predetermined point. - """ - print "display", self.sender() -# if newState == Phonon.PlayingState \ -# and oldState != Phonon.PausedState \ -# and self.serviceItem.start_time > 0: -# # set start time in milliseconds -# self.mediaObject.seek(self.serviceItem.start_time * 1000) - def videoFinished(self): """ Blank the Video when it has finished so the final frame is not left @@ -296,5 +315,7 @@ class MediaManager(object): Responds to the request to reset a loaded video """ log.debug(u'videoReset') + print "videoReset" if display in self.curDisplayMediaController: self.curDisplayMediaController[display].reset(display) + self.curDisplayMediaController[display] diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index f1bd0aea4..46b39ac32 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -89,7 +89,9 @@ class MediaMediaItem(MediaManagerItem): Called to reset the Live backgound with the media selected, """ self.resetAction.setVisible(False) - self.parent.liveController.display.resetVideo() + #self.parent.liveController.display.resetVideo() + Receiver.send_message(u'media_reset', + self.parent.liveController.display) def videobackgroundReplaced(self): """ diff --git a/openlp/plugins/media/lib/phononcontroller.py b/openlp/plugins/media/lib/phononcontroller.py index 40bbb275a..1e78b005f 100644 --- a/openlp/plugins/media/lib/phononcontroller.py +++ b/openlp/plugins/media/lib/phononcontroller.py @@ -27,10 +27,12 @@ from PyQt4.phonon import Phonon -from openlp.plugins.media.lib import MediaController +from openlp.plugins.media.lib import MediaController, MediaStates class PhononController(MediaController): """ + Specialiced MediaController class + to reflect Features of the Phonon backend """ def __init__(self, parent): self.parent = parent @@ -48,20 +50,20 @@ class PhononController(MediaController): display.mediaObject.setTickInterval(200) display.mediaObject.play() display.audio.setVolume(vol) - self.Timer.setInterval(200) + self.state = MediaStates.PlayingState def play(self, display): display.mediaObject.play() - display.parent.seekSlider.setMaximum(display.mediaObject.totalTime()) + self.state = MediaStates.PlayingState def pause(self, display): display.mediaObject.pause() - self.Timer.stop() + self.state = MediaStates.PausedState def stop(self, display): display.mediaObject.stop() - self.Timer.stop() + self.state = MediaStates.StoppedState def seek(self, display, seekVal): print "seek" @@ -73,9 +75,18 @@ class PhononController(MediaController): display.webView.setVisible(True) display.phononWidget.setVisible(False) display.phononActive = False - self.Timer.stop() - def updatePlayer(self): - for controller in self.parent.curDisplayMediaController: - if controller.getState() == 1: - pass + def updateUI(self, display): + display.parent.seekSlider.setMaximum(display.mediaObject.totalTime()) + if not display.parent.seekSlider.isSliderDown(): + display.parent.seekSlider.setSliderPosition(display.mediaObject.currentTime()) +# if newState == Phonon.PlayingState \ +# and oldState != Phonon.PausedState \ +# and self.serviceItem.start_time > 0: +# # set start time in milliseconds +# self.mediaObject.seek(self.serviceItem.start_time * 1000) + + pass + + def getSupportedFileTypes(self): + pass diff --git a/openlp/plugins/media/lib/vlccontroller.py b/openlp/plugins/media/lib/vlccontroller.py index a6c132ebb..5bbb438d4 100644 --- a/openlp/plugins/media/lib/vlccontroller.py +++ b/openlp/plugins/media/lib/vlccontroller.py @@ -27,8 +27,10 @@ from openlp.plugins.media.lib import MediaController -class WebkitController(MediaController): +class VlcController(MediaController): """ + Specialiced MediaController class + to reflect Features of the Vlc backend """ def __init__(self): pass @@ -45,5 +47,11 @@ class WebkitController(MediaController): def stop(self): pass - def seek(self): + def seek(self, display, seekVal): + pass + + def updateUI(self): + pass + + def getSupportedFileTypes(self): pass diff --git a/openlp/plugins/media/lib/webkitcontroller.py b/openlp/plugins/media/lib/webkitcontroller.py index b8b7f8e45..962440a20 100644 --- a/openlp/plugins/media/lib/webkitcontroller.py +++ b/openlp/plugins/media/lib/webkitcontroller.py @@ -29,6 +29,8 @@ from openlp.plugins.media.lib import MediaController class WebkitController(MediaController): """ + Specialiced MediaController class + to reflect Features of the QtWebkit backend """ def __init__(self, parent): self.parent = parent @@ -52,9 +54,7 @@ class WebkitController(MediaController): def play(self, display): if self.isFlash: display.frame.evaluateJavaScript(u'show_flash("play","");') -# display.frame.evaluateJavaScript(u'show_video("stop");') else: -# display.frame.evaluateJavaScript(u'show_flash("stop","");') display.frame.evaluateJavaScript(u'show_video("play");') @@ -70,8 +70,14 @@ class WebkitController(MediaController): else: display.frame.evaluateJavaScript(u'show_video("stop");') - def seek(self, display): + def seek(self, display, seekVal): pass def reset(self, display): display.frame.evaluateJavaScript(u'show_video("close");') + + def updateUI(self, display): + pass + + def getSupportedFileTypes(self): + pass