Browse Source

Finish REST API

tags/v1.9.11
falkTX 6 years ago
parent
commit
b985a95a4f
8 changed files with 1411 additions and 262 deletions
  1. +1
    -0
      source/carla_backend.py
  2. +263
    -112
      source/carla_backend_qtweb.py
  3. +2
    -2
      source/carla_host.py
  4. +69
    -36
      source/rest/buffers.cpp
  5. +3
    -0
      source/rest/buffers.hpp
  6. +971
    -94
      source/rest/carla-host.cpp
  7. +4
    -4
      source/rest/carla-utils.cpp
  8. +98
    -14
      source/rest/rest-server.cpp

+ 1
- 0
source/carla_backend.py View File

@@ -1241,6 +1241,7 @@ class CarlaHostMeta(object):
# info about this host object
self.isControl = False
self.isPlugin = False
self.isRemote = False
self.nsmOK = False

# settings


+ 263
- 112
source/carla_backend_qtweb.py View File

@@ -82,24 +82,36 @@ class CarlaHostQtWeb(CarlaHostQtNull):
self.baseurl = "http://localhost:2228"
self.stream = create_stream(self.baseurl)

self.isRemote = True

def get_engine_driver_count(self):
# FIXME
return int(requests.get("{}/get_engine_driver_count".format(self.baseurl)).text) - 1

def get_engine_driver_name(self, index):
return requests.get("{}/get_engine_driver_name/{}".format(self.baseurl, index)).text
return requests.get("{}/get_engine_driver_name".format(self.baseurl), params={
'index': index,
}).text

def get_engine_driver_device_names(self, index):
return requests.get("{}/get_engine_driver_device_names/{}".format(self.baseurl, index)).text.split("\n")
return requests.get("{}/get_engine_driver_device_names".format(self.baseurl), params={
'index': index,
}).text.split("\n")

def get_engine_driver_device_info(self, index, name):
return requests.get("{}/get_engine_driver_device_info/{}/{}".format(self.baseurl, index, name)).json()
return requests.get("{}/get_engine_driver_device_info".format(self.baseurl), params={
'index': index,
'name': name,
}).json()

def engine_init(self, driverName, clientName):
return requests.get("{}/engine_init/{}/{}".format(self.baseurl, driverName, clientName)).status_code == 200
return bool(int(requests.get("{}/engine_init".format(self.baseurl), params={
'driverName': driverName,
'clientName': clientName,
}).text))

def engine_close(self):
return requests.get("{}/engine_close".format(self.baseurl)).status_code == 200
return bool(int(requests.get("{}/engine_close".format(self.baseurl)).text))

def engine_idle(self):
closed = False
@@ -135,34 +147,53 @@ class CarlaHostQtWeb(CarlaHostQtNull):

def is_engine_running(self):
try:
return requests.get("{}/is_engine_running".format(self.baseurl)).status_code == 200
return bool(int(requests.get("{}/is_engine_running".format(self.baseurl)).text))
except requests.exceptions.ConnectionError:
if self.fEngineCallback is None:
self.fEngineCallback(None, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0, "")

def set_engine_about_to_close(self):
return requests.get("{}/set_engine_about_to_close".format(self.baseurl)).status_code == 200
return bool(int(requests.get("{}/set_engine_about_to_close".format(self.baseurl)).text))

def set_engine_option(self, option, value, valueStr):
requests.get("{}/set_engine_option/{}/{}/{}".format(self.baseurl, option, value, valueStr))
requests.get("{}/set_engine_option".format(self.baseurl), params={
'option': option,
'value': value,
'valueStr': valueStr,
})

def load_file(self, filename):
return requests.get("{}/load_file/{}".format(self.baseurl, filename)).status_code == 200
return bool(int(requests.get("{}/load_file".format(self.baseurl), params={
'filename': filename,
}).text))

def load_project(self, filename):
return requests.get("{}/load_project/{}".format(self.baseurl, filename)).status_code == 200
return bool(int(requests.get("{}/load_project".format(self.baseurl), params={
'filename': filename,
}).text))

def save_project(self, filename):
return requests.get("{}/save_project/{}".format(self.baseurl, filename)).status_code == 200
return bool(int(requests.get("{}/save_project".format(self.baseurl), params={
'filename': filename,
}).text))

def patchbay_connect(self, groupIdA, portIdA, groupIdB, portIdB):
return requests.get("{}/patchbay_connect/{}/{}/{}/{}".format(self.baseurl, groupIdA, portIdA, groupIdB, portIdB)).status_code == 200
return bool(int(requests.get("{}/patchbay_connect".format(self.baseurl), params={
'groupIdA': groupIdA,
'portIdA': portIdA,
'groupIdB': groupIdB,
'portIdB': portIdB,
}).text))

def patchbay_disconnect(self, connectionId):
return requests.get("{}/patchbay_disconnect/{}".format(self.baseurl, connectionId)).status_code == 200
return bool(int(requests.get("{}/patchbay_disconnect".format(self.baseurl), params={
'connectionId': connectionId,
}).text))

def patchbay_refresh(self, external):
return requests.get("{}/patchbay_refresh/{}".format(self.baseurl, external)).status_code == 200
return bool(int(requests.get("{}/patchbay_refresh".format(self.baseurl), params={
'external': external,
}).text))

def transport_play(self):
requests.get("{}/transport_play".format(self.baseurl))
@@ -171,10 +202,14 @@ class CarlaHostQtWeb(CarlaHostQtNull):
requests.get("{}/transport_pause".format(self.baseurl))

