This commit is contained in:
rimach crichter@web.de 2011-06-05 23:10:49 +02:00
parent 4ab7f93044
commit dbce448da1
15 changed files with 1143 additions and 941 deletions

View File

@ -183,7 +183,8 @@ sup {
case 'currentTime':
return vid.currentTime;
case 'seek':
vid.currentTime = seekVal;
// doesnt work curently
//vid.currentTime = seekVal;
break;
}
}
@ -327,20 +328,22 @@ sup {
}
}
function show_flash(state, path){
// http://www.adobe.com/support/flash/publishexport/scriptingwithflash/scriptingwithflash_03.html
function show_flash(state, path, volume, seekVal){
var text = document.getElementById('flash');
var flashMovie = getFlashMovieObject("OpenLPFlashMovie");
var src = "src = 'file:///" + path + "'";
var view_parm = " wmode='opaque'" +
" width='" + window.innerWidth + "'" +
" height='" + window.innerHeight + "'";
var swf_parm = " autostart='false' loop='false' play='false'" +
" hidden='false' swliveconnect='true'" +
" name='OpenLPFlashMovie'>";
var swf_parm = " name='OpenLPFlashMovie'" +
" autostart='true' loop='false' play='true'" +
" hidden='false' swliveconnect='true' allowscriptaccess='always'" +
" volume='" + volume + "'";
switch(state){
case 'load':
text.innerHTML = "<embed " + src + view_parm + swf_parm + ">";
text.innerHTML = "<embed " + src + view_parm + swf_parm + "/>";
flashMovie = getFlashMovieObject("OpenLPFlashMovie");
text.style.visibility = 'visible';
flashMovie.Play();
@ -349,28 +352,29 @@ sup {
text.style.visibility = 'visible';
flashMovie.Play();
break;
case 'rewind':
ret = 'rewind';
alert(' Wert: ' + flashMovie.TGetProperty("/", 4));
// flashMovie.TotalFrames()
// PercentLoaded()
// GotoFrame()
break;
case 'pause':
flashMovie.StopPlay();
text.style.visibility = 'hidden';
break;
case 'stop':
flashMovie.StopPlay();
// flashMovie.GotoFrame(0);
text.style.visibility = 'hidden';
tempHtml = text.innerHTML;
text.innerHTML = '';
text.innerHTML = tempHtml;
break;
case 'close':
flashMovie.StopPlay();
text.style.visibility = 'hidden';
break;
text.innerHTML = '';
break;
break;
case 'length':
return flashMovie.TotalFrames();
case 'currentTime':
return flashMovie.CurrentFrame();
case 'seek':
// flashMovie.GotoFrame(seekVal);
break;
}
}

View File

@ -244,6 +244,12 @@ class Plugin(QtCore.QObject):
"""
pass
def addControllerItems(self, controller, control_panel):
"""
Create items for all controller Panes
"""
pass
def getSettingsTab(self, parent):
"""
Create a tab for the settings window to display the configurable

View File

@ -187,6 +187,11 @@ class PluginManager(object):
if plugin.status is not PluginStatus.Disabled:
plugin.addToolsMenuItem(tools_menu)
def hook_controller_items(self, controller, control_panel):
for plugin in self.plugins:
if plugin.status is not PluginStatus.Disabled:
plugin.addControllerItems(controller, control_panel)
def initialise_plugins(self):
"""
Loop through all the plugins and give them an opportunity to

View File

@ -580,6 +580,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.pluginManager.hook_export_menu(self.FileExportMenu)
# Call the hook method to pull in tools menus.
self.pluginManager.hook_tools_menu(self.ToolsMenu)
# Call the hook method to pull in plugin Controller items
self.pluginManager.hook_controller_items(
self.previewController, self.previewController.getControlPanel())
self.pluginManager.hook_controller_items(
self.liveController, self.liveController.getControlPanel())
# Call the initialise method to setup plugins.
log.info(u'initialise plugins')
self.pluginManager.initialise_plugins()

View File

@ -73,7 +73,6 @@ class SlideController(QtGui.QWidget):
self.songEditList = [
u'Edit Song',
]
self.volume = 10
self.timer_id = 0
self.songEdit = False
self.selectedRow = 0
@ -224,20 +223,6 @@ class SlideController(QtGui.QWidget):
'Edit and reload song preview'),
self.onEditSong)
self.controllerLayout.addWidget(self.toolbar)
# Build a Media ToolBar
self.mediabar = OpenLPToolbar(self)
self.mediabar.addToolbarButton(
u'Media Start', u':/slides/media_playback_start.png',
translate('OpenLP.SlideController', 'Start playing media'),
self.onMediaPlay)
self.mediabar.addToolbarButton(
u'Media Pause', u':/slides/media_playback_pause.png',
translate('OpenLP.SlideController', 'Start playing media'),
self.onMediaPause)
self.mediabar.addToolbarButton(
u'Media Stop', u':/slides/media_playback_stop.png',
translate('OpenLP.SlideController', 'Start playing media'),
self.onMediaStop)
if self.isLive:
# Build the Song Toolbar
self.songMenu = QtGui.QToolButton(self.toolbar)
@ -247,22 +232,6 @@ class SlideController(QtGui.QWidget):
self.songMenu.setMenu(QtGui.QMenu(
translate('OpenLP.SlideController', 'Go To'), self.toolbar))
self.toolbar.makeWidgetsInvisible([u'Song Menu'])
# Build the seekSlider.
self.seekSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
self.seekSlider.setMaximum(1000)
# Build the volumeSlider.
self.volumeSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
self.volumeSlider.setTickInterval(1)
self.volumeSlider.setTickPosition(QtGui.QSlider.TicksAbove)
self.volumeSlider.setMinimum(0)
self.volumeSlider.setMaximum(10)
self.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
self.seekSlider.setObjectName(u'seekSlider')
self.mediabar.addToolbarWidget(u'Seek Slider', self.seekSlider)
self.volumeSlider.setGeometry(QtCore.QRect(90, 160, 221, 24))
self.volumeSlider.setObjectName(u'volumeSlider')
self.mediabar.addToolbarWidget(u'Audio Volume', self.volumeSlider)
self.controllerLayout.addWidget(self.mediabar)
# Screen preview area
self.previewFrame = QtGui.QFrame(self.splitter)
self.previewFrame.setGeometry(QtCore.QRect(0, 0, 300, 300 * self.ratio))
@ -302,10 +271,6 @@ class SlideController(QtGui.QWidget):
# Signals
QtCore.QObject.connect(self.previewListWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
QtCore.QObject.connect(self.seekSlider,
QtCore.SIGNAL(u'sliderMoved(int)'), self.mediaSeek)
QtCore.QObject.connect(self.volumeSlider,
QtCore.SIGNAL(u'sliderMoved(int)'), self.mediaVolume)
if self.isLive:
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_active'), self.updatePreview)
@ -319,7 +284,6 @@ class SlideController(QtGui.QWidget):
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
self.onGoLiveClick)
self.toolbar.makeWidgetsInvisible(self.songEditList)
self.mediabar.setVisible(False)
if self.isLive:
self.setLiveHotkeys(self)
self.__addActionsToWidget(self.previewListWidget)
@ -366,6 +330,19 @@ class SlideController(QtGui.QWidget):
QtCore.SIGNAL(u'slidecontroller_%s_text_request' % self.typePrefix),
self.onTextRequest)
def getControlPanel(self):
return self.controllerLayout
def sendToPlugins(self, v1=None, v2=None, v3=None, v4=None, v5=None):
"""
This is the generic function to send signal for control widgets,
created from within other plugins
This function is needed to catch the current controller
"""
sender = self.sender().objectName() or self.sender().text()
controller = self
Receiver.send_message('%s' % sender, [controller, v1, v2, v3, v4, v5])
def setPreviewHotkeys(self, parent=None):
self.previousItem.setObjectName(u'previousItemPreview')
self.nextItem.setObjectName(u'nextItemPreview')
@ -523,14 +500,9 @@ class SlideController(QtGui.QWidget):
Allows the Preview toolbar to be customised
"""
self.toolbar.setVisible(True)
self.mediabar.setVisible(False)
self.toolbar.makeWidgetsInvisible(self.songEditList)
if item.is_capable(ItemCapabilities.AllowsEdit) and item.from_plugin:
self.toolbar.makeWidgetsVisible(self.songEditList)
elif item.is_media():
#self.toolbar.setVisible(False)
self.mediabar.setVisible(True)
# self.volumeSlider.setAudioOutput(self.audio)
def refreshServiceItem(self):
"""
@ -1089,58 +1061,15 @@ class SlideController(QtGui.QWidget):
"""
log.debug(u'SlideController onMediaStart')
file = os.path.join(item.get_frame_path(), item.get_frame_title())
Receiver.send_message(u'media_video', [self, file, self.volume, False])
self.volumeSlider.setValue(self.volume)
Receiver.send_message(u'media_video', [self, file, False])
self.slidePreview.hide()
def mediaSeek(self):
"""
Respond to the release of Seek Slider
"""
log.debug(u'SlideController mediaSeek')
self.seekPos = self.seekSlider.value()
Receiver.send_message(u'media_seek', [self, self.seekPos])
def mediaVolume(self):
"""
Respond to the release of Volume Slider
"""
log.debug(u'SlideController mediaVolume')
self.volume = self.volumeSlider.value()
Receiver.send_message(u'media_volume', [self, self.volume])
def onMediaPause(self):
"""
Respond to the Pause from the media Toolbar
"""
log.debug(u'SlideController onMediaPause')
Receiver.send_message(u'media_pause', self)
def onMediaPlay(self):
"""
Respond to the Play from the media Toolbar
"""
log.debug(u'SlideController onMediaPlay')
Receiver.send_message(u'media_play', self)
self.slidePreview.hide()
def onMediaStop(self):
"""
Respond to the Stop from the media Toolbar
"""
log.debug(u'SlideController onMediaStop')
Receiver.send_message(u'media_stop', self)
self.slidePreview.clear()
self.slidePreview.show()
def onMediaClose(self):
"""
Respond to a request to close the Video
"""
log.debug(u'SlideController onMediaClose')
Receiver.send_message(u'media_reset', self)
self.slidePreview.clear()
self.slidePreview.show()
def _resetBlank(self):

View File

@ -24,9 +24,9 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
class MediaBackends(object):
class MediaAPIs(object):
"""
An enumeration for possible Backends.
An enumeration for possible APIs.
"""
Webkit = 0
Phonon = 1
@ -43,10 +43,32 @@ class MediaState(object):
Paused = 4
Off = 6
class MediaController(object):
class MediaType(object):
"""
Specialiced MediaController class
to reflect Features of the related backend
"""
Audio = 0
Video = 1
Cd = 3
Dvd = 4
class MediaInfo(object):
"""
This class hold the media related infos
"""
file_info = None
volume = 100
isFlash = False
is_background = False
length = 0
start_time = 0
end_time = 0
media_type = MediaType()
class MediaAPI(object):
"""
Specialiced Media API class
to reflect Features of the related API
"""
def __init__(self, parent):
self.parent = parent
@ -57,19 +79,19 @@ class MediaController(object):
self.audio_extensions_list = []
self.video_extensions_list = []
def setup(self, display, hasAudio):
def setup(self, display):
"""
Create the related widgets for the current display
"""
pass
def load(self, display, path, volume, isBackground):
def load(self, display):
"""
Load a new media file and check if it is valid
"""
return True
def resize(self, display, controller):
def resize(self, display):
"""
If the main display size or position is changed,
the media widgets should also resized
@ -118,7 +140,7 @@ class MediaController(object):
"""
pass
def update_ui(self, controller, display):
def update_ui(self, display):
"""
Do some ui related stuff
(e.g. update the seek slider)
@ -128,7 +150,7 @@ class MediaController(object):
@staticmethod
def is_available():
"""
Check availability of the related backend
Check availability of the related API
"""
return False
@ -143,6 +165,6 @@ class MediaController(object):
from mediaitem import MediaMediaItem
from mediatab import MediaTab
from mediacontroller import MediaManager
from mediamanager import MediaManager
__all__ = ['MediaMediaItem']

View File

@ -1,356 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import sys, os
from PyQt4 import QtCore, QtGui, QtWebKit
from openlp.core.lib import Receiver, translate
from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.plugins.media.lib import MediaBackends, MediaState
from webkitcontroller import WebkitController
from phononcontroller import PhononController
from vlccontroller import VlcController
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.
"""
def __init__(self, parent):
self.parent = parent
self.backends = {}
self.curDisplayMediaController = {}
#Create Backend Controllers
if WebkitController.is_available():
self.backends[u'Webkit'] = WebkitController(self)
if PhononController.is_available():
self.backends[u'Phonon'] = PhononController(self)
if VlcController.is_available():
self.backends[u'Vlc'] = VlcController(self)
#Timer for video state
self.Timer = QtCore.QTimer()
self.Timer.setInterval(200)
self.withLivePreview = False
#Signals
QtCore.QObject.connect(self.Timer,
QtCore.SIGNAL("timeout()"), self.video_state)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'setup_display'), self.setup_display)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_video'), self.video)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_play'), self.video_play)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_pause'), self.video_pause)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_stop'), self.video_stop)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_seek'), self.video_seek)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_volume'), self.video_volume)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_reset'), self.video_reset)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_hide'), self.video_hide)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_blank'), self.video_blank)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_unblank'), self.video_unblank)
def video_state(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():
if display == self.parent.previewController.previewDisplay or \
display == self.parent.previewController.display:
self.curDisplayMediaController[display] \
.update_ui(self.parent.previewController, display)
else:
self.curDisplayMediaController[display] \
.update_ui(self.parent.liveController, display)
if self.curDisplayMediaController[display] \
.state == MediaState.Playing:
isAnyonePlaying = True
if not isAnyonePlaying:
self.Timer.stop()
def setup_display(self, display):
"""
After a new display is configured, all media related widget
will be created too
"""
hasAudio = True
if not self.withLivePreview and \
display == self.parent.liveController.previewDisplay:
return
if display == self.parent.previewController.previewDisplay or \
display == self.parent.liveController.previewDisplay:
hasAudio = False
for backend in self.backends.values():
backend.setup(display, hasAudio)
def resize(self, controller):
"""
After Mainwindow changes or Splitter moved all related media
widgets have to be resized
"""
for display in self.curDisplayMediaController.keys():
if display == self.parent.previewController.previewDisplay or \
display == self.parent.liveController.previewDisplay:
display.resize(display.parent.slidePreview.size())
self.curDisplayMediaController[display].resize(display, controller)
def video(self, msg):
"""
Loads and starts a video to run with the option of sound
"""
controller = msg[0]
videoPath = os.path.abspath(msg[1])
volume = msg[2]
isBackground = msg[3]
log.debug(u'video')
vol = float(volume) / float(10)
isValid = False
#stop running videos
self.video_reset(controller)
if controller.isLive:
if self.withLivePreview:
display = controller.previewDisplay
if self.check_file_type(display, videoPath, False):
#check size of all media_widgets
self.resize(controller)
self.curDisplayMediaController[display] \
.load(display, videoPath, volume, isBackground)
display = controller.display
if self.check_file_type(display, videoPath, isBackground):
#check size of all media_widgets
self.resize(controller)
isValid = self.curDisplayMediaController[display] \
.load(display, videoPath, volume, isBackground)
else:
display = controller.previewDisplay
if self.check_file_type(display, videoPath, isBackground):
#check size of all media_widgets
self.resize(controller)
isValid = self.curDisplayMediaController[display] \
.load(display, videoPath, volume, isBackground)
if not isValid:
#Media could not be loaded correctly
critical_error_message_box(
translate('MediaPlugin.MediaItem', 'Unsupported File'),
unicode(translate('MediaPlugin.MediaItem',
'Unsupported File')))
return
# controller.display.webLoaded = True
#now start playing
self.video_play(controller)
def check_file_type(self, display, videoPath, isBackground):
"""
Used to choose the right media backend type
from the prioritized backend list
"""
usedBackends = QtCore.QSettings().value(u'media/backends',
QtCore.QVariant(u'Webkit')).toString().split(u',')
media_path = QtCore.QFileInfo(videoPath)
if media_path.isFile():
suffix = u'*.%s' % media_path.suffix()
for title in usedBackends:
backend = self.backends[str(title)]
if suffix in backend.video_extensions_list:
if isBackground:
if backend.canBackground:
self.curDisplayMediaController[display] = backend
return True
else:
self.curDisplayMediaController[display] = backend
return True
return False
# # Special FileType Check
# if videoPath.endswith(u'.swf') or isBackground:
# self.curDisplayMediaController[display] = self.backends[u'Webkit']
# else:
# # search extension in available backends
# # currently only use the first available backend
# self.curDisplayMediaController[display] = self.backends[str(usedBackends[0])]
# return True
def video_play(self, controller):
"""
Responds to the request to play a loaded video
"""
log.debug(u'video_play')
for display in self.curDisplayMediaController.keys():
if display.parent == controller:
self.curDisplayMediaController[display].play(display)
# show screen
if not self.Timer.isActive():
self.Timer.start()
def video_pause(self, controller):
"""
Responds to the request to pause a loaded video
"""
log.debug(u'videoPause')
for display in self.curDisplayMediaController.keys():
if display.parent == controller:
self.curDisplayMediaController[display].pause(display)
def video_stop(self, controller):
"""
Responds to the request to stop a loaded video
"""
log.debug(u'video_stop')
for display in self.curDisplayMediaController.keys():
if display.parent == controller:
self.curDisplayMediaController[display].stop(display)
self.curDisplayMediaController[display].set_visible(display, False)
def video_volume(self, msg):
"""
Changes the volume of a running video
"""
controller = msg[0]
volume = msg[1]
log.debug(u'video_volume %d' % volume)
vol = float(volume) / float(10)
for display in self.curDisplayMediaController.keys():
if display.parent == controller:
self.curDisplayMediaController[display].volume(display, vol)
def video_finished(self):
"""
Blank the Video when it has finished so the final frame is not left
hanging
"""
display.videoStop()
display.hideDisplay(HideMode.Blank)
display.videoHide = True
def video_tick(self, tick):
"""
Triggered on video tick every 200 milli seconds
"""
if tick > display.serviceItem.end_time * 1000:
display.videoFinished()
def video_seek(self, msg):
"""
Responds to the request to change the seek Slider of a loaded video
"""
log.debug(u'video_seek')
controller = msg[0]
seekVal = msg[1]
for display in self.curDisplayMediaController.keys():
if display.parent == controller:
self.curDisplayMediaController[display].seek(display, seekVal)
def video_reset(self, controller):
"""
Responds to the request to reset a loaded video
"""
log.debug(u'video_reset')
for display in self.curDisplayMediaController.keys():
if display.parent == controller:
self.curDisplayMediaController[display].reset(display)
del self.curDisplayMediaController[display]
def video_hide(self, msg):
"""
Hide the related video Widget
"""
isLive = msg[1]
if isLive:
controller = self.parent.liveController
for display in self.curDisplayMediaController.keys():
if display.parent == controller:
if self.curDisplayMediaController[display] \
.state == MediaState.Playing:
self.curDisplayMediaController[display].pause(display)
self.curDisplayMediaController[display] \
.set_visible(display, False)
def video_blank(self, msg):
"""
Blank the related video Widget
"""
isLive = msg[1]
if isLive:
controller = self.parent.liveController
for display in self.curDisplayMediaController.keys():
if display.parent == controller:
if self.curDisplayMediaController[display] \
.state == MediaState.Playing:
self.curDisplayMediaController[display].pause(display)
self.curDisplayMediaController[display] \
.set_visible(display, False)
def video_unblank(self, msg):
"""
Unblank the related video Widget
"""
Receiver.send_message(u'maindisplay_show')
isLive = msg[1]
if isLive:
controller = self.parent.liveController
for display in self.curDisplayMediaController.keys():
if display.parent == controller:
if self.curDisplayMediaController[display] \
.state == MediaState.Paused:
self.curDisplayMediaController[display].play(display)
self.curDisplayMediaController[display] \
.set_visible(display, True)
def get_audio_extensions_list(self):
audio_list = []
for backend in self.backends.values():
for item in backend.audio_extensions_list:
if not item in audio_list:
audio_list.append(item)
return audio_list
def get_video_extensions_list(self):
video_list = []
for backend in self.backends.values():
for item in backend.video_extensions_list:
if not item in video_list:
video_list.append(item)
return video_list

View File

@ -137,7 +137,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, 0, False])
#Receiver.send_message(u'media_video', [self.parent.liveController, filename, False])
# force a non-existent theme
service_item.theme = -1
frame = u':/media/image_clapperboard.png'

