332 lines
10 KiB
C++
332 lines
10 KiB
C++
//=============================================================================
|
|
// MuseScore
|
|
// Music Composition & Notation
|
|
// $Id: musescore.cpp 4961 2011-11-11 16:24:17Z lasconic $
|
|
//
|
|
// Copyright (C) 2002-2011 Werner Schweer and others
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License version 2.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
//=============================================================================
|
|
|
|
#include <fenv.h>
|
|
|
|
#include "musescore.h"
|
|
#include "libmscore/score.h"
|
|
#include "libmscore/instrument.h"
|
|
#include "libmscore/measure.h"
|
|
#include "libmscore/segment.h"
|
|
#include "libmscore/chordrest.h"
|
|
#include "libmscore/chord.h"
|
|
#include "libmscore/note.h"
|
|
#include "libmscore/undo.h"
|
|
#include "mixer.h"
|
|
#include "scoreview.h"
|
|
#include "playpanel.h"
|
|
#include "preferences.h"
|
|
#include "seq.h"
|
|
#include "synthesizer/msynthesizer.h"
|
|
|
|
#ifdef OSC
|
|
#include "ofqf/qoscserver.h"
|
|
#endif
|
|
|
|
namespace Ms {
|
|
|
|
extern MasterSynthesizer* synti;
|
|
|
|
//---------------------------------------------------------
|
|
// initOsc
|
|
//---------------------------------------------------------
|
|
|
|
#ifndef OSC
|
|
void MuseScore::initOsc()
|
|
{
|
|
}
|
|
|
|
#else // #ifndef OSC
|
|
|
|
//---------------------------------------------------------
|
|
// initOsc
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::initOsc()
|
|
{
|
|
if (!preferences.useOsc)
|
|
return;
|
|
int port = preferences.oscPort;
|
|
QOscServer* osc = new QOscServer(port, qApp);
|
|
|
|
PathObject* oo = new PathObject( "/addpitch", QVariant::Int, osc);
|
|
QObject::connect(oo, SIGNAL(data(int)), SLOT(oscIntMessage(int)));
|
|
|
|
oo = new PathObject( "/tempo", QVariant::Int, osc);
|
|
QObject::connect(oo, SIGNAL(data(int)), SLOT(oscTempo(int)));
|
|
oo = new PathObject( "/volume", QVariant::Int, osc);
|
|
QObject::connect(oo, SIGNAL(data(int)), SLOT(oscVolume(int)));
|
|
oo = new PathObject( "/goto", QVariant::Int, osc);
|
|
QObject::connect(oo, SIGNAL(data(int)), SLOT(oscGoto(int)));
|
|
oo = new PathObject( "/select-measure", QVariant::Int, osc);
|
|
QObject::connect(oo, SIGNAL(data(int)), SLOT(oscSelectMeasure(int)));
|
|
for (int i = 1; i <= 12; i++ ) {
|
|
oo = new PathObject( QString("/vol%1").arg(i), QVariant::Double, osc);
|
|
QObject::connect(oo, SIGNAL(data(double)), SLOT(oscVolChannel(double)));
|
|
}
|
|
for(int i = 1; i <= 12; i++ ) {
|
|
oo = new PathObject( QString("/pan%1").arg(i), QVariant::Double, osc);
|
|
QObject::connect(oo, SIGNAL(data(double)), SLOT(oscPanChannel(double)));
|
|
}
|
|
for(int i = 1; i <= 12; i++ ) {
|
|
oo = new PathObject( QString("/mute%1").arg(i), QVariant::Double, osc);
|
|
QObject::connect(oo, SIGNAL(data(double)), SLOT(oscMuteChannel(double)));
|
|
}
|
|
|
|
oo = new PathObject( "/open", QVariant::String, osc);
|
|
QObject::connect(oo, SIGNAL(data(QString)), SLOT(oscOpen(QString)));
|
|
oo = new PathObject( "/close-all", QVariant::Invalid, osc);
|
|
QObject::connect(oo, SIGNAL(data()), SLOT(oscCloseAll()));
|
|
|
|
oo = new PathObject( "/plugin", QVariant::String, osc);
|
|
QObject::connect(oo, SIGNAL(data(QString)), SLOT(oscTriggerPlugin(QString)));
|
|
|
|
oo = new PathObject( "/color-note", QVariant::List, osc);
|
|
QObject::connect(oo, SIGNAL(data(QVariantList)), SLOT(oscColorNote(QVariantList)));
|
|
|
|
for (const Shortcut* s : Shortcut::shortcuts()) {
|
|
oo = new PathObject( QString("/actions/%1").arg(s->key().data()), QVariant::Invalid, osc);
|
|
QObject::connect(oo, SIGNAL(data()), SLOT(oscAction()));
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// oscIntMessage
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::oscIntMessage(int val)
|
|
{
|
|
if (val < 128) {
|
|
midiNoteReceived(0, val, 60);
|
|
midiNoteReceived(0, val, 0);
|
|
}
|
|
else
|
|
midiCtrlReceived(val-128, 22);
|
|
}
|
|
|
|
void MuseScore::oscAction()
|
|
{
|
|
PathObject* pathObject = qobject_cast<PathObject*>(sender());
|
|
QString path = pathObject->path().mid(9);
|
|
QAction* a = getAction(path.toLocal8Bit().data());
|
|
a->trigger();
|
|
}
|
|
|
|
void MuseScore::oscGoto(int m)
|
|
{
|
|
qDebug("GOTO %d", m);
|
|
if (cv == 0)
|
|
return;
|
|
cv->searchPage(m);
|
|
}
|
|
|
|
void MuseScore::oscSelectMeasure(int m)
|
|
{
|
|
qDebug("SelectMeasure %d", m);
|
|
if (cv == 0)
|
|
return;
|
|
cv->selectMeasure(m);
|
|
}
|
|
|
|
|
|
void MuseScore::oscOpen(QString path)
|
|
{
|
|
qDebug("Open %s", qPrintable(path));
|
|
openScore(path);
|
|
}
|
|
|
|
|
|
void MuseScore::oscCloseAll()
|
|
{
|
|
qDebug("CloseAll");
|
|
while(cs != 0)
|
|
closeScore(cs);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// oscTempo
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::oscTempo(int val)
|
|
{
|
|
if (val < 0)
|
|
val = 0;
|
|
if (val > 127)
|
|
val = 127;
|
|
val = (val * 240) / 128;
|
|
if (playPanel)
|
|
playPanel->setRelTempo(val);
|
|
if (seq)
|
|
seq->setRelTempo(double(val));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// oscTriggerPlugin
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::oscTriggerPlugin(QString /*s*/)
|
|
{
|
|
#if 0 // TODO
|
|
QStringList args = s.split(",");
|
|
if(args.length() > 0) {
|
|
int idx = pluginIdxFromPath(args.at(0));
|
|
if(idx != -1) {
|
|
for(int i = 1; i < args.length()-1; i++) {
|
|
addGlobalObjectToPluginEngine(qPrintable(args.at(i)), args.at(i+1));
|
|
i++;
|
|
}
|
|
pluginTriggered(idx);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// oscColorNote
|
|
//---------------------------------------------------------
|
|
void MuseScore::oscColorNote(QVariantList list)
|
|
{
|
|
qDebug() << list;
|
|
if(!cs)
|
|
return;
|
|
if (list.length() != 2 && list.length() != 3)
|
|
return;
|
|
int tick;
|
|
int pitch;
|
|
QColor noteColor("red"); //default to red
|
|
bool ok;
|
|
tick = list[0].toInt(&ok);
|
|
if (!ok)
|
|
return;
|
|
pitch = list[1].toInt(&ok);
|
|
if (!ok)
|
|
return;
|
|
if(list.length() == 3 && list[2].canConvert(QVariant::String)) {
|
|
QColor color(list[2].toString());
|
|
if(color.isValid())
|
|
noteColor = color;
|
|
}
|
|
|
|
Measure* measure = cs->tick2measure(tick);
|
|
if(!measure)
|
|
return;
|
|
Segment* s = measure->findSegment(Segment::Type::ChordRest, tick);
|
|
if (!s)
|
|
return;
|
|
//get all chords in segment...
|
|
int n = cs->nstaves() * VOICES;
|
|
for (int i = 0; i < n; i++) {
|
|
Element* e = s->element(i);
|
|
if (e && e->isChordRest()) {
|
|
ChordRest* cr = static_cast<ChordRest*>(e);
|
|
if(cr->type() == Element::Type::CHORD) {
|
|
Chord* chord = static_cast<Chord*>(cr);
|
|
for (int idx = 0; idx < chord->notes().length(); idx++) {
|
|
Note* note = chord->notes()[idx];
|
|
if (note->pitch() == pitch) {
|
|
cs->startCmd();
|
|
cs->undo(new ChangeProperty(note, P_ID::COLOR, noteColor));
|
|
cs->endCmd();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------
|
|
// oscVolume
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::oscVolume(int val)
|
|
{
|
|
double v = val / 128.0;
|
|
synti->setGain(v);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// oscVolChannel
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::oscVolChannel(double val)
|
|
{
|
|
if(!cs)
|
|
return;
|
|
PathObject* po = (PathObject*) sender();
|
|
|
|
int i = po->path().mid(4).toInt() - 1;
|
|
QList<MidiMapping>* mms = cs->midiMapping();
|
|
if( i >= 0 && i < mms->size()) {
|
|
MidiMapping mm = mms->at(i);
|
|
Channel* channel = mm.articulation;
|
|
int iv = lrint(val*127);
|
|
seq->setController(channel->channel, CTRL_VOLUME, iv);
|
|
channel->volume = iv;
|
|
if (mixer)
|
|
mixer->partEdit(i)->volume->setValue(iv);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// oscPanChannel
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::oscPanChannel(double val)
|
|
{
|
|
if(!cs)
|
|
return;
|
|
PathObject* po = (PathObject*) sender();
|
|
|
|
int i = po->path().mid(4).toInt() - 1;
|
|
QList<MidiMapping>* mms = cs->midiMapping();
|
|
if( i >= 0 && i < mms->size()) {
|
|
MidiMapping mm = mms->at(i);
|
|
Channel* channel = mm.articulation;
|
|
int iv = lrint((val + 1) * 64);
|
|
seq->setController(channel->channel, CTRL_PANPOT, iv);
|
|
channel->volume = iv;
|
|
if (mixer)
|
|
mixer->partEdit(i)->pan->setValue(iv);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// oscMuteChannel
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::oscMuteChannel(double val)
|
|
{
|
|
if(!cs)
|
|
return;
|
|
PathObject* po = (PathObject*) sender();
|
|
|
|
int i = po->path().mid(5).toInt() - 1;
|
|
QList<MidiMapping>* mms = cs->midiMapping();
|
|
if( i >= 0 && i < mms->size()) {
|
|
MidiMapping mm = mms->at(i);
|
|
Channel* channel = mm.articulation;
|
|
channel->mute = (val==0.0f ? false : true);
|
|
if (mixer)
|
|
mixer->partEdit(i)->mute->setCheckState(val==0.0f ? Qt::Unchecked:Qt::Checked);
|
|
}
|
|
}
|
|
#endif // #ifndef OSC
|
|
}
|
|
|