def transport_bpm(self, bpm):
requests.get("{}/transport_bpm/{}".format(self.baseurl, bpm))
requests.get("{}/transport_bpm".format(self.baseurl), params={
'bpm': bpm,
})

def transport_relocate(self, frame):
requests.get("{}/transport_relocate/{}".format(self.baseurl, frame))
requests.get("{}/transport_relocate".format(self.baseurl), params={
'frame': frame,
})

def get_current_transport_frame(self):
return int(requests.get("{}/get_current_transport_frame".format(self.baseurl)).text)
@@ -189,169 +224,326 @@ class CarlaHostQtWeb(CarlaHostQtNull):
return int(requests.get("{}/get_max_plugin_number".format(self.baseurl)).text)

def add_plugin(self, btype, ptype, filename, name, label, uniqueId, extraPtr, options):
return requests.get("{}/add_plugin/{}/{}/{}/{}/{}/{}/{}/{}".format(self.baseurl, btype, ptype, filename, name, label, uniqueId, extraPtr, options)).status_code == 200
return bool(int(requests.get("{}/add_plugin".format(self.baseurl), params={
'btype': btype,
'ptype': ptype,
'filename': filename,
'name': name,
'label': label,
'uniqueId': uniqueId,
'options': options,
}).text))

def remove_plugin(self, pluginId):
return requests.get("{}/remove_plugin/{}".format(self.baseurl, pluginId)).status_code == 200
return bool(int(requests.get("{}/remove_plugin".format(self.baseurl), params={
'filename': pluginId,
}).text))

def remove_all_plugins(self):
return requests.get("{}/remove_all_plugins".format(self.baseurl)).status_code == 200
return bool(int(requests.get("{}/remove_all_plugins".format(self.baseurl)).text))

def rename_plugin(self, pluginId, newName):
return requests.get("{}/rename_plugin/{}/{}".format(self.baseurl, pluginId, newName)).text
return requests.get("{}/rename_plugin".format(self.baseurl), params={
'pluginId': pluginId,
'newName': newName,
}).text

def clone_plugin(self, pluginId):
return requests.get("{}/clone_plugin/{}".format(self.baseurl, pluginId)).status_code == 200
return bool(int(requests.get("{}/clone_plugin".format(self.baseurl), params={
'pluginId': pluginId,
}).text))

def replace_plugin(self, pluginId):
return requests.get("{}/replace_plugin/{}".format(self.baseurl, pluginId)).status_code == 200
return bool(int(requests.get("{}/replace_plugin".format(self.baseurl), params={
'pluginId': pluginId,
}).text))

def switch_plugins(self, pluginIdA, pluginIdB):
return requests.get("{}/switch_plugins/{}/{}".format(self.baseurl, pluginIdA, pluginIdB)).status_code == 200
return bool(int(requests.get("{}/switch_plugins".format(self.baseurl), params={
'pluginIdA': pluginIdA,
'pluginIdB': pluginIdB,
}).text))

def load_plugin_state(self, pluginId, filename):
return requests.get("{}/load_plugin_state/{}/{}".format(self.baseurl, pluginId, filename)).status_code == 200
return bool(int(requests.get("{}/load_plugin_state".format(self.baseurl), params={
'pluginId': pluginId,
'filename': filename,
}).text))

def save_plugin_state(self, pluginId, filename):
return requests.get("{}/save_plugin_state/{}/{}".format(self.baseurl, pluginId, filename)).status_code == 200
return bool(int(requests.get("{}/save_plugin_state".format(self.baseurl), params={
'pluginId': pluginId,
'filename': filename,
}).text))

def export_plugin_lv2(self, pluginId, lv2path):
return requests.get("{}/export_plugin_lv2/{}/{}".format(self.baseurl, pluginId, lv2path)).status_code == 200
return bool(int(requests.get("{}/export_plugin_lv2".format(self.baseurl), params={
'pluginId': pluginId,
'lv2path': lv2path,
}).text))

def get_plugin_info(self, pluginId):
return requests.get("{}/get_plugin_info/{}".format(self.baseurl, pluginId)).json()
return requests.get("{}/get_plugin_info".format(self.baseurl), params={
'pluginId': pluginId,
}).json()

def get_audio_port_count_info(self, pluginId):
return requests.get("{}/get_audio_port_count_info/{}".format(self.baseurl, pluginId)).json()
return requests.get("{}/get_audio_port_count_info".format(self.baseurl), params={
'pluginId': pluginId,
}).json()

def get_midi_port_count_info(self, pluginId):
return requests.get("{}/get_midi_port_count_info/{}".format(self.baseurl, pluginId)).json()
return requests.get("{}/get_midi_port_count_info".format(self.baseurl), params={
'pluginId': pluginId,
}).json()

def get_parameter_count_info(self, pluginId):
return requests.get("{}/get_parameter_count_info/{}".format(self.baseurl, pluginId)).json()
return requests.get("{}/get_parameter_count_info".format(self.baseurl), params={
'pluginId': pluginId,
}).json()

def get_parameter_info(self, pluginId, parameterId):
return requests.get("{}/get_parameter_info/{}/{}".format(self.baseurl, pluginId, parameterId)).json()
return requests.get("{}/get_parameter_info".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
}).json()

def get_parameter_scalepoint_info(self, pluginId, parameterId, scalePointId):
return requests.get("{}/get_parameter_scalepoint_info/{}/{}/{}".format(self.baseurl, pluginId, parameterId, scalePointId)).json()
return requests.get("{}/get_parameter_scalepoint_info".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
'scalePointId': scalePointId,
}).json()

