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.

480 lines
15KB

  1. /**
  2. * Extract Presets from realtime data
  3. */
  4. #include "../Params/PresetsStore.h"
  5. #include "../Misc/Master.h"
  6. #include "../Misc/Util.h"
  7. #include "../Misc/Allocator.h"
  8. #include "../Effects/EffectMgr.h"
  9. #include "../Synth/OscilGen.h"
  10. #include "../Synth/Resonance.h"
  11. #include "../Params/ADnoteParameters.h"
  12. #include "../Params/EnvelopeParams.h"
  13. #include "../Params/FilterParams.h"
  14. #include "../Params/LFOParams.h"
  15. #include "../Params/PADnoteParameters.h"
  16. #include "../Params/Presets.h"
  17. #include "../Params/PresetsArray.h"
  18. #include "../Params/PresetsStore.h"
  19. #include "../Params/SUBnoteParameters.h"
  20. #include "../Misc/MiddleWare.h"
  21. #include "PresetExtractor.h"
  22. #include <rtosc/ports.h>
  23. #include <rtosc/port-sugar.h>
  24. #include <string>
  25. using std::string;
  26. static void dummy(const char *, rtosc::RtData&) {}
  27. const rtosc::Ports real_preset_ports =
  28. {
  29. {"scan-for-presets:", 0, 0,
  30. [](const char *msg, rtosc::RtData &d) {
  31. presetsstore.scanforpresets();
  32. auto &pre = presetsstore.presets;
  33. d.reply(d.loc, "i", pre.size());
  34. for(unsigned i=0; i<pre.size();++i)
  35. d.reply(d.loc, "isss", i,
  36. pre[i].file.c_str(),
  37. pre[i].name.c_str(),
  38. pre[i].type.c_str());
  39. }},
  40. {"copy:s:ss:si:ssi", 0, 0,
  41. [](const char *msg, rtosc::RtData &d) {
  42. MiddleWare &mw = *(MiddleWare*)d.obj;
  43. std::string args = rtosc_argument_string(msg);
  44. d.reply(d.loc, "s", "clipboard copy...");
  45. printf("\nClipboard Copy...\n");
  46. if(args == "s")
  47. presetCopy(mw, rtosc_argument(msg, 0).s, "");
  48. else if(args == "ss")
  49. presetCopy(mw, rtosc_argument(msg, 0).s,
  50. rtosc_argument(msg, 1).s);
  51. else if(args == "si")
  52. presetCopyArray(mw, rtosc_argument(msg, 0).s,
  53. rtosc_argument(msg, 1).i, "");
  54. else if(args == "ssi")
  55. presetCopyArray(mw, rtosc_argument(msg, 0).s,
  56. rtosc_argument(msg, 2).i, rtosc_argument(msg, 1).s);
  57. else
  58. assert(false && "bad arguments");
  59. }},
  60. {"paste:s:ss:si:ssi", 0, 0,
  61. [](const char *msg, rtosc::RtData &d) {
  62. MiddleWare &mw = *(MiddleWare*)d.obj;
  63. std::string args = rtosc_argument_string(msg);
  64. d.reply(d.loc, "s", "clipboard paste...");
  65. printf("\nClipboard Paste...\n");
  66. if(args == "s")
  67. presetPaste(mw, rtosc_argument(msg, 0).s, "");
  68. else if(args == "ss")
  69. presetPaste(mw, rtosc_argument(msg, 0).s,
  70. rtosc_argument(msg, 1).s);
  71. else if(args == "si")
  72. presetPasteArray(mw, rtosc_argument(msg, 0).s,
  73. rtosc_argument(msg, 1).i, "");
  74. else if(args == "ssi")
  75. presetPasteArray(mw, rtosc_argument(msg, 0).s,
  76. rtosc_argument(msg, 2).i, rtosc_argument(msg, 1).s);
  77. else
  78. assert(false && "bad arguments");
  79. }},
  80. {"clipboard-type:", 0, 0,
  81. [](const char *msg, rtosc::RtData &d) {
  82. d.reply(d.loc, "s", presetsstore.clipboard.type.c_str());
  83. }},
  84. {"delete:s", 0, 0,
  85. [](const char *msg, rtosc::RtData &d) {
  86. presetsstore.deletepreset(rtosc_argument(msg,0).s);
  87. }},
  88. };
  89. const rtosc::Ports preset_ports
  90. {
  91. {"scan-for-presets:", rDoc("Scan For Presets"), 0, dummy},
  92. {"copy:s:ss:si:ssi", rDoc("Copy <s> URL to <s> Name/Clipboard from subfield <i>"), 0, dummy},
  93. {"paste:s:ss:si:ssi", rDoc("Paste <s> URL to <s> File-Name/Clipboard from subfield <i>"), 0, dummy},
  94. {"clipboard-type:", rDoc("Type Stored In Clipboard"), 0, dummy},
  95. {"delete:s", rDoc("Delete the given preset file"), 0, dummy},
  96. };
  97. //Relevant types to keep in mind
  98. //Effects/EffectMgr.cpp: setpresettype("Peffect");
  99. //Params/ADnoteParameters.cpp: setpresettype("Padsynth");
  100. //Params/EnvelopeParams.cpp: //setpresettype("Penvamplitude");
  101. //Params/EnvelopeParams.cpp: //setpresettype("Penvamplitude");
  102. //Params/EnvelopeParams.cpp: //setpresettype("Penvfrequency");
  103. //Params/EnvelopeParams.cpp: //setpresettype("Penvfilter");
  104. //Params/EnvelopeParams.cpp: //setpresettype("Penvbandwidth");
  105. //Params/FilterParams.cpp: //setpresettype("Pfilter");
  106. //Params/LFOParams.cpp: // setpresettype("Plfofrequency");
  107. //Params/LFOParams.cpp: // setpresettype("Plfoamplitude");
  108. //Params/LFOParams.cpp: // setpresettype("Plfofilter");
  109. //Params/PADnoteParameters.cpp: setpresettype("Ppadsynth");
  110. //Params/SUBnoteParameters.cpp: setpresettype("Psubsynth");
  111. //Synth/OscilGen.cpp: setpresettype("Poscilgen");
  112. //Synth/Resonance.cpp: setpresettype("Presonance");
  113. //Translate newer symbols to old preset types
  114. std::vector<string> translate_preset_types(std::string metatype)
  115. {
  116. std::vector<string> results;
  117. return results;
  118. }
  119. /*****************************************************************************
  120. * Implementation Methods *
  121. *****************************************************************************/
  122. class Capture:public rtosc::RtData
  123. {
  124. public:
  125. Capture(void *obj_)
  126. {
  127. matches = 0;
  128. memset(locbuf, 0, sizeof(locbuf));
  129. loc = locbuf;
  130. loc_size = sizeof(locbuf);
  131. obj = obj_;
  132. }
  133. virtual void reply(const char *path, const char *args, ...)
  134. {
  135. printf("reply(%p)(%s)(%s)...\n", msgbuf, path, args);
  136. //printf("size is %d\n", sizeof(msgbuf));
  137. va_list va;
  138. va_start(va,args);
  139. char *buffer = msgbuf;
  140. rtosc_vmessage(buffer,sizeof(msgbuf),path,args,va);
  141. va_end(va);
  142. }
  143. char msgbuf[1024];
  144. char locbuf[1024];
  145. };
  146. template <class T>
  147. T capture(Master *m, std::string url);
  148. template <>
  149. std::string capture(Master *m, std::string url)
  150. {
  151. Capture c(m);
  152. char query[1024];
  153. rtosc_message(query, 1024, url.c_str(), "");
  154. Master::ports.dispatch(query+1,c);
  155. if(rtosc_message_length(c.msgbuf, sizeof(c.msgbuf))) {
  156. if(rtosc_type(c.msgbuf, 0) == 's')
  157. return rtosc_argument(c.msgbuf,0).s;
  158. }
  159. return "";
  160. }
  161. template <>
  162. void *capture(Master *m, std::string url)
  163. {
  164. Capture c(m);
  165. char query[1024];
  166. rtosc_message(query, 1024, url.c_str(), "");
  167. Master::ports.dispatch(query+1,c);
  168. if(rtosc_message_length(c.msgbuf, sizeof(c.msgbuf))) {
  169. if(rtosc_type(c.msgbuf, 0) == 'b' &&
  170. rtosc_argument(c.msgbuf, 0).b.len == sizeof(void*))
  171. return *(void**)rtosc_argument(c.msgbuf,0).b.data;
  172. }
  173. return NULL;
  174. }
  175. template<class T>
  176. std::string doCopy(MiddleWare &mw, string url, string name)
  177. {
  178. XMLwrapper xml;
  179. mw.doReadOnlyOp([&xml, url, name, &mw](){
  180. Master *m = mw.spawnMaster();
  181. //Get the pointer
  182. T *t = (T*)capture<void*>(m, url+"self");
  183. //Extract Via mxml
  184. //t->add2XML(&xml);
  185. t->copy(presetsstore, name.empty()? NULL:name.c_str());
  186. });
  187. return "";//xml.getXMLdata();
  188. }
  189. template<class T, typename... Ts>
  190. void doPaste(MiddleWare &mw, string url, string type, XMLwrapper &xml, Ts&&... args)
  191. {
  192. //Generate a new object
  193. T *t = new T(std::forward<Ts>(args)...);
  194. if(xml.enterbranch(type) == 0)
  195. return;
  196. t->getfromXML(&xml);
  197. //Send the pointer
  198. string path = url+"paste";
  199. char buffer[1024];
  200. rtosc_message(buffer, 1024, path.c_str(), "b", sizeof(void*), &t);
  201. if(!Master::ports.apropos(path.c_str()))
  202. fprintf(stderr, "Warning: Missing Paste URL: '%s'\n", path.c_str());
  203. printf("Sending info to '%s'\n", buffer);
  204. mw.transmitMsg(buffer);
  205. //Let the pointer be reclaimed later
  206. }
  207. template<class T>
  208. std::string doArrayCopy(MiddleWare &mw, int field, string url, string name)
  209. {
  210. XMLwrapper xml;
  211. printf("Getting info from '%s'<%d>\n", url.c_str(), field);
  212. mw.doReadOnlyOp([&xml, url, field, name, &mw](){
  213. Master *m = mw.spawnMaster();
  214. //Get the pointer
  215. T *t = (T*)capture<void*>(m, url+"self");
  216. //Extract Via mxml
  217. t->copy(presetsstore, field, name.empty()?NULL:name.c_str());
  218. });
  219. return "";//xml.getXMLdata();
  220. }
  221. template<class T, typename... Ts>
  222. void doArrayPaste(MiddleWare &mw, int field, string url, string type,
  223. XMLwrapper &xml, Ts&&... args)
  224. {
  225. //Generate a new object
  226. T *t = new T(std::forward<Ts>(args)...);
  227. if(xml.enterbranch(type+"n") == 0) {
  228. delete t;
  229. return;
  230. }
  231. t->defaults(field);
  232. t->getfromXMLsection(&xml, field);
  233. xml.exitbranch();
  234. //Send the pointer
  235. string path = url+"paste-array";
  236. char buffer[1024];
  237. rtosc_message(buffer, 1024, path.c_str(), "bi", sizeof(void*), &t, field);
  238. if(!Master::ports.apropos(path.c_str()))
  239. fprintf(stderr, "Warning: Missing Paste URL: '%s'\n", path.c_str());
  240. printf("Sending info to '%s'<%d>\n", buffer, field);
  241. mw.transmitMsg(buffer);
  242. //Let the pointer be reclaimed later
  243. }
  244. /*
  245. * Dispatch to class specific operators
  246. *
  247. * Oscilgen and PADnoteParameters have mixed RT/non-RT parameters and require
  248. * extra handling.
  249. * See MiddleWare.cpp for these specifics
  250. */
  251. void doClassPaste(std::string type, std::string type_, MiddleWare &mw, string url, XMLwrapper &data)
  252. {
  253. printf("Class Paste\n");
  254. if(type == "EnvelopeParams")
  255. doPaste<EnvelopeParams>(mw, url, type_, data);
  256. else if(type == "LFOParams")
  257. doPaste<LFOParams>(mw, url, type_, data);
  258. else if(type == "FilterParams")
  259. doPaste<FilterParams>(mw, url, type_, data);
  260. else if(type == "ADnoteParameters")
  261. doPaste<ADnoteParameters>(mw, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL);
  262. else if(type == "PADnoteParameters")
  263. doPaste<PADnoteParameters>(mw, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL);
  264. else if(type == "SUBnoteParameters")
  265. doPaste<SUBnoteParameters>(mw, url, type_, data);
  266. else if(type == "OscilGen")
  267. doPaste<OscilGen>(mw, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL, (Resonance*)NULL);
  268. else if(type == "Resonance")
  269. doPaste<Resonance>(mw, url, type_, data);
  270. else if(type == "EffectMgr")
  271. doPaste<EffectMgr>(mw, url, type_, data, DummyAlloc, mw.getSynth(), false);
  272. else {
  273. fprintf(stderr, "Warning: Unknown type<%s> from url<%s>\n", type.c_str(), url.c_str());
  274. }
  275. }
  276. std::string doClassCopy(std::string type, MiddleWare &mw, string url, string name)
  277. {
  278. if(type == "EnvelopeParams")
  279. return doCopy<EnvelopeParams>(mw, url, name);
  280. else if(type == "LFOParams")
  281. return doCopy<LFOParams>(mw, url, name);
  282. else if(type == "FilterParams")
  283. return doCopy<FilterParams>(mw, url, name);
  284. else if(type == "ADnoteParameters")
  285. return doCopy<ADnoteParameters>(mw, url, name);
  286. else if(type == "PADnoteParameters")
  287. return doCopy<PADnoteParameters>(mw, url, name);
  288. else if(type == "SUBnoteParameters")
  289. return doCopy<SUBnoteParameters>(mw, url, name);
  290. else if(type == "OscilGen")
  291. return doCopy<OscilGen>(mw, url, name);
  292. else if(type == "Resonance")
  293. return doCopy<Resonance>(mw, url, name);
  294. else if(type == "EffectMgr")
  295. doCopy<EffectMgr>(mw, url, name);
  296. return "UNDEF";
  297. }
  298. void doClassArrayPaste(std::string type, std::string type_, int field, MiddleWare &mw, string url,
  299. XMLwrapper &data)
  300. {
  301. if(type == "FilterParams")
  302. doArrayPaste<FilterParams>(mw, field, url, type_, data);
  303. else if(type == "ADnoteParameters")
  304. doArrayPaste<ADnoteParameters>(mw, field, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL);
  305. }
  306. std::string doClassArrayCopy(std::string type, int field, MiddleWare &mw, string url, string name)
  307. {
  308. if(type == "FilterParams")
  309. return doArrayCopy<FilterParams>(mw, field, url, name);
  310. else if(type == "ADnoteParameters")
  311. return doArrayCopy<ADnoteParameters>(mw, field, url, name);
  312. return "UNDEF";
  313. }
  314. //This is an abuse of the readonly op, but one that might look reasonable from a
  315. //user perspective...
  316. std::string getUrlPresetType(std::string url, MiddleWare &mw)
  317. {
  318. std::string result;
  319. mw.doReadOnlyOp([url, &result, &mw](){
  320. Master *m = mw.spawnMaster();
  321. //Get the pointer
  322. result = capture<std::string>(m, url+"preset-type");
  323. });
  324. printf("preset type = %s\n", result.c_str());
  325. return result;
  326. }
  327. std::string getUrlType(std::string url)
  328. {
  329. assert(!url.empty());
  330. printf("Searching for '%s'\n", (url+"self").c_str());
  331. auto self = Master::ports.apropos((url+"self").c_str());
  332. if(!self)
  333. fprintf(stderr, "Warning: URL Metadata Not Found For '%s'\n", url.c_str());
  334. if(self)
  335. return self->meta()["class"];
  336. else
  337. return "";
  338. }
  339. /*****************************************************************************
  340. * API Stubs *
  341. *****************************************************************************/
  342. #if 0
  343. Clipboard clipboardCopy(MiddleWare &mw, string url)
  344. {
  345. //Identify The Self Type of the Object
  346. string type = getUrlType(url);
  347. printf("Copying a '%s' object", type.c_str());
  348. //Copy The Object
  349. string data = doClassCopy(type, mw, url);
  350. printf("Object Information '%s'\n", data.c_str());
  351. return {type, data};
  352. }
  353. void clipBoardPaste(const char *url, Clipboard clip)
  354. {
  355. (void) url;
  356. (void) clip;
  357. }
  358. #endif
  359. void presetCopy(MiddleWare &mw, std::string url, std::string name)
  360. {
  361. (void) name;
  362. doClassCopy(getUrlType(url), mw, url, name);
  363. printf("PresetCopy()\n");
  364. }
  365. void presetPaste(MiddleWare &mw, std::string url, std::string name)
  366. {
  367. (void) name;
  368. printf("PresetPaste()\n");
  369. string data = "";
  370. XMLwrapper xml;
  371. if(name.empty()) {
  372. data = presetsstore.clipboard.data;
  373. if(data.length() < 20)
  374. return;
  375. if(!xml.putXMLdata(data.c_str()))
  376. return;
  377. } else {
  378. if(xml.loadXMLfile(name))
  379. return;
  380. }
  381. doClassPaste(getUrlType(url), getUrlPresetType(url, mw), mw, url, xml);
  382. }
  383. void presetCopyArray(MiddleWare &mw, std::string url, int field, std::string name)
  384. {
  385. (void) name;
  386. printf("PresetArrayCopy()\n");
  387. doClassArrayCopy(getUrlType(url), field, mw, url, name);
  388. }
  389. void presetPasteArray(MiddleWare &mw, std::string url, int field, std::string name)
  390. {
  391. (void) name;
  392. printf("PresetArrayPaste()\n");
  393. string data = "";
  394. XMLwrapper xml;
  395. if(name.empty()) {
  396. data = presetsstore.clipboard.data;
  397. if(data.length() < 20)
  398. return;
  399. if(!xml.putXMLdata(data.c_str()))
  400. return;
  401. } else {
  402. if(xml.loadXMLfile(name))
  403. return;
  404. }
  405. printf("Performing Paste...\n");
  406. doClassArrayPaste(getUrlType(url), getUrlPresetType(url, mw), field, mw, url, xml);
  407. }
  408. #if 0
  409. void presetPaste(std::string url, int)
  410. {
  411. printf("PresetPaste()\n");
  412. doClassPaste(getUrlType(url), *middlewarepointer, url, presetsstore.clipboard.data);
  413. }
  414. #endif
  415. void presetDelete(int)
  416. {
  417. printf("PresetDelete()\n");
  418. }
  419. void presetRescan()
  420. {
  421. printf("PresetRescan()\n");
  422. }
  423. std::string presetClipboardType()
  424. {
  425. printf("PresetClipboardType()\n");
  426. return "dummy";
  427. }
  428. bool presetCheckClipboardType()
  429. {
  430. printf("PresetCheckClipboardType()\n");
  431. return true;
  432. }