|
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
-
- # Carla Backend code
- # Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com> FIXME
- #
- # 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 COPYING file
-
- # Imports (Global)
- import os, sys
- from ctypes import *
- from copy import deepcopy
- from subprocess import Popen, PIPE
-
- # Imports (Custom)
- try:
- import ladspa_rdf, lv2_rdf
- haveRDF = True
- except:
- print("RDF Support not available (LADSPA-RDF and LV2 will be disabled)")
- haveRDF = False
-
- # Set Platform and Architecture
- is64bit = False
- LINUX = False
- MACOS = False
- WINDOWS = False
-
- if (sys.platform == "darwin"):
- MACOS = True
- elif (sys.platform.startswith("linux")):
- LINUX = True
- if (len(os.uname()) > 4 and os.uname()[4] in ('x86_64',)): #FIXME - need more checks
- is64bit = True
- elif (sys.platform.startswith("win")):
- WINDOWS = True
- if (sys.platform == "win64"):
- is64bit = True
-
- if (is64bit):
- c_uintptr = c_uint64
- else:
- c_uintptr = c_uint32
-
- # Get short filename from full filename (/a/b.c -> b.c)
- def getShortFileName(filename):
- short = filename
- if (os.sep in filename):
- short = filename.rsplit(os.sep, 1)[1]
- return short
-
- # Convert a ctypes struct into a dict
- def struct_to_dict(struct):
- return dict((attr, getattr(struct, attr)) for attr, value in struct._fields_)
-
- # ------------------------------------------------------------------------------------------------
- # Default Plugin Folders
-
- if (WINDOWS):
- splitter = ";"
- APPDATA = os.getenv("APPDATA")
- PROGRAMFILES = os.getenv("PROGRAMFILES")
- COMMONPROGRAMFILES = os.getenv("COMMONPROGRAMFILES")
-
- # Small integrity tests
- if not APPDATA:
- print("APPDATA variable not set, cannot continue")
- sys.exit(1)
-
- if not PROGRAMFILES:
- print("PROGRAMFILES variable not set, cannot continue")
- sys.exit(1)
-
- if not COMMONPROGRAMFILES:
- print("COMMONPROGRAMFILES variable not set, cannot continue")
- sys.exit(1)
-
- DEFAULT_LADSPA_PATH = [
- os.path.join(APPDATA, "LADSPA"),
- os.path.join(PROGRAMFILES, "LADSPA")
- ]
-
- DEFAULT_DSSI_PATH = [
- os.path.join(APPDATA, "DSSI"),
- os.path.join(PROGRAMFILES, "DSSI")
- ]
-
- DEFAULT_LV2_PATH = [
- os.path.join(APPDATA, "LV2"),
- os.path.join(COMMONPROGRAMFILES, "LV2")
- ]
-
- DEFAULT_VST_PATH = [
- os.path.join(PROGRAMFILES, "VstPlugins"),
- os.path.join(PROGRAMFILES, "Steinberg", "VstPlugins")
- ]
-
- DEFAULT_SF2_PATH = [
- os.path.join(APPDATA, "SF2")
- ]
-
- #if (is64bit):
- # TODO
-
- elif (MACOS):
- splitter = ":"
- HOME = os.getenv("HOME")
-
- # Small integrity tests
- if not HOME:
- print("HOME variable not set, cannot continue")
- sys.exit(1)
-
- DEFAULT_LADSPA_PATH = [
- os.path.join(HOME, "Library", "Audio", "Plug-Ins", "LADSPA"),
- os.path.join("/", "Library", "Audio", "Plug-Ins", "LADSPA")
- ]
-
- DEFAULT_DSSI_PATH = [
- os.path.join(HOME, "Library", "Audio", "Plug-Ins", "DSSI"),
- os.path.join("/", "Library", "Audio", "Plug-Ins", "DSSI")
- ]
-
- DEFAULT_LV2_PATH = [
- os.path.join(HOME, "Library", "Audio", "Plug-Ins", "LV2"),
- os.path.join("/", "Library", "Audio", "Plug-Ins", "LV2")
- ]
-
- DEFAULT_VST_PATH = [
- os.path.join(HOME, "Library", "Audio", "Plug-Ins", "VST"),
- os.path.join("/", "Library", "Audio", "Plug-Ins", "VST")
- ]
-
- DEFAULT_SF2_PATH = [
- # TODO
- ]
-
- else:
- splitter = ":"
- HOME = os.getenv("HOME")
-
- # Small integrity tests
- if not HOME:
- print("HOME variable not set, cannot continue")
- sys.exit(1)
-
- DEFAULT_LADSPA_PATH = [
- os.path.join(HOME, ".ladspa"),
- os.path.join("/", "usr", "lib", "ladspa"),
- os.path.join("/", "usr", "local", "lib", "ladspa")
- ]
-
- DEFAULT_DSSI_PATH = [
- os.path.join(HOME, ".dssi"),
- os.path.join("/", "usr", "lib", "dssi"),
- os.path.join("/", "usr", "local", "lib", "dssi")
- ]
-
- DEFAULT_LV2_PATH = [
- os.path.join(HOME, ".lv2"),
- os.path.join("/", "usr", "lib", "lv2"),
- os.path.join("/", "usr", "local", "lib", "lv2")
- ]
-
- DEFAULT_VST_PATH = [
- os.path.join(HOME, ".vst"),
- os.path.join("/", "usr", "lib", "vst"),
- os.path.join("/", "usr", "local", "lib", "vst")
- ]
-
- DEFAULT_SF2_PATH = [
- os.path.join(HOME, ".sounds"),
- os.path.join("/", "usr", "share", "sounds", "sf2")
- ]
-
- # ------------------------------------------------------------------------------------------------
- # Search for Carla library and tools
-
- global carla_library_path
- carla_library_path = ""
-
- carla_discovery_unix32 = ""
- carla_discovery_unix64 = ""
- carla_discovery_win32 = ""
- carla_discovery_win64 = ""
-
- carla_bridge_unix32 = ""
- carla_bridge_unix64 = ""
- carla_bridge_win32 = ""
- carla_bridge_win64 = ""
-
- carla_bridge_lv2_gtk2 = ""
- carla_bridge_lv2_qt4 = ""
- carla_bridge_lv2_x11 = ""
-
- if (WINDOWS):
- carla_libname = "carla_backend.dll"
- elif (MACOS):
- carla_libname = "carla_backend.dylib"
- else:
- carla_libname = "carla_backend.so"
-
- if (WINDOWS):
- PATH = (os.path.join(PROGRAMFILES, "Cadence", "carla"),)
-
- else:
- PATH_env = os.getenv("PATH")
-
- if (PATH_env != None):
- PATH = PATH_env.split(":")
- else:
- PATH = ("/usr/bin", "/usr/local/bin")
-
- CWD = sys.path[0]
-
- # carla-backend
- if (os.path.exists(os.path.join(CWD, "carla", carla_libname))):
- carla_library_path = os.path.join(CWD, "carla", carla_libname)
- else:
- if (WINDOWS):
- CARLA_PATH = (os.path.join(PROGRAMFILES, "Cadence", "carla"),)
- elif (MACOS):
- CARLA_PATH = ("/usr/lib", "/usr/local/lib/") # FIXME
- else:
- CARLA_PATH = ("/usr/lib", "/usr/local/lib/")
- for p in CARLA_PATH:
- if (os.path.exists(os.path.join(p, "carla", carla_libname))):
- carla_library_path = os.path.join(p, "carla", carla_libname)
- break
-
- # discovery-unix32
- if (os.path.exists(os.path.join(CWD, "carla-discovery", "carla-discovery-unix32"))):
- carla_discovery_unix32 = os.path.join(CWD, "carla-discovery", "carla-discovery-unix32")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-discovery-unix32"))):
- carla_discovery_unix32 = os.path.join(p, "carla-discovery-unix32")
- break
-
- # discovery-unix64
- if (os.path.exists(os.path.join(CWD, "carla-discovery", "carla-discovery-unix64"))):
- carla_discovery_unix64 = os.path.join(CWD, "carla-discovery", "carla-discovery-unix64")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-discovery-unix64"))):
- carla_discovery_unix64 = os.path.join(p, "carla-discovery-unix64")
- break
-
- # discovery-win32
- if (os.path.exists(os.path.join(CWD, "carla-discovery", "carla-discovery-win32.exe"))):
- carla_discovery_win32 = os.path.join(CWD, "carla-discovery", "carla-discovery-win32.exe")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-discovery-wine32.exe"))):
- carla_discovery_win32 = os.path.join(p, "carla-discovery-win32.exe")
- break
-
- # discovery-win64
- if (os.path.exists(os.path.join(CWD, "carla-discovery", "carla-discovery-win64.exe"))):
- carla_discovery_win64 = os.path.join(CWD, "carla-discovery", "carla-discovery-win64.exe")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-discovery-win64.exe"))):
- carla_discovery_win64 = os.path.join(p, "carla-discovery-win64.exe")
- break
-
- # bridge-unix32
- if (os.path.exists(os.path.join(CWD, "carla-bridge", "carla-bridge-unix32"))):
- carla_bridge_unix32 = os.path.join(CWD, "carla-bridge", "carla-bridge-unix32")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-bridge-unix32"))):
- carla_bridge_unix32 = os.path.join(p, "carla-bridge-unix32")
- break
-
- # bridge-unix64
- if (os.path.exists(os.path.join(CWD, "carla-bridge", "carla-bridge-unix64"))):
- carla_bridge_unix64 = os.path.join(CWD, "carla-bridge", "carla-bridge-unix64")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-bridge-unix64"))):
- carla_bridge_unix64 = os.path.join(p, "carla-bridge-unix64")
- break
-
- # bridge-win32
- if (os.path.exists(os.path.join(CWD, "carla-bridge", "carla-bridge-win32.exe"))):
- carla_bridge_win32 = os.path.join(CWD, "carla-bridge", "carla-bridge-win32.exe")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-bridge-wine32.exe"))):
- carla_bridge_win32 = os.path.join(p, "carla-bridge-win32.exe")
- break
-
- # bridge-win64
- if (os.path.exists(os.path.join(CWD, "carla-bridge", "carla-bridge-win64.exe"))):
- carla_bridge_win64 = os.path.join(CWD, "carla-bridge", "carla-bridge-win64.exe")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-bridge-win64.exe"))):
- carla_bridge_win64 = os.path.join(p, "carla-bridge-win64.exe")
- break
-
- # bridge-lv2-gtk2
- if (os.path.exists(os.path.join(CWD, "carla-bridge-ui", "carla-bridge-lv2-gtk2"))):
- carla_bridge_lv2_gtk2 = os.path.join(CWD, "carla-bridge-ui", "carla-bridge-lv2-gtk2")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-bridge-lv2-gtk2"))):
- carla_bridge_lv2_gtk2 = os.path.join(p, "carla-bridge-lv2-gtk2")
- break
-
- # bridge-lv2-qt4
- if (os.path.exists(os.path.join(CWD, "carla-bridge-ui", "carla-bridge-lv2-qt4"))):
- carla_bridge_lv2_qt4 = os.path.join(CWD, "carla-bridge-ui", "carla-bridge-lv2-qt4")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-bridge-lv2-qt4"))):
- carla_bridge_lv2_qt4 = os.path.join(p, "carla-bridge-lv2-qt4")
- break
-
- # bridge-lv2-x11
- if (os.path.exists(os.path.join(CWD, "carla-bridge-ui", "carla-bridge-lv2-x11"))):
- carla_bridge_lv2_x11 = os.path.join(CWD, "carla-bridge-ui", "carla-bridge-lv2-x11")
- else:
- for p in PATH:
- if (os.path.exists(os.path.join(p, "carla-bridge-lv2-x11"))):
- carla_bridge_lv2_x11 = os.path.join(p, "carla-bridge-lv2-x11")
- break
-
- # ------------------------------------------------------------------------------------------------
- # Plugin Query (helper functions)
-
- def findBinaries(bPATH, OS):
- binaries = []
-
- if (OS == "WINDOWS"):
- extensions = (".dll",)
- elif (OS == "MACOS"):
- extensions = (".dylib", ".so")
- else:
- extensions = (".so", ".sO", ".SO", ".So")
-
- for root, dirs, files in os.walk(bPATH):
- for name in [name for name in files if name.endswith(extensions)]:
- binaries.append(os.path.join(root, name))
-
- return binaries
-
- def findSoundFonts(bPATH):
- soundfonts = []
-
- extensions = (".sf2", ".sF2", ".SF2", ".Sf2")
-
- for root, dirs, files in os.walk(bPATH):
- for name in [name for name in files if name.endswith(extensions)]:
- soundfonts.append(os.path.join(root, name))
-
- return soundfonts
-
- def findLV2Bundles(bPATH):
- bundles = []
- extensions = (".lv2", ".lV2", ".LV2", ".Lv2")
-
- for root, dirs, files in os.walk(bPATH):
- for dir_ in [dir_ for dir_ in dirs if dir_.endswith(extensions)]:
- bundles.append(os.path.join(root, dir_))
-
- return bundles
-
- def findDSSIGUI(filename, name, label):
- plugin_dir = filename.rsplit(".", 1)[0]
- short_name = getShortFileName(plugin_dir)
- gui_filename = ""
-
- check_name = name.replace(" ","_")
- check_label = label
- check_sname = short_name
-
- if (check_name[-1] != "_"): check_name += "_"
- if (check_label[-1] != "_"): check_label += "_"
- if (check_sname[-1] != "_"): check_sname += "_"
-
- for root, dirs, files in os.walk(plugin_dir):
- gui_files = files
- break
- else:
- gui_files = []
-
- for gui in gui_files:
- if (gui.startswith(check_name) or gui.startswith(check_label) or gui.startswith(check_sname)):
- gui_filename = os.path.join(plugin_dir, gui)
- break
-
- return gui_filename
-
- # ------------------------------------------------------------------------------------------------
- # Plugin Query
-
- PyPluginInfo = {
- 'build': 0, # BINARY_NONE
- 'type': 0, # PLUGIN_NONE,
- 'category': 0, # PLUGIN_CATEGORY_NONE
- 'hints': 0x0,
- 'binary': "",
- 'name': "",
- 'label': "",
- 'maker': "",
- 'copyright': "",
- 'unique_id': 0,
- 'audio.ins': 0,
- 'audio.outs': 0,
- 'audio.totals': 0,
- 'midi.ins': 0,
- 'midi.outs': 0,
- 'midi.totals': 0,
- 'parameters.ins': 0,
- 'parameters.outs': 0,
- 'parameters.total': 0,
- 'programs.total': 0
- }
-
- def runCarlaDiscovery(itype, stype, filename, tool, isWine=False):
- short_name = getShortFileName(filename).rsplit(".", 1)[0]
- plugins = []
- pinfo = None
-
- command = []
-
- if (LINUX or MACOS):
- command.append("env")
- command.append("LANG=C")
- if (isWine):
- command.append("WINEDEBUG=-all")
-
- command.append(tool)
- command.append(stype)
- command.append(filename)
-
- p = Popen(command, stdout=PIPE)
- p.wait()
- output = p.stdout.read().decode("utf-8", errors="ignore").split("\n")
-
- for line in output:
- if (line == "carla-discovery::init::-----------"):
- pinfo = deepcopy(PyPluginInfo)
- pinfo['type'] = itype
- pinfo['binary'] = filename
-
- elif (line == "carla-discovery::end::------------"):
- if (pinfo != None):
- plugins.append(pinfo)
- pinfo = None
-
- elif (line == "Segmentation fault"):
- print("carla-discovery::crash::%s crashed during discovery" % (filename))
-
- elif line.startswith("err:module:import_dll Library"):
- print(line)
-
- elif line.startswith("carla-discovery::error::"):
- print("%s - %s" % (line, filename))
-
- elif line.startswith("carla-discovery::"):
- if (pinfo == None):
- continue
-
- prop, value = line.replace("carla-discovery::","").split("::", 1)
-
- if (prop == "name"):
- pinfo['name'] = value if (value) else short_name
- elif (prop == "label"):
- pinfo['label'] = value if (value) else short_name
- elif (prop == "maker"):
- pinfo['maker'] = value
- elif (prop == "copyright"):
- pinfo['copyright'] = value
- elif (prop == "unique_id"):
- if value.isdigit(): pinfo['unique_id'] = int(value)
- elif (prop == "hints"):
- if value.isdigit(): pinfo['hints'] = int(value)
- elif (prop == "category"):
- if value.isdigit(): pinfo['category'] = int(value)
- elif (prop == "audio.ins"):
- if value.isdigit(): pinfo['audio.ins'] = int(value)
- elif (prop == "audio.outs"):
- if value.isdigit(): pinfo['audio.outs'] = int(value)
- elif (prop == "audio.total"):
- if value.isdigit(): pinfo['audio.total'] = int(value)
- elif (prop == "midi.ins"):
- if value.isdigit(): pinfo['midi.ins'] = int(value)
- elif (prop == "midi.outs"):
- if value.isdigit(): pinfo['midi.outs'] = int(value)
- elif (prop == "midi.total"):
- if value.isdigit(): pinfo['midi.total'] = int(value)
- elif (prop == "parameters.ins"):
- if value.isdigit(): pinfo['parameters.ins'] = int(value)
- elif (prop == "parameters.outs"):
- if value.isdigit(): pinfo['parameters.outs'] = int(value)
- elif (prop == "parameters.total"):
- if value.isdigit(): pinfo['parameters.total'] = int(value)
- elif (prop == "programs.total"):
- if value.isdigit(): pinfo['programs.total'] = int(value)
- elif (prop == "build"):
- if value.isdigit(): pinfo['build'] = int(value)
-
- # Additional checks
- for pinfo in plugins:
- if (itype == PLUGIN_DSSI):
- if (findDSSIGUI(pinfo['binary'], pinfo['name'], pinfo['label'])):
- pinfo['hints'] |= PLUGIN_HAS_GUI
-
- return plugins
-
- def checkPluginLADSPA(filename, tool, isWine=False):
- return runCarlaDiscovery(PLUGIN_LADSPA, "LADSPA", filename, tool, isWine)
-
- def checkPluginDSSI(filename, tool, isWine=False):
- return runCarlaDiscovery(PLUGIN_DSSI, "DSSI", filename, tool, isWine)
-
- def checkPluginVST(filename, tool, isWine=False):
- return runCarlaDiscovery(PLUGIN_VST, "VST", filename, tool, isWine)
-
- def checkPluginSF2(filename, tool):
- return runCarlaDiscovery(PLUGIN_SF2, "SF2", filename, tool)
-
- def checkPluginLV2(rdf_info):
- plugins = []
-
- pinfo = deepcopy(PyPluginInfo)
- pinfo['type'] = PLUGIN_LV2
- pinfo['build'] = BINARY_NATIVE
- pinfo['category'] = PLUGIN_CATEGORY_NONE # TODO
- pinfo['hints'] = 0
- pinfo['binary'] = rdf_info['Binary']
- pinfo['name'] = rdf_info['Name']
- pinfo['label'] = rdf_info['URI']
- pinfo['maker'] = rdf_info['Author']
- pinfo['copyright'] = rdf_info['License']
- pinfo['unique_id'] = rdf_info['UniqueID']
- pinfo['audio.ins'] = 0
- pinfo['audio.outs'] = 0
- pinfo['audio.total'] = 0
- pinfo['midi.ins'] = 0
- pinfo['midi.outs'] = 0
- pinfo['midi.total'] = 0
- pinfo['parameters.ins'] = 0
- pinfo['parameters.outs'] = 0
- pinfo['parameters.total'] = 0
- pinfo['programs.total'] = 0 #rdf_info['PresetCount']
-
- if (pinfo['binary'] == "" or pinfo['name'] == "" or not rdf_info['Bundle']):
- return None
-
- for i in range(rdf_info['PortCount']):
- PortType = rdf_info['Ports'][i]['Type']
- PortProps = rdf_info['Ports'][i]['Properties']
-
- if (PortType & lv2_rdf.LV2_PORT_AUDIO):
- pinfo['audio.total'] += 1
- if (PortType & lv2_rdf.LV2_PORT_INPUT):
- pinfo['audio.ins'] += 1
- elif (PortType & lv2_rdf.LV2_PORT_OUTPUT):
- pinfo['audio.outs'] += 1
-
- elif (PortType & lv2_rdf.LV2_PORT_SUPPORTS_MIDI):
- pinfo['midi.total'] += 1
- if (PortType & lv2_rdf.LV2_PORT_INPUT):
- pinfo['midi.ins'] += 1
- elif (PortType & lv2_rdf.LV2_PORT_OUTPUT):
- pinfo['midi.outs'] += 1
-
- elif (PortType & lv2_rdf.LV2_PORT_CONTROL):
- pinfo['parameters.total'] += 1
- if (PortType & lv2_rdf.LV2_PORT_INPUT):
- pinfo['parameters.ins'] += 1
- elif (PortType & lv2_rdf.LV2_PORT_OUTPUT):
- if (not PortProps & lv2_rdf.LV2_PORT_LATENCY):
- pinfo['parameters.outs'] += 1
-
- if (rdf_info['Type'] & lv2_rdf.LV2_GROUP_GENERATOR):
- pinfo['hints'] |= PLUGIN_IS_SYNTH
-
- if (rdf_info['UICount'] > 0):
- pinfo['hints'] |= PLUGIN_HAS_GUI
-
- plugins.append(pinfo)
-
- return plugins
-
- # ------------------------------------------------------------------------------------------------
- # Backend C++ -> Python variables
-
- c_enum = c_int
- c_nullptr = None
-
- # static max values
- MAX_PLUGINS = 99
- MAX_PARAMETERS = 200
- MAX_MIDI_EVENTS = 512
-
- # plugin hints
- PLUGIN_IS_BRIDGE = 0x01
- PLUGIN_IS_SYNTH = 0x02
- PLUGIN_HAS_GUI = 0x04
- PLUGIN_USES_CHUNKS = 0x08
- PLUGIN_CAN_DRYWET = 0x10
- PLUGIN_CAN_VOLUME = 0x20
- PLUGIN_CAN_BALANCE = 0x40
-
- # parameter hints
- PARAMETER_IS_BOOLEAN = 0x01
- PARAMETER_IS_INTEGER = 0x02
- PARAMETER_IS_LOGARITHMIC = 0x04
- PARAMETER_IS_ENABLED = 0x08
- PARAMETER_IS_AUTOMABLE = 0x10
- PARAMETER_USES_SCALEPOINTS = 0x20
- PARAMETER_USES_SAMPLERATE = 0x40
-
- # enum BinaryType
- BINARY_NONE = 0
- BINARY_UNIX32 = 1
- BINARY_UNIX64 = 2
- BINARY_WIN32 = 3
- BINARY_WIN64 = 4
-
- # enum PluginType
- PLUGIN_NONE = 0
- PLUGIN_LADSPA = 1
- PLUGIN_DSSI = 2
- PLUGIN_LV2 = 3
- PLUGIN_VST = 4
- PLUGIN_SF2 = 5
-
- # enum PluginCategory
- PLUGIN_CATEGORY_NONE = 0
- PLUGIN_CATEGORY_SYNTH = 1
- PLUGIN_CATEGORY_DELAY = 2 # also Reverb
- PLUGIN_CATEGORY_EQ = 3
- PLUGIN_CATEGORY_FILTER = 4
- PLUGIN_CATEGORY_DYNAMICS = 5 # Amplifier, Compressor, Gate
- PLUGIN_CATEGORY_MODULATOR = 6 # Chorus, Flanger, Phaser
- PLUGIN_CATEGORY_UTILITY = 7 # Analyzer, Converter, Mixer
- PLUGIN_CATEGORY_OUTRO = 8 # used to check if a plugin has a category
-
- # enum ParameterType
- PARAMETER_UNKNOWN = 0
- PARAMETER_INPUT = 1
- PARAMETER_OUTPUT = 2
- PARAMETER_LATENCY = 3
-
- # enum InternalParametersIndex
- PARAMETER_ACTIVE = -1
- PARAMETER_DRYWET = -2
- PARAMETER_VOLUME = -3
- PARAMETER_BALANCE_LEFT = -4
- PARAMETER_BALANCE_RIGHT = -5
-
- # enum CustomDataType
- CUSTOM_DATA_INVALID = 0
- CUSTOM_DATA_BOOL = 1
- CUSTOM_DATA_INT = 2
- CUSTOM_DATA_LONG = 3
- CUSTOM_DATA_FLOAT = 4
- CUSTOM_DATA_STRING = 5
- CUSTOM_DATA_BINARY = 6
-
- # enum GuiType
- GUI_NONE = 0
- GUI_INTERNAL_QT4 = 1
- GUI_INTERNAL_X11 = 2
- GUI_EXTERNAL_LV2 = 3
- GUI_EXTERNAL_OSC = 4
-
- # enum OptionsType
- OPTION_GLOBAL_JACK_CLIENT = 1
- OPTION_USE_DSSI_CHUNKS = 2
- OPTION_PREFER_UI_BRIDGES = 3
- OPTION_PATH_BRIDGE_UNIX32 = 4
- OPTION_PATH_BRIDGE_UNIX64 = 5
- OPTION_PATH_BRIDGE_WIN32 = 6
- OPTION_PATH_BRIDGE_WIN64 = 7
- OPTION_PATH_BRIDGE_LV2_GTK2 = 8
- OPTION_PATH_BRIDGE_LV2_QT4 = 9
- OPTION_PATH_BRIDGE_LV2_X11 = 10
-
- # enum CallbackType
- CALLBACK_DEBUG = 0
- CALLBACK_PARAMETER_CHANGED = 1 # parameter_id, 0, value
- CALLBACK_PROGRAM_CHANGED = 2 # program_id, 0, 0
- CALLBACK_MIDI_PROGRAM_CHANGED = 3 # midi_program_id, 0, 0
- CALLBACK_NOTE_ON = 4 # key, velocity, 0
- CALLBACK_NOTE_OFF = 5 # key, velocity, 0
- CALLBACK_SHOW_GUI = 6 # show? (0|1, -1=quit), 0, 0
- CALLBACK_RESIZE_GUI = 7 # width, height, 0
- CALLBACK_UPDATE = 8
- CALLBACK_RELOAD_INFO = 9
- CALLBACK_RELOAD_PARAMETERS = 10
- CALLBACK_RELOAD_PROGRAMS = 11
- CALLBACK_RELOAD_ALL = 12
- CALLBACK_QUIT = 13
-
- class ParameterData(Structure):
- _fields_ = [
- ("type", c_enum),
- ("index", c_int32),
- ("rindex", c_int32),
- ("hints", c_int32),
- ("midi_channel", c_uint8),
- ("midi_cc", c_int16)
- ]
-
- class ParameterRanges(Structure):
- _fields_ = [
- ("def", c_double),
- ("min", c_double),
- ("max", c_double),
- ("step", c_double),
- ("step_small", c_double),
- ("step_large", c_double)
- ]
-
- class CustomData(Structure):
- _fields_ = [
- ("type", c_enum),
- ("key", c_char_p),
- ("value", c_char_p)
- ]
-
- class PluginInfo(Structure):
- _fields_ = [
- ("valid", c_bool),
- ("type", c_enum),
- ("category", c_enum),
- ("hints", c_uint),
- ("binary", c_char_p),
- ("name", c_char_p),
- ("label", c_char_p),
- ("maker", c_char_p),
- ("copyright", c_char_p),
- ("unique_id", c_long)
- ]
-
- class PortCountInfo(Structure):
- _fields_ = [
- ("valid", c_bool),
- ("ins", c_uint32),
- ("outs", c_uint32),
- ("total", c_uint32)
- ]
-
- class ParameterInfo(Structure):
- _fields_ = [
- ("valid", c_bool),
- ("name", c_char_p),
- ("symbol", c_char_p),
- ("label", c_char_p),
- ("scalepoint_count", c_uint32)
- ]
-
- class ScalePointInfo(Structure):
- _fields_ = [
- ("valid", c_bool),
- ("value", c_double),
- ("label", c_char_p)
- ]
-
- class MidiProgramInfo(Structure):
- _fields_ = [
- ("valid", c_bool),
- ("bank", c_uint32),
- ("program", c_uint32),
- ("label", c_char_p)
- ]
-
- class GuiInfo(Structure):
- _fields_ = [
- ("type", c_enum),
- ("resizable", c_bool),
- ]
-
- class PluginBridgeInfo(Structure):
- _fields_ = [
- ("category", c_enum),
- ("hints", c_uint),
- ("name", c_char_p),
- ("maker", c_char_p),
- ("unique_id", c_long),
- ("ains", c_uint32),
- ("aouts", c_uint32),
- ("mins", c_uint32),
- ("mouts", c_uint32)
- ]
-
- CallbackFunc = CFUNCTYPE(None, c_enum, c_ushort, c_int, c_int, c_double)
-
- if (LINUX or MACOS):
- BINARY_NATIVE = BINARY_UNIX64 if (is64bit) else BINARY_UNIX32
- elif (WINDOWS):
- BINARY_NATIVE = BINARY_WIN64 if (is64bit) else BINARY_WIN32
- else:
- BINARY_NATIVE = BINARY_NONE
-
- # ------------------------------------------------------------------------------------------------
- # Backend C++ -> Python object
-
- global Callback
- Callback = None
-
- class Host(object):
- def __init__(self, lib_prefix_arg):
- object.__init__(self)
-
- global carla_library_path
-
- if (lib_prefix_arg):
- carla_library_path = os.path.join(lib_prefix_arg, "lib", "carla", carla_libname)
-
- self.lib = cdll.LoadLibrary(carla_library_path)
-
- self.lib.carla_init.argtypes = [c_char_p]
- self.lib.carla_init.restype = c_bool
-
- self.lib.carla_close.argtypes = None
- self.lib.carla_close.restype = c_bool
-
- self.lib.carla_is_engine_running.argtypes = None
- self.lib.carla_is_engine_running.restype = c_bool
-
- self.lib.add_plugin.argtypes = [c_enum, c_enum, c_char_p, c_char_p, c_void_p]
- self.lib.add_plugin.restype = c_short
-
- self.lib.remove_plugin.argtypes = [c_ushort]
- self.lib.remove_plugin.restype = c_bool
-
- self.lib.get_plugin_info.argtypes = [c_ushort]
- self.lib.get_plugin_info.restype = POINTER(PluginInfo)
-
- self.lib.get_audio_port_count_info.argtypes = [c_ushort]
- self.lib.get_audio_port_count_info.restype = POINTER(PortCountInfo)
-
- self.lib.get_midi_port_count_info.argtypes = [c_ushort]
- self.lib.get_midi_port_count_info.restype = POINTER(PortCountInfo)
-
- self.lib.get_parameter_count_info.argtypes = [c_ushort]
- self.lib.get_parameter_count_info.restype = POINTER(PortCountInfo)
-
- self.lib.get_parameter_info.argtypes = [c_ushort, c_uint32]
- self.lib.get_parameter_info.restype = POINTER(ParameterInfo)
-
- self.lib.get_scalepoint_info.argtypes = [c_ushort, c_uint32, c_uint32]
- self.lib.get_scalepoint_info.restype = POINTER(ScalePointInfo)
-
- self.lib.get_midi_program_info.argtypes = [c_ushort, c_uint32]
- self.lib.get_midi_program_info.restype = POINTER(MidiProgramInfo)
-
- self.lib.get_gui_info.argtypes = [c_ushort]
- self.lib.get_gui_info.restype = POINTER(GuiInfo)
-
- self.lib.get_parameter_data.argtypes = [c_ushort, c_uint32]
- self.lib.get_parameter_data.restype = POINTER(ParameterData)
-
- self.lib.get_parameter_ranges.argtypes = [c_ushort, c_uint32]
- self.lib.get_parameter_ranges.restype = POINTER(ParameterRanges)
-
- self.lib.get_custom_data.argtypes = [c_ushort, c_uint32]
- self.lib.get_custom_data.restype = POINTER(CustomData)
-
- self.lib.get_chunk_data.argtypes = [c_ushort]
- self.lib.get_chunk_data.restype = c_char_p
-
- self.lib.get_parameter_count.argtypes = [c_ushort]
- self.lib.get_parameter_count.restype = c_uint32
-
- self.lib.get_program_count.argtypes = [c_ushort]
- self.lib.get_program_count.restype = c_uint32
-
- self.lib.get_midi_program_count.argtypes = [c_ushort]
- self.lib.get_midi_program_count.restype = c_uint32
-
- self.lib.get_custom_data_count.argtypes = [c_ushort]
- self.lib.get_custom_data_count.restype = c_uint32
-
- self.lib.get_program_name.argtypes = [c_ushort, c_uint32]
- self.lib.get_program_name.restype = c_char_p
-
- self.lib.get_midi_program_name.argtypes = [c_ushort, c_uint32]
- self.lib.get_midi_program_name.restype = c_char_p
-
- self.lib.get_real_plugin_name.argtypes = [c_ushort]
- self.lib.get_real_plugin_name.restype = c_char_p
-
- self.lib.get_current_program_index.argtypes = [c_ushort]
- self.lib.get_current_program_index.restype = c_int32
-
- self.lib.get_current_midi_program_index.argtypes = [c_ushort]
- self.lib.get_current_midi_program_index.restype = c_int32
-
- self.lib.get_default_parameter_value.argtypes = [c_ushort, c_uint32]
- self.lib.get_default_parameter_value.restype = c_double
-
- self.lib.get_current_parameter_value.argtypes = [c_ushort, c_uint32]
- self.lib.get_current_parameter_value.restype = c_double
-
- self.lib.get_input_peak_value.argtypes = [c_ushort, c_ushort]
- self.lib.get_input_peak_value.restype = c_double
-
- self.lib.get_output_peak_value.argtypes = [c_ushort, c_ushort]
- self.lib.get_output_peak_value.restype = c_double
-
- self.lib.set_active.argtypes = [c_ushort, c_bool]
- self.lib.set_active.restype = None
-
- self.lib.set_drywet.argtypes = [c_ushort, c_double]
- self.lib.set_drywet.restype = None
-
- self.lib.set_volume.argtypes = [c_ushort, c_double]
- self.lib.set_volume.restype = None
-
- self.lib.set_balance_left.argtypes = [c_ushort, c_double]
- self.lib.set_balance_left.restype = None
-
- self.lib.set_balance_right.argtypes = [c_ushort, c_double]
- self.lib.set_balance_right.restype = None
-
- self.lib.set_parameter_value.argtypes = [c_ushort, c_uint32, c_double]
- self.lib.set_parameter_value.restype = None
-
- self.lib.set_parameter_midi_channel.argtypes = [c_ushort, c_uint32, c_uint8]
- self.lib.set_parameter_midi_channel.restype = None
-
- self.lib.set_parameter_midi_cc.argtypes = [c_ushort, c_uint32, c_int16]
- self.lib.set_parameter_midi_cc.restype = None
-
- self.lib.set_program.argtypes = [c_ushort, c_uint32]
- self.lib.set_program.restype = None
-
- self.lib.set_midi_program.argtypes = [c_ushort, c_uint32]
- self.lib.set_midi_program.restype = None
-
- self.lib.set_custom_data.argtypes = [c_ushort, c_enum, c_char_p, c_char_p]
- self.lib.set_custom_data.restype = None
-
- self.lib.set_chunk_data.argtypes = [c_ushort, c_char_p]
- self.lib.set_chunk_data.restype = None
-
- self.lib.set_gui_data.argtypes = [c_ushort, c_int, c_uintptr]
- self.lib.set_gui_data.restype = None
-
- self.lib.show_gui.argtypes = [c_ushort, c_bool]
- self.lib.show_gui.restype = None
-
- self.lib.idle_guis.argtypes = None
- self.lib.idle_guis.restype = None
-
- self.lib.send_midi_note.argtypes = [c_ushort, c_bool, c_uint8, c_uint8]
- self.lib.send_midi_note.restype = None
-
- self.lib.prepare_for_save.argtypes = [c_ushort]
- self.lib.prepare_for_save.restype = None
-
- self.lib.set_callback_function.argtypes = [CallbackFunc]
- self.lib.set_callback_function.restype = None
-
- self.lib.set_option.argtypes = [c_enum, c_int, c_char_p]
- self.lib.set_option.restype = None
-
- self.lib.get_last_error.argtypes = None
- self.lib.get_last_error.restype = c_char_p
-
- self.lib.get_host_client_name.argtypes = None
- self.lib.get_host_client_name.restype = c_char_p
-
- self.lib.get_host_osc_url.argtypes = None
- self.lib.get_host_osc_url.restype = c_char_p
-
- self.lib.get_buffer_size.argtypes = None
- self.lib.get_buffer_size.restype = c_uint32
-
- self.lib.get_sample_rate.argtypes = None
- self.lib.get_sample_rate.restype = c_double
-
- self.lib.get_latency.argtypes = None
- self.lib.get_latency.restype = c_double
-
- def carla_init(self, client_name):
- return self.lib.carla_init(client_name.encode("utf-8"))
-
- def carla_close(self):
- return self.lib.carla_close()
-
- def carla_is_engine_running(self):
- return self.lib.carla_is_engine_running()
-
- def add_plugin(self, btype, ptype, filename, label, extra_stuff):
- return self.lib.add_plugin(btype, ptype, filename.encode("utf-8"), label.encode("utf-8"), cast(extra_stuff, c_void_p))
-
- def remove_plugin(self, plugin_id):
- return self.lib.remove_plugin(plugin_id)
-
- def get_plugin_info(self, plugin_id):
- return struct_to_dict(self.lib.get_plugin_info(plugin_id).contents)
-
- def get_audio_port_count_info(self, plugin_id):
- return struct_to_dict(self.lib.get_audio_port_count_info(plugin_id).contents)
-
- def get_midi_port_count_info(self, plugin_id):
- return struct_to_dict(self.lib.get_midi_port_count_info(plugin_id).contents)
-
- def get_parameter_count_info(self, plugin_id):
- return struct_to_dict(self.lib.get_parameter_count_info(plugin_id).contents)
-
- def get_parameter_info(self, plugin_id, parameter_id):
- return struct_to_dict(self.lib.get_parameter_info(plugin_id, parameter_id).contents)
-
- def get_scalepoint_info(self, plugin_id, parameter_id, scalepoint_id):
- return struct_to_dict(self.lib.get_scalepoint_info(plugin_id, parameter_id, scalepoint_id).contents)
-
- def get_midi_program_info(self, plugin_id, midi_program_id):
- return struct_to_dict(self.lib.get_midi_program_info(plugin_id, midi_program_id).contents)
-
- def get_parameter_data(self, plugin_id, parameter_id):
- return struct_to_dict(self.lib.get_parameter_data(plugin_id, parameter_id).contents)
-
- def get_parameter_ranges(self, plugin_id, parameter_id):
- return struct_to_dict(self.lib.get_parameter_ranges(plugin_id, parameter_id).contents)
-
- def get_custom_data(self, plugin_id, custom_data_id):
- return struct_to_dict(self.lib.get_custom_data(plugin_id, custom_data_id).contents)
-
- def get_chunk_data(self, plugin_id):
- return self.lib.get_chunk_data(plugin_id)
-
- def get_gui_info(self, plugin_id):
- return struct_to_dict(self.lib.get_gui_info(plugin_id).contents)
-
- def get_parameter_count(self, plugin_id):
- return self.lib.get_parameter_count(plugin_id)
-
- def get_program_count(self, plugin_id):
- return self.lib.get_program_count(plugin_id)
-
- def get_midi_program_count(self, plugin_id):
- return self.lib.get_midi_program_count(plugin_id)
-
- def get_custom_data_count(self, plugin_id):
- return self.lib.get_custom_data_count(plugin_id)
-
- def get_program_name(self, plugin_id, program_id):
- return self.lib.get_program_name(plugin_id, program_id)
-
- def get_midi_program_name(self, plugin_id, midi_program_id):
- return self.lib.get_midi_program_name(plugin_id, midi_program_id)
-
- def get_real_plugin_name(self, plugin_id):
- return self.lib.get_real_plugin_name(plugin_id)
-
- def get_current_program_index(self, plugin_id):
- return self.lib.get_current_program_index(plugin_id)
-
- def get_current_midi_program_index(self, plugin_id):
- return self.lib.get_current_midi_program_index(plugin_id)
-
- def get_default_parameter_value(self, plugin_id, parameter_id):
- return self.lib.get_default_parameter_value(plugin_id, parameter_id)
-
- def get_current_parameter_value(self, plugin_id, parameter_id):
- return self.lib.get_current_parameter_value(plugin_id, parameter_id)
-
- def get_input_peak_value(self, plugin_id, port_id):
- return self.lib.get_input_peak_value(plugin_id, port_id)
-
- def get_output_peak_value(self, plugin_id, port_id):
- return self.lib.get_output_peak_value(plugin_id, port_id)
-
- def set_active(self, plugin_id, onoff):
- self.lib.set_active(plugin_id, onoff)
-
- def set_drywet(self, plugin_id, value):
- self.lib.set_drywet(plugin_id, value)
-
- def set_volume(self, plugin_id, value):
- self.lib.set_volume(plugin_id, value)
-
- def set_balance_left(self, plugin_id, value):
- self.lib.set_balance_left(plugin_id, value)
-
- def set_balance_right(self, plugin_id, value):
- self.lib.set_balance_right(plugin_id, value)
-
- def set_parameter_value(self, plugin_id, parameter_id, value):
- self.lib.set_parameter_value(plugin_id, parameter_id, value)
-
- def set_parameter_midi_channel(self, plugin_id, parameter_id, channel):
- self.lib.set_parameter_midi_channel(plugin_id, parameter_id, channel)
-
- def set_parameter_midi_cc(self, plugin_id, parameter_id, midi_cc):
- self.lib.set_parameter_midi_cc(plugin_id, parameter_id, midi_cc)
-
- def set_program(self, plugin_id, program_id):
- self.lib.set_program(plugin_id, program_id)
-
- def set_midi_program(self, plugin_id, midi_program_id):
- self.lib.set_midi_program(plugin_id, midi_program_id)
-
- def set_custom_data(self, plugin_id, dtype, key, value):
- self.lib.set_custom_data(plugin_id, dtype, key.encode("utf-8"), value.encode("utf-8"))
-
- def set_chunk_data(self, plugin_id, chunk_data):
- self.lib.set_chunk_data(plugin_id, chunk_data.encode("utf-8"))
-
- def set_gui_data(self, plugin_id, data, gui_addr):
- self.lib.set_gui_data(plugin_id, data, gui_addr)
-
- def show_gui(self, plugin_id, yesno):
- self.lib.show_gui(plugin_id, yesno)
-
- def idle_guis(self):
- self.lib.idle_guis()
-
- def send_midi_note(self, plugin_id, onoff, note, velocity):
- self.lib.send_midi_note(plugin_id, onoff, note, velocity)
-
- def prepare_for_save(self, plugin_id):
- self.lib.prepare_for_save(plugin_id)
-
- def set_callback_function(self, func):
- global Callback
- Callback = CallbackFunc(func)
- self.lib.set_callback_function(Callback)
-
- def set_option(self, option, value, value_str):
- self.lib.set_option(option, value, value_str.encode("utf-8"))
-
- def get_last_error(self):
- return self.lib.get_last_error()
-
- def get_host_client_name(self):
- return self.lib.get_host_client_name()
-
- def get_host_osc_url(self):
- return self.lib.get_host_osc_url()
-
- def get_buffer_size(self):
- return self.lib.get_buffer_size()
-
- def get_sample_rate(self):
- return self.lib.get_sample_rate()
-
- def get_latency(self):
- return self.lib.get_latency()
-
- # ------------------------------------------------------------------------------------------------
- # Default Plugin Folders (set)
-
- global LADSPA_PATH, DSSI_PATH, LV2_PATH, VST_PATH, SF2_PATH
-
- LADSPA_PATH_env = os.getenv("LADSPA_PATH")
- DSSI_PATH_env = os.getenv("DSSI_PATH")
- LV2_PATH_env = os.getenv("LV2_PATH")
- VST_PATH_env = os.getenv("VST_PATH")
- SF2_PATH_env = os.getenv("SF2_PATH")
-
- if (LADSPA_PATH_env):
- LADSPA_PATH = LADSPA_PATH_env.split(splitter)
- else:
- LADSPA_PATH = DEFAULT_LADSPA_PATH
-
- if (DSSI_PATH_env):
- DSSI_PATH = DSSI_PATH_env.split(splitter)
- else:
- DSSI_PATH = DEFAULT_DSSI_PATH
-
- if (LV2_PATH_env):
- LV2_PATH = LV2_PATH_env.split(splitter)
- else:
- LV2_PATH = DEFAULT_LV2_PATH
-
- if (VST_PATH_env):
- VST_PATH = VST_PATH_env.split(splitter)
- else:
- VST_PATH = DEFAULT_VST_PATH
-
- if (SF2_PATH_env):
- SF2_PATH = SF2_PATH_env.split(splitter)
- else:
- SF2_PATH = DEFAULT_SF2_PATH
-
- if (haveRDF):
- LADSPA_RDF_PATH_env = os.getenv("LADSPA_RDF_PATH")
- if (LADSPA_RDF_PATH_env):
- ladspa_rdf.set_rdf_path(LADSPA_RDF_PATH_env.split(splitter))
-
- lv2_rdf.set_rdf_path(LV2_PATH)
|