def get_parameter_data(self, pluginId, parameterId):
return requests.get("{}/get_parameter_data/{}/{}".format(self.baseurl, pluginId, parameterId)).json()
return requests.get("{}/get_parameter_data".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
}).json()

def get_parameter_ranges(self, pluginId, parameterId):
return requests.get("{}/get_parameter_ranges/{}/{}".format(self.baseurl, pluginId, parameterId)).json()
return requests.get("{}/get_parameter_ranges".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
}).json()

def get_midi_program_data(self, pluginId, midiProgramId):
return requests.get("{}/get_midi_program_data/{}/{}".format(self.baseurl, pluginId, midiProgramId)).json()
return requests.get("{}/get_midi_program_data".format(self.baseurl), params={
'pluginId': pluginId,
'midiProgramId': midiProgramId,
}).json()

def get_custom_data(self, pluginId, customDataId):
return requests.get("{}/get_custom_data/{}/{}".format(self.baseurl, pluginId, customDataId)).json()
return requests.get("{}/get_custom_data".format(self.baseurl), params={
'pluginId': pluginId,
'customDataId': customDataId,
}).json()

def get_chunk_data(self, pluginId):
return requests.get("{}/get_chunk_data/{}".format(self.baseurl, pluginId)).text
return requests.get("{}/get_chunk_data".format(self.baseurl), params={
'pluginId': pluginId,
}).text

def get_parameter_count(self, pluginId):
return int(requests.get("{}/get_parameter_count/{}".format(self.baseurl, pluginId)).text)
return int(requests.get("{}/get_parameter_count".format(self.baseurl), params={
'pluginId': pluginId,
}).text)

def get_program_count(self, pluginId):
return int(requests.get("{}/get_program_count/{}".format(self.baseurl, pluginId)).text)
return int(requests.get("{}/get_program_count".format(self.baseurl), params={
'pluginId': pluginId,
}).text)

def get_midi_program_count(self, pluginId):
return int(requests.get("{}/get_midi_program_count/{}".format(self.baseurl, pluginId)).text)
return int(requests.get("{}/get_midi_program_count".format(self.baseurl), params={
'pluginId': pluginId,
}).text)

def get_custom_data_count(self, pluginId):
return int(requests.get("{}/get_custom_data_count/{}".format(self.baseurl, pluginId)).text)
return int(requests.get("{}/get_custom_data_count".format(self.baseurl), params={
'pluginId': pluginId,
}).text)

def get_parameter_text(self, pluginId, parameterId):
return requests.get("{}/get_parameter_text/{}/{}".format(self.baseurl, pluginId, parameterId)).text
return requests.get("{}/get_parameter_text".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
}).text

def get_program_name(self, pluginId, programId):
return requests.get("{}/get_program_name/{}/{}".format(self.baseurl, pluginId, programId)).text
return requests.get("{}/get_program_name".format(self.baseurl), params={
'pluginId': pluginId,
'programId': programId,
}).text

def get_midi_program_name(self, pluginId, midiProgramId):
return requests.get("{}/get_midi_program_name/{}/{}".format(self.baseurl, pluginId, midiProgramId)).text
return requests.get("{}/get_midi_program_name".format(self.baseurl), params={
'pluginId': pluginId,
'midiProgramId': midiProgramId,
}).text

def get_real_plugin_name(self, pluginId):
return requests.get("{}/get_real_plugin_name/{}".format(self.baseurl, pluginId)).text
return requests.get("{}/get_real_plugin_name".format(self.baseurl), params={
'pluginId': pluginId,
}).text

def get_current_program_index(self, pluginId):
return int(requests.get("{}/get_custom_data_count/{}".format(self.baseurl, pluginId)).text)
return int(requests.get("{}/get_custom_data_count".format(self.baseurl), params={
'pluginId': pluginId,
}).text)

def get_current_midi_program_index(self, pluginId):
return int(requests.get("{}/get_custom_data_count/{}".format(self.baseurl, pluginId)).text)
return int(requests.get("{}/get_custom_data_count".format(self.baseurl), params={
'pluginId': pluginId,
}).text)

def get_default_parameter_value(self, pluginId, parameterId):
return float(requests.get("{}/get_default_parameter_value/{}/{}".format(self.baseurl, pluginId, parameterId)).text)
return float(requests.get("{}/get_default_parameter_value".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
}).text)

def get_current_parameter_value(self, pluginId, parameterId):
return float(requests.get("{}/get_current_parameter_value/{}/{}".format(self.baseurl, pluginId, parameterId)).text)
return float(requests.get("{}/get_current_parameter_value".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
}).text)

def get_internal_parameter_value(self, pluginId, parameterId):
return float(requests.get("{}/get_internal_parameter_value/{}/{}".format(self.baseurl, pluginId, parameterId)).text)
return float(requests.get("{}/get_internal_parameter_value".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
}).text)

def get_input_peak_value(self, pluginId, isLeft):
return float(requests.get("{}/get_input_peak_value/{}/{}".format(self.baseurl, pluginId, isLeft)).text)
return float(requests.get("{}/get_input_peak_value".format(self.baseurl), params={
'pluginId': pluginId,
'isLeft': isLeft,
}).text)

def get_output_peak_value(self, pluginId, isLeft):
return float(requests.get("{}/get_output_peak_value/{}/{}".format(self.baseurl, pluginId, isLeft)).text)
return float(requests.get("{}/get_output_peak_value".format(self.baseurl), params={
'pluginId': pluginId,
'isLeft': isLeft,
}).text)

