| 
							- #!/usr/bin/env python3
 - # -*- coding: utf-8 -*-
 - 
 - # Carla Backend code (OSC stuff)
 - # Copyright (C) 2011-2015 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 (Custom)
 - 
 - from carla_host import *
 - 
 - # ------------------------------------------------------------------------------------------------------------
 - # Imports (liblo)
 - 
 - from liblo import make_method, Address, ServerError, Server
 - from liblo import send as lo_send
 - from liblo import TCP as LO_TCP
 - from liblo import UDP as LO_UDP
 - 
 - from random import random
 - 
 - # ------------------------------------------------------------------------------------------------------------
 - # Global liblo objects
 - 
 - global lo_target, lo_target_name
 - lo_target      = None
 - lo_target_name = ""
 - 
 - # ------------------------------------------------------------------------------------------------------------
 - # Host OSC object
 - 
 - class CarlaHostOSC(CarlaHostQtPlugin):
 -     def __init__(self):
 -         CarlaHostQtPlugin.__init__(self)
 - 
 -     # -------------------------------------------------------------------
 - 
 -     def printAndReturnError(self, error):
 -         print(error)
 -         self.fLastError = error
 -         return False
 - 
 -     def sendMsg(self, lines):
 -         global lo_target, lo_target_name
 - 
 -         if lo_target is None:
 -             return self.printAndReturnError("lo_target is None")
 -         if lo_target_name is None:
 -             return self.printAndReturnError("lo_target_name is None")
 -         if len(lines) < 2:
 -             return self.printAndReturnError("not enough arguments")
 - 
 -         method = lines.pop(0)
 - 
 -         if method not in (
 -                           #"set_option",
 -                           "set_active",
 -                           "set_drywet",
 -                           "set_volume",
 -                           "set_balance_left",
 -                           "set_balance_right",
 -                           "set_panning",
 -                           #"set_ctrl_channel",
 -                           "set_parameter_value",
 -                           "set_parameter_midi_channel",
 -                           "set_parameter_midi_cc",
 -                           "set_program",
 -                           "set_midi_program",
 -                           #"set_custom_data",
 -                           #"set_chunk_data",
 -                           #"prepare_for_save",
 -                           #"reset_parameters",
 -                           #"randomize_parameters",
 -                           "send_midi_note"
 -                           ):
 -             return self.printAndReturnError("invalid method '%s'" % method)
 - 
 -         pluginId = lines.pop(0)
 - 
 -         args = []
 - 
 -         if method == "send_midi_note":
 -             channel, note, velocity = lines
 - 
 -             if velocity:
 -                 method = "note_on"
 -                 args   = [channel, note, velocity]
 -             else:
 -                 method = "note_off"
 -                 args   = [channel, note]
 - 
 -         else:
 -             for line in lines:
 -                 if isinstance(line, bool):
 -                     args.append(int(line))
 -                 else:
 -                     args.append(line)
 - 
 -         path = "/%s/%i/%s" % (lo_target_name, pluginId, method)
 - 
 -         print(path, args)
 - 
 -         lo_send(lo_target, path, *args)
 -         return True
 - 
 -     # -------------------------------------------------------------------
 - 
 -     def engine_init(self, driverName, clientName):
 -         global lo_target
 -         return lo_target is not None
 - 
 -     def engine_close(self):
 -         return True
 - 
 -     def engine_idle(self):
 -         return
 - 
 -     def is_engine_running(self):
 -         global lo_target
 -         return lo_target is not None
 - 
 -     def set_engine_about_to_close(self):
 -         return
 - 
 - # ------------------------------------------------------------------------------------------------------------
 - # OSC Control server
 - 
 - class CarlaControlServer(Server):
 -     def __init__(self, host, mode):
 -         Server.__init__(self, 8998 + int(random()*9000), mode)
 - 
 -         self.host = host
 - 
 -     def idle(self):
 -         self.fReceivedMsgs = False
 - 
 -         while self.recv(0) and self.fReceivedMsgs:
 -             pass
 - 
 -     def getFullURL(self):
 -         return "%scarla-control" % self.get_url()
 - 
 -     @make_method('/carla-control/add_plugin_start', 'is') # FIXME skip name
 -     def add_plugin_start_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, pluginName = args
 -         self.host._add(pluginId)
 -         self.host._set_pluginInfoUpdate(pluginId, {'name': pluginName})
 - 
 -     @make_method('/carla-control/add_plugin_end', 'i') # FIXME skip name
 -     def add_plugin_end_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, = args
 -         self.host.PluginAddedCallback.emit(pluginId, "") #self.fPluginsInfo[pluginId].pluginInfo['name'])
 - 
 -     @make_method('/carla-control/remove_plugin', 'i')
 -     def remove_plugin_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, = args
 -         self.host.PluginRemovedCallback.emit(pluginId)
 - 
 -     @make_method('/carla-control/set_plugin_info1', 'iiiih')
 -     def set_plugin_info1_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, type_, category, hints, uniqueId = args # , optsAvail, optsEnabled
 -         optsAvail = optsEnabled = 0x0 # FIXME
 - 
 -         hints &= ~PLUGIN_HAS_CUSTOM_UI
 - 
 -         pinfo = {
 -             'type': type_,
 -             'category': category,
 -             'hints': hints,
 -             'optionsAvailable': optsAvail,
 -             'optionsEnabled': optsEnabled,
 -             'uniqueId': uniqueId
 -         }
 - 
 -         self.host._set_pluginInfoUpdate(pluginId, pinfo)
 - 
 -     @make_method('/carla-control/set_plugin_info2', 'issss')
 -     def set_plugin_info2_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, realName, label, maker, copyright = args # , filename, name, iconName
 -         filename = name = iconName = "" # FIXME
 - 
 -         pinfo = {
 -             'filename': filename,
 -             #'name':  name, # FIXME
 -             'label': label,
 -             'maker': maker,
 -             'copyright': copyright,
 -             'iconName': iconName
 -         }
 - 
 -         self.host._set_pluginInfoUpdate(pluginId, pinfo)
 -         self.host._set_pluginRealName(pluginId, realName)
 - 
 -     @make_method('/carla-control/set_audio_count', 'iii')
 -     def set_audio_count_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, ins, outs = args
 -         self.host._set_audioCountInfo(pluginId, {'ins': ins, 'outs': outs})
 - 
 -     @make_method('/carla-control/set_midi_count', 'iii')
 -     def set_midi_count_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, ins, outs = args
 -         self.host._set_midiCountInfo(pluginId, {'ins': ins, 'outs': outs})
 - 
 -     @make_method('/carla-control/set_parameter_count', 'iii') # FIXME
 -     def set_parameter_count_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, ins, outs = args # , count
 -         count = ins + outs
 -         self.host._set_parameterCountInfo(pluginId, count, {'ins': ins, 'outs': outs})
 - 
 -     @make_method('/carla-control/set_program_count', 'ii')
 -     def set_program_count_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, count = args
 -         self.host._set_programCount(pluginId, count)
 - 
 -     @make_method('/carla-control/set_midi_program_count', 'ii')
 -     def set_midi_program_count_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, count = args
 -         self.host._set_midiProgramCount(pluginId, count)
 - 
 -     @make_method('/carla-control/set_parameter_data', 'iiiiss')
 -     def set_parameter_data_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, paramId, type_, hints, name, unit = args
 - 
 -         hints &= ~(PARAMETER_USES_SCALEPOINTS | PARAMETER_USES_CUSTOM_TEXT)
 - 
 -         paramInfo = {
 -             'name': name,
 -             'symbol': "",
 -             'unit': unit,
 -             'scalePointCount': 0,
 -         }
 -         self.host._set_parameterInfo(pluginId, paramId, paramInfo)
 - 
 -         paramData = {
 -             'type': type_,
 -             'hints': hints,
 -             'index': paramId,
 -             'rindex': -1,
 -             'midiCC': -1,
 -             'midiChannel': 0
 -         }
 -         self.host._set_parameterData(pluginId, paramId, paramData)
 - 
 -     @make_method('/carla-control/set_parameter_ranges1', 'iifff')
 -     def set_parameter_ranges1_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, paramId, def_, min_, max_ = args
 - 
 -         paramRanges = {
 -             'def': def_,
 -             'min': min_,
 -             'max': max_
 -         }
 - 
 -         self.host._set_parameterRangesUpdate(pluginId, paramId, paramRanges)
 - 
 -     @make_method('/carla-control/set_parameter_ranges2', 'iifff')
 -     def set_parameter_ranges2_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, paramId, step, stepSmall, stepLarge = args
 - 
 -         paramRanges = {
 -             'step': step,
 -             'stepSmall': stepSmall,
 -             'stepLarge': stepLarge
 -         }
 - 
 -         self.host._set_parameterRangesUpdate(pluginId, paramId, paramRanges)
 - 
 -     @make_method('/carla-control/set_parameter_midi_cc', 'iii')
 -     def set_parameter_midi_cc_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, paramId, cc = args
 -         self.host._set_parameterMidiCC(pluginId, paramId, cc)
 -         self.host.ParameterMidiCcChangedCallback.emit(pluginId, paramId, cc)
 - 
 -     @make_method('/carla-control/set_parameter_midi_channel', 'iii')
 -     def set_parameter_midi_channel_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, paramId, channel = args
 -         self.host._set_parameterMidiChannel(pluginId, paramId, channel)
 -         self.host.ParameterMidiChannelChangedCallback.emit(pluginId, paramId, channel)
 - 
 -     @make_method('/carla-control/set_parameter_value', 'iif')
 -     def set_parameter_value_callback(self, path, args):
 -         pluginId, paramId, paramValue = args
 - 
 -         if paramId < 0:
 -             self.host._set_internalValue(pluginId, paramId, paramValue)
 -         else:
 -             self.host._set_parameterValue(pluginId, paramId, paramValue)
 - 
 -         self.host.ParameterValueChangedCallback.emit(pluginId, paramId, paramValue)
 - 
 -     @make_method('/carla-control/set_default_value', 'iif')
 -     def set_default_value_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, paramId, paramValue = args
 -         self.host._set_parameterDefault(pluginId, paramId, paramValue)
 -         self.host.ParameterDefaultChangedCallback.emit(pluginId, paramId, paramValue)
 - 
 -     @make_method('/carla-control/set_current_program', 'ii')
 -     def set_current_program_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, current = args
 -         self.host._set_currentProgram(pluginId, current)
 -         self.host.ProgramChangedCallback.emit(pluginId, current)
 - 
 -     @make_method('/carla-control/set_current_midi_program', 'ii')
 -     def set_current_midi_program_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, current = args
 -         self.host._set_currentMidiProgram(pluginId, current)
 -         self.host.MidiProgramChangedCallback.emit(pluginId, current)
 - 
 -     @make_method('/carla-control/set_program_name', 'iis')
 -     def set_program_name_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, progId, progName = args
 -         self.host._set_programName(pluginId, progId, progName)
 - 
 -     @make_method('/carla-control/set_midi_program_data', 'iiiis')
 -     def set_midi_program_data_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, midiProgId, bank, program, name = args
 -         self.host._set_midiProgramData(pluginId, midiProgId, {'bank': bank, 'program': program, 'name': name})
 - 
 -     @make_method('/carla-control/note_on', 'iiii')
 -     def set_note_on_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, channel, note, velocity = args
 -         self.host.NoteOnCallback.emit(pluginId, channel, note, velocity)
 - 
 -     @make_method('/carla-control/note_off', 'iii')
 -     def set_note_off_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         pluginId, channel, note = args
 -         self.host.NoteOffCallback.emit(pluginId, channel, note)
 - 
 -     @make_method('/carla-control/set_peaks', 'iffff')
 -     def set_peaks_callback(self, path, args):
 -         self.fReceivedMsgs = True
 -         pluginId, in1, in2, out1, out2 = args
 -         self.host._set_peaks(pluginId, in1, in2, out1, out2)
 - 
 -     @make_method('/carla-control/exit', '')
 -     def set_exit_callback(self, path, args):
 -         print(path, args)
 -         self.fReceivedMsgs = True
 -         self.host.QuitCallback.emit()
 - 
 -     @make_method(None, None)
 -     def fallback(self, path, args):
 -         print("ControlServer::fallback(\"%s\") - unknown message, args =" % path, args)
 -         self.fReceivedMsgs = True
 - 
 - # ------------------------------------------------------------------------------------------------------------
 - # Main Window
 - 
 - class HostWindowOSC(HostWindow):
 -     def __init__(self, host, oscAddr):
 -         HostWindow.__init__(self, host, False)
 -         self.host = host
 - 
 -         if False:
 -             # kdevelop likes this :)
 -             host = CarlaHostPlugin()
 -             self.host = host
 - 
 -         # ----------------------------------------------------------------------------------------------------
 -         # Internal stuff
 - 
 -         self.fIdleTimer  = 0
 -         self.fOscAddress = oscAddr
 -         self.fOscServer  = None
 - 
 -         # ----------------------------------------------------------------------------------------------------
 -         # Set up GUI (not connected)
 - 
 -         self.ui.act_file_refresh.setEnabled(False)
 - 
 -         # ----------------------------------------------------------------------------------------------------
 -         # Connect actions to functions
 - 
 -         self.ui.act_file_connect.triggered.connect(self.slot_fileConnect)
 -         self.ui.act_file_refresh.triggered.connect(self.slot_fileRefresh)
 - 
 -         # ----------------------------------------------------------------------------------------------------
 -         # Final setup
 - 
 -         if oscAddr:
 -             QTimer.singleShot(0, self.connectOsc)
 - 
 -     def connectOsc(self, addr = None):
 -         global lo_target, lo_target_name
 - 
 -         if addr is not None:
 -             self.fOscAddress = addr
 - 
 -         lo_target      = Address(self.fOscAddress)
 -         lo_target_name = self.fOscAddress.rsplit("/", 1)[-1]
 -         print("Connecting to \"%s\" as '%s'..." % (self.fOscAddress, lo_target_name))
 - 
 -         try:
 -             self.fOscServer = CarlaControlServer(self.host, LO_UDP if self.fOscAddress.startswith("osc.udp") else LO_TCP)
 -         except: # ServerError as err:
 -             QMessageBox.critical(self, self.tr("Error"), self.tr("Failed to connect, operation failed."))
 -             return
 - 
 -         self.fIdleTimer = self.startTimer(20)
 -         lo_send(lo_target, "/register", self.fOscServer.getFullURL())
 - 
 -         self.startTimers()
 -         self.ui.act_file_refresh.setEnabled(True)
 - 
 -     def disconnectOsc(self):
 -         global lo_target, lo_target_name
 - 
 -         self.killTimers()
 -         self.ui.act_file_refresh.setEnabled(False)
 - 
 -         if lo_target is not None:
 -             try:
 -                 lo_send(lo_target, "/unregister")
 -             except:
 -                 pass
 - 
 -         self.killTimer(self.fIdleTimer)
 -         self.fIdleTimer = 0
 - 
 -         if self.fOscServer is not None:
 -             del self.fOscServer
 -             self.fOscServer = None
 - 
 -         self.removeAllPlugins()
 - 
 -         lo_target        = None
 -         lo_target_name   = ""
 -         self.fOscAddress = ""
 - 
 -     def removeAllPlugins(self):
 -         self.host.fPluginsInfo = []
 -         HostWindow.removeAllPlugins(self)
 - 
 -     @pyqtSlot()
 -     def slot_fileConnect(self):
 -         global lo_target, lo_target_name
 - 
 -         if lo_target and self.fOscServer:
 -             urlText = self.fOscAddress
 -         else:
 -             urlText = "osc.tcp://127.0.0.1:19000/Carla"
 - 
 -         addr, ok = QInputDialog.getText(self, self.tr("Carla Control - Connect"), self.tr("Address"), text=urlText)
 - 
 -         if not ok:
 -             return
 - 
 -         self.disconnectOsc()
 -         self.connectOsc(addr)
 - 
 -     @pyqtSlot()
 -     def slot_fileRefresh(self):
 -         global lo_target
 - 
 -         if lo_target is None or self.fOscServer is None:
 -             return
 - 
 -         self.killTimers()
 -         lo_send(lo_target, "/unregister")
 -         self.removeAllPlugins()
 -         lo_send(lo_target, "/register", self.fOscServer.getFullURL())
 -         self.startTimers()
 - 
 -     @pyqtSlot()
 -     def slot_handleQuitCallback(self):
 -         self.disconnectOsc()
 - 
 -     def timerEvent(self, event):
 -         if event.timerId() == self.fIdleTimer:
 -             self.fOscServer.idle()
 -         HostWindow.timerEvent(self, event)
 - 
 -     def closeEvent(self, event):
 -         global lo_target
 - 
 -         self.killTimers()
 - 
 -         if lo_target is not None and self.fOscServer is not None:
 -             lo_send(lo_target, "/unregister")
 - 
 -         HostWindow.closeEvent(self, event)
 - 
 - # ------------------------------------------------------------------------------------------------------------
 
 
  |