Head and bugfixing

This commit is contained in:
rimach 2011-11-02 21:44:44 +01:00
commit 4779a3f21a
23 changed files with 297 additions and 226 deletions

View File

@ -506,25 +506,3 @@ def build_footer_css(item, height):
item.footer.width(), theme.font_footer_name,
theme.font_footer_size, theme.font_footer_color)
return lyrics_html
def build_alert_css(alertTab):
"""
Build the display of the footer
``alertTab``
Details from the Alert tab for fonts etc
"""
style = u"""
width: 100%%;
vertical-align: %s;
font-family: %s;
font-size: %spt;
color: %s;
background-color: %s;
"""
if not alertTab:
return u''
align = VerticalType.Names[alertTab.location]
alert = style % (align, alertTab.font_face, alertTab.font_size,
alertTab.font_color, alertTab.bg_color)
return alert

View File

@ -31,7 +31,7 @@ from PyQt4 import QtGui, QtCore, QtWebKit
from openlp.core.lib import ServiceItem, expand_tags, \
build_lyrics_format_css, build_lyrics_outline_css, Receiver, \
ItemCapabilities, FormattingTags, PluginManager
ItemCapabilities, FormattingTags
from openlp.core.lib.theme import ThemeLevel
from openlp.core.ui import MainDisplay, ScreenList
@ -69,7 +69,6 @@ class Renderer(object):
log.debug(u'Initialisation started')
self.themeManager = themeManager
self.imageManager = imageManager
self.plugins = PluginManager.get_instance().plugins
self.screens = ScreenList.get_instance()
self.service_theme = u''
self.theme_level = u''

View File

@ -52,6 +52,24 @@ class HideMode(object):
Theme = 2
Screen = 3
class AlertLocation(object):
"""
This is an enumeration class which controls where Alerts are placed on the
screen.
``Top``
Place the text at the top of the screen.
``Middle``
Place the text in the middle of the screen.
``Bottom``
Place the text at the bottom of the screen.
"""
Top = 0
Middle = 1
Bottom = 2
from firsttimeform import FirstTimeForm
from firsttimelanguageform import FirstTimeLanguageForm
from themelayoutform import ThemeLayoutForm

View File

