forked from openlp/openlp
comments, update client, load html from disk, blanking
This commit is contained in:
parent
6c52ad359f
commit
9ef2b13ad6
@ -83,6 +83,12 @@ class EventReceiver(QtCore.QObject):
|
|||||||
Returns a slidecontroller_{live|preview}_text_response with an
|
Returns a slidecontroller_{live|preview}_text_response with an
|
||||||
array of dictionaries with the tag and verse text
|
array of dictionaries with the tag and verse text
|
||||||
|
|
||||||
|
``slidecontroller_{live|preview}_blank``
|
||||||
|
Request that the output screen is blanked
|
||||||
|
|
||||||
|
``slidecontroller_{live|preview}_unblank``
|
||||||
|
Request that the output screen is unblanked
|
||||||
|
|
||||||
``slidecontroller_live_spin_delay``
|
``slidecontroller_live_spin_delay``
|
||||||
Pushes out the loop delay
|
Pushes out the loop delay
|
||||||
|
|
||||||
@ -132,6 +138,9 @@ class EventReceiver(QtCore.QObject):
|
|||||||
``videodisplay_stop``
|
``videodisplay_stop``
|
||||||
Stop playing a media item
|
Stop playing a media item
|
||||||
|
|
||||||
|
``videodisplay_background``
|
||||||
|
Replace the background video
|
||||||
|
|
||||||
``theme_update_list``
|
``theme_update_list``
|
||||||
send out message with new themes
|
send out message with new themes
|
||||||
|
|
||||||
@ -196,6 +205,10 @@ class EventReceiver(QtCore.QObject):
|
|||||||
``bibles_stop_import``
|
``bibles_stop_import``
|
||||||
Stops the Bible Import
|
Stops the Bible Import
|
||||||
|
|
||||||
|
``remotes_poll_request``
|
||||||
|
Waits for openlp to do something "interesting" and sends a
|
||||||
|
remotes_poll_response signal when it does
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
|
@ -341,6 +341,12 @@ class SlideController(QtGui.QWidget):
|
|||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_%s_set' % self.type_prefix),
|
QtCore.SIGNAL(u'slidecontroller_%s_set' % self.type_prefix),
|
||||||
self.onSlideSelectedIndex)
|
self.onSlideSelectedIndex)
|
||||||
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
|
QtCore.SIGNAL(u'slidecontroller_%s_blank' % self.type_prefix),
|
||||||
|
self.onSlideBlank)
|
||||||
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
|
QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.type_prefix),
|
||||||
|
self.onSlideUnblank)
|
||||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||||
QtCore.SIGNAL(u'slidecontroller_%s_text_request' % self.type_prefix),
|
QtCore.SIGNAL(u'slidecontroller_%s_text_request' % self.type_prefix),
|
||||||
self.onTextRequest)
|
self.onTextRequest)
|
||||||
@ -616,6 +622,18 @@ class SlideController(QtGui.QWidget):
|
|||||||
self.PreviewListWidget.selectRow(index)
|
self.PreviewListWidget.selectRow(index)
|
||||||
self.onSlideSelected()
|
self.onSlideSelected()
|
||||||
|
|
||||||
|
def onSlideBlank(self):
|
||||||
|
"""
|
||||||
|
Handle the slidecontroller blank event
|
||||||
|
"""
|
||||||
|
self.onBlankDisplay(True)
|
||||||
|
|
||||||
|
def onSlideUnblank(self):
|
||||||
|
"""
|
||||||
|
Handle the slidecontroller unblank event
|
||||||
|
"""
|
||||||
|
self.onBlankDisplay(False)
|
||||||
|
|
||||||
def onBlankDisplay(self, checked):
|
def onBlankDisplay(self, checked):
|
||||||
"""
|
"""
|
||||||
Handle the blank screen button
|
Handle the blank screen button
|
||||||
|
@ -75,7 +75,10 @@ class AlertsManager(QtCore.QObject):
|
|||||||
Called via a alerts_text event. Message is single element array
|
Called via a alerts_text event. Message is single element array
|
||||||
containing text
|
containing text
|
||||||
"""
|
"""
|
||||||
|
if message:
|
||||||
self.displayAlert(message[0])
|
self.displayAlert(message[0])
|
||||||
|
else:
|
||||||
|
self.displayAlert(u'')
|
||||||
|
|
||||||
def displayAlert(self, text=u''):
|
def displayAlert(self, text=u''):
|
||||||
"""
|
"""
|
||||||
|
117
openlp/plugins/remotes/html/index.html
Normal file
117
openlp/plugins/remotes/html/index.html
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OpenLP Controller</title>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
|
||||||
|
function send_event(eventname, data){
|
||||||
|
var req = new XMLHttpRequest();
|
||||||
|
req.onreadystatechange = function() {
|
||||||
|
if(req.readyState==4)
|
||||||
|
response(eventname, req);
|
||||||
|
}
|
||||||
|
var url = '';
|
||||||
|
if(eventname.substr(-8) == '_request')
|
||||||
|
url = 'request';
|
||||||
|
else
|
||||||
|
url = 'send';
|
||||||
|
url += '/' + eventname;
|
||||||
|
if(data!=null)
|
||||||
|
url += '?q=' + escape(data);
|
||||||
|
req.open('GET', url, true);
|
||||||
|
req.send();
|
||||||
|
}
|
||||||
|
function failed_response(eventname, req){
|
||||||
|
switch(eventname){
|
||||||
|
case 'remotes_poll_request':
|
||||||
|
if(req.status==408)
|
||||||
|
send_event("remotes_poll_request");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function response(eventname, req){
|
||||||
|
if(req.status!=200){
|
||||||
|
failed_response(eventname, req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
text = req.responseText;
|
||||||
|
switch(eventname){
|
||||||
|
case 'servicemanager_list_request':
|
||||||
|
var data = eval('(' + text + ')');
|
||||||
|
var html = '<table>';
|
||||||
|
for(row in data){
|
||||||
|
html += '<tr onclick="send_event('
|
||||||
|
html += "'servicemanager_set_item', " + row + ')"';
|
||||||
|
if(data[row]['selected'])
|
||||||
|
html += ' style="font-weight: bold"';
|
||||||
|
html += '>'
|
||||||
|
html += '<td>' + (parseInt(row)+1) + '</td>'
|
||||||
|
html += '<td>' + data[row]['title'] + '</td>'
|
||||||
|
html += '<td>' + data[row]['plugin'] + '</td>'
|
||||||
|
html += '<td>' + data[row]['notes'] + '</td>'
|
||||||
|
html += '</tr>';
|
||||||
|
}
|
||||||
|
html += '</table>';
|
||||||
|
document.getElementById('service').innerHTML = html;
|
||||||
|
break;
|
||||||
|
case 'slidecontroller_live_text_request':
|
||||||
|
var data = eval('(' + text + ')');
|
||||||
|
var html = '<table>';
|
||||||
|
for(row in data){
|
||||||
|
html += '<tr onclick="send_event('
|
||||||
|
html += "'slidecontroller_live_set', " + row + ')"';
|
||||||
|
if(data[row]['selected'])
|
||||||
|
html += ' style="font-weight: bold"';
|
||||||
|
html += '>';
|
||||||
|
html += '<td>' + data[row]['tag'] + '</td>';
|
||||||
|
html += '<td>' + data[row]['text'].replace(/\\n/g, '<br>');
|
||||||
|
html += '</td></tr>';
|
||||||
|
}
|
||||||
|
html += '</table>';
|
||||||
|
document.getElementById('currentitem').innerHTML = html;
|
||||||
|
break;
|
||||||
|
case 'remotes_poll_request':
|
||||||
|
send_event("remotes_poll_request");
|
||||||
|
send_event("servicemanager_list_request");
|
||||||
|
send_event("slidecontroller_live_text_request");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
send_event("servicemanager_list_request");
|
||||||
|
send_event("slidecontroller_live_text_request");
|
||||||
|
send_event("remotes_poll_request");
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>OpenLP Controller</h1>
|
||||||
|
<input type='button' value='<- Previous Slide'
|
||||||
|
onclick='send_event("slidecontroller_live_previous");' />
|
||||||
|
<input type='button' value='Next Slide ->'
|
||||||
|
onclick='send_event("slidecontroller_live_next");' />
|
||||||
|
<br/>
|
||||||
|
<input type='button' value='<- Previous Item'
|
||||||
|
onclick='send_event("servicemanager_previous_item");' />
|
||||||
|
<input type='button' value='Next Item ->'
|
||||||
|
onclick='send_event("servicemanager_next_item");' />
|
||||||
|
<br/>
|
||||||
|
<input type='button' value='Blank'
|
||||||
|
onclick='send_event("slidecontroller_live_blank");' />
|
||||||
|
<input type='button' value='Unblank'
|
||||||
|
onclick='send_event("slidecontroller_live_unblank");' />
|
||||||
|
<br/>
|
||||||
|
<label>Alert text</label><input id='alert' type='text' />
|
||||||
|
<input type='button' value='Send'
|
||||||
|
onclick='send_event("alerts_text",
|
||||||
|
document.getElementById("alert").value);' />
|
||||||
|
<hr>
|
||||||
|
<input type='button' value='Order of service'
|
||||||
|
onclick='send_event("servicemanager_list_request");'>
|
||||||
|
<div id='service'></div>
|
||||||
|
<hr>
|
||||||
|
<input type='button' value='Current item'
|
||||||
|
onclick='send_event("slidecontroller_live_text_request");'>
|
||||||
|
<div id='currentitem'></div>
|
||||||
|
<hr>
|
||||||
|
<a href="http://www.openlp.org/">OpenLP website</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -24,12 +24,14 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import json
|
import json
|
||||||
import urlparse
|
import urlparse
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtNetwork
|
from PyQt4 import QtCore, QtNetwork
|
||||||
|
|
||||||
from openlp.core.lib import Receiver
|
from openlp.core.lib import Receiver
|
||||||
|
from openlp.core.utils import AppLocation
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -40,14 +42,25 @@ class HttpServer(object):
|
|||||||
http://localhost:4316/send/alerts_text?q=your%20alert%20text
|
http://localhost:4316/send/alerts_text?q=your%20alert%20text
|
||||||
"""
|
"""
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
|
"""
|
||||||
|
Initialise the httpserver, and start the server
|
||||||
|
"""
|
||||||
log.debug(u'Initialise httpserver')
|
log.debug(u'Initialise httpserver')
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
self.html_dir = os.path.join(
|
||||||
|
AppLocation.get_directory(AppLocation.PluginsDir),
|
||||||
|
u'remotes', u'html')
|
||||||
self.connections = []
|
self.connections = []
|
||||||
self.current_item = None
|
self.current_item = None
|
||||||
self.current_slide = None
|
self.current_slide = None
|
||||||
self.start_tcp()
|
self.start_tcp()
|
||||||
|
|
||||||
def start_tcp(self):
|
def start_tcp(self):
|
||||||
|
"""
|
||||||
|
Start the http server, use the port in the settings default to 4316
|
||||||
|
Listen out for slide and song changes so they can be broadcast to
|
||||||
|
clients. Listen out for socket connections
|
||||||
|
"""
|
||||||
log.debug(u'Start TCP server')
|
log.debug(u'Start TCP server')
|
||||||
port = QtCore.QSettings().value(
|
port = QtCore.QSettings().value(
|
||||||
self.parent.settingsSection + u'/remote port',
|
self.parent.settingsSection + u'/remote port',
|
||||||
@ -66,29 +79,48 @@ class HttpServer(object):
|
|||||||
log.debug(u'TCP listening on port %d' % port)
|
log.debug(u'TCP listening on port %d' % port)
|
||||||
|
|
||||||
def slide_change(self, row):
|
def slide_change(self, row):
|
||||||
|
"""
|
||||||
|
Slide change listener. Store the item and tell the clients
|
||||||
|
"""
|
||||||
self.current_slide = row
|
self.current_slide = row
|
||||||
self.send_poll()
|
self.send_poll()
|
||||||
|
|
||||||
def item_change(self, items):
|
def item_change(self, items):
|
||||||
|
"""
|
||||||
|
Item (song) change listener. Store the slide and tell the clients
|
||||||
|
"""
|
||||||
self.current_item = items[0].title
|
self.current_item = items[0].title
|
||||||
self.send_poll()
|
self.send_poll()
|
||||||
|
|
||||||
def send_poll(self):
|
def send_poll(self):
|
||||||
Receiver.send_message(u'remote_poll_response',
|
"""
|
||||||
|
Tell the clients something has changed
|
||||||
|
"""
|
||||||
|
Receiver.send_message(u'remotes_poll_response',
|
||||||
{'slide': self.current_slide,
|
{'slide': self.current_slide,
|
||||||
'item': self.current_item})
|
'item': self.current_item})
|
||||||
|
|
||||||
def new_connection(self):
|
def new_connection(self):
|
||||||
|
"""
|
||||||
|
A new http connection has been made. Create a client object to handle
|
||||||
|
communication
|
||||||
|
"""
|
||||||
log.debug(u'new http connection')
|
log.debug(u'new http connection')
|
||||||
socket = self.server.nextPendingConnection()
|
socket = self.server.nextPendingConnection()
|
||||||
if socket:
|
if socket:
|
||||||
self.connections.append(HttpConnection(self, socket))
|
self.connections.append(HttpConnection(self, socket))
|
||||||
|
|
||||||
def close_connection(self, connection):
|
def close_connection(self, connection):
|
||||||
|
"""
|
||||||
|
The connection has been closed. Clean up
|
||||||
|
"""
|
||||||
log.debug(u'close http connection')
|
log.debug(u'close http connection')
|
||||||
self.connections.remove(connection)
|
self.connections.remove(connection)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
"""
|
||||||
|
Close down the http server
|
||||||
|
"""
|
||||||
log.debug(u'close http server')
|
log.debug(u'close http server')
|
||||||
self.server.close()
|
self.server.close()
|
||||||
|
|
||||||
@ -98,6 +130,9 @@ class HttpConnection(object):
|
|||||||
and the client
|
and the client
|
||||||
"""
|
"""
|
||||||
def __init__(self, parent, socket):
|
def __init__(self, parent, socket):
|
||||||
|
"""
|
||||||
|
Initialise the http connection. Listen out for socket signals
|
||||||
|
"""
|
||||||
log.debug(u'Initialise HttpConnection: %s' %
|
log.debug(u'Initialise HttpConnection: %s' %
|
||||||
socket.peerAddress().toString())
|
socket.peerAddress().toString())
|
||||||
self.socket = socket
|
self.socket = socket
|
||||||
@ -108,6 +143,9 @@ class HttpConnection(object):
|
|||||||
self.disconnected)
|
self.disconnected)
|
||||||
|
|
||||||
def ready_read(self):
|
def ready_read(self):
|
||||||
|
"""
|
||||||
|
Data has been sent from the client. Respond to it
|
||||||
|
"""
|
||||||
log.debug(u'ready to read socket')
|
log.debug(u'ready to read socket')
|
||||||
if self.socket.canReadLine():
|
if self.socket.canReadLine():
|
||||||
data = unicode(self.socket.readLine())
|
data = unicode(self.socket.readLine())
|
||||||
@ -119,7 +157,9 @@ class HttpConnection(object):
|
|||||||
params = self.load_params(url.query)
|
params = self.load_params(url.query)
|
||||||
folders = url.path.split(u'/')
|
folders = url.path.split(u'/')
|
||||||
if folders[1] == u'':
|
if folders[1] == u'':
|
||||||
html = self.process_index()
|
html = self.serve_file(u'')
|
||||||
|
elif folders[1] == u'files':
|
||||||
|
html = self.serve_file(folders[2])
|
||||||
elif folders[1] == u'send':
|
elif folders[1] == u'send':
|
||||||
html = self.process_event(folders[2], params)
|
html = self.process_event(folders[2], params)
|
||||||
elif folders[1] == u'request':
|
elif folders[1] == u'request':
|
||||||
@ -132,119 +172,38 @@ class HttpConnection(object):
|
|||||||
self.socket.write(html)
|
self.socket.write(html)
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def process_index(self):
|
def serve_file(self, filename):
|
||||||
return u"""
|
"""
|
||||||
<html>
|
Send a file to the socket. For now, just .html files
|
||||||
<head>
|
and must be top level inside the html folder.
|
||||||
<title>OpenLP Controller</title>
|
If subfolders requested return 404, easier for security for the present.
|
||||||
<script type='text/javascript'>
|
|
||||||
|
|
||||||
function send_event(eventname, data){
|
Ultimately for i18n, this could first look for xx/file.html before
|
||||||
var req = new XMLHttpRequest();
|
falling back to file.html... where xx is the language, e.g. 'en'
|
||||||
req.onreadystatechange = function() {
|
"""
|
||||||
if(req.readyState==4)
|
log.debug(u'serve file request %s' % filename)
|
||||||
response(eventname, req);
|
if not filename:
|
||||||
}
|
filename = u'index.html'
|
||||||
var url = '';
|
if os.path.basename(filename) != filename:
|
||||||
if(eventname.substr(-8) == '_request')
|
return None
|
||||||
url = 'request';
|
(fileroot, ext) = os.path.splitext(filename)
|
||||||
else
|
if ext != u'.html':
|
||||||
url = 'send';
|
return None
|
||||||
url += '/' + eventname;
|
path = os.path.join(self.parent.html_dir, filename)
|
||||||
if(data!=null)
|
try:
|
||||||
url += '?q=' + escape(data);
|
f = open(path, u'rb')
|
||||||
req.open('GET', url, true);
|
except:
|
||||||
req.send();
|
log.exception(u'Failed to open %s' % path)
|
||||||
}
|
return None
|
||||||
function failed_response(eventname, req){
|
log.debug(u'Opened %s' % path)
|
||||||
switch(eventname){
|
html = f.read()
|
||||||
case 'remote_poll_request':
|
f.close()
|
||||||
if(req.status==408)
|
return html
|
||||||
send_event("remote_poll_request");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function response(eventname, req){
|
|
||||||
if(req.status!=200){
|
|
||||||
failed_response(eventname, req);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
text = req.responseText;
|
|
||||||
switch(eventname){
|
|
||||||
case 'servicemanager_list_request':
|
|
||||||
var data = eval('(' + text + ')');
|
|
||||||
var html = '<table>';
|
|
||||||
for(row in data){
|
|
||||||
html += '<tr onclick="send_event('
|
|
||||||
html += "'servicemanager_set_item', " + row + ')"';
|
|
||||||
if(data[row]['selected'])
|
|
||||||
html += ' style="font-weight: bold"';
|
|
||||||
html += '>'
|
|
||||||
html += '<td>' + (parseInt(row)+1) + '</td>'
|
|
||||||
html += '<td>' + data[row]['title'] + '</td>'
|
|
||||||
html += '<td>' + data[row]['plugin'] + '</td>'
|
|
||||||
html += '<td>' + data[row]['notes'] + '</td>'
|
|
||||||
html += '</tr>';
|
|
||||||
}
|
|
||||||
html += '</table>';
|
|
||||||
document.getElementById('service').innerHTML = html;
|
|
||||||
break;
|
|
||||||
case 'slidecontroller_live_text_request':
|
|
||||||
var data = eval('(' + text + ')');
|
|
||||||
var html = '<table>';
|
|
||||||
for(row in data){
|
|
||||||
html += '<tr onclick="send_event('
|
|
||||||
html += "'slidecontroller_live_set', " + row + ')"';
|
|
||||||
if(data[row]['selected'])
|
|
||||||
html += ' style="font-weight: bold"';
|
|
||||||
html += '>';
|
|
||||||
html += '<td>' + data[row]['tag'] + '</td>';
|
|
||||||
html += '<td>' + data[row]['text'].replace(/\\n/g, '<br>');
|
|
||||||
html += '</td></tr>';
|
|
||||||
}
|
|
||||||
html += '</table>';
|
|
||||||
document.getElementById('currentitem').innerHTML = html;
|
|
||||||
break;
|
|
||||||
case 'remote_poll_request':
|
|
||||||
send_event("remote_poll_request");
|
|
||||||
send_event("servicemanager_list_request");
|
|
||||||
send_event("slidecontroller_live_text_request");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
send_event("servicemanager_list_request");
|
|
||||||
send_event("slidecontroller_live_text_request");
|
|
||||||
send_event("remote_poll_request");
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>OpenLP Controller</h1>
|
|
||||||
<input type='button' value='<- Previous Slide'
|
|
||||||
onclick='send_event("slidecontroller_live_previous");' />
|
|
||||||
<input type='button' value='Next Slide ->'
|
|
||||||
onclick='send_event("slidecontroller_live_next");' />
|
|
||||||
<br>
|
|
||||||
<input type='button' value='<- Previous Item'
|
|
||||||
onclick='send_event("servicemanager_previous_item");' />
|
|
||||||
<input type='button' value='Next Item ->'
|
|
||||||
onclick='send_event("servicemanager_next_item");' />
|
|
||||||
<br/>
|
|
||||||
<label>Alert text</label><input id='alert' type='text' />
|
|
||||||
<input type='button' value='Send'
|
|
||||||
onclick='send_event("alerts_text",
|
|
||||||
document.getElementById("alert").value);' />
|
|
||||||
<br/>
|
|
||||||
<input type='button' value='Order of service'
|
|
||||||
onclick='send_event("servicemanager_list_request");'>
|
|
||||||
<div id='service'></div>
|
|
||||||
<input type='button' value='Current item'
|
|
||||||
onclick='send_event("slidecontroller_live_text_request");'>
|
|
||||||
<div id='currentitem'></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
"""
|
|
||||||
|
|
||||||
def load_params(self, query):
|
def load_params(self, query):
|
||||||
|
"""
|
||||||
|
Decode the query string parameters sent from the browser
|
||||||
|
"""
|
||||||
params = urlparse.parse_qs(query)
|
params = urlparse.parse_qs(query)
|
||||||
if not params:
|
if not params:
|
||||||
return None
|
return None
|
||||||
@ -252,6 +211,11 @@ send_event("remote_poll_request");
|
|||||||
return params['q']
|
return params['q']
|
||||||
|
|
||||||
def process_event(self, event, params):
|
def process_event(self, event, params):
|
||||||
|
"""
|
||||||
|
Send a signal to openlp to perform an action.
|
||||||
|
Currently lets anything through. Later we should restrict and perform
|
||||||
|
basic parameter checking, otherwise rogue clients could crash openlp
|
||||||
|
"""
|
||||||
if params:
|
if params:
|
||||||
Receiver.send_message(event, params)
|
Receiver.send_message(event, params)
|
||||||
else:
|
else:
|
||||||
@ -259,6 +223,16 @@ send_event("remote_poll_request");
|
|||||||
return u'OK'
|
return u'OK'
|
||||||
|
|
||||||
def process_request(self, event, params):
|
def process_request(self, event, params):
|
||||||
|
"""
|
||||||
|
Client has requested data. Send the signal and parameters for openlp
|
||||||
|
to handle, then listen out for a corresponding _request signal
|
||||||
|
which will have the data to return.
|
||||||
|
For most event timeout after 10 seconds (i.e. incase the signal
|
||||||
|
recipient isn't listening)
|
||||||
|
remotes_poll_request is a special case, this is a ajax long poll which
|
||||||
|
is just waiting for slide change/song change activity. This can wait
|
||||||
|
longer (one minute)
|
||||||
|
"""
|
||||||
if not event.endswith(u'_request'):
|
if not event.endswith(u'_request'):
|
||||||
return False
|
return False
|
||||||
self.event = event
|
self.event = event
|
||||||
@ -269,7 +243,7 @@ send_event("remote_poll_request");
|
|||||||
self.timer.setSingleShot(True)
|
self.timer.setSingleShot(True)
|
||||||
QtCore.QObject.connect(self.timer,
|
QtCore.QObject.connect(self.timer,
|
||||||
QtCore.SIGNAL(u'timeout()'), self.timeout)
|
QtCore.SIGNAL(u'timeout()'), self.timeout)
|
||||||
if event == 'remote_poll_request':
|
if event == 'remotes_poll_request':
|
||||||
self.timer.start(60000)
|
self.timer.start(60000)
|
||||||
else:
|
else:
|
||||||
self.timer.start(10000)
|
self.timer.start(10000)
|
||||||
@ -280,6 +254,10 @@ send_event("remote_poll_request");
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def process_response(self, data):
|
def process_response(self, data):
|
||||||
|
"""
|
||||||
|
The recipient of a _request signal has sent data. Convert this to
|
||||||
|
json and return it to client
|
||||||
|
"""
|
||||||
if not self.socket:
|
if not self.socket:
|
||||||
return
|
return
|
||||||
self.timer.stop()
|
self.timer.stop()
|
||||||
@ -289,19 +267,32 @@ send_event("remote_poll_request");
|
|||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def get_200_ok(self):
|
def get_200_ok(self):
|
||||||
|
"""
|
||||||
|
Successful request. Send OK headers. Assume html for now.
|
||||||
|
"""
|
||||||
return u'HTTP/1.1 200 OK\r\n' + \
|
return u'HTTP/1.1 200 OK\r\n' + \
|
||||||
u'Content-Type: text/html; charset="utf-8"\r\n' + \
|
u'Content-Type: text/html; charset="utf-8"\r\n' + \
|
||||||
u'\r\n'
|
u'\r\n'
|
||||||
|
|
||||||
def get_404_not_found(self):
|
def get_404_not_found(self):
|
||||||
|
"""
|
||||||
|
Invalid url. Say so
|
||||||
|
"""
|
||||||
return u'HTTP/1.1 404 Not Found\r\n'+ \
|
return u'HTTP/1.1 404 Not Found\r\n'+ \
|
||||||
u'Content-Type: text/html; charset="utf-8"\r\n' + \
|
u'Content-Type: text/html; charset="utf-8"\r\n' + \
|
||||||
u'\r\n'
|
u'\r\n'
|
||||||
|
|
||||||
def get_408_timeout(self):
|
def get_408_timeout(self):
|
||||||
|
"""
|
||||||
|
A _request hasn't returned anything in the timeout period.
|
||||||
|
Return timeout
|
||||||
|
"""
|
||||||
return u'HTTP/1.1 408 Request Timeout\r\n'
|
return u'HTTP/1.1 408 Request Timeout\r\n'
|
||||||
|
|
||||||
def timeout(self):
|
def timeout(self):
|
||||||
|
"""
|
||||||
|
Listener for timeout signal
|
||||||
|
"""
|
||||||
if not self.socket:
|
if not self.socket:
|
||||||
return
|
return
|
||||||
html = self.get_408_timeout()
|
html = self.get_408_timeout()
|
||||||
@ -309,10 +300,16 @@ send_event("remote_poll_request");
|
|||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def disconnected(self):
|
def disconnected(self):
|
||||||
|
"""
|
||||||
|
The client has disconnected. Tidy up
|
||||||
|
"""
|
||||||
log.debug(u'socket disconnected')
|
log.debug(u'socket disconnected')
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
"""
|
||||||
|
The server has closed the connection. Tidy up
|
||||||
|
"""
|
||||||
if not self.socket:
|
if not self.socket:
|
||||||
return
|
return
|
||||||
log.debug(u'close socket')
|
log.debug(u'close socket')
|
||||||
|
@ -36,17 +36,26 @@ class RemotesPlugin(Plugin):
|
|||||||
log.info(u'Remote Plugin loaded')
|
log.info(u'Remote Plugin loaded')
|
||||||
|
|
||||||
def __init__(self, plugin_helpers):
|
def __init__(self, plugin_helpers):
|
||||||
|
"""
|
||||||
|
remotes constructor
|
||||||
|
"""
|
||||||
Plugin.__init__(self, u'Remotes', u'1.9.1', plugin_helpers)
|
Plugin.__init__(self, u'Remotes', u'1.9.1', plugin_helpers)
|
||||||
self.weight = -1
|
self.weight = -1
|
||||||
self.server = None
|
self.server = None
|
||||||
|
|
||||||
def initialise(self):
|
def initialise(self):
|
||||||
|
"""
|
||||||
|
Initialise the remotes plugin, and start the http server
|
||||||
|
"""
|
||||||
log.debug(u'initialise')
|
log.debug(u'initialise')
|
||||||
Plugin.initialise(self)
|
Plugin.initialise(self)
|
||||||
self.insert_toolbox_item()
|
self.insert_toolbox_item()
|
||||||
self.server = HttpServer(self)
|
self.server = HttpServer(self)
|
||||||
|
|
||||||
def finalise(self):
|
def finalise(self):
|
||||||
|
"""
|
||||||
|
Tidy up and close down the http server
|
||||||
|
"""
|
||||||
log.debug(u'finalise')
|
log.debug(u'finalise')
|
||||||
self.remove_toolbox_item()
|
self.remove_toolbox_item()
|
||||||
if self.server:
|
if self.server:
|
||||||
@ -59,8 +68,11 @@ class RemotesPlugin(Plugin):
|
|||||||
return RemoteTab(self.name)
|
return RemoteTab(self.name)
|
||||||
|
|
||||||
def about(self):
|
def about(self):
|
||||||
|
"""
|
||||||
|
Information about this plugin
|
||||||
|
"""
|
||||||
about_text = self.trUtf8('<b>Remote Plugin</b><br>This plugin '
|
about_text = self.trUtf8('<b>Remote Plugin</b><br>This plugin '
|
||||||
'provides the ability to send messages to a running version of '
|
'provides the ability to send messages to a running version of '
|
||||||
'openlp on a different computer.<br>The Primary use for this '
|
'openlp on a different computer via a web browser or other app<br>'
|
||||||
'would be to send alerts from a creche')
|
'The Primary use for this would be to send alerts from a creche')
|
||||||
return about_text
|
return about_text
|
||||||
|
@ -24,34 +24,33 @@
|
|||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import socket
|
import urllib
|
||||||
import sys
|
import sys
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
|
||||||
def sendData(options, message):
|
def sendData(options):
|
||||||
addr = (options.address, options.port)
|
addr = 'http://%s:%s/send/%s?q=%s' % (options.address, options.port,
|
||||||
|
options.event, options.message)
|
||||||
try:
|
try:
|
||||||
UDPSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
|
urllib.urlopen(addr)
|
||||||
UDPSock.sendto(message, addr)
|
print u'Message sent ', addr
|
||||||
print u'message sent ', message, addr
|
|
||||||
except:
|
except:
|
||||||
print u'Errow thrown ', sys.exc_info()[1]
|
print u'Error thrown ', sys.exc_info()[1]
|
||||||
|
|
||||||
def format_message(options):
|
|
||||||
return u'%s:%s' % (u'alert', options.message)
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
usage = "usage: %prog [options] arg1 arg2"
|
usage = "usage: %prog [-a address] [-p port] [-e event] [-m message]"
|
||||||
parser = OptionParser(usage=usage)
|
parser = OptionParser(usage=usage)
|
||||||
parser.add_option("-v", "--verbose",
|
|
||||||
action="store_true", dest="verbose", default=True,
|
|
||||||
help="make lots of noise [%default]")
|
|
||||||
parser.add_option("-p", "--port", default=4316,
|
parser.add_option("-p", "--port", default=4316,
|
||||||
help="IP Port number %default ")
|
help="IP Port number %default ")
|
||||||
parser.add_option("-a", "--address",
|
parser.add_option("-a", "--address",
|
||||||
help="Recipient address ")
|
help="Recipient address ",
|
||||||
|
default="localhost")
|
||||||
|
parser.add_option("-e", "--event",
|
||||||
|
help="Action to be performed",
|
||||||
|
default="alerts_text")
|
||||||
parser.add_option("-m", "--message",
|
parser.add_option("-m", "--message",
|
||||||
help="Message to be passed for the action")
|
help="Message to be passed for the action",
|
||||||
|
default="")
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
if args:
|
if args:
|
||||||
@ -60,12 +59,8 @@ def main():
|
|||||||
elif options.address is None:
|
elif options.address is None:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
parser.error("IP address missing")
|
parser.error("IP address missing")
|
||||||
elif options.message is None:
|
|
||||||
parser.print_help()
|
|
||||||
parser.error("No message passed")
|
|
||||||
else:
|
else:
|
||||||
text = format_message(options)
|
sendData(options)
|
||||||
sendData(options, text)
|
|
||||||
|
|
||||||
if __name__ == u'__main__':
|
if __name__ == u'__main__':
|
||||||
main()
|
main()
|
||||||
|
Loading…
Reference in New Issue
Block a user