1 //=============================================================================
2 //  MuseScore
3 //  Linux Music Score Editor
4 //
5 //  Copyright (C) 2002-2016 Werner Schweer and others
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 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19 
20 #include "mixertrackpart.h"
21 
22 #include "musescore.h"
23 
24 #include "libmscore/score.h"
25 #include "libmscore/part.h"
26 #include "mixer.h"
27 #include "mixertrackitem.h"
28 #include "seq.h"
29 #include "libmscore/undo.h"
30 #include "synthcontrol.h"
31 #include "audio/midi/msynthesizer.h"
32 #include "preferences.h"
33 #include "icons.h"
34 
35 namespace Ms {
36 
37 const QString MixerTrackPart::unselStyleLight = "#controlWidget {"
38                                        "      background: #aaa;"
39                                        "      border-left: 2px solid #ddd;"
40                                        "      border-top: 2px solid #ddd;"
41                                        "      border-right: 2px solid #777;"
42                                        "      border-bottom: 2px solid #777;"
43                                        "}";
44 
45 const QString MixerTrackPart::selStyleLight = "#controlWidget {"
46                                      "      background: #ccc;"
47                                      "      border-left: 2px solid #eee;"
48                                      "      border-top: 2px solid #eee;"
49                                      "      border-right: 2px solid #777;"
50                                      "      border-bottom: 2px solid #777;"
51                                      "}";
52 
53 
54 const QString MixerTrackPart::unselStyleDark = "#controlWidget {"
55                                        "      background: #444;"
56                                        "      border-left: 2px solid #888;"
57                                        "      border-top: 2px solid #888;"
58                                        "      border-right: 2px solid #000;"
59                                        "      border-bottom: 2px solid #000;"
60                                        "}"
61                                        ".expandBn {"
62                                        "     background-color: #aaa;"
63                                        "}";
64 
65 const QString MixerTrackPart::selStyleDark = "#controlWidget {"
66                                      "      background: #666;"
67                                      "      border-left: 2px solid #888;"
68                                      "      border-top: 2px solid #888;"
69                                      "      border-right: 2px solid #000;"
70                                      "      border-bottom: 2px solid #000;"
71                                      "}"
72                                      ".expandBn {"
73                                      "     background-color: #aaa;"
74                                      "}";
75 
76 
77 
78 //---------------------------------------------------------
79 //   MixerTrack
80 //---------------------------------------------------------
81 
MixerTrackPart(QWidget * parent,MixerTrackItemPtr mti,bool expanded)82 MixerTrackPart::MixerTrackPart(QWidget *parent, MixerTrackItemPtr mti, bool expanded) :
83       QWidget(parent), _mti(mti), _selected(false), _group(0)
84       {
85       setupUi(this);
86 
87       int numChannels = 0;
88       Part* part = _mti->part();
89       const InstrumentList* il = part->instruments();
90       for (auto it = il->begin(); it != il->end(); ++it) {
91             Instrument* instr = it->second;
92             numChannels += instr->channel().size();
93             }
94 
95       expandBn->setEnabled(numChannels > 1);
96       expandBn->setChecked(expanded);
97       expandBn->setIcon(expanded ? *icons[int(Icons::goPrevious_ICON)] : *icons[int(Icons::goNext_ICON)]);
98 
99       connect(expandBn, SIGNAL(toggled(bool)), SLOT(expandToggled(bool)));
100 
101       connect(soloBn, SIGNAL(toggled(bool)), SLOT(updateSolo(bool)));
102       connect(muteBn, SIGNAL(toggled(bool)), SLOT(updateMute(bool)));
103 
104       updateNameLabel();
105 
106       //set up rest
107 
108       Channel* chan = _mti->focusedChan();
109 
110       soloBn->setChecked(chan->solo());
111       muteBn->setChecked(chan->mute());
112 
113       chan->addListener(this);
114       volumeSlider->setValue(chan->volume());
115       volumeSlider->setToolTip(tr("Volume: %1").arg(QString::number(chan->volume())));
116       volumeSlider->setMaxValue(127);
117       volumeSlider->setMinValue(0);
118       volumeSlider->setDoubleClickValue(Channel::defaultVolume);
119       volumeSlider->setNumMajorTicks(10);
120       volumeSlider->setNumMinorTicks(4);
121 
122       QIcon iconSliderHead;
123       iconSliderHead.addFile(QStringLiteral(":/data/icons/mixer-slider-handle-vertical.svg"), QSize(), QIcon::Normal, QIcon::Off);
124       volumeSlider->setSliderHeadIcon(iconSliderHead);
125 
126       panSlider->setValue(chan->pan());
127       panSlider->setToolTip(tr("Pan: %1").arg(QString::number(chan->pan())));
128       panSlider->setMaxValue(127);
129       panSlider->setMinValue(0);
130       panSlider->setDclickValue1(64);
131 
132       connect(volumeSlider, SIGNAL(valueChanged(double)),      SLOT(volumeChanged(double)));
133       connect(panSlider,    SIGNAL(valueChanged(double, int)), SLOT(panChanged(double)));
134 
135       connect(volumeSlider, SIGNAL(sliderPressed()),    SLOT(controlSelected()));
136       connect(panSlider,    SIGNAL(sliderPressed(int)), SLOT(controlSelected()));
137       }
138 
139 //---------------------------------------------------------
140 //   expandToggled
141 //---------------------------------------------------------
142 
applyStyle()143 void MixerTrackPart::applyStyle()
144       {
145       QString style;
146       switch (preferences.effectiveGlobalStyle()){
147             case MuseScoreEffectiveStyleType::DARK_FUSION:
148                   style = _selected ? selStyleDark : unselStyleDark;
149                   break;
150             case MuseScoreEffectiveStyleType::LIGHT_FUSION:
151                   style = _selected ? selStyleLight : unselStyleLight;
152                   break;
153             }
154 
155       setStyleSheet(style);
156       }
157 
158 //---------------------------------------------------------
159 //   expandToggled
160 //---------------------------------------------------------
161 
expandToggled(bool expanded)162 void MixerTrackPart::expandToggled(bool expanded)
163       {
164       _group->expandToggled(_mti->part(), expanded);
165       expandBn->setIcon(expanded ? *icons[int(Icons::goPrevious_ICON)] : *icons[int(Icons::goNext_ICON)]);
166       }
167 
168 //---------------------------------------------------------
169 //   updateNameLabel
170 //---------------------------------------------------------
171 
updateNameLabel()172 void MixerTrackPart::updateNameLabel()
173       {
174       Part* part = _mti->part();
175       Channel* chan = _mti->focusedChan();
176       trackLabel->setText(part->partName());
177 
178       MidiPatch* mp = synti->getPatchInfo(chan->synti(), chan->bank(), chan->program());
179 
180 
181       QString tooltip = tr("Part Name: %1\n"
182                                 "Primary Instrument: %2\n"
183                                 "Bank: %3\n"
184                                 "Program: %4\n"
185                                 "Sound: %5")
186                   .arg(part->partName(),
187                        part->longName().replace("&", "&"),
188                        QString::number(chan->bank()),
189                        QString::number(chan->program()),
190                        mp ? mp->name : tr("~no sound~"));
191 
192       trackLabel->setToolTip(tooltip);
193 
194       QColor bgCol((QRgb)part->color());
195       QString colName = bgCol.name();
196       int val = bgCol.value();
197 
198       QString ss = QString(".QLabel {"
199                  "border: 2px solid black;"
200                  "background: %1;"
201                 "color: %2;"
202                  "padding: 6px 0px;"
203              "}").arg(colName, val > 128 ? "black" : "white");
204 
205       trackLabel->setStyleSheet(ss);
206 
207       //Update component colors
208       qreal h, s, v;
209       bgCol.getHsvF(&h, &s, &v);
210       QColor brightCol = QColor::fromHsvF(h, s, 1);
211       panSlider->setScaleValueColor(brightCol);
212       volumeSlider->setHilightColor(brightCol);
213       }
214 
215 //---------------------------------------------------------
216 //   paintEvent
217 //---------------------------------------------------------
218 
showEvent(QShowEvent * event)219 void MixerTrackPart::showEvent(QShowEvent* event)
220       {
221       if (!event->spontaneous())
222             applyStyle();
223       QWidget::showEvent(event);
224       }
225 
226 //---------------------------------------------------------
227 //   propertyChanged
228 //---------------------------------------------------------
229 
propertyChanged(Channel::Prop property)230 void MixerTrackPart::propertyChanged(Channel::Prop property)
231       {
232       Channel* chan = _mti->focusedChan();
233 
234       switch (property) {
235             case Channel::Prop::VOLUME: {
236                   volumeSlider->blockSignals(true);
237                   volumeSlider->setValue(chan->volume());
238                   volumeSlider->setToolTip(tr("Volume: %1").arg(QString::number(chan->volume())));
239                   volumeSlider->blockSignals(false);
240                   break;
241                   }
242             case Channel::Prop::PAN: {
243                   panSlider->blockSignals(true);
244                   panSlider->setValue(chan->pan());
245                   panSlider->setToolTip(tr("Pan: %1").arg(QString::number(chan->pan())));
246                   panSlider->blockSignals(false);
247                   break;
248                   }
249             case Channel::Prop::MUTE: {
250                   muteBn->blockSignals(true);
251                   muteBn->setChecked(chan->mute());
252                   muteBn->blockSignals(false);
253                   break;
254                   }
255             case Channel::Prop::SOLO: {
256                   soloBn->blockSignals(true);
257                   soloBn->setChecked(chan->solo());
258                   soloBn->blockSignals(false);
259                   break;
260                   }
261             case Channel::Prop::COLOR: {
262                   updateNameLabel();
263                   break;
264                   }
265             default:
266                   break;
267             }
268       }
269 
270 //---------------------------------------------------------
271 //   volumeChanged
272 //---------------------------------------------------------
273 
volumeChanged(double value)274 void MixerTrackPart::volumeChanged(double value)
275       {
276       _mti->setVolume(value);
277       volumeSlider->setToolTip(tr("Volume: %1").arg(QString::number(value)));
278       }
279 
280 //---------------------------------------------------------
281 //   panChanged
282 //---------------------------------------------------------
283 
panChanged(double value)284 void MixerTrackPart::panChanged(double value)
285       {
286       _mti->setPan(value);
287       panSlider->setToolTip(tr("Pan: %1").arg(QString::number(value)));
288       }
289 
290 //---------------------------------------------------------
291 //   updateSolo
292 //---------------------------------------------------------
293 
updateSolo(bool val)294 void MixerTrackPart::updateSolo(bool val)
295       {
296       _mti->setSolo(val);
297       }
298 
299 //---------------------------------------------------------
300 //   udpateMute
301 //---------------------------------------------------------
302 
updateMute(bool val)303 void MixerTrackPart::updateMute(bool val)
304       {
305       _mti->setMute(val);
306       }
307 
308 //---------------------------------------------------------
309 //   controlSelected
310 //---------------------------------------------------------
311 
controlSelected()312 void MixerTrackPart::controlSelected()
313       {
314       setSelected(true);
315       }
316 
317 //---------------------------------------------------------
318 //   mouseReleaseEvent
319 //---------------------------------------------------------
320 
mouseReleaseEvent(QMouseEvent *)321 void MixerTrackPart::mouseReleaseEvent(QMouseEvent*)
322       {
323       setSelected(true);
324       }
325 
326 //---------------------------------------------------------
327 //   setSelected
328 //---------------------------------------------------------
329 
setSelected(bool sel)330 void MixerTrackPart::setSelected(bool sel)
331       {
332       if (_selected == sel)
333             return;
334 
335       _selected = sel;
336 
337       emit(selectedChanged(sel));
338 
339       if (_selected && _group)
340             _group->notifyTrackSelected(this);
341 
342       applyStyle();
343       }
344 
345 }
346