Plugins for 3.x

Updated 2 weeks ago

    This chapter is for MuseScore 3 plugin developers.
    For info on what plugins are, how to install and use them, visit Musescore 3 handbook plugin section
    For info on editing and building the MuseScore main program, visit the main sections in Developers' handbook
    For MuseScore 2 plugin development, visit Plugins for 2.x
    For MuseScore 1 plugin development, visit Plugins for 1.x

    Introduction

    This chapter aims to provide knowledge, code snippets and work-arounds for better understanding and programming of MuseScore plugin system. Anyone working on plugins are welcomed to document their learnings and experiences. To add your input, register a musescore.org account and login, click the ⠇ to the right of the title, choose Edit. For discussion about this chapter itself visit this forum thread. Before editing please read the Administrative guidelines.

    MuseScore 3 the main program is mostly written in C++ utilizing Qt framework 5.9.9, developers expose a minimal collection of frequently used functions and data as API to allow plugin development beyond MuseScore's built-in features.

    MuseScore 3 plugins use the QML language of Qt framework, which is a declarative language that provide visual user interfaces, along with the Qt JavaScript host environment it allows interaction programming with a restricted version of javascript

    MuseScore 3 plugin creation does not require C++ knowledge

    Web devs might not need to learn QML, use this boilerplate plus html, css and js code to create your plugin.

    What is QML and javascript

    Capability and limitation

    The current API fulfil most common needs. Some functionilities of Musescore the main program are yet to be available as plugin API, advanced dev often utilize non-API methods. Developers of MuseScore do not have resource to maintain and expose every function and data as API.

    • 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
      • Playback the audio of a score or part of score
      • Mute or change volume of an instrument
      • Manipulate MIDI Events
      • 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
    • Unachievable by plugin ( Please share your workaround )
      • Run plugin when audio is playing, or detect whether audio is playing
      • Directly changing the playback cursor displayed
      • Create a new instrument in a score
      • Change any instrument's name
      • To read data inside a frame, user must select it with a mouse click first.
      • Add spanners such as pedal marking to a score
      • Create or update key signatures in a score
      • Get current "Concert Pitch" status
      • Mimic a click on a palette item
      • Add plugin as a toolbar button
      • Add plugin as an item in right click context menu
      • Manipulation of MuseScore's window eg minimize

    Alternatives to plugin

    • Edit a score file as plaintext:
      • save as .mscz : rename as .zip, extract, edit, zip ; or
      • save as .mscx and edit
    • Install Musescore Nightly and use the (experimental) scripting/macro function to record and replay sequence of commands
    • Write a plugin outside the build-in QML plugin system

    Where to begin

    MuseScore Plugin writing is not rocket science, you may be suprised how easily things are done.

    Quickstart boilerplates, snippets and use cases

    This section gathers reusable code snippets and boilerplates to help beginners get things done without a hassle. Copy and paste to your plugin, tweak it to your liking. Also check out specific use cases and notes.

    Learn more

    Workflow

    Hot reloading (auto build) and auto-complete are absent in Plugin Creator. The developers of Musescore 4 are aware of its flaws and plan to replace it in later releases. While waiting for upgrades,
    the best option for hot reloading right now

    • Edit your .qml in an external text editor
    • Inside the Plugin Creator, browser to and open the .qml file
    • Edit code and save in external text editor
    • Press refresh in the Plugin Creator
    • Press run

    The best options for auto complete (QML syntax only, not auto reference or API auto complete)

    Don't reinvent the wheel

    • Search plugins on musescore.org, someone may have already made one in Musescore 2 or Musescore 1, remember you can always try to use an old version of MuseScore (Change search filter to find them).
    • Search plugins on github
    • Study their source code, sometimes all you need to do is a few tweak.
    • Seek help from the author via a comment under the repo or ask in the plugin forum.
    • Try Element Analyser plugin which aims to provide a reusable library

    Useful Resource

    Searchable github repo

    • A searchable MuseScore 3.6.2 source code fork for reference. Github.com's code search on the offical repo returns current master ie MuseScore 4 up-to-date version, its 3.6.2 tag branch is not searchable online because github disallow code search on forked repos.

    Plugin API Documentation

    The Plugin API Documentation is automatically generated (in Doxygen format) whenever MuseScore developers build the main program. It is normal for beginners to be startled by its complexity.Use the search on the top right, instead of menu navigation.
    Notes on API written by fellow musescore.org users, feel free to pitch in
    List of all API object types
    Namespace/enum list in api doc contains enumerables, eg understand why Element.NOTE represents the element.type number.

    To build UI

    Use the QML

    Qt Quick Controls, the anchors and Qt Quick Layouts may suffice, using Qt Widgets from QML may be overkill not worth your time.
    Note: doc.qt.io search sometimes returns an expected outdated page, eg QtQuick 1 Button instead of current QtQuick 2 Button
    List of all QML components for Qt 5.9
    Anchors enum
    Keys enum list eg Qt.Key_Space
    Mouse button enum list eg Qt.LeftButton, more on mouse see this notes
    QtQuick Type properties for disabled, qmlssed, checked, checkable, focused, highlighted, flat, mirrored, hovered etc.
    Settings{ }
    Musescore.org users' notes on QML and snippets

    and/or

    Use a WebEngine plus html, css and javascript

    See the two boilerplates
    Alternative to QML components, utilize hybrid view built with html, css and standard javascript thru a 100% width and height WebEngine, its version in MuseScore 3 (Qt 5.9) is based on Chromium version 56.0.2924.122. WebEngineView fetches url, search data on html and runs javascript from QML side only, to communicate bidirectionally between QML and webpage use it with WebChannel.
    This standard set of javascript is used with a Chromium based engine, for tech compatibility check on caniuse.com (find Chrome v56), eg css display:grid is unsupported. This js set should not be confused with the other restricted set in QML functions, more info in Caution section

    The following javascript inside WebEngine works:

    • Arrow function
    • template-literals ie `string${var}`
    • DOMParser().parseFromString("html")

    The following css works:

    • Flex

    The following css will not work:

    • Gap
    • Grid

    Note: WebView 1.1 is an older component and use a different engine which does not offer simple WebChannel support, try WebSocket.

    Bundled resource

    List of every qrc:/// in musescore.qrc, ref
    Icons, symbols and fonts(not soundfont) see this snippet
    MuseScore dev team designs and uses its own two sets of styles, their details are not exposed as API yet, find them in github repo (then plz share link here).

    import QML Module Versions

    Musescore 3.6.2 use Qt 5.9.9, for latest version of common modules use:

    import MuseScore 3.0
    import QtQuick 2.9
    import QtQuick.Controls 2.2
    import QtQuick.Layouts 1.2
    import Qt.labs.settings 1.0
    import FileIO 3.0
    import QtWebEngine 1.5
    import QtWebChannel 1.0

    The powerful unofficial / non API method

    Translation

    see Internationalization

    Caution

    API inheritance versus Score Structure

    Beginners into programming may get confused with API Class Inheritance Hierarchy and Musescore runtime internal score structure hierarchy, read up on inheritance object oriented programming, also try out the debugger

    Javascript issues

    A different non-QML javascript API was used in MuseScore 1.x. While one can still learn a lot reading those files, they use the old API and will not work with current one. One way to spot the old API is presence of new Cursor(curScore) . The current QML system use curScore.newCursor()

    The QML functions use a restricted version of javascript, the following will not work:

    • Arrow function
    • Spread syntax
    • Array.fill

    To write modular codes, QML has import .js

    Inside QML WebEngine, a standard javascript runs on outdated Chromium v56 engine, more info in UI section

    QML list and javascript array

    • in QML [ ] declares a list, which can only store QML objects
    • typeof list == 'object'
    • array use var eg property var anArray: [1, 2, 3, "four", "five", (function() { return "six"; })]
    • inside functions, declaration is same as standard javascript: var anArray=[]

    UI Styles

    Qt Quick Controls style unsupported, see reasons
    MuseScore dev team designs and uses its own two sets of styles, their details are not exposed as API yet, find them in github repo (then plz share link here).
    Above concerns UI component styles, not engraving style

    The Plugin Base Component Musescore { }

    • Component.onCompleted
      Run once, right after the plugin component is created, before console.log() is functional
    • You probably should not use Qt.Quit in your plugins
      See this post on why, and possible different approaches.
    • 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

    Troubleshooting with help from community

    If you are having difficulty, try

    • Identify whether the problem is related to QML, or javascript, or the MuseScore plugin API. If it is QML or javascript, you can seek help from sites like stackoverflow and forum.qt.io in addition to musescore.org
    • Use google and the musescore.org forum search before posting new questions.
      search.png

    • Ask politely in the plugins forum, provide a Minimal, Reproducible Example if possible, the community is usually more than happy to help.
      Do come back and help others by adding your valuable discovery to this handbook.

    Share your plugin

    Plugin could be posted as a project on musescore.org without any github knowledge. Chat with other dev at the plugin forum.

    Licensing

    Following is not written by a lawyer, consult a real one if you are concerned with licensing.
    Qt licenses do not affect scripts solely on the basis that they are written in the QML language per se, more info consult Qt dual licensing.
    MuseScore 3 use GPL which is copyleft, derivative work using MuseScore code base, once conveyed, must follow. As long as your plugin does not use MuseScore code base, it should not be a concern, though the matter remains debatable.

    Credits

    API 3.5 thanks to
    dmitrio95,
    and many others

    Reference footnote

    import API FileIO module version
    import module version at Qt
    import module version at wikipedia
    import WebChannel module version

    External links

    API 3.5 source code reference
    A searchable MuseScore 3.6.2 github repo
    github/master/ API source code dir (as of Sep2022)