@ -37,7 +37,7 @@ from PyQt4.phonon import Phonon
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \
translate, PluginManager
from openlp.core.ui import HideMode, ScreenList
from openlp.core.ui import HideMode, ScreenList, AlertLocation
log = logging.getLogger(__name__)
@ -46,49 +46,64 @@ log = logging.getLogger(__name__)
class Display(QtGui.QGraphicsView):
"""
This is a general display screen class.
This is a general display screen class. Here the general display settings
will done. It will be used as specialized classes by Main Display and
Preview display.
"""
def __init__(self, parent, live, controller):
if live:
QtGui.QGraphicsView.__init__(self)
# Do not overwrite the parent() method.
# Overwrite the parent() method.
self.parent = lambda: parent
else:
QtGui.QGraphicsView.__init__(self, parent)
self.isLive = live
self.controller = controller
self.screen = None
self.plugins = PluginManager.get_instance().plugins
self.setViewport(QtOpenGL.QGLWidget())
def setup(self):
"""
Set up and build the preview screen
Set up and build the screen base
"""
log.debug(u'Start Display base setup (live = %s)' % self.isLive)
self.setGeometry(self.screen[u'size'])
log.debug(u'Setup webView')
self.webView = QtWebKit.QWebView(self)
self.webView.setGeometry(0, 0,
self.width(), self.height())
self.screen[u'size'].width(), self.screen[u'size'].height())
self.webView.settings().setAttribute(
QtWebKit.QWebSettings.PluginsEnabled, True)
self.page = self.webView.page()
self.frame = self.page.mainFrame()
if self.isLive and log.getEffectiveLevel() == logging.DEBUG:
self.webView.settings().setAttribute(
QtWebKit.QWebSettings.DeveloperExtrasEnabled, True)
QtCore.QObject.connect(self.webView,
QtCore.SIGNAL(u'loadFinished(bool)'), self.isWebLoaded)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.frame.setScrollBarPolicy(QtCore.Qt.Vertical,
QtCore.Qt.ScrollBarAlwaysOff)
self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal,
QtCore.Qt.ScrollBarAlwaysOff)
screen = {}
screen[u'size'] = self.size()
serviceItem = ServiceItem()
self.webView.setHtml(build_html(serviceItem, screen,
None, self.isLive, None))
self.webView.hide()
def resizeEvent(self, ev):
self.webView.setGeometry(0, 0,
self.width(), self.height())
def isWebLoaded(self):
"""
Called by webView event to show display is fully loaded
"""
log.debug(u'Webloaded')
self.webLoaded = True
class MainDisplay(Display):
"""
This is the display screen.
This is the display screen as a specialized class from the Display class
"""
def __init__(self, parent, imageManager, live, controller):
Display.__init__(self, parent, live, controller)
@ -149,26 +164,7 @@ class MainDisplay(Display):
log.debug(u'Start MainDisplay setup (live = %s)' % self.isLive)
self.screen = self.screens.current
self.setVisible(False)
self.setGeometry(self.screen[u'size'])
log.debug(u'Setup webView')
self.webView = QtWebKit.QWebView(self)
self.webView.setGeometry(0, 0,
self.screen[u'size'].width(), self.screen[u'size'].height())
self.webView.settings().setAttribute(
QtWebKit.QWebSettings.PluginsEnabled, True)
self.page = self.webView.page()
self.frame = self.page.mainFrame()
if self.isLive and log.getEffectiveLevel() == logging.DEBUG:
self.webView.settings().setAttribute(
QtWebKit.QWebSettings.DeveloperExtrasEnabled, True)
QtCore.QObject.connect(self.webView,
QtCore.SIGNAL(u'loadFinished(bool)'), self.isWebLoaded)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.frame.setScrollBarPolicy(QtCore.Qt.Vertical,
QtCore.Qt.ScrollBarAlwaysOff)
self.frame.setScrollBarPolicy(QtCore.Qt.Horizontal,
QtCore.Qt.ScrollBarAlwaysOff)
Display.setup(self)
if self.isLive:
# Build the initial frame.
image_file = QtCore.QSettings().value(u'advanced/default image',
@ -195,7 +191,7 @@ class MainDisplay(Display):
serviceItem = ServiceItem()
serviceItem.bg_image_bytes = image_to_byte(self.initialFrame)
self.webView.setHtml(build_html(serviceItem, self.screen,
self.isLive, None))
self.isLive, None, plugins=self.plugins))
self.__hideMouse()
# To display or not to display?
if not self.screen[u'primary']:
@ -219,7 +215,7 @@ class MainDisplay(Display):
self.frame.evaluateJavaScript(u'show_text("%s")' %
slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
def alert(self, text):
def alert(self, text, location):
"""
Display an alert.
@ -243,10 +239,10 @@ class MainDisplay(Display):
alert_height = int(height.toString())
self.resize(self.width(), alert_height)
self.setVisible(True)
if self.alertTab.location == 1:
if location == AlertLocation.Middle:
self.move(self.screen[u'size'].left(),
(self.screen[u'size'].height() - alert_height) / 2)
elif self.alertTab.location == 2:
elif location == AlertLocation.Bottom:
self.move(self.screen[u'size'].left(),
self.screen[u'size'].height() - alert_height)
else:

View File

@ -27,8 +27,8 @@
class MediaState(object):
"""
An enumeration for possible States of the Media Player
(copied partially from Phonon::State)
An enumeration for possible States of the Media Player (copied partially
from Phonon::State)
"""
Loading = 0
Stopped = 1

View File

@ -29,11 +29,11 @@ from openlp.core.ui.media import MediaState
class MediaAPI(object):
"""
A generic media API class to provide OpenLP
with a pluggable media display framework.
A generic media API class to provide OpenLP with a pluggable media display
framework.
"""
def __init__(self, parent, name=u'MediaApi'):
def __init__(self, parent, name=u'media_api'):
self.parent = parent
self.name = name
self.available = self.check_available()
@ -65,8 +65,8 @@ class MediaAPI(object):
def resize(self, display):
"""
If the main display size or position is changed,
the media widgets should also resized
If the main display size or position is changed, the media widgets
should also resized
"""
pass
@ -114,8 +114,7 @@ class MediaAPI(object):
def update_ui(self, display):
"""
Do some ui related stuff
(e.g. update the seek slider)
Do some ui related stuff (e.g. update the seek slider)
"""
pass

View File

@ -39,14 +39,13 @@ log = logging.getLogger(__name__)
class MediaController(object):
"""
The implementation of the Media Controller
The Media Controller adds an own class for every API
Currently these are QtWebkit, Phonon and planed Vlc.
The implementation of the Media Controller. The Media Controller adds an own
class for every API. Currently these are QtWebkit, Phonon and planed Vlc.
"""
def __init__(self, parent):
self.parent = parent
self.APIs = {}
self.mediaApis = {}
self.controller = []
self.overridenApi = ''
self.curDisplayMediaAPI = {}
@ -59,15 +58,15 @@ class MediaController(object):
QtCore.QObject.connect(self.timer,
QtCore.SIGNAL("timeout()"), self.video_state)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'Media Start'), self.video_play)
QtCore.SIGNAL(u'media_playback_play'), self.video_play)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'Media Pause'), self.video_pause)
QtCore.SIGNAL(u'media_playback_pause'), self.video_pause)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'Media Stop'), self.video_stop)
QtCore.SIGNAL(u'media_playback_stop'), self.video_stop)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'seekSlider'), self.video_seek)
QtCore.SIGNAL(u'seek_slider'), self.video_seek)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'volumeSlider'), self.video_volume)
QtCore.SIGNAL(u'volume_slider'), self.video_volume)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_hide'), self.video_hide)
QtCore.QObject.connect(Receiver.get_receiver(),
@ -75,7 +74,7 @@ class MediaController(object):
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_unblank'), self.video_unblank)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_overrideApi'), self.override_api)
QtCore.SIGNAL(u'media_override_api'), self.override_api)
# Signals for background video
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'songs_hide'), self.video_hide)
@ -84,16 +83,16 @@ class MediaController(object):
def register_controllers(self, controller):
"""
Register each media API controller (Webkit, Phonon, etc) and
store for later use
Register each media API controller (Webkit, Phonon, etc) and store for
later use
"""
if controller.check_available():
self.APIs[controller.name] = controller
self.mediaApis[controller.name] = controller
def check_available_media_apis(self):
"""
Check to see if we have any media API's available
If Not do not install the plugin.
Check to see if we have any media API's available. If Not do not install
the plugin.
"""
log.debug(u'check_available_media_apis')
controller_dir = os.path.join(
@ -116,17 +115,26 @@ class MediaController(object):
for controller_class in controller_classes:
controller = controller_class(self)
self.register_controllers(controller)
if self.APIs:
if self.mediaApis:
apiSettings = str(QtCore.QSettings().value(u'media/apis',
QtCore.QVariant(u'webkit')).toString())
savedAPIs = apiSettings.split(u',')
invalidMediaAPIs = [mediaApi for mediaApi in savedAPIs \
if not mediaApi in self.mediaApis]
if len(invalidMediaAPIs)>0:
[savedAPIs.remove(invalidApi) for invalidApi in invalidMediaAPIs]
newApiSetting = u','.join(savedAPIs)
QtCore.QSettings().setValue(u'media/apis',
QtCore.QVariant(newApiSetting))
return True
else:
return False
def video_state(self):
"""
Check if there is an assigned media API and do some
updating stuff (e.g. update the UI)
Check if there is a running media Player and do updating stuff (e.g.
update the UI)
"""
isAnyonePlaying = False
if len(self.curDisplayMediaAPI.keys()) == 0:
self.timer.stop()
else:
@ -135,16 +143,15 @@ class MediaController(object):
self.curDisplayMediaAPI[display].update_ui(display)
if self.curDisplayMediaAPI[display] \
.state == MediaState.Playing:
isAnyonePlaying = True
if not isAnyonePlaying:
self.timer.stop()
return
self.timer.stop()
def get_media_display_css(self):
"""
Add css style sheets to htmlbuilder
"""
css = u''
for api in self.APIs.values():
for api in self.mediaApis.values():
css += api.get_media_display_css()
return css
@ -153,7 +160,7 @@ class MediaController(object):
Add javascript functions to htmlbuilder
"""
js = u''
for api in self.APIs.values():
for api in self.mediaApis.values():
js += api.get_media_display_javascript()
return js
@ -162,30 +169,32 @@ class MediaController(object):
Add html code to htmlbuilder
"""
html = u''
for api in self.APIs.values():
for api in self.mediaApis.values():
html += api.get_media_display_html()
return html
def add_controller_items(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)
self.setup_special_controls(controller, control_panel)
def setup_generic_controls(self, controller, control_panel):
"""
Add generic media control items (valid for all types of medias)
"""
controller.media_info = MediaInfo()
# Build a Media ToolBar
controller.mediabar = OpenLPToolbar(controller)
controller.mediabar.addToolbarButton(
u'Media Start', u':/slides/media_playback_start.png',
u'media_playback_play', 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',
u'media_playback_pause', u':/slides/media_playback_pause.png',
translate('OpenLP.SlideController', 'Pause playing media'),
controller.sendToPlugins)
controller.mediabar.addToolbarButton(
u'Media Stop', u':/slides/media_playback_stop.png',
u'media_playback_stop', u':/slides/media_playback_stop.png',
translate('OpenLP.SlideController', 'Stop playing media'),
controller.sendToPlugins)
# Build the seekSlider.
@ -194,8 +203,9 @@ class MediaController(object):
controller.seekSlider.setToolTip(translate(
'OpenLP.SlideController', 'Video position.'))
controller.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
controller.seekSlider.setObjectName(u'seekSlider')
controller.mediabar.addToolbarWidget(u'Seek Slider', controller.seekSlider)
controller.seekSlider.setObjectName(u'seek_slider')
controller.mediabar.addToolbarWidget(u'Seek Slider',
controller.seekSlider)
# Build the volumeSlider.
controller.volumeSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
controller.volumeSlider.setTickInterval(10)
@ -206,8 +216,9 @@ class MediaController(object):
'OpenLP.SlideController', 'Audio Volume.'))
controller.volumeSlider.setValue(controller.media_info.volume)
controller.volumeSlider.setGeometry(QtCore.QRect(90, 160, 221, 24))
controller.volumeSlider.setObjectName(u'volumeSlider')
controller.mediabar.addToolbarWidget(u'Audio Volume', controller.volumeSlider)
controller.volumeSlider.setObjectName(u'volume_slider')
controller.mediabar.addToolbarWidget(u'Audio Volume',
controller.volumeSlider)
control_panel.addWidget(controller.mediabar)
controller.mediabar.setVisible(False)
# Signals
@ -216,10 +227,17 @@ class MediaController(object):
QtCore.QObject.connect(controller.volumeSlider,
QtCore.SIGNAL(u'sliderMoved(int)'), controller.sendToPlugins)
def setup_special_controls(self, controller, control_panel):
"""
Special media Toolbars will be created here (e.g. for DVD Playback)
"""
controller.media_info = MediaInfo()
# TODO: add Toolbar for DVD, ...
def setup_display(self, display):
"""
After a new display is configured, all media related widget
will be created too
After a new display is configured, all media related widget will be
created too
"""
# clean up possible running old media files
self.finalise()
@ -230,21 +248,20 @@ class MediaController(object):
if display == self.parent.previewController.previewDisplay or \
display == self.parent.liveController.previewDisplay:
display.hasAudio = False
for api in self.APIs.values():
for api in self.mediaApis.values():
api.setup(display)
def set_controls_visible(self, controller, value):
# Generic controls
controller.mediabar.setVisible(value)
# Special controls
# Special controls: Here media type specific Controls will be enabled
# (e.g. for DVD control, ...)
# TODO
# for api in self.APIs.values():
# api.setup_controls(controller, control_panel)
def resize(self, controller, display, api):
"""
After Mainwindow changes or Splitter moved all related media
widgets have to be resized
After Mainwindow changes or Splitter moved all related media widgets
have to be resized
"""
api.resize(display)
@ -285,7 +302,6 @@ class MediaController(object):
'Unsupported File')))
return False
# now start playing
display.frame.evaluateJavaScript(u'show_blank("black");')
if self.video_play([controller], False):
self.video_pause([controller])
self.video_seek([controller, [0]])
@ -295,6 +311,10 @@ class MediaController(object):
controller.media_info.is_background == True) or \
controller.isLive == False:
self.video_play([controller])
if controller.isLive and ( \
controller.media_info.is_background == False):
display.frame.evaluateJavaScript(u'show_video( \
"setBackBoard", null, null, null,"visible");')
self.set_controls_visible(controller, True)
log.debug(u'use %s controller' % self.curDisplayMediaAPI[display])
return True
@ -307,20 +327,19 @@ class MediaController(object):
def check_file_type(self, controller, display):
"""
Used to choose the right media API type
from the prioritized API list
Used to choose the right media API type from the prioritized API list
"""
apiSettings = str(QtCore.QSettings().value(u'media/apis',
QtCore.QVariant(u'Webkit')).toString())
QtCore.QVariant(u'webkit')).toString())
usedAPIs = apiSettings.split(u',')
if QtCore.QSettings().value(u'media/override api',
QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked:
if self.overridenApi != '':
usedAPIs = [self.overridenApi]
if controller.media_info.file_info.isFile():
suffix = u'*.%s' % controller.media_info.file_info.suffix()
suffix = u'*.%s' % controller.media_info.file_info.suffix().toLower()
for title in usedAPIs:
api = self.APIs[title]
api = self.mediaApis[title]
if suffix in api.video_extensions_list:
if not controller.media_info.is_background or \
controller.media_info.is_background and api.canBackground:
@ -336,7 +355,7 @@ class MediaController(object):
return True
else:
for title in usedAPIs:
api = self.APIs[title]
api = self.mediaApis[title]
if api.canFolder:
self.resize(controller, display, api)
if api.load(display):
@ -421,6 +440,8 @@ class MediaController(object):
display.override = {}
self.curDisplayMediaAPI[display].reset(display)
self.curDisplayMediaAPI[display].set_visible(display, False)
display.frame.evaluateJavaScript(u'show_video( \
"setBackBoard", null, null, null,"hidden");')
del self.curDisplayMediaAPI[display]
self.set_controls_visible(controller, False)
@ -478,7 +499,7 @@ class MediaController(object):
def get_audio_extensions_list(self):
audio_list = []
for api in self.APIs.values():
for api in self.mediaApis.values():
for item in api.audio_extensions_list:
if not item in audio_list:
audio_list.append(item)
@ -486,7 +507,7 @@ class MediaController(object):
def get_video_extensions_list(self):
video_list = []
for api in self.APIs.values():
for api in self.mediaApis.values():
for item in api.video_extensions_list:
if not item in video_list:
video_list.append(item)
@ -494,7 +515,7 @@ class MediaController(object):
def override_api(self, override_api):
apiSettings = str(QtCore.QSettings().value(u'media/apis',
QtCore.QVariant(u'Webkit')).toString())
QtCore.QVariant(u'webkit')).toString())
usedAPIs = apiSettings.split(u',')
if override_api in usedAPIs:
self.overridenApi = override_api

View File

@ -37,16 +37,7 @@ from openlp.core.ui.media import MediaAPI, MediaState
log = logging.getLogger(__name__)
class PhononAPI(MediaAPI):
"""
A specialised version of the MediaAPI class,
which provides a Phonon display.
"""
def __init__(self, parent):
MediaAPI.__init__(self, parent, u'Phonon')
self.parent = parent
self.additional_extensions = {
ADDITIONAL_EXT = {
u'audio/ac3': [u'.ac3'],
u'audio/flac': [u'.flac'],
u'audio/x-m4a': [u'.m4a'],
@ -61,6 +52,18 @@ class PhononAPI(MediaAPI):
u'video/x-wmv': [u'.wmv'],
u'video/x-mpg': [u'.mpg'],
u'video/x-ms-wmv': [u'.wmv']}
class PhononAPI(MediaAPI):
"""
A specialised version of the MediaAPI class, which provides a Phonon
display.
"""
def __init__(self, parent):
MediaAPI.__init__(self, parent, u'phonon')
self.parent = parent
self.additional_extensions = ADDITIONAL_EXT
mimetypes.init()
for mimetype in Phonon.BackendCapabilities.availableMimeTypes():
mimetype = unicode(mimetype)
@ -89,9 +92,6 @@ class PhononAPI(MediaAPI):
log.info(u'MediaPlugin: %s additional extensions: %s' % (mimetype,
u' '.join(self.additional_extensions[mimetype])))
def setup_controls(self, controller, control_panel):
pass
def setup(self, display):
display.phononWidget = Phonon.VideoWidget(display)
display.phononWidget.resize(display.size())

View File

@ -35,11 +35,15 @@ from openlp.core.ui.media import MediaAPI, MediaState
log = logging.getLogger(__name__)
VIDEO_CSS = u"""
#video1 {
#videobackboard {
z-index:3;
background-color: black;
}
#video1 {
z-index:4;
}
#video2 {
z-index:3;
z-index:4;
}
"""
@ -135,11 +139,16 @@ VIDEO_JS = u"""
case 'setVisible':
vid.style.visibility = varVal;
break;
case 'setBackBoard':
var back = document.getElementById('videobackboard');
back.style.visibility = varVal;
break;
}
}
"""
VIDEO_HTML = u"""
<div id="videobackboard" class="size" style="visibility:hidden"></div>
<video id="video1" class="size" style="visibility:hidden" autobuffer preload>
</video>
<video id="video2" class="size" style="visibility:hidden" autobuffer preload>
@ -148,7 +157,7 @@ VIDEO_HTML = u"""
FLASH_CSS = u"""
#flash {
z-index:4;
z-index:5;
}
"""
@ -215,21 +224,7 @@ FLASH_HTML = u"""
<div id="flash" class="size" style="visibility:hidden"></div>
"""
class WebkitAPI(MediaAPI):
"""
A specialised version of the MediaAPI class,
which provides a QtWebKit display.
"""
def __init__(self, parent):
MediaAPI.__init__(self, parent, u'Webkit')
self.parent = parent
self.canBackground = True
self.audio_extensions_list = [
u'*.mp3'
, u'*.ogg'
]
self.video_extensions_list = [
VIDEO_EXT = [
u'*.3gp'
, u'*.3gpp'
, u'*.3g2'
@ -253,9 +248,24 @@ class WebkitAPI(MediaAPI):
, u'*.swf'
]
def setup_controls(self, controller, control_panel):
# no special controls
pass
AUDIO_EXT = [
u'*.mp3'
, u'*.ogg'
]
class WebkitAPI(MediaAPI):
"""
A specialised version of the MediaAPI class, which provides a QtWebKit
display.
"""
def __init__(self, parent):
MediaAPI.__init__(self, parent, u'webkit')
self.parent = parent
self.canBackground = True
self.audio_extensions_list = AUDIO_EXT
self.video_extensions_list = VIDEO_EXT
def get_media_display_css(self):
"""
@ -263,14 +273,12 @@ class WebkitAPI(MediaAPI):
"""
return VIDEO_CSS + FLASH_CSS
def get_media_display_javascript(self):
"""
Add javascript functions to htmlbuilder
"""
return VIDEO_JS + FLASH_JS
def get_media_display_html(self):
"""
Add html code to htmlbuilder
@ -395,10 +403,12 @@ class WebkitAPI(MediaAPI):
(currentTime, ok) = display.frame.evaluateJavaScript( \
u'show_video("currentTime");').toFloat()
# check if conversion was ok and value is not 'NaN'
print currentTime,
if ok and currentTime != float('inf'):
currentTime = int(currentTime*1000)
(length, ok) = display.frame.evaluateJavaScript( \
u'show_video("length");').toFloat()
print length
# check if conversion was ok and value is not 'NaN'
if ok and length != float('inf'):
length = int(length*1000)

