This commit is contained in:
Tim Bentley 2010-10-15 15:29:41 +01:00
commit 60c9813772
10 changed files with 272 additions and 51 deletions

View File

@ -0,0 +1,22 @@
.. OpenLP documentation master file, created by
sphinx-quickstart on Thu Sep 30 21:24:54 2010.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to OpenLP's documentation
==================================
Contents:
.. toctree::
:maxdepth: 2
introduction
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -0,0 +1,46 @@
=============
Introduction
=============
About
-----
OpenLP is an open source lyrics projection application developed specifically
for churches. It is licensed under the GNU Generic Public License, which means
that it is free to use and distribute, and it stays free.
Lyrics Projection
-----------------
OpenLP's purpose is to project the lyrics of songs and Bible verses using a
computer and a data projector. OpenLP also has the ability to project videos,
images, and also play audio. OpenLP also is highly customizable providing users
with the ability to set up a wide variety of themes, including themes with
video backgrounds.
Open Source
-----------
OpenLP is open source software. This means that the source code (the
programming instructions the developers write) is open to anyone who wants to
look at it. This gives you, the end user, a few freedoms.
From a developer's perspective, it gives you the freedom to inspect the code
and make sure that it is not malicious. Also, it gives you the freedom to
change the code and the freedom to "fork" the project and make it your own.
For end users open source software gives you the freedom to use software as
you wish. You are not required to pay for the software and you are free to
make copies and distribute it to anyone you want.
GNU General Public License
--------------------------
The GNU General Public License was specifically chosen because it ensures the
above mentioned freedoms. It specifically states that you are not allowed
to charge for the software, and that you have to distribute the source code as
well.
You can find a copy of the GNU General Public License from the Help menu
selecting about OpenLP or on-line
at: http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt

View File

