@@ -43,12 +43,39 @@ class CarlaHostQtWeb(CarlaHostQtNull): | |||
return requests.get("{}/get_engine_driver_name/{}".format(self.baseurl, index)).text | |||
def get_engine_driver_device_names(self, index): | |||
# FIXME strip should not be needed | |||
return requests.get("{}/get_engine_driver_device_names/{}".format(self.baseurl, index)).text.strip().split("\n") | |||
return requests.get("{}/get_engine_driver_device_names/{}".format(self.baseurl, 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() | |||
def engine_init(self, driverName, clientName): | |||
resp = requests.get("{}/engine_init/{}/{}".format(self.baseurl, driverName, clientName)).status_code | |||
# TESTING | |||
if self.fEngineCallback is not None: | |||
self.fEngineCallback(None, ENGINE_CALLBACK_ENGINE_STARTED, 0, self.processMode, self.transportMode, 0.0, driverName) | |||
return resp == 200 | |||
def engine_close(self): | |||
# TESTING | |||
if self.fEngineCallback is not None: | |||
self.fEngineCallback(None, ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0, "") | |||
return requests.get("{}/engine_close".format(self.baseurl)).status_code == 200 | |||
def engine_idle(self): | |||
requests.get("{}/engine_idle".format(self.baseurl)) | |||
def is_engine_running(self): | |||
return requests.get("{}/is_engine_running".format(self.baseurl)).status_code == 200 | |||
def set_engine_about_to_close(self): | |||
return requests.get("{}/set_engine_about_to_close".format(self.baseurl)).status_code == 200 | |||
def get_last_error(self): | |||
return requests.get("{}/get_last_error".format(self.baseurl)).text | |||
# --------------------------------------------------------------------------------------------------------------------- | |||
# TESTING | |||
@@ -66,9 +93,8 @@ if __name__ == '__main__': | |||
print("\t -", requests.get("{}/get_engine_driver_name/{}".format(baseurl, index)).text) | |||
print("Driver device names:") | |||
# FIXME strip should not be needed | |||
for index in range(driver_count): | |||
for name in requests.get("{}/get_engine_driver_device_names/{}".format(baseurl, index)).text.strip().split("\n"): | |||
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()) | |||
# --------------------------------------------------------------------------------------------------------------------- |
@@ -27,7 +27,7 @@ LINK_FLAGS += -L$(BINDIR) -lcarla_standalone2 -lcarla_utils -lrestbed -Wl,-rpath | |||
# ---------------------------------------------------------------------------------------------------------------------- | |||
OBJS = | |||
OBJS = $(OBJDIR)/rest-server.cpp.o $(OBJDIR)/buffers.cpp.o | |||
TARGETS = $(BINDIR)/carla-rest-server | |||
# ---------------------------------------------------------------------------------------------------------------------- | |||
@@ -44,7 +44,7 @@ debug: | |||
# ---------------------------------------------------------------------------------------------------------------------- | |||
$(BINDIR)/carla-rest-server: $(OBJDIR)/rest-server.cpp.o $(OBJDIR)/buffers.cpp.o | |||
$(BINDIR)/carla-rest-server: $(OBJS) | |||
-@mkdir -p $(BINDIR) | |||
@echo "Linking carla-rest-server" | |||
@$(CXX) $^ $(LINK_FLAGS) -o $@ | |||
@@ -16,6 +16,7 @@ | |||
*/ | |||
#include "buffers.hpp" | |||
#include "CarlaMathUtils.hpp" | |||
#include <cstdio> | |||
#include <cstring> | |||
@@ -50,6 +51,45 @@ const char* size_buf(const char* const buf) | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
const char* str_buf_bool(const uint value) | |||
{ | |||
strBuf[0] = value ? '1' : '0'; | |||
strBuf[1] = '\0'; | |||
return strBuf; | |||
} | |||
const char* str_buf_float(const double value) | |||
{ | |||
std::snprintf(strBuf, kStrBufSize, "%f", value); | |||
strBuf[kStrBufSize] = '\0'; | |||
return strBuf; | |||
} | |||
const char* str_buf_float_array(const double* const values, const char sep) | |||
{ | |||
size_t bytesRead = 0; | |||
char tmpBuf[32]; | |||
for (int i=0; carla_isNotZero(values[i]) && bytesRead < kStrBufSize; ++i) | |||
{ | |||
std::snprintf(tmpBuf, 31, "%f", values[i]); | |||
tmpBuf[31] = '\0'; | |||
const std::size_t size = std::strlen(tmpBuf); | |||
if (bytesRead + size > kStrBufSize) | |||
break; | |||
std::strncpy(strBuf+bytesRead, tmpBuf, kStrBufSize - bytesRead); | |||
bytesRead += size; | |||
strBuf[bytesRead] = sep; | |||
bytesRead += 1; | |||
} | |||
strBuf[bytesRead > 0 ? bytesRead-1 : 0] = '\0'; | |||
return strBuf; | |||
} | |||
const char* str_buf_string(const char* const string) | |||
{ | |||
std::strncpy(strBuf, string, kStrBufSize); | |||
@@ -68,13 +108,13 @@ const char* str_buf_string_array(const char* const* const array) | |||
if (bytesRead + size > kStrBufSize) | |||
break; | |||
std::strncpy(strBuf+bytesRead, array[i], kStrBufSize); | |||
std::strncpy(strBuf+bytesRead, array[i], kStrBufSize - bytesRead); | |||
bytesRead += size; | |||
strBuf[bytesRead] = '\n'; | |||
bytesRead += 1; | |||
} | |||
strBuf[bytesRead] = '\0'; | |||
strBuf[bytesRead > 0 ? bytesRead-1 : 0] = '\0'; | |||
return strBuf; | |||
} | |||
@@ -85,6 +125,31 @@ const char* str_buf_uint(const uint value) | |||
return strBuf; | |||
} | |||
const char* str_buf_uint_array(const uint* const values, const char sep) | |||
{ | |||
size_t bytesRead = 0; | |||
char tmpBuf[32]; | |||
for (int i=0; values[i] != 0 && bytesRead < kStrBufSize; ++i) | |||
{ | |||
std::snprintf(tmpBuf, 31, "%u", values[i]); | |||
tmpBuf[31] = '\0'; | |||
const std::size_t size = std::strlen(tmpBuf); | |||
if (bytesRead + size > kStrBufSize) | |||
break; | |||
std::strncpy(strBuf+bytesRead, tmpBuf, kStrBufSize - bytesRead); | |||
bytesRead += size; | |||
strBuf[bytesRead] = sep; | |||
bytesRead += 1; | |||
} | |||
strBuf[bytesRead > 0 ? bytesRead-1 : 0] = '\0'; | |||
return strBuf; | |||
} | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
char* json_buf_start() | |||
@@ -96,13 +161,32 @@ char* json_buf_start() | |||
template <typename T, typename Fn> | |||
char* json_buf_add(char* jsonBufPtr, const char* const key, const T value, const Fn fn) | |||
{ | |||
fn(value); | |||
const char* const valueBuf = fn(value); | |||
if (jsonBufPtr != jsonBuf+1) | |||
{ | |||
*jsonBufPtr = ','; | |||
jsonBufPtr += 1; | |||
} | |||
*jsonBufPtr++ = ','; | |||
*jsonBufPtr++ = '"'; | |||
std::strcpy(jsonBufPtr, key); | |||
jsonBufPtr += std::strlen(key); | |||
*jsonBufPtr++ = '"'; | |||
*jsonBufPtr++ = ':'; | |||
std::strcpy(jsonBufPtr, valueBuf); | |||
jsonBufPtr += std::strlen(valueBuf); | |||
return jsonBufPtr; | |||
} | |||
template <typename T, typename Fn> | |||
char* json_buf_add_array(char* jsonBufPtr, const char* const key, const T value, const Fn fn) | |||
{ | |||
const char* const valueBuf = fn(value, ','); | |||
if (jsonBufPtr != jsonBuf+1) | |||
*jsonBufPtr++ = ','; | |||
*jsonBufPtr++ = '"'; | |||
@@ -111,13 +195,35 @@ char* json_buf_add(char* jsonBufPtr, const char* const key, const T value, const | |||
*jsonBufPtr++ = '"'; | |||
*jsonBufPtr++ = ':'; | |||
*jsonBufPtr++ = '['; | |||
std::strcpy(jsonBufPtr, strBuf); | |||
jsonBufPtr += std::strlen(strBuf); | |||
std::strcpy(jsonBufPtr, valueBuf); | |||
jsonBufPtr += std::strlen(valueBuf); | |||
*jsonBufPtr++ = ']'; | |||
return jsonBufPtr; | |||
} | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
// typedef const char* (*str_buf_bool_type)(const bool value); | |||
// | |||
// char* json_buf_add_bool(char* jsonBufPtr, const char* const key, const bool value) | |||
// { | |||
// return json_buf_add<bool, str_buf_bool_type>(jsonBufPtr, key, value, str_buf_bool); | |||
// } | |||
char* json_buf_add_float(char* jsonBufPtr, const char* const key, const double value) | |||
{ | |||
return json_buf_add(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); | |||
} | |||
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); | |||
@@ -128,6 +234,11 @@ char* json_buf_add_uint(char* jsonBufPtr, const char* const key, const uint valu | |||
return json_buf_add(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); | |||
} | |||
const char* json_buf_end(char* jsonBufPtr) | |||
{ | |||
*jsonBufPtr++ = '}'; | |||
@@ -24,14 +24,22 @@ | |||
const char* size_buf(const char* const buf); | |||
// base types | |||
const char* str_buf_bool(const bool value); | |||
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_uint(const uint value); | |||
const char* str_buf_uint_array(const uint* const values, const char sep = '\n'); | |||
// json | |||
char* json_buf_start(); | |||
// char* json_buf_add_bool(char* jsonBufPtr, const char* const key, const bool value); | |||
char* json_buf_add_float(char* jsonBufPtr, const char* const key, const double value); | |||
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_uint(char* jsonBufPtr, const char* const key, const uint value); | |||
char* json_buf_add_uint_array(char* jsonBufPtr, const char* const key, const uint* const values); | |||
const char* json_buf_end(char* jsonBufPtr); | |||
#endif // REST_BUFFERS_HPP_INCLUDED |
@@ -63,10 +63,8 @@ void handle_carla_get_engine_driver_device_info(const std::shared_ptr<Session> s | |||
char* jsonBuf; | |||
jsonBuf = json_buf_start(); | |||
jsonBuf = json_buf_add_uint(jsonBuf, "hints", info->hints); | |||
// TODO | |||
//jsonBuf = json_buf_add_uint(jsonBuf, "bufferSizes", info->bufferSizes); | |||
//jsonBuf = json_buf_add_uint(jsonBuf, "sampleRates", info->sampleRates); | |||
jsonBuf = json_buf_add_uint_array(jsonBuf, "bufferSizes", info->bufferSizes); | |||
jsonBuf = json_buf_add_float_array(jsonBuf, "sampleRates", info->sampleRates); | |||
const char* const buf = json_buf_end(jsonBuf); | |||
session->close(OK, buf, { { "Content-Length", size_buf(buf) } } ); | |||
@@ -74,4 +72,47 @@ void handle_carla_get_engine_driver_device_info(const std::shared_ptr<Session> s | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
void handle_carla_engine_init(const std::shared_ptr<Session> session) | |||
{ | |||
const std::shared_ptr<const Request> request = session->get_request(); | |||
const std::string driverName = request->get_path_parameter("driverName"); | |||
const std::string clientName = request->get_path_parameter("clientName"); | |||
const bool resp = carla_engine_init(driverName.c_str(), clientName.c_str()); | |||
session->close(resp ? OK : BAD_REQUEST); | |||
} | |||
void handle_carla_engine_close(const std::shared_ptr<Session> session) | |||
{ | |||
const bool resp = carla_engine_close(); | |||
session->close(resp ? OK : BAD_REQUEST); | |||
} | |||
void handle_carla_engine_idle(const std::shared_ptr<Session> session) | |||
{ | |||
carla_engine_idle(); | |||
session->close(OK); | |||
} | |||
void handle_carla_is_engine_running(const std::shared_ptr<Session> session) | |||
{ | |||
const bool resp = carla_is_engine_running(); | |||
session->close(resp ? OK : BAD_REQUEST); | |||
} | |||
void handle_carla_set_engine_about_to_close(const std::shared_ptr<Session> session) | |||
{ | |||
const bool resp = carla_set_engine_about_to_close(); | |||
session->close(resp ? OK : BAD_REQUEST); | |||
} | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
void handle_carla_get_last_error(const std::shared_ptr<Session> session) | |||
{ | |||
const char* const buf = carla_get_last_error(); | |||
session->close(OK, buf, { { "Content-Length", size_buf(buf) } } ); | |||
} | |||
// ------------------------------------------------------------------------------------------------------------------- |
@@ -30,6 +30,7 @@ using restbed::Resource; | |||
using restbed::Service; | |||
using restbed::Session; | |||
using restbed::Settings; | |||
using restbed::BAD_REQUEST; | |||
using restbed::OK; | |||
CARLA_BACKEND_USE_NAMESPACE; | |||
@@ -50,6 +50,15 @@ int main(int, const char**) | |||
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, "/engine_init/{driverName: .*}/{clientName: .*}", handle_carla_engine_init); | |||
make_resource(service, "/engine_close", handle_carla_engine_close); | |||
make_resource(service, "/engine_idle", handle_carla_engine_idle); | |||
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); | |||
// ... | |||
make_resource(service, "/get_last_error", handle_carla_get_last_error); | |||
// 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); | |||