mirror of https://gitlab.com/openlp/openlp.git
187 lines
7.4 KiB
Python
187 lines
7.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
##########################################################################
|
|
# OpenLP - Open Source Lyrics Projection #
|
|
# ---------------------------------------------------------------------- #
|
|
# Copyright (c) 2008-2019 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, either version 3 of the License, or #
|
|
# (at your option) any later version. #
|
|
# #
|
|
# 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, see <https://www.gnu.org/licenses/>. #
|
|
##########################################################################
|
|
"""
|
|
The :mod:`http` module contains the API web server. This is a lightweight web server used by remotes to interact
|
|
with OpenLP. It uses JSON to communicate with the remotes.
|
|
"""
|
|
import logging
|
|
import time
|
|
|
|
from PyQt5 import QtCore, QtWidgets
|
|
from waitress.server import create_server
|
|
|
|
from openlp.core.api.deploy import download_and_check, download_sha256
|
|
from openlp.core.api.endpoint.controller import api_controller_endpoint, controller_endpoint
|
|
from openlp.core.api.endpoint.core import blank_endpoint, chords_endpoint, main_endpoint, stage_endpoint
|
|
from openlp.core.api.endpoint.remote import remote_endpoint
|
|
from openlp.core.api.endpoint.service import api_service_endpoint, service_endpoint
|
|
from openlp.core.api.http import application, register_endpoint
|
|
from openlp.core.api.poll import Poller
|
|
from openlp.core.common.applocation import AppLocation
|
|
from openlp.core.common.i18n import UiStrings, translate
|
|
from openlp.core.common.mixins import LogMixin, RegistryProperties
|
|
from openlp.core.common.path import create_paths
|
|
from openlp.core.common.registry import Registry, RegistryBase
|
|
from openlp.core.common.settings import Settings
|
|
from openlp.core.threading import ThreadWorker, run_thread
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class HttpWorker(ThreadWorker):
|
|
"""
|
|
A special Qt thread class to allow the HTTP server to run at the same time as the UI.
|
|
"""
|
|
def start(self):
|
|
"""
|
|
Run the thread.
|
|
"""
|
|
address = Settings().value('api/ip address')
|
|
port = Settings().value('api/port')
|
|
Registry().execute('get_website_version')
|
|
try:
|
|
self.server = create_server(application, host=address, port=port)
|
|
self.server.run()
|
|
except OSError:
|
|
log.exception('An error occurred when serving the application.')
|
|
self.quit.emit()
|
|
|
|
def stop(self):
|
|
"""
|
|
A method to stop the worker
|
|
"""
|
|
if hasattr(self, 'server'):
|
|
# Loop through all the channels and close them to stop the server
|
|
for channel in self.server._map.values():
|
|
if hasattr(channel, 'close'):
|
|
channel.close()
|
|
|
|
|
|
class HttpServer(RegistryBase, RegistryProperties, LogMixin):
|
|
"""
|
|
Wrapper round a server instance
|
|
"""
|
|
def __init__(self, parent=None):
|
|
"""
|
|
Initialise the http server, and start the http server
|
|
"""
|
|
super(HttpServer, self).__init__(parent)
|
|
if not Registry().get_flag('no_web_server'):
|
|
worker = HttpWorker()
|
|
run_thread(worker, 'http_server')
|
|
Registry().register_function('download_website', self.first_time)
|
|
Registry().register_function('get_website_version', self.website_version)
|
|
Registry().set_flag('website_version', '0.0')
|
|
|
|
def bootstrap_post_set_up(self):
|
|
"""
|
|
Register the poll return service and start the servers.
|
|
"""
|
|
self.initialise()
|
|
self.poller = Poller()
|
|
Registry().register('poller', self.poller)
|
|
application.initialise()
|
|
register_endpoint(controller_endpoint)
|
|
register_endpoint(api_controller_endpoint)
|
|
register_endpoint(chords_endpoint)
|
|
register_endpoint(stage_endpoint)
|
|
register_endpoint(blank_endpoint)
|
|
register_endpoint(main_endpoint)
|
|
register_endpoint(service_endpoint)
|
|
register_endpoint(api_service_endpoint)
|
|
register_endpoint(remote_endpoint)
|
|
|
|
@staticmethod
|
|
def initialise():
|
|
"""
|
|
Create the internal file structure if it does not exist
|
|
:return:
|
|
"""
|
|
create_paths(AppLocation.get_section_data_path('remotes') / 'assets',
|
|
AppLocation.get_section_data_path('remotes') / 'images',
|
|
AppLocation.get_section_data_path('remotes') / 'static',
|
|
AppLocation.get_section_data_path('remotes') / 'static' / 'index',
|
|
AppLocation.get_section_data_path('remotes') / 'templates')
|
|
|
|
def first_time(self):
|
|
"""
|
|
Import web site code if active
|
|
"""
|
|
self.application.process_events()
|
|
progress = DownloadProgressDialog(self)
|
|
progress.forceShow()
|
|
self.application.process_events()
|
|
time.sleep(1)
|
|
download_and_check(progress)
|
|
self.application.process_events()
|
|
time.sleep(1)
|
|
progress.close()
|
|
self.application.process_events()
|
|
Settings().setValue('remotes/download version', self.version)
|
|
|
|
def website_version(self):
|
|
"""
|
|
Download and save the website version and sha256
|
|
:return: None
|
|
"""
|
|
sha256, self.version = download_sha256()
|
|
Registry().set_flag('website_sha256', sha256)
|
|
Registry().set_flag('website_version', self.version)
|
|
|
|
|
|
class DownloadProgressDialog(QtWidgets.QProgressDialog):
|
|
"""
|
|
Local class to handle download display based and supporting httputils:get_web_page
|
|
"""
|
|
def __init__(self, parent):
|
|
super(DownloadProgressDialog, self).__init__(parent.main_window)
|
|
self.parent = parent
|
|
self.setWindowModality(QtCore.Qt.WindowModal)
|
|
self.setWindowTitle(translate('RemotePlugin', 'Importing Website'))
|
|
self.setLabelText(UiStrings().StartingImport)
|
|
self.setCancelButton(None)
|
|
self.setRange(0, 1)
|
|
self.setMinimumDuration(0)
|
|
self.was_cancelled = False
|
|
self.previous_size = 0
|
|
|
|
def update_progress(self, count, block_size):
|
|
"""
|
|
Calculate and display the download progress.
|
|
"""
|
|
increment = (count * block_size) - self.previous_size
|
|
self._increment_progress_bar(None, increment)
|
|
self.previous_size = count * block_size
|
|
|
|
def _increment_progress_bar(self, status_text, increment=1):
|
|
"""
|
|
Update the wizard progress page.
|
|
|
|
:param status_text: Current status information to display.
|
|
:param increment: The value to increment the progress bar by.
|
|
"""
|
|
if status_text:
|
|
self.setText(status_text)
|
|
if increment > 0:
|
|
self.setValue(self.value() + increment)
|
|
self.parent.application.process_events()
|