Change ALSA device default to 'default' from hw:0
[zynaddsubfx-code.git] / src / Misc / PresetExtractor.cpp
blobe54df12dce4af5a4d02ad6c79690671e1e5bcbfd
1 /*
2 ZynAddSubFX - a software synthesizer
4 PresetExtractor.cpp - Extract Presets from realtime data
5 Copyright (C) 2015 Mark McCurry
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
13 #include "../Params/PresetsStore.h"
15 #include "../Misc/Master.h"
16 #include "../Misc/Util.h"
17 #include "../Misc/Allocator.h"
18 #include "../Effects/EffectMgr.h"
19 #include "../Synth/OscilGen.h"
20 #include "../Synth/Resonance.h"
21 #include "../Params/ADnoteParameters.h"
22 #include "../Params/EnvelopeParams.h"
23 #include "../Params/FilterParams.h"
24 #include "../Params/LFOParams.h"
25 #include "../Params/PADnoteParameters.h"
26 #include "../Params/Presets.h"
27 #include "../Params/PresetsArray.h"
28 #include "../Params/SUBnoteParameters.h"
29 #include "../Misc/MiddleWare.h"
30 #include "PresetExtractor.h"
31 #include <rtosc/ports.h>
32 #include <rtosc/port-sugar.h>
33 #include <string>
35 namespace zyn {
37 using std::string;
38 static void dummy(const char *, rtosc::RtData&) {}
40 const rtosc::Ports real_preset_ports =
42 {"scan-for-presets:", 0, 0,
43 [](const char *, rtosc::RtData &d) {
44 MiddleWare &mw = *(MiddleWare*)d.obj;
45 assert(d.obj);
46 mw.getPresetsStore().scanforpresets();
47 auto &pre = mw.getPresetsStore().presets;
48 d.reply(d.loc, "i", pre.size());
49 for(unsigned i=0; i<pre.size();++i)
50 d.reply(d.loc, "isss", i,
51 pre[i].file.c_str(),
52 pre[i].name.c_str(),
53 pre[i].type.c_str());
55 }},
56 {"copy:s:ss:si:ssi", 0, 0,
57 [](const char *msg, rtosc::RtData &d) {
58 MiddleWare &mw = *(MiddleWare*)d.obj;
59 assert(d.obj);
60 std::string args = rtosc_argument_string(msg);
61 d.reply(d.loc, "s", "clipboard copy...");
62 printf("\nClipboard Copy...\n");
63 if(args == "s")
64 presetCopy(mw, rtosc_argument(msg, 0).s, "");
65 else if(args == "ss")
66 presetCopy(mw, rtosc_argument(msg, 0).s,
67 rtosc_argument(msg, 1).s);
68 else if(args == "si")
69 presetCopyArray(mw, rtosc_argument(msg, 0).s,
70 rtosc_argument(msg, 1).i, "");
71 else if(args == "ssi")
72 presetCopyArray(mw, rtosc_argument(msg, 0).s,
73 rtosc_argument(msg, 2).i, rtosc_argument(msg, 1).s);
74 else
75 assert(false && "bad arguments");
76 }},
77 {"paste:s:ss:si:ssi", 0, 0,
78 [](const char *msg, rtosc::RtData &d) {
79 MiddleWare &mw = *(MiddleWare*)d.obj;
80 assert(d.obj);
81 std::string args = rtosc_argument_string(msg);
82 d.reply(d.loc, "s", "clipboard paste...");
83 if(args == "s")
84 presetPaste(mw, rtosc_argument(msg, 0).s, "");
85 else if(args == "ss")
86 presetPaste(mw, rtosc_argument(msg, 0).s,
87 rtosc_argument(msg, 1).s);
88 else if(args == "si")
89 presetPasteArray(mw, rtosc_argument(msg, 0).s,
90 rtosc_argument(msg, 1).i, "");
91 else if(args == "ssi")
92 presetPasteArray(mw, rtosc_argument(msg, 0).s,
93 rtosc_argument(msg, 2).i, rtosc_argument(msg, 1).s);
94 else
95 assert(false && "bad arguments");
96 }},
97 {"clipboard-type:", 0, 0,
98 [](const char *, rtosc::RtData &d) {
99 const MiddleWare &mw = *(MiddleWare*)d.obj;
100 assert(d.obj);
101 d.reply(d.loc, "s", mw.getPresetsStore().clipboard.type.c_str());
103 {"delete:s", 0, 0,
104 [](const char *msg, rtosc::RtData &d) {
105 MiddleWare &mw = *(MiddleWare*)d.obj;
106 assert(d.obj);
107 mw.getPresetsStore().deletepreset(rtosc_argument(msg,0).s);
112 // Documentation for real_preset_ports above.
113 const rtosc::Ports preset_ports
115 {"scan-for-presets:", rDoc("Scan For Presets"), 0, dummy},
116 {"copy:s:ss:si:ssi", rDoc("Copy (s)URL to (s) Name/Clipboard from subfield (i)"), 0, dummy},
117 {"paste:s:ss:si:ssi", rDoc("Paste (s) URL to (s) File-Name/Clipboard from subfield (i)"), 0, dummy},
118 {"clipboard-type:", rDoc("Type Stored In Clipboard"), 0, dummy},
119 {"delete:s", rDoc("Delete the given preset file"), 0, dummy},
122 //Relevant types to keep in mind
123 //Effects/EffectMgr.cpp: setpresettype("Peffect");
124 //Params/ADnoteParameters.cpp: setpresettype("Padsynth");
125 //Params/EnvelopeParams.cpp: //setpresettype("Penvamplitude");
126 //Params/EnvelopeParams.cpp: //setpresettype("Penvamplitude");
127 //Params/EnvelopeParams.cpp: //setpresettype("Penvfrequency");
128 //Params/EnvelopeParams.cpp: //setpresettype("Penvfilter");
129 //Params/EnvelopeParams.cpp: //setpresettype("Penvbandwidth");
130 //Params/FilterParams.cpp: //setpresettype("Pfilter");
131 //Params/LFOParams.cpp: // setpresettype("Plfofrequency");
132 //Params/LFOParams.cpp: // setpresettype("Plfoamplitude");
133 //Params/LFOParams.cpp: // setpresettype("Plfofilter");
134 //Params/PADnoteParameters.cpp: setpresettype("Ppadsynth");
135 //Params/SUBnoteParameters.cpp: setpresettype("Psubsynth");
136 //Synth/OscilGen.cpp: setpresettype("Poscilgen");
137 //Synth/Resonance.cpp: setpresettype("Presonance");
140 /*****************************************************************************
141 * Implementation Methods *
142 *****************************************************************************/
143 class Capture:public rtosc::RtData
145 public:
146 Capture(void *obj_)
148 matches = 0;
149 memset(locbuf, 0, sizeof(locbuf));
150 memset(msgbuf, 0, sizeof(msgbuf));
151 loc = locbuf;
152 loc_size = sizeof(locbuf);
153 obj = obj_;
156 virtual void reply(const char *path, const char *args, ...)
158 //printf("reply(%p)(%s)(%s)...\n", msgbuf, path, args);
159 //printf("size is %d\n", sizeof(msgbuf));
160 va_list va;
161 va_start(va,args);
162 char *buffer = msgbuf;
163 rtosc_vmessage(buffer,sizeof(msgbuf),path,args,va);
164 va_end(va);
166 char msgbuf[1024];
167 char locbuf[1024];
170 template <class T>
171 T capture(Master *m, std::string url);
173 template <>
174 std::string capture(Master *m, std::string url)
176 Capture c(m);
177 char query[1024];
178 rtosc_message(query, 1024, url.c_str(), "");
179 Master::ports.dispatch(query+1,c);
180 if(rtosc_message_length(c.msgbuf, sizeof(c.msgbuf))) {
181 if(rtosc_type(c.msgbuf, 0) == 's')
182 return rtosc_argument(c.msgbuf,0).s;
185 return "";
188 template <>
189 void *capture(Master *m, std::string url)
191 Capture c(m);
192 char query[1024];
193 rtosc_message(query, 1024, url.c_str(), "");
194 Master::ports.dispatch(query+1,c);
195 if(rtosc_message_length(c.msgbuf, sizeof(c.msgbuf))) {
196 if(rtosc_type(c.msgbuf, 0) == 'b' &&
197 rtosc_argument(c.msgbuf, 0).b.len == sizeof(void*))
198 return *(void**)rtosc_argument(c.msgbuf,0).b.data;
201 return NULL;
204 template<class T>
205 std::string doCopy(MiddleWare &mw, string url, string name)
207 mw.doReadOnlyOp([url, name, &mw](){
208 Master *m = mw.spawnMaster();
209 //Get the pointer
210 T *t = (T*)capture<void*>(m, url+"self");
211 assert(t);
212 //Extract Via mxml
213 t->copy(mw.getPresetsStore(), name.empty()? NULL:name.c_str());
216 return "";
219 template<class T, typename... Ts>
220 void doPaste(MiddleWare &mw, string url, string type, XMLwrapper &xml, Ts&&... args)
222 //Generate a new object
223 T *t = new T(std::forward<Ts>(args)...);
225 //Old workaround for LFO parameters
226 if(strstr(type.c_str(), "Plfo"))
227 type = "Plfo";
229 if(xml.enterbranch(type) == 0)
231 delete t;
232 return;
235 t->getfromXML(xml);
237 //Send the pointer
238 string path = url+"paste";
239 char buffer[1024];
240 rtosc_message(buffer, 1024, path.c_str(), "b", sizeof(void*), &t);
241 if(!Master::ports.apropos(path.c_str()))
242 fprintf(stderr, "Warning: Missing Paste URL: '%s'\n", path.c_str());
243 //printf("Sending info to '%s'\n", buffer);
244 mw.transmitMsg(buffer);
246 //Let the pointer be reclaimed later
249 template<class T>
250 std::string doArrayCopy(MiddleWare &mw, int field, string url, string name)
252 //printf("Getting info from '%s'<%d>\n", url.c_str(), field);
253 mw.doReadOnlyOp([url, field, name, &mw](){
254 Master *m = mw.spawnMaster();
255 //Get the pointer
256 T *t = (T*)capture<void*>(m, url+"self");
257 //Extract Via mxml
258 t->copy(mw.getPresetsStore(), field, name.empty()?NULL:name.c_str());
261 return "";
264 template<class T, typename... Ts>
265 void doArrayPaste(MiddleWare &mw, int field, string url, string type,
266 XMLwrapper &xml, Ts&&... args)
268 //Generate a new object
269 T *t = new T(std::forward<Ts>(args)...);
271 if(xml.enterbranch(type+"n") == 0) {
272 delete t;
273 return;
275 t->defaults(field);
276 t->getfromXMLsection(xml, field);
277 xml.exitbranch();
279 //Send the pointer
280 string path = url+"paste-array";
281 char buffer[1024];
282 rtosc_message(buffer, 1024, path.c_str(), "bi", sizeof(void*), &t, field);
283 if(!Master::ports.apropos(path.c_str()))
284 fprintf(stderr, "Warning: Missing Paste URL: '%s'\n", path.c_str());
285 //printf("Sending info to '%s'<%d>\n", buffer, field);
286 mw.transmitMsg(buffer);
288 //Let the pointer be reclaimed later
292 * Dispatch to class specific operators
294 * Oscilgen and PADnoteParameters have mixed RT/non-RT parameters and require
295 * extra handling.
296 * See MiddleWare.cpp for these specifics
298 void doClassPaste(std::string type, std::string type_, MiddleWare &mw, string url, XMLwrapper &data)
300 //printf("Class Paste\n");
301 if(type == "EnvelopeParams")
302 doPaste<EnvelopeParams>(mw, url, type_, data);
303 else if(type == "LFOParams")
304 doPaste<LFOParams>(mw, url, type_, data);
305 else if(type == "FilterParams")
306 doPaste<FilterParams>(mw, url, type_, data);
307 else if(type == "ADnoteParameters")
308 doPaste<ADnoteParameters>(mw, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL);
309 else if(type == "PADnoteParameters")
310 doPaste<PADnoteParameters>(mw, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL);
311 else if(type == "SUBnoteParameters")
312 doPaste<SUBnoteParameters>(mw, url, type_, data);
313 else if(type == "OscilGen")
314 doPaste<OscilGen>(mw, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL, (Resonance*)NULL);
315 else if(type == "Resonance")
316 doPaste<Resonance>(mw, url, type_, data);
317 else if(type == "EffectMgr")
318 doPaste<EffectMgr>(mw, url, type_, data, DummyAlloc, mw.getSynth(), false);
319 else {
320 fprintf(stderr, "Warning: Unknown type<%s> from url<%s>\n", type.c_str(), url.c_str());
324 std::string doClassCopy(std::string type, MiddleWare &mw, string url, string name)
326 //printf("doClassCopy(%p)\n", mw.spawnMaster()->uToB);
327 if(type == "EnvelopeParams")
328 return doCopy<EnvelopeParams>(mw, url, name);
329 else if(type == "LFOParams")
330 return doCopy<LFOParams>(mw, url, name);
331 else if(type == "FilterParams")
332 return doCopy<FilterParams>(mw, url, name);
333 else if(type == "ADnoteParameters")
334 return doCopy<ADnoteParameters>(mw, url, name);
335 else if(type == "PADnoteParameters")
336 return doCopy<PADnoteParameters>(mw, url, name);
337 else if(type == "SUBnoteParameters")
338 return doCopy<SUBnoteParameters>(mw, url, name);
339 else if(type == "OscilGen")
340 return doCopy<OscilGen>(mw, url, name);
341 else if(type == "Resonance")
342 return doCopy<Resonance>(mw, url, name);
343 else if(type == "EffectMgr")
344 doCopy<EffectMgr>(mw, url, name);
345 return "UNDEF";
348 void doClassArrayPaste(std::string type, std::string type_, int field, MiddleWare &mw, string url,
349 XMLwrapper &data)
351 if(type == "FilterParams")
352 doArrayPaste<FilterParams>(mw, field, url, type_, data);
353 else if(type == "ADnoteParameters")
354 doArrayPaste<ADnoteParameters>(mw, field, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL);
357 std::string doClassArrayCopy(std::string type, int field, MiddleWare &mw, string url, string name)
359 if(type == "FilterParams")
360 return doArrayCopy<FilterParams>(mw, field, url, name);
361 else if(type == "ADnoteParameters")
362 return doArrayCopy<ADnoteParameters>(mw, field, url, name);
363 return "UNDEF";
366 //This is an abuse of the readonly op, but one that might look reasonable from a
367 //user perspective...
368 std::string getUrlPresetType(std::string url, MiddleWare &mw)
370 std::string result;
371 mw.doReadOnlyOp([url, &result, &mw](){
372 Master *m = mw.spawnMaster();
373 //Get the pointer
374 result = capture<std::string>(m, url+"preset-type");
376 //printf("preset type = %s\n", result.c_str());
377 return result;
380 std::string getUrlType(std::string url)
382 assert(!url.empty());
383 //printf("Searching for '%s'\n", (url+"self").c_str());
384 auto self = Master::ports.apropos((url+"self").c_str());
385 if(!self)
386 fprintf(stderr, "Warning: URL Metadata Not Found For '%s'\n", url.c_str());
388 if(self)
389 return self->meta()["class"];
390 else
391 return "";
395 /*****************************************************************************
396 * API Stubs *
397 *****************************************************************************/
399 #if 0
400 Clipboard clipboardCopy(MiddleWare &mw, string url)
402 //Identify The Self Type of the Object
403 string type = getUrlType(url);
404 printf("Copying a '%s' object", type.c_str());
406 //Copy The Object
407 string data = doClassCopy(type, mw, url);
408 printf("Object Information '%s'\n", data.c_str());
410 return {type, data};
413 void clipBoardPaste(const char *url, Clipboard clip)
415 (void) url;
416 (void) clip;
418 #endif
420 void presetCopy(MiddleWare &mw, std::string url, std::string name)
422 (void) name;
423 doClassCopy(getUrlType(url), mw, url, name);
424 //printf("PresetCopy()\n");
426 void presetPaste(MiddleWare &mw, std::string url, std::string name)
428 (void) name;
429 //printf("PresetPaste()\n");
430 string data = "";
431 XMLwrapper xml;
432 if(name.empty()) {
433 data = mw.getPresetsStore().clipboard.data;
434 if(data.length() < 20)
435 return;
436 if(!xml.putXMLdata(data.c_str()))
437 return;
438 } else {
439 if(xml.loadXMLfile(name))
440 return;
443 doClassPaste(getUrlType(url), getUrlPresetType(url, mw), mw, url, xml);
445 void presetCopyArray(MiddleWare &mw, std::string url, int field, std::string name)
447 (void) name;
448 //printf("PresetArrayCopy()\n");
449 doClassArrayCopy(getUrlType(url), field, mw, url, name);
451 void presetPasteArray(MiddleWare &mw, std::string url, int field, std::string name)
453 (void) name;
454 //printf("PresetArrayPaste()\n");
455 string data = "";
456 XMLwrapper xml;
457 if(name.empty()) {
458 data = mw.getPresetsStore().clipboard.data;
459 if(data.length() < 20)
460 return;
461 if(!xml.putXMLdata(data.c_str()))
462 return;
463 } else {
464 if(xml.loadXMLfile(name))
465 return;
467 //printf("Performing Paste...\n");
468 doClassArrayPaste(getUrlType(url), getUrlPresetType(url, mw), field, mw, url, xml);
470 #if 0
471 void presetPaste(std::string url, int)
473 printf("PresetPaste()\n");
474 doClassPaste(getUrlType(url), *middlewarepointer, url, presetsstore.clipboard.data);
476 #endif
477 void presetDelete(int)
479 printf("PresetDelete()<UNIMPLEMENTED>\n");
481 void presetRescan()
483 printf("PresetRescan()<UNIMPLEMENTED>\n");
485 std::string presetClipboardType()
487 printf("PresetClipboardType()<UNIMPLEMENTED>\n");
488 return "dummy";
490 bool presetCheckClipboardType()
492 printf("PresetCheckClipboardType()<UNIMPLEMENTED>\n");
493 return true;