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.

220 lines
8.6KB

  1. #pragma once
  2. #include "../plugin.h"
  3. /// @page GUI
  4. ///
  5. /// This extension defines how the plugin will present its GUI.
  6. ///
  7. /// There are two approaches:
  8. /// 1. the plugin creates a window and embeds it into the host's window
  9. /// 2. the plugin creates a floating window
  10. ///
  11. /// Embedding the window gives more control to the host, and feels more integrated.
  12. /// Floating window are sometimes the only option due to technical limitations.
  13. ///
  14. /// Showing the GUI works as follow:
  15. /// 1. clap_plugin_gui->is_api_supported(), check what can work
  16. /// 2. clap_plugin_gui->create(), allocates gui resources
  17. /// 3. if the plugin window is floating
  18. /// 4. -> clap_plugin_gui->set_transient()
  19. /// 5. -> clap_plugin_gui->suggest_title()
  20. /// 6. else
  21. /// 7. -> clap_plugin_gui->set_scale()
  22. /// 8. -> clap_plugin_gui->can_resize()
  23. /// 9. -> if resizable and has known size from previous session, clap_plugin_gui->set_size()
  24. /// 10. -> else clap_plugin_gui->get_size(), gets initial size
  25. /// 11. -> clap_plugin_gui->set_parent()
  26. /// 12. clap_plugin_gui->show()
  27. /// 13. clap_plugin_gui->hide()/show() ...
  28. /// 14. clap_plugin_gui->destroy() when done with the gui
  29. ///
  30. /// Resizing the window (initiated by the plugin, if embedded):
  31. /// 1. Plugins calls clap_host_gui->request_resize()
  32. /// 2. If the host returns true the new size is accepted,
  33. /// the host doesn't have to call clap_plugin_gui->set_size().
  34. /// If the host returns false, the new size is rejected.
  35. ///
  36. /// Resizing the window (drag, if embedded)):
  37. /// 1. Only possible if clap_plugin_gui->can_resize() returns true
  38. /// 2. Mouse drag -> new_size
  39. /// 3. clap_plugin_gui->adjust_size(new_size) -> working_size
  40. /// 4. clap_plugin_gui->set_size(working_size)
  41. static CLAP_CONSTEXPR const char CLAP_EXT_GUI[] = "clap.gui";
  42. // If your windowing API is not listed here, please open an issue and we'll figure it out.
  43. // https://github.com/free-audio/clap/issues/new
  44. // uses physical size
  45. // embed using https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent
  46. static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WIN32[] = "win32";
  47. // uses logical size, don't call clap_plugin_gui->set_scale()
  48. static const CLAP_CONSTEXPR char CLAP_WINDOW_API_COCOA[] = "cocoa";
  49. // uses physical size
  50. // embed using https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html
  51. static const CLAP_CONSTEXPR char CLAP_WINDOW_API_X11[] = "x11";
  52. // uses physical size
  53. // embed is currently not supported, use floating windows
  54. static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WAYLAND[] = "wayland";
  55. #ifdef __cplusplus
  56. extern "C" {
  57. #endif
  58. typedef void *clap_hwnd;
  59. typedef void *clap_nsview;
  60. typedef unsigned long clap_xwnd;
  61. // Represent a window reference.
  62. typedef struct clap_window {
  63. const char *api; // one of CLAP_WINDOW_API_XXX
  64. union {
  65. clap_nsview cocoa;
  66. clap_xwnd x11;
  67. clap_hwnd win32;
  68. void *ptr; // for anything defined outside of clap
  69. uintptr_t uptr;
  70. };
  71. } clap_window_t;
  72. // Information to improve window resizing when initiated by the host or window manager.
  73. typedef struct clap_gui_resize_hints {
  74. bool can_resize_horizontally;
  75. bool can_resize_vertically;
  76. // only if can resize horizontally and vertically
  77. bool preserve_aspect_ratio;
  78. uint32_t aspect_ratio_width;
  79. uint32_t aspect_ratio_height;
  80. } clap_gui_resize_hints_t;
  81. // Size (width, height) is in pixels; the corresponding windowing system extension is
  82. // responsible for defining if it is physical pixels or logical pixels.
  83. typedef struct clap_plugin_gui {
  84. // Returns true if the requested gui api is supported
  85. // [main-thread]
  86. bool (CLAP_ABI *is_api_supported)(const clap_plugin_t *plugin, const char *api, bool is_floating);
  87. // Returns true if the plugin has a preferred api.
  88. // The host has no obligation to honor the plugin preferrence, this is just a hint.
  89. // [main-thread]
  90. bool (CLAP_ABI *get_preferred_api)(const clap_plugin_t *plugin, const char **api, bool *is_floating);
  91. // Create and allocate all resources necessary for the gui.
  92. //
  93. // If is_floating is true, then the window will not be managed by the host. The plugin
  94. // can set its window to stays above the parent window, see set_transient().
  95. // api may be null or blank for floating window.
  96. //
  97. // If is_floating is false, then the plugin has to embbed its window into the parent window, see
  98. // set_parent().
  99. //
  100. // After this call, the GUI may not be visible yet; don't forget to call show().
  101. // [main-thread]
  102. bool (CLAP_ABI *create)(const clap_plugin_t *plugin, const char *api, bool is_floating);
  103. // Free all resources associated with the gui.
  104. // [main-thread]
  105. void (CLAP_ABI *destroy)(const clap_plugin_t *plugin);
  106. // Set the absolute GUI scaling factor, and override any OS info.
  107. // Should not be used if the windowing api relies upon logical pixels.
  108. //
  109. // If the plugin prefers to work out the scaling factor itself by querying the OS directly,
  110. // then ignore the call.
  111. //
  112. // Returns true if the scaling could be applied
  113. // Returns false if the call was ignored, or the scaling could not be applied.
  114. // [main-thread]
  115. bool (CLAP_ABI *set_scale)(const clap_plugin_t *plugin, double scale);
  116. // Get the current size of the plugin UI.
  117. // clap_plugin_gui->create() must have been called prior to asking the size.
  118. // [main-thread]
  119. bool (CLAP_ABI *get_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height);
  120. // Returns true if the window is resizeable (mouse drag).
  121. // Only for embedded windows.
  122. // [main-thread]
  123. bool (CLAP_ABI *can_resize)(const clap_plugin_t *plugin);
  124. // Returns true if the plugin can provide hints on how to resize the window.
  125. // [main-thread]
  126. bool (CLAP_ABI *get_resize_hints)(const clap_plugin_t *plugin, clap_gui_resize_hints_t *hints);
  127. // If the plugin gui is resizable, then the plugin will calculate the closest
  128. // usable size which fits in the given size.
  129. // This method does not change the size.
  130. //
  131. // Only for embedded windows.
  132. // [main-thread]
  133. bool (CLAP_ABI *adjust_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height);
  134. // Sets the window size. Only for embedded windows.
  135. // [main-thread]
  136. bool (CLAP_ABI *set_size)(const clap_plugin_t *plugin, uint32_t width, uint32_t height);
  137. // Embbeds the plugin window into the given window.
  138. // [main-thread & !floating]
  139. bool (CLAP_ABI *set_parent)(const clap_plugin_t *plugin, const clap_window_t *window);
  140. // Set the plugin floating window to stay above the given window.
  141. // [main-thread & floating]
  142. bool (CLAP_ABI *set_transient)(const clap_plugin_t *plugin, const clap_window_t *window);
  143. // Suggests a window title. Only for floating windows.
  144. // [main-thread & floating]
  145. void (CLAP_ABI *suggest_title)(const clap_plugin_t *plugin, const char *title);
  146. // Show the window.
  147. // [main-thread]
  148. bool (CLAP_ABI *show)(const clap_plugin_t *plugin);
  149. // Hide the window, this method does not free the resources, it just hides
  150. // the window content. Yet it may be a good idea to stop painting timers.
  151. // [main-thread]
  152. bool (CLAP_ABI *hide)(const clap_plugin_t *plugin);
  153. } clap_plugin_gui_t;
  154. typedef struct clap_host_gui {
  155. // The host should call get_resize_hints() again.
  156. // [thread-safe]
  157. void (CLAP_ABI *resize_hints_changed)(const clap_host_t *host);
  158. /* Request the host to resize the client area to width, height.
  159. * Return true if the new size is accepted, false otherwise.
  160. * The host doesn't have to call set_size().
  161. *
  162. * Note: if not called from the main thread, then a return value simply means that the host
  163. * acknowledged the request and will process it asynchronously. If the request then can't be
  164. * satisfied then the host will call set_size() to revert the operation.
  165. *
  166. * [thread-safe] */
  167. bool (CLAP_ABI *request_resize)(const clap_host_t *host, uint32_t width, uint32_t height);
  168. /* Request the host to show the plugin gui.
  169. * Return true on success, false otherwise.
  170. * [thread-safe] */
  171. bool (CLAP_ABI *request_show)(const clap_host_t *host);
  172. /* Request the host to hide the plugin gui.
  173. * Return true on success, false otherwise.
  174. * [thread-safe] */
  175. bool (CLAP_ABI *request_hide)(const clap_host_t *host);
  176. // The floating window has been closed, or the connection to the gui has been lost.
  177. //
  178. // If was_destroyed is true, then the host must call clap_plugin_gui->destroy() to acknowledge
  179. // the gui destruction.
  180. // [thread-safe]
  181. void (CLAP_ABI *closed)(const clap_host_t *host, bool was_destroyed);
  182. } clap_host_gui_t;
  183. #ifdef __cplusplus
  184. }
  185. #endif