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.

152 lines
5.6KB

  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 "common.hpp"
  23. #include "carla-host.cpp"
  24. #include "carla-utils.cpp"
  25. #include "CarlaMutex.hpp"
  26. #include "CarlaStringList.hpp"
  27. // -------------------------------------------------------------------------------------------------------------------
  28. std::vector<std::shared_ptr<Session>> gSessions;
  29. CarlaStringList gSessionMessages;
  30. CarlaMutex gSessionMessagesMutex;
  31. // -------------------------------------------------------------------------------------------------------------------
  32. void send_server_side_message(const char* const message)
  33. {
  34. const CarlaMutexLocker cml(gSessionMessagesMutex);
  35. gSessionMessages.append(message);
  36. }
  37. // -------------------------------------------------------------------------------------------------------------------
  38. static void register_server_side_handler(const std::shared_ptr<Session> session)
  39. {
  40. const auto headers = std::multimap<std::string, std::string> {
  41. { "Connection", "keep-alive" },
  42. { "Cache-Control", "no-cache" },
  43. { "Content-Type", "text/event-stream" },
  44. { "Access-Control-Allow-Origin", "*" } //Only required for demo purposes.
  45. };
  46. session->yield(OK, headers, [](const std::shared_ptr<Session> rsession) {
  47. gSessions.push_back(rsession);
  48. });
  49. }
  50. static void event_stream_handler(void)
  51. {
  52. gSessions.erase(
  53. std::remove_if(gSessions.begin(), gSessions.end(),
  54. [](const std::shared_ptr<Session> &a) {
  55. return a->is_closed();
  56. }),
  57. gSessions.end());
  58. CarlaStringList messages;
  59. {
  60. const CarlaMutexLocker cml(gSessionMessagesMutex);
  61. if (gSessionMessages.count() > 0)
  62. gSessionMessages.moveTo(messages);
  63. }
  64. for (auto message : messages)
  65. {
  66. std::puts(message);
  67. for (auto session : gSessions)
  68. session->yield(OK, message);
  69. }
  70. }
  71. // -------------------------------------------------------------------------------------------------------------------
  72. static void make_resource(Service& service,
  73. const char* const path,
  74. const std::function<void (const std::shared_ptr<Session>)>& callback)
  75. {
  76. std::shared_ptr<Resource> resource = std::make_shared<Resource>();
  77. resource->set_path(path);
  78. resource->set_method_handler("GET", callback);
  79. service.publish(resource);
  80. }
  81. // -------------------------------------------------------------------------------------------------------------------
  82. int main(int, const char**)
  83. {
  84. Service service;
  85. // server-side messages
  86. {
  87. std::shared_ptr<Resource> resource = std::make_shared<Resource>();
  88. resource->set_path("/stream");
  89. resource->set_method_handler("GET", register_server_side_handler);
  90. service.publish(resource);
  91. }
  92. // carla-host
  93. make_resource(service, "/get_engine_driver_count", handle_carla_get_engine_driver_count);
  94. make_resource(service, "/get_engine_driver_name/{index: .*}", handle_carla_get_engine_driver_name);
  95. make_resource(service, "/get_engine_driver_device_names/{index: .*}", handle_carla_get_engine_driver_device_names);
  96. make_resource(service, "/get_engine_driver_device_info/{index: .*}/{name: .*}", handle_carla_get_engine_driver_device_info);
  97. make_resource(service, "/engine_init/{driverName: .*}/{clientName: .*}", handle_carla_engine_init);
  98. make_resource(service, "/engine_close", handle_carla_engine_close);
  99. make_resource(service, "/is_engine_running", handle_carla_is_engine_running);
  100. make_resource(service, "/set_engine_about_to_close", handle_carla_set_engine_about_to_close);
  101. // ...
  102. make_resource(service, "/get_last_error", handle_carla_get_last_error);
  103. // carla-utils
  104. make_resource(service, "/get_complete_license_text", handle_carla_get_complete_license_text);
  105. make_resource(service, "/get_supported_file_extensions", handle_carla_get_supported_file_extensions);
  106. make_resource(service, "/get_supported_features", handle_carla_get_supported_features);
  107. make_resource(service, "/get_cached_plugin_count/{ptype: .*}/{pluginPath: .*}", handle_carla_get_cached_plugin_count);
  108. make_resource(service, "/get_cached_plugin_info/{ptype: .*}/{index: .*}", handle_carla_get_cached_plugin_info);
  109. // schedule events
  110. service.schedule(engine_idle_handler, std::chrono::milliseconds(33)); // ~30Hz
  111. service.schedule(event_stream_handler, std::chrono::milliseconds(500));
  112. std::shared_ptr<Settings> settings = std::make_shared<Settings>();
  113. settings->set_port(2228);
  114. settings->set_default_header("Connection", "close");
  115. carla_stdout("Carla REST-API Server started");
  116. service.start(settings);
  117. return 0;
  118. }
  119. // -------------------------------------------------------------------------------------------------------------------