@ -55,14 +55,17 @@ body {
background-color: black;
display: none;
}
#image {
#bgimage {
z-index:1;
}
#video1 {
#image {
z-index:2;
}
#video1 {
z-index:3;
}
#video2 {
z-index:2;
z-index:3;
}
#alert {
position: absolute;
@ -73,7 +76,7 @@ body {
}
#footer {
position: absolute;
z-index:5;
z-index:6;
%s
}
/* lyric css */
@ -112,7 +115,7 @@ body {
vid2.volume = volume;
}
switch(state){
case 'init':
case 'init':
vid.src = path;
vid2.src = path;
if(loop == null) loop = false;
@ -294,7 +297,8 @@ body {
</script>
</head>
<body>
<img id="image" class="size" %s />
<img id="bgimage" class="size" %s />
<img id="image" class="size" style="display:none" />
<video id="video1" class="size" style="visibility:hidden" autobuffer preload>
</video>
<video id="video2" class="size" style="visibility:hidden" autobuffer preload>
@ -397,7 +401,7 @@ def build_lyrics_css(item, webkitvers):
"""
style = """
.lyricstable {
z-index:4;
z-index:5;
position: absolute;
display: table;
%s

View File

@ -155,15 +155,15 @@ class ServiceItem(object):
line_break = True
if self.is_capable(ItemCapabilities.NoLineBreaks):
line_break = False
theme = None
if self.theme:
theme = self.theme
self.main, self.footer = \
self.render_manager.set_override_theme(theme, useOverride)
self.bg_image_bytes = self.render_manager.renderer.bg_image_bytes
self.themedata = self.render_manager.renderer._theme
if self.service_item_type == ServiceItemType.Text:
log.debug(u'Formatting slides')
theme = None
if self.theme:
theme = self.theme
self.main, self.footer = \
self.render_manager.set_override_theme(theme, useOverride)
self.bg_image_bytes = self.render_manager.renderer.bg_image_bytes
self.themedata = self.render_manager.renderer._theme
for slide in self._raw_frames:
before = time.time()
formatted = self.render_manager \
@ -176,7 +176,6 @@ class ServiceItem(object):
u'verseTag': slide[u'verseTag'] })
log.log(15, u'Formatting took %4s' % (time.time() - before))
elif self.service_item_type == ServiceItemType.Image:
self.themedata = self.render_manager.global_theme_data
for slide in self._raw_frames:
slide[u'image'] = resize_image(slide[u'image'],
self.render_manager.width, self.render_manager.height)

View File

@ -114,21 +114,23 @@ class MainDisplay(DisplayWidget):
"""
log.debug(u'Setup live = %s for %s ' % (self.isLive,
self.screens.monitor_number))
self.usePhonon = QtCore.QSettings().value(
u'media/use phonon', QtCore.QVariant(True)).toBool()
self.phononActive = False
self.screen = self.screens.current
self.setVisible(False)
self.setGeometry(self.screen[u'size'])
try:
self.webView = QtWebKit.QGraphicsWebView()
self.scene = QtGui.QGraphicsScene(self)
self.setScene(self.scene)
self.scene.addItem(self.webView)
self.webView.setGeometry(QtCore.QRectF(0, 0,
self.screen[u'size'].width(), self.screen[u'size'].height()))
except AttributeError:
# QGraphicsWebView a recent addition, so fall back to QWebView
self.webView = QtWebKit.QWebView(self)
self.webView.setGeometry(0, 0,
self.screen[u'size'].width(), self.screen[u'size'].height())
self.videoWidget = Phonon.VideoWidget(self)
self.videoWidget.setVisible(False)
self.videoWidget.setGeometry(QtCore.QRect(0, 0,
self.screen[u'size'].width(), self.screen[u'size'].height()))
self.mediaObject = Phonon.MediaObject(self)
self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject)
Phonon.createPath(self.mediaObject, self.videoWidget)
Phonon.createPath(self.mediaObject, self.audio)
self.webView = QtWebKit.QWebView(self)
self.webView.setGeometry(0, 0,
self.screen[u'size'].width(), self.screen[u'size'].height())
self.page = self.webView.page()
self.frame = self.page.mainFrame()
QtCore.QObject.connect(self.webView,
@ -199,7 +201,7 @@ class MainDisplay(DisplayWidget):
"""
log.debug(u'alert')
if self.height() != self.screen[u'size'].height() \
or not self.isVisible():
or not self.isVisible() or self.videoWidget.isVisible():
shrink = True
else:
shrink = False
@ -208,12 +210,17 @@ class MainDisplay(DisplayWidget):
u'top' if shrink else u'')
height = self.frame.evaluateJavaScript(js)
if shrink:
if text:
self.resize(self.width(), int(height.toString()))
self.setVisible(True)
if self.phononActive:
shrinkItem = self.webView
else:
self.setGeometry(self.screen[u'size'])
self.setVisible(False)
shrinkItem = self
if text:
shrinkItem.resize(self.width(), int(height.toString()))
shrinkItem.setVisible(True)
else:
shrinkItem.setVisible(False)
shrinkItem.resize(self.screen[u'size'].width(),
self.screen[u'size'].height())
def image(self, image):
"""
@ -259,14 +266,24 @@ class MainDisplay(DisplayWidget):
Used after Video plugin has changed the background
"""
log.debug(u'resetVideo')
self.frame.evaluateJavaScript(u'show_video("close");')
if self.phononActive:
self.mediaObject.stop()
self.mediaObject.clearQueue()
self.webView.setVisible(True)
self.videoWidget.setVisible(False)
self.phononActive = False
else:
self.frame.evaluateJavaScript(u'show_video("close");')
def videoPlay(self):
"""
Responds to the request to play a loaded video
"""
log.debug(u'videoPlay')
self.frame.evaluateJavaScript(u'show_video("play");')
if self.phononActive:
self.mediaObject.play()
else:
self.frame.evaluateJavaScript(u'show_video("play");')
# show screen
if self.isLive:
self.setVisible(True)
@ -276,32 +293,54 @@ class MainDisplay(DisplayWidget):
Responds to the request to pause a loaded video
"""
log.debug(u'videoPause')
self.frame.evaluateJavaScript(u'show_video("pause");')
if self.phononActive:
self.mediaObject.pause()
else:
self.frame.evaluateJavaScript(u'show_video("pause");')
def videoStop(self):
"""
Responds to the request to stop a loaded video
"""
log.debug(u'videoStop')
self.frame.evaluateJavaScript(u'show_video("stop");')
if self.phononActive:
self.mediaObject.stop()
else:
self.frame.evaluateJavaScript(u'show_video("stop");')
def videoVolume(self, volume):
"""
Changes the volume of a running video
"""
log.debug(u'videoVolume %d' % volume)
self.frame.evaluateJavaScript(u'show_video(null, null, %s);' %
str(float(volume)/float(10)))
vol = float(volume)/float(10)
if self.phononActive:
self.audio.setVolume(vol)
else:
self.frame.evaluateJavaScript(u'show_video(null, null, %s);' %
str(vol))
def video(self, videoPath, volume):
def video(self, videoPath, volume, isBackground=False):
"""
Loads and starts a video to run with the option of sound
"""
log.debug(u'video')
self.loaded = True
js = u'show_video("init", "%s", %s, true); show_video("play");' % \
(videoPath.replace(u'\\', u'\\\\'), str(float(volume)/float(10)))
self.frame.evaluateJavaScript(js)
vol = float(volume)/float(10)
if isBackground or not self.usePhonon:
js = u'show_video("init", "%s", %s, true); show_video("play");' % \
(videoPath.replace(u'\\', u'\\\\'), \
str(vol))
self.frame.evaluateJavaScript(js)
else:
self.phononActive = True
self.mediaObject.stop()
self.mediaObject.clearQueue()
self.mediaObject.setCurrentSource(Phonon.MediaSource(videoPath))
self.mediaObject.play()
self.webView.setVisible(False)
self.videoWidget.setVisible(True)
self.audio.setVolume(vol)
return self.preview()
def isLoaded(self):
@ -382,6 +421,8 @@ class MainDisplay(DisplayWidget):
Store the images so they can be replaced when required
"""
log.debug(u'hideDisplay mode = %d', mode)
if self.phononActive:
self.videoPause()
if mode == HideMode.Screen:
self.frame.evaluateJavaScript(u'show_blank("desktop");')
self.setVisible(False)
@ -389,8 +430,11 @@ class MainDisplay(DisplayWidget):
self.frame.evaluateJavaScript(u'show_blank("black");')
else:
self.frame.evaluateJavaScript(u'show_blank("theme");')
if mode != HideMode.Screen and self.isHidden():
self.setVisible(True)
if mode != HideMode.Screen:
if self.isHidden():
self.setVisible(True)
if self.phononActive:
self.webView.setVisible(True)
self.hide_mode = mode
def showDisplay(self):
@ -403,6 +447,9 @@ class MainDisplay(DisplayWidget):
self.frame.evaluateJavaScript('show_blank("show");')
if self.isHidden():
self.setVisible(True)
if self.phononActive:
self.webView.setVisible(False)
self.videoPlay()
# Trigger actions when display is active again
Receiver.send_message(u'maindisplay_active')
self.hide_mode = None
@ -484,3 +531,4 @@ class AudioPlayer(QtCore.QObject):
"""
log.debug(u'AudioPlayer Reached end of media playlist')
self.mediaObject.clearQueue()

View File

@ -543,7 +543,7 @@ class SlideController(QtGui.QWidget):
Receiver.send_message(u'%s_stop' %
self.serviceItem.name.lower(), [serviceItem, self.isLive])
if self.serviceItem.is_media():
self.onMediaStop()
self.onMediaClose()
if self.isLive:
blanked = self.BlankScreen.isChecked()
else:
@ -931,14 +931,13 @@ class SlideController(QtGui.QWidget):
Respond to the arrival of a media service item
"""
log.debug(u'SlideController onMediaStart')
file = os.path.join(item.get_frame_path(), item.get_frame_title())
if self.isLive:
file = os.path.join(item.get_frame_path(), item.get_frame_title())
self.display.video(file, self.volume)
self.volumeSlider.setValue(self.volume)
else:
self.mediaObject.stop()
self.mediaObject.clearQueue()
file = os.path.join(item.get_frame_path(), item.get_frame_title())
self.mediaObject.setCurrentSource(Phonon.MediaSource(file))
self.seekSlider.setMediaObject(self.mediaObject)
self.seekSlider.show()
@ -986,3 +985,18 @@ class SlideController(QtGui.QWidget):
self.video.hide()
self.SlidePreview.clear()
self.SlidePreview.show()
def onMediaClose(self):
"""
Respond to a request to close the Video
"""
log.debug(u'SlideController onMediaStop')
if self.isLive:
self.display.resetVideo()
else:
self.mediaObject.stop()
self.mediaObject.clearQueue()
self.video.hide()
self.SlidePreview.clear()
self.SlidePreview.show()

