1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2002-2016 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "synthcontrol.h"
14 #include "musescore.h"
15 #include "seq.h"
16 #include "audio/midi/msynthesizer.h"
17 #include "audio/midi/synthesizer.h"
18 #include "audio/midi/synthesizergui.h"
19 #include "mixer/mixer.h"
20 #include "file.h"
21 #include "icons.h"
22 #include "libmscore/score.h"
23 #include "libmscore/mscore.h"
24 #include "libmscore/xml.h"
25 #include "libmscore/undo.h"
26 #include "effects/effectgui.h"
27 #include "libmscore/part.h"
28 #include "libmscore/instrument.h"
29
30 namespace Ms {
31
32 extern MasterSynthesizer* synti;
33 extern bool useFactorySettings;
34
35 //---------------------------------------------------------
36 // SynthControl
37 //---------------------------------------------------------
38
SynthControl(QWidget * parent)39 SynthControl::SynthControl(QWidget* parent)
40 : QWidget(parent, Qt::Dialog)
41 {
42 setObjectName("SynthControl");
43 setupUi(this);
44 _score = 0;
45
46 setWindowFlags(Qt::Tool);
47 // setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
48
49 int idx = 0;
50 for (Synthesizer* s : synti->synthesizer()) {
51 if (strcmp(s->name(), "Aeolus") == 0) // no gui for aeolus
52 continue;
53 tabWidget->insertTab(idx++, s->gui(), tr(s->name()));
54 s->gui()->synthesizerChanged();
55 connect(s->gui(), SIGNAL(valueChanged()), SLOT(setDirty()));
56 }
57
58 // effectA combo box
59 // effectStackA widget stack
60
61 effectA->clear();
62 for (Effect* e : synti->effectList(0)) {
63 effectA->addItem(tr(e->name()));
64 EffectGui* gui = e->gui();
65 if (gui) {
66 effectStackA->addWidget(gui);
67 connect(gui, SIGNAL(valueChanged()), SLOT(setDirty()));
68 }
69 }
70
71 effectB->clear();
72 for (Effect* e : synti->effectList(1)) {
73 effectB->addItem(tr(e->name()));
74 EffectGui* gui = e->gui();
75 if (gui) {
76 effectStackB->addWidget(gui);
77 connect(gui, SIGNAL(valueChanged()), SLOT(setDirty()));
78 }
79 }
80 readSettings();
81
82 updateGui();
83
84 storeButton->setEnabled(false);
85 recallButton->setEnabled(false);
86 changeTuningButton->setEnabled(false);
87
88 gainSlider->setLog(false);
89 gainSlider->setRange(synti->minGainAsDecibels, synti->maxGainAsDecibels);
90 gainSlider->setDclickValue1(synti->defaultGainAsDecibels);
91 gainSlider->setDclickValue2(synti->defaultGainAsDecibels);
92 gainSlider->setValue(synti->gainAsDecibels());
93
94 enablePlay = new EnablePlayForWidget(this);
95 connect(effectA, SIGNAL(currentIndexChanged(int)), SLOT(effectAChanged(int)));
96 connect(effectB, SIGNAL(currentIndexChanged(int)), SLOT(effectBChanged(int)));
97 connect(gainSlider, SIGNAL(valueChanged(double,int)), SLOT(gainChanged(double,int)));
98 connect(masterTuning, SIGNAL(valueChanged(double)), SLOT(masterTuningChanged(double)));
99 connect(changeTuningButton, SIGNAL(clicked()), SLOT(changeMasterTuning()));
100 connect(loadButton, SIGNAL(clicked()), SLOT(loadButtonClicked()));
101 connect(saveButton, SIGNAL(clicked()), SLOT(saveButtonClicked()));
102 connect(storeButton, SIGNAL(clicked()), SLOT(storeButtonClicked()));
103 connect(recallButton, SIGNAL(clicked()), SLOT(recallButtonClicked()));
104 connect(gainSlider, SIGNAL(valueChanged(double,int)), SLOT(setDirty()));
105 connect(dynamicsMethodList, SIGNAL(currentIndexChanged(int)), SLOT(dynamicsMethodChanged(int)));
106 connect(ccToUseList, SIGNAL(currentIndexChanged(int)), SLOT(ccToUseChanged(int)));
107 connect(switchExpr, SIGNAL(clicked()), SLOT(switchExprButtonClicked()));
108 connect(switchNonExpr,SIGNAL(clicked()), SLOT(switchNonExprButtonClicked()));
109 connect(resetExpr, SIGNAL(clicked()), SLOT(resetExprButtonClicked()));
110 }
111
112 //---------------------------------------------------------
113 // setGain
114 //---------------------------------------------------------
115
116 // synthesizer has signalled a gain change - update the slider
setGain(float val)117 void SynthControl::setGain(float val)
118 {
119 Q_UNUSED(val);
120 gainSlider->setValue(synti->gainAsDecibels());
121 }
122
123 //---------------------------------------------------------
124 // closeEvent
125 //---------------------------------------------------------
126
closeEvent(QCloseEvent * ev)127 void SynthControl::closeEvent(QCloseEvent* ev)
128 {
129 emit closed(false);
130 QWidget::closeEvent(ev);
131 }
132
133 //---------------------------------------------------------
134 // showEvent
135 //---------------------------------------------------------
136
showEvent(QShowEvent * e)137 void SynthControl::showEvent(QShowEvent* e)
138 {
139 enablePlay->showEvent(e);
140 QWidget::showEvent(e);
141 activateWindow();
142 setFocus();
143 }
144
145 //---------------------------------------------------------
146 // eventFilter
147 //---------------------------------------------------------
148
eventFilter(QObject * obj,QEvent * e)149 bool SynthControl::eventFilter(QObject* obj, QEvent* e)
150 {
151 if(enablePlay->eventFilter(obj, e))
152 return true;
153 return QWidget::eventFilter(obj, e);
154 }
155
keyPressEvent(QKeyEvent * ev)156 void SynthControl::keyPressEvent(QKeyEvent* ev) {
157 if (ev->key() == Qt::Key_Escape && ev->modifiers() == Qt::NoModifier) {
158 close();
159 return;
160 }
161 QWidget::keyPressEvent(ev);
162 }
163
164 //---------------------------------------------------------
165 // showSynthControl
166 //---------------------------------------------------------
167
showSynthControl(bool val)168 void MuseScore::showSynthControl(bool val)
169 {
170 QAction* a = getAction("synth-control");
171 if (synthControl == 0) {
172 synthControl = new SynthControl(this);
173 mscore->stackUnder(synthControl);
174 synthControl->setScore(cs);
175 connect(synti, SIGNAL(gainChanged(float)), synthControl, SLOT(setGain(float)));
176 connect(synthControl, SIGNAL(closed(bool)), a, SLOT(setChecked(bool)));
177 }
178 synthControl->setVisible(val);
179 }
180
181 //---------------------------------------------------------
182 // gainChanged
183 //---------------------------------------------------------
184
185 // user has moved the gain control on this widget - update the synthesizer
gainChanged(double val,int)186 void SynthControl::gainChanged(double val, int)
187 {
188 synti->setGainAsDecibels(val);
189 }
190
191 //---------------------------------------------------------
192 // masterTuningChanged
193 //---------------------------------------------------------
194
masterTuningChanged(double)195 void SynthControl::masterTuningChanged(double /*val*/)
196 {
197 changeTuningButton->setEnabled(true);
198 }
199
200 //---------------------------------------------------------
201 // changeMasterTuning
202 //---------------------------------------------------------
203
changeMasterTuning()204 void SynthControl::changeMasterTuning()
205 {
206 synti->setMasterTuning(masterTuning->value());
207 changeTuningButton->setEnabled(false);
208 setDirty();
209 }
210
211 //---------------------------------------------------------
212 // setMeter
213 //---------------------------------------------------------
214
setMeter(float l,float r,float left_peak,float right_peak)215 void SynthControl::setMeter(float l, float r, float left_peak, float right_peak)
216 {
217 gainSlider->setMeterVal(0, l, left_peak);
218 gainSlider->setMeterVal(1, r, right_peak);
219 }
220
221 //---------------------------------------------------------
222 // setScore
223 //---------------------------------------------------------
setScore(Score * s)224 void SynthControl::setScore(Score* s) {
225 _score = s;
226
227 loadButton->setEnabled(true);
228 saveButton->setEnabled(true);
229 }
230
231 //---------------------------------------------------------
232 // stop
233 //---------------------------------------------------------
234
stop()235 void SynthControl::stop()
236 {
237 gainSlider->setMeterVal(0, .0, .0);
238 gainSlider->setMeterVal(1, .0, .0);
239 }
240
241 //---------------------------------------------------------
242 // effectAChanged
243 //---------------------------------------------------------
244
effectAChanged(int idx)245 void SynthControl::effectAChanged(int idx)
246 {
247 synti->setEffect(0, idx);
248 effectStackA->setCurrentIndex(idx);
249 setDirty();
250 }
251
252 //---------------------------------------------------------
253 // effectBChanged
254 //---------------------------------------------------------
255
effectBChanged(int idx)256 void SynthControl::effectBChanged(int idx)
257 {
258 synti->setEffect(1, idx);
259 effectStackB->setCurrentIndex(idx);
260 setDirty();
261 }
262
263 //---------------------------------------------------------
264 // dynamicsMethodChanged
265 //---------------------------------------------------------
266
dynamicsMethodChanged(int val)267 void SynthControl::dynamicsMethodChanged(int val)
268 {
269 ccToUseList->setEnabled(val != 0);
270 synti->setDynamicsMethod(val);
271 setDirty();
272 }
273
274 //---------------------------------------------------------
275 // ccToUseChanged
276 //---------------------------------------------------------
277
ccToUseChanged(int val)278 void SynthControl::ccToUseChanged(int val)
279 {
280 synti->setCcToUseIndex(val);
281 setDirty();
282 }
283
284 //---------------------------------------------------------
285 // switchExprButtonClicked
286 //---------------------------------------------------------
287
switchExprButtonClicked()288 void SynthControl::switchExprButtonClicked()
289 {
290 _score->masterScore()->updateExpressive(MuseScore::synthesizer("Fluid"), true, true);
291 setAllUserBankController(true);
292 updateMixer();
293 }
294
295 //---------------------------------------------------------
296 // switchNonExprButtonClicked
297 //---------------------------------------------------------
298
switchNonExprButtonClicked()299 void SynthControl::switchNonExprButtonClicked()
300 {
301 _score->masterScore()->updateExpressive(MuseScore::synthesizer("Fluid"), false, true);
302 setAllUserBankController(true);
303 updateMixer();
304 }
305
306 //---------------------------------------------------------
307 // resetExprButtonClicked
308 //---------------------------------------------------------
309
resetExprButtonClicked()310 void SynthControl::resetExprButtonClicked()
311 {
312 setAllUserBankController(false);
313 _score->masterScore()->updateExpressive(MuseScore::synthesizer("Fluid"));
314 updateMixer();
315 }
316
317 //---------------------------------------------------------
318 // setAllUserBankController
319 //---------------------------------------------------------
320
setAllUserBankController(bool val)321 void SynthControl::setAllUserBankController(bool val)
322 {
323 _score->startCmd();
324 for (Part* p : _score->parts()) {
325 const InstrumentList* il = p->instruments();
326 for (auto it = il->begin(); it != il->end(); it++) {
327 Instrument* i = it->second;
328 for (Channel* c : i->channel()) {
329 _score->undo(new SetUserBankController(c, val));
330 }
331 }
332 }
333 _score->endCmd();
334 }
335
336 //---------------------------------------------------------
337 // loadButtonClicked
338 // load synthesizer settings from score
339 //---------------------------------------------------------
340
loadButtonClicked()341 void SynthControl::loadButtonClicked()
342 {
343 if (!_score)
344 return;
345 synti->setState(_score->synthesizerState());
346 updateGui();
347 loadButton->setEnabled(false);
348 saveButton->setEnabled(false);
349 storeButton->setEnabled(true);
350 recallButton->setEnabled(true);
351 changeTuningButton->setEnabled(false);
352 }
353
354 //---------------------------------------------------------
355 // saveButtonClicked
356 // save synthesizer settings to score
357 //---------------------------------------------------------
358
saveButtonClicked()359 void SynthControl::saveButtonClicked()
360 {
361 if (!_score)
362 return;
363 _score->startCmd();
364 SynthesizerState ss = synti->state();
365 if (_dirty || !_score->synthesizerState().isDefault())
366 ss.setIsDefault(false);
367 _score->undo(new ChangeSynthesizerState(_score, ss));
368 _score->endCmd();
369
370 updateExpressivePatches();
371 loadButton->setEnabled(false);
372 saveButton->setEnabled(false);
373 storeButton->setEnabled(true);
374 recallButton->setEnabled(true);
375 _dirty = false;
376 }
377
378 //---------------------------------------------------------
379 // recallButtonClicked
380 // load stored synthesizer settings
381 //---------------------------------------------------------
382
recallButtonClicked()383 void SynthControl::recallButtonClicked()
384 {
385 if (!_score) {
386 qDebug("no score");
387 return;
388 }
389
390 SynthesizerState state;
391 QString s(dataPath + "/synthesizer.xml");
392 QFile f(s);
393 if (!f.open(QIODevice::ReadOnly)) {
394 qDebug("cannot read synthesizer settings <%s>", qPrintable(s));
395 return;
396 }
397 XmlReader e(&f);
398 while (e.readNextStartElement()) {
399 if (e.name() == "Synthesizer")
400 state.read(e);
401 else
402 e.unknown();
403 }
404 state.setIsDefault(true);
405 synti->setState(state);
406 updateGui();
407
408 storeButton->setEnabled(false);
409 recallButton->setEnabled(false);
410
411 loadButton->setEnabled(true);
412 saveButton->setEnabled(true);
413 changeTuningButton->setEnabled(false);
414 }
415
416 //---------------------------------------------------------
417 // storeButtonClicked
418 // save synthesizer settings
419 //---------------------------------------------------------
420
storeButtonClicked()421 void SynthControl::storeButtonClicked()
422 {
423 if (!_score) {
424 qDebug("no score");
425 return;
426 }
427 synti->storeState();
428 updateExpressivePatches();
429 storeButton->setEnabled(false);
430 recallButton->setEnabled(false);
431 _dirty = false;
432 }
433
434 //---------------------------------------------------------
435 // Gui
436 //---------------------------------------------------------
437
updateGui()438 void SynthControl::updateGui()
439 {
440 masterTuning->setValue(synti->masterTuning());
441 setGain(synti->gain());
442
443 dynamicsMethodList->setCurrentIndex(synti->dynamicsMethod());
444 ccToUseList->setCurrentIndex(synti->ccToUseIndex());
445 if (dynamicsMethodList->currentIndex() == 0)
446 ccToUseList->setEnabled(false);
447 else
448 ccToUseList->setEnabled(true);
449
450 int idx = synti->indexOfEffect(0);
451 effectA->setCurrentIndex(idx);
452 effectStackA->setCurrentIndex(idx);
453 if (synti->effect(0) && synti->effect(0)->gui())
454 synti->effect(0)->gui()->updateValues();
455 if (synti->effect(1) && synti->effect(1)->gui())
456 synti->effect(1)->gui()->updateValues();
457
458 idx = synti->indexOfEffect(1);
459 effectB->setCurrentIndex(idx);
460 effectStackB->setCurrentIndex(idx);
461 for (Synthesizer* s : synti->synthesizer()) {
462 if (strcmp(s->name(), "Aeolus") == 0) // no gui for aeolus
463 continue;
464 s->gui()->synthesizerChanged();
465 }
466 }
467
468 //---------------------------------------------------------
469 // updateExpressivePatches
470 //---------------------------------------------------------
471
updateExpressivePatches()472 void SynthControl::updateExpressivePatches()
473 {
474 _score->masterScore()->rebuildAndUpdateExpressive(MuseScore::synthesizer("Fluid"));
475 updateMixer();
476 }
477
478 //---------------------------------------------------------
479 // updateMixer
480 //---------------------------------------------------------
481
updateMixer()482 void SynthControl::updateMixer()
483 {
484 if (mscore->getMixer())
485 mscore->getMixer()->updateTracks();
486 }
487
488 //---------------------------------------------------------
489 // setDirty
490 //---------------------------------------------------------
491
setDirty()492 void SynthControl::setDirty()
493 {
494 _dirty = true;
495 loadButton->setEnabled(true);
496 saveButton->setEnabled(true);
497 storeButton->setEnabled(true);
498 recallButton->setEnabled(true);
499 }
500
501 //---------------------------------------------------------
502 // writeSettings
503 //---------------------------------------------------------
504
writeSettings()505 void SynthControl::writeSettings()
506 {
507 QSettings settings;
508 settings.beginGroup(objectName());
509 settings.setValue("tab", tabWidget->currentIndex());
510 settings.endGroup();
511
512 MuseScore::saveGeometry(this);
513 }
514
515 //---------------------------------------------------------
516 // readSettings
517 //---------------------------------------------------------
518
readSettings()519 void SynthControl::readSettings()
520 {
521 if (!useFactorySettings) {
522 QSettings settings;
523 settings.beginGroup(objectName());
524 tabWidget->setCurrentIndex(settings.value("tab", 0).toInt());
525 settings.endGroup();
526 }
527 else {
528 tabWidget->setCurrentIndex(0);
529 }
530
531 MuseScore::restoreGeometry(this);
532 }
533
534 //---------------------------------------------------------
535 // changeEvent
536 //---------------------------------------------------------
537
changeEvent(QEvent * event)538 void SynthControl::changeEvent(QEvent *event)
539 {
540 QWidget::changeEvent(event);
541 if (event->type() == QEvent::LanguageChange)
542 retranslate();
543 }
544
545 }
546
547