Browse Source

Remove old, non-working modgui related code

Signed-off-by: falkTX <falktx@falktx.com>
pull/1996/head
falkTX 7 months ago
parent
commit
54ebc831f5
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
10 changed files with 7 additions and 942 deletions
  1. +0
    -24
      Makefile
  2. +0
    -11
      data/carla-bridge-lv2-modgui
  3. +6
    -24
      source/backend/plugin/CarlaPluginLV2.cpp
  4. +0
    -2
      source/frontend/Makefile
  5. +0
    -77
      source/frontend/carla_modgui.py
  6. +0
    -0
      source/frontend/modgui/__init__.py
  7. +0
    -546
      source/frontend/modgui/host.py
  8. +0
    -225
      source/frontend/modgui/webserver.py
  9. +0
    -2
      source/includes/lv2_rdf.hpp
  10. +1
    -31
      source/utils/CarlaLv2Utils.hpp

+ 0
- 24
Makefile View File

@@ -428,7 +428,6 @@ ifeq ($(HAVE_FRONTEND),true)
install -d $(DESTDIR)$(DATADIR)/carla/resources/translations
install -d $(DESTDIR)$(DATADIR)/carla/common
install -d $(DESTDIR)$(DATADIR)/carla/dialogs
install -d $(DESTDIR)$(DATADIR)/carla/modgui
install -d $(DESTDIR)$(DATADIR)/carla/patchcanvas
install -d $(DESTDIR)$(DATADIR)/carla/utils
install -d $(DESTDIR)$(DATADIR)/carla/widgets
@@ -563,14 +562,6 @@ ifeq ($(HAVE_LIBLO),true)
$(DESTDIR)$(BINDIR)/carla-control
endif

# Install the real modgui bridge
install -m 755 \
data/carla-bridge-lv2-modgui \
$(DESTDIR)$(LIBDIR)/carla

sed $(SED_ARGS) 's?X-PREFIX-X?$(PREFIX)?' \
$(DESTDIR)$(LIBDIR)/carla/carla-bridge-lv2-modgui