def set_option(self, pluginId, option, yesNo):
requests.get("{}/set_option/{}/{}/{}".format(self.baseurl, pluginId, option, yesNo))
requests.get("{}/set_option".format(self.baseurl), params={
'pluginId': pluginId,
'option': option,
'yesNo': yesNo,
})

def set_active(self, pluginId, onOff):
requests.get("{}/set_active/{}/{}".format(self.baseurl, pluginId, onOff))
requests.get("{}/set_active".format(self.baseurl), params={
'pluginId': pluginId,
'onOff': onOff,
})

def set_drywet(self, pluginId, value):
requests.get("{}/set_drywet/{}/{}".format(self.baseurl, pluginId, value))
requests.get("{}/set_drywet".format(self.baseurl), params={
'pluginId': pluginId,
'value': value,
})

def set_volume(self, pluginId, value):
requests.get("{}/set_volume/{}/{}".format(self.baseurl, pluginId, value))
requests.get("{}/set_volume".format(self.baseurl), params={
'pluginId': pluginId,
'value': value,
})

def set_balance_left(self, pluginId, value):
requests.get("{}/set_balance_left/{}/{}".format(self.baseurl, pluginId, value))
requests.get("{}/set_balance_left".format(self.baseurl), params={
'pluginId': pluginId,
'value': value,
})

def set_balance_right(self, pluginId, value):
requests.get("{}/set_balance_right/{}/{}".format(self.baseurl, pluginId, value))
requests.get("{}/set_balance_right".format(self.baseurl), params={
'pluginId': pluginId,
'value': value,
})

def set_panning(self, pluginId, value):
requests.get("{}/set_panning/{}/{}".format(self.baseurl, pluginId, value))
requests.get("{}/set_panning".format(self.baseurl), params={
'pluginId': pluginId,
'value': value,
})

def set_ctrl_channel(self, pluginId, channel):
requests.get("{}/set_ctrl_channel/{}/{}".format(self.baseurl, pluginId, channel))
requests.get("{}/set_ctrl_channel".format(self.baseurl), params={
'pluginId': pluginId,
'channel': channel,
})

def set_parameter_value(self, pluginId, parameterId, value):
requests.get("{}/set_parameter_value/{}/{}/{}".format(self.baseurl, pluginId, parameterId, value))
requests.get("{}/set_parameter_value".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
'value': value,
})

def set_parameter_midi_channel(self, pluginId, parameterId, channel):
requests.get("{}/set_parameter_midi_channel/{}/{}/{}".format(self.baseurl, pluginId, parameterId, channel))
requests.get("{}/set_parameter_midi_channel".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
'channel': channel,
})

def set_parameter_midi_cc(self, pluginId, parameterId, cc):
requests.get("{}/set_parameter_midi_cc/{}/{}/{}".format(self.baseurl, pluginId, parameterId, cc))
requests.get("{}/set_parameter_midi_cc".format(self.baseurl), params={
'pluginId': pluginId,
'parameterId': parameterId,
'cc': cc,
})

def set_program(self, pluginId, programId):
requests.get("{}/set_program/{}/{}".format(self.baseurl, pluginId, programId))
requests.get("{}/set_program".format(self.baseurl), params={
'pluginId': pluginId,
})

def set_midi_program(self, pluginId, midiProgramId):
requests.get("{}/set_midi_program/{}/{}".format(self.baseurl, pluginId, midiProgramId))
requests.get("{}/set_midi_program".format(self.baseurl), params={
'pluginId': pluginId,
'midiProgramId': midiProgramId,
})

def set_custom_data(self, pluginId, type_, key, value):
requests.get("{}/set_custom_data/{}/{}/{}/{}".format(self.baseurl, pluginId, type_, key, value))
requests.get("{}/set_custom_data".format(self.baseurl), params={
'pluginId': pluginId,
'type': type_,
'key': key,
'value': value,
})

def set_chunk_data(self, pluginId, chunkData):
requests.get("{}/set_chunk_data/{}/{}".format(self.baseurl, pluginId, chunkData))
requests.get("{}/set_chunk_data".format(self.baseurl), params={
'pluginId': pluginId,
'chunkData': chunkData,
})

def prepare_for_save(self, pluginId):
requests.get("{}/prepare_for_save/{}".format(self.baseurl, pluginId))
requests.get("{}/prepare_for_save".format(self.baseurl), params={
'pluginId': pluginId,
})

def reset_parameters(self, pluginId):
requests.get("{}/reset_parameters/{}".format(self.baseurl, pluginId))
requests.get("{}/reset_parameters".format(self.baseurl), params={
'pluginId': pluginId,
})

def randomize_parameters(self, pluginId):
requests.get("{}/randomize_parameters/{}".format(self.baseurl, pluginId))
requests.get("{}/randomize_parameters".format(self.baseurl), params={
'pluginId': pluginId,
})

def send_midi_note(self, pluginId, channel, note, velocity):
requests.get("{}/send_midi_note/{}/{}/{}/{}".format(self.baseurl, pluginId, channel, note, velocity))
requests.get("{}/send_midi_note".format(self.baseurl), params={
'pluginId': pluginId,
'channel': channel,
'note': note,
'velocity': velocity,
})

def get_buffer_size(self):
return int(requests.get("{}/get_buffer_size".format(self.baseurl)).text)
@@ -367,44 +559,3 @@ class CarlaHostQtWeb(CarlaHostQtNull):

def get_host_osc_url_udp(self):
return requests.get("{}/get_host_osc_url_udp".format(self.baseurl)).text

