Skip to content

Commit

Permalink
Merge pull request #6090 from dmitrio95/plugin-api-instruments
Browse files Browse the repository at this point in the history
Instruments and channels API for plugins
  • Loading branch information
anatoly-os authored Jun 6, 2020
2 parents 9e2bc70 + 4ea5007 commit 4a1d51b
Show file tree
Hide file tree
Showing 15 changed files with 777 additions and 42 deletions.
21 changes: 1 addition & 20 deletions libmscore/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3668,27 +3668,8 @@ bool Score::switchLayer(const QString& s)
// appendPart
//---------------------------------------------------------

void Score::appendPart(const QString& name)
void Score::appendPart(const InstrumentTemplate* t)
{
static InstrumentTemplate defaultInstrument;
InstrumentTemplate* t;

t = searchTemplate(name);
if (t == 0) {
qDebug("appendPart: <%s> not found", qPrintable(name));
t = &defaultInstrument;
}

if (t->channel.empty()) {
Channel a;
a.setChorus(0);
a.setReverb(0);
a.setName(Channel::DEFAULT_NAME);
a.setBank(0);
a.setVolume(90);
a.setPan(0);
t->channel.append(a);
}
Part* part = new Part(this);
part->initFromInstrTemplate(t);
int n = nstaves();
Expand Down
3 changes: 1 addition & 2 deletions libmscore/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ class Score : public QObject, public ScoreElement {
const QList<Part*>& parts() const { return _parts; }

void appendPart(Part* p);
void appendPart(const InstrumentTemplate*);
void updateStaffIndex();
void sortStaves(QList<int>& dst);

Expand Down Expand Up @@ -1119,8 +1120,6 @@ class Score : public QObject, public ScoreElement {

QList<Score*> scoreList();
bool switchLayer(const QString& s);
//@ appends to the score a named part as last part
void appendPart(const QString&);
//@ appends to the score a number of measures
void appendMeasures(int);

Expand Down
2 changes: 1 addition & 1 deletion mscore/plugin/api/cursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ void Cursor::nextInTrack()

int Cursor::qmlKeySignature()
{
Staff* staff = _score->staves()[staffIdx()];
Ms::Staff* staff = _score->staves()[staffIdx()];
return static_cast<int>(staff->key(Fraction::fromTicks(tick())));
}

Expand Down
9 changes: 9 additions & 0 deletions mscore/plugin/api/elements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "elements.h"
#include "fraction.h"
#include "part.h"
#include "libmscore/property.h"
#include "libmscore/undo.h"

Expand Down Expand Up @@ -273,6 +274,14 @@ void Chord::remove(Ms::PluginAPI::Element* wrapped)
chord()->score()->deleteItem(s); // Create undo op and remove the element.
}

//---------------------------------------------------------
// Staff::part
//---------------------------------------------------------

Part* Staff::part()
{
return wrap<Part>(staff()->part());
}

//---------------------------------------------------------
// wrap
Expand Down
71 changes: 63 additions & 8 deletions mscore/plugin/api/elements.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "libmscore/notedot.h"
#include "libmscore/page.h"
#include "libmscore/segment.h"
#include "libmscore/staff.h"
#include "libmscore/tuplet.h"
#include "libmscore/accidental.h"
#include "libmscore/musescoreCore.h"
Expand All @@ -35,6 +36,8 @@ namespace PluginAPI {

class FractionWrapper;
class Element;
class Part;
class Staff;
class Tuplet;
class Tie;
extern Tie* tieWrap(Ms::Tie* tie);
Expand Down Expand Up @@ -84,6 +87,11 @@ class Element : public Ms::PluginAPI::ScoreElement {
* \since 3.3
*/
Q_PROPERTY(Ms::PluginAPI::Element* parent READ parent)
/**
* Staff which this element belongs to.
* \since MuseScore 3.5
*/
Q_PROPERTY(Ms::PluginAPI::Staff* staff READ staff)
/**
* X-axis offset from a reference position in spatium units.
* \see Element::offset
Expand Down Expand Up @@ -208,6 +216,7 @@ class Element : public Ms::PluginAPI::ScoreElement {
API_PROPERTY( beamMode, BEAM_MODE )
API_PROPERTY( beamNoSlope, BEAM_NO_SLOPE )
API_PROPERTY( userLen, USER_LEN )
/** For spacers: amount of space between staves. */
API_PROPERTY( space, SPACE )
API_PROPERTY( tempo, TEMPO )
API_PROPERTY( tempoFollowText, TEMPO_FOLLOW_TEXT )
Expand Down Expand Up @@ -300,10 +309,6 @@ class Element : public Ms::PluginAPI::ScoreElement {
API_PROPERTY( dashLineLen, DASH_LINE_LEN )
API_PROPERTY( dashGapLen, DASH_GAP_LEN )
// API_PROPERTY_READ_ONLY( tick, TICK ) // wasn't available in 2.X, disabled due to fractions transition
API_PROPERTY( playbackVoice1, PLAYBACK_VOICE1 )
API_PROPERTY( playbackVoice2, PLAYBACK_VOICE2 )
API_PROPERTY( playbackVoice3, PLAYBACK_VOICE3 )
API_PROPERTY( playbackVoice4, PLAYBACK_VOICE4 )
API_PROPERTY( symbol, SYMBOL )
API_PROPERTY( playRepeats, PLAY_REPEATS )
API_PROPERTY( createSystemHeader, CREATE_SYSTEM_HEADER )
Expand All @@ -317,10 +322,6 @@ class Element : public Ms::PluginAPI::ScoreElement {
API_PROPERTY( staffGenTimesig, STAFF_GEN_TIMESIG )
API_PROPERTY( staffGenKeysig, STAFF_GEN_KEYSIG )
API_PROPERTY( staffYoffset, STAFF_YOFFSET )
API_PROPERTY( staffUserdist, STAFF_USERDIST )
API_PROPERTY( staffBarlineSpan, STAFF_BARLINE_SPAN )
API_PROPERTY( staffBarlineSpanFrom, STAFF_BARLINE_SPAN_FROM )
API_PROPERTY( staffBarlineSpanTo, STAFF_BARLINE_SPAN_TO )
API_PROPERTY( bracketSpan, BRACKET_SPAN )
API_PROPERTY( bracketColumn, BRACKET_COLUMN )
API_PROPERTY( inameLayoutPosition, INAME_LAYOUT_POSITION )
Expand Down Expand Up @@ -377,6 +378,7 @@ class Element : public Ms::PluginAPI::ScoreElement {
QPointF pagePos() const { return element()->pagePos() / element()->spatium(); }

Ms::PluginAPI::Element* parent() const { return wrap(element()->parent()); }
Staff* staff() { return wrap<Staff>(element()->staff()); }

QRectF bbox() const;

Expand Down Expand Up @@ -792,6 +794,59 @@ class Page : public Element {
/// \endcond
};

//---------------------------------------------------------
// Staff
/// \since MuseScore 3.5
//---------------------------------------------------------

class Staff : public ScoreElement {
Q_OBJECT

API_PROPERTY_T( bool, small, SMALL )
API_PROPERTY_T( qreal, mag, MAG )
/**
* Staff color. See https://doc.qt.io/qt-5/qml-color.html
* for the reference on color type in QML.
*/
API_PROPERTY_T( QColor, color, COLOR )

/** Whether voice 1 participates in playback. */
API_PROPERTY_T( bool, playbackVoice1, PLAYBACK_VOICE1 )
/** Whether voice 2 participates in playback. */
API_PROPERTY_T( bool, playbackVoice2, PLAYBACK_VOICE2 )
/** Whether voice 3 participates in playback. */
API_PROPERTY_T( bool, playbackVoice3, PLAYBACK_VOICE3 )
/** Whether voice 4 participates in playback. */
API_PROPERTY_T( bool, playbackVoice4, PLAYBACK_VOICE4 )

API_PROPERTY_T( int, staffBarlineSpan, STAFF_BARLINE_SPAN )
API_PROPERTY_T( int, staffBarlineSpanFrom, STAFF_BARLINE_SPAN_FROM )
API_PROPERTY_T( int, staffBarlineSpanTo, STAFF_BARLINE_SPAN_TO )

/**
* User-defined amount of additional space before this staff.
* It is recommended to consider adding a spacer instead as it
* allows adjusting staff spacing locally as opposed to this
* property.
* \see \ref Element.space
*/
API_PROPERTY_T( qreal, staffUserdist, STAFF_USERDIST )

/** Part which this staff belongs to. */
Q_PROPERTY(Ms::PluginAPI::Part* part READ part);

public:
/// \cond MS_INTERNAL
Staff(Ms::Staff* staff, Ownership own = Ownership::PLUGIN)
: Ms::PluginAPI::ScoreElement(staff, own) {}

Ms::Staff* staff() { return toStaff(e); }
const Ms::Staff* staff() const { return toStaff(e); }

Part* part();
/// \endcond
};

#undef API_PROPERTY
#undef API_PROPERTY_T
#undef API_PROPERTY_READ_ONLY
Expand Down
163 changes: 163 additions & 0 deletions mscore/plugin/api/instrument.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA
//
// 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 "instrument.h"

#include "audio/midi/midipatch.h"
#include "libmscore/part.h"
#include "libmscore/score.h"
#include "libmscore/undo.h"

namespace Ms {
namespace PluginAPI {

//---------------------------------------------------------
// Channel::activeChannel
//---------------------------------------------------------

Ms::Channel* Channel::activeChannel()
{
Ms::Score* score = _part->score();
Ms::MasterScore* masterScore = score->masterScore();

if (masterScore->playbackScore() == score)
return masterScore->playbackChannel(_channel);
return _channel;
}

//---------------------------------------------------------
// Channel::setMidiBankAndProgram
//---------------------------------------------------------

void Channel::setMidiBankAndProgram(int bank, int program, bool setUserBankController)
{
Ms::Channel* ch = activeChannel();

MidiPatch patch;
// other values are unused in ChangePatch command
patch.synti = ch->synti();
patch.bank = bank;
patch.prog = program;

Ms::Score* score = _part->score();
score->undo(new ChangePatch(score, ch, &patch));

if (setUserBankController)
score->undo(new SetUserBankController(ch, true));
}

//---------------------------------------------------------
// Channel::setMidiProgram
//---------------------------------------------------------

void Channel::setMidiProgram(int prog)
{
prog = qBound(0, prog, 127);
setMidiBankAndProgram(activeChannel()->bank(), prog, false);
}

//---------------------------------------------------------
// Channel::setMidiBank
//---------------------------------------------------------

void Channel::setMidiBank(int bank)
{
bank = qBound(0, bank, 255);
setMidiBankAndProgram(bank, activeChannel()->program(), true);
}

//---------------------------------------------------------
// StringData::stringList
//---------------------------------------------------------

QVariantList StringData::stringList() const
{
QVariantList pluginStringsList;
for (instrString str : _data.stringList()) {
QVariantMap pluginStringData;
pluginStringData["pitch"] = str.pitch;
pluginStringData["open"] = str.open;
pluginStringsList.append(pluginStringData);
}
return pluginStringsList;
}

//---------------------------------------------------------
// ChannelListProperty
//---------------------------------------------------------

ChannelListProperty::ChannelListProperty(Instrument* i)
: QQmlListProperty<Channel>(i, i, &count, &at) {}

//---------------------------------------------------------
// ChannelListProperty::count
//---------------------------------------------------------

int ChannelListProperty::count(QQmlListProperty<Channel>* l)
{
return static_cast<int>(static_cast<Instrument*>(l->data)->instrument()->channel().size());
}

//---------------------------------------------------------
// ChannelListProperty::at
//---------------------------------------------------------

Channel* ChannelListProperty::at(QQmlListProperty<Channel>* l, int i)
{
Instrument* instr = static_cast<Instrument*>(l->data);

if (i < 0 || i >= instr->instrument()->channel().size())
return nullptr;

Ms::Channel* ch = instr->instrument()->channel(i);

return customWrap<Channel>(ch, instr->part());
}

//---------------------------------------------------------
// Instrument::longName
//---------------------------------------------------------

QString Instrument::longName() const
{
const QList<Ms::StaffName>& names = instrument()->longNames();
return names.empty() ? "" : names[0].name();
}

//---------------------------------------------------------
// Instrument::shortName
//---------------------------------------------------------

QString Instrument::shortName() const
{
const QList<Ms::StaffName>& names = instrument()->shortNames();
return names.empty() ? "" : names[0].name();
}

//---------------------------------------------------------
// Instrument::channels
//---------------------------------------------------------

ChannelListProperty Instrument::channels()
{
return ChannelListProperty(this);
}

} // namespace PluginAPI
} // namespace Ms
Loading

0 comments on commit 4a1d51b

Please sign in to comment.