openlp/openlp/core/lib/htmlbuilder.py

442 lines
14 KiB
Python
Raw Normal View History

2010-07-11 10:58: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 #
2010-07-25 09:03:01 +00:00
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, Frode Woldsund #
2010-07-11 10:58:36 +00:00
# --------------------------------------------------------------------------- #
# 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 openlp.core.lib import image_to_byte
HTMLSRC = u"""
<html>
<head>
<title>OpenLP Display</title>
<style>
*{
margin: 0;
2010-08-09 21:21:04 +00:00
padding: 0;
border: 0;
2010-07-11 10:58:36 +00:00
}
2010-08-07 06:18:05 +00:00
body {
background-color: black;
}
2010-08-09 21:21:04 +00:00
.dim {
position: absolute;
left: 0px;
top: 0px;
width: %spx;
height: %spx;
}
#black {
z-index:8;
background-color: black;
display: none;
}
#video {
z-index:2;
}
#alert {
position: absolute;
left: 0px;
top: 0px;
z-index:10;
%s
}
#footer {
position: absolute;
z-index:5;
%s
}
/* lyric css */
2010-07-11 10:58:36 +00:00
%s
2010-08-09 21:21:04 +00:00
2010-07-11 10:58:36 +00:00
</style>
<script language="javascript">
2010-08-09 21:21:04 +00:00
var timer = null;
2010-07-30 05:08:49 +00:00
var transition = %s;
2010-08-01 08:28:31 +00:00
2010-08-09 21:21:04 +00:00
function show_video(state, path, volume, loop){
2010-08-07 06:18:05 +00:00
var vid = document.getElementById('video');
2010-08-09 21:21:04 +00:00
if(path != null)
2010-08-07 06:18:05 +00:00
vid.src = path;
2010-08-09 21:21:04 +00:00
if(loop != null){
2010-08-07 06:18:05 +00:00
if(loop)
vid.loop = 'loop';
else
vid.loop = '';
}
2010-08-09 21:21:04 +00:00
if(volume != null){
vid.volume = volume;
}
2010-08-07 06:18:05 +00:00
switch(state){
case 'play':
vid.play();
vid.style.display = 'block';
break;
case 'pause':
vid.pause();
vid.style.display = 'block';
break;
case 'stop':
vid.pause();
vid.style.display = 'none';
break;
case 'close':
vid.pause();
vid.style.display = 'none';
2010-08-09 21:21:04 +00:00
vid.src = '';
2010-08-07 06:18:05 +00:00
break;
}
}
2010-08-09 21:21:04 +00:00
function show_image(src){
2010-08-07 06:18:05 +00:00
var img = document.getElementById('image');
img.src = src;
2010-08-09 21:21:04 +00:00
if(src == '')
2010-08-07 06:18:05 +00:00
img.style.display = 'none';
else
img.style.display = 'block';
}
2010-08-09 21:21:04 +00:00
function show_blank(state){
2010-08-05 05:37:26 +00:00
var black = 'none';
var lyrics = '';
2010-08-07 06:18:05 +00:00
var pause = false;
2010-08-05 05:37:26 +00:00
switch(state){
case 'theme':
2010-08-07 06:18:05 +00:00
lyrics = 'hidden';
pause = true;
2010-08-05 05:37:26 +00:00
break;
case 'black':
2010-08-07 06:18:05 +00:00
black = 'block';
pause = true;
break;
case 'desktop':
pause = true;
2010-08-05 19:01:24 +00:00
break;
2010-08-05 05:37:26 +00:00
}
document.getElementById('black').style.display = black;
2010-08-07 06:18:05 +00:00
document.getElementById('lyricsmain').style.visibility = lyrics;
document.getElementById('lyricsoutline').style.visibility = lyrics;
document.getElementById('lyricsshadow').style.visibility = lyrics;
document.getElementById('footer').style.visibility = lyrics;
var vid = document.getElementById('video');
if(vid.src != ''){
if(pause)
vid.pause();
else
vid.play();
}
2010-08-05 05:37:26 +00:00
}
2010-08-09 21:21:04 +00:00
function show_alert(alerttext, position){
2010-08-07 06:18:05 +00:00
var text = document.getElementById('alert');
text.innerHTML = alerttext;
2010-08-09 21:21:04 +00:00
if(alerttext == '') {
2010-08-07 06:18:05 +00:00
text.style.visibility = 'hidden';
return 0;
}
2010-08-09 21:21:04 +00:00
if(position == ''){
position = window.getComputedStyle(text, '').verticalAlign;
2010-08-07 06:18:05 +00:00
}
2010-08-09 21:21:04 +00:00
switch(position)
2010-08-07 06:18:05 +00:00
{
2010-08-09 21:21:04 +00:00
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;
2010-08-07 06:18:05 +00:00
}
text.style.visibility = 'visible';
return text.clientHeight;
}
2010-08-09 21:21:04 +00:00
function show_footer(text){
document.getElementById('footer').innerHTML(text);
}
function show_text(newtext){
2010-07-30 05:08:49 +00:00
var text1 = document.getElementById('lyricsmain');
var texto1 = document.getElementById('lyricsoutline');
var texts1 = document.getElementById('lyricsshadow');
if(!transition){
text1.innerHTML = newtext;
texto1.innerHTML = newtext;
texts1.innerHTML = newtext;
return;
2010-08-01 08:28:31 +00:00
}
2010-07-30 05:08:49 +00:00
var text2 = document.getElementById('lyricsmain2');
var texto2 = document.getElementById('lyricsoutline2');
var texts2 = document.getElementById('lyricsshadow2');
2010-08-09 21:21:04 +00:00
if((text2.style.opacity == '')||(parseFloat(text2.style.opacity) < 0.5))
{
2010-07-11 10:58:36 +00:00
text2.innerHTML = text1.innerHTML;
text2.style.opacity = text1.style.opacity;
2010-07-30 05:08:49 +00:00
texto2.innerHTML = text1.innerHTML;
texto2.style.opacity = text1.style.opacity;
texts2.innerHTML = text1.innerHTML;
texts2.style.opacity = text1.style.opacity;
2010-07-11 10:58:36 +00:00
}
text1.style.opacity = 0;
text1.innerHTML = newtext;
2010-07-30 05:08:49 +00:00
texto1.style.opacity = 0;
texto1.innerHTML = newtext;
texts1.style.opacity = 0;
texts1.innerHTML = newtext;
2010-08-09 21:21:04 +00:00
// For performance reasons, we'll not animate the shadow for now
2010-07-30 05:08:49 +00:00
texts2.style.opacity = 0;
2010-08-09 21:21:04 +00:00
if(timer != null)
clearTimeout(timer);
timer = setTimeout('text_fade()', 50);
2010-07-11 10:58:36 +00:00
}
2010-08-06 05:09:32 +00:00
2010-08-09 21:21:04 +00:00
function text_fade(){
2010-07-30 05:08:49 +00:00
var text1 = document.getElementById('lyricsmain');
var texto1 = document.getElementById('lyricsoutline');
var texts1 = document.getElementById('lyricsshadow');
var text2 = document.getElementById('lyricsmain2');
var texto2 = document.getElementById('lyricsoutline2');
var texts2 = document.getElementById('lyricsshadow2');
if(parseFloat(text1.style.opacity) < 1){
text1.style.opacity = parseFloat(text1.style.opacity) + 0.1;
texto1.style.opacity = parseFloat(texto1.style.opacity) + 0.1;
2010-08-09 21:21:04 +00:00
// Don't animate shadow (performance)
2010-07-30 05:08:49 +00:00
//texts1.style.opacity = parseFloat(texts1.style.opacity) + 0.1;
}
if(parseFloat(text2.style.opacity) > 0){
text2.style.opacity = parseFloat(text2.style.opacity) - 0.1;
texto2.style.opacity = parseFloat(texto2.style.opacity) - 0.1;
2010-08-09 21:21:04 +00:00
// Don't animate shadow (performance)
2010-07-30 05:08:49 +00:00
//texts2.style.opacity = parseFloat(texts2.style.opacity) - 0.1;
}
2010-08-09 21:21:04 +00:00
if((parseFloat(text1.style.opacity) < 1) ||
(parseFloat(text2.style.opacity) > 0)){
t = setTimeout('text_fade()', 50);
} else {
2010-08-07 06:18:05 +00:00
text1.style.opacity = 1;
texto1.style.opacity = 1;
texts1.style.opacity = 1;
text2.style.opacity = 0;
texto2.style.opacity = 0;
texts2.style.opacity = 0;
2010-07-30 05:08:49 +00:00
}
2010-08-06 05:09:32 +00:00
}
2010-08-09 21:21:04 +00:00
function show_text_complete(){
return (document.getElementById('lyricsmain').style.opacity == 1);
2010-07-11 10:58:36 +00:00
}
</script>
</head>
<body>
2010-08-09 21:21:04 +00:00
<!--
Using tables, rather than div's to make use of the vertical-align style that
doesn't work on div's. This avoids the need to do positioning manually which
could get messy when changing verses esp. with transitions
Would prefer to use a single table and make use of -webkit-text-fill-color
-webkit-text-stroke and text-shadow styles, but they have problems working/
co-operating in qwebkit. https://bugs.webkit.org/show_bug.cgi?id=43187
Therefore one table for text, one for outline and one for shadow.
-->
2010-07-30 05:08:49 +00:00
<table class="lyricstable lyricscommon">
2010-07-28 16:53:54 +00:00
<tr><td id="lyricsmain" class="lyrics"></td></tr>
</table>
2010-07-30 05:08:49 +00:00
<table class="lyricsoutlinetable lyricscommon">
<tr><td id="lyricsoutline" class="lyricsoutline lyrics"></td></tr>
</table>
<table class="lyricsshadowtable lyricscommon">
<tr><td id="lyricsshadow" class="lyricsshadow lyrics"></td></tr>
</table>
<table class="lyricstable lyricscommon">
<tr><td id="lyricsmain2" class="lyrics"></td></tr>
</table>
<table class="lyricsoutlinetable lyricscommon">
<tr><td id="lyricsoutline2" class="lyricsoutline lyrics"></td></tr>
</table>
<table class="lyricsshadowtable lyricscommon">
<tr><td id="lyricsshadow2" class="lyricsshadow lyrics"></td></tr>
2010-07-28 16:53:54 +00:00
</table>
2010-08-07 06:18:05 +00:00
<div id="alert" style="visibility:hidden;"></div>
2010-07-19 18:03:00 +00:00
<div id="footer" class="footer"></div>
2010-08-09 21:21:04 +00:00
<video class="dim" id="video"></video>
<div class="dim" id="black"></div>
<img class="dim" id="image" src="%s" />
2010-07-11 10:58:36 +00:00
</body>
</html>
"""
2010-07-27 19:13:56 +00:00
2010-07-17 08:59:15 +00:00
def build_html(item, screen, alert):
2010-07-25 08:58:08 +00:00
"""
Build the full web paged structure for display
`item`
Service Item to be displayed
`screen`
Current display information
`alert`
Alert display display information
"""
2010-07-11 10:58:36 +00:00
width = screen[u'size'].width()
height = screen[u'size'].height()
2010-07-30 05:08:49 +00:00
theme = item.themedata
2010-08-09 21:21:04 +00:00
if item.bg_frame:
image = u'data:image/png;base64,%s' % image_to_byte(item.bg_frame)
2010-08-07 06:18:05 +00:00
else:
2010-08-09 21:21:04 +00:00
image = u''
html = HTMLSRC % (width, height,
build_alert(alert, width),
build_footer(item),
build_lyrics(item),
u'true' if theme and theme.display_slideTransition else u'false',
image)
return html
2010-07-11 10:58:36 +00:00
2010-07-24 16:55:06 +00:00
def build_lyrics(item):
2010-07-25 08:58:08 +00:00
"""
Build the video display div
`item`
Service Item containing theme and location information
"""
2010-07-28 16:53:54 +00:00
style = """
2010-07-30 05:08:49 +00:00
.lyricscommon { position: absolute; %s }
.lyricstable { z-index:4; %s }
.lyricsoutlinetable { z-index:3; %s }
.lyricsshadowtable { z-index:2; %s }
2010-07-28 16:53:54 +00:00
.lyrics { %s }
2010-07-30 05:08:49 +00:00
.lyricsoutline { %s }
2010-08-01 08:28:31 +00:00
.lyricsshadow { %s }
2010-07-30 05:08:49 +00:00
"""
2010-07-17 08:59:15 +00:00
theme = item.themedata
2010-07-30 05:08:49 +00:00
lyricscommon = u''
lyricstable = u''
outlinetable = u''
shadowtable = u''
2010-07-28 16:53:54 +00:00
lyrics = u''
2010-07-30 05:08:49 +00:00
outline = u'display: none;'
shadow = u'display: none;'
2010-07-12 16:49:38 +00:00
if theme:
2010-08-07 06:18:05 +00:00
lyricscommon = u'width: %spx; height: %spx; word-wrap: break-word ' \
2010-07-30 05:08:49 +00:00
u'font-family %s; font-size: %spx; color: %s; line-height: %d%%' % \
(item.main.width(), item.main.height(),
2010-08-01 08:28:31 +00:00
theme.font_main_name, theme.font_main_proportion,
2010-07-30 05:08:49 +00:00
theme.font_main_color, 100 + int(theme.font_main_line_adjustment))
lyricstable = u'left: %spx; top: %spx;' % \
(item.main.x(), item.main.y())
outlinetable = u'left: %spx; top: %spx;' % \
(item.main.x(), item.main.y())
shadowtable = u'left: %spx; top: %spx;' % \
(item.main.x() + float(theme.display_shadow_size),
item.main.y() + float(theme.display_shadow_size))
2010-07-18 18:01:35 +00:00
align = u''
if theme.display_horizontalAlign == 2:
2010-07-28 16:53:54 +00:00
align = u'text-align:center;'
2010-07-18 18:01:35 +00:00
elif theme.display_horizontalAlign == 1:
2010-07-28 16:53:54 +00:00
align = u'text-align:right;'
else:
align = u'text-align:left;'
2010-07-18 18:01:35 +00:00
if theme.display_verticalAlign == 2:
2010-07-27 19:13:56 +00:00
valign = u'vertical-align:bottom;'
2010-07-18 18:01:35 +00:00
elif theme.display_verticalAlign == 1:
2010-07-27 19:13:56 +00:00
valign = u'vertical-align:middle;'
2010-07-18 18:01:35 +00:00
else:
2010-07-27 19:13:56 +00:00
valign = u'vertical-align:top;'
2010-07-30 05:08:49 +00:00
lyrics = u'%s %s' % (align, valign)
2010-07-28 16:53:54 +00:00
if theme.display_outline:
2010-07-30 05:08:49 +00:00
outline = u'-webkit-text-stroke: %sem %s; ' % \
2010-07-28 16:53:54 +00:00
(float(theme.display_outline_size) / 16,
theme.display_outline_color)
2010-07-30 05:08:49 +00:00
if theme.display_shadow:
shadow = u'-webkit-text-stroke: %sem %s; ' % \
(float(theme.display_outline_size) / 16,
theme.display_shadow_color)
else:
if theme.display_shadow:
shadow = u'color: %s;' % (theme.display_shadow_color)
lyrics_html = style % (lyricscommon, lyricstable, outlinetable,
shadowtable, lyrics, outline, shadow)
2010-07-19 18:03:00 +00:00
return lyrics_html
2010-07-24 16:55:06 +00:00
def build_footer(item):
2010-08-03 04:56:21 +00:00
"""
Build the display of the item footer
`item`
Service Item to be processed.
"""
2010-08-09 21:21:04 +00:00
style = """
left: %spx;
top: %spx;
width: %spx;
height: %spx;
font-family: %s;
font-size: %spx;
color: %s;
align: %s;
2010-07-19 18:03:00 +00:00
"""
theme = item.themedata
2010-08-09 21:21:04 +00:00
if not theme:
return u''
if theme.display_horizontalAlign == 2:
align = u'center'
elif theme.display_horizontalAlign == 1:
align = u'right'
else:
align = u'left'
lyrics_html = style % (item.footer.x(), item.footer.y(),
item.footer.width(), item.footer.height(), theme.font_footer_name,
theme.font_footer_proportion, theme.font_footer_color, align)
2010-07-12 16:49:38 +00:00
return lyrics_html
2010-07-11 10:58:36 +00:00
2010-08-09 21:21:04 +00:00
def build_alert(alertTab, width):
2010-08-03 04:56:21 +00:00
"""
Build the display of the footer
2010-07-19 18:03:00 +00:00
2010-08-03 04:56:21 +00:00
`alertTab`
Details from the Alert tab for fonts etc
"""
2010-08-01 08:28:31 +00:00
style = """
2010-08-09 21:21:04 +00:00
width: %s;
vertical-align: %s;
font-family %s;
font-size: %spx;
color: %s;
background-color: %s;
2010-08-07 06:18:05 +00:00
"""
2010-08-09 21:21:04 +00:00
if not alertTab:
return u''
align = u''
if alertTab.location == 2:
align = u'bottom'
elif alertTab.location == 1:
align = u'middle'
else:
align = u'top'
alert = style % (width, align, alertTab.font_face, alertTab.font_size,
alertTab.font_color, alertTab.bg_color)
return alert