Stage works!

This commit is contained in:
Tim Bentley 2016-06-11 17:28:50 +01:00
parent 6a955a5573
commit 4a30e71a79
6 changed files with 304 additions and 106 deletions

View File

@ -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

View File

@ -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__)

View 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)

View 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)

View File

@ -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):

View File

@ -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)