1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2002-2011 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 <fenv.h>
21 
22 #include "musescore.h"
23 #include "libmscore/score.h"
24 #include "libmscore/instrument.h"
25 #include "libmscore/measure.h"
26 #include "libmscore/segment.h"
27 #include "libmscore/chordrest.h"
28 #include "libmscore/chord.h"
29 #include "libmscore/note.h"
30 #include "libmscore/undo.h"
31 #include "mixer/mixer.h"
32 #include "parteditbase.h"
33 #include "scoreview.h"
34 #include "playpanel.h"
35 #include "preferences.h"
36 #include "seq.h"
37 #include "audio/midi/msynthesizer.h"
38 #include "shortcut.h"
39 
40 #ifdef OSC
41 #include "ofqf/qoscserver.h"
42 #endif
43 
44 namespace Ms {
45 
46 extern MasterSynthesizer* synti;
47 
48 //---------------------------------------------------------
49 //   initOsc
50 //---------------------------------------------------------
51 
52 #ifndef OSC
initOsc()53 void MuseScore::initOsc()
54       {
55       }
56 
57 #else // #ifndef OSC
58 
59 //---------------------------------------------------------
60 //   initOsc
61 //---------------------------------------------------------
62 
initOsc()63 void MuseScore::initOsc()
64       {
65       if (!preferences.getBool(PREF_IO_OSC_USEREMOTECONTROL))
66             return;
67       int port = preferences.getInt(PREF_IO_OSC_PORTNUMBER);
68       QOscServer* osc = new QOscServer(port, qApp);
69 
70       PathObject* oo = new PathObject( "/addpitch", QVariant::Int, osc);
71       QObject::connect(oo, SIGNAL(data(int)), SLOT(oscIntMessage(int)));
72 
73       oo = new PathObject( "/tempo", QVariant::Int, osc);
74       QObject::connect(oo, SIGNAL(data(int)), SLOT(oscTempo(int)));
75       oo = new PathObject( "/volume", QVariant::Int, osc);
76       QObject::connect(oo, SIGNAL(data(int)), SLOT(oscVolume(int)));
77       oo = new PathObject( "/goto", QVariant::Int, osc);
78       QObject::connect(oo, SIGNAL(data(int)), SLOT(oscGoto(int)));
79       oo = new PathObject( "/select-measure", QVariant::Int, osc);
80       QObject::connect(oo, SIGNAL(data(int)), SLOT(oscSelectMeasure(int)));
81       for (int i = 1; i <= 12; i++ ) {
82             oo = new PathObject( QString("/vol%1").arg(i), QVariant::Double, osc);
83             QObject::connect(oo, SIGNAL(data(double)), SLOT(oscVolChannel(double)));
84             }
85       for(int i = 1; i <= 12; i++ ) {
86             oo = new PathObject( QString("/pan%1").arg(i), QVariant::Double, osc);
87             QObject::connect(oo, SIGNAL(data(double)), SLOT(oscPanChannel(double)));
88             }
89       for(int i = 1; i <= 12; i++ ) {
90             oo = new PathObject( QString("/mute%1").arg(i), QVariant::Double, osc);
91             QObject::connect(oo, SIGNAL(data(double)), SLOT(oscMuteChannel(double)));
92             }
93 
94       oo = new PathObject( "/open", QVariant::String, osc);
95       QObject::connect(oo, SIGNAL(data(QString)), SLOT(oscOpen(QString)));
96       oo = new PathObject( "/close-all", QVariant::Invalid, osc);
97       QObject::connect(oo, SIGNAL(data()), SLOT(oscCloseAll()));
98 
99       oo = new PathObject( "/plugin", QVariant::String, osc);
100       QObject::connect(oo, SIGNAL(data(QString)), SLOT(oscTriggerPlugin(QString)));
101 
102       oo = new PathObject( "/color-note", QVariant::List, osc);
103       QObject::connect(oo, SIGNAL(data(QVariantList)), SLOT(oscColorNote(QVariantList)));
104 
105       for (const Shortcut* s : Shortcut::shortcuts()) {
106             oo = new PathObject( QString("/actions/%1").arg(s->key().data()), QVariant::Invalid, osc);
107             QObject::connect(oo, SIGNAL(data()), SLOT(oscAction()));
108             }
109       }
110 
111 //---------------------------------------------------------
112 //   oscIntMessage
113 //---------------------------------------------------------
114 
oscIntMessage(int val)115 void MuseScore::oscIntMessage(int val)
116       {
117       if (val < 128) {
118             midiNoteReceived(0, val, 60);
119             midiNoteReceived(0, val, 0);
120             }
121       else
122             midiCtrlReceived(val-128, 22);
123       }
124 
oscAction()125 void MuseScore::oscAction()
126       {
127       PathObject* pathObject = qobject_cast<PathObject*>(sender());
128       QString path = pathObject->path().mid(9);
129       QAction* a = getAction(path.toLocal8Bit().data());
130       a->trigger();
131       }
132 
oscGoto(int m)133 void MuseScore::oscGoto(int m)
134       {
135       qDebug("GOTO %d", m);
136       if (cv == 0)
137             return;
138       cv->searchPage(m);
139       }
140 
oscSelectMeasure(int m)141 void MuseScore::oscSelectMeasure(int m)
142       {
143       qDebug("SelectMeasure %d", m);
144       if (cv == 0)
145             return;
146 //      cv->selectMeasure(m);
147       Score* score = cv->score();
148       int i = 0;
149       for (Measure* measure = score->firstMeasure(); measure; measure = measure->nextMeasure()) {
150             if (++i < m)
151                   continue;
152             score->selection().setState(SelState::RANGE);
153             score->selection().setStartSegment(measure->first());
154             score->selection().setEndSegment(measure->last());
155             score->selection().setStaffStart(0);
156             score->selection().setStaffEnd(score->nstaves());
157             score->selection().updateSelectedElements();
158             score->selection().setState(SelState::RANGE);
159             score->addRefresh(measure->canvasBoundingRect());
160             cv->adjustCanvasPosition(measure, true);
161             score->setUpdateAll();
162             score->update();
163             break;
164             }
165       }
166 
167 
oscOpen(QString path)168 void MuseScore::oscOpen(QString path)
169       {
170       qDebug("Open %s", qPrintable(path));
171       openScore(path);
172       }
173 
174 
oscCloseAll()175 void MuseScore::oscCloseAll()
176       {
177       qDebug("CloseAll");
178       while(cs != 0)
179           closeScore(cs);
180       }
181 
182 //---------------------------------------------------------
183 //   oscTempo
184 //---------------------------------------------------------
185 
oscTempo(int val)186 void MuseScore::oscTempo(int val)
187       {
188       if (val < 10)
189             val = 10;
190       if (val > 300)
191             val = 300;
192       qreal t = val * .01;
193       if (playPanel)
194             playPanel->setSpeed(t);
195       if (seq)
196             seq->setRelTempo(double(t));
197       }
198 
199 //---------------------------------------------------------
200 //   oscTriggerPlugin
201 //---------------------------------------------------------
202 
oscTriggerPlugin(QString)203 void MuseScore::oscTriggerPlugin(QString /*s*/)
204       {
205 #if 0 // TODO
206 #ifdef SCRIPT_INTERFACE
207       QStringList args = s.split(",");
208       if(args.length() > 0) {
209             int idx = pluginIdxFromPath(args.at(0));
210             if(idx != -1) {
211                   for(int i = 1; i < args.length()-1; i++) {
212                         addGlobalObjectToPluginEngine(qPrintable(args.at(i)), args.at(i+1));
213                         i++;
214                         }
215                   pluginTriggered(idx);
216                   }
217             }
218 #endif
219 #endif
220       }
221 
222 //---------------------------------------------------------
223 //   oscColorNote
224 //---------------------------------------------------------
oscColorNote(QVariantList list)225 void MuseScore::oscColorNote(QVariantList list)
226       {
227       qDebug() << list;
228       if(!cs)
229             return;
230       if (list.length() != 2 && list.length() != 3)
231             return;
232       int tick;
233       int pitch;
234       QColor noteColor("red"); //default to red
235       bool ok;
236       tick = list[0].toInt(&ok);
237       if (!ok)
238             return;
239       pitch = list[1].toInt(&ok);
240       if (!ok)
241             return;
242       if(list.length() == 3 && list[2].canConvert(QVariant::String)) {
243             QColor color(list[2].toString());
244             if(color.isValid())
245                   noteColor = color;
246             }
247 
248       Measure* measure = cs->tick2measure(Fraction::fromTicks(tick));
249       if(!measure)
250             return;
251       Segment* s = measure->findSegment(SegmentType::ChordRest, Fraction::fromTicks(tick));
252       if (!s)
253             return;
254       //get all chords in segment...
255       int n = cs->nstaves() * VOICES;
256       for (int i = 0; i < n; i++) {
257             Element* e = s->element(i);
258             if (e && e->isChordRest()) {
259                   ChordRest* cr = static_cast<ChordRest*>(e);
260                   if (cr->type() == ElementType::CHORD) {
261                         Chord* chord = static_cast<Chord*>(cr);
262                         for (Note* note : chord->notes()) {
263                               if (note->pitch() == pitch) {
264                                     cs->startCmd();
265                                     cs->undo(new ChangeProperty(note, Pid::COLOR, noteColor));
266                                     cs->endCmd();
267                                     return;
268                                     }
269                               }
270                         }
271                   }
272             }
273       }
274 //---------------------------------------------------------
275 //   oscVolume
276 //---------------------------------------------------------
277 
oscVolume(int val)278 void MuseScore::oscVolume(int val)
279       {
280       double v = val / 128.0;
281       synti->setGain(v);
282       }
283 
284 //---------------------------------------------------------
285 //   oscVolChannel
286 //---------------------------------------------------------
287 
oscVolChannel(double val)288 void MuseScore::oscVolChannel(double val)
289       {
290       if (!cs)
291             return;
292       PathObject* po = (PathObject*) sender();
293 
294       int i = po->path().mid(4).toInt() - 1;
295       auto& mms = cs->masterScore()->midiMapping();
296       if( i >= 0 && i < int(mms.size())) {
297             MidiMapping& mm = mms[i];
298             Channel* channel = mm.articulation();
299             int iv = lrint(val*127);
300             seq->setController(channel->channel(), CTRL_VOLUME, iv);
301             channel->setVolume(val * 100.0);
302             if (mixer)
303                   mixer->getPartAtIndex(i)->volume->setValue(val * 100.0);
304             }
305       }
306 
307 //---------------------------------------------------------
308 //   oscPanChannel
309 //---------------------------------------------------------
310 
oscPanChannel(double val)311 void MuseScore::oscPanChannel(double val)
312       {
313       if (!cs)
314             return;
315       PathObject* po = (PathObject*) sender();
316 
317       int i = po->path().mid(4).toInt() - 1;
318       auto& mms = cs->masterScore()->midiMapping();
319       if (i >= 0 && i < int(mms.size())) {
320             MidiMapping& mm = mms[i];
321             Channel* channel = mm.articulation();
322             int iv = lrint((val + 1) * 64);
323             seq->setController(channel->channel(), CTRL_PANPOT, iv);
324             channel->setPan(val * 180.0);
325             if (mixer)
326                   mixer->getPartAtIndex(i)->pan->setValue(val * 100.0);
327             }
328       }
329 
330 //---------------------------------------------------------
331 //   oscMuteChannel
332 //---------------------------------------------------------
333 
oscMuteChannel(double val)334 void MuseScore::oscMuteChannel(double val)
335       {
336       if (!cs)
337             return;
338       PathObject* po = (PathObject*) sender();
339 
340       int i = po->path().mid(5).toInt() - 1;
341       auto& mms = cs->masterScore()->midiMapping();
342       if (i >= 0 && i < int(mms.size())) {
343             MidiMapping& mm = mms[i];
344             Channel* channel = mm.articulation();
345             channel->setMute(val==0.0f ? false : true);
346             if (mixer)
347                   mixer->getPartAtIndex(i)->mute->setChecked(channel->mute());
348             }
349       }
350 #endif // #ifndef OSC
351 }
352 
353