forked from openlp/openlp
Latest version
This commit is contained in:
parent
1113044955
commit
e1f3024ff1
@ -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
|
||||||
|
@ -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>
|
@ -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(" <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(" <span>");
|
|
||||||
$("#verseorder span").last().attr("id", "tag" + tags).text(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OpenLP.currentTags[idx] = tags;
|
|
||||||
if (slide["selected"])
|
|
||||||
OpenLP.currentSlide = idx;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user