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