2010-07-03 19:02:36 +00:00
# -*- 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, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# 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 os
from PyQt4 import QtCore , QtGui , QtWebKit
from PyQt4 . phonon import Phonon
2010-07-17 11:00:36 +00:00
from openlp . core . lib import Receiver , resize_image , build_html , ServiceItem , image_to_byte
2010-07-03 19:02:36 +00:00
from openlp . core . ui import HideMode
log = logging . getLogger ( __name__ )
#http://www.steveheffernan.com/html5-video-player/demo-video-player.html
2010-07-20 05:16:06 +00:00
## QtCore.QObject.connect(Receiver.get_receiver(),
## QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay)
## QtCore.QObject.connect(Receiver.get_receiver(),
## QtCore.SIGNAL(u'maindisplay_show'), self.showDisplay)
## QtCore.QObject.connect(Receiver.get_receiver(),
## QtCore.SIGNAL(u'videodisplay_start'), self.onStartVideo)
## QtCore.QObject.connect(Receiver.get_receiver(),
## QtCore.SIGNAL(u'videodisplay_stop'), self.onStopVideo)
## QtCore.QObject.connect(Receiver.get_receiver(),
## QtCore.SIGNAL(u'config_updated'), self.setup)
2010-07-17 08:59:15 +00:00
2010-07-03 19:02:36 +00:00
class DisplayWidget ( QtGui . QGraphicsView ) :
"""
Customised version of QTableWidget which can respond to keyboard
events .
"""
2010-07-11 07:45:49 +00:00
log . info ( u ' Display Widget loaded ' )
2010-07-03 19:02:36 +00:00
2010-07-11 15:53:40 +00:00
def __init__ ( self , live , parent = None , name = None ) :
2010-07-11 07:45:49 +00:00
QtGui . QGraphicsView . __init__ ( self )
2010-07-03 19:02:36 +00:00
self . parent = parent
2010-07-11 15:53:40 +00:00
self . live = live
2010-07-23 05:05:34 +00:00
# self.hotkey_map = {
# QtCore.Qt.Key_Return: 'servicemanager_next_item',
# QtCore.Qt.Key_Space: 'slidecontroller_live_next_noloop',
# QtCore.Qt.Key_Enter: 'slidecontroller_live_next_noloop',
# QtCore.Qt.Key_0: 'servicemanager_next_item',
# QtCore.Qt.Key_Backspace: 'slidecontroller_live_previous_noloop'}
2010-07-03 19:02:36 +00:00
def keyPressEvent ( self , event ) :
2010-07-23 05:05:34 +00:00
# Key events only needed for live
if not self . live :
2010-07-11 15:53:40 +00:00
return
2010-07-23 05:05:34 +00:00
# if isinstance(event, QtGui.QKeyEvent):
# #here accept the event and do something
# if event.key() == QtCore.Qt.Key_Up:
# Receiver.send_message(u'slidecontroller_live_previous')
# event.accept()
# elif event.key() == QtCore.Qt.Key_Down:
# Receiver.send_message(u'slidecontroller_live_next')
# event.accept()
# elif event.key() == QtCore.Qt.Key_PageUp:
# Receiver.send_message(u'slidecontroller_live_first')
# event.accept()
# elif event.key() == QtCore.Qt.Key_PageDown:
# Receiver.send_message(u'slidecontroller_live_last')
# event.accept()
# elif event.key() in self.hotkey_map:
# Receiver.send_message(self.hotkey_map[event.key()])
# event.accept()
# elif event.key() == QtCore.Qt.Key_Escape:
# self.resetDisplay()
# event.accept()
# event.ignore()
# else:
# event.ignore()
2010-07-03 19:02:36 +00:00
2010-07-23 05:05:34 +00:00
class MainDisplay ( DisplayWidget ) :
2010-07-03 19:02:36 +00:00
2010-07-11 15:53:40 +00:00
def __init__ ( self , parent , screens , live ) :
DisplayWidget . __init__ ( self , live , parent = None )
2010-07-12 16:49:38 +00:00
self . parent = parent
2010-07-11 11:38:09 +00:00
self . screens = screens
2010-07-17 08:59:15 +00:00
self . isLive = live
2010-07-11 11:38:09 +00:00
self . setWindowTitle ( u ' OpenLP Display ' )
self . setWindowFlags ( QtCore . Qt . FramelessWindowHint |
QtCore . Qt . WindowStaysOnTopHint )
2010-07-17 11:00:36 +00:00
2010-07-11 07:45:49 +00:00
self . currvideo = False
self . video1 = " c: \\ users \\ jonathan \\ Desktop \\ Wildlife.wmv "
self . video2 = " c: \\ users \\ jonathan \\ Desktop \\ movie.ogg "
self . currslide = False
self . slide1 = " <sup>[1:1]</sup> In the beginning God created the heavens and the earth.<br/><br/><sup> [1:2]</sup> Now the earth was formless and empty, darkness was over the surface of the deep, and the Spirit of God was hovering over the waters.<br/><br/><sup>[1:3]</sup> And God said, \" Let there be light, \" and there was light.<br/><br/><sup>[1:4]</sup> God saw that the light was good, and he separated the light from the darkness.<br/><br/> "
self . slide2 = " <br /><br />This is the chorus<br />Blah Blah Blah<br />Blah Blah Blah<br />Blah Blah Blah<br />Blah Blah Blah<br />Blah Blah Blah "
self . alerttext = " <p>Red Alert! Raise Shields!</p> "
2010-07-23 05:05:34 +00:00
def setup ( self ) :
log . debug ( u ' Setup %s for %s ' % (
self . screens , self . screens . monitor_number ) )
self . screen = self . screens . current
self . setVisible ( False )
self . setGeometry ( self . screen [ u ' size ' ] )
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 ,
QtCore . SIGNAL ( u ' loadFinished(bool) ' ) , self . loaded )
self . frame . setScrollBarPolicy ( QtCore . Qt . Vertical ,
QtCore . Qt . ScrollBarAlwaysOff )
self . frame . setScrollBarPolicy ( QtCore . Qt . Horizontal ,
QtCore . Qt . ScrollBarAlwaysOff )
if self . isLive :
#Build the initial frame.
initialFrame = QtGui . QImage (
self . screens . current [ u ' size ' ] . width ( ) ,
self . screens . current [ u ' size ' ] . height ( ) ,
QtGui . QImage . Format_ARGB32_Premultiplied )
splash_image = QtGui . QImage ( u ' :/graphics/openlp-splash-screen.png ' )
painter_image = QtGui . QPainter ( )
painter_image . begin ( initialFrame )
painter_image . fillRect ( initialFrame . rect ( ) , QtCore . Qt . white )
painter_image . drawImage (
( self . screens . current [ u ' size ' ] . width ( ) - splash_image . width ( ) ) / 2 ,
( self . screens . current [ u ' size ' ] . height ( ) - splash_image . height ( ) ) / 2 ,
splash_image )
serviceItem = ServiceItem ( )
serviceItem . bg_frame = initialFrame
self . webView . setHtml ( build_html ( serviceItem , self . screen , None ) )
self . show ( )
2010-07-11 07:45:49 +00:00
def next ( self ) :
if self . currslide :
self . frame . evaluateJavaScript ( " startfade( ' " + self . slide2 + " ' ) " )
#self.frame.findFirstElement('div#lyrics').setInnerXml(self.slide2)
2010-07-03 19:02:36 +00:00
else :
2010-07-11 07:45:49 +00:00
self . frame . evaluateJavaScript ( " startfade( ' " + self . slide1 + " ' ) " )
#self.frame.findFirstElement('div#lyrics').setInnerXml(self.slide1)
self . currslide = not self . currslide
def text ( self , slide ) :
2010-07-12 16:49:38 +00:00
print slide
2010-07-11 16:02:20 +00:00
self . frame . findFirstElement ( ' div#lyrics ' ) . setInnerXml ( slide )
2010-07-17 08:59:15 +00:00
return self . preview ( )
2010-07-11 07:45:49 +00:00
def alert ( self ) :
self . frame . findFirstElement ( ' div#alert ' ) . setInnerXml ( self . alerttext )
2010-07-17 11:00:36 +00:00
def image ( self , image ) :
2010-07-19 20:05:25 +00:00
image = resize_image ( image , self . screen [ u ' size ' ] . width ( ) ,
self . screen [ u ' size ' ] . height ( ) )
2010-07-11 07:45:49 +00:00
self . frame . evaluateJavaScript (
" document.getElementById( ' video ' ).style.visibility = ' hidden ' " )
self . frame . evaluateJavaScript (
" document.getElementById( ' image ' ).style.visibility = ' visible ' " )
2010-07-17 11:00:36 +00:00
self . frame . findFirstElement ( ' img ' ) . setAttribute (
' src ' , unicode ( ' data:image/png;base64, %s ' % image_to_byte ( image ) ) )
2010-07-11 07:45:49 +00:00
2010-07-19 20:05:25 +00:00
def reset ( self ) :
self . frame . findFirstElement ( ' img ' ) . setAttribute (
' src ' , unicode ( ' data:image/png;base64, %s ' % image_to_byte ( self . serviceItem . bg_frame ) ) )
2010-07-11 07:45:49 +00:00
def video ( self , videoPath , noSound = False ) :
if self . currimage :
self . frame . findFirstElement ( ' video ' ) . setAttribute ( ' src ' , videoPath )
self . frame . evaluateJavaScript (
" document.getElementById( ' video ' ).style.visibility = ' visible ' " )
self . frame . evaluateJavaScript (
" document.getElementById( ' image ' ).style.visibility = ' hidden ' " )
self . frame . evaluateJavaScript ( " document.getElementById( ' video ' ).play() " )
self . currimage = not self . currimage
2010-07-17 10:25:52 +00:00
def loaded ( self ) :
self . loaded = True
2010-07-17 08:59:15 +00:00
def preview ( self ) :
2010-07-17 11:00:36 +00:00
# Wait for the webview to update before geting the preview.
# Important otherwise first preview will miss the background !
2010-07-17 10:25:52 +00:00
while not self . loaded :
Receiver . send_message ( u ' openlp_process_events ' )
2010-07-11 15:53:40 +00:00
preview = QtGui . QImage ( self . screen [ u ' size ' ] . width ( ) ,
self . screen [ u ' size ' ] . height ( ) ,
QtGui . QImage . Format_ARGB32_Premultiplied )
2010-07-11 07:45:49 +00:00
painter = QtGui . QPainter ( preview )
painter . setRenderHint ( QtGui . QPainter . Antialiasing )
self . frame . render ( painter )
painter . end ( )
2010-07-17 10:25:52 +00:00
if log . isEnabledFor ( logging . DEBUG ) :
#save preview for debugging
preview . save ( " temp.png " , " png " )
2010-07-11 07:45:49 +00:00
return preview
2010-07-17 08:59:15 +00:00
def buildHtml ( self , serviceItem ) :
"""
Store the serviceItem and build the new HTML from it . Add the
HTML to the display
"""
2010-07-17 10:25:52 +00:00
self . loaded = False
2010-07-17 08:59:15 +00:00
self . serviceItem = serviceItem
html = build_html ( self . serviceItem , self . screen , None )
2010-07-12 19:36:42 +00:00
self . webView . setHtml ( html )
2010-07-19 18:03:00 +00:00
if serviceItem . footer :
self . frame . findFirstElement ( ' div#footer ' ) . setInnerXml ( serviceItem . foot_text )
2010-07-12 19:36:42 +00:00
2010-07-23 05:05:34 +00:00
def hideDisplay ( self , mode = HideMode . Screen ) :
"""
Hide the display by making all layers transparent
Store the images so they can be replaced when required
"""
log . debug ( u ' hideDisplay mode = %d ' , mode )
#self.displayText.setPixmap(self.transparent)
if mode == HideMode . Screen :
#self.display_image.setPixmap(self.transparent)
self . setVisible ( False )
elif mode == HideMode . Blank :
self . displayBlank . setPixmap (
QtGui . QPixmap . fromImage ( self . blankFrame ) )
else :
if self . parent . renderManager . renderer . bg_frame :
self . displayBlank . setPixmap ( QtGui . QPixmap . fromImage (
self . parent . renderManager . renderer . bg_frame ) )
else :
self . displayBlank . setPixmap (
QtGui . QPixmap . fromImage ( self . blankFrame ) )
if mode != HideMode . Screen and self . isHidden ( ) :
self . setVisible ( True )
def showDisplay ( self , message = u ' ' ) :
"""
Show the stored layers so the screen reappears as it was
originally .
Make the stored images None to release memory .
"""
log . debug ( u ' showDisplay ' )
self . displayBlank . setPixmap ( self . transparent )
if self . isHidden ( ) :
self . setVisible ( True )
#Trigger actions when display is active again
Receiver . send_message ( u ' maindisplay_active ' )
2010-07-03 19:02:36 +00:00
class AudioPlayer ( QtCore . QObject ) :
"""
2010-07-06 21:59:52 +00:00
This Class will play audio only allowing components to work with a
2010-07-11 07:45:49 +00:00
soundtrack independent of the user interface .
2010-07-03 19:02:36 +00:00
"""
log . info ( u ' AudioPlayer Loaded ' )
def __init__ ( self , parent ) :
"""
The constructor for the display form .
` ` parent ` `
The parent widget .
` ` screens ` `
The list of screens .
"""
log . debug ( u ' AudioPlayer Initialisation started ' )
2010-07-06 21:59:52 +00:00
QtCore . QObject . __init__ ( self , parent )
2010-07-03 19:02:36 +00:00
self . message = None
self . mediaObject = Phonon . MediaObject ( )
self . audioObject = Phonon . AudioOutput ( Phonon . VideoCategory )
Phonon . createPath ( self . mediaObject , self . audioObject )
def setup ( self ) :
"""
Sets up the Audio Player for use
"""
log . debug ( u ' AudioPlayer Setup ' )
def close ( self ) :
"""
Shutting down so clean up connections
"""
self . onMediaStop ( )
2010-07-07 14:44:22 +00:00
for path in self . mediaObject . outputPaths ( ) :
2010-07-08 08:14:10 +00:00
path . disconnect ( )
2010-07-03 19:02:36 +00:00
def onMediaQueue ( self , message ) :
"""
Set up a video to play from the serviceitem .
"""
log . debug ( u ' AudioPlayer Queue new media message %s ' % message )
file = os . path . join ( message [ 0 ] . get_frame_path ( ) ,
message [ 0 ] . get_frame_title ( ) )
self . mediaObject . setCurrentSource ( Phonon . MediaSource ( file ) )
self . onMediaPlay ( )
def onMediaPlay ( self ) :
"""
We want to play the play so start it
"""
log . debug ( u ' AudioPlayer _play called ' )
self . mediaObject . play ( )
def onMediaPause ( self ) :
"""
Pause the Audio
"""
log . debug ( u ' AudioPlayer Media paused by user ' )
self . mediaObject . pause ( )
def onMediaStop ( self ) :
"""
Stop the Audio and clean up
"""
log . debug ( u ' AudioPlayer Media stopped by user ' )
self . message = None
self . mediaObject . stop ( )
self . onMediaFinish ( )
def onMediaFinish ( self ) :
"""
Clean up the Object queue
"""
log . debug ( u ' AudioPlayer Reached end of media playlist ' )
self . mediaObject . clearQueue ( )