View File

@ -34,7 +34,7 @@ from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon
from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \
translate, build_icon
translate, build_icon, ServiceItem, build_html
from openlp.core.lib.ui import UiStrings, shortcut_action
from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList
from openlp.core.utils.actions import ActionList, CategoryOrder
@ -287,6 +287,12 @@ class SlideController(Controller):
self.slideLayout.setObjectName(u'SlideLayout')
self.previewDisplay = Display(self, self.isLive, self)
self.previewDisplay.setGeometry(QtCore.QRect(0, 0, 300, 300))
self.previewDisplay.screen = {u'size':self.previewDisplay.geometry()}
self.previewDisplay.setup()
serviceItem = ServiceItem()
self.previewDisplay.webView.setHtml(build_html(serviceItem,
self.previewDisplay.screen, None, self.isLive, None))
# self.previewDisplay.webView.hide()
self.slideLayout.insertWidget(0, self.previewDisplay)
self.previewDisplay.hide()
# Actual preview screen

View File

@ -71,11 +71,24 @@ JAVASCRIPT = """
function update_css(align, font, size, color, bgcolor){
var text = document.getElementById('alert');
text.style.verticalAlign = align;
text.style.fontSize = size + "pt";
text.style.fontFamily = font;
text.style.color = color;
text.style.backgroundColor = bgcolor;
switch(align)
{
case 'top':
text.style.top = '0px';
break;
case 'middle':
text.style.top = ((window.innerHeight - text.clientHeight) / 2)
+ 'px';
break;
case 'bottom':
text.style.top = (window.innerHeight - text.clientHeight)
+ 'px';
break;
}
}
"""
CSS = """

View File

@ -85,7 +85,7 @@ class AlertsManager(QtCore.QObject):
return
text = self.alertList.pop(0)
alertTab = self.parent().settings_tab
self.parent().liveController.display.alert(text)
self.parent().liveController.display.alert(text, alertTab.location)
# Check to see if we have a timer running.
if self.timer_id == 0:
self.timer_id = self.startTimer(int(alertTab.timeout) * 1000)
@ -100,7 +100,8 @@ class AlertsManager(QtCore.QObject):
"""
log.debug(u'timer event')
if event.timerId() == self.timer_id:
self.parent().liveController.display.alert(u'')
alertTab = self.parent().settings_tab
self.parent().liveController.display.alert(u'', alertTab.location)
self.killTimer(self.timer_id)
self.timer_id = 0
self.generateAlert()

