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.

NativePlugin.cpp 87KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611
  1. /*
  2. * Carla Native Plugin
  3. * Copyright (C) 2012-2013 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 "CarlaPluginInternal.hpp"
  18. #ifdef WANT_NATIVE
  19. #include "CarlaNative.h"
  20. extern "C" {
  21. // Simple plugins
  22. void carla_register_native_plugin_bypass();
  23. void carla_register_native_plugin_lfo();
  24. void carla_register_native_plugin_midiGain();
  25. void carla_register_native_plugin_midiSplit();
  26. void carla_register_native_plugin_midiThrough();
  27. void carla_register_native_plugin_midiTranspose();
  28. void carla_register_native_plugin_nekofilter();
  29. void carla_register_native_plugin_sunvoxfile();
  30. void carla_register_native_plugin_vex();
  31. #ifndef BUILD_BRIDGE
  32. // Carla
  33. void carla_register_native_plugin_carla();
  34. #endif
  35. #ifdef WANT_AUDIOFILE
  36. // AudioFile
  37. void carla_register_native_plugin_audiofile();
  38. #endif
  39. #ifdef WANT_MIDIFILE
  40. // MidiFile
  41. void carla_register_native_plugin_midifile();
  42. #endif
  43. #ifdef WANT_OPENGL
  44. // DISTRHO plugins (OpenGL)
  45. void carla_register_native_plugin_3BandEQ();
  46. void carla_register_native_plugin_3BandSplitter();
  47. void carla_register_native_plugin_Nekobi();
  48. void carla_register_native_plugin_PingPongPan();
  49. //void carla_register_native_plugin_StereoEnhancer();
  50. #endif
  51. // DISTRHO plugins (PyQt)
  52. void carla_register_native_plugin_BigMeter();
  53. void carla_register_native_plugin_BigMeterM();
  54. void carla_register_native_plugin_Notes();
  55. #ifdef WANT_ZYNADDSUBFX
  56. // ZynAddSubFX
  57. void carla_register_native_plugin_zynaddsubfx();
  58. #endif
  59. }
  60. void carla_register_all_plugins()
  61. {
  62. // Simple plugins
  63. carla_register_native_plugin_bypass();
  64. carla_register_native_plugin_lfo();
  65. carla_register_native_plugin_midiGain();
  66. carla_register_native_plugin_midiSplit();
  67. carla_register_native_plugin_midiThrough();
  68. carla_register_native_plugin_midiTranspose();
  69. carla_register_native_plugin_nekofilter();
  70. //carla_register_native_plugin_sunvoxfile(); // unfinished
  71. carla_register_native_plugin_vex();
  72. #ifndef BUILD_BRIDGE
  73. // Carla
  74. //carla_register_native_plugin_carla(); // kinda unfinished
  75. #endif
  76. #ifdef WANT_AUDIOFILE
  77. // AudioFile
  78. carla_register_native_plugin_audiofile();
  79. #endif
  80. #ifdef WANT_MIDIFILE
  81. // MidiFile
  82. carla_register_native_plugin_midifile();
  83. #endif
  84. #ifdef WANT_OPENGL
  85. // DISTRHO plugins (OpenGL)
  86. carla_register_native_plugin_3BandEQ();
  87. carla_register_native_plugin_3BandSplitter();
  88. carla_register_native_plugin_Nekobi();
  89. carla_register_native_plugin_PingPongPan();
  90. //carla_register_native_plugin_StereoEnhancer(); // unfinished
  91. #endif
  92. // DISTRHO plugins (PyQt)
  93. carla_register_native_plugin_BigMeter();
  94. carla_register_native_plugin_BigMeterM();
  95. carla_register_native_plugin_Notes();
  96. #ifdef WANT_ZYNADDSUBFX
  97. // ZynAddSubFX
  98. carla_register_native_plugin_zynaddsubfx();
  99. #endif
  100. }
  101. CARLA_BACKEND_START_NAMESPACE
  102. #if 0
  103. }
  104. #endif
  105. struct NativePluginMidiData {
  106. uint32_t count;
  107. uint32_t* indexes;
  108. CarlaEngineEventPort** ports;
  109. NativePluginMidiData()
  110. : count(0),
  111. indexes(nullptr),
  112. ports(nullptr) {}
  113. ~NativePluginMidiData()
  114. {
  115. CARLA_ASSERT_INT(count == 0, count);
  116. CARLA_ASSERT(ports == nullptr);
  117. CARLA_ASSERT(indexes == nullptr);
  118. }
  119. void createNew(const uint32_t newCount)
  120. {
  121. CARLA_ASSERT_INT(count == 0, count);
  122. CARLA_ASSERT(ports == nullptr);
  123. CARLA_ASSERT(indexes == nullptr);
  124. CARLA_ASSERT_INT(newCount > 0, newCount);
  125. if (ports != nullptr || indexes != nullptr || newCount == 0)
  126. return;
  127. ports = new CarlaEngineEventPort*[newCount];
  128. indexes = new uint32_t[newCount];
  129. count = newCount;
  130. for (uint32_t i=0; i < newCount; ++i)
  131. ports[i] = nullptr;
  132. for (uint32_t i=0; i < newCount; ++i)
  133. indexes[i] = 0;
  134. }
  135. void clear()
  136. {
  137. if (ports != nullptr)
  138. {
  139. for (uint32_t i=0; i < count; ++i)
  140. {
  141. if (ports[i] != nullptr)
  142. {
  143. delete ports[i];
  144. ports[i] = nullptr;
  145. }
  146. }
  147. delete[] ports;
  148. ports = nullptr;
  149. }
  150. if (indexes != nullptr)
  151. {
  152. delete[] indexes;
  153. indexes = nullptr;
  154. }
  155. count = 0;
  156. }
  157. void initBuffers()
  158. {
  159. for (uint32_t i=0; i < count; ++i)
  160. {
  161. if (ports[i] != nullptr)
  162. ports[i]->initBuffer();
  163. }
  164. }
  165. CARLA_DECLARE_NON_COPY_STRUCT(NativePluginMidiData)
  166. };
  167. class NativePlugin : public CarlaPlugin
  168. {
  169. public:
  170. NativePlugin(CarlaEngine* const engine, const unsigned int id)
  171. : CarlaPlugin(engine, id),
  172. fHandle(nullptr),
  173. fHandle2(nullptr),
  174. fDescriptor(nullptr),
  175. fIsProcessing(false),
  176. fIsUiVisible(false),
  177. fAudioInBuffers(nullptr),
  178. fAudioOutBuffers(nullptr),
  179. #ifdef CARLA_PROPER_CPP11_SUPPORT
  180. fMidiEventCount(0),
  181. fCurMidiProgs{0}
  182. #else
  183. fMidiEventCount(0)
  184. #endif
  185. {
  186. carla_debug("NativePlugin::NativePlugin(%p, %i)", engine, id);
  187. #ifndef CARLA_PROPER_CPP11_SUPPORT
  188. carla_fill<int32_t>(fCurMidiProgs, MAX_MIDI_CHANNELS, 0);
  189. #endif
  190. carla_zeroStruct< ::MidiEvent>(fMidiEvents, kPluginMaxMidiEvents*2);
  191. carla_zeroStruct< ::TimeInfo>(fTimeInfo);
  192. fHost.handle = this;
  193. fHost.resourceDir = carla_strdup((const char*)engine->getOptions().resourceDir);
  194. fHost.uiName = nullptr;
  195. fHost.get_buffer_size = carla_host_get_buffer_size;
  196. fHost.get_sample_rate = carla_host_get_sample_rate;
  197. fHost.is_offline = carla_host_is_offline;
  198. fHost.get_time_info = carla_host_get_time_info;
  199. fHost.write_midi_event = carla_host_write_midi_event;
  200. fHost.ui_parameter_changed = carla_host_ui_parameter_changed;
  201. fHost.ui_custom_data_changed = carla_host_ui_custom_data_changed;
  202. fHost.ui_closed = carla_host_ui_closed;
  203. fHost.ui_open_file = carla_host_ui_open_file;
  204. fHost.ui_save_file = carla_host_ui_save_file;
  205. fHost.dispatcher = carla_host_dispatcher;
  206. }
  207. ~NativePlugin() override
  208. {
  209. carla_debug("NativePlugin::~NativePlugin()");
  210. // close UI
  211. if (fHints & PLUGIN_HAS_GUI)
  212. {
  213. if (fIsUiVisible && fDescriptor != nullptr && fDescriptor->ui_show != nullptr && fHandle != nullptr)
  214. fDescriptor->ui_show(fHandle, false);
  215. }
  216. pData->singleMutex.lock();
  217. pData->masterMutex.lock();
  218. if (pData->client != nullptr && pData->client->isActive())
  219. pData->client->deactivate();
  220. CARLA_ASSERT(! fIsProcessing);
  221. if (pData->active)
  222. {
  223. deactivate();
  224. pData->active = false;
  225. }
  226. if (fDescriptor != nullptr)
  227. {
  228. if (fDescriptor->cleanup != nullptr)
  229. {
  230. if (fHandle != nullptr)
  231. fDescriptor->cleanup(fHandle);
  232. if (fHandle2 != nullptr)
  233. fDescriptor->cleanup(fHandle2);
  234. }
  235. fHandle = nullptr;
  236. fHandle2 = nullptr;
  237. fDescriptor = nullptr;
  238. }
  239. if (fHost.resourceDir != nullptr)
  240. {
  241. delete[] fHost.resourceDir;
  242. fHost.resourceDir = nullptr;
  243. }
  244. if (fHost.uiName != nullptr)
  245. {
  246. delete[] fHost.uiName;
  247. fHost.uiName = nullptr;
  248. }
  249. clearBuffers();
  250. }
  251. // -------------------------------------------------------------------
  252. // Information (base)
  253. PluginType getType() const noexcept override
  254. {
  255. return PLUGIN_INTERNAL;
  256. }
  257. PluginCategory getCategory() const override
  258. {
  259. CARLA_ASSERT(fDescriptor != nullptr);
  260. return static_cast<PluginCategory>(fDescriptor->category);
  261. }
  262. // -------------------------------------------------------------------
  263. // Information (count)
  264. uint32_t getMidiInCount() const noexcept override
  265. {
  266. return fMidiIn.count;
  267. }
  268. uint32_t getMidiOutCount() const noexcept override
  269. {
  270. return fMidiOut.count;
  271. }
  272. uint32_t getParameterScalePointCount(const uint32_t parameterId) const override
  273. {
  274. CARLA_ASSERT(fDescriptor != nullptr);
  275. CARLA_ASSERT(fHandle != nullptr);
  276. CARLA_ASSERT(parameterId < pData->param.count);
  277. if (fDescriptor->get_parameter_info != nullptr && parameterId < pData->param.count)
  278. {
  279. if (const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  280. return param->scalePointCount;
  281. }
  282. return 0;
  283. }
  284. // -------------------------------------------------------------------
  285. // Information (current data)
  286. // nothing
  287. // -------------------------------------------------------------------
  288. // Information (per-plugin data)
  289. unsigned int getAvailableOptions() const override
  290. {
  291. CARLA_ASSERT(fDescriptor != nullptr);
  292. if (fDescriptor == nullptr)
  293. return 0x0;
  294. const bool hasMidiProgs(fDescriptor->get_midi_program_count != nullptr && fDescriptor->get_midi_program_count(fHandle) > 0);
  295. unsigned int options = 0x0;
  296. if (hasMidiProgs && (fDescriptor->supports & ::PLUGIN_SUPPORTS_PROGRAM_CHANGES) == 0)
  297. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  298. if (getMidiInCount() == 0 && (fDescriptor->hints & ::PLUGIN_NEEDS_FIXED_BUFFERS) == 0)
  299. options |= PLUGIN_OPTION_FIXED_BUFFERS;
  300. if (pData->engine->getProccessMode() != PROCESS_MODE_CONTINUOUS_RACK)
  301. {
  302. if (fOptions & PLUGIN_OPTION_FORCE_STEREO)
  303. options |= PLUGIN_OPTION_FORCE_STEREO;
  304. else if (pData->audioIn.count <= 1 && pData->audioOut.count <= 1 && (pData->audioIn.count != 0 || pData->audioOut.count != 0))
  305. options |= PLUGIN_OPTION_FORCE_STEREO;
  306. }
  307. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_CONTROL_CHANGES)
  308. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  309. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_CHANNEL_PRESSURE)
  310. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  311. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_NOTE_AFTERTOUCH)
  312. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  313. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_PITCHBEND)
  314. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  315. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_ALL_SOUND_OFF)
  316. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  317. return options;
  318. }
  319. float getParameterValue(const uint32_t parameterId) const override
  320. {
  321. CARLA_ASSERT(fDescriptor != nullptr);
  322. CARLA_ASSERT(fHandle != nullptr);
  323. CARLA_ASSERT(parameterId < pData->param.count);
  324. if (fDescriptor->get_parameter_value != nullptr && parameterId < pData->param.count)
  325. return fDescriptor->get_parameter_value(fHandle, parameterId);
  326. return 0.0f;
  327. }
  328. float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const override
  329. {
  330. CARLA_ASSERT(fDescriptor != nullptr);
  331. CARLA_ASSERT(fHandle != nullptr);
  332. CARLA_ASSERT(parameterId < pData->param.count);
  333. CARLA_ASSERT(scalePointId < getParameterScalePointCount(parameterId));
  334. if (fDescriptor->get_parameter_info != nullptr && parameterId < pData->param.count)
  335. {
  336. if (const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  337. {
  338. const ParameterScalePoint& scalePoint(param->scalePoints[scalePointId]);
  339. return scalePoint.value;
  340. }
  341. }
  342. return 0.0f;
  343. }
  344. void getLabel(char* const strBuf) const override
  345. {
  346. CARLA_ASSERT(fDescriptor != nullptr);
  347. if (fDescriptor->label != nullptr)
  348. std::strncpy(strBuf, fDescriptor->label, STR_MAX);
  349. else
  350. CarlaPlugin::getLabel(strBuf);
  351. }
  352. void getMaker(char* const strBuf) const override
  353. {
  354. CARLA_ASSERT(fDescriptor != nullptr);
  355. if (fDescriptor->maker != nullptr)
  356. std::strncpy(strBuf, fDescriptor->maker, STR_MAX);
  357. else
  358. CarlaPlugin::getMaker(strBuf);
  359. }
  360. void getCopyright(char* const strBuf) const override
  361. {
  362. CARLA_ASSERT(fDescriptor != nullptr);
  363. if (fDescriptor->copyright != nullptr)
  364. std::strncpy(strBuf, fDescriptor->copyright, STR_MAX);
  365. else
  366. CarlaPlugin::getCopyright(strBuf);
  367. }
  368. void getRealName(char* const strBuf) const override
  369. {
  370. CARLA_ASSERT(fDescriptor != nullptr);
  371. if (fDescriptor->name != nullptr)
  372. std::strncpy(strBuf, fDescriptor->name, STR_MAX);
  373. else
  374. CarlaPlugin::getRealName(strBuf);
  375. }
  376. void getParameterName(const uint32_t parameterId, char* const strBuf) const override
  377. {
  378. CARLA_ASSERT(fDescriptor != nullptr);
  379. CARLA_ASSERT(fHandle != nullptr);
  380. CARLA_ASSERT(parameterId < pData->param.count);
  381. if (fDescriptor->get_parameter_info != nullptr && parameterId < pData->param.count)
  382. {
  383. const Parameter* const param(fDescriptor->get_parameter_info(fHandle, parameterId));
  384. if (param != nullptr && param->name != nullptr)
  385. {
  386. std::strncpy(strBuf, param->name, STR_MAX);
  387. return;
  388. }
  389. }
  390. CarlaPlugin::getParameterName(parameterId, strBuf);
  391. }
  392. void getParameterText(const uint32_t parameterId, char* const strBuf) const override
  393. {
  394. CARLA_ASSERT(fDescriptor != nullptr);
  395. CARLA_ASSERT(fHandle != nullptr);
  396. CARLA_ASSERT(parameterId < pData->param.count);
  397. if (fDescriptor->get_parameter_value != nullptr && fDescriptor->get_parameter_text != nullptr && parameterId < pData->param.count)
  398. {
  399. const float value(fDescriptor->get_parameter_value(fHandle, parameterId));
  400. if (const char* const text = fDescriptor->get_parameter_text(fHandle, parameterId, value))
  401. {
  402. std::strncpy(strBuf, text, STR_MAX);
  403. return;
  404. }
  405. }
  406. CarlaPlugin::getParameterText(parameterId, strBuf);
  407. }
  408. void getParameterUnit(const uint32_t parameterId, char* const strBuf) const override
  409. {
  410. CARLA_ASSERT(fDescriptor != nullptr);
  411. CARLA_ASSERT(fHandle != nullptr);
  412. CARLA_ASSERT(parameterId < pData->param.count);
  413. if (fDescriptor->get_parameter_info != nullptr && parameterId < pData->param.count)
  414. {
  415. const Parameter* const param(fDescriptor->get_parameter_info(fHandle, parameterId));
  416. if (param != nullptr && param->unit != nullptr)
  417. {
  418. std::strncpy(strBuf, param->unit, STR_MAX);
  419. return;
  420. }
  421. }
  422. CarlaPlugin::getParameterUnit(parameterId, strBuf);
  423. }
  424. void getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const override
  425. {
  426. CARLA_ASSERT(fDescriptor != nullptr);
  427. CARLA_ASSERT(fHandle != nullptr);
  428. CARLA_ASSERT(parameterId < pData->param.count);
  429. CARLA_ASSERT(scalePointId < getParameterScalePointCount(parameterId));
  430. if (fDescriptor->get_parameter_info != nullptr && parameterId < pData->param.count)
  431. {
  432. if (const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  433. {
  434. const ParameterScalePoint& scalePoint(param->scalePoints[scalePointId]);
  435. if (scalePoint.label != nullptr)
  436. {
  437. std::strncpy(strBuf, scalePoint.label, STR_MAX);
  438. return;
  439. }
  440. }
  441. }
  442. CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf);
  443. }
  444. // -------------------------------------------------------------------
  445. // Set data (state)
  446. void prepareForSave() override
  447. {
  448. CARLA_ASSERT(fDescriptor != nullptr);
  449. CARLA_ASSERT(fHandle != nullptr);
  450. if (pData->midiprog.count > 0 /*&& (fHints & PLUGIN_IS_SYNTH) != 0*/) // TODO
  451. {
  452. char strBuf[STR_MAX+1];
  453. std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i",
  454. fCurMidiProgs[0], fCurMidiProgs[1], fCurMidiProgs[2], fCurMidiProgs[3],
  455. fCurMidiProgs[4], fCurMidiProgs[5], fCurMidiProgs[6], fCurMidiProgs[7],
  456. fCurMidiProgs[8], fCurMidiProgs[9], fCurMidiProgs[10], fCurMidiProgs[11],
  457. fCurMidiProgs[12], fCurMidiProgs[13], fCurMidiProgs[14], fCurMidiProgs[15]);
  458. strBuf[STR_MAX] = '\0';
  459. CarlaPlugin::setCustomData(CUSTOM_DATA_STRING, "midiPrograms", strBuf, false);
  460. }
  461. if (fDescriptor == nullptr || fDescriptor->get_state == nullptr || (fDescriptor->hints & ::PLUGIN_USES_STATE) == 0)
  462. return;
  463. if (char* data = fDescriptor->get_state(fHandle))
  464. {
  465. CarlaPlugin::setCustomData(CUSTOM_DATA_CHUNK, "State", data, false);
  466. std::free(data);
  467. }
  468. }
  469. // -------------------------------------------------------------------
  470. // Set data (internal stuff)
  471. void setName(const char* const newName) override
  472. {
  473. CARLA_ASSERT(fDescriptor != nullptr);
  474. CARLA_ASSERT(fHandle != nullptr);
  475. char uiName[std::strlen(newName)+6+1];
  476. std::strcpy(uiName, newName);
  477. std::strcat(uiName, " (GUI)");
  478. if (fHost.uiName != nullptr)
  479. delete[] fHost.uiName;
  480. fHost.uiName = carla_strdup(uiName);
  481. if (fDescriptor != nullptr && fDescriptor->dispatcher != nullptr)
  482. fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_UI_NAME_CHANGED, 0, 0, uiName, 0.0f);
  483. CarlaPlugin::setName(newName);
  484. }
  485. void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) override
  486. {
  487. if (channel < MAX_MIDI_CHANNELS && pData->midiprog.count > 0)
  488. pData->midiprog.current = fCurMidiProgs[channel];
  489. CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback);
  490. }
  491. // -------------------------------------------------------------------
  492. // Set data (plugin-specific stuff)
  493. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) override
  494. {
  495. CARLA_ASSERT(fDescriptor != nullptr);
  496. CARLA_ASSERT(fHandle != nullptr);
  497. CARLA_ASSERT(parameterId < pData->param.count);
  498. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  499. if (fDescriptor->set_parameter_value != nullptr && parameterId < pData->param.count)
  500. {
  501. fDescriptor->set_parameter_value(fHandle, parameterId, fixedValue);
  502. if (fHandle2 != nullptr)
  503. fDescriptor->set_parameter_value(fHandle2, parameterId, fixedValue);
  504. }
  505. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  506. }
  507. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  508. {
  509. CARLA_ASSERT(fDescriptor != nullptr);
  510. CARLA_ASSERT(fHandle != nullptr);
  511. CARLA_ASSERT(type != nullptr);
  512. CARLA_ASSERT(key != nullptr);
  513. CARLA_ASSERT(value != nullptr);
  514. carla_debug("NativePlugin::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));
  515. if (type == nullptr)
  516. return carla_stderr2("NativePlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is null", type, key, value, bool2str(sendGui));
  517. if (std::strcmp(type, CUSTOM_DATA_STRING) != 0 && std::strcmp(type, CUSTOM_DATA_CHUNK) != 0)
  518. return carla_stderr2("NativePlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is invalid", type, key, value, bool2str(sendGui));
  519. if (key == nullptr)
  520. return carla_stderr2("NativePlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - key is null", type, key, value, bool2str(sendGui));
  521. if (value == nullptr)
  522. return carla_stderr2("Nativelugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - value is null", type, key, value, bool2str(sendGui));
  523. if (std::strcmp(type, CUSTOM_DATA_CHUNK) == 0)
  524. {
  525. if (fDescriptor->set_state != nullptr && (fDescriptor->hints & ::PLUGIN_USES_STATE) != 0)
  526. {
  527. const ScopedSingleProcessLocker spl(this, true);
  528. fDescriptor->set_state(fHandle, value);
  529. if (fHandle2 != nullptr)
  530. fDescriptor->set_state(fHandle2, value);
  531. }
  532. }
  533. else if (std::strcmp(key, "midiPrograms") == 0 && fDescriptor->set_midi_program != nullptr)
  534. {
  535. #if 0 // TODO
  536. QStringList midiProgramList(QString(value).split(":", QString::SkipEmptyParts));
  537. if (midiProgramList.count() == MAX_MIDI_CHANNELS)
  538. {
  539. uint i = 0;
  540. foreach (const QString& midiProg, midiProgramList)
  541. {
  542. bool ok;
  543. const uint index(midiProg.toUInt(&ok));
  544. if (ok && index < pData->midiprog.count)
  545. {
  546. const uint32_t bank = pData->midiprog.data[index].bank;
  547. const uint32_t program = pData->midiprog.data[index].program;
  548. fDescriptor->set_midi_program(fHandle, i, bank, program);
  549. if (fHandle2 != nullptr)
  550. fDescriptor->set_midi_program(fHandle2, i, bank, program);
  551. fCurMidiProgs[i] = index;
  552. if (pData->ctrlChannel == static_cast<int32_t>(i))
  553. {
  554. pData->midiprog.current = index;
  555. pData->engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, fId, index, 0, 0.0f, nullptr);
  556. }
  557. }
  558. ++i;
  559. }
  560. }
  561. #endif
  562. }
  563. else
  564. {
  565. if (fDescriptor->set_custom_data != nullptr)
  566. {
  567. fDescriptor->set_custom_data(fHandle, key, value);
  568. if (fHandle2 != nullptr)
  569. fDescriptor->set_custom_data(fHandle2, key, value);
  570. }
  571. if (sendGui && fIsUiVisible && fDescriptor->ui_set_custom_data != nullptr)
  572. fDescriptor->ui_set_custom_data(fHandle, key, value);
  573. }
  574. CarlaPlugin::setCustomData(type, key, value, sendGui);
  575. }
  576. void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) override
  577. {
  578. CARLA_ASSERT(fDescriptor != nullptr);
  579. CARLA_ASSERT(fHandle != nullptr);
  580. CARLA_ASSERT(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count));
  581. if (index < -1)
  582. index = -1;
  583. else if (index > static_cast<int32_t>(pData->midiprog.count))
  584. return;
  585. // TODO
  586. //if ((fHints & PLUGIN_IS_SYNTH) != 0 && (pData->ctrlChannel < 0 || pData->ctrlChannel >= MAX_MIDI_CHANNELS))
  587. // return;
  588. if (index >= 0)
  589. {
  590. const uint8_t channel = (pData->ctrlChannel >= 0 || pData->ctrlChannel < MAX_MIDI_CHANNELS) ? pData->ctrlChannel : 0;
  591. const uint32_t bank = pData->midiprog.data[index].bank;
  592. const uint32_t program = pData->midiprog.data[index].program;
  593. const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
  594. fDescriptor->set_midi_program(fHandle, channel, bank, program);
  595. if (fHandle2 != nullptr)
  596. fDescriptor->set_midi_program(fHandle2, channel, bank, program);
  597. fCurMidiProgs[channel] = index;
  598. }
  599. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
  600. }
  601. // -------------------------------------------------------------------
  602. // Set gui stuff
  603. void showGui(const bool yesNo) override
  604. {
  605. CARLA_ASSERT(fDescriptor != nullptr);
  606. CARLA_ASSERT(fHandle != nullptr);
  607. if (fDescriptor->ui_show == nullptr)
  608. return;
  609. fDescriptor->ui_show(fHandle, yesNo);
  610. fIsUiVisible = yesNo;
  611. if (! yesNo)
  612. return;
  613. if (fDescriptor->ui_set_custom_data != nullptr)
  614. {
  615. for (NonRtList<CustomData>::Itenerator it = pData->custom.begin(); it.valid(); it.next())
  616. {
  617. const CustomData& cData(*it);
  618. if (std::strcmp(cData.type, CUSTOM_DATA_STRING) == 0 && std::strcmp(cData.key, "midiPrograms") != 0)
  619. fDescriptor->ui_set_custom_data(fHandle, cData.key, cData.value);
  620. }
  621. }
  622. if (fDescriptor->ui_set_midi_program != nullptr && pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  623. {
  624. const uint32_t index = pData->midiprog.current;
  625. const uint8_t channel = (pData->ctrlChannel >= 0 || pData->ctrlChannel < MAX_MIDI_CHANNELS) ? pData->ctrlChannel : 0;
  626. const uint32_t bank = pData->midiprog.data[index].bank;
  627. const uint32_t program = pData->midiprog.data[index].program;
  628. fDescriptor->ui_set_midi_program(fHandle, channel, bank, program);
  629. }
  630. if (fDescriptor->ui_set_parameter_value != nullptr)
  631. {
  632. for (uint32_t i=0; i < pData->param.count; ++i)
  633. fDescriptor->ui_set_parameter_value(fHandle, i, fDescriptor->get_parameter_value(fHandle, i));
  634. }
  635. }
  636. void idleGui() override
  637. {
  638. CARLA_ASSERT(fDescriptor != nullptr);
  639. CARLA_ASSERT(fHandle != nullptr);
  640. if (fIsUiVisible && fDescriptor->ui_idle != nullptr)
  641. fDescriptor->ui_idle(fHandle);
  642. }
  643. // -------------------------------------------------------------------
  644. // Plugin state
  645. void reload() override
  646. {
  647. carla_debug("NativePlugin::reload() - start");
  648. CARLA_ASSERT(pData->engine != nullptr);
  649. CARLA_ASSERT(fDescriptor != nullptr);
  650. CARLA_ASSERT(fHandle != nullptr);
  651. if (pData->engine == nullptr)
  652. return;
  653. if (fDescriptor == nullptr)
  654. return;
  655. if (fHandle == nullptr)
  656. return;
  657. const ProcessMode processMode(pData->engine->getProccessMode());
  658. // Safely disable plugin for reload
  659. const ScopedDisabler sd(this);
  660. if (pData->active)
  661. deactivate();
  662. clearBuffers();
  663. const float sampleRate((float)pData->engine->getSampleRate());
  664. uint32_t aIns, aOuts, mIns, mOuts, params, j;
  665. bool forcedStereoIn, forcedStereoOut;
  666. forcedStereoIn = forcedStereoOut = false;
  667. bool needsCtrlIn, needsCtrlOut;
  668. needsCtrlIn = needsCtrlOut = false;
  669. aIns = fDescriptor->audioIns;
  670. aOuts = fDescriptor->audioOuts;
  671. mIns = fDescriptor->midiIns;
  672. mOuts = fDescriptor->midiOuts;
  673. params = (fDescriptor->get_parameter_count != nullptr && fDescriptor->get_parameter_info != nullptr) ? fDescriptor->get_parameter_count(fHandle) : 0;
  674. if ((fOptions & PLUGIN_OPTION_FORCE_STEREO) != 0 && (aIns == 1 || aOuts == 1) && mIns <= 1 && mOuts <= 1)
  675. {
  676. if (fHandle2 == nullptr)
  677. fHandle2 = fDescriptor->instantiate(&fHost);
  678. if (fHandle2 != nullptr)
  679. {
  680. if (aIns == 1)
  681. {
  682. aIns = 2;
  683. forcedStereoIn = true;
  684. }
  685. if (aOuts == 1)
  686. {
  687. aOuts = 2;
  688. forcedStereoOut = true;
  689. }
  690. }
  691. }
  692. if (aIns > 0)
  693. {
  694. pData->audioIn.createNew(aIns);
  695. fAudioInBuffers = new float*[aIns];
  696. for (uint32_t i=0; i < aIns; ++i)
  697. fAudioInBuffers[i] = nullptr;
  698. }
  699. if (aOuts > 0)
  700. {
  701. pData->audioOut.createNew(aOuts);
  702. fAudioOutBuffers = new float*[aOuts];
  703. needsCtrlIn = true;
  704. for (uint32_t i=0; i < aOuts; ++i)
  705. fAudioOutBuffers[i] = nullptr;
  706. }
  707. if (mIns > 0)
  708. {
  709. fMidiIn.createNew(mIns);
  710. needsCtrlIn = (mIns == 1);
  711. }
  712. if (mOuts > 0)
  713. {
  714. fMidiOut.createNew(mOuts);
  715. needsCtrlOut = (mOuts == 1);
  716. }
  717. if (params > 0)
  718. {
  719. pData->param.createNew(params);
  720. }
  721. const uint portNameSize(pData->engine->getMaxPortNameSize());
  722. CarlaString portName;
  723. // Audio Ins
  724. for (j=0; j < aIns; ++j)
  725. {
  726. portName.clear();
  727. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  728. {
  729. portName = fName;
  730. portName += ":";
  731. }
  732. if (aIns > 1 && ! forcedStereoIn)
  733. {
  734. portName += "input_";
  735. portName += CarlaString(j+1);
  736. }
  737. else
  738. portName += "input";
  739. portName.truncate(portNameSize);
  740. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  741. pData->audioIn.ports[j].rindex = j;
  742. if (forcedStereoIn)
  743. {
  744. portName += "_2";
  745. pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  746. pData->audioIn.ports[1].rindex = j;
  747. break;
  748. }
  749. }
  750. // Audio Outs
  751. for (j=0; j < aOuts; ++j)
  752. {
  753. portName.clear();
  754. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  755. {
  756. portName = fName;
  757. portName += ":";
  758. }
  759. if (aOuts > 1 && ! forcedStereoOut)
  760. {
  761. portName += "output_";
  762. portName += CarlaString(j+1);
  763. }
  764. else
  765. portName += "output";
  766. portName.truncate(portNameSize);
  767. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  768. pData->audioOut.ports[j].rindex = j;
  769. if (forcedStereoOut)
  770. {
  771. portName += "_2";
  772. pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  773. pData->audioOut.ports[1].rindex = j;
  774. break;
  775. }
  776. }
  777. // MIDI Input (only if multiple)
  778. if (mIns > 1)
  779. {
  780. for (j=0; j < mIns; ++j)
  781. {
  782. portName.clear();
  783. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  784. {
  785. portName = fName;
  786. portName += ":";
  787. }
  788. portName += "midi-in_";
  789. portName += CarlaString(j+1);
  790. portName.truncate(portNameSize);
  791. fMidiIn.ports[j] = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true);
  792. fMidiIn.indexes[j] = j;
  793. }
  794. }
  795. // MIDI Output (only if multiple)
  796. if (mOuts > 1)
  797. {
  798. for (j=0; j < mOuts; ++j)
  799. {
  800. portName.clear();
  801. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  802. {
  803. portName = fName;
  804. portName += ":";
  805. }
  806. portName += "midi-out_";
  807. portName += CarlaString(j+1);
  808. portName.truncate(portNameSize);
  809. fMidiOut.ports[j] = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false);
  810. fMidiOut.indexes[j] = j;
  811. }
  812. }
  813. for (j=0; j < params; ++j)
  814. {
  815. const ::Parameter* const paramInfo(fDescriptor->get_parameter_info(fHandle, j));
  816. CARLA_ASSERT(paramInfo != nullptr);
  817. if (paramInfo == nullptr)
  818. continue;
  819. pData->param.data[j].index = j;
  820. pData->param.data[j].rindex = j;
  821. pData->param.data[j].hints = 0x0;
  822. pData->param.data[j].midiChannel = 0;
  823. pData->param.data[j].midiCC = -1;
  824. float min, max, def, step, stepSmall, stepLarge;
  825. // min value
  826. min = paramInfo->ranges.min;
  827. // max value
  828. max = paramInfo->ranges.max;
  829. if (min > max)
  830. max = min;
  831. else if (max < min)
  832. min = max;
  833. if (max - min == 0.0f)
  834. {
  835. carla_stderr2("WARNING - Broken plugin parameter '%s': max - min == 0.0f", paramInfo->name);
  836. max = min + 0.1f;
  837. }
  838. // default value
  839. def = paramInfo->ranges.def;
  840. if (def < min)
  841. def = min;
  842. else if (def > max)
  843. def = max;
  844. if (paramInfo->hints & ::PARAMETER_USES_SAMPLE_RATE)
  845. {
  846. min *= sampleRate;
  847. max *= sampleRate;
  848. def *= sampleRate;
  849. pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
  850. }
  851. if (paramInfo->hints & ::PARAMETER_IS_BOOLEAN)
  852. {
  853. step = max - min;
  854. stepSmall = step;
  855. stepLarge = step;
  856. pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
  857. }
  858. else if (paramInfo->hints & ::PARAMETER_IS_INTEGER)
  859. {
  860. step = 1.0f;
  861. stepSmall = 1.0f;
  862. stepLarge = 10.0f;
  863. pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
  864. }
  865. else
  866. {
  867. float range = max - min;
  868. step = range/100.0f;
  869. stepSmall = range/1000.0f;
  870. stepLarge = range/10.0f;
  871. }
  872. if (paramInfo->hints & ::PARAMETER_IS_OUTPUT)
  873. {
  874. pData->param.data[j].type = PARAMETER_OUTPUT;
  875. needsCtrlOut = true;
  876. }
  877. else
  878. {
  879. pData->param.data[j].type = PARAMETER_INPUT;
  880. needsCtrlIn = true;
  881. }
  882. // extra parameter hints
  883. if (paramInfo->hints & ::PARAMETER_IS_ENABLED)
  884. pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  885. if (paramInfo->hints & ::PARAMETER_IS_AUTOMABLE)
  886. pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
  887. if (paramInfo->hints & ::PARAMETER_IS_LOGARITHMIC)
  888. pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
  889. if (paramInfo->hints & ::PARAMETER_USES_SCALEPOINTS)
  890. pData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS;
  891. if (paramInfo->hints & ::PARAMETER_USES_CUSTOM_TEXT)
  892. pData->param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT;
  893. pData->param.ranges[j].min = min;
  894. pData->param.ranges[j].max = max;
  895. pData->param.ranges[j].def = def;
  896. pData->param.ranges[j].step = step;
  897. pData->param.ranges[j].stepSmall = stepSmall;
  898. pData->param.ranges[j].stepLarge = stepLarge;
  899. }
  900. if (needsCtrlIn)
  901. {
  902. portName.clear();
  903. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  904. {
  905. portName = fName;
  906. portName += ":";
  907. }
  908. portName += "events-in";
  909. portName.truncate(portNameSize);
  910. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true);
  911. }
  912. if (needsCtrlOut)
  913. {
  914. portName.clear();
  915. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  916. {
  917. portName = fName;
  918. portName += ":";
  919. }
  920. portName += "events-out";
  921. portName.truncate(portNameSize);
  922. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false);
  923. }
  924. if (forcedStereoIn || forcedStereoOut)
  925. fOptions |= PLUGIN_OPTION_FORCE_STEREO;
  926. else
  927. fOptions &= ~PLUGIN_OPTION_FORCE_STEREO;
  928. // plugin hints
  929. fHints = 0x0;
  930. if (aOuts > 0 && (aIns == aOuts || aIns == 1))
  931. fHints |= PLUGIN_CAN_DRYWET;
  932. if (aOuts > 0)
  933. fHints |= PLUGIN_CAN_VOLUME;
  934. if (aOuts >= 2 && aOuts % 2 == 0)
  935. fHints |= PLUGIN_CAN_BALANCE;
  936. // native plugin hints
  937. if (fDescriptor->hints & ::PLUGIN_IS_RTSAFE)
  938. fHints |= PLUGIN_IS_RTSAFE;
  939. if (fDescriptor->hints & ::PLUGIN_HAS_GUI)
  940. fHints |= PLUGIN_HAS_GUI;
  941. if (fDescriptor->hints & ::PLUGIN_NEEDS_SINGLE_THREAD)
  942. fHints |= PLUGIN_NEEDS_SINGLE_THREAD;
  943. if (fDescriptor->hints & ::PLUGIN_NEEDS_FIXED_BUFFERS)
  944. fHints |= PLUGIN_NEEDS_FIXED_BUFFERS;
  945. // extra plugin hints
  946. pData->extraHints = 0x0;
  947. if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0) && mIns <= 1 && mOuts <= 1)
  948. pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
  949. bufferSizeChanged(pData->engine->getBufferSize());
  950. reloadPrograms(true);
  951. if (pData->active)
  952. activate();
  953. carla_debug("NativePlugin::reload() - end");
  954. }
  955. void reloadPrograms(const bool init) override
  956. {
  957. carla_debug("NativePlugin::reloadPrograms(%s)", bool2str(init));
  958. uint32_t i, oldCount = pData->midiprog.count;
  959. const int32_t current = pData->midiprog.current;
  960. // Delete old programs
  961. pData->midiprog.clear();
  962. // Query new programs
  963. uint32_t count = 0;
  964. if (fDescriptor->get_midi_program_count != nullptr && fDescriptor->get_midi_program_info != nullptr && fDescriptor->set_midi_program != nullptr)
  965. count = fDescriptor->get_midi_program_count(fHandle);
  966. if (count > 0)
  967. {
  968. pData->midiprog.createNew(count);
  969. // Update data
  970. for (i=0; i < count; ++i)
  971. {
  972. const ::MidiProgram* const mpDesc = fDescriptor->get_midi_program_info(fHandle, i);
  973. CARLA_ASSERT(mpDesc != nullptr);
  974. CARLA_ASSERT(mpDesc->name != nullptr);
  975. pData->midiprog.data[i].bank = mpDesc->bank;
  976. pData->midiprog.data[i].program = mpDesc->program;
  977. pData->midiprog.data[i].name = carla_strdup(mpDesc->name);
  978. }
  979. }
  980. #ifndef BUILD_BRIDGE
  981. // Update OSC Names
  982. if (pData->engine->isOscControlRegistered())
  983. {
  984. pData->engine->oscSend_control_set_midi_program_count(fId, count);
  985. for (i=0; i < count; ++i)
  986. pData->engine->oscSend_control_set_midi_program_data(fId, i, pData->midiprog.data[i].bank, pData->midiprog.data[i].program, pData->midiprog.data[i].name);
  987. }
  988. #endif
  989. if (init)
  990. {
  991. if (count > 0)
  992. setMidiProgram(0, false, false, false);
  993. }
  994. else
  995. {
  996. // Check if current program is invalid
  997. bool programChanged = false;
  998. if (count == oldCount+1)
  999. {
  1000. // one midi program added, probably created by user
  1001. pData->midiprog.current = oldCount;
  1002. programChanged = true;
  1003. }
  1004. else if (current < 0 && count > 0)
  1005. {
  1006. // programs exist now, but not before
  1007. pData->midiprog.current = 0;
  1008. programChanged = true;
  1009. }
  1010. else if (current >= 0 && count == 0)
  1011. {
  1012. // programs existed before, but not anymore
  1013. pData->midiprog.current = -1;
  1014. programChanged = true;
  1015. }
  1016. else if (current >= static_cast<int32_t>(count))
  1017. {
  1018. // current midi program > count
  1019. pData->midiprog.current = 0;
  1020. programChanged = true;
  1021. }
  1022. else
  1023. {
  1024. // no change
  1025. pData->midiprog.current = current;
  1026. }
  1027. if (programChanged)
  1028. setMidiProgram(pData->midiprog.current, true, true, true);
  1029. pData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);
  1030. }
  1031. }
  1032. // -------------------------------------------------------------------
  1033. // Plugin processing
  1034. void activate() override
  1035. {
  1036. CARLA_ASSERT(fDescriptor != nullptr);
  1037. CARLA_ASSERT(fHandle != nullptr);
  1038. if (fDescriptor->activate != nullptr)
  1039. {
  1040. fDescriptor->activate(fHandle);
  1041. if (fHandle2 != nullptr)
  1042. fDescriptor->activate(fHandle2);
  1043. }
  1044. }
  1045. void deactivate() override
  1046. {
  1047. CARLA_ASSERT(fDescriptor != nullptr);
  1048. CARLA_ASSERT(fHandle != nullptr);
  1049. if (fDescriptor->deactivate != nullptr)
  1050. {
  1051. fDescriptor->deactivate(fHandle);
  1052. if (fHandle2 != nullptr)
  1053. fDescriptor->deactivate(fHandle2);
  1054. }
  1055. }
  1056. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override
  1057. {
  1058. uint32_t i, k;
  1059. // --------------------------------------------------------------------------------------------------------
  1060. // Check if active
  1061. if (! pData->active)
  1062. {
  1063. // disable any output sound
  1064. for (i=0; i < pData->audioOut.count; ++i)
  1065. carla_zeroFloat(outBuffer[i], frames);
  1066. return;
  1067. }
  1068. fMidiEventCount = 0;
  1069. carla_zeroStruct< ::MidiEvent>(fMidiEvents, kPluginMaxMidiEvents*2);
  1070. // --------------------------------------------------------------------------------------------------------
  1071. // Check if needs reset
  1072. if (pData->needsReset)
  1073. {
  1074. if (fOptions & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1075. {
  1076. for (k=0, i=MAX_MIDI_CHANNELS; k < MAX_MIDI_CHANNELS; ++k)
  1077. {
  1078. fMidiEvents[k].data[0] = MIDI_STATUS_CONTROL_CHANGE + k;
  1079. fMidiEvents[k].data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
  1080. fMidiEvents[k].data[2] = 0;
  1081. fMidiEvents[k].size = 3;
  1082. fMidiEvents[k+i].data[0] = MIDI_STATUS_CONTROL_CHANGE + k;
  1083. fMidiEvents[k+i].data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
  1084. fMidiEvents[k+i].data[2] = 0;
  1085. fMidiEvents[k+i].size = 3;
  1086. }
  1087. fMidiEventCount = MAX_MIDI_CHANNELS*2;
  1088. }
  1089. else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
  1090. {
  1091. for (k=0; k < MAX_MIDI_NOTE; ++k)
  1092. {
  1093. fMidiEvents[k].data[0] = MIDI_STATUS_NOTE_OFF + pData->ctrlChannel;
  1094. fMidiEvents[k].data[1] = k;
  1095. fMidiEvents[k].data[2] = 0;
  1096. fMidiEvents[k].size = 3;
  1097. }
  1098. fMidiEventCount = MAX_MIDI_NOTE;
  1099. }
  1100. pData->needsReset = false;
  1101. }
  1102. CARLA_PROCESS_CONTINUE_CHECK;
  1103. // --------------------------------------------------------------------------------------------------------
  1104. // Set TimeInfo
  1105. const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
  1106. fTimeInfo.playing = timeInfo.playing;
  1107. fTimeInfo.frame = timeInfo.frame;
  1108. fTimeInfo.usecs = timeInfo.usecs;
  1109. if (timeInfo.valid & EngineTimeInfo::ValidBBT)
  1110. {
  1111. fTimeInfo.bbt.valid = true;
  1112. fTimeInfo.bbt.bar = timeInfo.bbt.bar;
  1113. fTimeInfo.bbt.beat = timeInfo.bbt.beat;
  1114. fTimeInfo.bbt.tick = timeInfo.bbt.tick;
  1115. fTimeInfo.bbt.barStartTick = timeInfo.bbt.barStartTick;
  1116. fTimeInfo.bbt.beatsPerBar = timeInfo.bbt.beatsPerBar;
  1117. fTimeInfo.bbt.beatType = timeInfo.bbt.beatType;
  1118. fTimeInfo.bbt.ticksPerBeat = timeInfo.bbt.ticksPerBeat;
  1119. fTimeInfo.bbt.beatsPerMinute = timeInfo.bbt.beatsPerMinute;
  1120. }
  1121. else
  1122. fTimeInfo.bbt.valid = false;
  1123. CARLA_PROCESS_CONTINUE_CHECK;
  1124. // --------------------------------------------------------------------------------------------------------
  1125. // Event Input and Processing
  1126. if (pData->event.portIn != nullptr)
  1127. {
  1128. // ----------------------------------------------------------------------------------------------------
  1129. // MIDI Input (External)
  1130. if (pData->extNotes.mutex.tryLock())
  1131. {
  1132. while (fMidiEventCount < kPluginMaxMidiEvents*2 && ! pData->extNotes.data.isEmpty())
  1133. {
  1134. const ExternalMidiNote& note(pData->extNotes.data.getFirst(true));
  1135. CARLA_ASSERT(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  1136. fMidiEvents[fMidiEventCount].data[0] = (note.velo > 0) ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF;
  1137. fMidiEvents[fMidiEventCount].data[0] += note.channel;
  1138. fMidiEvents[fMidiEventCount].data[1] = note.note;
  1139. fMidiEvents[fMidiEventCount].data[2] = note.velo;
  1140. fMidiEvents[fMidiEventCount].size = 3;
  1141. fMidiEventCount += 1;
  1142. }
  1143. pData->extNotes.mutex.unlock();
  1144. } // End of MIDI Input (External)
  1145. // ----------------------------------------------------------------------------------------------------
  1146. // Event Input (System)
  1147. bool allNotesOffSent = false;
  1148. bool sampleAccurate = (fOptions & PLUGIN_OPTION_FIXED_BUFFERS) == 0;
  1149. uint32_t time, nEvents = pData->event.portIn->getEventCount();
  1150. uint32_t startTime = 0;
  1151. uint32_t timeOffset = 0;
  1152. uint32_t nextBankId = 0;
  1153. if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  1154. nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
  1155. for (i=0; i < nEvents; ++i)
  1156. {
  1157. const EngineEvent& event(pData->event.portIn->getEvent(i));
  1158. time = event.time;
  1159. if (time >= frames)
  1160. continue;
  1161. CARLA_ASSERT_INT2(time >= timeOffset, time, timeOffset);
  1162. if (time > timeOffset && sampleAccurate)
  1163. {
  1164. if (processSingle(inBuffer, outBuffer, time - timeOffset, timeOffset))
  1165. {
  1166. startTime = 0;
  1167. timeOffset = time;
  1168. if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  1169. nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
  1170. else
  1171. nextBankId = 0;
  1172. if (fMidiEventCount > 0)
  1173. {
  1174. carla_zeroStruct< ::MidiEvent>(fMidiEvents, fMidiEventCount);
  1175. fMidiEventCount = 0;
  1176. }
  1177. }
  1178. else
  1179. startTime += timeOffset;
  1180. }
  1181. // Control change
  1182. switch (event.type)
  1183. {
  1184. case kEngineEventTypeNull:
  1185. break;
  1186. case kEngineEventTypeControl:
  1187. {
  1188. const EngineControlEvent& ctrlEvent = event.ctrl;
  1189. switch (ctrlEvent.type)
  1190. {
  1191. case kEngineControlEventTypeNull:
  1192. break;
  1193. case kEngineControlEventTypeParameter:
  1194. {
  1195. #ifndef BUILD_BRIDGE
  1196. // Control backend stuff
  1197. if (event.channel == pData->ctrlChannel)
  1198. {
  1199. float value;
  1200. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (fHints & PLUGIN_CAN_DRYWET) > 0)
  1201. {
  1202. value = ctrlEvent.value;
  1203. setDryWet(value, false, false);
  1204. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  1205. }
  1206. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (fHints & PLUGIN_CAN_VOLUME) > 0)
  1207. {
  1208. value = ctrlEvent.value*127.0f/100.0f;
  1209. setVolume(value, false, false);
  1210. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  1211. }
  1212. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (fHints & PLUGIN_CAN_BALANCE) > 0)
  1213. {
  1214. float left, right;
  1215. value = ctrlEvent.value/0.5f - 1.0f;
  1216. if (value < 0.0f)
  1217. {
  1218. left = -1.0f;
  1219. right = (value*2.0f)+1.0f;
  1220. }
  1221. else if (value > 0.0f)
  1222. {
  1223. left = (value*2.0f)-1.0f;
  1224. right = 1.0f;
  1225. }
  1226. else
  1227. {
  1228. left = -1.0f;
  1229. right = 1.0f;
  1230. }
  1231. setBalanceLeft(left, false, false);
  1232. setBalanceRight(right, false, false);
  1233. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  1234. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  1235. }
  1236. }
  1237. #endif
  1238. // Control plugin parameters
  1239. for (k=0; k < pData->param.count; ++k)
  1240. {
  1241. if (pData->param.data[k].midiChannel != event.channel)
  1242. continue;
  1243. if (pData->param.data[k].midiCC != ctrlEvent.param)
  1244. continue;
  1245. if (pData->param.data[k].type != PARAMETER_INPUT)
  1246. continue;
  1247. if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
  1248. continue;
  1249. float value;
  1250. if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN)
  1251. {
  1252. value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max;
  1253. }
  1254. else
  1255. {
  1256. value = pData->param.ranges[k].getUnnormalizedValue(ctrlEvent.value);
  1257. if (pData->param.data[k].hints & PARAMETER_IS_INTEGER)
  1258. value = std::rint(value);
  1259. }
  1260. setParameterValue(k, value, false, false, false);
  1261. pData->postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value);
  1262. }
  1263. if ((fOptions & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F)
  1264. {
  1265. if (fMidiEventCount >= kPluginMaxMidiEvents*2)
  1266. continue;
  1267. fMidiEvents[fMidiEventCount].port = 0;
  1268. fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time;
  1269. fMidiEvents[fMidiEventCount].data[0] = MIDI_STATUS_CONTROL_CHANGE + event.channel;
  1270. fMidiEvents[fMidiEventCount].data[1] = ctrlEvent.param;
  1271. fMidiEvents[fMidiEventCount].data[2] = ctrlEvent.value*127.0f;
  1272. fMidiEvents[fMidiEventCount].size = 3;
  1273. fMidiEventCount += 1;
  1274. }
  1275. break;
  1276. }
  1277. case kEngineControlEventTypeMidiBank:
  1278. if (event.channel == pData->ctrlChannel && (fOptions & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  1279. nextBankId = ctrlEvent.param;
  1280. break;
  1281. case kEngineControlEventTypeMidiProgram:
  1282. if (event.channel < MAX_MIDI_CHANNELS && (fOptions & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  1283. {
  1284. const uint32_t nextProgramId(ctrlEvent.param);
  1285. for (k=0; k < pData->midiprog.count; ++k)
  1286. {
  1287. if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId)
  1288. {
  1289. fDescriptor->set_midi_program(fHandle, event.channel, nextBankId, nextProgramId);
  1290. if (fHandle2 != nullptr)
  1291. fDescriptor->set_midi_program(fHandle2, event.channel, nextBankId, nextProgramId);
  1292. fCurMidiProgs[event.channel] = k;
  1293. if (event.channel == pData->ctrlChannel)
  1294. pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0f);
  1295. break;
  1296. }
  1297. }
  1298. }
  1299. break;
  1300. case kEngineControlEventTypeAllSoundOff:
  1301. if (fOptions & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1302. {
  1303. if (fMidiEventCount >= kPluginMaxMidiEvents*2)
  1304. continue;
  1305. fMidiEvents[fMidiEventCount].port = 0;
  1306. fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time;
  1307. fMidiEvents[fMidiEventCount].data[0] = MIDI_STATUS_CONTROL_CHANGE + event.channel;
  1308. fMidiEvents[fMidiEventCount].data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
  1309. fMidiEvents[fMidiEventCount].data[2] = 0;
  1310. fMidiEvents[fMidiEventCount].size = 3;
  1311. fMidiEventCount += 1;
  1312. }
  1313. break;
  1314. case kEngineControlEventTypeAllNotesOff:
  1315. if (fOptions & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1316. {
  1317. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  1318. {
  1319. allNotesOffSent = true;
  1320. sendMidiAllNotesOffToCallback();
  1321. }
  1322. if (fMidiEventCount >= kPluginMaxMidiEvents*2)
  1323. continue;
  1324. fMidiEvents[fMidiEventCount].port = 0;
  1325. fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time;
  1326. fMidiEvents[fMidiEventCount].data[0] = MIDI_STATUS_CONTROL_CHANGE + event.channel;
  1327. fMidiEvents[fMidiEventCount].data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
  1328. fMidiEvents[fMidiEventCount].data[2] = 0;
  1329. fMidiEvents[fMidiEventCount].size = 3;
  1330. fMidiEventCount += 1;
  1331. }
  1332. break;
  1333. }
  1334. break;
  1335. }
  1336. case kEngineEventTypeMidi:
  1337. {
  1338. if (fMidiEventCount >= kPluginMaxMidiEvents*2)
  1339. continue;
  1340. const EngineMidiEvent& midiEvent(event.midi);
  1341. uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
  1342. uint8_t channel = event.channel;
  1343. if (MIDI_IS_STATUS_CHANNEL_PRESSURE(status) && (fOptions & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
  1344. continue;
  1345. if (MIDI_IS_STATUS_CONTROL_CHANGE(status) && (fOptions & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
  1346. continue;
  1347. if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) && (fOptions & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  1348. continue;
  1349. if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) && (fOptions & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
  1350. continue;
  1351. // Fix bad note-off
  1352. if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
  1353. status -= 0x10;
  1354. fMidiEvents[fMidiEventCount].port = 0;
  1355. fMidiEvents[fMidiEventCount].time = sampleAccurate ? startTime : time;
  1356. fMidiEvents[fMidiEventCount].size = midiEvent.size;
  1357. fMidiEvents[fMidiEventCount].data[0] = status + channel;
  1358. fMidiEvents[fMidiEventCount].data[1] = midiEvent.data[1];
  1359. fMidiEvents[fMidiEventCount].data[2] = midiEvent.data[2];
  1360. fMidiEvents[fMidiEventCount].data[3] = midiEvent.data[3];
  1361. fMidiEventCount += 1;
  1362. if (status == MIDI_STATUS_NOTE_ON)
  1363. pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]);
  1364. else if (status == MIDI_STATUS_NOTE_OFF)
  1365. pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, midiEvent.data[1], 0.0f);
  1366. break;
  1367. }
  1368. }
  1369. }
  1370. pData->postRtEvents.trySplice();
  1371. if (frames > timeOffset)
  1372. processSingle(inBuffer, outBuffer, frames - timeOffset, timeOffset);
  1373. } // End of Event Input and Processing
  1374. // --------------------------------------------------------------------------------------------------------
  1375. // Plugin processing (no events)
  1376. else
  1377. {
  1378. processSingle(inBuffer, outBuffer, frames, 0);
  1379. } // End of Plugin processing (no events)
  1380. CARLA_PROCESS_CONTINUE_CHECK;
  1381. // --------------------------------------------------------------------------------------------------------
  1382. // Control and MIDI Output
  1383. if (fMidiOut.count > 0 || pData->event.portOut != nullptr)
  1384. {
  1385. float value, curValue;
  1386. for (k=0; k < pData->param.count; ++k)
  1387. {
  1388. if (pData->param.data[k].type != PARAMETER_OUTPUT)
  1389. continue;
  1390. curValue = fDescriptor->get_parameter_value(fHandle, k);
  1391. pData->param.ranges[k].fixValue(curValue);
  1392. if (pData->param.data[k].midiCC > 0)
  1393. {
  1394. value = pData->param.ranges[k].getNormalizedValue(curValue);
  1395. pData->event.portOut->writeControlEvent(0, pData->param.data[k].midiChannel, kEngineControlEventTypeParameter, pData->param.data[k].midiCC, value);
  1396. }
  1397. }
  1398. // reverse lookup MIDI events
  1399. for (k = (kPluginMaxMidiEvents*2)-1; k >= fMidiEventCount; --k)
  1400. {
  1401. if (fMidiEvents[k].data[0] == 0)
  1402. break;
  1403. const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(fMidiEvents[k].data);
  1404. const uint8_t port = fMidiEvents[k].port;
  1405. if (pData->event.portOut != nullptr)
  1406. pData->event.portOut->writeMidiEvent(fMidiEvents[k].time, channel, port, fMidiEvents[k].data, fMidiEvents[k].size);
  1407. else if (port < fMidiOut.count)
  1408. fMidiOut.ports[port]->writeMidiEvent(fMidiEvents[k].time, channel, port, fMidiEvents[k].data, fMidiEvents[k].size);
  1409. }
  1410. } // End of Control and MIDI Output
  1411. }
  1412. bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset)
  1413. {
  1414. CARLA_ASSERT(frames > 0);
  1415. if (frames == 0)
  1416. return false;
  1417. if (pData->audioIn.count > 0)
  1418. {
  1419. CARLA_ASSERT(inBuffer != nullptr);
  1420. if (inBuffer == nullptr)
  1421. return false;
  1422. }
  1423. if (pData->audioOut.count > 0)
  1424. {
  1425. CARLA_ASSERT(outBuffer != nullptr);
  1426. if (outBuffer == nullptr)
  1427. return false;
  1428. }
  1429. uint32_t i, k;
  1430. // --------------------------------------------------------------------------------------------------------
  1431. // Try lock, silence otherwise
  1432. if (pData->engine->isOffline())
  1433. {
  1434. pData->singleMutex.lock();
  1435. }
  1436. else if (! pData->singleMutex.tryLock())
  1437. {
  1438. for (i=0; i < pData->audioOut.count; ++i)
  1439. {
  1440. for (k=0; k < frames; ++k)
  1441. outBuffer[i][k+timeOffset] = 0.0f;
  1442. }
  1443. return false;
  1444. }
  1445. // --------------------------------------------------------------------------------------------------------
  1446. // Reset audio buffers
  1447. for (i=0; i < pData->audioIn.count; ++i)
  1448. carla_copyFloat(fAudioInBuffers[i], inBuffer[i]+timeOffset, frames);
  1449. for (i=0; i < pData->audioOut.count; ++i)
  1450. carla_zeroFloat(fAudioOutBuffers[i], frames);
  1451. // --------------------------------------------------------------------------------------------------------
  1452. // Run plugin
  1453. fIsProcessing = true;
  1454. if (fHandle2 == nullptr)
  1455. {
  1456. fDescriptor->process(fHandle, fAudioInBuffers, fAudioOutBuffers, frames, fMidiEvents, fMidiEventCount);
  1457. }
  1458. else
  1459. {
  1460. fDescriptor->process(fHandle,
  1461. (pData->audioIn.count > 0) ? &fAudioInBuffers[0] : nullptr,
  1462. (pData->audioOut.count > 0) ? &fAudioOutBuffers[0] : nullptr,
  1463. frames, fMidiEvents, fMidiEventCount);
  1464. fDescriptor->process(fHandle2,
  1465. (pData->audioIn.count > 0) ? &fAudioInBuffers[1] : nullptr,
  1466. (pData->audioOut.count > 0) ? &fAudioOutBuffers[1] : nullptr,
  1467. frames, fMidiEvents, fMidiEventCount);
  1468. }
  1469. fIsProcessing = false;
  1470. fTimeInfo.frame += frames;
  1471. #ifndef BUILD_BRIDGE
  1472. // --------------------------------------------------------------------------------------------------------
  1473. // Post-processing (dry/wet, volume and balance)
  1474. {
  1475. const bool doDryWet = (fHints & PLUGIN_CAN_DRYWET) != 0 && pData->postProc.dryWet != 1.0f;
  1476. const bool doBalance = (fHints & PLUGIN_CAN_BALANCE) != 0 && (pData->postProc.balanceLeft != -1.0f || pData->postProc.balanceRight != 1.0f);
  1477. bool isPair;
  1478. float bufValue, oldBufLeft[doBalance ? frames : 1];
  1479. for (i=0; i < pData->audioOut.count; ++i)
  1480. {
  1481. // Dry/Wet
  1482. if (doDryWet)
  1483. {
  1484. for (k=0; k < frames; ++k)
  1485. {
  1486. bufValue = fAudioInBuffers[(pData->audioIn.count == 1) ? 0 : i][k];
  1487. fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  1488. }
  1489. }
  1490. // Balance
  1491. if (doBalance)
  1492. {
  1493. isPair = (i % 2 == 0);
  1494. if (isPair)
  1495. {
  1496. CARLA_ASSERT(i+1 < pData->audioOut.count);
  1497. carla_copyFloat(oldBufLeft, fAudioOutBuffers[i], frames);
  1498. }
  1499. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  1500. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  1501. for (k=0; k < frames; ++k)
  1502. {
  1503. if (isPair)
  1504. {
  1505. // left
  1506. fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  1507. fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR);
  1508. }
  1509. else
  1510. {
  1511. // right
  1512. fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR;
  1513. fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
  1514. }
  1515. }
  1516. }
  1517. // Volume (and buffer copy)
  1518. {
  1519. for (k=0; k < frames; ++k)
  1520. outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume;
  1521. }
  1522. }
  1523. } // End of Post-processing
  1524. #else
  1525. for (i=0; i < pData->audioOut.count; ++i)
  1526. {
  1527. for (k=0; k < frames; ++k)
  1528. outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k];
  1529. }
  1530. #endif
  1531. // --------------------------------------------------------------------------------------------------------
  1532. pData->singleMutex.unlock();
  1533. return true;
  1534. }
  1535. void bufferSizeChanged(const uint32_t newBufferSize) override
  1536. {
  1537. CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
  1538. carla_debug("NativePlugin::bufferSizeChanged(%i)", newBufferSize);
  1539. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1540. {
  1541. if (fAudioInBuffers[i] != nullptr)
  1542. delete[] fAudioInBuffers[i];
  1543. fAudioInBuffers[i] = new float[newBufferSize];
  1544. }
  1545. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1546. {
  1547. if (fAudioOutBuffers[i] != nullptr)
  1548. delete[] fAudioOutBuffers[i];
  1549. fAudioOutBuffers[i] = new float[newBufferSize];
  1550. }
  1551. if (fDescriptor != nullptr && fDescriptor->dispatcher != nullptr)
  1552. {
  1553. fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, newBufferSize, nullptr, 0.0f);
  1554. if (fHandle2 != nullptr)
  1555. fDescriptor->dispatcher(fHandle2, PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, newBufferSize, nullptr, 0.0f);
  1556. }
  1557. }
  1558. void sampleRateChanged(const double newSampleRate) override
  1559. {
  1560. CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
  1561. carla_debug("NativePlugin::sampleRateChanged(%g)", newSampleRate);
  1562. if (fDescriptor != nullptr && fDescriptor->dispatcher != nullptr)
  1563. {
  1564. fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, newSampleRate);
  1565. if (fHandle2 != nullptr)
  1566. fDescriptor->dispatcher(fHandle2, PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, newSampleRate);
  1567. }
  1568. }
  1569. void offlineModeChanged(const bool isOffline) override
  1570. {
  1571. if (fDescriptor != nullptr && fDescriptor->dispatcher != nullptr)
  1572. {
  1573. fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_OFFLINE_CHANGED, 0, isOffline ? 1 : 0, nullptr, 0.0f);
  1574. if (fHandle2 != nullptr)
  1575. fDescriptor->dispatcher(fHandle2, PLUGIN_OPCODE_OFFLINE_CHANGED, 0, isOffline ? 1 : 0, nullptr, 0.0f);
  1576. }
  1577. }
  1578. // -------------------------------------------------------------------
  1579. // Plugin buffers
  1580. void initBuffers() override
  1581. {
  1582. fMidiIn.initBuffers();
  1583. fMidiOut.initBuffers();
  1584. CarlaPlugin::initBuffers();
  1585. }
  1586. void clearBuffers() override
  1587. {
  1588. carla_debug("NativePlugin::clearBuffers() - start");
  1589. if (fAudioInBuffers != nullptr)
  1590. {
  1591. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1592. {
  1593. if (fAudioInBuffers[i] != nullptr)
  1594. {
  1595. delete[] fAudioInBuffers[i];
  1596. fAudioInBuffers[i] = nullptr;
  1597. }
  1598. }
  1599. delete[] fAudioInBuffers;
  1600. fAudioInBuffers = nullptr;
  1601. }
  1602. if (fAudioOutBuffers != nullptr)
  1603. {
  1604. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1605. {
  1606. if (fAudioOutBuffers[i] != nullptr)
  1607. {
  1608. delete[] fAudioOutBuffers[i];
  1609. fAudioOutBuffers[i] = nullptr;
  1610. }
  1611. }
  1612. delete[] fAudioOutBuffers;
  1613. fAudioOutBuffers = nullptr;
  1614. }
  1615. fMidiIn.clear();
  1616. fMidiOut.clear();
  1617. CarlaPlugin::clearBuffers();
  1618. carla_debug("NativePlugin::clearBuffers() - end");
  1619. }
  1620. // -------------------------------------------------------------------
  1621. // Post-poned UI Stuff
  1622. void uiParameterChange(const uint32_t index, const float value) override
  1623. {
  1624. CARLA_ASSERT(fDescriptor != nullptr);
  1625. CARLA_ASSERT(fHandle != nullptr);
  1626. CARLA_ASSERT(index < pData->param.count);
  1627. if (! fIsUiVisible)
  1628. return;
  1629. if (fDescriptor == nullptr || fHandle == nullptr)
  1630. return;
  1631. if (index >= pData->param.count)
  1632. return;
  1633. if (fDescriptor->ui_set_parameter_value != nullptr)
  1634. fDescriptor->ui_set_parameter_value(fHandle, index, value);
  1635. }
  1636. void uiMidiProgramChange(const uint32_t index) override
  1637. {
  1638. CARLA_ASSERT(fDescriptor != nullptr);
  1639. CARLA_ASSERT(fHandle != nullptr);
  1640. CARLA_ASSERT(index < pData->midiprog.count);
  1641. if (! fIsUiVisible)
  1642. return;
  1643. if (fDescriptor == nullptr || fHandle == nullptr)
  1644. return;
  1645. if (index >= pData->midiprog.count)
  1646. return;
  1647. if (fDescriptor->ui_set_midi_program != nullptr) // TODO
  1648. fDescriptor->ui_set_midi_program(fHandle, 0, pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
  1649. }
  1650. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) override
  1651. {
  1652. CARLA_ASSERT(fDescriptor != nullptr);
  1653. CARLA_ASSERT(fHandle != nullptr);
  1654. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  1655. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  1656. CARLA_ASSERT(velo > 0 && velo < MAX_MIDI_VALUE);
  1657. if (! fIsUiVisible)
  1658. return;
  1659. if (fDescriptor == nullptr || fHandle == nullptr)
  1660. return;
  1661. if (channel >= MAX_MIDI_CHANNELS)
  1662. return;
  1663. if (note >= MAX_MIDI_NOTE)
  1664. return;
  1665. if (velo >= MAX_MIDI_VALUE)
  1666. return;
  1667. // TODO
  1668. }
  1669. void uiNoteOff(const uint8_t channel, const uint8_t note) override
  1670. {
  1671. CARLA_ASSERT(fDescriptor != nullptr);
  1672. CARLA_ASSERT(fHandle != nullptr);
  1673. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  1674. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  1675. if (! fIsUiVisible)
  1676. return;
  1677. if (fDescriptor == nullptr || fHandle == nullptr)
  1678. return;
  1679. if (channel >= MAX_MIDI_CHANNELS)
  1680. return;
  1681. if (note >= MAX_MIDI_NOTE)
  1682. return;
  1683. // TODO
  1684. }
  1685. // -------------------------------------------------------------------
  1686. protected:
  1687. uint32_t handleGetBufferSize()
  1688. {
  1689. return pData->engine->getBufferSize();
  1690. }
  1691. double handleGetSampleRate()
  1692. {
  1693. return pData->engine->getSampleRate();
  1694. }
  1695. bool handleIsOffline()
  1696. {
  1697. return pData->engine->isOffline();
  1698. }
  1699. const ::TimeInfo* handleGetTimeInfo()
  1700. {
  1701. CARLA_ASSERT(fIsProcessing);
  1702. return &fTimeInfo;
  1703. }
  1704. bool handleWriteMidiEvent(const ::MidiEvent* const event)
  1705. {
  1706. CARLA_ASSERT(fEnabled);
  1707. CARLA_ASSERT(fIsProcessing);
  1708. CARLA_ASSERT(fMidiOut.count > 0 || pData->event.portOut != nullptr);
  1709. CARLA_ASSERT(event != nullptr);
  1710. CARLA_ASSERT(event->data[0] != 0);
  1711. if (! fEnabled)
  1712. return false;
  1713. if (fMidiOut.count == 0)
  1714. return false;
  1715. if (event == nullptr)
  1716. return false;
  1717. if (event->data[0] == 0)
  1718. return false;
  1719. if (! fIsProcessing)
  1720. {
  1721. carla_stderr2("NativePlugin::handleWriteMidiEvent(%p) - received MIDI out event outside audio thread, ignoring", event);
  1722. return false;
  1723. }
  1724. // reverse-find first free event, and put it there
  1725. for (uint32_t i=(kPluginMaxMidiEvents*2)-1; i > fMidiEventCount; --i)
  1726. {
  1727. if (fMidiEvents[i].data[0] == 0)
  1728. {
  1729. std::memcpy(&fMidiEvents[i], event, sizeof(::MidiEvent));
  1730. return true;
  1731. }
  1732. }
  1733. return false;
  1734. }
  1735. void handleUiParameterChanged(const uint32_t index, const float value)
  1736. {
  1737. setParameterValue(index, value, false, true, true);
  1738. }
  1739. void handleUiCustomDataChanged(const char* const key, const char* const value)
  1740. {
  1741. setCustomData(CUSTOM_DATA_STRING, key, value, false);
  1742. }
  1743. void handleUiClosed()
  1744. {
  1745. pData->engine->callback(CALLBACK_SHOW_GUI, fId, 0, 0, 0.0f, nullptr);
  1746. fIsUiVisible = false;
  1747. }
  1748. const char* handleUiOpenFile(const bool isDir, const char* const title, const char* const filter)
  1749. {
  1750. static CarlaString retStr;
  1751. #if 0
  1752. QFileDialog::Options options(isDir ? QFileDialog::ShowDirsOnly : 0x0);
  1753. retStr = QFileDialog::getOpenFileName(nullptr, title, "", filter, nullptr, options).toUtf8().constData();
  1754. #endif
  1755. return retStr.isNotEmpty() ? (const char*)retStr : nullptr;
  1756. }
  1757. const char* handleUiSaveFile(const bool isDir, const char* const title, const char* const filter)
  1758. {
  1759. static CarlaString retStr;
  1760. #if 0
  1761. QFileDialog::Options options(isDir ? QFileDialog::ShowDirsOnly : 0x0);
  1762. retStr = QFileDialog::getSaveFileName(nullptr, title, "", filter, nullptr, options).toUtf8().constData();
  1763. #endif
  1764. return retStr.isNotEmpty() ? (const char*)retStr : nullptr;
  1765. }
  1766. intptr_t handleDispatcher(const ::HostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt)
  1767. {
  1768. carla_debug("NativePlugin::handleDispatcher(%i, %i, " P_INTPTR ", %p, %f)", opcode, index, value, ptr, opt);
  1769. intptr_t ret = 0;
  1770. switch (opcode)
  1771. {
  1772. case ::HOST_OPCODE_NULL:
  1773. break;
  1774. #ifdef BUILD_BRIDGE
  1775. case ::HOST_OPCODE_SET_VOLUME:
  1776. case ::HOST_OPCODE_SET_DRYWET:
  1777. case ::HOST_OPCODE_SET_BALANCE_LEFT:
  1778. case ::HOST_OPCODE_SET_BALANCE_RIGHT:
  1779. case ::HOST_OPCODE_SET_PANNING:
  1780. break;
  1781. #else
  1782. case ::HOST_OPCODE_SET_VOLUME:
  1783. setVolume(opt, true, true);
  1784. break;
  1785. case ::HOST_OPCODE_SET_DRYWET:
  1786. setDryWet(opt, true, true);
  1787. break;
  1788. case ::HOST_OPCODE_SET_BALANCE_LEFT:
  1789. setBalanceLeft(opt, true, true);
  1790. break;
  1791. case ::HOST_OPCODE_SET_BALANCE_RIGHT:
  1792. setBalanceRight(opt, true, true);
  1793. break;
  1794. case ::HOST_OPCODE_SET_PANNING:
  1795. setPanning(opt, true, true);
  1796. break;
  1797. #endif
  1798. case HOST_OPCODE_GET_PARAMETER_MIDI_CC:
  1799. case HOST_OPCODE_SET_PARAMETER_MIDI_CC:
  1800. // TODO
  1801. break;
  1802. case ::HOST_OPCODE_SET_PROCESS_PRECISION:
  1803. // TODO
  1804. break;
  1805. case ::HOST_OPCODE_UPDATE_PARAMETER:
  1806. break;
  1807. case ::HOST_OPCODE_UPDATE_MIDI_PROGRAM:
  1808. break;
  1809. case ::HOST_OPCODE_RELOAD_PARAMETERS:
  1810. break;
  1811. case ::HOST_OPCODE_RELOAD_MIDI_PROGRAMS:
  1812. break;
  1813. case ::HOST_OPCODE_RELOAD_ALL:
  1814. break;
  1815. case HOST_OPCODE_UI_UNAVAILABLE:
  1816. pData->engine->callback(CALLBACK_SHOW_GUI, fId, -1, 0, 0.0f, nullptr);
  1817. break;
  1818. }
  1819. return ret;
  1820. // unused for now
  1821. (void)index;
  1822. (void)value;
  1823. (void)ptr;
  1824. }
  1825. // -------------------------------------------------------------------
  1826. public:
  1827. static size_t getPluginCount()
  1828. {
  1829. return sPluginDescriptors.count();
  1830. }
  1831. static const ::PluginDescriptor* getPluginDescriptor(const size_t index)
  1832. {
  1833. CARLA_ASSERT(index < sPluginDescriptors.count());
  1834. if (index < sPluginDescriptors.count())
  1835. return sPluginDescriptors.getAt(index);
  1836. return nullptr;
  1837. }
  1838. static void registerPlugin(const ::PluginDescriptor* desc)
  1839. {
  1840. sPluginDescriptors.append(desc);
  1841. }
  1842. // -------------------------------------------------------------------
  1843. bool init(const char* const name, const char* const label)
  1844. {
  1845. CARLA_ASSERT(pData->engine != nullptr);
  1846. CARLA_ASSERT(pData->client == nullptr);
  1847. CARLA_ASSERT(label != nullptr);
  1848. // ---------------------------------------------------------------
  1849. // first checks
  1850. if (pData->engine == nullptr)
  1851. {
  1852. return false;
  1853. }
  1854. if (pData->client != nullptr)
  1855. {
  1856. pData->engine->setLastError("Plugin client is already registered");
  1857. return false;
  1858. }
  1859. if (label == nullptr)
  1860. {
  1861. pData->engine->setLastError("null label");
  1862. return false;
  1863. }
  1864. // ---------------------------------------------------------------
  1865. // get descriptor that matches label
  1866. for (NonRtList<const ::PluginDescriptor*>::Itenerator it = sPluginDescriptors.begin(); it.valid(); it.next())
  1867. {
  1868. fDescriptor = *it;
  1869. CARLA_ASSERT(fDescriptor != nullptr);
  1870. if (fDescriptor == nullptr)
  1871. break;
  1872. if (fDescriptor->label != nullptr && std::strcmp(fDescriptor->label, label) == 0)
  1873. break;
  1874. fDescriptor = nullptr;
  1875. }
  1876. if (fDescriptor == nullptr)
  1877. {
  1878. pData->engine->setLastError("Invalid internal plugin");
  1879. return false;
  1880. }
  1881. // ---------------------------------------------------------------
  1882. // set icon
  1883. if (std::strcmp(fDescriptor->label, "audiofile") == 0)
  1884. fIconName = "file";
  1885. else if (std::strcmp(fDescriptor->label, "midifile") == 0)
  1886. fIconName = "file";
  1887. else if (std::strcmp(fDescriptor->label, "sunvoxfile") == 0)
  1888. fIconName = "file";
  1889. else if (std::strcmp(fDescriptor->label, "3BandEQ") == 0)
  1890. fIconName = "distrho";
  1891. else if (std::strcmp(fDescriptor->label, "3BandSplitter") == 0)
  1892. fIconName = "distrho";
  1893. else if (std::strcmp(fDescriptor->label, "Nekobi") == 0)
  1894. fIconName = "distrho";
  1895. else if (std::strcmp(fDescriptor->label, "Notes") == 0)
  1896. fIconName = "distrho";
  1897. else if (std::strcmp(fDescriptor->label, "PingPongPan") == 0)
  1898. fIconName = "distrho";
  1899. else if (std::strcmp(fDescriptor->label, "StereoEnhancer") == 0)
  1900. fIconName = "distrho";
  1901. // ---------------------------------------------------------------
  1902. // get info
  1903. if (name != nullptr)
  1904. fName = pData->engine->getUniquePluginName(name);
  1905. else if (fDescriptor->name != nullptr)
  1906. fName = pData->engine->getUniquePluginName(fDescriptor->name);
  1907. else
  1908. fName = pData->engine->getUniquePluginName(label);
  1909. {
  1910. CARLA_ASSERT(fHost.uiName == nullptr);
  1911. char uiName[fName.length()+6+1];
  1912. std::strcpy(uiName, (const char*)fName);
  1913. std::strcat(uiName, " (GUI)");
  1914. fHost.uiName = carla_strdup(uiName);
  1915. }
  1916. // ---------------------------------------------------------------
  1917. // register client
  1918. pData->client = pData->engine->addClient(this);
  1919. if (pData->client == nullptr || ! pData->client->isOk())
  1920. {
  1921. pData->engine->setLastError("Failed to register plugin client");
  1922. return false;
  1923. }
  1924. // ---------------------------------------------------------------
  1925. // initialize plugin
  1926. fHandle = fDescriptor->instantiate(&fHost);
  1927. if (fHandle == nullptr)
  1928. {
  1929. pData->engine->setLastError("Plugin failed to initialize");
  1930. return false;
  1931. }
  1932. // ---------------------------------------------------------------
  1933. // load plugin settings
  1934. {
  1935. const bool hasMidiProgs(fDescriptor->get_midi_program_count != nullptr && fDescriptor->get_midi_program_count(fHandle) > 0);
  1936. // set default options
  1937. fOptions = 0x0;
  1938. if (hasMidiProgs && (fDescriptor->supports & ::PLUGIN_SUPPORTS_PROGRAM_CHANGES) == 0)
  1939. fOptions |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  1940. if (getMidiInCount() > 0 || (fDescriptor->hints & ::PLUGIN_NEEDS_FIXED_BUFFERS) != 0)
  1941. fOptions |= PLUGIN_OPTION_FIXED_BUFFERS;
  1942. if (pData->engine->getOptions().forceStereo)
  1943. fOptions |= PLUGIN_OPTION_FORCE_STEREO;
  1944. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_CHANNEL_PRESSURE)
  1945. fOptions |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  1946. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_NOTE_AFTERTOUCH)
  1947. fOptions |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  1948. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_PITCHBEND)
  1949. fOptions |= PLUGIN_OPTION_SEND_PITCHBEND;
  1950. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_ALL_SOUND_OFF)
  1951. fOptions |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  1952. // load settings
  1953. pData->idStr = "Native/";
  1954. pData->idStr += label;
  1955. fOptions = pData->loadSettings(fOptions, getAvailableOptions());
  1956. // ignore settings, we need this anyway
  1957. if (getMidiInCount() > 0 || (fDescriptor->hints & ::PLUGIN_NEEDS_FIXED_BUFFERS) != 0)
  1958. fOptions |= PLUGIN_OPTION_FIXED_BUFFERS;
  1959. }
  1960. return true;
  1961. }
  1962. class ScopedInitializer
  1963. {
  1964. public:
  1965. ScopedInitializer()
  1966. {
  1967. carla_register_all_plugins();
  1968. }
  1969. ~ScopedInitializer()
  1970. {
  1971. sPluginDescriptors.clear();
  1972. }
  1973. };
  1974. private:
  1975. ::PluginHandle fHandle;
  1976. ::PluginHandle fHandle2;
  1977. ::HostDescriptor fHost;
  1978. const ::PluginDescriptor* fDescriptor;
  1979. bool fIsProcessing;
  1980. bool fIsUiVisible;
  1981. float** fAudioInBuffers;
  1982. float** fAudioOutBuffers;
  1983. uint32_t fMidiEventCount;
  1984. ::MidiEvent fMidiEvents[kPluginMaxMidiEvents*2];
  1985. int32_t fCurMidiProgs[MAX_MIDI_CHANNELS];
  1986. NativePluginMidiData fMidiIn;
  1987. NativePluginMidiData fMidiOut;
  1988. ::TimeInfo fTimeInfo;
  1989. static NonRtList<const ::PluginDescriptor*> sPluginDescriptors;
  1990. // -------------------------------------------------------------------
  1991. #define handlePtr ((NativePlugin*)handle)
  1992. static uint32_t carla_host_get_buffer_size(::HostHandle handle)
  1993. {
  1994. return handlePtr->handleGetBufferSize();
  1995. }
  1996. static double carla_host_get_sample_rate(::HostHandle handle)
  1997. {
  1998. return handlePtr->handleGetSampleRate();
  1999. }
  2000. static bool carla_host_is_offline(::HostHandle handle)
  2001. {
  2002. return handlePtr->handleIsOffline();
  2003. }
  2004. static const ::TimeInfo* carla_host_get_time_info(::HostHandle handle)
  2005. {
  2006. return handlePtr->handleGetTimeInfo();
  2007. }
  2008. static bool carla_host_write_midi_event(::HostHandle handle, const ::MidiEvent* event)
  2009. {
  2010. return handlePtr->handleWriteMidiEvent(event);
  2011. }
  2012. static void carla_host_ui_parameter_changed(::HostHandle handle, uint32_t index, float value)
  2013. {
  2014. handlePtr->handleUiParameterChanged(index, value);
  2015. }
  2016. static void carla_host_ui_custom_data_changed(::HostHandle handle, const char* key, const char* value)
  2017. {
  2018. handlePtr->handleUiCustomDataChanged(key, value);
  2019. }
  2020. static void carla_host_ui_closed(::HostHandle handle)
  2021. {
  2022. handlePtr->handleUiClosed();
  2023. }
  2024. static const char* carla_host_ui_open_file(::HostHandle handle, bool isDir, const char* title, const char* filter)
  2025. {
  2026. return handlePtr->handleUiOpenFile(isDir, title, filter);
  2027. }
  2028. static const char* carla_host_ui_save_file(::HostHandle handle, bool isDir, const char* title, const char* filter)
  2029. {
  2030. return handlePtr->handleUiSaveFile(isDir, title, filter);
  2031. }
  2032. static intptr_t carla_host_dispatcher(::HostHandle handle, ::HostDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  2033. {
  2034. return handlePtr->handleDispatcher(opcode, index, value, ptr, opt);
  2035. }
  2036. #undef handlePtr
  2037. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePlugin)
  2038. };
  2039. NonRtList<const ::PluginDescriptor*> NativePlugin::sPluginDescriptors;
  2040. static const NativePlugin::ScopedInitializer _si;
  2041. CARLA_BACKEND_END_NAMESPACE
  2042. void carla_register_native_plugin(const PluginDescriptor* desc)
  2043. {
  2044. CARLA_BACKEND_USE_NAMESPACE
  2045. NativePlugin::registerPlugin(desc);
  2046. }
  2047. #else // WANT_NATIVE
  2048. # warning Building without Internal plugin support
  2049. #endif
  2050. CARLA_BACKEND_START_NAMESPACE
  2051. // -----------------------------------------------------------------------
  2052. #ifdef WANT_NATIVE
  2053. size_t CarlaPlugin::getNativePluginCount()
  2054. {
  2055. return NativePlugin::getPluginCount();
  2056. }
  2057. const PluginDescriptor* CarlaPlugin::getNativePluginDescriptor(const size_t index)
  2058. {
  2059. return NativePlugin::getPluginDescriptor(index);
  2060. }
  2061. #endif
  2062. // -----------------------------------------------------------------------
  2063. CarlaPlugin* CarlaPlugin::newNative(const Initializer& init)
  2064. {
  2065. carla_debug("CarlaPlugin::newNative({%p, \"%s\", \"%s\", \"%s\"})", init.engine, init.filename, init.name, init.label);
  2066. #ifdef WANT_NATIVE
  2067. NativePlugin* const plugin(new NativePlugin(init.engine, init.id));
  2068. if (! plugin->init(init.name, init.label))
  2069. {
  2070. delete plugin;
  2071. return nullptr;
  2072. }
  2073. plugin->reload();
  2074. if (init.engine->getProccessMode() == PROCESS_MODE_CONTINUOUS_RACK && ! plugin->canRunInRack())
  2075. {
  2076. init.engine->setLastError("Carla's rack mode can only work with Mono or Stereo Internal plugins, sorry!");
  2077. delete plugin;
  2078. return nullptr;
  2079. }
  2080. return plugin;
  2081. #else
  2082. init.engine->setLastError("Internal plugins support not available");
  2083. return nullptr;
  2084. #endif
  2085. }
  2086. CARLA_BACKEND_END_NAMESPACE