# ---------------------------------------------------------------------------------------------------------------------
# TESTING

if __name__ == '__main__':

baseurl = "http://localhost:2228"

#driver_count = int(requests.get("{}/get_engine_driver_count".format(baseurl)).text)

## FIXME
#driver_count -= 1

#print("Driver names:")
#for index in range(driver_count):
#print("\t -", requests.get("{}/get_engine_driver_name/{}".format(baseurl, index)).text)

#print("Driver device names:")
#for index in range(driver_count):
#for name in requests.get("{}/get_engine_driver_device_names/{}".format(baseurl, index)).text.split("\n"):
#print("\t {}:".format(name), requests.get("{}/get_engine_driver_device_info/{}/{}".format(baseurl, index, name)).json())

requests.get("{}/engine_close".format(baseurl)).status_code

if requests.get("{}/engine_init/{}/{}".format(baseurl, "JACK", "test")).status_code == 200:
stream = requests.get("{}/stream".format(baseurl), stream=True, timeout=0.25)
#stream.add_done_callback(cb)
#print(stream, dir(stream))

#for line in stream.iter_lines():
#print("line", stream, line)

while True:
print("idle")
for line in iterate_stream_nonblock(stream):
print("line", line)
sleep(0.5)

requests.get("{}/engine_close".format(baseurl)).status_code

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

+ 2
- 2
source/carla_host.py View File

@@ -2774,15 +2774,15 @@ def setHostSettings(host):
host.set_engine_option(ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, host.preferPluginBridges, "")
host.set_engine_option(ENGINE_OPTION_PREFER_UI_BRIDGES, host.preferUIBridges, "")
host.set_engine_option(ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR, host.preventBadBehaviour, "")
host.set_engine_option(ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT, host.showLogs, "")
host.set_engine_option(ENGINE_OPTION_UI_BRIDGES_TIMEOUT, host.uiBridgesTimeout, "")
host.set_engine_option(ENGINE_OPTION_UIS_ALWAYS_ON_TOP, host.uisAlwaysOnTop, "")

if host.isPlugin or host.is_engine_running():
if host.isPlugin or host.isRemote or host.is_engine_running():
return

host.set_engine_option(ENGINE_OPTION_PROCESS_MODE, host.nextProcessMode, "")
host.set_engine_option(ENGINE_OPTION_TRANSPORT_MODE, host.transportMode, "")
host.set_engine_option(ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT, host.showLogs, "")

# ------------------------------------------------------------------------------------------------------------
# Set Engine settings according to carla preferences. Returns selected audio driver.


+ 69
- 36
source/rest/buffers.cpp View File

@@ -51,7 +51,7 @@ const char* size_buf(const char* const buf)

// -------------------------------------------------------------------------------------------------------------------

