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>
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
;
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
,
56 {"copy:s:ss:si:ssi", 0, 0,
57 [](const char *msg
, rtosc::RtData
&d
) {
58 MiddleWare
&mw
= *(MiddleWare
*)d
.obj
;
60 std::string args
= rtosc_argument_string(msg
);
61 d
.reply(d
.loc
, "s", "clipboard copy...");
62 printf("\nClipboard Copy...\n");
64 presetCopy(mw
, rtosc_argument(msg
, 0).s
, "");
66 presetCopy(mw
, rtosc_argument(msg
, 0).s
,
67 rtosc_argument(msg
, 1).s
);
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
);
75 assert(false && "bad arguments");
77 {"paste:s:ss:si:ssi", 0, 0,
78 [](const char *msg
, rtosc::RtData
&d
) {
79 MiddleWare
&mw
= *(MiddleWare
*)d
.obj
;
81 std::string args
= rtosc_argument_string(msg
);
82 d
.reply(d
.loc
, "s", "clipboard paste...");
84 presetPaste(mw
, rtosc_argument(msg
, 0).s
, "");
86 presetPaste(mw
, rtosc_argument(msg
, 0).s
,
87 rtosc_argument(msg
, 1).s
);
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
);
95 assert(false && "bad arguments");
97 {"clipboard-type:", 0, 0,
98 [](const char *, rtosc::RtData
&d
) {
99 const MiddleWare
&mw
= *(MiddleWare
*)d
.obj
;
101 d
.reply(d
.loc
, "s", mw
.getPresetsStore().clipboard
.type
.c_str());
104 [](const char *msg
, rtosc::RtData
&d
) {
105 MiddleWare
&mw
= *(MiddleWare
*)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
149 memset(locbuf
, 0, sizeof(locbuf
));
150 memset(msgbuf
, 0, sizeof(msgbuf
));
152 loc_size
= sizeof(locbuf
);
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));
162 char *buffer
= msgbuf
;
163 rtosc_vmessage(buffer
,sizeof(msgbuf
),path
,args
,va
);
171 T
capture(Master
*m
, std::string url
);
174 std::string
capture(Master
*m
, std::string url
)
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
;
189 void *capture(Master
*m
, std::string url
)
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
;
205 std::string
doCopy(MiddleWare
&mw
, string url
, string name
)
207 mw
.doReadOnlyOp([url
, name
, &mw
](){
208 Master
*m
= mw
.spawnMaster();
210 T
*t
= (T
*)capture
<void*>(m
, url
+"self");
213 t
->copy(mw
.getPresetsStore(), name
.empty()? NULL
:name
.c_str());
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"))
229 if(xml
.enterbranch(type
) == 0)
238 string path
= url
+"paste";
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
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();
256 T
*t
= (T
*)capture
<void*>(m
, url
+"self");
258 t
->copy(mw
.getPresetsStore(), field
, name
.empty()?NULL
:name
.c_str());
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) {
276 t
->getfromXMLsection(xml
, field
);
280 string path
= url
+"paste-array";
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
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);
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
);
348 void doClassArrayPaste(std::string type
, std::string type_
, int field
, MiddleWare
&mw
, string url
,
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
);
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
)
371 mw
.doReadOnlyOp([url
, &result
, &mw
](){
372 Master
*m
= mw
.spawnMaster();
374 result
= capture
<std::string
>(m
, url
+"preset-type");
376 //printf("preset type = %s\n", result.c_str());
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());
386 fprintf(stderr
, "Warning: URL Metadata Not Found For '%s'\n", url
.c_str());
389 return self
->meta()["class"];
395 /*****************************************************************************
397 *****************************************************************************/
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());
407 string data
= doClassCopy(type
, mw
, url
);
408 printf("Object Information '%s'\n", data
.c_str());
413 void clipBoardPaste(const char *url
, Clipboard clip
)
420 void presetCopy(MiddleWare
&mw
, std::string url
, std::string name
)
423 doClassCopy(getUrlType(url
), mw
, url
, name
);
424 //printf("PresetCopy()\n");
426 void presetPaste(MiddleWare
&mw
, std::string url
, std::string name
)
429 //printf("PresetPaste()\n");
433 data
= mw
.getPresetsStore().clipboard
.data
;
434 if(data
.length() < 20)
436 if(!xml
.putXMLdata(data
.c_str()))
439 if(xml
.loadXMLfile(name
))
443 doClassPaste(getUrlType(url
), getUrlPresetType(url
, mw
), mw
, url
, xml
);
445 void presetCopyArray(MiddleWare
&mw
, std::string url
, int field
, std::string 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
)
454 //printf("PresetArrayPaste()\n");
458 data
= mw
.getPresetsStore().clipboard
.data
;
459 if(data
.length() < 20)
461 if(!xml
.putXMLdata(data
.c_str()))
464 if(xml
.loadXMLfile(name
))
467 //printf("Performing Paste...\n");
468 doClassArrayPaste(getUrlType(url
), getUrlPresetType(url
, mw
), field
, mw
, url
, xml
);
471 void presetPaste(std::string url
, int)
473 printf("PresetPaste()\n");
474 doClassPaste(getUrlType(url
), *middlewarepointer
, url
, presetsstore
.clipboard
.data
);
477 void presetDelete(int)
479 printf("PresetDelete()<UNIMPLEMENTED>\n");
483 printf("PresetRescan()<UNIMPLEMENTED>\n");
485 std::string
presetClipboardType()
487 printf("PresetClipboardType()<UNIMPLEMENTED>\n");
490 bool presetCheckClipboardType()
492 printf("PresetCheckClipboardType()<UNIMPLEMENTED>\n");