diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py
index 86b114e1e..e2d318549 100644
--- a/openlp/core/ui/slidecontroller.py
+++ b/openlp/core/ui/slidecontroller.py
@@ -136,6 +136,8 @@ class SlideController(DisplayController):
self.keypress_loop = False
self.category = UiStrings().LiveToolbar
ActionList.get_instance().add_category(unicode(self.category), CategoryOrder.standard_toolbar)
+ self.slide_count = 0
+ self.slide_image = None
else:
Registry().register(u'preview_controller', self)
self.type_label.setText(UiStrings().Preview)
@@ -1050,27 +1052,28 @@ class SlideController(DisplayController):
def updatePreview(self):
"""
- This updates the preview frame, for example after changing a slide or
- using *Blank to Theme*.
+ This updates the preview frame, for example after changing a slide or using *Blank to Theme*.
"""
log.debug(u'updatePreview %s ' % self.screens.current[u'primary'])
if not self.screens.current[u'primary'] and self.service_item and \
self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay):
- # Grab now, but try again in a couple of seconds if slide change
- # is slow
- QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
- QtCore.QTimer.singleShot(2.5, self.grabMainDisplay)
+ # Grab now, but try again in a couple of seconds if slide change is slow
+ QtCore.QTimer.singleShot(0.5, self.grab_maindisplay)
+ QtCore.QTimer.singleShot(2.5, self.grab_maindisplay)
else:
- self.slidePreview.setPixmap(self.display.preview())
+ self.slide_image = self.display.preview()
+ self.slidePreview.setPixmap(self.slide_image)
+ self.slide_count += 1
- def grabMainDisplay(self):
+ def grab_maindisplay(self):
"""
Creates an image of the current screen and updates the preview frame.
"""
- winid = QtGui.QApplication.desktop().winId()
+ win_id = QtGui.QApplication.desktop().winId()
rect = self.screens.current[u'size']
- winimg = QtGui.QPixmap.grabWindow(winid, rect.x(), rect.y(), rect.width(), rect.height())
- self.slidePreview.setPixmap(winimg)
+ win_image = QtGui.QPixmap.grabWindow(win_id, rect.x(), rect.y(), rect.width(), rect.height())
+ self.slidePreview.setPixmap(win_image)
+ self.slide_image = win_image
def on_slide_selected_next_action(self, checked):
"""
diff --git a/openlp/plugins/remotes/html/live.html b/openlp/plugins/remotes/html/live.html
new file mode 100644
index 000000000..2f505f98e
--- /dev/null
+++ b/openlp/plugins/remotes/html/live.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+ ${live_title}
+
+
+
+
+
+
+
+
A
+
+
\ No newline at end of file
diff --git a/openlp/plugins/remotes/html/live.js b/openlp/plugins/remotes/html/live.js
new file mode 100644
index 000000000..a44ce02ca
--- /dev/null
+++ b/openlp/plugins/remotes/html/live.js
@@ -0,0 +1,92 @@
+/******************************************************************************
+ * OpenLP - Open Source Lyrics Projection *
+ * --------------------------------------------------------------------------- *
+ * Copyright (c) 2008-2013 Raoul Snyman *
+ * Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan *
+ * Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, *
+ * Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. *
+ * Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, *
+ * Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, *
+ * Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, *
+ * Frode Woldsund, Martin Zibricky *
+ * --------------------------------------------------------------------------- *
+ * 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 *
+ ******************************************************************************/
+window.OpenLP = {
+ loadSlide: function (event) {
+ $.getJSON(
+ "/live/image",
+ function (data, status) {
+ OpenLP.currentSlides = data.results.slides;
+ OpenLP.currentSlide = 0;
+ OpenLP.currentTags = Array();
+ 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(" ");
+ $("#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(" ");
+ $("#verseorder span").last().attr("id", "tag" + tags).text(tag);
+ }
+ }
+ }
+ OpenLP.currentTags[idx] = tags;
+ if (slide["selected"])
+ OpenLP.currentSlide = idx;
+ })
+ }
+ );
+ },
+ pollServer: function () {
+ $.getJSON(
+ "/live/poll",
+ function (data, status) {
+ if (OpenLP.slideCount != data.results.slide_count) {
+ OpenLP.slideCount = data.results.slide_count;
+ OpenLP.loadSlide();
+ }
+ }
+ );
+ }
+}
+$.ajaxSetup({ cache: false });
+setInterval("OpenLP.pollServer();", 500);
+OpenLP.pollServer();
+
diff --git a/openlp/plugins/remotes/lib/httpserver.py b/openlp/plugins/remotes/lib/httpserver.py
index eedc30102..7a7acab2b 100644
--- a/openlp/plugins/remotes/lib/httpserver.py
+++ b/openlp/plugins/remotes/lib/httpserver.py
@@ -265,9 +265,11 @@ class HttpRouter(object):
self.routes = [
(u'^/$', self.serve_file),
(u'^/(stage)$', self.serve_file),
+ (u'^/(live)$', self.serve_file),
(r'^/files/(.*)$', self.serve_file),
(r'^/api/poll$', self.poll),
(r'^/stage/poll$', self.poll),
+ (r'^/live/poll$', self.live_poll),
(r'^/api/controller/(live|preview)/(.*)$', self.controller),
(r'^/stage/controller/(live|preview)/(.*)$', self.controller),
(r'^/api/service/(.*)$', self.service),
@@ -305,6 +307,7 @@ class HttpRouter(object):
if response:
return response
else:
+ log.debug('Path not found %s', url_path)
return self._http_not_found()
def _get_service_items(self):
@@ -334,6 +337,7 @@ class HttpRouter(object):
self.template_vars = {
'app_title': translate('RemotePlugin.Mobile', 'OpenLP 2.1 Remote'),
'stage_title': translate('RemotePlugin.Mobile', 'OpenLP 2.1 Stage View'),
+ 'live_title': translate('RemotePlugin.Mobile', 'OpenLP 2.1 Live View'),
'service_manager': translate('RemotePlugin.Mobile', 'Service Manager'),
'slide_controller': translate('RemotePlugin.Mobile', 'Slide Controller'),
'alerts': translate('RemotePlugin.Mobile', 'Alerts'),
@@ -371,6 +375,8 @@ class HttpRouter(object):
filename = u'index.html'
elif filename == u'stage':
filename = u'stage.html'
+ elif filename == u'live':
+ filename = u'live.html'
path = os.path.normpath(os.path.join(self.html_dir, filename))
if not path.startswith(self.html_dir):
return self._http_not_found()
@@ -425,6 +431,16 @@ class HttpRouter(object):
cherrypy.response.headers['Content-Type'] = u'application/json'
return json.dumps({u'results': result})
+ def live_poll(self):
+ """
+ Poll OpenLP to determine the current display value.
+ """
+ result = {
+ u'slide_count': self.live_controller.slide_count
+ }
+ cherrypy.response.headers['Content-Type'] = u'application/json'
+ return json.dumps({u'results': result})
+
def display(self, action):
"""
Hide or show the display screen.