View File

@ -28,6 +28,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate, Receiver
from openlp.core.ui import AlertLocation
from openlp.core.lib.ui import UiStrings, create_valign_combo
class AlertsTab(SettingsTab):
@ -159,7 +160,7 @@ class AlertsTab(SettingsTab):
self.font_face = unicode(settings.value(
u'font face', QtCore.QVariant(QtGui.QFont().family())).toString())
self.location = settings.value(
u'location', QtCore.QVariant(1)).toInt()[0]
u'location', QtCore.QVariant(AlertLocation.Bottom)).toInt()[0]
settings.endGroup()
self.fontSizeSpinBox.setValue(self.font_size)
self.timeoutSpinBox.setValue(self.timeout)

View File

@ -46,5 +46,4 @@ class MediaOpenForm(QtGui.QDialog, Ui_MediaOpenDialog):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
# Connecting signals and slots
# QtCore.QObject.connect(self.previewButton,
# QtCore.SIGNAL(u'pressed()'), self.onPreviewButtonPressed)

View File

@ -33,7 +33,8 @@ from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon
from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \
SettingsManager, translate, check_item_selected, Receiver, MediaType
SettingsManager, translate, check_item_selected, Receiver, MediaType, \
ServiceItem, build_html
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
media_item_combo_box
from openlp.core.ui import Controller, Display
@ -69,6 +70,15 @@ class MediaMediaItem(MediaManagerItem):
False)
self.mediaController.previewDisplay = Display(self.mediaController, \
False, self.mediaController)
self.mediaController.previewDisplay.setGeometry(
QtCore.QRect(0, 0, 300, 300))
self.mediaController.previewDisplay.screen = \
{u'size':self.mediaController.previewDisplay.geometry()}
self.mediaController.previewDisplay.setup()
serviceItem = ServiceItem()
self.mediaController.previewDisplay.webView.setHtml(build_html( \
serviceItem, self.mediaController.previewDisplay.screen, None, \
False, None))
self.mediaController.previewDisplay.setup()
self.plugin.mediaController.setup_display( \
self.mediaController.previewDisplay)
@ -100,11 +110,6 @@ class MediaMediaItem(MediaManagerItem):
def requiredIcons(self):
MediaManagerItem.requiredIcons(self)
self.hasFileIcon = True
apiSettings = str(QtCore.QSettings().value(u'media/apis',
QtCore.QVariant(u'Webkit')).toString())
usedAPIs = apiSettings.split(u',')
for title in usedAPIs:
api = self.plugin.mediaController.APIs[title]
self.hasNewIcon = False
self.hasEditIcon = False
@ -148,7 +153,7 @@ class MediaMediaItem(MediaManagerItem):
self.mediaOpenForm.exec_()
def overrideApiChanged(self, index):
Receiver.send_message(u'media_overrideApi', \
Receiver.send_message(u'media_override_api', \
u'%s' % self.displayTypeComboBox.currentText())
def onResetClick(self):
@ -244,7 +249,7 @@ class MediaMediaItem(MediaManagerItem):
"""
self.displayTypeComboBox.clear()
apiSettings = str(QtCore.QSettings().value(u'media/apis',
QtCore.QVariant(u'Webkit')).toString())
QtCore.QVariant(u'webkit')).toString())
usedAPIs = apiSettings.split(u',')
for title in usedAPIs:
# load the drop down selection

View File

@ -34,8 +34,8 @@ class MediaTab(SettingsTab):
"""
MediaTab is the Media settings tab in the settings dialog.
"""
def __init__(self, parent, title, visible_title, apis, icon_path):
self.apis = apis
def __init__(self, parent, title, visible_title, media_apis, icon_path):
self.media_apis = media_apis
SettingsTab.__init__(self, parent, title, visible_title, icon_path)
def setupUi(self):
@ -46,8 +46,8 @@ class MediaTab(SettingsTab):
self.mediaApiLayout = QtGui.QVBoxLayout(self.mediaAPIGroupBox)
self.mediaApiLayout.setObjectName(u'mediaApiLayout')
self.ApiCheckBoxes = {}
for key in self.apis:
api = self.apis[key]
for key in self.media_apis:
api = self.media_apis[key]
checkbox = QtGui.QCheckBox(self.mediaAPIGroupBox)
checkbox.setEnabled(api.available)
checkbox.setObjectName(api.name + u'CheckBox')
@ -98,8 +98,8 @@ class MediaTab(SettingsTab):
self.leftLayout.addWidget(self.AdvancedGroupBox)
self.leftLayout.addStretch()
self.rightLayout.addStretch()
for key in self.apis:
api = self.apis[key]
for key in self.media_apis:
api = self.media_apis[key]
checkbox = self.ApiCheckBoxes[api.name]
QtCore.QObject.connect(checkbox,
QtCore.SIGNAL(u'stateChanged(int)'),
@ -112,8 +112,8 @@ class MediaTab(SettingsTab):
def retranslateUi(self):
self.mediaAPIGroupBox.setTitle(
translate('MediaPlugin.MediaTab', 'Available Media APIs'))
for key in self.apis:
api = self.apis[key]
for key in self.media_apis:
api = self.media_apis[key]
checkbox = self.ApiCheckBoxes[api.name]
if api.available:
checkbox.setText(api.name)
@ -166,9 +166,9 @@ class MediaTab(SettingsTab):
def load(self):
self.usedAPIs = QtCore.QSettings().value(
self.settingsSection + u'/apis',
QtCore.QVariant(u'Webkit')).toString().split(u',')
for key in self.apis:
api = self.apis[key]
QtCore.QVariant(u'webkit')).toString().split(u',')
for key in self.media_apis:
api = self.media_apis[key]
checkbox = self.ApiCheckBoxes[api.name]
if api.available and api.name in self.usedAPIs:
checkbox.setChecked(True)
@ -182,7 +182,7 @@ class MediaTab(SettingsTab):
api_string_changed = False
oldApiString = QtCore.QSettings().value(
self.settingsSection + u'/apis',
QtCore.QVariant(u'Webkit')).toString()
QtCore.QVariant(u'webkit')).toString()
newApiString = self.usedAPIs.join(u',')
if oldApiString != newApiString:
# clean old Media stuff

View File

@ -59,7 +59,7 @@ class MediaPlugin(Plugin):
"""
visible_name = self.getString(StringContent.VisibleName)
return MediaTab(parent, self.name, visible_name[u'title'],
self.mediaController.APIs, self.icon_path)
self.mediaController.mediaApis, self.icon_path)
def about(self):
about_text = translate('MediaPlugin', '<strong>Media Plugin</strong>'

View File

@ -419,8 +419,7 @@ class SongMediaItem(MediaManagerItem):
item_id = (self.editItem.data(QtCore.Qt.UserRole)).toInt()[0]
old_song = self.plugin.manager.get_object(Song, item_id)
song_xml = self.openLyrics.song_to_xml(old_song)
new_song_id = self.openLyrics.xml_to_song(song_xml)
new_song = self.plugin.manager.get_object(Song, new_song_id)
new_song = self.openLyrics.xml_to_song(song_xml)
new_song.title = u'%s <%s>' % (new_song.title,
translate('SongsPlugin.MediaItem', 'copy',
'For song cloning'))

View File

@ -78,30 +78,35 @@ class OpenLP1SongImport(SongImport):
connection = sqlite.connect(self.importSource, mode=0444,
encoding=(encoding, 'replace'))
cursor = connection.cursor()
# Determine if we're using a new or an old DB.
# Determine if the db supports linking audio to songs.
cursor.execute(u'SELECT name FROM sqlite_master '
u'WHERE type = \'table\' AND name = \'tracks\'')
new_db = len(cursor.fetchall()) > 0
db_has_tracks = len(cursor.fetchall()) > 0
# Determine if the db contains theme information.
cursor.execute(u'SELECT name FROM sqlite_master '
u'WHERE type = \'table\' AND name = \'settings\'')
db_has_themes = len(cursor.fetchall()) > 0
# "cache" our list of authors.
cursor.execute(u'-- types int, unicode')
cursor.execute(u'SELECT authorid, authorname FROM authors')
authors = cursor.fetchall()
if new_db:
if db_has_tracks:
# "cache" our list of tracks.
cursor.execute(u'-- types int, unicode')
cursor.execute(u'SELECT trackid, fulltrackname FROM tracks')
tracks = cursor.fetchall()
# "cache" our list of themes.
cursor.execute(u'-- types int, unicode')
cursor.execute(u'SELECT settingsid, settingsname FROM settings')
themes = {}
for theme_id, theme_name in cursor.fetchall():
if theme_name in self.availableThemes:
themes[theme_id] = theme_name
if db_has_themes:
# "cache" our list of themes.
themes = {}
cursor.execute(u'-- types int, unicode')
cursor.execute(u'SELECT settingsid, settingsname FROM settings')
for theme_id, theme_name in cursor.fetchall():
if theme_name in self.availableThemes:
themes[theme_id] = theme_name
# Import the songs.
cursor.execute(u'-- types int, unicode, unicode, unicode, int')
cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS lyrics, '
u'copyrightinfo, settingsid FROM songs')
cursor.execute(u'-- types int, unicode, unicode, unicode')
cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS ' \
u'lyrics, copyrightinfo FROM songs')
songs = cursor.fetchall()
self.importWizard.progressBar.setMaximum(len(songs))
for song in songs:
@ -112,8 +117,13 @@ class OpenLP1SongImport(SongImport):
self.title = song[1]
lyrics = song[2].replace(u'\r\n', u'\n')
self.addCopyright(song[3])
if themes.has_key(song[4]):
self.themeName = themes[song[4]]
if db_has_themes:
cursor.execute(u'-- types int')
cursor.execute(
u'SELECT settingsid FROM songs WHERE songid = %s' % song_id)
theme_id = cursor.fetchone()[0]
if themes.has_key(theme_id):
self.themeName = themes[theme_id]
verses = lyrics.split(u'\n\n')
for verse in verses:
if verse.strip():
@ -131,7 +141,7 @@ class OpenLP1SongImport(SongImport):
break
if self.stopImportFlag:
break
if new_db:
if db_has_tracks:
cursor.execute(u'-- types int, int')
cursor.execute(u'SELECT trackid, listindex '
u'FROM songtracks '

View File

@ -65,7 +65,7 @@ class OooImport(SongImport):
if not isinstance(self.importSource, list):
return
try:
self.start_ooo()
self.startOoo()
except NoConnectException as exc:
self.logError(
self.importSource[0],
@ -145,7 +145,7 @@ class OooImport(SongImport):
process.waitForStarted()
self.processStarted = True
except:
log.exception("start_ooo_process failed")
log.exception("startOooProcess failed")
def openOooFile(self, filepath):
"""
@ -171,7 +171,7 @@ class OooImport(SongImport):
self.importWizard.incrementProgressBar(
u'Processing file ' + filepath, 0)
except AttributeError:
log.exception("open_ooo_file failed: %s", url)
log.exception("openOooFile failed: %s", url)
return
def closeOooFile(self):

View File

@ -25,6 +25,6 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
hiddenimports = ['openlp.plugins.presentations.lib.impresscontroller',
'openlp.plugins.presentations.lib.powerpointcontroller',
'openlp.plugins.presentations.lib.pptviewcontroller']
hiddenimports = ['openlp.core.ui.media.phononapi',
'openlp.core.ui.media.vlcapi',
'openlp.core.ui.media.webkitapi']

View File

@ -67,7 +67,7 @@ Name: quicklaunchicon; Description: {cm:CreateQuickLaunchIcon}; GroupDescription
Source: ..\..\dist\OpenLP\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs
; DLL used to check if the target program is running at install time
Source: psvince.dll; flags: dontcopy
; psvince is installed in {app} folder, so it will be loaded at
; psvince is installed in {app} folder, so it will be loaded at
; uninstall time to check if the target program is running
Source: psvince.dll; DestDir: {app}
@ -84,10 +84,16 @@ Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\{#AppName}; Filenam
Filename: {app}\{#AppExeName}; Description: {cm:LaunchProgram,{#AppName}}; Flags: nowait postinstall skipifsilent
[Registry]
Root: HKCR; Subkey: ".osz"; ValueType: string; ValueName: ""; ValueData: "OpenLP"; Flags: uninsdeletevalue
Root: HKCR; Subkey: "OpenLP"; ValueType: string; ValueName: ""; ValueData: "OpenLP Service"; Flags: uninsdeletekey
Root: HKCR; Subkey: "OpenLP\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\OpenLP.exe,0"
Root: HKCR; Subkey: "OpenLP\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\OpenLP.exe"" ""%1"""
Root: HKCR; Subkey: .osz; ValueType: string; ValueName: ; ValueData: OpenLP; Flags: uninsdeletevalue
Root: HKCR; Subkey: OpenLP; ValueType: string; ValueName: ; ValueData: OpenLP Service; Flags: uninsdeletekey
Root: HKCR; Subkey: OpenLP\DefaultIcon; ValueType: string; ValueName: ; ValueData: {app}\OpenLP.exe,0
Root: HKCR; Subkey: OpenLP\shell\open\command; ValueType: string; ValueName: ; ValueData: """{app}\OpenLP.exe"" ""%1"""
[UninstallDelete]
; Remove support directory created when program is run:
Type: filesandordirs; Name: {app}\support
; Remove program directory if empty:
Name: {app}; Type: dirifempty
[Code]
// Function to call psvince.dll at install time
@ -173,4 +179,6 @@ begin
Result := false;
end;
end;
end;
// Unload psvince.dll, otherwise it is not deleted
UnloadDLL(ExpandConstant('{app}\psvince.dll'));
end;

View File

@ -48,10 +48,10 @@ Inno Setup 5
Sphinx
This is used to build the documentation. The documentation trunk must be at
the same directory level as Openlp trunk and named "documentation"
the same directory level as Openlp trunk and named "documentation".
HTML Help Workshop
This is used to create the help file
This is used to create the help file.
PyInstaller
PyInstaller should be a checkout of revision 1470 of trunk, and in a
@ -65,10 +65,6 @@ PyInstaller
http://svn.pyinstaller.org/trunk
Then you need to copy the two hook-*.py files from the "pyinstaller"
subdirectory in OpenLP's "resources" directory into PyInstaller's
"PyInstaller/hooks" directory.
Bazaar
You need the command line "bzr" client installed.
@ -79,7 +75,7 @@ OpenLP
Visual C++ 2008 Express Edition
This is to build pptviewlib.dll, the library for controlling the
PowerPointViewer
PowerPointViewer.
windows-builder.py
This script, of course. It should be in the "scripts" directory of OpenLP.
@ -88,15 +84,25 @@ psvince.dll
This dll is used during the actual install of OpenLP to check if OpenLP is
running on the users machine prior to the setup. If OpenLP is running,
the install will fail. The dll can be obtained from here:
http://www.vincenzo.net/isxkb/index.php?title=PSVince)
http://www.vincenzo.net/isxkb/index.php?title=PSVince)
The dll is presently included in .\\resources\\windows
Mako
Mako Templates for Python. This package is required for building the
remote plugin. It can be installed by going to your
python_directory\scripts\.. and running "easy_install Mako". If you do not
have easy_install, the Mako package can be obtained here:
http://www.makotemplates.org/download.html
http://www.makotemplates.org/download.html
Sqlalchemy Migrate
Required for the data-bases used in OpenLP. The package can be
obtained here:
http://code.google.com/p/sqlalchemy-migrate/
"""
import os
@ -149,6 +155,7 @@ build_path = os.path.join(branch_path, u'build')
dist_path = os.path.join(branch_path, u'dist', u'OpenLP')
pptviewlib_path = os.path.join(source_path, u'plugins', u'presentations',
u'lib', u'pptviewlib')
hooks_path = os.path.join(branch_path , u'resources', u'pyinstaller')
def update_code():
os.chdir(branch_path)
@ -173,7 +180,8 @@ def run_pyinstaller():
pyinstaller = Popen((python_exe, pyi_build,
u'--noconfirm',
u'--windowed',
u'--noupx',
u'--noupx',
u'--additional-hooks-dir', hooks_path,
u'-o', branch_path,
u'-i', win32_icon,
u'-p', branch_path,