|
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
-
- # Carla bridge for LV2 modguis
- # Copyright (C) 2015-2019 Filipe Coelho <falktx@falktx.com>
- #
- # 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 2 of
- # the License, or 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.
- #
- # For a full copy of the GNU General Public License see the doc/GPL.txt file.
-
- # ------------------------------------------------------------------------------------------------------------
- # Imports (Global)
-
- import os
-
- from PyQt5.QtCore import pyqtSignal, QThread
-
- # ------------------------------------------------------------------------------------------------------------
- # Generate a random port number between 9000 and 18000
-
- from random import random
-
- PORTn = 8998 + int(random()*9000)
-
- # ------------------------------------------------------------------------------------------------------------
- # Imports (tornado)
-
- from tornado.log import enable_pretty_logging
- from tornado.ioloop import IOLoop
- from tornado.util import unicode_type
- from tornado.web import HTTPError
- from tornado.web import Application, RequestHandler, StaticFileHandler
-
- # ------------------------------------------------------------------------------------------------------------
- # Set up environment for the webserver
-
- PORT = str(PORTn)
- ROOT = "/usr/share/mod"
- DATA_DIR = os.path.expanduser("~/.local/share/mod-data/")
- HTML_DIR = os.path.join(ROOT, "html")
-
- os.environ['MOD_DEV_HOST'] = "1"
- os.environ['MOD_DEV_HMI'] = "1"
- os.environ['MOD_DESKTOP'] = "1"
-
- os.environ['MOD_DATA_DIR'] = DATA_DIR
- os.environ['MOD_HTML_DIR'] = HTML_DIR
- os.environ['MOD_KEY_PATH'] = os.path.join(DATA_DIR, "keys")
- os.environ['MOD_CLOUD_PUB'] = os.path.join(ROOT, "keys", "cloud_key.pub")
- os.environ['MOD_PLUGIN_LIBRARY_DIR'] = os.path.join(DATA_DIR, "lib")
-
- os.environ['MOD_PHANTOM_BINARY'] = "/usr/bin/phantomjs"
- os.environ['MOD_SCREENSHOT_JS'] = os.path.join(ROOT, "screenshot.js")
- os.environ['MOD_DEVICE_WEBSERVER_PORT'] = PORT
-
- # ------------------------------------------------------------------------------------------------------------
- # Imports (MOD)
-
- from mod.utils import get_plugin_info, get_plugin_gui, get_plugin_gui_mini, init as lv2_init
-
- # ------------------------------------------------------------------------------------------------------------
- # MOD related classes
-
- class JsonRequestHandler(RequestHandler):
- def write(self, data):
- if isinstance(data, (bytes, unicode_type, dict)):
- RequestHandler.write(self, data)
- self.finish()
- return
-
- elif data is True:
- data = "true"
- self.set_header("Content-Type", "application/json; charset=UTF-8")
-
- elif data is False:
- data = "false"
- self.set_header("Content-Type", "application/json; charset=UTF-8")
-
- else:
- data = json.dumps(data)
- self.set_header("Content-Type", "application/json; charset=UTF-8")
-
- RequestHandler.write(self, data)
- self.finish()
-
- class EffectGet(JsonRequestHandler):
- def get(self):
- uri = self.get_argument('uri')
-
- try:
- data = get_plugin_info(uri)
- except:
- print("ERROR: get_plugin_info for '%s' failed" % uri)
- raise HTTPError(404)
-
- self.write(data)
-
- class EffectFile(StaticFileHandler):
- def initialize(self):
- # return custom type directly. The browser will do the parsing
- self.custom_type = None
-
- uri = self.get_argument('uri')
-
- try:
- self.modgui = get_plugin_gui(uri)
- except:
- raise HTTPError(404)
-
- try:
- root = self.modgui['resourcesDirectory']
- except:
- raise HTTPError(404)
-
- return StaticFileHandler.initialize(self, root)
-
- def parse_url_path(self, prop):
- try:
- path = self.modgui[prop]
- except:
- raise HTTPError(404)
-
- if prop in ("iconTemplate", "settingsTemplate", "stylesheet", "javascript"):
- self.custom_type = "text/plain"
-
- return path
-
- def get_content_type(self):
- if self.custom_type is not None:
- return self.custom_type
- return StaticFileHandler.get_content_type(self)
-
- class EffectResource(StaticFileHandler):
-
- def initialize(self):
- # Overrides StaticFileHandler initialize
- pass
-
- def get(self, path):
- try:
- uri = self.get_argument('uri')
- except:
- return self.shared_resource(path)
-
- try:
- modgui = get_plugin_gui_mini(uri)
- except:
- raise HTTPError(404)
-
- try:
- root = modgui['resourcesDirectory']
- except:
- raise HTTPError(404)
-
- try:
- super(EffectResource, self).initialize(root)
- return super(EffectResource, self).get(path)
- except HTTPError as e:
- if e.status_code != 404:
- raise e
- return self.shared_resource(path)
- except IOError:
- raise HTTPError(404)
-
- def shared_resource(self, path):
- super(EffectResource, self).initialize(os.path.join(HTML_DIR, 'resources'))
- return super(EffectResource, self).get(path)
-
- # ------------------------------------------------------------------------------------------------------------
- # WebServer Thread
-
- class WebServerThread(QThread):
- # signals
- running = pyqtSignal()
-
- def __init__(self, parent=None):
- QThread.__init__(self, parent)
-
- self.fApplication = Application(
- [
- (r"/effect/get/?", EffectGet),
- (r"/effect/file/(.*)", EffectFile),
- (r"/resources/(.*)", EffectResource),
- (r"/(.*)", StaticFileHandler, {"path": HTML_DIR}),
- ],
- debug=True)
-
- self.fPrepareWasCalled = False
-
- def run(self):
- if not self.fPrepareWasCalled:
- self.fPrepareWasCalled = True
- self.fApplication.listen(PORT, address="0.0.0.0")
- if int(os.getenv("MOD_LOG", "0")):
- enable_pretty_logging()
-
- self.running.emit()
- IOLoop.instance().start()
-
- def stopWait(self):
- IOLoop.instance().stop()
- return self.wait(5000)
|