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.

324 lines
8.1KB

  1. /*
  2. * Carla Native Plugin API (JACK Compatibility header)
  3. * Copyright (C) 2015 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. #ifndef CARLA_NATIVE_JACK_H_INCLUDED
  18. #define CARLA_NATIVE_JACK_H_INCLUDED
  19. #include "CarlaNative.h"
  20. #include <pthread.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #ifdef __cplusplus
  24. extern "C" {
  25. #endif
  26. /* ------------------------------------------------------------------------------------------------------------
  27. * Macros */
  28. #define JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio"
  29. #define JACK_DEFAULT_MIDI_TYPE "8 bit raw midi"
  30. /* ------------------------------------------------------------------------------------------------------------
  31. * Basic types */
  32. typedef float jack_default_audio_sample_t;
  33. typedef uint8_t jack_midi_data_t;
  34. typedef uint32_t jack_nframes_t;
  35. typedef void (*jack_shutdown_callback)(void* ptr);
  36. typedef int (*jack_process_callback)(jack_nframes_t nframes, void* ptr);
  37. /*
  38. * Helper struct for midi events.
  39. */
  40. typedef struct {
  41. uint32_t count;
  42. NativeMidiEvent* events;
  43. } NativeMidiEventsBuffer;
  44. /* ------------------------------------------------------------------------------------------------------------
  45. * Enums */
  46. enum JackPortFlags {
  47. JackPortIsInput = 0x01,
  48. JackPortIsOutput = 0x02,
  49. JackPortIsPhysical = 0x04,
  50. JackPortCanMonitor = 0x08,
  51. JackPortIsTerminal = 0x10
  52. };
  53. enum JackOptions {
  54. JackNullOption = 0x00,
  55. JackNoStartServer = 0x01,
  56. JackUseExactName = 0x02,
  57. JackServerName = 0x04,
  58. JackLoadName = 0x08,
  59. JackLoadInit = 0x10,
  60. JackSessionID = 0x20
  61. };
  62. enum JackStatus {
  63. JackFailure = 0x0001,
  64. JackInvalidOption = 0x0002,
  65. JackNameNotUnique = 0x0004,
  66. JackServerStarted = 0x0008,
  67. JackServerFailed = 0x0010,
  68. JackServerError = 0x0020,
  69. JackNoSuchClient = 0x0040,
  70. JackLoadFailure = 0x0080,
  71. JackInitFailure = 0x0100,
  72. JackShmFailure = 0x0200,
  73. JackVersionError = 0x0400,
  74. JackBackendError = 0x0800,
  75. JackClientZombie = 0x1000
  76. };
  77. typedef enum JackOptions jack_options_t;
  78. typedef enum JackStatus jack_status_t;
  79. /* ------------------------------------------------------------------------------------------------------------
  80. * Structs */
  81. typedef struct {
  82. bool registered;
  83. bool isAudio;
  84. uint flags;
  85. union {
  86. void* audio;
  87. NativeMidiEventsBuffer midi;
  88. } buffer;
  89. } jack_port_t;
  90. typedef struct {
  91. // current state
  92. bool active;
  93. jack_nframes_t bufferSize;
  94. jack_nframes_t sampleRate;
  95. // callbacks
  96. jack_process_callback processCallback;
  97. void* processPtr;
  98. // ports
  99. jack_port_t portsAudioIn [16];
  100. jack_port_t portsAudioOut[16];
  101. jack_port_t portsMidiIn [16];
  102. jack_port_t portsMidiOut [16];
  103. } jack_client_t;
  104. typedef struct {
  105. uint32_t time;
  106. uint32_t size;
  107. uint8_t* buffer;
  108. } jack_midi_event_t;
  109. /* ------------------------------------------------------------------------------------------------------------
  110. * Client functions */
  111. /*
  112. * NOTE: This function purposefully returns NULL, as we *do not* want global variables.
  113. * The client pointer is passed into the plugin code directly.
  114. */
  115. static inline
  116. jack_client_t* jack_client_open(const char* clientname, jack_options_t options, jack_status_t* status, ...)
  117. {
  118. if (status != NULL)
  119. *status = JackFailure;
  120. return NULL;
  121. // unused
  122. (void)clientname;
  123. (void)options;
  124. }
  125. static inline
  126. int jack_client_close(jack_client_t* client)
  127. {
  128. // keep bufsize and srate
  129. const jack_nframes_t bufferSize = client->bufferSize;
  130. const jack_nframes_t sampleRate = client->sampleRate;
  131. memset(client, 0, sizeof(jack_client_t));
  132. client->bufferSize = bufferSize;
  133. client->sampleRate = sampleRate;
  134. return 0;
  135. }
  136. /* ------------------------------------------------------------------------------------------------------------
  137. * Callback functions */
  138. static inline
  139. int jack_on_shutdown(jack_client_t* client, jack_shutdown_callback callback, void* ptr)
  140. {
  141. return 0;
  142. // unused
  143. (void)client;
  144. (void)callback;
  145. (void)ptr;
  146. }
  147. static inline
  148. int jack_set_process_callback(jack_client_t* client, jack_process_callback callback, void* ptr)
  149. {
  150. client->processCallback = callback;
  151. client->processPtr = ptr;
  152. return 0;
  153. }
  154. /* ------------------------------------------------------------------------------------------------------------
  155. * Port functions */
  156. static inline
  157. jack_port_t* jack_port_register(jack_client_t* client, const char* name, const char* type, ulong flags, ulong buffersize)
  158. {
  159. const bool isAudio = strcmp(type, JACK_DEFAULT_AUDIO_TYPE) == 0;
  160. const bool isMIDI = strcmp(type, JACK_DEFAULT_MIDI_TYPE ) == 0;
  161. if (! (isAudio || isMIDI))
  162. return NULL;
  163. jack_port_t* ports;
  164. if (isAudio)
  165. ports = (flags & JackPortIsInput) ? client->portsAudioIn : client->portsAudioOut;
  166. else
  167. ports = (flags & JackPortIsInput) ? client->portsMidiIn : client->portsMidiOut;
  168. for (int i=0; i<16; ++i)
  169. {
  170. jack_port_t* const port = &ports[i];
  171. if (port->registered)
  172. continue;
  173. memset(port, 0, sizeof(jack_port_t));
  174. port->registered = true;
  175. port->isAudio = isAudio;
  176. port->flags = flags;
  177. return port;
  178. }
  179. return NULL;
  180. // unused
  181. (void)name;
  182. (void)type;
  183. (void)buffersize;
  184. }
  185. static inline
  186. int jack_port_unregister(jack_client_t* client, jack_port_t* port)
  187. {
  188. jack_port_t* const ports = (port->flags & JackPortIsInput) ? client->portsAudioIn : client->portsAudioOut;
  189. for (int i=0; i<8; ++i)
  190. {
  191. if (&ports[i] == port)
  192. {
  193. memset(port, 0, sizeof(jack_port_t));
  194. return 0;
  195. }
  196. }
  197. return 1;
  198. }
  199. static inline
  200. void* jack_port_get_buffer(jack_port_t* port, jack_nframes_t nframes)
  201. {
  202. return port->isAudio ? port->buffer.audio : &port->buffer.midi;
  203. // unused
  204. (void)nframes;
  205. }
  206. /* ------------------------------------------------------------------------------------------------------------
  207. * MIDI functions */
  208. static inline
  209. uint32_t jack_midi_get_event_count(void* port_buffer)
  210. {
  211. NativeMidiEventsBuffer* const midi_buffer = (NativeMidiEventsBuffer*)port_buffer;
  212. return midi_buffer->count;
  213. }
  214. static inline
  215. int jack_midi_event_get(jack_midi_event_t* event, void* port_buffer, uint32_t event_index)
  216. {
  217. NativeMidiEventsBuffer* const midi_buffer = (NativeMidiEventsBuffer*)port_buffer;
  218. if (midi_buffer->count == 0)
  219. return ENODATA;
  220. if (event_index >= midi_buffer->count)
  221. return 1; // FIXME
  222. NativeMidiEvent* const midiEvent = &midi_buffer->events[event_index];
  223. event->time = midiEvent->time;
  224. event->size = midiEvent->size;
  225. event->buffer = midiEvent->data;
  226. return 0;
  227. }
  228. /* ------------------------------------------------------------------------------------------------------------
  229. * [De/]Activate */
  230. static inline
  231. int jack_activate(jack_client_t* client)
  232. {
  233. client->active = true;
  234. return 0;
  235. }
  236. static inline
  237. int jack_deactivate(jack_client_t* client)
  238. {
  239. client->active = false;
  240. return 0;
  241. }
  242. /* ------------------------------------------------------------------------------------------------------------
  243. * Get data functions */
  244. static inline
  245. jack_nframes_t jack_get_buffer_size(const jack_client_t* client)
  246. {
  247. return client->bufferSize;
  248. }
  249. static inline
  250. jack_nframes_t jack_get_sample_rate(const jack_client_t* client)
  251. {
  252. return client->sampleRate;
  253. }
  254. /* ------------------------------------------------------------------------------------------------------------ */
  255. #ifdef __cplusplus
  256. } /* extern "C" */
  257. #endif
  258. #endif /* CARLA_NATIVE_JACK_H_INCLUDED */