1 /*
2 * Copyright (C) 2002 - David W. Durham
3 *
4 * This file is part of ReZound, an audio editing application.
5 *
6 * ReZound is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License,
9 * or (at your option) any later version.
10 *
11 * ReZound is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 */
20
21 #include "CActionParamDialog.h"
22
23 #include <stdexcept>
24
25 #include <istring>
26
27 #include <CNestedDataFile/CNestedDataFile.h>
28
29 #include "CStatusComm.h"
30 #include "settings.h"
31
32 #include "../backend/CActionParameters.h"
33 #include "../backend/CActionSound.h"
34 #include "../backend/AAction.h" // for EUserMessage
35
36 #include "CFOXIcons.h"
37
38 FXDEFMAP(CActionParamDialog) CActionParamDialogMap[]=
39 {
40 // Message_Type ID Message_Handler
41
42 FXMAPFUNC(SEL_COMMAND, CActionParamDialog::ID_NATIVE_PRESET_BUTTON, CActionParamDialog::onPresetUseButton),
43 FXMAPFUNC(SEL_DOUBLECLICKED, CActionParamDialog::ID_NATIVE_PRESET_LIST, CActionParamDialog::onPresetUseButton),
44
45 FXMAPFUNC(SEL_COMMAND, CActionParamDialog::ID_USER_PRESET_USE_BUTTON, CActionParamDialog::onPresetUseButton),
46 FXMAPFUNC(SEL_COMMAND, CActionParamDialog::ID_USER_PRESET_SAVE_BUTTON, CActionParamDialog::onPresetSaveButton),
47 FXMAPFUNC(SEL_COMMAND, CActionParamDialog::ID_USER_PRESET_REMOVE_BUTTON,CActionParamDialog::onPresetRemoveButton),
48 FXMAPFUNC(SEL_DOUBLECLICKED, CActionParamDialog::ID_USER_PRESET_LIST, CActionParamDialog::onPresetUseButton),
49
50 FXMAPFUNC(SEL_COMMAND, CActionParamDialog::ID_EXPLAIN_BUTTON, CActionParamDialog::onExplainButton),
51 };
52
53
FXIMPLEMENT(CActionParamDialog,FXModalDialogBox,CActionParamDialogMap,ARRAYNUMBER (CActionParamDialogMap))54 FXIMPLEMENT(CActionParamDialog,FXModalDialogBox,CActionParamDialogMap,ARRAYNUMBER(CActionParamDialogMap))
55
56
57 // ----------------------------------------
58
59 // ??? TODO Well, I got it to not need the width, it's determined by the
60 // widgets' needed widths.. I don't quite know tho, what the height won't
61 // work the same what.. I'll work on figuring that out and then both
62 // parameters should be unnecessary
63
64 CActionParamDialog::CActionParamDialog(FXWindow *mainWindow,bool _showPresetPanel,const string _presetPrefix,FXModalDialogBox::ShowTypes showType) :
65 FXModalDialogBox(mainWindow,"",0,0,FXModalDialogBox::ftVertical,showType),
66
67 showPresetPanel(_showPresetPanel),
68
69 explanationButtonCreated(false),
70
71 splitter(new FXSplitter(getFrame(),SPLITTER_VERTICAL|SPLITTER_REVERSED | LAYOUT_FILL_X|LAYOUT_FILL_Y)),
72 topPanel(new FXHorizontalFrame(splitter,FRAME_RAISED|FRAME_THICK, 0,0,0,0, 0,0,0,0, 0,0)),
73 leftMargin(new FXFrame(topPanel,FRAME_NONE|LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH,0,0,0,0, 0,0,0,0)),
74 controlsFrame(new FXPacker(topPanel,FRAME_NONE | LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0, 0,0)),
75 rightMargin(new FXFrame(topPanel,FRAME_NONE|LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH,0,0,0,0, 0,0,0,0)),
76 presetsFrame(NULL),
77 nativePresetList(NULL),
78 userPresetList(NULL),
79
80 presetPrefix(_presetPrefix=="" ? "" : _presetPrefix DOT ""),
81 firstShowing(true)
82 {
83 disableFrameDecor();
84
85 setHeight(getHeight()+100); // since we're adding this presets section, make the dialog taller
86
87 // make sure the dialog has at least a minimum height and width
88 //ASSURE_HEIGHT(this,10);
89 //ASSURE_WIDTH(this,200);
90 }
91
~CActionParamDialog()92 CActionParamDialog::~CActionParamDialog()
93 {
94 }
95
create()96 void CActionParamDialog::create()
97 {
98 if(!explanationButtonCreated && getExplanation()!="")
99 new FXButton(getButtonFrame(),_("Explain"),FOXIcons->explain,this,ID_EXPLAIN_BUTTON,FRAME_RAISED|FRAME_THICK | JUSTIFY_NORMAL | ICON_ABOVE_TEXT | LAYOUT_FIX_WIDTH, 0,0,60,0, 2,2,2,2);
100 explanationButtonCreated=true;
101
102 FXModalDialogBox::create();
103 }
104
onExplainButton(FXObject * sender,FXSelector sel,void * ptr)105 long CActionParamDialog::onExplainButton(FXObject *sender,FXSelector sel,void *ptr)
106 {
107 Message(getExplanation());
108 return 1;
109 }
110
newHorzPanel(void * parent,bool createMargin,bool createFrame)111 FXPacker *CActionParamDialog::newHorzPanel(void *parent,bool createMargin,bool createFrame)
112 {
113 if(parent==NULL)
114 {
115 if(controlsFrame->numChildren()>0)
116 throw runtime_error(string(__func__)+" -- this method has already been called with a NULL parameter");
117 parent=controlsFrame;
118 }
119 if(createMargin)
120 return new FXHorizontalFrame((FXPacker *)parent,(createFrame ? FRAME_RAISED : FRAME_NONE) | LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 2,2,2,2, 0,0);
121 else
122 return new FXHorizontalFrame((FXPacker *)parent,(createFrame ? FRAME_RAISED : FRAME_NONE) | LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0, 0,0);
123 }
124
newVertPanel(void * parent,bool createMargin,bool createFrame)125 FXPacker *CActionParamDialog::newVertPanel(void *parent,bool createMargin,bool createFrame)
126 {
127 if(parent==NULL)
128 {
129 if(controlsFrame->numChildren()>0)
130 throw runtime_error(string(__func__)+" -- this method has already been called with a NULL parameter");
131 parent=controlsFrame;
132 }
133 if(createMargin)
134 return new FXVerticalFrame((FXPacker *)parent,(createFrame ? FRAME_RAISED : FRAME_NONE) | LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 2,2,2,2, 0,0);
135 else
136 return new FXVerticalFrame((FXPacker *)parent,(createFrame ? FRAME_RAISED : FRAME_NONE) | LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0, 0,0);
137 }
138
addSlider(void * parent,const string name,const string units,AActionParamMapper * valueMapper,f_at_x optRetValueConv,bool showInverseButton)139 FXConstantParamValue *CActionParamDialog::addSlider(void *parent,const string name,const string units,AActionParamMapper *valueMapper,f_at_x optRetValueConv,bool showInverseButton)
140 {
141 if(parent==NULL)
142 throw runtime_error(string(__func__)+" -- parent was passed NULL -- use CActionParameValue::newHorzPanel() or newVertPanel() to obtain a parent parameter to pass");
143 FXConstantParamValue *slider=new FXConstantParamValue(valueMapper,showInverseButton,(FXPacker *)parent,0,name.c_str());
144 slider->setUnits(units.c_str());
145 slider->setValue(valueMapper->getDefaultValue());
146 parameters.push_back(make_pair(ptConstant,slider));
147 retValueConvs.push_back(optRetValueConv);
148
149 return slider;
150 }
151
getSliderParam(const string name)152 FXConstantParamValue *CActionParamDialog::getSliderParam(const string name)
153 {
154 const unsigned index=findParamByName(name);
155 if(parameters[index].first==ptConstant);
156 return (FXConstantParamValue *)parameters[index].second;
157 throw runtime_error(string(__func__)+" -- widget with name, "+name+", is not a slider");
158 }
159
addNumericTextEntry(void * parent,const string name,const string units,const double initialValue,const double minValue,const double maxValue,const string unitsTipText)160 FXTextParamValue *CActionParamDialog::addNumericTextEntry(void *parent,const string name,const string units,const double initialValue,const double minValue,const double maxValue,const string unitsTipText)
161 {
162 if(parent==NULL)
163 throw runtime_error(string(__func__)+" -- parent was passed NULL -- use CActionParameValue::newHorzPanel() or newVertPanel() to obtain a parent parameter to pass");
164 FXTextParamValue *textEntry=new FXTextParamValue((FXPacker *)parent,0,name.c_str(),initialValue,minValue,maxValue);
165 textEntry->setUnits(units.c_str(),unitsTipText.c_str());
166 parameters.push_back(make_pair(ptNumericText,textEntry));
167 retValueConvs.push_back(NULL);
168
169 return textEntry;
170 }
171
addStringTextEntry(void * parent,const string name,const string initialValue,const string tipText)172 FXTextParamValue *CActionParamDialog::addStringTextEntry(void *parent,const string name,const string initialValue,const string tipText)
173 {
174 if(parent==NULL)
175 throw runtime_error(string(__func__)+" -- parent was passed NULL -- use CActionParameValue::newHorzPanel() or newVertPanel() to obtain a parent parameter to pass");
176 FXTextParamValue *textEntry=new FXTextParamValue((FXPacker *)parent,0,name.c_str(),initialValue);
177 textEntry->setTipText(tipText.c_str());
178 parameters.push_back(make_pair(ptStringText,textEntry));
179 retValueConvs.push_back(NULL);
180
181 return textEntry;
182 }
183
getTextParam(const string name)184 FXTextParamValue *CActionParamDialog::getTextParam(const string name)
185 {
186 for(size_t t=0;t<parameters.size();t++)
187 {
188 if((parameters[t].first==ptStringText || parameters[t].first==ptNumericText) && ((FXTextParamValue *)parameters[t].second)->getName()==name)
189 return (FXTextParamValue *)parameters[t].second;
190 }
191 throw runtime_error(string(__func__)+" -- no text param found named "+name);
192 }
193
addDiskEntityEntry(void * parent,const string name,const string initialEntityName,FXDiskEntityParamValue::DiskEntityTypes entityType,const string tipText)194 FXDiskEntityParamValue *CActionParamDialog::addDiskEntityEntry(void *parent,const string name,const string initialEntityName,FXDiskEntityParamValue::DiskEntityTypes entityType,const string tipText)
195 {
196 if(parent==NULL)
197 throw runtime_error(string(__func__)+" -- parent was passed NULL -- use CActionParameValue::newHorzPanel() or newVertPanel() to obtain a parent parameter to pass");
198 FXDiskEntityParamValue *diskEntityEntry=new FXDiskEntityParamValue((FXPacker *)parent,0,name.c_str(),initialEntityName,entityType);
199 diskEntityEntry->setTipText(tipText.c_str());
200 parameters.push_back(make_pair(ptDiskEntity,diskEntityEntry));
201 retValueConvs.push_back(NULL);
202
203 return diskEntityEntry;
204 }
205
getDiskEntityParam(const string name)206 FXDiskEntityParamValue *CActionParamDialog::getDiskEntityParam(const string name)
207 {
208 const unsigned index=findParamByName(name);
209 if(parameters[index].first==ptDiskEntity)
210 return (FXDiskEntityParamValue *)parameters[index].second;
211 throw runtime_error(string(__func__)+" -- widget with name, "+name+", is not a disk entity");
212 }
213
addComboTextEntry(void * parent,const string name,const vector<string> & items,ComboParamValueTypes type,const string tipText,bool isEditable)214 FXComboTextParamValue *CActionParamDialog::addComboTextEntry(void *parent,const string name,const vector<string> &items,ComboParamValueTypes type,const string tipText,bool isEditable)
215 {
216 if(parent==NULL)
217 throw runtime_error(string(__func__)+" -- parent was passed NULL -- use CActionParameValue::newHorzPanel() or newVertPanel() to obtain a parent parameter to pass");
218 FXComboTextParamValue *comboTextEntry=new FXComboTextParamValue((FXPacker *)parent,0,name.c_str(),items,isEditable);
219 if(type==cpvtAsString)
220 comboTextEntry->asString=true;
221 else
222 comboTextEntry->asString=false;
223 comboTextEntry->setTipText(tipText.c_str());
224 parameters.push_back(make_pair(ptComboText,comboTextEntry));
225 retValueConvs.push_back(NULL);
226
227 return comboTextEntry;
228 }
229
getComboText(const string name)230 FXComboTextParamValue *CActionParamDialog::getComboText(const string name)
231 {
232 const unsigned index=findParamByName(name);
233 if(parameters[index].first==ptComboText);
234 return (FXComboTextParamValue *)parameters[index].second;
235 throw runtime_error(string(__func__)+" -- widget with name, "+name+", is not a combobox");
236 }
237
238
addCheckBoxEntry(void * parent,const string name,const bool checked,const string tipText)239 FXCheckBoxParamValue *CActionParamDialog::addCheckBoxEntry(void *parent,const string name,const bool checked,const string tipText)
240 {
241 if(parent==NULL)
242 throw runtime_error(string(__func__)+" -- parent was passed NULL -- use CActionParameValue::newHorzPanel() or newVertPanel() to obtain a parent parameter to pass");
243 FXCheckBoxParamValue *checkBoxEntry=new FXCheckBoxParamValue((FXPacker *)parent,0,name.c_str(),checked);
244 checkBoxEntry->setTipText(tipText.c_str());
245 parameters.push_back(make_pair(ptCheckBox,checkBoxEntry));
246 retValueConvs.push_back(NULL);
247
248 return checkBoxEntry;
249 }
250
getCheckBoxParam(const string name)251 FXCheckBoxParamValue *CActionParamDialog::getCheckBoxParam(const string name)
252 {
253 const unsigned index=findParamByName(name);
254 if(parameters[index].first==ptCheckBox)
255 return (FXCheckBoxParamValue *)parameters[index].second;
256 throw runtime_error(string(__func__)+" -- widget with name, "+name+", is not a checkbox");
257 }
258
addGraph(void * parent,const string name,const string horzAxisLabel,const string horzUnits,AActionParamMapper * horzValueMapper,const string vertAxisLabel,const string vertUnits,AActionParamMapper * vertValueMapper,f_at_x optRetValueConv)259 FXGraphParamValue *CActionParamDialog::addGraph(void *parent,const string name,const string horzAxisLabel,const string horzUnits,AActionParamMapper *horzValueMapper,const string vertAxisLabel,const string vertUnits,AActionParamMapper *vertValueMapper,f_at_x optRetValueConv)
260 {
261 if(parent==NULL)
262 throw runtime_error(string(__func__)+" -- parent was passed NULL -- use CActionParameValue::newHorzPanel() or newVertPanel() to obtain a parent parameter to pass");
263 FXGraphParamValue *graph=new FXGraphParamValue(name.c_str(),(FXPacker *)parent,LAYOUT_FILL_X|LAYOUT_FILL_Y);
264 graph->setHorzParameters(horzAxisLabel,horzUnits,horzValueMapper);
265 graph->setVertParameters(vertAxisLabel,vertUnits,vertValueMapper);
266 parameters.push_back(make_pair(ptGraph,graph));
267 retValueConvs.push_back(optRetValueConv);
268
269 return graph;
270 }
271
addGraphWithWaveform(void * parent,const string name,const string vertAxisLabel,const string vertUnits,AActionParamMapper * vertValueMapper,f_at_x optRetValueConv)272 FXGraphParamValue *CActionParamDialog::addGraphWithWaveform(void *parent,const string name,const string vertAxisLabel,const string vertUnits,AActionParamMapper *vertValueMapper,f_at_x optRetValueConv)
273 {
274 if(parent==NULL)
275 throw runtime_error(string(__func__)+" -- parent was passed NULL -- use CActionParameValue::newHorzPanel() or newVertPanel() to obtain a parent parameter to pass");
276 FXGraphParamValue *graph=new FXGraphParamValue(name.c_str(),(FXPacker *)parent,LAYOUT_FILL_X|LAYOUT_FILL_Y);
277 graph->setVertParameters(vertAxisLabel,vertUnits,vertValueMapper);
278 parameters.push_back(make_pair(ptGraphWithWaveform,graph));
279 retValueConvs.push_back(optRetValueConv);
280
281 return graph;
282 }
283
getGraphParam(const string name)284 FXGraphParamValue *CActionParamDialog::getGraphParam(const string name)
285 {
286 for(size_t t=0;t<parameters.size();t++)
287 {
288 if((parameters[t].first==ptGraph || parameters[t].first==ptGraphWithWaveform) && ((FXGraphParamValue *)parameters[t].second)->getName()==name)
289 return (FXGraphParamValue *)parameters[t].second;
290 }
291 throw runtime_error(string(__func__)+" -- no graph param found named "+name);
292 }
293
addLFO(void * parent,const string name,const string ampUnits,const string ampTitle,const double maxAmp,const string freqUnits,const double maxFreq,const bool hideBipolarLFOs)294 FXLFOParamValue *CActionParamDialog::addLFO(void *parent,const string name,const string ampUnits,const string ampTitle,const double maxAmp,const string freqUnits,const double maxFreq,const bool hideBipolarLFOs)
295 {
296 if(parent==NULL)
297 throw runtime_error(string(__func__)+" -- parent was passed NULL -- use CActionParameValue::newHorzPanel() or newVertPanel() to obtain a parent parameter to pass");
298 FXLFOParamValue *LFOEntry=new FXLFOParamValue((FXPacker *)parent,0,name.c_str(),ampUnits,ampTitle,maxAmp,freqUnits,maxFreq,hideBipolarLFOs);
299 //LFOEntry->setTipText(tipText.c_str());
300 parameters.push_back(make_pair(ptLFO,LFOEntry));
301 retValueConvs.push_back(NULL);
302
303 return LFOEntry;
304 }
305
getLFOParam(const string name)306 FXLFOParamValue *CActionParamDialog::getLFOParam(const string name)
307 {
308 const unsigned index=findParamByName(name);
309 if(parameters[index].first==ptLFO);
310 return (FXLFOParamValue *)parameters[index].second;
311 throw runtime_error(string(__func__)+" -- widget with name, "+name+", is not an LFO");
312 }
313
addPluginRoutingParam(void * parent,const string name,const LADSPA_Descriptor * desc)314 FXPluginRoutingParamValue *CActionParamDialog::addPluginRoutingParam(void *parent,const string name,const LADSPA_Descriptor *desc)
315 {
316 if(parent==NULL)
317 throw runtime_error(string(__func__)+" -- parent was passed NULL -- use CActionParameValue::newHorzPanel() or newVertPanel() to obtain a parent parameter to pass");
318 FXPluginRoutingParamValue *pluginRoutingEntry=new FXPluginRoutingParamValue((FXPacker *)parent,0,name.c_str(),desc);
319 parameters.push_back(make_pair(ptPluginRouting,pluginRoutingEntry));
320 retValueConvs.push_back(NULL);
321
322 return pluginRoutingEntry;
323 }
324
getPluginRoutingParam(const string name)325 FXPluginRoutingParamValue *CActionParamDialog::getPluginRoutingParam(const string name)
326 {
327 const unsigned index=findParamByName(name);
328 if(parameters[index].first==ptPluginRouting);
329 return (FXPluginRoutingParamValue *)parameters[index].second;
330 throw runtime_error(string(__func__)+" -- widget with name, "+name+", is not a Plugin Routing");
331 }
332
setMargin(FXint margin)333 void CActionParamDialog::setMargin(FXint margin)
334 {
335 leftMargin->setWidth(margin);
336 rightMargin->setWidth(margin);
337 }
338
setValue(size_t index,const double value)339 void CActionParamDialog::setValue(size_t index,const double value)
340 {
341 switch(parameters[index].first)
342 {
343 case ptConstant:
344 ((FXConstantParamValue *)parameters[index].second)->setValue(value);
345 break;
346
347 case ptNumericText:
348 ((FXTextParamValue *)parameters[index].second)->setValue(value);
349 break;
350
351 case ptStringText:
352 ((FXTextParamValue *)parameters[index].second)->setText(istring(value));
353 break;
354
355 case ptComboText:
356 ((FXComboTextParamValue *)parameters[index].second)->setIntegerValue((FXint)value);
357 break;
358
359 case ptCheckBox:
360 ((FXCheckBoxParamValue *)parameters[index].second)->setValue((bool)value);
361 break;
362
363 case ptGraph:
364 case ptGraphWithWaveform:
365 /*
366 ((FXGraphParamValue *)parameters[index].second)->setValue(value);
367 break;
368 */
369
370 case ptLFO:
371 /*
372 ((FXGraphParamValue *)parameters[index].second)->setValue(value);
373 break;
374 */
375
376 case ptPluginRouting:
377 /*
378 ((FXGraphParamValue *)parameters[index].second)->setValue(value);
379 break;
380 */
381
382 default:
383 throw runtime_error(string(__func__)+" -- unhandled or unimplemented parameter type: "+istring(parameters[index].first));
384 }
385 }
386
setTipText(const string name,const string tipText)387 void CActionParamDialog::setTipText(const string name,const string tipText)
388 {
389 const unsigned index=findParamByName(name);
390
391 switch(parameters[index].first)
392 {
393 case ptConstant:
394 ((FXConstantParamValue *)parameters[index].second)->setTipText(tipText.c_str());
395 break;
396
397 case ptNumericText:
398 case ptStringText:
399 ((FXTextParamValue *)parameters[index].second)->setTipText(tipText.c_str());
400 break;
401
402 case ptDiskEntity:
403 ((FXDiskEntityParamValue *)parameters[index].second)->setTipText(tipText.c_str());
404 break;
405
406 case ptComboText:
407 ((FXComboTextParamValue *)parameters[index].second)->setTipText(tipText.c_str());
408 break;
409
410 case ptCheckBox:
411 ((FXCheckBoxParamValue *)parameters[index].second)->setTipText(tipText.c_str());
412 break;
413
414 case ptGraph:
415 case ptGraphWithWaveform:
416 /*
417 ((FXGraphParamValue *)parameters[index].second)->setTipText(tipText.c_str());
418 break;
419 */
420
421 case ptLFO:
422 /*
423 ((FXLFOParamValue *)parameters[index].second)->setTipText(tipText.c_str());
424 break;
425 */
426
427 case ptPluginRouting:
428 /*
429 ((FXPluginRoutingParamValue *)parameters[index].second)->setTipText(tipText.c_str());
430 break;
431 */
432
433 default:
434 throw runtime_error(string(__func__)+" -- unhandled or unimplemented parameter type: "+istring(parameters[index].first));
435 }
436 }
437
showControl(const string name,bool show)438 void CActionParamDialog::showControl(const string name,bool show)
439 {
440 const unsigned index=findParamByName(name);
441
442 switch(parameters[index].first)
443 {
444 case ptConstant:
445 if(show)
446 ((FXConstantParamValue *)parameters[index].second)->show();
447 else
448 ((FXConstantParamValue *)parameters[index].second)->hide();
449 break;
450
451 case ptNumericText:
452 case ptStringText:
453 if(show)
454 ((FXTextParamValue *)parameters[index].second)->show();
455 else
456 ((FXTextParamValue *)parameters[index].second)->hide();
457 break;
458
459 case ptDiskEntity:
460 if(show)
461 ((FXDiskEntityParamValue *)parameters[index].second)->show();
462 else
463 ((FXDiskEntityParamValue *)parameters[index].second)->hide();
464 break;
465
466 case ptComboText:
467 if(show)
468 ((FXComboTextParamValue *)parameters[index].second)->show();
469 else
470 ((FXComboTextParamValue *)parameters[index].second)->hide();
471 break;
472
473 case ptCheckBox:
474 if(show)
475 ((FXCheckBoxParamValue *)parameters[index].second)->show();
476 else
477 ((FXCheckBoxParamValue *)parameters[index].second)->hide();
478 break;
479
480 case ptGraph:
481 case ptGraphWithWaveform:
482 if(show)
483 ((FXGraphParamValue *)parameters[index].second)->show();
484 else
485 ((FXGraphParamValue *)parameters[index].second)->hide();
486 break;
487
488 case ptLFO:
489 if(show)
490 ((FXLFOParamValue *)parameters[index].second)->show();
491 else
492 ((FXLFOParamValue *)parameters[index].second)->hide();
493 break;
494
495 case ptPluginRouting:
496 if(show)
497 ((FXPluginRoutingParamValue *)parameters[index].second)->show();
498 else
499 ((FXPluginRoutingParamValue *)parameters[index].second)->hide();
500 break;
501
502 default:
503 throw runtime_error(string(__func__)+" -- unhandled or unimplemented parameter type: "+istring(parameters[index].first));
504 }
505
506 // tell it to recalc if the number of shown or hidden children changes
507 parameters[index].second->getParent()->recalc();
508 }
509
show(CActionSound * actionSound,CActionParameters * actionParameters)510 bool CActionParamDialog::show(CActionSound *actionSound,CActionParameters *actionParameters)
511 {
512 bool retval=false;
513
514 if(getOrigTitle()=="")
515 throw runtime_error(string(__func__)+" -- title was never set");
516
517 buildPresetLists();
518
519 // restore the splitter's position
520 const FXint h=gSettingsRegistry->getValue<int>("FOX" DOT "SplitterPositions" DOT presetPrefix+getOrigTitle());
521 if(presetsFrame!=NULL)
522 presetsFrame->setHeight(h);
523
524
525 // initialize all the graphs to this sound
526 for(size_t t=0;t<parameters.size();t++)
527 {
528 if(parameters[t].first==ptGraphWithWaveform)
529 {
530 ((FXGraphParamValue *)parameters[t].second)->setSound(actionSound->sound,actionSound->start,actionSound->stop);
531 if(firstShowing)
532 ((FXGraphParamValue *)parameters[t].second)->clearNodes();
533 }
534 else if(parameters[t].first==ptPluginRouting)
535 ((FXPluginRoutingParamValue *)parameters[t].second)->setSound(actionSound->sound);
536 }
537
538 firstShowing=false;
539
540 reshow:
541
542 if(execute(PLACEMENT_CURSOR))
543 {
544 vector<string> addedParameters;
545 try
546 {
547 for(unsigned t=0;t<parameters.size();t++)
548 {
549 switch(parameters[t].first)
550 {
551 case ptConstant:
552 {
553 FXConstantParamValue *slider=(FXConstantParamValue *)parameters[t].second;
554 double ret=slider->getValue();
555
556 if(retValueConvs[t]!=NULL)
557 ret=retValueConvs[t](ret);
558
559 actionParameters->setValue<double>(slider->getName(),ret);
560 addedParameters.push_back(slider->getName());
561 }
562 break;
563
564 case ptNumericText:
565 {
566 FXTextParamValue *textEntry=(FXTextParamValue *)parameters[t].second;
567 double ret=textEntry->getValue();
568
569 if(retValueConvs[t]!=NULL)
570 ret=retValueConvs[t](ret);
571
572 actionParameters->setValue<double>(textEntry->getName(),ret);
573 addedParameters.push_back(textEntry->getName());
574 }
575 break;
576
577 case ptStringText:
578 {
579 FXTextParamValue *textEntry=(FXTextParamValue *)parameters[t].second;
580 const string ret=textEntry->getText();
581 actionParameters->setValue<string>(textEntry->getName(),ret);
582 addedParameters.push_back(textEntry->getName());
583 }
584 break;
585
586 case ptDiskEntity:
587 {
588 FXDiskEntityParamValue *diskEntityEntry=(FXDiskEntityParamValue *)parameters[t].second;
589 const string ret=diskEntityEntry->getEntityName();
590
591 actionParameters->setValue<string>(diskEntityEntry->getName(),ret);
592
593 if(diskEntityEntry->getEntityType()==FXDiskEntityParamValue::detAudioFilename)
594 actionParameters->setValue<bool>(diskEntityEntry->getName()+" OpenAsRaw",diskEntityEntry->getOpenAsRaw());
595 addedParameters.push_back(diskEntityEntry->getName());
596 }
597 break;
598
599 case ptComboText:
600 {
601 FXComboTextParamValue *comboTextEntry=(FXComboTextParamValue *)parameters[t].second;
602 if(comboTextEntry->asString)
603 { // return the text of the item selected
604 actionParameters->setValue<string>(comboTextEntry->getName(),comboTextEntry->getStringValue());
605 }
606 else
607 { // return values as integer of the index that was selected
608 FXint ret=comboTextEntry->getIntegerValue();
609 actionParameters->setValue<unsigned>(comboTextEntry->getName(),(unsigned)ret);
610 }
611 addedParameters.push_back(comboTextEntry->getName());
612 }
613 break;
614
615 case ptCheckBox:
616 {
617 FXCheckBoxParamValue *checkBoxEntry=(FXCheckBoxParamValue *)parameters[t].second;
618 bool ret=checkBoxEntry->getValue();
619
620 actionParameters->setValue<bool>(checkBoxEntry->getName(),ret);
621 addedParameters.push_back(checkBoxEntry->getName());
622 }
623 break;
624
625 case ptGraph:
626 case ptGraphWithWaveform:
627 {
628 FXGraphParamValue *graph=(FXGraphParamValue *)parameters[t].second;
629 CGraphParamValueNodeList nodes=graph->getNodes();
630
631 if(retValueConvs[t]!=NULL)
632 {
633 for(size_t i=0;i<nodes.size();i++)
634 nodes[i].y=retValueConvs[t](nodes[i].y);
635 }
636
637 actionParameters->setValue<CGraphParamValueNodeList>(graph->getName(),nodes);
638 addedParameters.push_back(graph->getName());
639 }
640 break;
641
642 case ptLFO:
643 {
644 FXLFOParamValue *LFOEntry=(FXLFOParamValue *)parameters[t].second;
645 actionParameters->setValue<CLFODescription>(LFOEntry->getName(),LFOEntry->getValue());
646 addedParameters.push_back(LFOEntry->getName());
647 }
648 break;
649
650 case ptPluginRouting:
651 {
652 FXPluginRoutingParamValue *pluginRoutingEntry=(FXPluginRoutingParamValue *)parameters[t].second;
653 actionParameters->setValue<CPluginMapping>(pluginRoutingEntry->getName(),pluginRoutingEntry->getValue());
654 addedParameters.push_back(pluginRoutingEntry->getName());
655 }
656 break;
657
658 default:
659 throw runtime_error(string(__func__)+" -- unhandled parameter type: "+istring(parameters[t].first));
660 }
661 }
662 retval=true;
663 }
664 catch(EUserMessage &e)
665 {
666 if(e.what()[0])
667 {
668 Message(e.what());
669 for(size_t t=0;t<addedParameters.size();t++)
670 actionParameters->removeKey(addedParameters[t]);
671 goto reshow;
672 }
673 else
674 retval=false;;
675 }
676 }
677
678 // save the splitter's position
679 if(presetsFrame!=NULL)
680 {
681 FXint h2=presetsFrame->getHeight();
682 gSettingsRegistry->setValue<string>("FOX" DOT "SplitterPositions" DOT presetPrefix+getOrigTitle(),istring(h2));
683 }
684
685 hide(); // hide now and ...
686 #if FOX_MAJOR>0 // stupid debian's old crap
687 getApp()->repaint(); // force redraws from disappearing dialogs now
688 #endif
689
690 return retval;
691 }
692
hide()693 void CActionParamDialog::hide()
694 {
695 FXModalDialogBox::hide();
696 }
697
onPresetUseButton(FXObject * sender,FXSelector sel,void * ptr)698 long CActionParamDialog::onPresetUseButton(FXObject *sender,FXSelector sel,void *ptr)
699 {
700 CNestedDataFile *presetsFile;
701 FXList *listBox;
702 if(FXSELID(sel)==ID_NATIVE_PRESET_BUTTON || FXSELID(sel)==ID_NATIVE_PRESET_LIST)
703 {
704 presetsFile=gSysPresetsFile;
705 listBox=nativePresetList;
706 }
707 else //if(FXSELID(sel)==ID_USER_PRESET_BUTTON || FXSELID(sel)==ID_USER_PRESET_LIST)
708 {
709 presetsFile=gUserPresetsFile;
710 listBox=userPresetList;
711 }
712
713 try
714 {
715 if(listBox->getCurrentItem()<0)
716 {
717 gStatusComm->beep();
718 return 1;
719 }
720
721 const string name=string(listBox->getItemText(listBox->getCurrentItem()).text()).substr(4);
722 const string title=presetPrefix+getOrigTitle() DOT name;
723
724 for(unsigned t=0;t<parameters.size();t++)
725 {
726 switch(parameters[t].first)
727 {
728 case ptConstant:
729 ((FXConstantParamValue *)parameters[t].second)->readFromFile(title,presetsFile);
730 break;
731
732 case ptNumericText:
733 case ptStringText:
734 ((FXTextParamValue *)parameters[t].second)->readFromFile(title,presetsFile);
735 break;
736
737 case ptDiskEntity:
738 ((FXDiskEntityParamValue *)parameters[t].second)->readFromFile(title,presetsFile);
739 break;
740
741 case ptComboText:
742 ((FXComboTextParamValue *)parameters[t].second)->readFromFile(title,presetsFile);
743 break;
744
745 case ptCheckBox:
746 ((FXCheckBoxParamValue *)parameters[t].second)->readFromFile(title,presetsFile);
747 break;
748
749 case ptGraph:
750 case ptGraphWithWaveform:
751 ((FXGraphParamValue *)parameters[t].second)->readFromFile(title,presetsFile);
752 break;
753
754 case ptLFO:
755 ((FXLFOParamValue *)parameters[t].second)->readFromFile(title,presetsFile);
756 break;
757
758 case ptPluginRouting:
759 ((FXPluginRoutingParamValue *)parameters[t].second)->readFromFile(title,presetsFile);
760 break;
761
762 default:
763 throw runtime_error(string(__func__)+" -- unhandled parameter type: "+istring(parameters[t].first));
764 }
765 }
766 }
767 catch(exception &e)
768 {
769 Error(e.what());
770 }
771
772 return 1;
773 }
774
onPresetSaveButton(FXObject * sender,FXSelector sel,void * ptr)775 long CActionParamDialog::onPresetSaveButton(FXObject *sender,FXSelector sel,void *ptr)
776 {
777 FXString _name=userPresetList->getCurrentItem()>=0 ? (userPresetList->getItemText(userPresetList->getCurrentItem())).mid(4,255) : "";
778
779 askAgain:
780 if(FXInputDialog::getString(_name,this,_("Preset Name"),_("Preset Name")))
781 {
782 if(_name.trim()=="")
783 {
784 Error(_("Invalid Preset Name"));
785 goto askAgain;
786 }
787
788 string name=_name.text();
789
790 // make sure it doesn't contain DOT
791 if(name.find(CNestedDataFile::delim)!=string::npos)
792 {
793 Error(_("Preset Name cannot contain")+string(" '")+string(CNestedDataFile::delim)+"'");
794 goto askAgain;
795 }
796
797 try
798 {
799 CNestedDataFile *presetsFile=gUserPresetsFile;
800
801
802 const string title=presetPrefix+getOrigTitle() DOT name;
803
804 bool alreadyExists=false;
805 if(presetsFile->keyExists(title))
806 {
807 alreadyExists=true;
808 if(Question(_("Overwrite Existing Preset")+string(" '")+name+"'",yesnoQues)!=yesAns)
809 return 1;
810 }
811
812 for(unsigned t=0;t<parameters.size();t++)
813 {
814 switch(parameters[t].first)
815 {
816 case ptConstant:
817 ((FXConstantParamValue *)parameters[t].second)->writeToFile(title,presetsFile);
818 break;
819
820 case ptNumericText:
821 case ptStringText:
822 ((FXTextParamValue *)parameters[t].second)->writeToFile(title,presetsFile);
823 break;
824
825 case ptDiskEntity:
826 ((FXDiskEntityParamValue *)parameters[t].second)->writeToFile(title,presetsFile);
827 break;
828
829 case ptComboText:
830 ((FXComboTextParamValue *)parameters[t].second)->writeToFile(title,presetsFile);
831 break;
832
833 case ptCheckBox:
834 ((FXCheckBoxParamValue *)parameters[t].second)->writeToFile(title,presetsFile);
835 break;
836
837 case ptGraph:
838 case ptGraphWithWaveform:
839 ((FXGraphParamValue *)parameters[t].second)->writeToFile(title,presetsFile);
840 break;
841
842 case ptLFO:
843 ((FXLFOParamValue *)parameters[t].second)->writeToFile(title,presetsFile);
844 break;
845
846 case ptPluginRouting:
847 ((FXPluginRoutingParamValue *)parameters[t].second)->writeToFile(title,presetsFile);
848 break;
849
850 default:
851 throw runtime_error(string(__func__)+" -- unhandled parameter type: "+istring(parameters[t].first));
852 }
853 }
854
855 if(!alreadyExists)
856 {
857 const string key=presetPrefix+getOrigTitle() DOT "names";
858 vector<string> names=presetsFile->getValue<vector<string> >(key);
859 names.push_back(name);
860 presetsFile->setValue<vector<string> >(key,names);
861 buildPresetList(presetsFile,userPresetList);
862 }
863
864 presetsFile->save();
865 }
866 catch(exception &e)
867 {
868 Error(e.what());
869 }
870 }
871
872 return 1;
873 }
874
onPresetRemoveButton(FXObject * sender,FXSelector sel,void * ptr)875 long CActionParamDialog::onPresetRemoveButton(FXObject *sender,FXSelector sel,void *ptr)
876 {
877 if(userPresetList->getCurrentItem()>=0)
878 {
879 string name=(userPresetList->getItemText(userPresetList->getCurrentItem())).mid(4,255).text();
880 if(Question(_("Remove Preset")+string(" '")+name+"'",yesnoQues)==yesAns)
881 {
882 CNestedDataFile *presetsFile=gUserPresetsFile;
883
884 const string key=presetPrefix+getOrigTitle() DOT name;
885
886 // remove preset's values
887 presetsFile->removeKey(key);
888
889 // remove preset's name from the names array
890 vector<string> names=presetsFile->getValue<vector<string> >(presetPrefix+getOrigTitle() DOT "names");
891 names.erase(names.begin()+userPresetList->getCurrentItem());
892 presetsFile->setValue<vector<string> >(presetPrefix+getOrigTitle() DOT "names",names);
893
894 buildPresetList(presetsFile,userPresetList);
895 presetsFile->save();
896 }
897 }
898 else
899 gStatusComm->beep();
900
901 return 1;
902 }
903
buildPresetLists()904 void CActionParamDialog::buildPresetLists()
905 {
906 if(showPresetPanel)
907 {
908 bool firstTime=presetsFrame==NULL;
909
910 FXint currentNativePresetItem=nativePresetList ? nativePresetList->getCurrentItem() : 0;
911 FXint currentUserPresetItem=userPresetList ? userPresetList->getCurrentItem() : 0;
912
913 // delete previous stuff
914 delete presetsFrame;
915 nativePresetList=NULL;
916 userPresetList=NULL;
917
918 // (re)create GUI widgets
919 presetsFrame=new FXHorizontalFrame(splitter,FRAME_RAISED|FRAME_THICK | LAYOUT_FILL_X, 0,0,0,0, 2,2,2,2);
920 try
921 {
922 if(gSysPresetsFile->getValue<vector<string> >(presetPrefix+getOrigTitle() DOT "names").size()>0)
923 {
924 // native preset stuff
925 FXPacker *listFrame=new FXPacker(presetsFrame,FRAME_SUNKEN|FRAME_THICK|LAYOUT_FIX_WIDTH | LAYOUT_FILL_Y, 0,0,210,0, 0,0,0,0, 0,0); // had to do this because FXList won't take that frame style
926 nativePresetList=new FXList(listFrame,this,ID_NATIVE_PRESET_LIST,LIST_BROWSESELECT | LAYOUT_FILL_X|LAYOUT_FILL_Y);
927 nativePresetList->setNumVisible(4);
928 new FXButton(presetsFrame,_("&Use\tOr Double-Click an Item in the List"),NULL,this,ID_NATIVE_PRESET_BUTTON);
929 }
930 }
931 catch(exception &e)
932 {
933 nativePresetList=NULL;
934 Error(e.what());
935 }
936
937 // user preset stuff
938 FXPacker *listFrame=new FXPacker(presetsFrame,FRAME_SUNKEN|FRAME_THICK|LAYOUT_FIX_WIDTH | LAYOUT_FILL_Y, 0,0,210,0, 0,0,0,0, 0,0); // had to do this because FXList won't take that frame style
939 userPresetList=new FXList(listFrame,this,ID_USER_PRESET_LIST,LIST_BROWSESELECT | LAYOUT_FILL_X|LAYOUT_FILL_Y);
940 userPresetList->setNumVisible(4);
941 FXPacker *buttonGroup=new FXVerticalFrame(presetsFrame);
942 new FXButton(buttonGroup,_("&Use\tOr Double-Click an Item in the List"),NULL,this,ID_USER_PRESET_USE_BUTTON,BUTTON_NORMAL|LAYOUT_FILL_X);
943 new FXButton(buttonGroup,_("&Save"),NULL,this,ID_USER_PRESET_SAVE_BUTTON,BUTTON_NORMAL|LAYOUT_FILL_X);
944 new FXButton(buttonGroup,_("&Remove"),NULL,this,ID_USER_PRESET_REMOVE_BUTTON,BUTTON_NORMAL|LAYOUT_FILL_X);
945
946
947
948
949 // load presets from file
950
951 if(nativePresetList!=NULL)
952 {
953 try
954 {
955 buildPresetList(gSysPresetsFile,nativePresetList);
956 if(currentNativePresetItem<nativePresetList->getNumItems())
957 nativePresetList->setCurrentItem(currentNativePresetItem);
958 }
959 catch(exception &e)
960 {
961 Error(e.what());
962 nativePresetList->clearItems();
963 }
964 }
965
966 try
967 {
968 buildPresetList(gUserPresetsFile,userPresetList);
969 if(currentUserPresetItem<userPresetList->getNumItems())
970 userPresetList->setCurrentItem(currentUserPresetItem);
971 }
972 catch(exception &e)
973 {
974 Error(e.what());
975 userPresetList->clearItems();
976 }
977
978 // have to do this after the first showing, otherwise the presets won't show up until you resize the dialog
979 if(!firstTime)
980 presetsFrame->create();
981 }
982 }
983
buildPresetList(CNestedDataFile * f,FXList * list)984 void CActionParamDialog::buildPresetList(CNestedDataFile *f,FXList *list)
985 {
986 const vector<string> names=f->getValue<vector<string> >(presetPrefix+getOrigTitle() DOT "names");
987 list->clearItems();
988 for(size_t t=0;t<names.size();t++)
989 list->appendItem((istring(t,3,true)+" "+names[t]).c_str());
990 }
991
992
findParamByName(const string name) const993 unsigned CActionParamDialog::findParamByName(const string name) const
994 {
995 for(unsigned t=0;t<parameters.size();t++)
996 {
997 switch(parameters[t].first)
998 {
999 case ptConstant:
1000 if(((FXConstantParamValue *)parameters[t].second)->getName()==name)
1001 return t;
1002 break;
1003
1004 case ptNumericText:
1005 case ptStringText:
1006 if(((FXTextParamValue *)parameters[t].second)->getName()==name)
1007 return t;
1008 break;
1009
1010 case ptDiskEntity:
1011 if(((FXDiskEntityParamValue *)parameters[t].second)->getName()==name)
1012 return t;
1013 break;
1014
1015 case ptComboText:
1016 if(((FXComboTextParamValue *)parameters[t].second)->getName()==name)
1017 return t;
1018 break;
1019
1020 case ptCheckBox:
1021 if(((FXCheckBoxParamValue *)parameters[t].second)->getName()==name)
1022 return t;
1023 break;
1024
1025 case ptGraph:
1026 case ptGraphWithWaveform:
1027 if(((FXGraphParamValue *)parameters[t].second)->getName()==name)
1028 return t;
1029 break;
1030
1031 case ptLFO:
1032 if(((FXLFOParamValue *)parameters[t].second)->getName()==name)
1033 return t;
1034 break;
1035
1036 case ptPluginRouting:
1037 if(((FXPluginRoutingParamValue *)parameters[t].second)->getName()==name)
1038 return t;
1039 break;
1040
1041 default:
1042 throw runtime_error(string(__func__)+" -- unhandled parameter type: "+istring(parameters[t].first));
1043 }
1044 }
1045
1046 throw runtime_error(string(__func__)+" -- no param found named "+name);
1047 }
1048
1049