View File

@ -0,0 +1,385 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import sys, os,time
from PyQt4 import QtCore, QtGui, QtWebKit
from openlp.core.lib import OpenLPToolbar, Receiver, translate
from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.plugins.media.lib import MediaAPI, MediaState, MediaInfo
from webkitapi import WebkitAPI
from phononapi import PhononAPI
from vlcapi import VlcAPI
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 API
Currently these are QtWebkit, Phonon and planed Vlc.
Manager
- different API classes with specialised Access functions
Controller
- have general and API specific control Elements
- have one or more displays (Preview, Live, ...) with different settings
Display
- have API-Specific Display Elements
- have media info for current media
"""
def __init__(self, parent):
self.parent = parent
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)
self.withLivePreview = False
#Signals
QtCore.QObject.connect(self.Timer,
QtCore.SIGNAL("timeout()"), self.video_state)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'setup_display'), self.setup_display)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_video'), self.video)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'Media Start'), self.video_play)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'Media Pause'), self.video_pause)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'Media Stop'), self.video_stop)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'seekSlider'), self.video_seek)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'volumeSlider'), self.video_volume)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_reset'), self.video_reset)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_hide'), self.video_hide)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_blank'), self.video_blank)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_unblank'), self.video_unblank)
def video_state(self):
"""
Check if there is an assigned media API and do some
updating stuff (e.g. update the UI)
"""
isAnyonePlaying = False
if len(self.curDisplayMediaAPI.keys()) == 0:
self.Timer.stop()
else:
for display in self.curDisplayMediaAPI.keys():
self.curDisplayMediaAPI[display].update_ui(display)
if self.curDisplayMediaAPI[display] \
.state == MediaState.Playing:
isAnyonePlaying = True
if not isAnyonePlaying:
self.Timer.stop()
def addControllerItems(self, controller, control_panel):
self.controller.append(controller)
self.setup_generic_controls(controller, control_panel)
for api in self.APIs.values():
api.setup_controls(controller, control_panel)
def setup_generic_controls(self, controller, control_panel):
controller.media_info = MediaInfo()
# Build a Media ToolBar
controller.mediabar = OpenLPToolbar(controller)
controller.mediabar.addToolbarButton(
u'Media Start', u':/slides/media_playback_start.png',
translate('OpenLP.SlideController', 'Start playing media'),
controller.sendToPlugins)
controller.mediabar.addToolbarButton(
u'Media Pause', u':/slides/media_playback_pause.png',
translate('OpenLP.SlideController', 'Start playing media'),
controller.sendToPlugins)
controller.mediabar.addToolbarButton(
u'Media Stop', u':/slides/media_playback_stop.png',
translate('OpenLP.SlideController', 'Start playing media'),
controller.sendToPlugins)
# Build the seekSlider.
controller.seekSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
controller.seekSlider.setMaximum(1000)
# Build the volumeSlider.
controller.volumeSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
controller.volumeSlider.setTickInterval(10)
controller.volumeSlider.setTickPosition(QtGui.QSlider.TicksAbove)
controller.volumeSlider.setMinimum(0)
controller.volumeSlider.setMaximum(100)
controller.volumeSlider.setValue(controller.media_info.volume)
controller.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
controller.seekSlider.setObjectName(u'seekSlider')
controller.mediabar.addToolbarWidget(u'Seek Slider', controller.seekSlider)
controller.volumeSlider.setGeometry(QtCore.QRect(90, 160, 221, 24))
controller.volumeSlider.setObjectName(u'volumeSlider')
controller.mediabar.addToolbarWidget(u'Audio Volume', controller.volumeSlider)
control_panel.addWidget(controller.mediabar)
controller.mediabar.setVisible(False)
#Signals
QtCore.QObject.connect(controller.seekSlider,
QtCore.SIGNAL(u'sliderMoved(int)'), controller.sendToPlugins)
QtCore.QObject.connect(controller.volumeSlider,
QtCore.SIGNAL(u'sliderMoved(int)'), controller.sendToPlugins)
def setup_display(self, display):
"""
After a new display is configured, all media related widget
will be created too
"""
display.hasAudio = True
if not self.withLivePreview and \
display == self.parent.liveController.previewDisplay:
return
if display == self.parent.previewController.previewDisplay or \
display == self.parent.liveController.previewDisplay:
display.hasAudio = False
for api in self.APIs.values():
api.setup(display)
def set_controls_visible(self, controller, value):
# Generic controls
controller.mediabar.setVisible(value)
# Special controls
# for api in self.APIs.values():
# api.setup_controls(controller, control_panel)
def resize(self, display, api):
"""
After Mainwindow changes or Splitter moved all related media
widgets have to be resized
"""
if display == self.parent.previewController.previewDisplay or \
display == self.parent.liveController.previewDisplay:
display.resize(display.parent.slidePreview.size())
api.resize(display)
def video(self, msg):
"""
Loads and starts a video to run with the option of sound
"""
log.debug(u'video')
controller = msg[0]
isValid = False
# stop running videos
self.video_reset(controller)
controller.media_info = MediaInfo()
controller.media_info.volume = controller.volumeSlider.value()
controller.media_info.file_info = QtCore.QFileInfo(msg[1])
controller.media_info.is_background = msg[2]
if controller.isLive:
if self.withLivePreview:
display = controller.previewDisplay
isValid = self.check_file_type(display)
display = controller.display
isValid = self.check_file_type(display)
else:
display = controller.previewDisplay
isValid = self.check_file_type(display)
if not isValid:
#Media could not be loaded correctly
critical_error_message_box(
translate('MediaPlugin.MediaItem', 'Unsupported File'),
unicode(translate('MediaPlugin.MediaItem',
'Unsupported File')))
return
#now start playing
self.video_play([controller])
# self.video_pause([controller])
# self.video_seek([controller, 0])
# self.video_play([controller])
self.set_controls_visible(controller, True)
def check_file_type(self, display):
"""
Used to choose the right media API type
from the prioritized API list
"""
controller = display.parent
apiSettings = str(QtCore.QSettings().value(u'media/apis',
QtCore.QVariant(u'Webkit')).toString())
usedAPIs = apiSettings.split(u',')
if controller.media_info.file_info.isFile():
suffix = u'*.%s' % controller.media_info.file_info.suffix()
for title in usedAPIs:
api = self.APIs[title]
if suffix in api.video_extensions_list:
if not controller.media_info.is_background or \
controller.media_info.is_background and api.canBackground:
self.resize(display, api)
if api.load(display):
print api
self.curDisplayMediaAPI[display] = api
return True
# no valid api found
return False
def video_play(self, msg):
"""
Responds to the request to play a loaded video
"""
log.debug(u'video_play')
controller = msg[0]
for display in self.curDisplayMediaAPI.keys():
if display.parent == controller:
self.curDisplayMediaAPI[display].play(display)
# Start Timer for ui updates
if not self.Timer.isActive():
self.Timer.start()
def video_pause(self, msg):
"""
Responds to the request to pause a loaded video
"""
log.debug(u'videoPause')
controller = msg[0]
for display in self.curDisplayMediaAPI.keys():
if display.parent == controller:
self.curDisplayMediaAPI[display].pause(display)
def video_stop(self, msg):
"""
Responds to the request to stop a loaded video
"""
log.debug(u'video_stop')
controller = msg[0]
for display in self.curDisplayMediaAPI.keys():
if display.parent == controller:
self.curDisplayMediaAPI[display].stop(display)
self.curDisplayMediaAPI[display].set_visible(display, False)
def video_volume(self, msg):
"""
Changes the volume of a running video
"""
controller = msg[0]
vol = msg[1]
log.debug(u'video_volume %d' % vol)
for display in self.curDisplayMediaAPI.keys():
if display.parent == controller:
self.curDisplayMediaAPI[display].volume(display, vol)
def video_seek(self, msg):
"""
Responds to the request to change the seek Slider of a loaded video
"""
log.debug(u'video_seek')
controller = msg[0]
seekVal = msg[1]
for display in self.curDisplayMediaAPI.keys():
if display.parent == controller:
self.curDisplayMediaAPI[display].seek(display, seekVal)
def video_reset(self, controller):
"""
Responds to the request to reset a loaded video
"""
log.debug(u'video_reset')
for display in self.curDisplayMediaAPI.keys():
if display.parent == controller:
self.curDisplayMediaAPI[display].reset(display)
del self.curDisplayMediaAPI[display]
self.set_controls_visible(controller, False)
def video_hide(self, msg):
"""
Hide the related video Widget
"""
isLive = msg[1]
if isLive:
controller = self.parent.liveController
for display in self.curDisplayMediaAPI.keys():
if display.parent == controller:
if self.curDisplayMediaAPI[display] \
.state == MediaState.Playing:
self.curDisplayMediaAPI[display].pause(display)
self.curDisplayMediaAPI[display] \
.set_visible(display, False)
def video_blank(self, msg):
"""
Blank the related video Widget
"""
isLive = msg[1]
if isLive:
controller = self.parent.liveController
for display in self.curDisplayMediaAPI.keys():
if display.parent == controller:
if self.curDisplayMediaAPI[display] \
.state == MediaState.Playing:
self.curDisplayMediaAPI[display].pause(display)
self.curDisplayMediaAPI[display] \
.set_visible(display, False)
def video_unblank(self, msg):
"""
Unblank the related video Widget
"""
Receiver.send_message(u'maindisplay_show')
isLive = msg[1]
if isLive:
controller = self.parent.liveController
for display in self.curDisplayMediaAPI.keys():
if display.parent == controller:
if self.curDisplayMediaAPI[display] \
.state == MediaState.Paused:
self.curDisplayMediaAPI[display].play(display)
self.curDisplayMediaAPI[display] \
.set_visible(display, True)
def get_audio_extensions_list(self):
audio_list = []
for api in self.APIs.values():
for item in api.audio_extensions_list:
if not item in audio_list:
audio_list.append(item)
return audio_list
def get_video_extensions_list(self):
video_list = []
for api in self.APIs.values():
for item in api.video_extensions_list:
if not item in video_list:
video_list.append(item)
return video_list

View File

@ -38,52 +38,52 @@ class MediaTab(SettingsTab):
def setupUi(self):
self.setObjectName(u'MediaTab')
SettingsTab.setupUi(self)
self.mediaBackendsGroupBox = QtGui.QGroupBox(self.leftColumn)
self.mediaBackendsGroupBox.setObjectName(u'mediaBackendsGroupBox')
self.mediaBackendLayout = QtGui.QVBoxLayout(self.mediaBackendsGroupBox)
self.mediaBackendLayout.setObjectName(u'mediaBackendLayout')
self.usePhononCheckBox = QtGui.QCheckBox(self.mediaBackendsGroupBox)
self.mediaAPIsGroupBox = QtGui.QGroupBox(self.leftColumn)
self.mediaAPIsGroupBox.setObjectName(u'mediaAPIsGroupBox')
self.mediaApiLayout = QtGui.QVBoxLayout(self.mediaAPIsGroupBox)
self.mediaApiLayout.setObjectName(u'mediaApiLayout')
self.usePhononCheckBox = QtGui.QCheckBox(self.mediaAPIsGroupBox)
self.usePhononCheckBox.setObjectName(u'usePhononCheckBox')
self.mediaBackendLayout.addWidget(self.usePhononCheckBox)
self.useVlcCheckBox = QtGui.QCheckBox(self.mediaBackendsGroupBox)
self.mediaApiLayout.addWidget(self.usePhononCheckBox)
self.useVlcCheckBox = QtGui.QCheckBox(self.mediaAPIsGroupBox)
self.useVlcCheckBox.setObjectName(u'useVlcCheckBox')
self.mediaBackendLayout.addWidget(self.useVlcCheckBox)
self.leftLayout.addWidget(self.mediaBackendsGroupBox)
self.mediaApiLayout.addWidget(self.useVlcCheckBox)
self.leftLayout.addWidget(self.mediaAPIsGroupBox)
self.backendOrderGroupBox = QtGui.QGroupBox(self.leftColumn)
self.backendOrderGroupBox.setObjectName(u'backendOrderGroupBox')
self.backendOrderLayout = QtGui.QVBoxLayout(self.backendOrderGroupBox)
self.backendOrderLayout.setObjectName(u'backendOrderLayout')
self.backendOrderlistWidget = QtGui.QListWidget( \
self.backendOrderGroupBox)
self.apiOrderGroupBox = QtGui.QGroupBox(self.leftColumn)
self.apiOrderGroupBox.setObjectName(u'apiOrderGroupBox')
self.apiOrderLayout = QtGui.QVBoxLayout(self.apiOrderGroupBox)
self.apiOrderLayout.setObjectName(u'apiOrderLayout')
self.apiOrderlistWidget = QtGui.QListWidget( \
self.apiOrderGroupBox)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.backendOrderlistWidget. \
sizePolicy.setHeightForWidth(self.apiOrderlistWidget. \
sizePolicy().hasHeightForWidth())
self.backendOrderlistWidget.setSizePolicy(sizePolicy)
self.apiOrderlistWidget.setSizePolicy(sizePolicy)
self.backendOrderlistWidget.setVerticalScrollBarPolicy( \
self.apiOrderlistWidget.setVerticalScrollBarPolicy( \
QtCore.Qt.ScrollBarAsNeeded)
self.backendOrderlistWidget.setHorizontalScrollBarPolicy( \
self.apiOrderlistWidget.setHorizontalScrollBarPolicy( \
QtCore.Qt.ScrollBarAlwaysOff)
self.backendOrderlistWidget.setEditTriggers( \
self.apiOrderlistWidget.setEditTriggers( \
QtGui.QAbstractItemView.NoEditTriggers)
self.backendOrderlistWidget.setObjectName(u'backendOrderlistWidget')
self.backendOrderLayout.addWidget(self.backendOrderlistWidget)
self.orderingButtonsWidget = QtGui.QWidget(self.backendOrderGroupBox)
self.apiOrderlistWidget.setObjectName(u'apiOrderlistWidget')
self.apiOrderLayout.addWidget(self.apiOrderlistWidget)
self.orderingButtonsWidget = QtGui.QWidget(self.apiOrderGroupBox)
self.orderingButtonsWidget.setObjectName(u'orderingButtonsWidget')
self.orderingButtonLayout = QtGui.QHBoxLayout(self.orderingButtonsWidget)
self.orderingButtonLayout.setObjectName(u'orderingButtonLayout')
self.orderingDownButton = QtGui.QPushButton(self.orderingButtonsWidget)
self.orderingDownButton.setObjectName(u'orderingDownButton')
self.orderingButtonLayout.addWidget(self.orderingDownButton)
self.orderingUpButton = QtGui.QPushButton(self.backendOrderGroupBox)
self.orderingUpButton = QtGui.QPushButton(self.apiOrderGroupBox)
self.orderingUpButton.setObjectName(u'orderingUpButton')
self.orderingButtonLayout.addWidget(self.orderingUpButton)
self.backendOrderLayout.addWidget(self.orderingButtonsWidget)
self.leftLayout.addWidget(self.backendOrderGroupBox)
self.apiOrderLayout.addWidget(self.orderingButtonsWidget)
self.leftLayout.addWidget(self.apiOrderGroupBox)
self.leftLayout.addStretch()
self.rightLayout.addStretch()
QtCore.QObject.connect(self.usePhononCheckBox,
@ -98,14 +98,14 @@ class MediaTab(SettingsTab):
QtCore.SIGNAL(u'pressed()'), self.onOrderingDownButtonPressed)
def retranslateUi(self):
self.mediaBackendsGroupBox.setTitle(
translate('MediaPlugin.MediaTab', 'Media Backends'))
self.mediaAPIsGroupBox.setTitle(
translate('MediaPlugin.MediaTab', 'Media APIs'))
self.usePhononCheckBox.setText(
translate('MediaPlugin.MediaTab', 'use Phonon'))
self.useVlcCheckBox.setText(
translate('MediaPlugin.MediaTab', 'use Vlc'))
self.backendOrderGroupBox.setTitle(
translate('MediaPlugin.MediaTab', 'Backends Order'))
self.apiOrderGroupBox.setTitle(
translate('MediaPlugin.MediaTab', 'API Order'))
self.orderingDownButton.setText(
translate('MediaPlugin.MediaTab', 'Down'))
self.orderingUpButton.setText(
@ -114,61 +114,61 @@ class MediaTab(SettingsTab):
def onUsePhononCheckBoxChanged(self, check_state):
if check_state == QtCore.Qt.Checked:
self.usePhonon = True
if u'Phonon' not in self.usedBackends:
self.usedBackends.append(u'Phonon')
if u'Phonon' not in self.usedAPIs:
self.usedAPIs.append(u'Phonon')
else:
self.usePhonon = False
self.usedBackends.takeAt(self.usedBackends.indexOf(u'Phonon'))
self.updateBackendList()
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.usedBackends:
self.usedBackends.append(u'Vlc')
if u'Vlc' not in self.usedAPIs:
self.usedAPIs.append(u'Vlc')
else:
self.useVlc = False
self.usedBackends.takeAt(self.usedBackends.indexOf(u'Vlc'))
self.updateBackendList()
self.usedAPIs.takeAt(self.usedAPIs.indexOf(u'Vlc'))
self.updateApiList()
def updateBackendList(self):
self.backendOrderlistWidget.clear()
for backend in self.usedBackends:
self.backendOrderlistWidget.addItem(backend)
def updateApiList(self):
self.apiOrderlistWidget.clear()
for api in self.usedAPIs:
self.apiOrderlistWidget.addItem(api)
def onOrderingUpButtonPressed(self):
currentRow = self.backendOrderlistWidget.currentRow()
currentRow = self.apiOrderlistWidget.currentRow()
if currentRow > 0:
item = self.backendOrderlistWidget.takeItem(currentRow)
self.backendOrderlistWidget.insertItem(currentRow-1, item)
self.backendOrderlistWidget.setCurrentRow(currentRow-1)
self.usedBackends.move(currentRow, currentRow-1)
item = self.apiOrderlistWidget.takeItem(currentRow)
self.apiOrderlistWidget.insertItem(currentRow-1, item)
self.apiOrderlistWidget.setCurrentRow(currentRow-1)
self.usedAPIs.move(currentRow, currentRow-1)
def onOrderingDownButtonPressed(self):
currentRow = self.backendOrderlistWidget.currentRow()
if currentRow < self.backendOrderlistWidget.count()-1:
item = self.backendOrderlistWidget.takeItem(currentRow)
self.backendOrderlistWidget.insertItem(currentRow+1, item)
self.backendOrderlistWidget.setCurrentRow(currentRow+1)
self.usedBackends.move(currentRow, currentRow+1)
currentRow = self.apiOrderlistWidget.currentRow()
if currentRow < self.apiOrderlistWidget.count()-1:
item = self.apiOrderlistWidget.takeItem(currentRow)
self.apiOrderlistWidget.insertItem(currentRow+1, item)
self.apiOrderlistWidget.setCurrentRow(currentRow+1)
self.usedAPIs.move(currentRow, currentRow+1)
def load(self):
self.usedBackends = QtCore.QSettings().value(
self.settingsSection + u'/backends',
self.usedAPIs = QtCore.QSettings().value(
self.settingsSection + u'/apis',
QtCore.QVariant(u'Webkit')).toString().split(u',')
self.useWebkit = u'Webkit' in self.usedBackends
self.usePhonon = u'Phonon' in self.usedBackends
self.useVlc = u'Vlc' in self.usedBackends
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)
self.updateBackendList()
self.updateApiList()
def save(self):
oldBackendString = QtCore.QSettings().value(
self.settingsSection + u'/backends',
oldApiString = QtCore.QSettings().value(
self.settingsSection + u'/apis',
QtCore.QVariant(u'Webkit')).toString()
newBackendString = self.usedBackends.join(u',')
if oldBackendString != newBackendString:
QtCore.QSettings().setValue(self.settingsSection + u'/backends',
QtCore.QVariant(newBackendString))
newApiString = self.usedAPIs.join(u',')
if oldApiString != newApiString:
QtCore.QSettings().setValue(self.settingsSection + u'/apis',
QtCore.QVariant(newApiString))
Receiver.send_message(u'config_screen_changed')

View File

@ -33,18 +33,18 @@ from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon
from openlp.core.lib import Receiver
from openlp.plugins.media.lib import MediaController, MediaState
from openlp.plugins.media.lib import MediaAPI, MediaState
log = logging.getLogger(__name__)
class PhononController(MediaController):
class PhononAPI(MediaAPI):
"""
Specialiced MediaController class
to reflect Features of the Phonon backend
Specialiced MediaAPI class
to reflect Features of the Phonon API
"""
def __init__(self, parent):
MediaController.__init__(self, parent)
MediaAPI.__init__(self, parent)
self.parent = parent
self.additional_extensions = {
u'audio/ac3': [u'.ac3'],
@ -59,6 +59,7 @@ class PhononController(MediaController):
u'video/x-flv': [u'.flv'],
u'video/x-matroska': [u'.mpv', u'.mkv'],
u'video/x-wmv': [u'.wmv'],
u'video/x-mpg': [u'.mpg'],
u'video/x-ms-wmv': [u'.wmv']}
mimetypes.init()
for mimetype in Phonon.BackendCapabilities.availableMimeTypes():
@ -90,7 +91,10 @@ class PhononController(MediaController):
log.info(u'MediaPlugin: %s additional extensions: %s' % (mimetype,
u' '.join(self.additional_extensions[mimetype])))
def setup(self, display, hasAudio):
def setup_controls(self, controller, control_panel):
pass
def setup(self, display):
display.phononWidget = Phonon.VideoWidget(display)
display.phononWidget.setVisible(False)
display.phononWidget.resize(display.size())
@ -126,13 +130,18 @@ class PhononController(MediaController):
u'video/x-wmv': [u'.wmv'],
u'video/x-ms-wmv': [u'.wmv']}
def load(self, display, path, volume, isBackground):
def load(self, display):
log.debug(u'load vid in Phonon Controller')
controller = display.parent
volume = controller.media_info.volume
path = controller.media_info.file_info.absoluteFilePath()
display.mediaObject.setCurrentSource(Phonon.MediaSource(path))
if not self.mediaStateWait(display, Phonon.StoppedState):
return False
vol = float(volume) / float(10)
display.audio.setVolume(vol)
#self.info.start_time = 10000
#self.info.end_time = 20000
return True
def mediaStateWait(self, display, mediaState):
@ -149,12 +158,13 @@ class PhononController(MediaController):
return False
return True
def resize(self, display, controller):
def resize(self, display):
display.phononWidget.resize(display.size())
def play(self, display):
self.set_visible(display, True)
vol = float(display.parent.volume) / float(10)
#self.set_visible(display, True)
controller = display.parent
vol = float(controller.media_info.volume) / float(10)
display.audio.setVolume(vol)
display.mediaObject.play()
self.state = MediaState.Playing
@ -168,6 +178,8 @@ class PhononController(MediaController):
self.state = MediaState.Stopped
def volume(self, display, vol):
# 1.0 is the highest value
vol = float(vol) / float(100)
display.audio.setVolume(vol)
def seek(self, display, seekVal):
@ -183,16 +195,20 @@ class PhononController(MediaController):
if self.hasOwnWidget:
display.phononWidget.setVisible(status)
def update_ui(self, controller, display):
controller.seekSlider.setMaximum(display.mediaObject.totalTime())
if display.serviceItem.end_time > 0:
if display.mediaObject.currentTime() > \
display.serviceItem.end_time:
self.stop(display)
if display.serviceItem.start_time > 0:
def update_ui(self, display):
controller = display.parent
controller.media_info.length = display.mediaObject.totalTime()
controller.seekSlider.setMaximum(controller.media_info.length)
if controller.media_info.start_time > 0:
if display.mediaObject.currentTime() < \
display.serviceItem.start_time:
self.seek(display, self.serviceItem.start_time * 1000)
controller.media_info.start_time:
self.seek(display, controller.media_info.start_time)
self.set_visible(display, True)
if controller.media_info.end_time > 0:
if display.mediaObject.currentTime() > \
controller.media_info.end_time:
self.stop(display)
self.set_visible(display, False)
if not controller.seekSlider.isSliderDown():
controller.seekSlider.setSliderPosition( \
display.mediaObject.currentTime())

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@
###############################################################################
import logging
import sys
import sys, os
from datetime import datetime
try:
import vlc
@ -34,17 +34,17 @@ except:
pass
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver
from openlp.plugins.media.lib import MediaController, MediaState
from openlp.plugins.media.lib import MediaAPI, MediaState
log = logging.getLogger(__name__)
class VlcController(MediaController):
class VlcAPI(MediaAPI):
"""
Specialiced MediaController class
to reflect Features of the Vlc backend
Specialiced MediaAPI class
to reflect Features of the Vlc API
"""
def __init__(self, parent):
MediaController.__init__(self, parent)
MediaAPI.__init__(self, parent)
self.parent = parent
self.video_extensions_list = [
u'*.3gp'
@ -70,10 +70,13 @@ class VlcController(MediaController):
, u'*.iso'
]
def setup(self, display, hasAudio):
def setup_controls(self, controller, control_panel):
pass
def setup(self, display):
display.vlcWidget = QtGui.QFrame(display)
# creating a basic vlc instance
if hasAudio:
if display.hasAudio:
display.vlcInstance = vlc.Instance()
else:
display.vlcInstance = vlc.Instance('--no-audio')
@ -121,26 +124,28 @@ class VlcController(MediaController):
u'video/x-wmv': [u'.wmv'],
u'video/x-ms-wmv': [u'.wmv']}
def load(self, display, path, volume, isBackground):
def load(self, display):
log.debug(u'load vid in Vlc Controller')
vol = float(volume) / float(10)
controller = display.parent
volume = controller.media_info.volume
file_path = str(
controller.media_info.file_info.absoluteFilePath().toUtf8())
path = os.path.normcase(file_path)
# create the media
display.vlcMedia = display.vlcInstance.media_new_path(unicode(path))
display.vlcMedia = display.vlcInstance.media_new_path(path)
# put the media in the media player
display.vlcMediaPlayer.set_media(display.vlcMedia)
# parse the metadata of the file
display.vlcMedia.parse()
if not self.mediaStateWait(display):
return False
return True
def mediaStateWait(self, display):
def mediaStateWait(self, display, mediaState):
"""
Wait for the video to change its state
Wait no longer than 5 seconds.
"""
start = datetime.now()
while not display.vlcMedia.is_parsed():
while not mediaState == display.vlcMedia.get_state():
if display.vlcMedia.get_state() == vlc.State.Error:
return False
Receiver.send_message(u'openlp_process_events')
@ -148,24 +153,26 @@ class VlcController(MediaController):
return False
return True
def resize(self, display, controller):
def resize(self, display):
display.vlcWidget.resize(display.size())
def play(self, display):
self.set_visible(display, True)
display.vlcMediaPlayer.play()
self.state = MediaState.Playing
if self.mediaStateWait(display, vlc.State.Playing):
self.state = MediaState.Playing
def pause(self, display):
display.vlcMediaPlayer.pause()
self.state = MediaState.Paused
if self.mediaStateWait(display, vlc.State.Paused):
self.state = MediaState.Paused
def stop(self, display):
display.vlcMediaPlayer.stop()
self.state = MediaState.Stopped
def volume(self, display, vol):
pass
display.vlcMediaPlayer.audio_set_volume(vol)
def seek(self, display, seekVal):
if display.vlcMediaPlayer.is_seekable():
@ -180,7 +187,8 @@ class VlcController(MediaController):
if self.hasOwnWidget:
display.vlcWidget.setVisible(status)
def update_ui(self, controller, display):
def update_ui(self, display):
controller = display.parent
controller.seekSlider.setMaximum(1000)
if not controller.seekSlider.isSliderDown():
currentPos = display.vlcMediaPlayer.get_position() * 1000

View File

@ -28,20 +28,21 @@
import logging
from PyQt4 import QtCore, QtGui, QtWebKit
from openlp.plugins.media.lib import MediaController, MediaState
from openlp.core.lib import OpenLPToolbar, translate
from openlp.plugins.media.lib import MediaAPI, MediaState
log = logging.getLogger(__name__)
class WebkitController(MediaController):
class WebkitAPI(MediaAPI):
"""
Specialiced MediaController class
to reflect Features of the QtWebkit backend
Specialiced MediaAPI class
to reflect Features of the QtWebkit API
"""
def __init__(self, parent):
MediaController.__init__(self, parent)
MediaAPI.__init__(self, parent)
self.parent = parent
self.isFlash = False
self.canBackground = True
self.video_extensions_list = [
u'*.3gp'
@ -68,7 +69,11 @@ class WebkitController(MediaController):
, u'*.swf', u'*.mpg', u'*.wmv', u'*.mpeg', u'*.avi'
]
def setup(self, display, hasAudio):
def setup_controls(self, controller, control_panel):
# no special controls
pass
def setup(self, display):
display.webView.raise_()
self.hasOwnWidget = False
@ -79,68 +84,83 @@ class WebkitController(MediaController):
def get_supported_file_types(self):
pass
def load(self, display, path, volume, isBackground):
def load(self, display):
log.debug(u'load vid in Webkit Controller')
vol = float(volume) / float(10)
if isBackground:
controller = display.parent
volume = controller.media_info.volume
vol = float(volume) / float(100)
path = controller.media_info.file_info.absoluteFilePath()
if controller.media_info.is_background:
loop = u'true'
else:
loop = u'false'
display.webView.setVisible(True)
if path.endswith(u'.swf'):
if controller.media_info.file_info.suffix() == u'swf':
controller.media_info.isFlash = True
js = u'show_flash("load","%s");' % \
(path.replace(u'\\', u'\\\\'))
self.isFlash = True
else:
js = u'show_video("init", "%s", %s, %s);' % \
(path.replace(u'\\', u'\\\\'), str(vol), loop)
self.isFlash = False
display.frame.evaluateJavaScript(js)
return True
def resize(self, display, controller):
def resize(self, display):
controller = display.parent
if display == controller.previewDisplay:
display.webView.resize(display.size())
def play(self, display):
display.override[u'theme'] = u''
display.override[u'video'] = True
controller = display.parent
#display.override[u'theme'] = u''
#display.override[u'video'] = True
display.webLoaded = True
self.set_visible(display, True)
if self.isFlash:
display.frame.evaluateJavaScript(u'show_flash("play","");')
if controller.media_info.isFlash:
display.frame.evaluateJavaScript(u'show_flash("play");')
else:
display.frame.evaluateJavaScript(u'show_video("play");')
self.state = MediaState.Playing
def pause(self, display):
if self.isFlash:
display.frame.evaluateJavaScript(u'show_flash("pause","");')
controller = display.parent
if controller.media_info.isFlash:
display.frame.evaluateJavaScript(u'show_flash("pause");')
else:
display.frame.evaluateJavaScript(u'show_video("pause");')
self.state = MediaState.Paused
def stop(self, display):
if self.isFlash:
display.frame.evaluateJavaScript(u'show_flash("stop","");')
controller = display.parent
if controller.media_info.isFlash:
display.frame.evaluateJavaScript(u'show_flash("stop");')
else:
display.frame.evaluateJavaScript(u'show_video("stop");')
self.state = MediaState.Stopped
def volume(self, display, vol):
if not self.isFlash:
controller = display.parent
# 1.0 is the highest value
vol = float(vol) / float(100)
if not controller.media_info.isFlash:
display.frame.evaluateJavaScript(u'show_video(null, null, %s);' %
str(vol))
def seek(self, display, seekVal):
if not self.isFlash:
controller = display.parent
if controller.media_info.isFlash:
seek = seekVal
display.frame.evaluateJavaScript( \
u'show_flash("seek", null, null, "%s");' % (seek))
else:
seek = float(seekVal)/1000
display.frame.evaluateJavaScript( \
u'show_video("seek", null, null, null, "%f");' % (seek))
def reset(self, display):
if self.isFlash:
display.frame.evaluateJavaScript(u'show_flash("close","");')
controller = display.parent
if controller.media_info.isFlash:
display.frame.evaluateJavaScript(u'show_flash("close");')
else:
display.frame.evaluateJavaScript(u'show_video("close");')
self.state = MediaState.Off
@ -149,16 +169,26 @@ class WebkitController(MediaController):
if self.hasOwnWidget:
display.webView.setVisible(status)
def update_ui(self, controller, display):
if not self.isFlash:
def update_ui(self, display):
controller = display.parent
if controller.media_info.isFlash:
currentTime = display.frame.evaluateJavaScript( \
u'show_video("currentTime");')
length = display.frame.evaluateJavaScript(u'show_video("length");')
if int(currentTime.toFloat()[0]*1000) > 0:
controller.seekSlider.setMaximum(int(length.toFloat()[0]*1000))
if not controller.seekSlider.isSliderDown():
controller.seekSlider.setSliderPosition( \
int(currentTime.toFloat()[0]*1000))
u'show_flash("currentTime");').toInt()[0]
length = display.frame.evaluateJavaScript( \
u'show_flash("length");').toInt()[0]
else:
(currentTime, ok) = display.frame.evaluateJavaScript( \
u'show_video("currentTime");').toFloat()
if ok:
currentTime = int(currentTime*1000)
(length, ok) = display.frame.evaluateJavaScript( \
u'show_video("length");').toFloat()
if ok:
length = int(length*1000)
if currentTime > 0:
controller.seekSlider.setMaximum(length)
if not controller.seekSlider.isSliderDown():
controller.seekSlider.setSliderPosition(currentTime)
def get_supported_file_types(self):
pass

View File

@ -53,6 +53,9 @@ class MediaPlugin(Plugin):
'<br />The media plugin provides playback of audio and video.')
return about_text
def addControllerItems(self, controller, control_panel):
self.mediaManager.addControllerItems(controller, control_panel)
def setPluginTextStrings(self):
"""
Called to define all translatable texts of the plugin