# Install frontend
install -m 644 \
source/frontend/carla \
@@ -590,10 +581,6 @@ endif
source/frontend/dialogs/*.py \
$(DESTDIR)$(DATADIR)/carla/dialogs/

install -m 644 \
source/frontend/modgui/*.py \
$(DESTDIR)$(DATADIR)/carla/modgui/

install -m 644 \
source/frontend/patchcanvas/*.py \
$(DESTDIR)$(DATADIR)/carla/patchcanvas/
@@ -672,7 +659,6 @@ endif
# Install resources (re-use python files)
$(LINK) ../common $(DESTDIR)$(DATADIR)/carla/resources
$(LINK) ../dialogs $(DESTDIR)$(DATADIR)/carla/resources
$(LINK) ../modgui $(DESTDIR)$(DATADIR)/carla/resources
$(LINK) ../patchcanvas $(DESTDIR)$(DATADIR)/carla/resources
$(LINK) ../utils $(DESTDIR)$(DATADIR)/carla/resources
$(LINK) ../widgets $(DESTDIR)$(DATADIR)/carla/resources
@@ -780,16 +766,6 @@ ifeq ($(HAVE_FRONTEND),true)
rm -rf $(DESTDIR)$(LIBDIR)/vst/carla.vst/styles
$(LINK) ../../carla/styles $(DESTDIR)$(LIBDIR)/vst/carla.vst/styles
endif
endif

# -------------------------------------------------------------------------------------------------------------

ifneq ($(HAVE_FRONTEND),true)
# Remove gui files for non-gui build
rm $(DESTDIR)$(LIBDIR)/carla/carla-bridge-lv2-modgui
ifeq ($(CAN_GENERATE_LV2_TTL),true)
rm $(DESTDIR)$(LIBDIR)/lv2/carla.lv2/carla-bridge-lv2-modgui
endif
endif

# ---------------------------------------------------------------------------------------------------------------------


+ 0
- 11
data/carla-bridge-lv2-modgui View File

@@ -1,11 +0,0 @@
#!/bin/sh

PYTHON=$(which python3 2>/dev/null)

if [ ! -f ${PYTHON} ]; then
PYTHON=python
fi

INSTALL_PREFIX="X-PREFIX-X"
export CARLA_LIB_PREFIX="$INSTALL_PREFIX"
exec $PYTHON "$INSTALL_PREFIX"/share/carla/carla_modgui.py "$@"

+ 6
- 24
source/backend/plugin/CarlaPluginLV2.cpp View File

@@ -1940,11 +1940,6 @@ public:

fPipeServer.syncMessages();
}

#ifndef BUILD_BRIDGE
if (fUI.rdfDescriptor->Type == LV2_UI_MOD)
pData->tryTransient();
#endif
}
else
{
@@ -5394,9 +5389,6 @@ public:
case LV2_UI_X11:
bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-x11";
break;
case LV2_UI_MOD:
bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-modgui";
break;
#if 0
case LV2_UI_EXTERNAL:
case LV2_UI_OLD_EXTERNAL:
@@ -6990,8 +6982,8 @@ public:
// ---------------------------------------------------------------
// find the most appropriate ui

int eQt4, eQt5, eGtk2, eGtk3, eCocoa, eWindows, eX11, eMod, iCocoa, iWindows, iX11, iExt, iFinal;
eQt4 = eQt5 = eGtk2 = eGtk3 = eCocoa = eWindows = eX11 = eMod = iCocoa = iWindows = iX11 = iExt = iFinal = -1;
int eQt4, eQt5, eGtk2, eGtk3, eCocoa, eWindows, eX11, iCocoa, iWindows, iX11, iExt, iFinal;
eQt4 = eQt5 = eGtk2 = eGtk3 = eCocoa = eWindows = eX11 = iCocoa = iWindows = iX11 = iExt = iFinal = -1;

#if defined(LV2_UIS_ONLY_BRIDGES)
const bool preferUiBridges = true;
@@ -7049,9 +7041,6 @@ public:
case LV2_UI_OLD_EXTERNAL:
iExt = ii;
break;
case LV2_UI_MOD:
eMod = ii;
break;
default:
break;
}
@@ -7118,14 +7107,8 @@ public:

if (iFinal < 0)
{
if (eMod < 0)
{
carla_stderr("Failed to find an appropriate LV2 UI for this plugin");
return;
}

// use MODGUI as last resort
iFinal = eMod;
carla_stderr("Failed to find an appropriate LV2 UI for this plugin");
return;
}
}

@@ -7179,8 +7162,7 @@ public:
iFinal == eGtk3 ||
iFinal == eCocoa ||
iFinal == eWindows ||
iFinal == eX11 ||
iFinal == eMod)
iFinal == eX11)
#ifdef BUILD_BRIDGE
&& ! hasShowInterface
#endif
@@ -7214,7 +7196,7 @@ public:
return;
}

if (iFinal == eQt4 || iFinal == eQt5 || iFinal == eGtk2 || iFinal == eGtk3 || iFinal == eMod)
if (iFinal == eQt4 || iFinal == eQt5 || iFinal == eGtk2 || iFinal == eGtk3)
{
carla_stderr2("Failed to find UI bridge binary for '%s', cannot use UI", pData->name);
fUI.rdfDescriptor = nullptr;


+ 0
- 2
source/frontend/Makefile View File

@@ -69,7 +69,6 @@ OBJS = $(CPP_FILES:%=$(OBJDIR)/%.o)
RES = \
qt_config.py \
resources_rc.py \
$(BINDIR)/resources/modgui \
$(BINDIR)/resources/patchcanvas \
$(BINDIR)/resources/widgets \
$(BINDIR)/resources/bigmeter-ui \
@@ -80,7 +79,6 @@ RES = \
$(BINDIR)/resources/carla_backend_qt.py \
$(BINDIR)/resources/carla_host.py \
$(BINDIR)/resources/carla_host_control.py \
$(BINDIR)/resources/carla_modgui.py \
$(BINDIR)/resources/carla_settings.py \
$(BINDIR)/resources/carla_skin.py \
$(BINDIR)/resources/carla_shared.py \


+ 0
- 77
source/frontend/carla_modgui.py View File

@@ -1,77 +0,0 @@
#!/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
import sys

# ------------------------------------------------------------------------------------------------------------
# Imports (local)

from carla_app import CarlaApplication, gCarla, getPaths
from carla_shared import DLL_EXTENSION, setUpSignals
from carla_utils import CarlaUtils

from modgui.host import HostWindow

# ------------------------------------------------------------------------------------------------------------
# Main

if __name__ == '__main__':
# -------------------------------------------------------------
# Read CLI args

if len(sys.argv) < 2:
print("usage: %s <plugin-uri>" % sys.argv[0])
sys.exit(1)

libPrefix = os.getenv("CARLA_LIB_PREFIX")

# -------------------------------------------------------------
# App initialization

app = CarlaApplication("Carla2-MODGUI", libPrefix)

# -------------------------------------------------------------
# Init utils

pathBinaries, pathResources = getPaths(libPrefix)

utilsname = "libcarla_utils.%s" % (DLL_EXTENSION)

gCarla.utils = CarlaUtils(os.path.join(pathBinaries, utilsname))
gCarla.utils.set_process_name("carla-bridge-lv2-modgui")

# -------------------------------------------------------------
# Set-up custom signal handling

setUpSignals()

# -------------------------------------------------------------
# Create GUI

gui = HostWindow()

# --------------------------------------------------------------------------------------------------------
# App-Loop

app.exit_exec()

# ------------------------------------------------------------------------------------------------------------

+ 0
- 0
source/frontend/modgui/__init__.py View File


+ 0
- 546
source/frontend/modgui/host.py View File

@@ -1,546 +0,0 @@
#!/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)

from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QPoint, QSize, QUrl
from PyQt5.QtGui import QImage, QPainter, QPalette
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtWebKitWidgets import QWebView

import sys

# ------------------------------------------------------------------------------------------------------------
# Imports (Custom)

from carla_host import charPtrToString, gCarla
from .webserver import WebServerThread, PORT

# ------------------------------------------------------------------------------------------------------------
# Imports (MOD)

from modtools.utils import get_plugin_info, init as lv2_init

# ------------------------------------------------------------------------------------------------------------
# Host Window

class HostWindow(QMainWindow):
# signals
SIGTERM = pyqtSignal()
SIGUSR1 = pyqtSignal()

# --------------------------------------------------------------------------------------------------------

def __init__(self):
QMainWindow.__init__(self)
gCarla.gui = self

URI = sys.argv[1]

# ----------------------------------------------------------------------------------------------------
# Internal stuff

self.fCurrentFrame = None
self.fDocElemement = None
self.fCanSetValues = False
self.fNeedsShow = False
self.fSizeSetup = False
self.fQuitReceived = False
self.fWasRepainted = False

lv2_init()

self.fPlugin = get_plugin_info(URI)
self.fPorts = self.fPlugin['ports']
self.fPortSymbols = {}
self.fPortValues = {}
self.fParamTypes = {}
self.fParamValues = {}

for port in self.fPorts['control']['input']:
self.fPortSymbols[port['index']] = (port['symbol'], False)
self.fPortValues [port['index']] = port['ranges']['default']

for port in self.fPorts['control']['output']:
self.fPortSymbols[port['index']] = (port['symbol'], True)
self.fPortValues [port['index']] = port['ranges']['default']

for parameter in self.fPlugin['parameters']:
if parameter['ranges'] is None:
continue
if parameter['type'] == "http://lv2plug.in/ns/ext/atom#Bool":
paramtype = 'b'
elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#Int":
paramtype = 'i'
elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#Long":
paramtype = 'l'
elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#Float":
paramtype = 'f'
elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#Double":
paramtype = 'g'
elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#String":
paramtype = 's'
elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#Path":
paramtype = 'p'
elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#URI":
paramtype = 'u'
else:
continue
if paramtype not in ('s','p','u') and parameter['ranges']['minimum'] == parameter['ranges']['maximum']:
continue
self.fParamTypes [parameter['uri']] = paramtype
self.fParamValues[parameter['uri']] = parameter['ranges']['default']

# ----------------------------------------------------------------------------------------------------
# Init pipe

if len(sys.argv) == 7:
self.fPipeClient = gCarla.utils.pipe_client_new(lambda s,msg: self.msgCallback(msg))
else:
self.fPipeClient = None

# ----------------------------------------------------------------------------------------------------
# Init Web server

self.fWebServerThread = WebServerThread(self)
self.fWebServerThread.start()

# ----------------------------------------------------------------------------------------------------
# Set up GUI

self.setContentsMargins(0, 0, 0, 0)

self.fWebview = QWebView(self)
#self.fWebview.setAttribute(Qt.WA_OpaquePaintEvent, False)
#self.fWebview.setAttribute(Qt.WA_TranslucentBackground, True)
self.setCentralWidget(self.fWebview)

page = self.fWebview.page()
page.setViewportSize(QSize(980, 600))

mainFrame = page.mainFrame()
mainFrame.setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
mainFrame.setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)

palette = self.fWebview.palette()
palette.setBrush(QPalette.Base, palette.brush(QPalette.Window))
page.setPalette(palette)
self.fWebview.setPalette(palette)

settings = self.fWebview.settings()
settings.setAttribute(QWebSettings.DeveloperExtrasEnabled, True)

self.fWebview.loadFinished.connect(self.slot_webviewLoadFinished)

url = "http://127.0.0.1:%s/icon.html#%s" % (PORT, URI)
print("url:", url)
self.fWebview.load(QUrl(url))

# ----------------------------------------------------------------------------------------------------
# Connect actions to functions

self.SIGTERM.connect(self.slot_handleSIGTERM)

# ----------------------------------------------------------------------------------------------------
# Final setup

self.fIdleTimer = self.startTimer(30)

if self.fPipeClient is None:
# testing, show UI only
self.setWindowTitle("TestUI")
self.fNeedsShow = True

# --------------------------------------------------------------------------------------------------------

def closeExternalUI(self):
self.fWebServerThread.stopWait()

if self.fPipeClient is None:
return

if not self.fQuitReceived:
self.send(["exiting"])

gCarla.utils.pipe_client_destroy(self.fPipeClient)
self.fPipeClient = None

def idleStuff(self):
if self.fPipeClient is not None:
gCarla.utils.pipe_client_idle(self.fPipeClient)
self.checkForRepaintChanges()

if self.fSizeSetup:
return
if self.fDocElemement is None or self.fDocElemement.isNull():
return

pedal = self.fDocElemement.findFirst(".mod-pedal")

if pedal.isNull():
return

size = pedal.geometry().size()

if size.width() <= 10 or size.height() <= 10:
return

# render web frame to image
image = QImage(self.fWebview.page().viewportSize(), QImage.Format_ARGB32_Premultiplied)
image.fill(Qt.transparent)

painter = QPainter(image)
self.fCurrentFrame.render(painter)
painter.end()

#image.save("/tmp/test.png")

# get coordinates and size from image
#x = -1
#y = -1
#lastx = -1
#lasty = -1
#bgcol = self.fHostColor.rgba()

#for h in range(0, image.height()):
#hasNonTransPixels = False

#for w in range(0, image.width()):
#if image.pixel(w, h) not in (0, bgcol): # 0xff070707):
#hasNonTransPixels = True
#if x == -1 or x > w:
#x = w
#lastx = max(lastx, w)

#if hasNonTransPixels:
##if y == -1:
##y = h
#lasty = h

# set size and position accordingly
#if -1 not in (x, lastx, lasty):
#self.setFixedSize(lastx-x, lasty)
#self.fCurrentFrame.setScrollPosition(QPoint(x, 0))
#else:

# TODO that^ needs work
if True:
self.setFixedSize(size)

# set initial values
self.fCurrentFrame.evaluateJavaScript("icongui.setPortWidgetsValue(':bypass', 0, null)")

for index in self.fPortValues.keys():
symbol, isOutput = self.fPortSymbols[index]
value = self.fPortValues[index]
if isOutput:
self.fCurrentFrame.evaluateJavaScript("icongui.setOutputPortValue('%s', %f)" % (symbol, value))
else:
self.fCurrentFrame.evaluateJavaScript("icongui.setPortWidgetsValue('%s', %f, null)" % (symbol, value))

for uri in self.fParamValues.keys():
ptype = self.fParamTypes[uri]
value = str(self.fParamValues[uri])
print("icongui.setWritableParameterValue('%s', '%c', %s, 'from-carla')" % (uri, ptype, value))
self.fCurrentFrame.evaluateJavaScript("icongui.setWritableParameterValue('%s', '%c', %s, 'from-carla')" % (
uri, ptype, value))

# final setup
self.fCanSetValues = True
self.fSizeSetup = True
self.fDocElemement = None

if self.fNeedsShow:
self.show()

def checkForRepaintChanges(self):
if not self.fWasRepainted:
return

self.fWasRepainted = False

if not self.fCanSetValues:
return

for index in self.fPortValues.keys():
symbol, isOutput = self.fPortSymbols[index]

if isOutput:
continue

oldValue = self.fPortValues[index]
newValue = self.fCurrentFrame.evaluateJavaScript("icongui.controls['%s'].value" % (symbol,))

if oldValue != newValue:
self.fPortValues[index] = newValue
self.send(["control", index, newValue])

for uri in self.fParamValues.keys():
oldValue = self.fParamValues[uri]
newValue = self.fCurrentFrame.evaluateJavaScript("icongui.parameters['%s'].value" % (uri,))

if oldValue != newValue:
self.fParamValues[uri] = newValue
self.send(["pcontrol", uri, newValue])

# --------------------------------------------------------------------------------------------------------

@pyqtSlot(bool)
def slot_webviewLoadFinished(self, ok):
page = self.fWebview.page()
page.repaintRequested.connect(self.slot_repaintRequested)

self.fCurrentFrame = page.currentFrame()
self.fDocElemement = self.fCurrentFrame.documentElement()

def slot_repaintRequested(self):
if self.fCanSetValues:
self.fWasRepainted = True

# --------------------------------------------------------------------------------------------------------
# Callback

def msgCallback(self, msg):
msg = charPtrToString(msg)

if msg == "control":
index = self.readlineblock_int()
value = self.readlineblock_float()
self.dspControlChanged(index, value)

elif msg == "parameter":
uri = self.readlineblock()
value = self.readlineblock_float()
self.dspParameterChanged(uri, value)

elif msg == "program":
index = self.readlineblock_int()
self.dspProgramChanged(index)

elif msg == "midiprogram":
bank = self.readlineblock_int()
program = self.readlineblock_int()
self.dspMidiProgramChanged(bank, program)

elif msg == "configure":
key = self.readlineblock()
value = self.readlineblock()
self.dspStateChanged(key, value)

elif msg == "note":
onOff = self.readlineblock_bool()
channel = self.readlineblock_int()
note = self.readlineblock_int()
velocity = self.readlineblock_int()
self.dspNoteReceived(onOff, channel, note, velocity)

elif msg == "atom":
index = self.readlineblock_int()
atomsize = self.readlineblock_int()
base64size = self.readlineblock_int()
base64atom = self.readlineblock()
# nothing to do yet

elif msg == "urid":
urid = self.readlineblock_int()
size = self.readlineblock_int()
uri = self.readlineblock()
# nothing to do yet

elif msg == "uiOptions":
sampleRate = self.readlineblock_float()
bgColor = self.readlineblock_int()
fgColor = self.readlineblock_int()
uiScale = self.readlineblock_float()
useTheme = self.readlineblock_bool()
useThemeColors = self.readlineblock_bool()
windowTitle = self.readlineblock()
transWindowId = self.readlineblock_int()
self.uiTitleChanged(windowTitle)

elif msg == "show":
self.uiShow()

elif msg == "focus":
self.uiFocus()

elif msg == "hide":
self.uiHide()

elif msg == "quit":
self.fQuitReceived = True
self.uiQuit()

elif msg == "uiTitle":
uiTitle = self.readlineblock()
self.uiTitleChanged(uiTitle)

else:
print("unknown message: \"" + msg + "\"")

# --------------------------------------------------------------------------------------------------------

def dspControlChanged(self, index, value):
self.fPortValues[index] = value

if self.fCurrentFrame is None or not self.fCanSetValues:
return

symbol, isOutput = self.fPortSymbols[index]

if isOutput:
self.fCurrentFrame.evaluateJavaScript("icongui.setOutputPortValue('%s', %f)" % (symbol, value))
else:
self.fCurrentFrame.evaluateJavaScript("icongui.setPortWidgetsValue('%s', %f, null)" % (symbol, value))

def dspParameterChanged(self, uri, value):
print("dspParameterChanged", uri, value)
if uri not in self.fParamValues:
return

self.fParamValues[uri] = value

if self.fCurrentFrame is None or not self.fCanSetValues:
return

ptype = self.fParamTypes[uri]

self.fCurrentFrame.evaluateJavaScript("icongui.setWritableParameterValue('%s', '%c', %f, 'from-carla')" % (
uri, ptype, value))

def dspProgramChanged(self, index):
return

def dspMidiProgramChanged(self, bank, program):
return

def dspStateChanged(self, key, value):
return

def dspNoteReceived(self, onOff, channel, note, velocity):
return

# --------------------------------------------------------------------------------------------------------

def uiShow(self):
if self.fSizeSetup:
self.show()
else:
self.fNeedsShow = True

def uiFocus(self):
if not self.fSizeSetup:
return

self.setWindowState((self.windowState() & ~Qt.WindowMinimized) | Qt.WindowActive)
self.show()

self.raise_()
self.activateWindow()

def uiHide(self):
self.hide()

def uiQuit(self):
self.closeExternalUI()
self.close()
QApplication.instance().quit()

def uiTitleChanged(self, uiTitle):
self.setWindowTitle(uiTitle)

# --------------------------------------------------------------------------------------------------------
# Qt events

def closeEvent(self, event):
self.closeExternalUI()
QMainWindow.closeEvent(self, event)

# there might be other qt windows open which will block carla-modgui from quitting
QApplication.instance().quit()

def timerEvent(self, event):
if event.timerId() == self.fIdleTimer:
self.idleStuff()

QMainWindow.timerEvent(self, event)

# --------------------------------------------------------------------------------------------------------

@pyqtSlot()
def slot_handleSIGTERM(self):
print("Got SIGTERM -> Closing now")
self.close()

# --------------------------------------------------------------------------------------------------------
# Internal stuff

def readlineblock(self):
if self.fPipeClient is None:
return ""

return gCarla.utils.pipe_client_readlineblock(self.fPipeClient, 5000)

def readlineblock_bool(self):
if self.fPipeClient is None:
return False

return gCarla.utils.pipe_client_readlineblock_bool(self.fPipeClient, 5000)

def readlineblock_int(self):
if self.fPipeClient is None:
return 0

return gCarla.utils.pipe_client_readlineblock_int(self.fPipeClient, 5000)

def readlineblock_float(self):
if self.fPipeClient is None:
return 0.0

return gCarla.utils.pipe_client_readlineblock_float(self.fPipeClient, 5000)

def send(self, lines):
if self.fPipeClient is None or len(lines) == 0:
return

gCarla.utils.pipe_client_lock(self.fPipeClient)

# this must never fail, we need to unlock at the end
try:
for line in lines:
if line is None:
line2 = "(null)"
elif isinstance(line, str):
line2 = line.replace("\n", "\r")
elif isinstance(line, bool):
line2 = "true" if line else "false"
elif isinstance(line, int):
line2 = "%i" % line
elif isinstance(line, float):
line2 = "%.10f" % line
else:
print("unknown data type to send:", type(line))
return

gCarla.utils.pipe_client_write_msg(self.fPipeClient, line2 + "\n")
except:
pass

gCarla.utils.pipe_client_flush_and_unlock(self.fPipeClient)

+ 0
- 225
source/frontend/modgui/webserver.py View File

@@ -1,225 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Carla bridge for LV2 modguis
# Copyright (C) 2015-2020 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 (asyncio)

try:
from asyncio import new_event_loop, set_event_loop
haveAsyncIO = True
except:
haveAsyncIO = False

# ------------------------------------------------------------------------------------------------------------
# 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 modtools.utils import get_plugin_info, get_plugin_gui, get_plugin_gui_mini

# ------------------------------------------------------------------------------------------------------------
# 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
self.fEventLoop = None

def run(self):
if not self.fPrepareWasCalled:
self.fPrepareWasCalled = True
if haveAsyncIO:
self.fEventLoop = new_event_loop()
set_event_loop(self.fEventLoop)
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()
if self.fEventLoop is not None:
self.fEventLoop.call_soon_threadsafe(self.fEventLoop.stop)
return self.wait(5000)

+ 0
- 2
source/includes/lv2_rdf.hpp View File

@@ -242,7 +242,6 @@ typedef uint32_t LV2_Property;
#define LV2_UI_X11 7
#define LV2_UI_EXTERNAL 8
#define LV2_UI_OLD_EXTERNAL 9
#define LV2_UI_MOD 10

#define LV2_IS_UI_GTK2(x) ((x) == LV2_UI_GTK2)
#define LV2_IS_UI_GTK3(x) ((x) == LV2_UI_GTK3)
@@ -253,7 +252,6 @@ typedef uint32_t LV2_Property;
#define LV2_IS_UI_X11(x) ((x) == LV2_UI_X11)
#define LV2_IS_UI_EXTERNAL(x) ((x) == LV2_UI_EXTERNAL)
#define LV2_IS_UI_OLD_EXTERNAL(x) ((x) == LV2_UI_OLD_EXTERNAL)
#define LV2_IS_UI_MOD(x) ((x) == LV2_UI_MOD)

// Plugin Types
#define LV2_PLUGIN_DELAY 0x000001


+ 1
- 31
source/utils/CarlaLv2Utils.hpp View File

@@ -104,7 +104,6 @@ typedef std::map<double,const LilvScalePoint*> LilvScalePointMap;
#define NS_rdfs "http://www.w3.org/2000/01/rdf-schema#"
#define NS_llmm "http://ll-plugins.nongnu.org/lv2/ext/midimap#"
#define NS_devp "http://lv2plug.in/ns/dev/extportinfo#"
#define NS_mod "http://moddevices.com/ns/modgui#"

#define LV2_MIDI_Map__CC "http://ll-plugins.nongnu.org/lv2/namespace#CC"
#define LV2_MIDI_Map__NRPN "http://ll-plugins.nongnu.org/lv2/namespace#NRPN"
@@ -2914,15 +2913,9 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
// ----------------------------------------------------------------------------------------------------------------
// Set Plugin UIs
{
#ifdef CARLA_OS_LINUX
const bool hasMODGui = lilvPlugin.get_modgui_resources_directory().as_uri() != nullptr;
#else
const bool hasMODGui = false;
#endif

Lilv::UIs lilvUIs(lilvPlugin.get_uis());

const uint numUIs = lilvUIs.size() + (hasMODGui ? 1 : 0);
const uint numUIs = lilvUIs.size();

if (numUIs > 0)
{
@@ -3119,29 +3112,6 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
}
}

for (; hasMODGui;)
{
CARLA_SAFE_ASSERT_BREAK(numUsed == numUIs-1);

LV2_RDF_UI* const rdfUI(&rdfDescriptor->UIs[numUsed++]);

// -------------------------------------------------------
// Set UI Type

rdfUI->Type = LV2_UI_MOD;

// -------------------------------------------------------
// Set UI Information

if (const char* const resDir = lilvPlugin.get_modgui_resources_directory().as_uri())
rdfUI->URI = carla_strdup_free(lilv_file_uri_parse(resDir, nullptr));

if (rdfDescriptor->Bundle != nullptr)
rdfUI->Bundle = carla_strdup(rdfDescriptor->Bundle);

break;
}

rdfDescriptor->UICount = numUsed;
}



Loading…
Cancel
Save