View File

@ -25,5 +25,6 @@
###############################################################################
from mediaitem import MediaMediaItem
from mediatab import MediaTab
__all__ = ['MediaMediaItem']

View File

@ -113,7 +113,7 @@ class MediaMediaItem(MediaManagerItem):
'You must select a media file to replace the background with.')):
item = self.listView.currentItem()
filename = unicode(item.data(QtCore.Qt.UserRole).toString())
self.parent.liveController.display.video(filename, 0)
self.parent.liveController.display.video(filename, 0, True)
self.resetButton.setVisible(True)
def generateSlideData(self, service_item, item=None):

View File

@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, 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 #
###############################################################################
from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate, Receiver
class MediaTab(SettingsTab):
"""
MediaTab is the Media settings tab in the settings dialog.
"""
def __init__(self, title):
SettingsTab.__init__(self, title)
def setupUi(self):
self.setObjectName(u'MediaTab')
self.tabTitleVisible = translate('MediaPlugin.MediaTab', 'Media')
self.mediaLayout = QtGui.QFormLayout(self)
self.mediaLayout.setSpacing(8)
self.mediaLayout.setMargin(8)
self.mediaLayout.setObjectName(u'mediaLayout')
self.mediaModeGroupBox = QtGui.QGroupBox(self)
self.mediaModeGroupBox.setObjectName(u'mediaModeGroupBox')
self.mediaModeLayout = QtGui.QVBoxLayout(self.mediaModeGroupBox)
self.mediaModeLayout.setSpacing(8)
self.mediaModeLayout.setMargin(8)
self.mediaModeLayout.setObjectName(u'mediaModeLayout')
self.usePhononCheckBox = QtGui.QCheckBox(self.mediaModeGroupBox)
self.usePhononCheckBox.setObjectName(u'usePhononCheckBox')
self.mediaModeLayout.addWidget(self.usePhononCheckBox)
self.mediaLayout.setWidget(
0, QtGui.QFormLayout.LabelRole, self.mediaModeGroupBox)
QtCore.QObject.connect(self.usePhononCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onUsePhononCheckBoxChanged)
def retranslateUi(self):
self.mediaModeGroupBox.setTitle(translate('MediaPlugin.MediaTab',
'Media Display'))
self.usePhononCheckBox.setText(
translate('MediaPlugin.MediaTab', 'Use Phonon for video playback'))
def onUsePhononCheckBoxChanged(self, check_state):
self.usePhonon = (check_state == QtCore.Qt.Checked)
self.usePhononChanged = True
def load(self):
self.usePhonon = QtCore.QSettings().value(
self.settingsSection + u'/use phonon',
QtCore.QVariant(True)).toBool()
self.usePhononCheckBox.setChecked(self.usePhonon)
def save(self):
oldUsePhonon = QtCore.QSettings().value(
u'media/use phonon', QtCore.QVariant(True)).toBool()
if oldUsePhonon != self.usePhonon:
QtCore.QSettings().setValue(self.settingsSection + u'/use phonon',
QtCore.QVariant(self.usePhonon))
Receiver.send_message(u'config_screen_changed')

View File

@ -29,7 +29,7 @@ import logging
from PyQt4.phonon import Phonon
from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.plugins.media.lib import MediaMediaItem
from openlp.plugins.media.lib import MediaMediaItem, MediaTab
log = logging.getLogger(__name__)
@ -68,6 +68,9 @@ class MediaPlugin(Plugin):
type = u''
return list, type
def getSettingsTab(self):
return MediaTab(self.name)
def getMediaManagerItem(self):
# Create the MediaManagerItem object
return MediaMediaItem(self, self, self.icon)
@ -132,4 +135,4 @@ class MediaPlugin(Plugin):
u'title': translate('MediaPlugin', 'Service'),
u'tooltip': translate('MediaPlugin',
'Add the selected Media to the service')
}
}