Latest version

This commit is contained in:
Tim Bentley 2013-05-21 18:45:33 +01:00
parent 1113044955
commit e1f3024ff1
4 changed files with 46 additions and 53 deletions

View File

@ -36,6 +36,7 @@ from openlp.core.ui import HideMode
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class Controller(object): class Controller(object):
""" """
This is the Presentation listener who acts on events from the slide controller and passes the messages on the the This is the Presentation listener who acts on events from the slide controller and passes the messages on the the

View File

@ -29,14 +29,22 @@
--> -->
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>${live_title}</title> <title>${live_title}A</title>
<link rel="stylesheet" href="/files/stage.css" /> <link rel="stylesheet" href="/files/stage.css" />
<link rel="shortcut icon" type="image/x-icon" href="/files/images/favicon.ico"> <link rel="shortcut icon" type="image/x-icon" href="/files/images/favicon.ico">
<script type="text/javascript" src="/files/jquery.js"></script> <script type="text/javascript" src="/files/jquery.js"></script>
<script type="text/javascript" src="/files/live.js"></script> <script type="text/javascript" src="/files/live.js"></script>
</head> </head>
<style>
.size {
position: absolute;
left: 0px;
top: 0px;
width: 100%%;
height: 100%%;
}
</style>
<body> <body>
<input type="hidden" id="live_id" value="${next}" /> <img id="image" class="size"/>
<div id="live_display">A</div>
</body> </body>
</html> </html>

View File

@ -28,49 +28,9 @@ window.OpenLP = {
$.getJSON( $.getJSON(
"/live/image", "/live/image",
function (data, status) { function (data, status) {
OpenLP.currentSlides = data.results.slides; var img = document.getElementById('image');
OpenLP.currentSlide = 0; img.src = data.results.slide_image;
OpenLP.currentTags = Array(); img.style.display = 'block';
var div = $("#verseorder");
div.html("");
var tag = "";
var tags = 0;
var lastChange = 0;
$.each(data.results.slides, function(idx, slide) {
var prevtag = tag;
tag = slide["tag"];
if (tag != prevtag) {
// If the tag has changed, add new one to the list
lastChange = idx;
tags = tags + 1;
div.append("&nbsp;<span>");
$("#verseorder span").last().attr("id", "tag" + tags).text(tag);
}
else {
if ((slide["text"] == data.results.slides[lastChange]["text"]) &&
(data.results.slides.length > idx + (idx - lastChange))) {
// If the tag hasn't changed, check to see if the same verse
// has been repeated consecutively. Note the verse may have been
// split over several slides, so search through. If so, repeat the tag.
var match = true;
for (var idx2 = 0; idx2 < idx - lastChange; idx2++) {
if(data.results.slides[lastChange + idx2]["text"] != data.results.slides[idx + idx2]["text"]) {
match = false;
break;
}
}
if (match) {
lastChange = idx;
tags = tags + 1;
div.append("&nbsp;<span>");
$("#verseorder span").last().attr("id", "tag" + tags).text(tag);
}
}
}
OpenLP.currentTags[idx] = tags;
if (slide["selected"])
OpenLP.currentSlide = idx;
})
} }
); );
}, },

View File

