Technical Documentation: musescore/MuseScore
โน๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference
Overview (README.md)
Music notation and composition software
MuseScore Studio is an open source and free music notation software. For support, contribution, and bug reports visit MuseScore.org. Fork and make pull requests!
Features
- WYSIWYG design, notes are entered on a "virtual notepaper"
- TrueType font(s) for printing & display allows for high quality scaling to all sizes
- Easy & fast note entry
- Many editing functions
- MusicXML import/export
- MIDI (SMF) import/export
- MEI import/export
- MuseData import
- MIDI input for note entry
- Integrated sequencer and software synthesizer to play the score
- Print or create PDF files
More info
- MuseScore Studio Homepage
- MuseScore Studio Git workflow instructions
- How to compile MuseScore Studio?
License
MuseScore Studio is licensed under GPL version 3.0. See license file in the same directory.
Packages
Building
Read the Compilation section of the MuseScore Wiki for a complete build walkthrough and a list of dependencies.
Getting sources
If using git to download repo of entire code history, type:
git clone --recurse-submodules https://github.com/musescore/MuseScore.git
cd MuseScore(The --recurse-submodules ensures that the muse_framework git submodule is checked out into the muse/ subdirectory.)
Otherwise, you can just download the latest source release tarball from the Releases page, and then from your download directory type:
tar xzf MuseScore-x.x.x.tar.gz
cd MuseScore-x.x.xRelease Build
To compile MuseScore Studio for release, type:
cmake -P build.cmake -DCMAKE_BUILD_TYPE=ReleaseOn MacOS, append -G Ninja in order to use the ninja build tool (which you may need to install), since this
is required to compile Swift components.
If something goes wrong, append the word "clean" to the above command to delete the build subdirectory:
cmake -P build.cmake -DCMAKE_BUILD_TYPE=Release cleanThen try running the first command again.
Running
To start MuseScore Studio, type:
cmake -P build.cmake -DCMAKE_BUILD_TYPE=Release runOr run the compiled executable directly.
Debug Build
A debug version can be built and run by replacing -DCMAKE_BUILD_TYPE=Release
with -DCMAKE_BUILD_TYPE=Debug in the above commands.
If you omit the -DCMAKE_BUILD_TYPE option entirely then RelWithDebInfo is
used by default, as it provides a useful compromise between Release and Debug.
Testing
See the Unit tests section of the MuseScore Studio Wiki for instructions on how to run the test suite.
Code Formatting
Run ./hooks/install.sh to install a pre-commit hook that will format your staged files. Requires that you install uncrustify.
If you have problems, please report them. To uninstall, run ./hooks/uninstall.sh.
README (`docs/README.md`)
We use the jsdoc tool to create API documentation.
What does the documentation consist of:
- Static documentation - here is a tutorial and description of classes
- Description of API methods - located in the API implementation files.
- Snapshots - here is the generated documentation for each version.
- index.html - this is the entry point for https://musescore.github.io
- Tools for generation - here you will find a documentation extractor for API methods, a documentation generator (jsdoc) and automation scripts.
- Generation and update process - see description below
Static documentation
location: docs/apidocs_static
This is where static documentation is stored in the jsdoc format.
- index.md - home page of documentation
- Tutorials - see jsdoc documentation about tutorials.
Description of API
Descriptions of API methods are located in .cpp,.h files where the implementation of the methods is located.
The description is in jsdoc format (see https://jsdoc.app), but the first line should indicate that this is APIDOC documentation.
Namesapces
Like api.log., api.interactive....
/** APIDOC
* Write messages to log and console
* @namespace log
*/
LogApi::LogApi(api::IApiEngine* e)
: ApiObject(e)
{
}There must be the @namespace tag with the namespace name
Classes (types)
/** APIDOC
* Class representing a lyric.
* @class Lyric
* @hideconstructor
*/
class Lyric : public EngravingItem
{
...There must be the @class tag with the class name
If the type cannot be created in js using the new operator,
then we need to add the @hideconstructor tag
Methods
/** APIDOC
* Show information message
* @method
* @param {String} title Title
* @param {String} text Message
*/
void InteractiveApi::info(const QString& contentTitle, const QString& text)
{There must be the @method tag
Properties
/** APIDOC @property {number} - count of lyrics */
int Score::lyricCount() constThere must be the @property tag, the description should be in one line
Enums
/** APIDOC
* Question buttons
* @enum
*/
enum Button {
...
};There must be the @enum tag
When generating documentation, we first extract this documentation from the cpp files.
Snapshots
location: snapshots
To be able to view the documentation for each version, we generate snapshots of the documentation for each version and place them in the appropriate folder, for example: snapshots/4.5, snapshots/4.6
index.html
location: index.html - this is the entry point for https://musescore.github.io
After generating a snapshot for a new version, we need to add a link to it in this index.html, like others.
Tools for generation
location: tools/jsdoc
List of tools:
- template - template for
jsdoc - jsdoc_extractor.js - this is a documentation extractor from
cppfiles. It extracts documentation and stores it in temporary, fakejsfiles so thatjsdoccan process them. - conf.json - file of configuration for
jsdoc - jsdoc_install.sh - script of
jsdocinstall - jsdoc_run.sh - script for executing the generation process
This tool requires node.js and npm to be installed to work. To run scripts on Windows, use GitBash.
The generated documentation is placed in a temporary dir gen_apidoc.
Generation and update process
When developing a new version of an application, adding new APIs or changing current ones, or for those that don't have documentation, we need to write documentation, just like any other change in the repository.
After releasing a new version of the application, we need to generate a snapshot of the API documentation for it.
Process:
- Install node.js and npm
- Run
bash ./tools/jsdoc/jsdoc_install.sh - Run
bash ./tools/jsdoc/jsdoc_run.sh - Look the result, open it in browser index.html from
./tools/jsdoc/gen_apidoc/ - Clone musescore.github.io
- Copy dir
./tools/jsdoc/gen_apidoc/tomusescore.github.io/snapshots/x.x - Add a link to the new version in
musescore.github.io/index.html
Apidocs Static Home (`docs/apidocs_static/Home.md`)
Extensions
Extensions are a way to extend the basic functionality and add new features to the application.
The application has built-in extensions, we can find them at Home - Plugins. We can also install third-party extensions.
Before the extension will work, we need to enable it. This can be done at Home - Plugins. Enabled extensions will be available for calling from the Menu - Plugins.
Development
Now we have two types of extensions:
- forms are extensions that have a user interface through which we can control the extension logic.
- macros are extensions without a user interface, having only a script that performs some actions (usually some kind of automation)
There is also a special type - composite. This is an extension that can consist of several forms, or a form and macros.
Each extension consists of a {@tutorial 2_manifest} file that describes the extension - its identifier, type, title, icon, scripts, config and etc.
Qml is used to create {@tutorial 3_form} user interfaces, and javascript is used to write {@tutorial 4_macros} scripts. Api is provided to access the application, and API UI is provided UI controls.
See {@tutorial 1_getting_started}
Documentation
How this documentation is created, see docs/README.md
Old Docs I18n (`docs/old_docs/i18n.md`)
\page i18n Internationalization
This page gives an overview of options on how to translate a plugin to different languages.
Reuse MuseScore translatable strings
If your plugin only needs strings that are already used within MuseScore (e.g. some musical terms or actions names) the simplest method to keep a plugin translated is to reuse translations that already exist in MuseScore. In order to do this you need to use qsTranslate() function with appropriate translation contexts:
var t1 = qsTranslate("symUserNames", "Sharp"); // gets a translation for "Sharp" symbol name
console.log(t1);
var t2 = qsTranslate("action", "Export parts"); // gets a translation for "Export parts" action
console.log(t2);Translation contexts for existing strings can be searched for on Transifex or directly in MuseScore source code.
This method allows to quickly make a plugin translatable. Still, it may not fit a particular plugin's needs. \n
Translation contexts are not guaranteed to remain unchanged between MuseScore releases. Also, this method won't work if a plugin needs strings that are not used anywhere else in MuseScore.
Add translation files to the plugin
To make the plugin's strings translatable you need to use qsTr() for all your "quoted strings" in the .qml files. qsTr() has 3 arguments, the 1st is the string to be translated, the 2nd (optional) argument is a comment to the translator (which is later visible in Qt Linguist), the 3rd (also optional) is intended to be used for handling plurals in translations. \n
It can work with placeholders, e.g. qsTr("Pages: %1").arg(numberOfPages)
For translating \ref Ms::PluginAPI::PluginAPI::menuPath "menu item" of the plugin it is better not to translate the top-level item of menu path (usually "Plugins"):
menuPath: "Plugins." + qsTr("Note Names")In order to avoid conflicts with other plugins' translations it is recommended to have a separate directory for your plugin (that is, plugin's .qml files should not be put directly to the Plugins directory but to a subdirectory created specifically for that plugin).
Then create a directory named translations in the plugin's directory. You need to put locale_XX.qm files in it. \n
To obtain a .qm file for your plugin run the following command: \n
(replace XX with the targetted language (eg.: "de" for German) and include .qml and .js files)
lupdate <your plugin files> translations/locale_XX.tsThis extracts all translatable strings from the .qml and .js files into that .ts file. \n
Repeat for other languages if needed.
Use Qt Linguist to put the translation into locale_XX.ts. Once done use File โ Release in Qt Linguist or run the following:
lrelease translations/locale_XX.tsThat will create/update a locale_XX.qm file. \n
Now, run MuseScore in your language and your plugin should be translated!
More detailed information can be found in Qt documentation.
A working example of translation files usage can be found in Batch Export plugin.
Old Docs Pitch (`docs/old_docs/pitch.md`)
\page pitch Note Pitch values
Note pitches are internally expressed with their respective MIDI pitch values. This corresponds to the absolute height of the note, regardless of the way it is actually written (enharmony; to retrieve the actual enharmony employed for a note, use its \ref tpc "Tonal Pitch Class" instead).
The pitch is used by the \ref Ms::PluginAPI::Note::pitch "Note.pitch" property.
Note Pitch Values
| Note \ Octave | -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| C | 0 | 12 | 24 | 36 | 48 | 60 (middle C) | 72 | 84 | 96 | 108 | 120 |
| Cโฏ | 1 | 13 | 25 | 37 | 49 | 61 | 73 | 85 | 97 | 109 | 121 |
| D | 2 | 14 | 26 | 38 | 50 | 62 | 74 | 86 | 98 | 110 | 122 |
| Dโฏ | 3 | 15 | 27 | 39 | 51 | 63 | 75 | 87 | 99 | 111 | 123 |
| E | 4 | 16 | 28 | 40 | 52 | 64 | 76 | 88 | 100 | 112 | 124 |
| F | 5 | 17 | 29 | 41 | 53 | 65 | 77 | 89 | 101 | 113 | 125 |
| Fโฏ | 6 | 18 | 30 | 42 | 54 | 66 | 78 | 90 | 102 | 114 | 126 |
| G | 7 | 19 | 31 | 43 | 55 | 67 | 79 | 91 | 103 | 115 | 127 |
| Gโฏ | 8 | 20 | 32 | 44 | 56 | 68 | 80 | 92 | 104 | 116 | -- |
| A | 9 | 21 | 33 | 45 | 57 | 69 | 81 | 93 | 105 | 117 | -- |
| Aโฏ | 10 | 22 | 34 | 46 | 58 | 70 | 82 | 94 | 106 | 118 | -- |
| B | 11 | 23 | 35 | 47 | 59 | 71 | 83 | 95 | 107 | 119 | -- |
Old Docs Plugins (`docs/old_docs/plugins.md`)
Welcome to the MuseScore plugins documentation!
This page gives a brief overview of the topics related to plugins development.
Plugin development overview
Here are some points concerning MuseScore plugin development:
Plugins are QML components.
MuseScore plugins are coded in
QML.
Each plugin is a QML component using which implements some logic inside its
instance of \ref Ms::PluginAPI::PluginAPI "MuseScore" class and are capable to
interact both with MuseScore API and with Qt itself (so MuseScore plugins can
create their own windows, dialogs). Most of the plugins are contained within a
single .qml file though they may contain more items like resources and
translation files.
Debugging plugins
MuseScore provides a simple plugin code editor which allows developing and
instantly testing the developed plugin. This editor can be launched with Plugins โ
Plugin Creator menu item or by pressing
Ctrl+Shift+P.
Clicking on a New button will create a sample plugin, you can also run your
plugin with the Run button and see some debugging output in the console window below
the editing area. In order to print some debugging messages to that console useconsole.log():
var e = newElement(Element.STAFF_TEXT);
console.log("the created element:", e, e.name);Alternatively, you can edit your plugin's code with your favourite text editor
and test it by launching it from MuseScore as long as the plugin is properly
installed. See this Handbook
page
for the reference on plugins installation.
Hello World plugin
Here is an example of a simple plugin which prints "Hello World" to the
debugging console:
import MuseScore 3.0
MuseScore {
menuPath: "Plugins.pluginName"
description: "Description goes here"
version: "1.0"
onRun: {
console.log("Hello World!");
Qt.quit();
}
}Here is what happens here.
import MuseScore 3.0is necessary to use MuseScore API in QML code.- The
MuseScore { ... }statement declares an object ofMuseScoretype (\ref
Ms::PluginAPI::PluginAPI is exposed to QML asMuseScore). This should be
the root object of any QML plugin for MuseScore. - Statements like
menuPath: "Plugins.pluginName"assign properties to that
object, see \ref
Ms::PluginAPI::PluginAPI "the class reference" for the meaning of those
properties. Apart from the properties listed in that page, you can assign any
other properties and/or declare other QML objects too. onRun()is the function that is invoked when the plugin is executed (via a
menu entry or via a shortcut). This is the entry point of your plugin.Qt.quit()statement
requests termination of the plugin's execution.
Documentation from Earlier Versions
Although it is not up to date, documentation for creating plugins for earlier versions is available and may be useful.
https://musescore.org/en/handbook/developers-handbook/plugin-development
Plugins Installed By Default
MuseScore is shipped with a set of simple plugins which can also be used as
a reference while developing your own plugins.
ABC Import
This plugin imports ABC text from a file or the clipboard. Internet connection is required, because it uses an external web-service for the conversion, which uses abc2xml and gets send the ABC data, returns MusicXML and imports that into MuseScore.
Color Notes
This demo plugin colors notes in the selected range (or the entire score), depending on their pitch. It colors the note head of all notes in all staves and voices according to the Boomwhackers convention. Each pitch has a different color. C and Cโฏ have different color. Cโฏ and Dโญ have the same color.
To color all the notes in black, just run that plugin again (on the same selection). You could also use the 'Remove Notes Color' plugin for this.
Create Score
This demo plugin creates a new score. It creates a new piano score with 4 quarters C D E F. It's a good start to learn how to make a new score and add notes from a plugin.
helloQml
This demo plugin shows some basic tasks.
Note Names
This plugin names notes in the selected range or the entire score. It displays the names of the notes (as a staff text) as per MuseScore's language settings, for voices 1 and 3 above the staff, for voices 2 and 4 below the staff, and for chords in a comma-separated list, starting with the top note.
Note Names -Interactive
This plugin names notes as per your language setting.
Panel
This demo plugin creates a GUI panel.
random
Creates a random score.
random2
Creates a random score too.
run
This demo plugin runs an external command. Probably this will only work on Linux.
scorelist
This test plugin iterates through the score list.
View
Demo plugin to demonstrate the use of a ScoreView
Walk
This test plugin walks through all elements in a score
Porting MuseScore 2 plugins
This documentation corresponds to the plugins API for MuseScore 3.X version.
To see the information on its difference from MuseScore 2 plugins API as well
as some instructions on adapting MuseScore 2 plugins code to work with
MuseScore 3, please refer to the \ref plugin2to3 page.
Internationalization
For the questions related to making a plugin translatable to different languages
please refer to https://github.com/musescore/MuseScore/blob/master/docs/i18n.md.
Old Docs Plugins2to3 (`docs/old_docs/plugins2to3.md`)
\page plugin2to3 Porting MuseScore 2 plugins
This page describes changes between MuseScore 2.X and MuseScore 3 plugins API.
Import statement
Replace import MuseScore 1.0 with import MuseScore 3.0 to start porting a 2.X plugin.
This is needed to distinguish between plugins for different MuseScore versions.
If your plugin uses \ref Ms::PluginAPI::FileIO "FileIO" API, replace also
import FileIO 1.0 with import FileIO 3.0.
Properties assignments
Most of the properties should remain the same as in MuseScore 2.X. Most notable differences:
TimeSig doesn't have setSig() function anymore. \par
Replace
\code ts.setSig(numerator, denominator) \endcode
with
\code ts.timesig = fraction(numerator, denominator) \endcodeNo pos property available. \par
The Autoplacement engine makes it not necessary to adjust elements' position in most cases.
If this is still needed, use offset or offsetX and offsetY properties to adjust position offset:
\code element.offset = Qt.point(x, y); \endcode
or
\code
element.offsetX = x;
element.offsetY = y;
\endcode
where x, y are arbitrary numbers (in spatium units).
.
Enumerations
Most of the enumerations exposed to QML plugins remain the same but some were renamed compared to MuseScore 2.X API. The renamed enumerations include:
\ref Ms::PluginAPI::PluginAPI::Placement "Placement" โ element placement above or below staff \par
Element.ABOVE, Element.BELOW โ Placement.ABOVE, Placement.BELOW\ref Ms::PluginAPI::PluginAPI::Direction "Direction" โ vertical direction \par
MScore.UP, MScore.DOWN, MScore.AUTO โ Direction.UP, Direction.DOWN, Direction.AUTO\ref Ms::PluginAPI::PluginAPI::DirectionH "DirectionH" โ horizontal direction \par
MScore.LEFT, MScore.RIGHT, MScore.AUTO โ DirectionH.LEFT, DirectionH.RIGHT, DirectionH.AUTO\ref Ms::PluginAPI::PluginAPI::OrnamentStyle "OrnamentStyle" \par
MScore.DEFAULT, MScore.BAROQUE โ OrnamentStyle.DEFAULT, OrnamentStyle.BAROQUE\ref Ms::PluginAPI::PluginAPI::GlissandoStyle "GlissandoStyle" \par
MScore.CHROMATIC, MScore.WHITE_KEYS, MScore.BLACK_KEYS, MScore.DIATONIC
โ
GlissandoStyle.CHROMATIC etc.TextStyleType โ \ref Ms::PluginAPI::PluginAPI::Tid "Tid"
\ref Ms::PluginAPI::PluginAPI::NoteHeadType "NoteHeadType" \par
HEAD_AUTO, HEAD_WHOLE, HEAD_HALF, HEAD_QUARTER, HEAD_BREVIS, HEAD_TYPES are now in NoteHeadType enumeration.\ref Ms::PluginAPI::PluginAPI::NoteHeadGroup "NoteHeadGroup" \par
Other HEAD_* values are in NoteHeadGroup enumeration.\ref Ms::PluginAPI::PluginAPI::NoteValueType "NoteValueType" \par
Note.OFFSET_VAL, Note.USER_VAL โ NoteValueType.OFFSET_VAL, NoteValueType.USER_VAL
Old Docs Ticklength (`docs/old_docs/ticklength.md`)
\page ticklength Tick Length values
Note and rest values are expressed in an internal unit, to express their mutual relationships and to make them independent from actual tempo. This unit is used by the following object properties:
- \ref Ms::PluginAPI::PluginAPI::division (defines a number of ticks per quarter note)
- \ref Ms::PluginAPI::Segment::tick
- Other properties (to be added to this list)
Tick Lengths
All tick lengths in this table are defined through the \ref Ms::PluginAPI::PluginAPI::division "division" property. Raw numeric values are better to be avoided.
| Duration | Ticks value |
|---|---|
| whole note (semibreve) | 4 * division |
| double-dotted half note | 3.5 * division |
| dotted half note | 3 * division |
| triplet whole note (1/3 of breve) | 8 * division / 3 |
| half note (minim) | 2 * division |
| double-dotted crochet | 1.75 * division |
| dotted crochet | 1.5 * division |
| triplet half note (1/3 of semibreve) | 4 * division / 3 |
| 1/4 note (crochet) | division |
| double-dotted quaver | 0.875 * division |
| dotted quaver | 0.75 * division |
| triplet crochet (1/3 of minim) | 2 * division / 3 |
| 1/8 note (quaver) | division / 2 |
| double-dotted semiquaver | 0.4375 * division |
| dotted semiquaver | 0.375 * division |
| triplet quaver (1/3 of crochet) | division / 3 |
| 1/16 note (semiquaver) | division / 4 |
| double-dotted demi-semiquaver | 0.21875 * division |
| dotted demi-semiquaver | 0.1875 * division |
| triplet semiquaver (1/3 of quaver) | division / 6 |
| 1/32 note (demi-semiquaver) | division / 8 |
| dotted hemi-demi-semiquaver | 0.09375 * division |
| triplet demi-semiquaver (1/3 of semiquaver) | division / 12 |
| 1/64 note (hemi-demi-semiquaver) | division / 16 |
Old Docs Tpc (`docs/old_docs/tpc.md`)
\page tpc Tonal Pitch Class
The Tonal Pitch Class (tpc) is used to differentiate among notes with the same MIDI pitch but with different representation (also covering enharmony). The tpc is used by the following properties:
- \ref Ms::PluginAPI::Note::tpc1
- \ref Ms::PluginAPI::Note::tpc2
- \ref Ms::PluginAPI::Note::tpc
Tonal Pitch Classes in numeric order
| tpc | name | tpc | name | tpc | name | tpc | name | tpc | name |
|---|---|---|---|---|---|---|---|---|---|
| -1 | Fโญโญ | 6 | Fโญ | 13 | F | 20 | Fโฏ | 27 | Fโฏโฏ |
| 0 | Cโญโญ | 7 | Cโญ | 14 | C | 21 | Cโฏ | 28 | Cโฏโฏ |
| 1 | Gโญโญ | 8 | Gโญ | 15 | G | 22 | Gโฏ | 29 | Gโฏโฏ |
| 2 | Dโญโญ | 9 | Dโญ | 16 | D | 23 | Dโฏ | 30 | Dโฏโฏ |
| 3 | Aโญโญ | 10 | Aโญ | 17 | A | 24 | Aโฏ | 31 | Aโฏโฏ |
| 4 | Eโญโญ | 11 | Eโญ | 18 | E | 25 | Eโฏ | 32 | Eโฏโฏ |
| 5 | Bโญโญ | 12 | Bโญ | 19 | B | 26 | Bโฏ | 33 | Bโฏโฏ |
Tonal Pitch Classes in pitch order
| pitch | tpc | name | tpc | name | tpc | name |
|---|---|---|---|---|---|---|
| 11 | 31 | Aโฏโฏ | 19 | B | 7 | Cโญ |
| 10 | 24 | Aโฏ | 12 | Bโญ | 0 | Cโญโญ |
| 9 | 29 | Gโฏโฏ | 17 | A | 5 | Bโญโญ |
| 8 | 22 | Gโฏ | 10 | Aโญ | ||
| 7 | 27 | Fโฏโฏ | 15 | G | 3 | Aโญโญ |
| 6 | 32 | Eโฏโฏ | 20 | Fโฏ | 8 | Gโญ |
| 5 | 25 | Eโฏ | 13 | F | 1 | Gโญโญ |
| 4 | 30 | Dโฏโฏ | 18 | E | 6 | Fโญ |
| 3 | 23 | Dโฏ | 11 | Eโญ | -1 | Fโญโญ |
| 2 | 28 | Cโฏโฏ | 16 | D | 4 | Eโญโญ |
| 1 | 33 | Bโฏโฏ | 21 | Cโฏ | 9 | Dโญ |
| 0 | 26 | Bโฏ | 14 | C | 2 | Dโญโญ |
Apidocs Static Tutorials 1 Getting Started (`docs/apidocs_static/tutorials/1_getting_started.md`)
Adding a new non-visual extension
Create a new folder in the user extensions folder:
- Windows -
C:\Users\username\AppData\Local\MuseScore\MuseScore5\extensions - MacOS -
- Linux -
$HOME/.local/share/MuseScore/MuseScore5/extensions
for example myquickstart.
In this folder, create a new file manifest.json
Fill out the manifest as follows:
{
"uri": "musescore://extensions/myquickstart",
"type": "macros",
"title": "My quick start",
"description": "This is a development extension for API research.",
"actions": [
{
"path": "main.js"
}
]
}Create a new file main.js
Fill out as follows:
const Log = require("MuseApi.Log");
const Interactive = require("MuseApi.Interactive");
function main() {
Log.info("called main from quickstart")
Interactive.info("Quick start", "called MAIN from quickstart")
}Launch MuseScore and enable your extension on the plugins page.
Open a project (some a score or create new) and call your extension from the plugins menu.
A dialog should be displayed with information from your extension.
Congratulations! You've created and added a new extension!
Adding a new visual extension
Create a new folder in the custom extensions folder:
- Windows -
C:\Users\username\AppData\Local\MuseScore\MuseScore5\extensions - MacOS -
- Linux -
$HOME/.local/share/MuseScore/MuseScore5/extensions
for example myquickstart_v.
In this folder, create a new file manifest.json
Fill out the manifest as follows:
{
"uri": "musescore://extensions/myquickstart_v",
"type": "form",
"title": "My quick start visual",
"description": "This is a development extension for API research.",
"actions": [
{
"path": "Main.qml"
}
]
}Create a new file Main.qml
Fill out as follows:
import QtQuick
import MuseApi.Controls
import MuseApi.Interactive
ExtensionBlank {
id: root
implicitHeight: 400
implicitWidth: 400
StyledTextLabel {
id: label1
anchors.centerIn: parent
text: "Quick start"
}
FlatButton {
id: btn1
anchors.top: label1.bottom
anchors.topMargin: 8
anchors.horizontalCenter: parent.horizontalCenter
text: "Click me"
onClicked: {
Interactive.info("Quick start", "Clicked on button")
}
}
}Launch MuseScore and enable your extension on the plugins page.
Open a project (some a score or create new) and call your extension from the plugins menu.
A dialog with you form.
Congratulations! You've created and added a new visual extension!
Apidocs Static Tutorials 2 Manifest (`docs/apidocs_static/tutorials/2_manifest.md`)
Each extension must contain a manifest.json file. This is what is searched for to detect the extension and obtain information about it.
manifest.json
{
"uri": "musescore://extensions/myquickstart",
"type": "macros",
"title": "My quick start",
"description": "This is a development extension for API research.",
"thumbnail": "my_icon.png",
"version": "0.1",
"vendor": "Me"
"ui_context": "Any",
"apiversion": 2,
"actions": [
{
"path": "main.js"
}
]
}uri (required)
This is the extension identifier, used to call it.
It must be unique and follow the pattern: musescore://extensions/extensions_name
type (required)
Type of extension
macros- extension without user interfaceform- extension with user interfacecomposite- extension consisting of several forms or forms and macros
title (required)
Title of extension. Please write a concise and clear title.
description (required)
Description of extension. Please write a one-sentence description to make it clear what this extension does.
thumbnail (optional)
Thumbnail of extension. PNG format is supported.
category (optional)
Category of extension.
version (optional)
Version of extension.
vendor (optional)
About the author
apiversion (optional)
The API version used:
1- api of old plugins, deprecated, don't use this for new extensions2(default) - actual api
ui_context (optional)
The context in which the extension is available:
ProjectOpened(default) - Project (score) openAny- always available
actions (required)
List of extension actions.
An extension typically has one action, but can have multiple.
Actions are displayed as menu items in Menu->Plugins by default.
However, they can also be displayed as buttons on the toolbar.
example
...
"actions": [
{"code": "configure", "type": "form", "title": "Configure", "path": "configure.qml"},
{"code": "add", "type": "macros", "title": "Add", "path": "add.js"},
{"code": "remove", "type": "macros", "title": "Remove", "path": "remove.js"}
]action: code (optional)
Action code
action: type (required for type `composite`/optional for `form`/`macros`)
If an extension consists of forms and macros (type composite), then you must specify the type of each action. If the extension has a single action, or all actions are of the same type, then you don't need to specify it; the action type will be equivalent to the extension type.
action: title (optional)
The action title, if not specified, will be equivalent to the extension title.
action: icon (optional)
Action icon, displayed in the menu or on the toolbar.
see {@link Qml.IconCode|IconCode}
action: ui_context (optional)
The context in which the action is available.
If not specified, then equivalent to the extension ui_context.
action: show_on_appmenu (optional)
Whether to show the action in the menu. Default is true.
action: show_on_toolbar (optional)
Whether to show the action on the toolbar. Default is false.
action: path (required)
Path to the js script of macros or Qml form
action: func (optional)
For macros only. The name of the function to call.
This means you can specify the same script file but different functions for different actions.
If not specified, the default function name is main.
Apidocs Static Tutorials 3 Form (`docs/apidocs_static/tutorials/3_form.md`)
Extension Forms
Forms are extensions that have a user interface. To create UI, Qml is used. For form extensions, we need to specify the appropriate type and file name using .qml in the extension manifest.
Like this:
manifest.json
{
"uri": "musescore://extensions/example1",
"type": "form",
...
"actions": [
{
"path": "Main.qml"
}
]
}To create a UI, use ExtensionBlank as the root element and the provided UI component library. For this we need to do import MuseApi.Controls. You can also use the various services provided, which are described in the documentation.
Example of a simple interface:
import QtQuick
import MuseApi.Controls
import MuseApi.Log
import MuseApi.Interactive
ExtensionBlank {
id: root
implicitHeight: 400
implicitWidth: 400
Component.onCompleted: {
Log.info("Component.onCompleted from example1")
}
StyledTextLabel {
id: label1
text: "This is example1"
}
FlatButton {
id: btn1
anchors.top: label1.bottom
text: "Click me"
onClicked: {
Interactive.info("Example1", "Clicked on Btn1")
}
}
}Apidocs Static Tutorials 4 Macros (`docs/apidocs_static/tutorials/4_macros.md`)
Extension Macros
Macros are extensions that do not have a user interface, there is only a script that does something. Usually this is a way to automate some actions.
For macros extensions, we need to specify the appropriate type and file name using .js in the extension manifest.
Like this:
manifest.json
{
"uri": "musescore://extensions/example1",
"type": "macros",
...
"actions": [
{
"path": "main.js"
}
]
}In the manifest you can specify the name of the function that will be called; if not specified, then the main function will be called by default. You can also use the various services provided, which are described in the documentation.
main.js
const Log = require("MuseApi.Log");
const Interactive = require("MuseApi.Interactive");
function main() {
Log.info("called main from example 2")
Interactive.info("Quick start", "called main from example 2")
}--- METRICS ---
- Files Extracted: 13
- Estimated Token Budget: ~8811 tokens
- Canonical Reference: https://codewiki.google/github.com/musescore/MuseScore