Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
6.8KB

  1. /*
  2. * Carla REST API Server
  3. * Copyright (C) 2018 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. /* NOTE
  18. * Even though Carla is GPL, restbed if AGPL.
  19. * As such, the resulting binary will be AGPL.
  20. * Take this into consideration before deploying it to any servers.
  21. */
  22. #include "CarlaHost.h"
  23. #include "CarlaUtils.h"
  24. #include "CarlaUtils.hpp"
  25. #include <cstring>
  26. #include <restbed>
  27. // #include <memory>
  28. // #include <cstdlib>
  29. // using namespace std;
  30. using namespace restbed;
  31. #if 0
  32. void post_method_handler(const std::shared_ptr<Session> session)
  33. {
  34. const std::shared_ptr<const Request> request = session->get_request();
  35. const string body = "Hello, " + request->get_path_parameter("id");
  36. session->close(OK, body, { { "Content-Length", ::to_string( body.size( ) ) } } );
  37. }
  38. #endif
  39. CARLA_BACKEND_START_NAMESPACE
  40. enum {
  41. kStrBufSize = 1023,
  42. kJsonBufSize = 4095,
  43. kSizeBufSize = 31,
  44. };
  45. // static buffer to returned content
  46. static char strBuf[kStrBufSize+1];
  47. static char jsonBuf[kJsonBufSize+1];
  48. // static buffer to returned content size
  49. static char sizeBuf[kSizeBufSize+1];
  50. void prepare_size()
  51. {
  52. const std::size_t size = std::strlen(strBuf);
  53. std::snprintf(sizeBuf, kSizeBufSize, P_SIZE, size);
  54. sizeBuf[kSizeBufSize] = '\0';
  55. }
  56. void prepare_buffer_uint(const uint value)
  57. {
  58. std::snprintf(strBuf, kStrBufSize, "%u", value);
  59. strBuf[kStrBufSize] = '\0';
  60. }
  61. void prepare_buffer_string(const char* const string)
  62. {
  63. std::strncpy(strBuf, string, kStrBufSize);
  64. strBuf[kStrBufSize] = '\0';
  65. }
  66. void prepare_buffer_string_array(const char* const* const array)
  67. {
  68. size_t bytesRead = 0;
  69. strBuf[0] = '\0';
  70. for (int i=0; array[i] != nullptr && bytesRead < kStrBufSize; ++i)
  71. {
  72. const std::size_t size = std::strlen(array[i]);
  73. if (bytesRead + size > kStrBufSize)
  74. break;
  75. std::strncpy(strBuf+bytesRead, array[i], kStrBufSize);
  76. bytesRead += size;
  77. strBuf[bytesRead] = '\n';
  78. bytesRead += 1;
  79. }
  80. strBuf[bytesRead] = '\0';
  81. }
  82. char* prepare_buffer_json_start()
  83. {
  84. std::strcpy(jsonBuf, "{");
  85. return jsonBuf + 1;
  86. }
  87. char* prepare_buffer_json_add_uint(char* bufPtr, const char* const key, const uint value)
  88. {
  89. prepare_buffer_uint(value);
  90. if (bufPtr != jsonBuf+1)
  91. {
  92. *bufPtr = ',';
  93. bufPtr += 1;
  94. }
  95. *bufPtr++ = '"';
  96. std::strcpy(bufPtr, key);
  97. bufPtr += std::strlen(key);
  98. *bufPtr++ = '"';
  99. *bufPtr++ = ':';
  100. std::strcpy(bufPtr, strBuf);
  101. bufPtr += std::strlen(strBuf);
  102. return bufPtr;
  103. }
  104. void prepare_buffer_json_end(char* const bufPtr)
  105. {
  106. std::strcpy(bufPtr, "}");
  107. const std::size_t size = std::strlen(jsonBuf);
  108. std::snprintf(sizeBuf, kSizeBufSize, P_SIZE, size);
  109. sizeBuf[kSizeBufSize] = '\0';
  110. }
  111. void handle_carla_get_complete_license_text(const std::shared_ptr<Session> session)
  112. {
  113. prepare_buffer_string(carla_get_complete_license_text());
  114. prepare_size();
  115. session->close(OK, strBuf, { { "Content-Length", sizeBuf } } );
  116. }
  117. void handle_carla_get_supported_file_extensions(const std::shared_ptr<Session> session)
  118. {
  119. prepare_buffer_string_array(carla_get_supported_file_extensions());
  120. prepare_size();
  121. session->close(OK, strBuf, { { "Content-Length", sizeBuf } } );
  122. }
  123. void handle_carla_get_supported_features(const std::shared_ptr<Session> session)
  124. {
  125. prepare_buffer_string_array(carla_get_supported_features());
  126. prepare_size();
  127. session->close(OK, strBuf, { { "Content-Length", sizeBuf } } );
  128. }
  129. void handle_carla_get_cached_plugin_count(const std::shared_ptr<Session> session)
  130. {
  131. PluginType ptype = PLUGIN_LV2;
  132. const char* pluginPath = nullptr;
  133. prepare_buffer_uint(carla_get_cached_plugin_count(ptype, pluginPath));
  134. prepare_size();
  135. session->close(OK, strBuf, { { "Content-Length", sizeBuf } } );
  136. }
  137. void handle_carla_get_cached_plugin_info(const std::shared_ptr<Session> session)
  138. {
  139. PluginType ptype = PLUGIN_LV2;
  140. const uint index = 0;
  141. // REMOVE THIS
  142. carla_get_cached_plugin_count(ptype, nullptr);
  143. const CarlaCachedPluginInfo* const info = carla_get_cached_plugin_info(ptype, index);
  144. char* bufPtr;
  145. bufPtr = prepare_buffer_json_start();
  146. bufPtr = prepare_buffer_json_add_uint(bufPtr, "category", info->category);
  147. bufPtr = prepare_buffer_json_add_uint(bufPtr, "hints", info->hints);
  148. bufPtr = prepare_buffer_json_add_uint(bufPtr, "audioIns", info->audioIns);
  149. bufPtr = prepare_buffer_json_add_uint(bufPtr, "audioOuts", info->audioOuts);
  150. bufPtr = prepare_buffer_json_add_uint(bufPtr, "midiIns", info->midiIns);
  151. bufPtr = prepare_buffer_json_add_uint(bufPtr, "midiOuts", info->midiOuts);
  152. bufPtr = prepare_buffer_json_add_uint(bufPtr, "parameterIns", info->parameterIns);
  153. bufPtr = prepare_buffer_json_add_uint(bufPtr, "parameterOuts", info->parameterOuts);
  154. // const char* name;
  155. // const char* label;
  156. // const char* maker;
  157. // const char* copyright;
  158. prepare_buffer_json_end(bufPtr);
  159. session->close(OK, jsonBuf, { { "Content-Length", sizeBuf } } );
  160. }
  161. // CARLA_EXPORT const CarlaCachedPluginInfo* carla_get_cached_plugin_info(PluginType ptype, uint index);
  162. CARLA_BACKEND_END_NAMESPACE
  163. void make_resource(Service& service,
  164. const char* const path,
  165. const std::function<void (const std::shared_ptr<Session>)>& callback)
  166. {
  167. std::shared_ptr<Resource> resource = std::make_shared<Resource>();
  168. resource->set_path(path);
  169. resource->set_method_handler("GET", callback);
  170. service.publish(resource);
  171. }
  172. int main(int, const char**)
  173. {
  174. CARLA_BACKEND_USE_NAMESPACE;
  175. Service service;
  176. make_resource(service, "/get_complete_license_text", handle_carla_get_complete_license_text);
  177. make_resource(service, "/get_supported_file_extensions", handle_carla_get_supported_file_extensions);
  178. make_resource(service, "/get_supported_features", handle_carla_get_supported_features);
  179. make_resource(service, "/get_cached_plugin_count", handle_carla_get_cached_plugin_count);
  180. make_resource(service, "/get_cached_plugin_info", handle_carla_get_cached_plugin_info);
  181. std::shared_ptr<Settings> settings = std::make_shared<Settings>();
  182. settings->set_port(2228);
  183. settings->set_default_header("Connection", "close");
  184. carla_stdout("Carla REST-API Server started");
  185. service.start(settings);
  186. return 0;
  187. }