const char* str_buf_bool(const uint value)
const char* str_buf_bool(const bool value)
{
strBuf[0] = value ? '1' : '0';
strBuf[1] = '\0';
@@ -69,7 +69,7 @@ const char* str_buf_float(const double value)

const char* str_buf_float_array(const double* const values, const char sep)
{
size_t bytesRead = 0;
std::size_t bytesRead = 0;
char tmpBuf[32];

for (int i=0; carla_isNotZero(values[i]) && bytesRead < kStrBufSize; ++i)
@@ -103,7 +103,7 @@ const char* str_buf_string(const char* const string)

const char* str_buf_string_array(const char* const* const array)
{
size_t bytesRead = 0;
std::size_t bytesRead = 0;

for (int i=0; array[i] != nullptr && bytesRead < kStrBufSize; ++i)
{
@@ -122,6 +122,43 @@ const char* str_buf_string_array(const char* const* const array)
return strBuf;
}

const char* str_buf_string_quoted(const char* const string)
{
const std::size_t size = std::strlen(string);
char* strBufPtr = strBuf;

*strBufPtr++ = '"';

for (std::size_t i=0, bytesWritten=0; i < size && bytesWritten < kStrBufSize-1; ++i)
{
switch (string[i])
{
case '"':
case '\\':
*strBufPtr++ = '\\';
++bytesWritten;
break;
case '\n':
*strBufPtr++ = '\\';
*strBufPtr++ = 'n';;
bytesWritten += 2;
continue;
case '\f':
*strBufPtr++ = '\\';
*strBufPtr++ = 'f';;
bytesWritten += 2;
continue;
}

*strBufPtr++ = string[i];
++bytesWritten;
}

*strBufPtr++ = '"';
*strBufPtr++ = '\0';
return strBuf;
}

// -------------------------------------------------------------------------------------------------------------------

const char* str_buf_int(const int value)
@@ -131,6 +168,13 @@ const char* str_buf_int(const int value)
return strBuf;
}

const char* str_buf_int64(const int64_t value)
{
std::snprintf(strBuf, kStrBufSize, P_INT64, value);
strBuf[kStrBufSize] = '\0';
return strBuf;
}

const char* str_buf_uint(const uint value)
{
std::snprintf(strBuf, kStrBufSize, "%u", value);
@@ -147,7 +191,7 @@ const char* str_buf_uint64(const uint64_t value)

const char* str_buf_uint_array(const uint* const values, const char sep)
{
size_t bytesRead = 0;
std::size_t bytesRead = 0;
char tmpBuf[32];

for (int i=0; values[i] != 0 && bytesRead < kStrBufSize; ++i)
@@ -178,11 +222,8 @@ char* json_buf_start()
return jsonBuf + 1;
}

template <typename T, typename Fn>
char* json_buf_add(char* jsonBufPtr, const char* const key, const T value, const Fn fn)
char* json_buf_add(char* jsonBufPtr, const char* const key, const char* const valueBuf)
{
const char* const valueBuf = fn(value);

if (jsonBufPtr != jsonBuf+1)
*jsonBufPtr++ = ',';

@@ -201,28 +242,15 @@ char* json_buf_add(char* jsonBufPtr, const char* const key, const T value, const
}

template <typename T, typename Fn>
char* json_buf_add_array(char* jsonBufPtr, const char* const key, const T value, const Fn fn)
char* json_buf_add_fn(char* jsonBufPtr, const char* const key, const T value, const Fn fn)
{
const char* const valueBuf = fn(value, ',');

if (jsonBufPtr != jsonBuf+1)
*jsonBufPtr++ = ',';

*jsonBufPtr++ = '"';

std::strcpy(jsonBufPtr, key);
jsonBufPtr += std::strlen(key);

*jsonBufPtr++ = '"';
*jsonBufPtr++ = ':';
*jsonBufPtr++ = '[';

std::strcpy(jsonBufPtr, valueBuf);
jsonBufPtr += std::strlen(valueBuf);

*jsonBufPtr++ = ']';
return json_buf_add(jsonBufPtr, key, fn(value));
}

return jsonBufPtr;
template <typename T, typename Fn>
char* json_buf_add_fn_array(char* jsonBufPtr, const char* const key, const T value, const Fn fn)
{
return json_buf_add(jsonBufPtr, key, fn(value, ','));
}

// -------------------------------------------------------------------------------------------------------------------
@@ -231,42 +259,47 @@ char* json_buf_add_bool(char* jsonBufPtr, const char* const key, const bool valu
{
static const char* const kTrue = "true";
static const char* const kFalse = "false";
return json_buf_add(jsonBufPtr, key, value ? kTrue : kFalse, str_buf_string);
return json_buf_add_fn(jsonBufPtr, key, value ? kTrue : kFalse, str_buf_string);
}

char* json_buf_add_float(char* jsonBufPtr, const char* const key, const double value)
{
return json_buf_add(jsonBufPtr, key, value, str_buf_float);
return json_buf_add_fn(jsonBufPtr, key, value, str_buf_float);
}

char* json_buf_add_float_array(char* jsonBufPtr, const char* const key, const double* const values)
{
return json_buf_add_array(jsonBufPtr, key, values, str_buf_float_array);
return json_buf_add_fn_array(jsonBufPtr, key, values, str_buf_float_array);
}

char* json_buf_add_string(char* jsonBufPtr, const char* const key, const char* const value)
{
return json_buf_add(jsonBufPtr, key, value, str_buf_string);
return json_buf_add_fn(jsonBufPtr, key, value, str_buf_string_quoted);
}

char* json_buf_add_int(char* jsonBufPtr, const char* const key, const int value)
{
return json_buf_add(jsonBufPtr, key, value, str_buf_int);
return json_buf_add_fn(jsonBufPtr, key, value, str_buf_int);
}

char* json_buf_add_int64(char* jsonBufPtr, const char* const key, const int64_t value)
{
return json_buf_add_fn(jsonBufPtr, key, value, str_buf_int64);
}

char* json_buf_add_uint(char* jsonBufPtr, const char* const key, const uint value)
{
return json_buf_add(jsonBufPtr, key, value, str_buf_uint);
return json_buf_add_fn(jsonBufPtr, key, value, str_buf_uint);
}

char* json_buf_add_uint_array(char* jsonBufPtr, const char* const key, const uint* const values)
{
return json_buf_add_array(jsonBufPtr, key, values, str_buf_uint_array);
return json_buf_add_fn_array(jsonBufPtr, key, values, str_buf_uint_array);
}

char* json_buf_add_uint64(char* jsonBufPtr, const char* const key, const uint64_t value)
{
return json_buf_add(jsonBufPtr, key, value, str_buf_uint64);
return json_buf_add_fn(jsonBufPtr, key, value, str_buf_uint64);
}

const char* json_buf_end(char* jsonBufPtr)


+ 3
- 0
source/rest/buffers.hpp View File

@@ -35,7 +35,9 @@ const char* str_buf_float(const double value);
const char* str_buf_float_array(const double* const values, const char sep = '\n');
const char* str_buf_string(const char* const string);
const char* str_buf_string_array(const char* const* const array);
const char* str_buf_string_quoted(const char* const string);
const char* str_buf_int(const int value);
const char* str_buf_int64(const int64_t value);
const char* str_buf_uint(const uint value);
const char* str_buf_uint64(const uint64_t value);
const char* str_buf_uint_array(const uint* const values, const char sep = '\n');
@@ -47,6 +49,7 @@ char* json_buf_add_float(char* jsonBufPtr, const char* const key, const double v
char* json_buf_add_float_array(char* jsonBufPtr, const char* const key, const double* const values);
char* json_buf_add_string(char* jsonBufPtr, const char* const key, const char* const value);
char* json_buf_add_int(char* jsonBufPtr, const char* const key, const int value);
char* json_buf_add_int64(char* jsonBufPtr, const char* const key, const int64_t value);
char* json_buf_add_uint(char* jsonBufPtr, const char* const key, const uint value);
char* json_buf_add_uint64(char* jsonBufPtr, const char* const key, const uint64_t value);
char* json_buf_add_uint_array(char* jsonBufPtr, const char* const key, const uint* const values);


+ 971
- 94
source/rest/carla-host.cpp
File diff suppressed because it is too large
View File


+ 4
- 4
source/rest/carla-utils.cpp View File

@@ -43,10 +43,10 @@ void handle_carla_get_cached_plugin_count(const std::shared_ptr<Session> session
{
const std::shared_ptr<const Request> request = session->get_request();

const int ptype = std::atoi(request->get_path_parameter("ptype").c_str());
const int ptype = std::atoi(request->get_query_parameter("ptype").c_str());
CARLA_SAFE_ASSERT_RETURN(ptype >= PLUGIN_NONE && ptype <= PLUGIN_JACK,)

const std::string pluginPath = request->get_path_parameter("pluginPath");
const std::string pluginPath = request->get_query_parameter("pluginPath");

const char* const buf = str_buf_uint(carla_get_cached_plugin_count(static_cast<PluginType>(ptype),
pluginPath.c_str()));
@@ -57,10 +57,10 @@ void handle_carla_get_cached_plugin_info(const std::shared_ptr<Session> session)
{
const std::shared_ptr<const Request> request = session->get_request();

const int ptype = std::atoi(request->get_path_parameter("ptype").c_str());
const int ptype = std::atoi(request->get_query_parameter("ptype").c_str());
CARLA_SAFE_ASSERT_RETURN(ptype >= PLUGIN_NONE && ptype <= PLUGIN_JACK,)

const int index = std::atoi(request->get_path_parameter("index").c_str());
const int index = std::atoi(request->get_query_parameter("index").c_str());
CARLA_SAFE_ASSERT_RETURN(index >= 0 /*&& index < INT_MAX*/,)

const CarlaCachedPluginInfo* const info = carla_get_cached_plugin_info(static_cast<PluginType>(ptype),


+ 98
- 14
source/rest/rest-server.cpp View File

@@ -63,6 +63,14 @@ static void register_server_side_handler(const std::shared_ptr<Session> session)

static void event_stream_handler(void)
{
static bool firstInit = true;

if (firstInit)
{
firstInit = false;
carla_stdout("Carla REST-API Server started");
}

gSessions.erase(
std::remove_if(gSessions.begin(), gSessions.end(),
[](const std::shared_ptr<Session> &a) {
@@ -81,7 +89,7 @@ static void event_stream_handler(void)

for (auto message : messages)
{
std::puts(message);
// std::puts(message);

for (auto session : gSessions)
session->yield(OK, message);
@@ -116,45 +124,121 @@ int main(int, const char**)

// carla-host
make_resource(service, "/get_engine_driver_count", handle_carla_get_engine_driver_count);
make_resource(service, "/get_engine_driver_name/{index: .*}", handle_carla_get_engine_driver_name);
make_resource(service, "/get_engine_driver_device_names/{index: .*}", handle_carla_get_engine_driver_device_names);
make_resource(service, "/get_engine_driver_device_info/{index: .*}/{name: .*}", handle_carla_get_engine_driver_device_info);
make_resource(service, "/get_engine_driver_name", handle_carla_get_engine_driver_name);
make_resource(service, "/get_engine_driver_device_names", handle_carla_get_engine_driver_device_names);
make_resource(service, "/get_engine_driver_device_info", handle_carla_get_engine_driver_device_info);

make_resource(service, "/engine_init/{driverName: .*}/{clientName: .*}", handle_carla_engine_init);
make_resource(service, "/engine_init", handle_carla_engine_init);
make_resource(service, "/engine_close", handle_carla_engine_close);
make_resource(service, "/is_engine_running", handle_carla_is_engine_running);
make_resource(service, "/set_engine_about_to_close", handle_carla_set_engine_about_to_close);

// project
make_resource(service, "/set_engine_option", handle_carla_set_engine_option);
make_resource(service, "/load_file", handle_carla_load_file);
make_resource(service, "/load_project", handle_carla_load_project);
make_resource(service, "/save_project", handle_carla_save_project);

// patchbay
make_resource(service, "/patchbay_connect", handle_carla_patchbay_connect);
make_resource(service, "/patchbay_disconnect", handle_carla_patchbay_disconnect);
make_resource(service, "/patchbay_refresh", handle_carla_patchbay_refresh);

make_resource(service, "/transport_play", handle_carla_transport_play);
make_resource(service, "/transport_pause", handle_carla_transport_pause);
make_resource(service, "/transport_bpm/{bpm: .*}", handle_carla_transport_bpm);
make_resource(service, "/transport_relocate/{frame: .*}", handle_carla_transport_relocate);
make_resource(service, "/transport_bpm", handle_carla_transport_bpm);
make_resource(service, "/transport_relocate", handle_carla_transport_relocate);
make_resource(service, "/get_current_transport_frame", handle_carla_get_current_transport_frame);
make_resource(service, "/get_transport_info", handle_carla_get_transport_info);

// ...
make_resource(service, "/get_current_plugin_count", handle_carla_get_current_plugin_count);
make_resource(service, "/get_max_plugin_number", handle_carla_get_max_plugin_number);
make_resource(service, "/add_plugin", handle_carla_add_plugin);
make_resource(service, "/remove_plugin", handle_carla_remove_plugin);
make_resource(service, "/remove_all_plugins", handle_carla_remove_all_plugins);

make_resource(service, "/rename_plugin", handle_carla_rename_plugin);
make_resource(service, "/clone_plugin", handle_carla_clone_plugin);
make_resource(service, "/replace_plugin", handle_carla_replace_plugin);
make_resource(service, "/switch_plugins", handle_carla_switch_plugins);

make_resource(service, "/load_plugin_state", handle_carla_load_plugin_state);
make_resource(service, "/save_plugin_state", handle_carla_save_plugin_state);
make_resource(service, "/export_plugin_lv2", handle_carla_export_plugin_lv2);

make_resource(service, "/get_plugin_info", handle_carla_get_plugin_info);
make_resource(service, "/get_audio_port_count_info", handle_carla_get_audio_port_count_info);
make_resource(service, "/get_midi_port_count_info", handle_carla_get_midi_port_count_info);
make_resource(service, "/get_parameter_count_info", handle_carla_get_parameter_count_info);
make_resource(service, "/get_parameter_info", handle_carla_get_parameter_info);
make_resource(service, "/get_parameter_scalepoint_info", handle_carla_get_parameter_scalepoint_info);

make_resource(service, "/get_parameter_data", handle_carla_get_parameter_data);
make_resource(service, "/get_parameter_ranges", handle_carla_get_parameter_ranges);
make_resource(service, "/get_midi_program_data", handle_carla_get_midi_program_data);
make_resource(service, "/get_custom_data", handle_carla_get_custom_data);
make_resource(service, "/get_chunk_data", handle_carla_get_chunk_data);

make_resource(service, "/get_parameter_count", handle_carla_get_parameter_count);
make_resource(service, "/get_program_count", handle_carla_get_program_count);
make_resource(service, "/get_midi_program_count", handle_carla_get_midi_program_count);
make_resource(service, "/get_custom_data_count", handle_carla_get_custom_data_count);

make_resource(service, "/get_parameter_text", handle_carla_get_parameter_text);
make_resource(service, "/get_program_name", handle_carla_get_program_name);
make_resource(service, "/get_midi_program_name", handle_carla_get_midi_program_name);
make_resource(service, "/get_real_plugin_name", handle_carla_get_real_plugin_name);

make_resource(service, "/get_current_program_index", handle_carla_get_current_program_index);
make_resource(service, "/get_current_midi_program_index", handle_carla_get_current_midi_program_index);

make_resource(service, "/get_default_parameter_value", handle_carla_get_default_parameter_value);
make_resource(service, "/get_current_parameter_value", handle_carla_get_current_parameter_value);
make_resource(service, "/get_internal_parameter_value", handle_carla_get_internal_parameter_value);
make_resource(service, "/get_input_peak_value", handle_carla_get_input_peak_value);
make_resource(service, "/get_output_peak_value", handle_carla_get_output_peak_value);

make_resource(service, "/set_active", handle_carla_set_active);
make_resource(service, "/set_drywet", handle_carla_set_drywet);
make_resource(service, "/set_volume", handle_carla_set_volume);
make_resource(service, "/set_balance_left", handle_carla_set_balance_left);
make_resource(service, "/set_balance_right", handle_carla_set_balance_right);
make_resource(service, "/set_panning", handle_carla_set_panning);
make_resource(service, "/set_ctrl_channel", handle_carla_set_ctrl_channel);
make_resource(service, "/set_option", handle_carla_set_option);

make_resource(service, "/set_parameter_value", handle_carla_set_parameter_value);
make_resource(service, "/set_parameter_midi_channel", handle_carla_set_parameter_midi_channel);
make_resource(service, "/set_parameter_midi_cc", handle_carla_set_parameter_midi_cc);
make_resource(service, "/set_program", handle_carla_set_program);
make_resource(service, "/set_midi_program", handle_carla_set_midi_program);
make_resource(service, "/set_custom_data", handle_carla_set_custom_data);
make_resource(service, "/set_chunk_data", handle_carla_set_chunk_data);

make_resource(service, "/prepare_for_save", handle_carla_prepare_for_save);
make_resource(service, "/reset_parameters", handle_carla_reset_parameters);
make_resource(service, "/randomize_parameters", handle_carla_randomize_parameters);
make_resource(service, "/send_midi_note", handle_carla_send_midi_note);

make_resource(service, "/get_buffer_size", handle_carla_get_buffer_size);
make_resource(service, "/get_sample_rate", handle_carla_get_sample_rate);
make_resource(service, "/get_last_error", handle_carla_get_last_error);
make_resource(service, "/get_host_osc_url_tcp", handle_carla_get_host_osc_url_tcp);
make_resource(service, "/get_host_osc_url_udp", handle_carla_get_host_osc_url_udp);

// carla-utils
make_resource(service, "/get_complete_license_text", handle_carla_get_complete_license_text);
make_resource(service, "/get_supported_file_extensions", handle_carla_get_supported_file_extensions);
make_resource(service, "/get_supported_features", handle_carla_get_supported_features);
make_resource(service, "/get_cached_plugin_count/{ptype: .*}/{pluginPath: .*}", handle_carla_get_cached_plugin_count);
make_resource(service, "/get_cached_plugin_info/{ptype: .*}/{index: .*}", handle_carla_get_cached_plugin_info);
make_resource(service, "/get_cached_plugin_count", handle_carla_get_cached_plugin_count);
make_resource(service, "/get_cached_plugin_info", handle_carla_get_cached_plugin_info);

// schedule events
service.schedule(engine_idle_handler, std::chrono::milliseconds(33)); // ~30Hz
service.schedule(engine_idle_handler); // FIXME, crashes on fast times, but we need ~30Hz for OSC..
service.schedule(event_stream_handler, std::chrono::milliseconds(500));

std::shared_ptr<Settings> settings = std::make_shared<Settings>();
settings->set_port(2228);
settings->set_default_header("Connection", "close");

carla_stdout("Carla REST-API Server started");
service.start(settings);
return 0;
}


Loading…
Cancel
Save