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 9.9KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. fBuffer = new EngineEvent[kMaxEngineEventInternalCount];
  77. }
  78. CarlaEngineEventPort::~CarlaEngineEventPort() noexcept
  79. {
  80. carla_debug("CarlaEngineEventPort::~CarlaEngineEventPort()");
  81. if (kProcessMode == ENGINE_PROCESS_MODE_PATCHBAY)
  82. {
  83. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,);
  84. delete[] fBuffer;
  85. fBuffer = nullptr;
  86. }
  87. }
  88. void CarlaEngineEventPort::initBuffer() noexcept
  89. {
  90. if (kProcessMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == ENGINE_PROCESS_MODE_BRIDGE)
  91. fBuffer = kClient.getEngine().getInternalEventBuffer(kIsInput);
  92. else if (kProcessMode == ENGINE_PROCESS_MODE_PATCHBAY && ! kIsInput)
  93. carla_zeroStructs(fBuffer, kMaxEngineEventInternalCount);
  94. }
  95. uint32_t CarlaEngineEventPort::getEventCount() const noexcept
  96. {
  97. CARLA_SAFE_ASSERT_RETURN(kIsInput, 0);
  98. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, 0);
  99. CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, 0);
  100. uint32_t i=0;
  101. for (; i < kMaxEngineEventInternalCount; ++i)
  102. {
  103. if (fBuffer[i].type == kEngineEventTypeNull)
  104. break;
  105. }
  106. return i;
  107. }
  108. const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index) const noexcept
  109. {
  110. CARLA_SAFE_ASSERT_RETURN(kIsInput, kFallbackEngineEvent);
  111. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, kFallbackEngineEvent);
  112. CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, kFallbackEngineEvent);
  113. CARLA_SAFE_ASSERT_RETURN(index < kMaxEngineEventInternalCount, kFallbackEngineEvent);
  114. return fBuffer[index];
  115. }
  116. const EngineEvent& CarlaEngineEventPort::getEventUnchecked(const uint32_t index) const noexcept
  117. {
  118. return fBuffer[index];
  119. }
  120. bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEvent& ctrl) noexcept
  121. {
  122. return writeControlEvent(time, channel, ctrl.type, ctrl.param, ctrl.value);
  123. }
  124. bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const float value) noexcept
  125. {
  126. CARLA_SAFE_ASSERT_RETURN(! kIsInput, false);
  127. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false);
  128. CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false);
  129. CARLA_SAFE_ASSERT_RETURN(type != kEngineControlEventTypeNull, false);
  130. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false);
  131. CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f);
  132. if (type == kEngineControlEventTypeParameter) {
  133. CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param));
  134. }
  135. for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i)
  136. {
  137. EngineEvent& event(fBuffer[i]);
  138. if (event.type != kEngineEventTypeNull)
  139. continue;
  140. event.type = kEngineEventTypeControl;
  141. event.time = time;
  142. event.channel = channel;
  143. event.ctrl.type = type;
  144. event.ctrl.param = param;
  145. event.ctrl.value = carla_fixedValue<float>(0.0f, 1.0f, value);
  146. return true;
  147. }
  148. carla_stderr2("CarlaEngineEventPort::writeControlEvent() - buffer full");
  149. return false;
  150. }
  151. bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t size, const uint8_t* const data) noexcept
  152. {
  153. return writeMidiEvent(time, uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data)), size, data);
  154. }
  155. bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const EngineMidiEvent& midi) noexcept
  156. {
  157. CARLA_SAFE_ASSERT(midi.port == kIndexOffset);
  158. return writeMidiEvent(time, channel, midi.size, midi.data);
  159. }
  160. bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t size, const uint8_t* const data) noexcept
  161. {
  162. CARLA_SAFE_ASSERT_RETURN(! kIsInput, false);
  163. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false);
  164. CARLA_SAFE_ASSERT_RETURN(kProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && kProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false);
  165. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false);
  166. CARLA_SAFE_ASSERT_RETURN(size > 0 && size <= EngineMidiEvent::kDataSize, false);
  167. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  168. for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i)
  169. {
  170. EngineEvent& event(fBuffer[i]);
  171. if (event.type != kEngineEventTypeNull)
  172. continue;
  173. event.time = time;
  174. event.channel = channel;
  175. const uint8_t status(uint8_t(MIDI_GET_STATUS_FROM_DATA(data)));
  176. if (status == MIDI_STATUS_CONTROL_CHANGE)
  177. {
  178. CARLA_SAFE_ASSERT_RETURN(size >= 3, true);
  179. switch (data[1])
  180. {
  181. case MIDI_CONTROL_BANK_SELECT:
  182. case MIDI_CONTROL_BANK_SELECT__LSB:
  183. event.type = kEngineEventTypeControl;
  184. event.ctrl.type = kEngineControlEventTypeMidiBank;
  185. event.ctrl.param = data[2];
  186. event.ctrl.value = 0.0f;
  187. return true;
  188. case MIDI_CONTROL_ALL_SOUND_OFF:
  189. event.type = kEngineEventTypeControl;
  190. event.ctrl.type = kEngineControlEventTypeAllSoundOff;
  191. event.ctrl.param = 0;
  192. event.ctrl.value = 0.0f;
  193. return true;
  194. case MIDI_CONTROL_ALL_NOTES_OFF:
  195. event.type = kEngineEventTypeControl;
  196. event.ctrl.type = kEngineControlEventTypeAllNotesOff;
  197. event.ctrl.param = 0;
  198. event.ctrl.value = 0.0f;
  199. return true;
  200. }
  201. }
  202. if (status == MIDI_STATUS_PROGRAM_CHANGE)
  203. {
  204. CARLA_SAFE_ASSERT_RETURN(size == 2, true);
  205. event.type = kEngineEventTypeControl;
  206. event.ctrl.type = kEngineControlEventTypeMidiBank;
  207. event.ctrl.param = data[1];
  208. event.ctrl.value = 0.0f;
  209. return true;
  210. }
  211. event.type = kEngineEventTypeMidi;
  212. event.midi.size = size;
  213. if (kIndexOffset < 0xFF /* uint8_t max */)
  214. {
  215. event.midi.port = kIndexOffset;
  216. }
  217. else
  218. {
  219. event.midi.port = 0;
  220. carla_safe_assert_int("kIndexOffset < 0xFF", __FILE__, __LINE__, kIndexOffset);
  221. }
  222. event.midi.data[0] = status;
  223. uint8_t j=1;
  224. for (; j < size; ++j)
  225. event.midi.data[j] = data[j];
  226. for (; j < EngineMidiEvent::kDataSize; ++j)
  227. event.midi.data[j] = 0;
  228. return true;
  229. }
  230. carla_stderr2("CarlaEngineEventPort::writeMidiEvent() - buffer full");
  231. return false;
  232. }
  233. // -----------------------------------------------------------------------
  234. CARLA_BACKEND_END_NAMESPACE