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.

CarlaEnginePorts.cpp 10KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2014 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. #include "CarlaEngineUtils.hpp"
  18. #include "CarlaMathUtils.hpp"
  19. #include "CarlaMIDI.h"
  20. CARLA_BACKEND_START_NAMESPACE
  21. // -----------------------------------------------------------------------
  22. // Fallback data
  23. static const EngineEvent kFallbackEngineEvent = { kEngineEventTypeNull, 0, 0, {{ kEngineControlEventTypeNull, 0, 0.0f }} };
  24. // -----------------------------------------------------------------------
  25. // Carla Engine port (Abstract)
  26. CarlaEnginePort::CarlaEnginePort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept
  27. : kClient(client),
  28. kIsInput(isInputPort),
  29. kIndexOffset(indexOffset)
  30. {
  31. carla_debug("CarlaEnginePort::CarlaEnginePort(%s)", bool2str(isInputPort));
  32. }
  33. CarlaEnginePort::~CarlaEnginePort() noexcept
  34. {
  35. carla_debug("CarlaEnginePort::~CarlaEnginePort()");
  36. }
  37. // -----------------------------------------------------------------------
  38. // Carla Engine Audio port
  39. CarlaEngineAudioPort::CarlaEngineAudioPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept
  40. : CarlaEnginePort(client, isInputPort, indexOffset),
  41. fBuffer(nullptr)
  42. {
  43. carla_debug("CarlaEngineAudioPort::CarlaEngineAudioPort(%s)", bool2str(isInputPort));
  44. }
  45. CarlaEngineAudioPort::~CarlaEngineAudioPort() noexcept
  46. {
  47. carla_debug("CarlaEngineAudioPort::~CarlaEngineAudioPort()");
  48. }
  49. void CarlaEngineAudioPort::initBuffer() noexcept
  50. {
  51. }
  52. // -----------------------------------------------------------------------
  53. // Carla Engine CV port
  54. CarlaEngineCVPort::CarlaEngineCVPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept
  55. : CarlaEnginePort(client, isInputPort, indexOffset),
  56. fBuffer(nullptr)
  57. {
  58. carla_debug("CarlaEngineCVPort::CarlaEngineCVPort(%s)", bool2str(isInputPort));
  59. }
  60. CarlaEngineCVPort::~CarlaEngineCVPort() noexcept
  61. {
  62. carla_debug("CarlaEngineCVPort::~CarlaEngineCVPort()");
  63. }
  64. void CarlaEngineCVPort::initBuffer() noexcept
  65. {
  66. }
  67. // -----------------------------------------------------------------------
  68. // Carla Engine Event port
  69. CarlaEngineEventPort::CarlaEngineEventPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept
  70. : CarlaEnginePort(client, isInputPort, indexOffset),
  71. fBuffer(nullptr),
  72. kProcessMode(client.getEngine().getProccessMode())
  73. {
  74. carla_debug("CarlaEngineEventPort::CarlaEngineEventPort(%s)", bool2str(isInputPort));
  75. if (kProcessMode == ENGINE_PROCESS_MODE_PATCHBAY)
  76. {
  77. fBuffer = new EngineEvent[kMaxEngineEventInternalCount];
  78. carla_zeroStructs(fBuffer, kMaxEngineEventInternalCount);
  79. }
  80. }
  81. CarlaEngineEventPort::~CarlaEngineEventPort() noexcept
  82. {
  83. carla_debug("CarlaEngineEventPort::~CarlaEngineEventPort()");
  84. if (kProcessMode == ENGINE_PROCESS_MODE_PATCHBAY)
  85. {
  86. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,);
  87. delete[] fBuffer;
  88. fBuffer = nullptr;
  89. }
  90. }
  91. void CarlaEngineEventPort::initBuffer() noexcept
  92. {
  93. if (kProcessMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == ENGINE_PROCESS_MODE_BRIDGE)
  94. fBuffer = kClient.getEngine().getInternalEventBuffer(kIsInput);
  95. else if (kProcessMode == ENGINE_PROCESS_MODE_PATCHBAY && ! kIsInput)
  96. carla_zeroStructs(fBuffer, kMaxEngineEventInternalCount);
  97. }
  98. uint32_t CarlaEngineEventPort::getEventCount() const noexcept
  99. {
  100. CARLA_SAFE_ASSERT_RETURN(kIsInput, 0);
  101. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, 0);
  102. CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, 0);
  103. uint32_t i=0;
  104. for (; i < kMaxEngineEventInternalCount; ++i)
  105. {
  106. if (fBuffer[i].type == kEngineEventTypeNull)
  107. break;
  108. }
  109. return i;
  110. }
  111. const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index) const noexcept
  112. {
  113. CARLA_SAFE_ASSERT_RETURN(kIsInput, kFallbackEngineEvent);
  114. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, kFallbackEngineEvent);
  115. CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, kFallbackEngineEvent);
  116. CARLA_SAFE_ASSERT_RETURN(index < kMaxEngineEventInternalCount, kFallbackEngineEvent);
  117. return fBuffer[index];
  118. }
  119. const EngineEvent& CarlaEngineEventPort::getEventUnchecked(const uint32_t index) const noexcept
  120. {
  121. return fBuffer[index];
  122. }
  123. bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEvent& ctrl) noexcept
  124. {
  125. return writeControlEvent(time, channel, ctrl.type, ctrl.param, ctrl.value);
  126. }
  127. bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const float value) noexcept
  128. {
  129. CARLA_SAFE_ASSERT_RETURN(! kIsInput, false);
  130. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false);
  131. CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false);
  132. CARLA_SAFE_ASSERT_RETURN(type != kEngineControlEventTypeNull, false);
  133. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false);
  134. CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f);
  135. if (type == kEngineControlEventTypeParameter) {
  136. CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param));
  137. }
  138. for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i)
  139. {
  140. EngineEvent& event(fBuffer[i]);
  141. if (event.type != kEngineEventTypeNull)
  142. continue;
  143. event.type = kEngineEventTypeControl;
  144. event.time = time;
  145. event.channel = channel;
  146. event.ctrl.type = type;
  147. event.ctrl.param = param;
  148. event.ctrl.value = carla_fixedValue<float>(0.0f, 1.0f, value);
  149. return true;
  150. }
  151. carla_stderr2("CarlaEngineEventPort::writeControlEvent() - buffer full");
  152. return false;
  153. }
  154. bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t size, const uint8_t* const data) noexcept
  155. {
  156. return writeMidiEvent(time, uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data)), size, data);
  157. }
  158. bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const EngineMidiEvent& midi) noexcept
  159. {
  160. CARLA_SAFE_ASSERT(midi.port == kIndexOffset);
  161. return writeMidiEvent(time, channel, midi.size, midi.data);
  162. }
  163. bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t size, const uint8_t* const data) noexcept
  164. {
  165. CARLA_SAFE_ASSERT_RETURN(! kIsInput, false);
  166. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false);
  167. CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false);
  168. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false);
  169. CARLA_SAFE_ASSERT_RETURN(size > 0 && size <= EngineMidiEvent::kDataSize, false);
  170. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  171. for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i)
  172. {
  173. EngineEvent& event(fBuffer[i]);
  174. if (event.type != kEngineEventTypeNull)
  175. continue;
  176. event.time = time;
  177. event.channel = channel;
  178. const uint8_t status(uint8_t(MIDI_GET_STATUS_FROM_DATA(data)));
  179. if (status == MIDI_STATUS_CONTROL_CHANGE)
  180. {
  181. CARLA_SAFE_ASSERT_RETURN(size >= 2, true);
  182. switch (data[1])
  183. {
  184. case MIDI_CONTROL_BANK_SELECT:
  185. case MIDI_CONTROL_BANK_SELECT__LSB:
  186. CARLA_SAFE_ASSERT_RETURN(size >= 3, true);
  187. event.type = kEngineEventTypeControl;
  188. event.ctrl.type = kEngineControlEventTypeMidiBank;
  189. event.ctrl.param = data[2];
  190. event.ctrl.value = 0.0f;
  191. return true;
  192. case MIDI_CONTROL_ALL_SOUND_OFF:
  193. event.type = kEngineEventTypeControl;
  194. event.ctrl.type = kEngineControlEventTypeAllSoundOff;
  195. event.ctrl.param = 0;
  196. event.ctrl.value = 0.0f;
  197. return true;
  198. case MIDI_CONTROL_ALL_NOTES_OFF:
  199. event.type = kEngineEventTypeControl;
  200. event.ctrl.type = kEngineControlEventTypeAllNotesOff;
  201. event.ctrl.param = 0;
  202. event.ctrl.value = 0.0f;
  203. return true;
  204. }
  205. }
  206. if (status == MIDI_STATUS_PROGRAM_CHANGE)
  207. {
  208. CARLA_SAFE_ASSERT_RETURN(size >= 2, true);
  209. event.type = kEngineEventTypeControl;
  210. event.ctrl.type = kEngineControlEventTypeMidiProgram;
  211. event.ctrl.param = data[1];
  212. event.ctrl.value = 0.0f;
  213. return true;
  214. }
  215. event.type = kEngineEventTypeMidi;
  216. event.midi.size = size;
  217. if (kIndexOffset < 0xFF /* uint8_t max */)
  218. {
  219. event.midi.port = static_cast<uint8_t>(kIndexOffset);
  220. }
  221. else
  222. {
  223. event.midi.port = 0;
  224. carla_safe_assert_uint("kIndexOffset < 0xFF", __FILE__, __LINE__, kIndexOffset);
  225. }
  226. event.midi.data[0] = status;
  227. uint8_t j=1;
  228. for (; j < size; ++j)
  229. event.midi.data[j] = data[j];
  230. for (; j < EngineMidiEvent::kDataSize; ++j)
  231. event.midi.data[j] = 0;
  232. return true;
  233. }
  234. carla_stderr2("CarlaEngineEventPort::writeMidiEvent() - buffer full");
  235. return false;
  236. }
  237. // -----------------------------------------------------------------------
  238. CARLA_BACKEND_END_NAMESPACE