Plugins for 3.x

Mis à jour il y a 2 jours

Not to be confused with Musescore 4's VST and VSTi feature. Other plugin versions see Plugin development.

Introduction

Edit this page to share Musescore 3 plugin programming knowledge. Discussion thread.

Writing and running plugins requires,

  • Musescore Studio installed,
  • Javascript knowledge, and
  • QML knowledge.

You own what you create.

QML

Written with just enough jargon inaccurately, like "the sun rises in the east"..

Qt company invented QML,

  1. rules to write .qml files, including
    • QML Types
      • Data, eg a Point has a X and a Y
      • UI, eg a Rectangle has width, height, color etc
  2. extended rules to write .qml files, by adding import statements
  3. rules to write C++ (.cpp, .h etc) files including separated copies share similar naming of some items above,
    • Qt Widget, fine-control UI programming.
    • QML Widget (Qt Quick Widget), abstract UI programming.

Note that item 3 is for Musescore main app devs only. Things with similar names use different rules, don't read the wrong doc.

//https://doc.qt.io/archives/qt-5.9/qtqml-documents-topic.html
import QtQuick 2.0
Rectangle {
    width: 100; height: 100
    color: "red"
    MouseArea {
        anchors.fill: parent
        onClicked: console.log("Button clicked!")
    }
}

Any of these work,

onClicked: console.log("Button clicked!") 
onClicked: function(){ console.log("Button clicked!") }

Use javascript / ECMAScript 7th edition function. Unsupported are arrow function, spread syntax, array.fill etc.

Musescore plugin qml

Musescore plugin qml uses,

  1. all rules of .qml files,
  2. functions made available by the Musescore dev team.

Capability and limitation

This non-exclusive list contains observations reported by coders.

  • Examples of basic functionality
    • Change a note's property such as pitch, color
    • Add or remove score elements such as notes, rests, symbol, text
    • Read or save tags in File > Score Properties
    • Play the audio of a score or part of score
    • Create a new staff (Cannot change its name afterwards)
    • Create/update text and symbols eg dynamics, lyrics etc
    • Create/update tempo
    • Change playback speed (cmd('playback-speed-increase'))
    • Mute or change volume of an instrument
    • Create/update MIDI Play Event
    • Conversion of a different score format to and from MuseScore
    • Send and receive score data through internet
    • Opens a local or online webpage inside MuseScore
    • Save or load a score or any file
    • Start another program on your Windows/iOS outside MuseScore
  • Seems unachievable (please share if you find workaround, for example a suitable cmd() command )

See also https://musescore.org/en/node/372023

Alternatives to QML plugin

Workflow and external editors

Edit plugin with,

Plugin scripts are cached at program startup. To run a script updated afterwards in external editor,

  • Restart Musescore and then run from the plugin menu; or
  • Load the script inside Plugin Creator
    • Inside the Plugin Creator, open an existing .qml file
    • Press run
    • After subsequent edits in external editor, it is required to press Refresh in the Plugin Creator.
    • It is not required to restart Musescore when using this method.

Code examples

copycat200.jpg

Copy and paste. Share yours.

Common tasks

Changing menu name, window behavior

Get elements

  • Read Score elements, internal score structure.
  • curScore.newCursor() to create a Cursor, transverse and find. For more info, open and study walk.qml
  • curScore.newCursor() to create a Cursor, sync with current mouse selection example
  • select with mouse click then get curScore.selection.elements[ ]
  • listen to state.selectionChanged, get curScore.selection example
  • select with curScore.selection.selectRange() , get curScore.selection example

Read meaningful info of element type

  • Print .name property.

Match and compare element types

enum2.png

Match and compare reliably with .type property eg  Accidental.FLAT . See enumeration / enum. These pages are useful,

Try log type enum string snippet and Makeshift REPL plugin function tester plugin for enum and keyword autocompletion.

Note starting time, ending time, duration (note value)

Note pitch

Placement of objects, cursor track and tick

cursor.rewindToTick(x) will only work correctly if there is a segment at x. Otherwise it will put the cursor at the next available segment (in the current track) after x, see https://musescore.org/en/node/345409#comment-1206211

Save settings to score, tagging

Save settings to OS

eg registry in windows

File saving and loading

Instrument / staff info eg instrument name, and channel audio status

Create/update MIDI Play Event

Fetching webpage

Starting another program, command line and parameters

Get UI theme status

Not engraving style

Browsing help sites

QML help sites

doc.qt.io

When browsing https://doc.qt.io, note that

  • "C++ classes" pages are not useful in qml.
  • Check qt version on URL. Musescore 3.6.2 requires Qt 5.9.9 syntax. Some pages can be auto redirected by changing "6" in URL to "5.9". eg changing https://doc.qt.io/qt-6/qml-qtquick-wheelevent.html to https://doc.qt.io/qt-5.9/qml-qtquick-wheelevent.html and refreshing jumps to https://doc.qt.io/archives/qt-5.9/qml-qtquick-wheelevent.html.
  • Use a matching the import module version number on pages returned from site search. eg site search "button" returns QtQuick 1 Button but not QtQuick 2 Button.

    url6.png
    url59.png
    text_cpp.png
    text_qml.png

musescore.org

plugin help sites

musescore.github.io

The cmd ( ) method

Unstable. Backup QML. Use cmd() to run internal program actions.

musescore.org

Useful Resource

The Plugin Base Component Musescore { }

  • Api doc
  • Component.onCompleted
    Run once, right after the plugin component is created, before console.log() is functional
  • You should not use Qt.quit() in your plugins, see this post on why, and possible different approaches. Qt.quit() crashes Musescore 4.0 plugins.
  • Set pluginType: "dock" for normal behavior eg stay on top; "dialog" is quite outdated.
  • Create plugin as an action instead of a persistent object with prop and methods, because when the user close and reopen the plugin window, it may cause unwanted behavior.
    • This post explains the nature of onRun() and Qt.quit(). The code Qt.quit() may not work the way you expect.
    • The plugin window onClosing Event is not accessable from QML. The [Plugin API base] is in a QQuickView in a QWidget window docked inside a QDockWidget , see code.
    • No way to detect plugin's open or closed.
    • After plugin window is closed, listeners will continue to run, eg experimental onScoreStateChanged Handler
    • Workaround palette-like plugin
    • use Qt Labs Settings to save data across sessions
    • other tips also check out the snippets and notes page

Score elements, internal score structure

Bundled resource (qrc protocol)

Searchable museScore 3.6.2 source code

Translation

Troubleshooting with help from community

Share your plugin

Licensing

  • Writing in QML language is unlikely to be the ground on which plugin script subjects to Qt licensing.
  • Opening in Musescore is unlikely to be the ground on which plugin script subjects to MuseScore 3 GPL licensing.

Credits