# Technical Documentation: musescore/MuseScore

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/musescore/MuseScore)

### Overview (README.md)

# 

Music notation and composition software

[](https://www.gnu.org/licenses/gpl-3.0.en.html)
[](https://github.com/musescore/MuseScore/actions/workflows/check_unit_tests.yml)

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](https://musescore.org)
- [MuseScore Studio Git workflow instructions](https://musescore.org/en/developers-handbook/git-workflow)
- [How to compile MuseScore Studio?](https://github.com/musescore/MuseScore/wiki/Set-up-developer-environment)

## License

MuseScore Studio is licensed under GPL version 3.0. See [license file](https://github.com/musescore/MuseScore/blob/master/LICENSE.txt) in the same directory.

## Packages

See [Code Structure on Wiki](https://github.com/musescore/MuseScore/wiki/CodeStructure)

## Building

**Read the [Compilation section](https://github.com/musescore/MuseScore/wiki/Set-up-developer-environment) of the [MuseScore Wiki](https://github.com/musescore/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`](https://github.com/musescore/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](https://github.com/musescore/MuseScore/releases), and then from your download directory type:

    tar xzf MuseScore-x.x.x.tar.gz
    cd MuseScore-x.x.x

### Release Build

To compile MuseScore Studio for release, type:

    cmake -P build.cmake -DCMAKE_BUILD_TYPE=Release

On 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 clean

Then try running the first command again.

### Running

To start MuseScore Studio, type:

    cmake -P build.cmake -DCMAKE_BUILD_TYPE=Release run

Or 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](https://github.com/musescore/MuseScore/wiki/Unit-tests) of the [MuseScore Studio Wiki](https://github.com/musescore/MuseScore/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](https://github.com/jsdoc/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](https://github.com/musescore/MuseScore/tree/master/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](https://jsdoc.app/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](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() const
```
There 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](https://github.com/musescore/musescore.github.io/tree/main/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](https://github.com/musescore/musescore.github.io/blob/main/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 ](https://github.com/musescore/MuseScore/tree/master/tools/jsdoc)  

List of tools: 
* template - template for `jsdoc`
* jsdoc_extractor.js - this is a documentation extractor from `cpp` files. It extracts documentation and stores it in temporary, fake `js` files so that `jsdoc` can process them.  
* conf.json - file of configuration for `jsdoc` 
* jsdoc_install.sh - script of `jsdoc` install 
* jsdoc_run.sh - script for executing the generation process  
   
This tool requires [node.js](https://nodejs.org) 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: 
1. Install [node.js](https://nodejs.org) and npm 
2. Run `bash ./tools/jsdoc/jsdoc_install.sh`  
3. Run `bash ./tools/jsdoc/jsdoc_run.sh`  
4. Look the result, open it in browser index.html from `./tools/jsdoc/gen_apidoc/`  
5. Clone [musescore.github.io](https://github.com/musescore/musescore.github.io)
5. Copy dir `./tools/jsdoc/gen_apidoc/` to `musescore.github.io/snapshots/x.x` 
6. 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](https://github.com/musescore/MuseScore/tree/master/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()`](https://doc.qt.io/qt-5/qml-qtqml-qt.html#qsTranslate-method) 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](https://app.transifex.com/musescore/musescore) or directly in MuseScore [source code](https://github.com/musescore/MuseScore).

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()`](https://doc.qt.io/qt-5/qml-qtqml-qt.html#qsTr-method) 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.ts
```
This 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.ts
```
That 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](https://doc.qt.io/qt-5/qtquick-internationalization.html).

A working example of translation files usage can be found in [Batch Export](https://musescore.org/en/project/batch-convert) 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](https://doc.qt.io/qt-5/qmlapplications.html#what-is-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
<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>.

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 use
`console.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](https://handbook.musescore.org/customization/plugins)
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.0` is necessary to use MuseScore API in QML code.
- The `MuseScore { ... }` statement declares an object of `MuseScore` type (\ref
Ms::PluginAPI::PluginAPI is exposed to QML as `MuseScore`). 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()`](https://doc.qt.io/qt-5/qml-qtqml-qt.html#quit-method) 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) \endcode

- No **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 interface
* `form` - extension with user interface
* `composite` - 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 extensions
* `2` (default) - actual api  

### ui_context (optional)
The context in which the extension is available:  
* `ProjectOpened` (default) - Project (score) open 
* `Any` - 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
