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.

336 lines
8.5KB

  1. /*
  2. * Carla JACK API for external applications
  3. * Copyright (C) 2016-2022 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_LIBJACK_HPP_INCLUDED
  18. #define CARLA_LIBJACK_HPP_INCLUDED
  19. // need to include this first
  20. #include "CarlaDefines.h"
  21. // now define as bridge
  22. #define BUILD_BRIDGE 1
  23. // now include a bunch of stuff
  24. #include "CarlaBackendUtils.hpp"
  25. #include "CarlaBridgeUtils.hpp"
  26. #include "CarlaMIDI.h"
  27. #include "CarlaMutex.hpp"
  28. #include "LinkedList.hpp"
  29. #if 0
  30. #include <jack/jack.h>
  31. #include <jack/midiport.h>
  32. #include <jack/transport.h>
  33. #include <jack/session.h>
  34. #include <jack/metadata.h>
  35. #endif
  36. #include <cerrno>
  37. #include <map>
  38. #include <string>
  39. #ifdef __SSE2_MATH__
  40. # include <xmmintrin.h>
  41. #endif
  42. // must be last include
  43. #include "api.hpp"
  44. // small check to not hurt myself
  45. #ifdef JACKBRIDGE_DIRECT
  46. # error "Cannot create custom jack server while linking to libjack directly"
  47. #endif
  48. CARLA_BACKEND_START_NAMESPACE
  49. // --------------------------------------------------------------------------------------------------------------------
  50. class CarlaJackAppClient;
  51. struct JackClientState;
  52. struct JackServerState;
  53. struct JackMidiPortBufferBase {
  54. static const uint8_t kMaxEventSize = 128;
  55. static const size_t kMaxEventCount = 512;
  56. static const size_t kBufferPoolSize = kMaxEventCount*8;
  57. bool isInput;
  58. bool isDummy;
  59. };
  60. struct JackMidiPortBufferOnStack : JackMidiPortBufferBase {
  61. size_t bufferPoolPos;
  62. uint16_t count;
  63. jack_midi_event_t events[kMaxEventCount];
  64. jack_midi_data_t bufferPool[kBufferPoolSize];
  65. JackMidiPortBufferOnStack()
  66. : bufferPoolPos(0),
  67. count(0),
  68. events(),
  69. bufferPool()
  70. {
  71. isInput = true;
  72. isDummy = false;
  73. }
  74. CARLA_DECLARE_NON_COPYABLE(JackMidiPortBufferOnStack)
  75. };
  76. struct JackMidiPortBufferDummy : JackMidiPortBufferBase {
  77. JackMidiPortBufferDummy(const bool input)
  78. {
  79. isInput = input;
  80. isDummy = true;
  81. }
  82. CARLA_DECLARE_NON_COPYABLE(JackMidiPortBufferDummy)
  83. };
  84. struct JackPortState {
  85. enum Offsets {
  86. kPortIdOffsetAudioIn = 100,
  87. kPortIdOffsetMidiIn = 300,
  88. kPortIdOffsetAudioOut = 500,
  89. kPortIdOffsetMidiOut = 700,
  90. kPortIdOffsetUser = 1000,
  91. };
  92. char* name;
  93. char* fullname;
  94. void* buffer;
  95. uint index;
  96. int flags;
  97. uint gid;
  98. jack_uuid_t uuid;
  99. bool isMidi : 1;
  100. bool isSystem : 1;
  101. bool isConnected : 1;
  102. bool unused : 1;
  103. JackPortState(const char* const fullPortName,
  104. const char* const portName,
  105. const uint i, const int f, const uint id,
  106. const bool midi, const bool con)
  107. : name(portName != nullptr ? strdup(portName) : nullptr),
  108. fullname(fullPortName != nullptr ? strdup(fullPortName) : nullptr),
  109. buffer(nullptr),
  110. index(i),
  111. flags(f),
  112. gid(id),
  113. uuid(jack_port_uuid_generate(id)),
  114. isMidi(midi),
  115. isSystem(true),
  116. isConnected(con),
  117. unused(false) {}
  118. JackPortState(const char* const clientName,
  119. const char* const portName,
  120. const uint i, const int f, const uint id,
  121. const bool midi, const bool sys, const bool con)
  122. : name(portName != nullptr ? strdup(portName) : nullptr),
  123. fullname(nullptr),
  124. buffer(nullptr),
  125. index(i),
  126. flags(f),
  127. gid(id),
  128. uuid(jack_port_uuid_generate(id)),
  129. isMidi(midi),
  130. isSystem(sys),
  131. isConnected(con),
  132. unused(false)
  133. {
  134. if (clientName != nullptr && portName != nullptr)
  135. {
  136. char strBuf[STR_MAX+1];
  137. snprintf(strBuf, STR_MAX, "%s:%s", clientName, portName);
  138. strBuf[STR_MAX] = '\0';
  139. fullname = strdup(strBuf);
  140. }
  141. }
  142. ~JackPortState()
  143. {
  144. std::free(name);
  145. name = nullptr;
  146. std::free(fullname);
  147. fullname = nullptr;
  148. }
  149. CARLA_DECLARE_NON_COPYABLE(JackPortState)
  150. };
  151. struct JackClientState {
  152. const JackServerState& server;
  153. CarlaMutex mutex;
  154. bool activated;
  155. bool deactivated; // activated once, then deactivated
  156. char* name;
  157. jack_uuid_t uuid;
  158. LinkedList<JackPortState*> audioIns;
  159. LinkedList<JackPortState*> audioOuts;
  160. LinkedList<JackPortState*> midiIns;
  161. LinkedList<JackPortState*> midiOuts;
  162. std::map<uint, JackPortState*> portIdMapping;
  163. std::map<std::string, JackPortState*> portNameMapping;
  164. JackShutdownCallback shutdownCb;
  165. void* shutdownCbPtr;
  166. JackInfoShutdownCallback infoShutdownCb;
  167. void* infoShutdownCbPtr;
  168. JackProcessCallback processCb;
  169. void* processCbPtr;
  170. JackFreewheelCallback freewheelCb;
  171. void* freewheelCbPtr;
  172. JackBufferSizeCallback bufferSizeCb;
  173. void* bufferSizeCbPtr;
  174. JackSampleRateCallback sampleRateCb;
  175. void* sampleRateCbPtr;
  176. JackSyncCallback syncCb;
  177. void* syncCbPtr;
  178. JackThreadInitCallback threadInitCb;
  179. void* threadInitCbPtr;
  180. JackClientState(const JackServerState& s, const char* const n)
  181. : server(s),
  182. mutex(),
  183. activated(false),
  184. deactivated(false),
  185. name(strdup(n)),
  186. uuid(jack_client_uuid_generate()),
  187. audioIns(),
  188. audioOuts(),
  189. midiIns(),
  190. midiOuts(),
  191. portIdMapping(),
  192. portNameMapping(),
  193. shutdownCb(nullptr),
  194. shutdownCbPtr(nullptr),
  195. infoShutdownCb(nullptr),
  196. infoShutdownCbPtr(nullptr),
  197. processCb(nullptr),
  198. processCbPtr(nullptr),
  199. freewheelCb(nullptr),
  200. freewheelCbPtr(nullptr),
  201. bufferSizeCb(nullptr),
  202. bufferSizeCbPtr(nullptr),
  203. sampleRateCb(nullptr),
  204. sampleRateCbPtr(nullptr),
  205. syncCb(nullptr),
  206. syncCbPtr(nullptr),
  207. threadInitCb(nullptr),
  208. threadInitCbPtr(nullptr) {}
  209. ~JackClientState()
  210. {
  211. const CarlaMutexLocker cms(mutex);
  212. for (LinkedList<JackPortState*>::Itenerator it = audioIns.begin2(); it.valid(); it.next())
  213. {
  214. if (JackPortState* const jport = it.getValue(nullptr))
  215. delete jport;
  216. }
  217. for (LinkedList<JackPortState*>::Itenerator it = audioOuts.begin2(); it.valid(); it.next())
  218. {
  219. if (JackPortState* const jport = it.getValue(nullptr))
  220. delete jport;
  221. }
  222. for (LinkedList<JackPortState*>::Itenerator it = midiIns.begin2(); it.valid(); it.next())
  223. {
  224. if (JackPortState* const jport = it.getValue(nullptr))
  225. delete jport;
  226. }
  227. for (LinkedList<JackPortState*>::Itenerator it = midiOuts.begin2(); it.valid(); it.next())
  228. {
  229. if (JackPortState* const jport = it.getValue(nullptr))
  230. delete jport;
  231. }
  232. std::free(name);
  233. name = nullptr;
  234. audioIns.clear();
  235. audioOuts.clear();
  236. midiIns.clear();
  237. midiOuts.clear();
  238. portIdMapping.clear();
  239. portNameMapping.clear();
  240. }
  241. CARLA_DECLARE_NON_COPYABLE(JackClientState)
  242. };
  243. struct JackServerState {
  244. CarlaJackAppClient* jackAppPtr;
  245. uint32_t bufferSize;
  246. double sampleRate;
  247. jack_uuid_t uuid;
  248. uint8_t numAudioIns;
  249. uint8_t numAudioOuts;
  250. uint8_t numMidiIns;
  251. uint8_t numMidiOuts;
  252. bool playing;
  253. jack_position_t position;
  254. jack_nframes_t monotonic_frame;
  255. JackServerState(CarlaJackAppClient* const app)
  256. : jackAppPtr(app),
  257. bufferSize(0),
  258. sampleRate(0.0),
  259. uuid(jack_client_uuid_generate()),
  260. numAudioIns(0),
  261. numAudioOuts(0),
  262. numMidiIns(0),
  263. numMidiOuts(0),
  264. playing(false),
  265. position(),
  266. monotonic_frame(0)
  267. {
  268. carla_zeroStruct(position);
  269. }
  270. CARLA_DECLARE_NON_COPYABLE(JackServerState)
  271. };
  272. CARLA_BACKEND_END_NAMESPACE
  273. // --------------------------------------------------------------------------------------------------------------------
  274. #endif // CARLA_LIBJACK_HPP_INCLUDED