forked from openlp/openlp
Stage works!
This commit is contained in:
parent
6a955a5573
commit
4a30e71a79
@ -39,13 +39,13 @@ def _route_from_url(url_prefix, url):
|
||||
return url
|
||||
|
||||
|
||||
def register_endpoint(endpoint):
|
||||
def register_endpoint(end_point):
|
||||
"""
|
||||
Register an endpoint with the app
|
||||
"""
|
||||
print("ep", endpoint)
|
||||
for url, view_func, method, secure in endpoint.routes:
|
||||
route = _route_from_url(endpoint.url_prefix, url)
|
||||
print("ep", end_point)
|
||||
for url, view_func, method, secure in end_point.routes:
|
||||
route = _route_from_url(end_point.url_prefix, url)
|
||||
application.add_route(route, view_func, method, secure)
|
||||
|
||||
from .endpoint import Endpoint
|
||||
|
@ -23,7 +23,10 @@ import logging
|
||||
|
||||
from openlp.core.api import OpenWSServer, OpenLPPoll, OpenLPHttpServer
|
||||
from openlp.core.common import OpenLPMixin, Registry, RegistryMixin, RegistryProperties
|
||||
from openlp.core.api.uiinterfaces import stage_endpoint
|
||||
|
||||
# These are here to load the endpoints
|
||||
from openlp.core.api.coreendpoints import stage_endpoint
|
||||
from openlp.core.api.controllerendpoints import controller_endpoint
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
122
openlp/core/api/controllerendpoints.py
Normal file
122
openlp/core/api/controllerendpoints.py
Normal file
@ -0,0 +1,122 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2016 OpenLP Developers #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
import logging
|
||||
import os
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
from openlp.core.api import Endpoint, register_endpoint
|
||||
from openlp.core.common import Registry, AppLocation, Settings
|
||||
from openlp.core.lib import ItemCapabilities, create_thumb
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
controller_endpoint = Endpoint('api')
|
||||
|
||||
|
||||
@controller_endpoint.route('controller/live/text')
|
||||
def controller_text(request):
|
||||
"""
|
||||
Perform an action on the slide controller.
|
||||
|
||||
:param request: the http request - not used
|
||||
"""
|
||||
log.debug("controller_text ")
|
||||
live_controller = Registry().get('live_controller')
|
||||
current_item = live_controller.service_item
|
||||
data = []
|
||||
if current_item:
|
||||
for index, frame in enumerate(current_item.get_frames()):
|
||||
item = {}
|
||||
# Handle text (songs, custom, bibles)
|
||||
if current_item.is_text():
|
||||
if frame['verseTag']:
|
||||
item['tag'] = str(frame['verseTag'])
|
||||
else:
|
||||
item['tag'] = str(index + 1)
|
||||
item['text'] = str(frame['text'])
|
||||
item['html'] = str(frame['html'])
|
||||
# Handle images, unless a custom thumbnail is given or if thumbnails is disabled
|
||||
elif current_item.is_image() and not frame.get('image', '') and Settings().value('remotes/thumbnails'):
|
||||
item['tag'] = str(index + 1)
|
||||
thumbnail_path = os.path.join('images', 'thumbnails', frame['title'])
|
||||
full_thumbnail_path = os.path.join(AppLocation.get_data_path(), thumbnail_path)
|
||||
# Create thumbnail if it doesn't exists
|
||||
if not os.path.exists(full_thumbnail_path):
|
||||
create_thumb(current_item.get_frame_path(index), full_thumbnail_path, False)
|
||||
item['img'] = urllib.request.pathname2url(os.path.sep + thumbnail_path)
|
||||
item['text'] = str(frame['title'])
|
||||
item['html'] = str(frame['title'])
|
||||
else:
|
||||
# Handle presentation etc.
|
||||
item['tag'] = str(index + 1)
|
||||
if current_item.is_capable(ItemCapabilities.HasDisplayTitle):
|
||||
item['title'] = str(frame['display_title'])
|
||||
if current_item.is_capable(ItemCapabilities.HasNotes):
|
||||
item['slide_notes'] = str(frame['notes'])
|
||||
if current_item.is_capable(ItemCapabilities.HasThumbnails) and \
|
||||
Settings().value('remotes/thumbnails'):
|
||||
# If the file is under our app directory tree send the portion after the match
|
||||
data_path = AppLocation.get_data_path()
|
||||
if frame['image'][0:len(data_path)] == data_path:
|
||||
item['img'] = urllib.request.pathname2url(frame['image'][len(data_path):])
|
||||
item['text'] = str(frame['title'])
|
||||
item['html'] = str(frame['title'])
|
||||
item['selected'] = (live_controller.selected_row == index)
|
||||
data.append(item)
|
||||
json_data = {'results': {'slides': data}}
|
||||
if current_item:
|
||||
json_data['results']['item'] = live_controller.service_item.unique_identifier
|
||||
return json_data
|
||||
|
||||
|
||||
@controller_endpoint.route('service/list')
|
||||
def service_list(request):
|
||||
"""
|
||||
Handles requests for service items in the service manager
|
||||
|
||||
"""
|
||||
return {'results': {'items': get_service_items()}}
|
||||
|
||||
|
||||
def get_service_items():
|
||||
"""
|
||||
Read the service item in use and return the data as a json object
|
||||
"""
|
||||
live_controller = Registry().get('live_controller')
|
||||
service_items = []
|
||||
if live_controller.service_item:
|
||||
current_unique_identifier = live_controller.service_item.unique_identifier
|
||||
else:
|
||||
current_unique_identifier = None
|
||||
for item in Registry().get('service_manager').service_items:
|
||||
service_item = item['service_item']
|
||||
service_items.append({
|
||||
'id': str(service_item.unique_identifier),
|
||||
'title': str(service_item.get_display_title()),
|
||||
'plugin': str(service_item.name),
|
||||
'notes': str(service_item.notes),
|
||||
'selected': (service_item.unique_identifier == current_unique_identifier)
|
||||
})
|
||||
return service_items
|
||||
|
||||
register_endpoint(controller_endpoint)
|
166
openlp/core/api/coreendpoints.py
Normal file
166
openlp/core/api/coreendpoints.py
Normal file
@ -0,0 +1,166 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
from openlp.core.api import Endpoint, register_endpoint
|
||||
from openlp.core.common import AppLocation, UiStrings, translate
|
||||
|
||||
|
||||
from mako.template import Template
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
stage_endpoint = Endpoint('')
|
||||
|
||||
FILE_TYPES = {
|
||||
'.html': 'text/html',
|
||||
'.css': 'text/css',
|
||||
'.js': 'application/javascript',
|
||||
'.jpg': 'image/jpeg',
|
||||
'.gif': 'image/gif',
|
||||
'.ico': 'image/x-icon',
|
||||
'.png': 'image/png'
|
||||
}
|
||||
|
||||
remote = translate('RemotePlugin.Mobile', 'Remote')
|
||||
stage = translate('RemotePlugin.Mobile', 'Stage View')
|
||||
live = translate('RemotePlugin.Mobile', 'Live View')
|
||||
|
||||
template_vars = {
|
||||
'app_title': "{main} {remote}".format(main=UiStrings().OLPV2x, remote=remote),
|
||||
'stage_title': "{main} {stage}".format(main=UiStrings().OLPV2x, stage=stage),
|
||||
'live_title': "{main} {live}".format(main=UiStrings().OLPV2x, live=live),
|
||||
'service_manager': translate('RemotePlugin.Mobile', 'Service Manager'),
|
||||
'slide_controller': translate('RemotePlugin.Mobile', 'Slide Controller'),
|
||||
'alerts': translate('RemotePlugin.Mobile', 'Alerts'),
|
||||
'search': translate('RemotePlugin.Mobile', 'Search'),
|
||||
'home': translate('RemotePlugin.Mobile', 'Home'),
|
||||
'refresh': translate('RemotePlugin.Mobile', 'Refresh'),
|
||||
'blank': translate('RemotePlugin.Mobile', 'Blank'),
|
||||
'theme': translate('RemotePlugin.Mobile', 'Theme'),
|
||||
'desktop': translate('RemotePlugin.Mobile', 'Desktop'),
|
||||
'show': translate('RemotePlugin.Mobile', 'Show'),
|
||||
'prev': translate('RemotePlugin.Mobile', 'Prev'),
|
||||
'next': translate('RemotePlugin.Mobile', 'Next'),
|
||||
'text': translate('RemotePlugin.Mobile', 'Text'),
|
||||
'show_alert': translate('RemotePlugin.Mobile', 'Show Alert'),
|
||||
'go_live': translate('RemotePlugin.Mobile', 'Go Live'),
|
||||
'add_to_service': translate('RemotePlugin.Mobile', 'Add to Service'),
|
||||
'add_and_go_to_service': translate('RemotePlugin.Mobile', 'Add & Go to Service'),
|
||||
'no_results': translate('RemotePlugin.Mobile', 'No Results'),
|
||||
'options': translate('RemotePlugin.Mobile', 'Options'),
|
||||
'service': translate('RemotePlugin.Mobile', 'Service'),
|
||||
'slides': translate('RemotePlugin.Mobile', 'Slides'),
|
||||
'settings': translate('RemotePlugin.Mobile', 'Settings'),
|
||||
}
|
||||
|
||||
|
||||
@stage_endpoint.route('$')
|
||||
@stage_endpoint.route('(stage)$')
|
||||
@stage_endpoint.route('(main)$')
|
||||
@stage_endpoint.route('(css)')
|
||||
@stage_endpoint.route('(js)')
|
||||
@stage_endpoint.route('(assets)')
|
||||
def file_access(request):
|
||||
"""
|
||||
Get a list of songs`
|
||||
"""
|
||||
file_name = request.path
|
||||
html_dir = os.path.join(AppLocation.get_directory(AppLocation.AppDir), 'core', 'api', 'html')
|
||||
log.debug('serve file request {name}'.format(name=file_name))
|
||||
if file_name.startswith('/'):
|
||||
file_name = file_name[1:]
|
||||
if not file_name:
|
||||
file_name = 'index.html'
|
||||
if '.' not in file_name:
|
||||
file_name += '.html'
|
||||
if file_name.startswith('/'):
|
||||
file_name = file_name[1:]
|
||||
path = os.path.normpath(os.path.join(html_dir, file_name))
|
||||
return _process_file(path)
|
||||
|
||||
|
||||
@stage_endpoint.route('(stage)/(.*)$')
|
||||
def bespoke_file_access(request):
|
||||
"""
|
||||
Allow Stage view to be delivered with custom views.
|
||||
|
||||
:param request: base path of the URL. Not used but passed by caller
|
||||
:return:
|
||||
"""
|
||||
file_name = request.path
|
||||
config_dir = os.path.join(AppLocation.get_data_path(), 'stages')
|
||||
log.debug('serve file request {name}'.format(name=file_name))
|
||||
parts = file_name.split('/')
|
||||
if len(parts) == 1:
|
||||
file_name = os.path.join(parts[0], 'stage.html')
|
||||
elif len(parts) == 3:
|
||||
file_name = os.path.join(parts[1], parts[2])
|
||||
path = os.path.normpath(os.path.join(config_dir, file_name))
|
||||
return _process_file(path)
|
||||
|
||||
|
||||
@stage_endpoint.route('main/image$')
|
||||
def main_image(request):
|
||||
"""
|
||||
Return the latest display image as a byte stream.
|
||||
:param request: base path of the URL. Not used but passed by caller
|
||||
:return:
|
||||
"""
|
||||
# result = {
|
||||
# 'slide_image': 'data:image/png;base64,' + str(image_to_byte(self.live_controller.slide_image))
|
||||
# }
|
||||
# self.do_json_header()
|
||||
# return json.dumps({'results': result}).encode()
|
||||
pass
|
||||
|
||||
@stage_endpoint.route(r'^/(\w+)/thumbnails([^/]+)?/(.*)$')
|
||||
def main_image(request):
|
||||
"""
|
||||
Get a list of songs
|
||||
:param request: base path of the URL. Not used but passed by caller
|
||||
:return:
|
||||
"""
|
||||
# songs = db.query(Song).get()
|
||||
# return {'songs': [dictify(song) for song in songs]}
|
||||
print("AAA")
|
||||
|
||||
|
||||
def _process_file(path):
|
||||
"""
|
||||
Common file processing code
|
||||
|
||||
:param path: path to file to be loaded
|
||||
:return: web resource to be loaded
|
||||
"""
|
||||
ext, content_type = get_content_type(path)
|
||||
file_handle = None
|
||||
try:
|
||||
if ext == '.html':
|
||||
variables = template_vars
|
||||
content = Template(filename=path, input_encoding='utf-8').render(**variables)
|
||||
else:
|
||||
file_handle = open(path, 'rb')
|
||||
log.debug('Opened {path}'.format(path=path))
|
||||
content = file_handle.read().decode("utf-8")
|
||||
except IOError:
|
||||
log.exception('Failed to open {path}'.format(path=path))
|
||||
return None
|
||||
finally:
|
||||
if file_handle:
|
||||
file_handle.close()
|
||||
return content
|
||||
|
||||
|
||||
def get_content_type(file_name):
|
||||
"""
|
||||
Examines the extension of the file and determines what the content_type should be, defaults to text/plain
|
||||
Returns the extension and the content_type
|
||||
|
||||
:param file_name: name of file
|
||||
"""
|
||||
ext = os.path.splitext(file_name)[1]
|
||||
content_type = FILE_TYPES.get(ext, 'text/plain')
|
||||
return ext, content_type
|
||||
|
||||
register_endpoint(stage_endpoint)
|
@ -37,6 +37,7 @@ def _make_response(view_result):
|
||||
"""
|
||||
Create a Response object from response
|
||||
"""
|
||||
print(view_result)
|
||||
if isinstance(view_result, Response):
|
||||
return view_result
|
||||
elif isinstance(view_result, tuple):
|
||||
@ -54,8 +55,12 @@ def _make_response(view_result):
|
||||
return Response(body=json.dumps(view_result), status=200,
|
||||
content_type='application/json', charset='utf8')
|
||||
elif isinstance(view_result, str):
|
||||
return Response(body=view_result, status=200,
|
||||
content_type='text/html', charset='utf8')
|
||||
if 'body {' in view_result:
|
||||
return Response(body=view_result, status=200,
|
||||
content_type='text/css', charset='utf8')
|
||||
else:
|
||||
return Response(body=view_result, status=200,
|
||||
content_type='text/html', charset='utf8')
|
||||
|
||||
|
||||
def _handle_exception(error):
|
||||
@ -92,14 +97,13 @@ class WSGIApplication(object):
|
||||
"""
|
||||
Find the appropriate URL and run the view function
|
||||
"""
|
||||
print(request.path)
|
||||
print(self.route_map.items())
|
||||
for route, views in self.route_map.items():
|
||||
if re.match(route, request.path):
|
||||
if request.method.upper() in views:
|
||||
log.debug('Found {method} {url}'.format(method=request.method, url=request.path))
|
||||
view_func = views[request.method.upper()]['function']
|
||||
return _make_response(view_func(request))
|
||||
log.error('Not Found url {url} '.format(url=request.path))
|
||||
raise NotFound()
|
||||
|
||||
def wsgi_app(self, environ, start_response):
|
||||
|
@ -1,97 +0,0 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
from openlp.core.api import Endpoint, register_endpoint
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
stage_endpoint = Endpoint('')
|
||||
|
||||
|
||||
@stage_endpoint.route('$')
|
||||
@stage_endpoint.route('(stage)$')
|
||||
@stage_endpoint.route('(main)$')
|
||||
def file_access(request):
|
||||
"""
|
||||
Get a list of songs`
|
||||
"""
|
||||
#songs = db.query(Song).get()
|
||||
#return {'songs': [dictify(song) for song in songs]}
|
||||
print("AAA")
|
||||
|
||||
|
||||
@stage_endpoint.route('(stage)/(.*)$')
|
||||
def bespoke_file_access(request):
|
||||
"""
|
||||
Allow Stage view to be delivered with custom views.
|
||||
|
||||
:param url_path: base path of the URL. Not used but passed by caller
|
||||
:param file_name: file name with path
|
||||
:return:
|
||||
"""
|
||||
pass
|
||||
# log.debug('serve file request {name}'.format(name=file_name))
|
||||
# parts = file_name.split('/')
|
||||
# if len(parts) == 1:
|
||||
# file_name = os.path.join(parts[0], 'stage.html')
|
||||
# elif len(parts) == 3:
|
||||
# file_name = os.path.join(parts[1], parts[2])
|
||||
# path = os.path.normpath(os.path.join(self.config_dir, file_name))
|
||||
# if not path.startswith(self.config_dir):
|
||||
# return self.do_not_found()
|
||||
# return _process_file(path)
|
||||
|
||||
|
||||
@stage_endpoint.route('main/image$')
|
||||
def main_image(request):
|
||||
"""
|
||||
Return the latest display image as a byte stream.
|
||||
"""
|
||||
# result = {
|
||||
# 'slide_image': 'data:image/png;base64,' + str(image_to_byte(self.live_controller.slide_image))
|
||||
# }
|
||||
# self.do_json_header()
|
||||
# return json.dumps({'results': result}).encode()
|
||||
pass
|
||||
|
||||
@stage_endpoint.route(r'^/(\w+)/thumbnails([^/]+)?/(.*)$')
|
||||
def main_image(request):
|
||||
"""
|
||||
Get a list of songs
|
||||
"""
|
||||
# songs = db.query(Song).get()
|
||||
# return {'songs': [dictify(song) for song in songs]}
|
||||
print("AAA")
|
||||
|
||||
|
||||
def _process_file(self, path):
|
||||
"""
|
||||
Common file processing code
|
||||
|
||||
:param path: path to file to be loaded
|
||||
:return: web resource to be loaded
|
||||
"""
|
||||
# content = None
|
||||
# ext, content_type = self.get_content_type(path)
|
||||
# file_handle = None
|
||||
# try:
|
||||
# if ext == '.html':
|
||||
# variables = self.template_vars
|
||||
# content = Template(filename=path, input_encoding='utf-8', output_encoding='utf-8').render(**variables)
|
||||
# else:
|
||||
# file_handle = open(path, 'rb')
|
||||
# log.debug('Opened {path}'.format(path=path))
|
||||
# content = file_handle.read()
|
||||
# except IOError:
|
||||
# log.exception('Failed to open {path}'.format(path=path))
|
||||
# return self.do_not_found()
|
||||
# finally:
|
||||
# if file_handle:
|
||||
# file_handle.close()
|
||||
# self.send_response(200)
|
||||
# self.send_header('Content-type', content_type)
|
||||
# self.end_headers()
|
||||
# return content
|
||||
pass
|
||||
|
||||
register_endpoint(stage_endpoint)
|
Loading…
Reference in New Issue
Block a user