diff --git a/CHANGELOG.md b/CHANGELOG.md index c89deab..15e9eab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.4.0 + +- Attempt MuseScore 4 support. + - Changed 'dock' to 'dialog' type to support MuseScore 4. + - Remove dependency on old `PluginAPI::Ms`, using `Element.name` instead. + - Use `AccidentalType` when on MS4 instead of `Accidental`. +- Fix shortcuts breaking when plugin closed and reopened in plugin creator/MS 4. + ## 0.3.2 - Huge performance improvements for tuning & up/down/enharmonic cycle for large scores diff --git a/README.md b/README.md index 0abac0c..d27ef9b 100644 --- a/README.md +++ b/README.md @@ -250,6 +250,8 @@ This is still a work in progress. Free for all to edit, and [in need of communit - [Enharmonic equivalents aren't showing up / are incorrect](#enharmonic-equivalents-arent-showing-up--are-incorrect) - [Keyboard shortcuts stop working](#keyboard-shortcuts-stop-working) - [Reporting an issue](#reporting-an-issue) + - [Accessing plugin debug logs in MuseScore 3](#accessing-plugin-debug-logs-in-musescore-3) + - [Accessing plugin debug logs for MuseScore 4](#accessing-plugin-debug-logs-for-musescore-4) - [HELP NEEDED!](#help-needed) - [1. Testing on MS 4](#1-testing-on-ms-4) - [2. Data entry of accidentals](#2-data-entry-of-accidentals) @@ -1340,15 +1342,29 @@ If none of the above remedies work, you will need to [file an issue here](https: - Operating system - Example score - Tuning config you were using -- Debug logs - - Stop running Xen Tuner (close plugin window/quit button). - - Open the **Plugin Creator** (Plugins > Plugin Creator). - - Open the `xen tuner.qml` file - - Run `xen tuner.qml` from the Plugin Creator. - - Repeat the action you did that caused the issue. - - Usually if an error occurs, you should be able to see the error message at the bottom of the log. - - Copy and paste as much of the debug log as you can, **including the error message** at the bottom. - - If you stopped the plugin/modified source code in the Plugin Creator, you will need to restart MuseScore to get the plugin working again. +- **Debug logs** + +### Accessing plugin debug logs in MuseScore 3 + +- Stop running Xen Tuner (close plugin window/quit button). +- Open the **Plugin Creator** (Plugins > Plugin Creator). +- Open the `xen tuner.qml` file +- Run `xen tuner.qml` from the Plugin Creator. +- Repeat the action you did that caused the issue. +- Usually if an error occurs, you should be able to see the error message at the bottom of the log. +- Copy and paste as much of the debug log as you can, **including the error message** at the bottom. + +### Accessing plugin debug logs for MuseScore 4 + +Logs created directly by the plugin aren't accessible anywhere in MuseScore 4 yet. + +The best option would be to attach the `.log` files located at: + +- **Windows**: `C:\Users\\AppData\Local\MuseScore\MuseScore4\logs\` +- **MacOS**: `~/Library/Application Support/MuseScore/MuseScore4/logs/` +- **Linux**: `~/.local/share/data/MuseScore/MuseScore4/logs/` + +if you're not on Windows, you can try running MuseScore from the command line/terminal to see if there's any output. ## HELP NEEDED! diff --git a/clear tuning cache.qml b/Xen Tuner/clear tuning cache.qml similarity index 89% rename from clear tuning cache.qml rename to Xen Tuner/clear tuning cache.qml index 3b45a2a..ffa82b4 100644 --- a/clear tuning cache.qml +++ b/Xen Tuner/clear tuning cache.qml @@ -27,7 +27,7 @@ import Qt.labs.settings 1.0 import FileIO 3.0 MuseScore { - version: "0.3.2" + version: "0.4.0" description: "The tuning cache contains cached data about tunings used in the score.\n" + "If you've experimented with many different tunings within a score, but aren't currently using most of them," + "it is highly recommended to clear the Tuning Config cache." @@ -52,10 +52,12 @@ MuseScore { } onRun: { - console.log('Xenharmonic Clear Tuning Cache'); + console.log('Xen Tuner - Clear Tuning Cache'); // When you want to find which import has a syntax error, uncomment this line // console.log(JSON.stringify(Fns)); - Fns.init(Accidental, NoteType, SymId, Element, Ms, fileIO, Qt.resolvedUrl("."), curScore); + var isMS4 = mscoreMajorVersion >= 4; + Fns.init(isMS4 ? AccidentalType : Accidental, NoteType, SymId, Element, + fileIO, Qt.resolvedUrl("."), curScore, isMS4); console.log(Qt.resolvedUrl(".")); if (typeof curScore === 'undefined') diff --git a/debug xen tuner.qml b/Xen Tuner/debug xen tuner.qml similarity index 90% rename from debug xen tuner.qml rename to Xen Tuner/debug xen tuner.qml index 30a52ec..ccae6a9 100644 --- a/debug xen tuner.qml +++ b/Xen Tuner/debug xen tuner.qml @@ -31,7 +31,7 @@ import Qt.labs.settings 1.0 import FileIO 3.0 MuseScore { - version: "0.3.2" + version: "0.4.0" description: "Debug Tune function.\n\n" + "The docking Xen Tuner plugin is hard to debug as the shortcuts break everytime you re-run " + "the plugin in the plugin creator. Use this instead to test functions without having to " + @@ -61,11 +61,12 @@ MuseScore { } onRun: { - console.log('Started Xen Tuner'); + console.log('Xen Tuner - Debug'); // When you want to find which import has a syntax error, uncomment this line // console.log(JSON.stringify(Fns)); - Fns.init(Accidental, NoteType, SymId, Element, Ms, fileIO, Qt.resolvedUrl("."), curScore); - console.log('present working dir: ' + Qt.resolvedUrl(".")); + var isMS4 = mscoreMajorVersion >= 4; + Fns.init(isMS4 ? AccidentalType : Accidental, NoteType, SymId, Element, + fileIO, Qt.resolvedUrl("."), curScore, isMS4); // Debug code here. Fns.operationTune(); // test tune diff --git a/display cents.qml b/Xen Tuner/display cents.qml similarity index 90% rename from display cents.qml rename to Xen Tuner/display cents.qml index fe370fd..1c47bc1 100644 --- a/display cents.qml +++ b/Xen Tuner/display cents.qml @@ -31,7 +31,7 @@ import Qt.labs.settings 1.0 import FileIO 3.0 MuseScore { - version: "0.3.2" + version: "0.4.0" description: "Create fingerings to display cent offsets of notes.\n\n" + "Applies to selection, or entire score if nothing is selected." menuPath: "Plugins.Xen Tuner.Display Cents" @@ -60,7 +60,9 @@ MuseScore { onRun: { console.log('Xen Tuner - Display Cents'); - Fns.init(Accidental, NoteType, SymId, Element, Ms, fileIO, Qt.resolvedUrl("."), curScore); + var isMS4 = mscoreMajorVersion >= 4; + Fns.init(isMS4 ? AccidentalType : Accidental, NoteType, SymId, Element, + fileIO, Qt.resolvedUrl("."), curScore, isMS4); Fns.operationTune(1); } diff --git a/display steps.qml b/Xen Tuner/display steps.qml similarity index 90% rename from display steps.qml rename to Xen Tuner/display steps.qml index 707f7f0..ae8528c 100644 --- a/display steps.qml +++ b/Xen Tuner/display steps.qml @@ -31,7 +31,7 @@ import Qt.labs.settings 1.0 import FileIO 3.0 MuseScore { - version: "0.3.2" + version: "0.4.0" description: "Create fingerings to display edo/neji-steps of notes relative to the reference note.\n\n" + "Applies to selection, or entire score if nothing is selected." menuPath: "Plugins.Xen Tuner.Display Steps" @@ -60,7 +60,9 @@ MuseScore { onRun: { console.log('Xen Tuner - Display Steps'); - Fns.init(Accidental, NoteType, SymId, Element, Ms, fileIO, Qt.resolvedUrl("."), curScore); + var isMS4 = mscoreMajorVersion >= 4; + Fns.init(isMS4 ? AccidentalType : Accidental, NoteType, SymId, Element, + fileIO, Qt.resolvedUrl("."), curScore, isMS4); Fns.operationTune(2); } diff --git a/export midi csv.qml b/Xen Tuner/export midi csv.qml similarity index 97% rename from export midi csv.qml rename to Xen Tuner/export midi csv.qml index 344f032..6463c27 100644 --- a/export midi csv.qml +++ b/Xen Tuner/export midi csv.qml @@ -28,7 +28,7 @@ import QtQuick.Dialogs 1.1 import FileIO 3.0 MuseScore { - version: "0.3.2" + version: "0.4.0" description: "Tunes & export the entire score/selection as a midi.csv file. Feed the generated text file into the text-to-midi.py " + "script to generate one MPE midi file per staff." menuPath: "Plugins.Xen Tuner.Export MIDI CSV" @@ -64,7 +64,9 @@ MuseScore { console.log('Xenharmonic Export MIDI CSV'); // When you want to find which import has a syntax error, uncomment this line // console.log(JSON.stringify(Fns)); - Fns.init(Accidental, NoteType, SymId, Element, Ms, fileIO, Qt.resolvedUrl("."), curScore); + var isMS4 = mscoreMajorVersion >= 4; + Fns.init(isMS4 ? AccidentalType : Accidental, NoteType, SymId, Element, + fileIO, Qt.resolvedUrl("."), curScore, isMS4); console.log(Qt.resolvedUrl(".")); @@ -271,7 +273,7 @@ MuseScore { // Tune the note! if (cursor.element) { - if (cursor.element.type == Ms.CHORD) { + if (cursor.element.name == "Chord") { var graceChords = cursor.element.graceNotes; for (var i = 0; i < graceChords.length; i++) { // iterate through all grace chords diff --git a/fns.js b/Xen Tuner/fns.js similarity index 99% rename from fns.js rename to Xen Tuner/fns.js index 7dc5bad..6617bd4 100644 --- a/fns.js +++ b/Xen Tuner/fns.js @@ -19,13 +19,15 @@ var Lookup = ImportLookup(); +var isMS4; // init sets this to true if MuseScore 4 is detected. + /** - * During init, this will be assigned to the MuseScore plugin API `Accidental` enum. + * If {@link isMS4}, this will be assigned to `mu::plugins::api::enums::AccidentalType`, + * otherwise, it will be `MS::PluginAPI::Accidental` for MuseScore 3. */ var Accidental = null; var NoteType = null; var Element = null; -var Ms = null; var SymId = null; // WARNING: SymId has a long loading time. /** @type {FileIO} */ var fileIO; @@ -323,17 +325,17 @@ function generateDefaultTuningConfig() { * @param {*} MSAccidental Accidental enum from MuseScore plugin API. * @param {*} MSNoteType NoteType enum from MuseScore plugin API. */ -function init(MSAccidental, MSNoteType, MSSymId, MSElement, MSMs, MSFileIO, homePath, MSCurScore) { +function init(MSAccidental, MSNoteType, MSSymId, MSElement, MSFileIO, homePath, MSCurScore, _isMS4) { Lookup = ImportLookup(); // console.log(JSON.stringify(Lookup)); Accidental = MSAccidental; SymId = MSSymId; NoteType = MSNoteType; - Ms = MSMs; Element = MSElement; fileIO = MSFileIO; pluginHomePath = homePath; _curScore = MSCurScore; + isMS4 = _isMS4; console.log("Initialized! Enharmonic eqv: " + ENHARMONIC_EQUIVALENT_THRESHOLD + " cents"); } @@ -3625,7 +3627,7 @@ function readBarState(tickOfThisBar, tickOfNextBar, cursor) { setCursorToPosition(cursor, tickOfThisBar, voice, ogCursorPos.staffIdx); while (cursor.segment && cursor.tick < tickOfNextBar) { - if (cursor.element && cursor.element.type == Ms.CHORD) { + if (cursor.element && cursor.element.name == "Chord") { var notes = cursor.element.notes; var graceChords = cursor.element.graceNotes; var currTick = cursor.tick; @@ -4598,7 +4600,7 @@ function forceExplicitAccidentalsAfterNote( while (cursor.segment && (cursor.tick < tickOfNextBar || tickOfNextBar == -1)) { // console.log('cursor.tick: ' + cursor.tick + ', tickOfNextBar: ' + tickOfNextBar); - if (!(cursor.element && cursor.element.type == Ms.CHORD)) { + if (!(cursor.element && cursor.element.name == "Chord")) { cursor.next(); continue; } @@ -5059,7 +5061,7 @@ function partitionChords(tickOfThisBar, tickOfNextBar, cursor) { setCursorToPosition(cursor, tickOfThisBar, voice, ogCursorPos.staffIdx); while (cursor.segment && cursor.tick < tickOfNextBar) { - if (cursor.element && cursor.element.type == Ms.CHORD) { + if (cursor.element && cursor.element.name == "Chord") { var notes = cursor.element.notes; var graceChords = cursor.element.graceNotes; var currTick = cursor.tick; @@ -5523,7 +5525,9 @@ function autoPositionAccidentals(startTick, endTick, parms, cursor, firstBarTick // '\nTicks found: ' + ticks.join(', ')); ticks.forEach(function (tick) { - // the Chords object + /** + * @type {Chords} + */ var chords = chordsByTick[tick]; // One vert stack = all chords at a tick that should be @@ -5574,7 +5578,7 @@ function autoPositionAccidentals(startTick, endTick, parms, cursor, firstBarTick continue; } - if (chdElement.parent.type != Ms.CHORD) { + if (chdElement.parent.name != "Chord") { console.error("ERROR: parent of note object isn't a chord??"); continue; } @@ -5966,7 +5970,7 @@ function operationTune(display) { // Tune the note! if (cursor.element) { - if (cursor.element.type == Ms.CHORD) { + if (cursor.element.name == "Chord") { var graceChords = cursor.element.graceNotes; for (var i = 0; i < graceChords.length; i++) { // iterate through all grace chords @@ -6293,7 +6297,7 @@ function operationTranspose(stepwiseDirection, stepwiseAux) { } if (cursor.element) { - if (cursor.element.type == Ms.CHORD) { + if (cursor.element.name == "Chord") { var graceChords = cursor.element.graceNotes; for (var i = 0; i < graceChords.length; i++) { // iterate through all grace chords diff --git a/fns.ms.js b/Xen Tuner/fns.ms.js similarity index 100% rename from fns.ms.js rename to Xen Tuner/fns.ms.js diff --git a/generated-tables.js b/Xen Tuner/generated-tables.js similarity index 100% rename from generated-tables.js rename to Xen Tuner/generated-tables.js diff --git a/lookup-tables.js b/Xen Tuner/lookup-tables.js similarity index 100% rename from lookup-tables.js rename to Xen Tuner/lookup-tables.js diff --git a/main.js b/Xen Tuner/main.js similarity index 100% rename from main.js rename to Xen Tuner/main.js diff --git a/xen tuner.qml b/Xen Tuner/xen tuner.qml similarity index 85% rename from xen tuner.qml rename to Xen Tuner/xen tuner.qml index e86caec..549bbaf 100644 --- a/xen tuner.qml +++ b/Xen Tuner/xen tuner.qml @@ -31,17 +31,28 @@ import Qt.labs.settings 1.0 import FileIO 3.0 MuseScore { - version: "0.3.2" - pluginType: "dock" - dockArea: "left" + version: "0.4.0" + pluginType: "dialog" // changed from "dock" to "dialog" to support both MS3 and 4 + // dockArea: "left" description: "Starts the XenTuner plugin.\n\n" + "This will open a small docked panel to the side.\n\nIMPORTANT: Do not close the window.\n"+ "Make sure you only have 1 instance of this plugin running at a time." menuPath: "Plugins.Xen Tuner.Start Xen Tuner" implicitHeight: 80 - implicitWidth: 200 + implicitWidth: 300 id: pluginId readonly property var window: Window.window + + onRun: { + console.log('Started Xen Tuner'); + // When you want to find which import has a syntax error, uncomment this line + // console.log(JSON.stringify(Fns)); + + var isMS4 = mscoreMajorVersion >= 4; + Fns.init(isMS4 ? AccidentalType : Accidental, NoteType, SymId, Element, + fileIO, Qt.resolvedUrl("."), curScore, isMS4); + console.log('present working dir: ' + Qt.resolvedUrl(".")); + } Component.onCompleted : { if (mscoreMajorVersion >= 4) { @@ -79,11 +90,18 @@ MuseScore { font.pointSize: 8 onClicked: { infoText.text = "Quitting..."; - if (mscoreMajorVersion >= 4) { - pluginId.parent.Window.window.close(); - } else { - Qt.quit(); + console.log('Quitting'); + var shortcuts = [ + tuneShortcut, enharmonicShortcut, upShortcut, up1Shortcut, + up2Shortcut, up3Shortcut, up4Shortcut, up5Shortcut, up6Shortcut, + downShortcut, down1Shortcut, down2Shortcut, down3Shortcut, + down4Shortcut, down5Shortcut, down6Shortcut + ]; + for (var i = 0; i < shortcuts.length; i++) { + shortcuts[i].context = Qt.WindowShortcut; // make the shortcut disappear with the window. + console.log('disable shortcut: ' + shortcuts[i].sequence); } + pluginId.parent.Window.window.close(); } } } @@ -91,6 +109,7 @@ MuseScore { Shortcut { sequence: "Alt+R" context: Qt.ApplicationShortcut + id: tuneShortcut onActivated: { infoText.text = "Tuning score/selection..."; Fns.operationTune(); @@ -120,6 +139,7 @@ MuseScore { Shortcut { sequence: "Alt+Up" context: Qt.ApplicationShortcut + id: up1Shortcut onActivated: { infoText.text = "Moving note(s) up aux 1"; Fns.operationTranspose(1, 1); @@ -129,6 +149,7 @@ MuseScore { Shortcut { sequence: "Ctrl+Alt+Up" context: Qt.ApplicationShortcut + id: up2Shortcut onActivated: { infoText.text = "Moving note(s) up aux 2"; Fns.operationTranspose(1, 2); @@ -138,6 +159,7 @@ MuseScore { Shortcut { sequence: "Alt+Shift+Up" context: Qt.ApplicationShortcut + id: up3Shortcut onActivated: { infoText.text = "Moving note(s) up aux 3"; Fns.operationTranspose(1, 3); @@ -147,6 +169,7 @@ MuseScore { Shortcut { sequence: "Ctrl+Alt+Shift+Up" context: Qt.ApplicationShortcut + id: up4Shortcut onActivated: { infoText.text = "Moving note(s) up aux 4"; Fns.operationTranspose(1, 4); @@ -157,6 +180,7 @@ MuseScore { sequence: "End" enabled: false // set to true to enable context: Qt.ApplicationShortcut + id: up5Shortcut onActivated: { infoText.text = "Moving note(s) up aux 5"; Fns.operationTranspose(1, 5); @@ -167,6 +191,7 @@ MuseScore { sequence: "End" enabled: false context: Qt.ApplicationShortcut + id: up6Shortcut onActivated: { infoText.text = "Moving note(s) up aux 6"; Fns.operationTranspose(1, 6); @@ -186,6 +211,7 @@ MuseScore { Shortcut { sequence: "Alt+Down" context: Qt.ApplicationShortcut + id: down1Shortcut onActivated: { infoText.text = "Moving note(s) down aux 1"; Fns.operationTranspose(-1, 1); @@ -195,6 +221,7 @@ MuseScore { Shortcut { sequence: "Ctrl+Alt+Down" context: Qt.ApplicationShortcut + id: down2Shortcut onActivated: { infoText.text = "Moving note(s) down aux 2"; Fns.operationTranspose(-1, 2); @@ -204,6 +231,7 @@ MuseScore { Shortcut { sequence: "Alt+Shift+Down" context: Qt.ApplicationShortcut + id: down3Shortcut onActivated: { infoText.text = "Moving note(s) down aux 3"; Fns.operationTranspose(-1, 3); @@ -213,6 +241,7 @@ MuseScore { Shortcut { sequence: "Ctrl+Alt+Shift+Down" context: Qt.ApplicationShortcut + id: down4Shortcut onActivated: { infoText.text = "Moving note(s) down aux 4"; Fns.operationTranspose(-1, 4); @@ -223,6 +252,7 @@ MuseScore { sequence: "Home" enabled: false context: Qt.ApplicationShortcut + id: down5Shortcut onActivated: { infoText.text = "Moving note(s) down aux 5"; Fns.operationTranspose(-1, 5); @@ -233,6 +263,7 @@ MuseScore { sequence: "Home" enabled: false context: Qt.ApplicationShortcut + id: down6Shortcut onActivated: { infoText.text = "Moving note(s) down aux 5"; Fns.operationTranspose(-1, 5); @@ -240,14 +271,6 @@ MuseScore { } } - onRun: { - console.log('Started Xen Tuner'); - // When you want to find which import has a syntax error, uncomment this line - // console.log(JSON.stringify(Fns)); - Fns.init(Accidental, NoteType, SymId, Element, Ms, fileIO, Qt.resolvedUrl("."), curScore); - console.log('present working dir: ' + Qt.resolvedUrl(".")); - } - onScoreStateChanged: { if (state.selectionChanged && curScore) { var elems = curScore.selection.elements; diff --git a/index.html b/index.html index 35f498f..0f2e25c 100644 --- a/index.html +++ b/index.html @@ -60,9 +60,9 @@

Tuning config .json generator for large tuning configs

- - - - + + + + \ No newline at end of file diff --git a/scripts/tabulate_accidentals.py b/scripts/tabulate_accidentals.py index c3a44a9..51b1c95 100644 --- a/scripts/tabulate_accidentals.py +++ b/scripts/tabulate_accidentals.py @@ -10,7 +10,7 @@ SHEET_URL = "https://docs.google.com/spreadsheets/d/1kRBJNl-jdvD9BBgOMJQPcVOHjdXurx5UFWqsPf46Ffw/gviz/tq?tqx=out:csv&sheet=CSV+export" with urllib.request.urlopen(SHEET_URL) as csv_download: - with open('generated-tables.js', 'w') as f: + with open('Xen Tuner/generated-tables.js', 'w') as f: csv_data = csv_download.read().decode('utf-8') # Remove the first 5 lines of the csv diff --git a/types.js b/types.js index 86997dd..af35a3e 100644 --- a/types.js +++ b/types.js @@ -1288,7 +1288,7 @@ class PluginAPIElement { /** @type {QRectF} */ bbox; /** - * @type {'Fingering' | 'StaffText' | 'SystemText'} + * @type {'Fingering' | 'StaffText' | 'SystemText' | 'Chord'} */ name; /**