@ -124,7 +124,7 @@ import cherrypy
from mako.template import Template from mako.template import Template
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Registry, Settings, PluginStatus, StringContent from openlp.core.lib import Registry, Settings, PluginStatus, StringContent, image_to_byte
from openlp.core.utils import AppLocation, translate from openlp.core.utils import AppLocation, translate
from cherrypy._cpcompat import sha, ntob from cherrypy._cpcompat import sha, ntob
@ -175,9 +175,11 @@ class HttpServer(object):
self.root = self.Public() self.root = self.Public()
self.root.files = self.Files() self.root.files = self.Files()
self.root.stage = self.Stage() self.root.stage = self.Stage()
self.root.live = self.Live()
self.root.router = self.router self.root.router = self.router
self.root.files.router = self.router self.root.files.router = self.router
self.root.stage.router = self.router self.root.stage.router = self.router
self.root.live.router = self.router
cherrypy.tree.mount(self.root, '/', config=self.define_config()) cherrypy.tree.mount(self.root, '/', config=self.define_config())
# Turn off the flood of access messages cause by poll # Turn off the flood of access messages cause by poll
cherrypy.log.access_log.propagate = False cherrypy.log.access_log.propagate = False
@ -212,6 +214,9 @@ class HttpServer(object):
u'tools.staticdir.dir': self.router.html_dir, u'tools.staticdir.dir': self.router.html_dir,
u'tools.basic_auth.on': False}, u'tools.basic_auth.on': False},
u'/stage': {u'tools.staticdir.on': True, u'/stage': {u'tools.staticdir.on': True,
u'tools.staticdir.dir': self.router.html_dir,
u'tools.basic_auth.on': False},
u'/live': {u'tools.staticdir.on': True,
u'tools.staticdir.dir': self.router.html_dir, u'tools.staticdir.dir': self.router.html_dir,
u'tools.basic_auth.on': False}} u'tools.basic_auth.on': False}}
return directory_config return directory_config
@ -239,7 +244,16 @@ class HttpServer(object):
class Stage(object): class Stage(object):
""" """
Stageview is read only so security is not relevant and would reduce it's usability Stage view is read only so security is not relevant and would reduce it's usability
"""
@cherrypy.expose
def default(self, *args, **kwargs):
url = urlparse.urlparse(cherrypy.url())
return self.router.process_http_request(url.path, *args)
class Live(object):
"""
Live view is read only so security is not relevant and would reduce it's usability
""" """
@cherrypy.expose @cherrypy.expose
def default(self, *args, **kwargs): def default(self, *args, **kwargs):
@ -270,6 +284,7 @@ class HttpRouter(object):
(r'^/api/poll$', self.poll), (r'^/api/poll$', self.poll),
(r'^/stage/poll$', self.poll), (r'^/stage/poll$', self.poll),
(r'^/live/poll$', self.live_poll), (r'^/live/poll$', self.live_poll),
(r'^/live/image$', self.live_image),
(r'^/api/controller/(live|preview)/(.*)$', self.controller), (r'^/api/controller/(live|preview)/(.*)$', self.controller),
(r'^/stage/controller/(live|preview)/(.*)$', self.controller), (r'^/stage/controller/(live|preview)/(.*)$', self.controller),
(r'^/api/service/(.*)$', self.service), (r'^/api/service/(.*)$', self.service),
@ -363,12 +378,11 @@ class HttpRouter(object):
def serve_file(self, filename=None): def serve_file(self, filename=None):
""" """
Send a file to the socket. For now, just a subset of file types Send a file to the socket. For now, just a subset of file types and must be top level inside the html folder.
and must be top level inside the html folder.
If subfolders requested return 404, easier for security for the present. If subfolders requested return 404, easier for security for the present.
Ultimately for i18n, this could first look for xx/file.html before Ultimately for i18n, this could first look for xx/file.html before falling back to file.html.
falling back to file.html... where xx is the language, e.g. 'en' where xx is the language, e.g. 'en'
""" """
log.debug(u'serve file request %s' % filename) log.debug(u'serve file request %s' % filename)
if not filename: if not filename:
@ -433,7 +447,7 @@ class HttpRouter(object):
def live_poll(self): def live_poll(self):
""" """
Poll OpenLP to determine the current display value. Poll OpenLP to determine the current slide count.
""" """
result = { result = {
u'slide_count': self.live_controller.slide_count u'slide_count': self.live_controller.slide_count
@ -441,6 +455,16 @@ class HttpRouter(object):
cherrypy.response.headers['Content-Type'] = u'application/json' cherrypy.response.headers['Content-Type'] = u'application/json'
return json.dumps({u'results': result}) return json.dumps({u'results': result})
def live_image(self):
"""
Return the latest display image as a byte stream.
"""
result = {
u'slide_image': str(image_to_byte(self.live_controller.slide_image))
}
cherrypy.response.headers['Content-Type'] = u'application/json'
return json.dumps({u'results': result})
def display(self, action): def display(self, action):
""" """
Hide or show the display screen. Hide or show the display screen.