Can a plugin access on-time/off-time?
Reported version
3.2
Type
Plugins
Frequency
Once
Severity
S5 - Suggestion
Reproducibility
Always
Status
closed
Regression
No
Workaround
No
Project
Can I write a plugin to impart a desired phrasing upon a run of notes?
For more detail on this request see these forum posts in order:
This is the original post:
https://musescore.org/en/node/291414
This post continues the discussion in the are of implementation:
https://musescore.org/en/node/291519
-Dale
Fix version
3.3.0
Comments
see https://github.com/musescore/MuseScore/pull/5190
This concern was posted in PR# 5190:
Why do you use exactly the first note event (both here and in libmscore)?
Some notes may have more than one note event, for example notes with ornaments applied. If your intention is to add an ability to allow a more complete control over playback for plugins then it may be worth to expose play events to plugins directly in some way. I am not sure how would it be better to implement that but otherwise only a limited functionality will be exposed, and it is not clear in which way that functionality should actually be limited.
In reply to This concern was posted in… by DLLarson
I don't know "fer sure" what "NoteEvents" are, other than from the obvious conclusion from their name, possible plurality, and demetrio's comment. I suspect you have to "look through all of them that are on this note", find the one that relates to "off-time" (or "on-time") and deal with it in its own terms. Whatever it is, the PRE must do it somehow. I'm not ready to sign on to "why don't we address all properties or event types for visibility" right yet. I have a vested interest in seeing these two visible, for they they make the difference between mechanical performance and phrased performance. Your thoughts?
In reply to I don't know "fer sure" what… by [DELETED] 1831606
NoteEvents encapsulate the following values:
class NoteEvent {
int _pitch; // relative pitch to note pitch
int _ontime; // 1/1000 of nominal note len
int _len; // 1/1000 of nominal note len
:
};
We have been working with the last two.
I'm not sure how pitch works its way into the class, if only notes contain NoteEvents and notes already have pitch. This seems redundant but I really don't know.
If only these two properties are exposed it might be simpler to just provide an index argument that defaults to zero if not specified (if QML allows default parameter values.)
-Dale
In reply to NoteEvents encapsulate the… by DLLarson
Wait a sec... The NoteEvent pitch is somehow relative to the base pitch? If so then I would think it should be exposed as well.
-Dale
In reply to Wait a sec... The NoteEvent… by DLLarson
So there can be multiple note events, each of which specifies an on-time, an off-time, and a pitch? What does that mean? Are these "sub-notes" (e.g., ornamentation) of the note they call their parent?
In reply to So there can be multiple… by [DELETED] 1831606
That question is, as they say, beyond my pay grade. :)
It would be good to have a subject matter expert to weigh in. It seems to have a tight tie to midi as I see many references to NoteEvent's from within that code.
-Dale
I suspect sooner rather than later I will simply have to start building MS to figure out what has to be developed and how much must change. The NoteEvent paradigm seems very odd in that we can see little "noticules" for ornamentation in the Piano Roll Editor, but not edit them, and you can't see them at all in the MSCX/Z, but nondefault on/off time are fully visible -- the ornament is only saved as "macro form" (i.e., "there is a Koffeeschlag mit doppeltem Cacao here") - so the PRE and the MSCX seem already to reveal a design conflict, and if NoteEvents were to be exposed to qml, the same restriction would have to be imposed, and documentation would be a mess. But what I want is profoundly useful, and a way must be found by someone. I would like to hear from demetrios or someone else on a first-name basis with NoteEvents.
How about this (input from someone knowledgeable needed - I have the sources, but someone else could answer faster). Are there any kinds of NoteEvents other than ornamentation and basic note on/off time? If not, then a consistent solution might be: If there is only one note event , you can change its on time or off time as per DLL's PR. If there are more than one, then, as in the PRE, you can't change the values, and perhaps the "get" should return null. This would be basically consistent with the PRE behavior.
In reply to How about this (input from… by [DELETED] 1831606
Please see my comment on the PR regarding engagement from the those in the know:
https://github.com/musescore/MuseScore/pull/5190#discussion_r300756774
I'm happy to commit to implementing a solution but only after I know it won't be fruitless work.
-Dale
In reply to Please see my comment on the… by DLLarson
I see, OK, yes. Do we know how to ping demetrio, or explore the responsibility chain?
In reply to I see, OK, yes. Do we know… by [DELETED] 1831606
>Do we know how to ping demetrio, or explore the responsibility chain?
The "we" that's "me" doesn't. That's why I've been leaving the "plea's" at various places.
In fact, I just became aware of MuseScore recently and, being a programmer/engineer type, fixed a few things having to do with a tin whistle tab plugin I liked that didn't work well in v3.0 release. A classic open source contribution.
Once agreement on this feature is reached I'm happy to adapt my code to the agreed upon implementation.
-Dale
Actually Piano Roll Editor is already able to edit each note event separately — at least via its bottom panel where all the properties of
NoteEvent
s mentioned above can be adjusted. I believe if we want to allow plugins to have a better control over playback we should probably expose thoseNoteEvent
s to them too, otherwise the solution will be rather limited. However my concern here is that note events may not be properly created to the time when a plugin gets called. It is also true for the piano roll editor: try to open it on a score with ornamented notes before triggering any playback, and you will not see any note events that correspond to those ornaments. Editing note events at this stage will lead to probably unintended results. So perhaps using this API should somehow trigger creating note events for the whole score or some its part. This all is possible to do but the implementation should probably be especially accurate with handling these issues to avoid both possible errors and possible extra performance penalty.Given the aversion of the "powers that be" to enhancing the playback features of the product, or even introducing more UI to control playback, I think the possibility of plugin control over playback is a necessity.
> we should probably expose those NoteEvents
For my clarification, to expose NoteEvent's as free-standing QML objects we would need to create said objects internally along with the ownership enum of PLUGIN? Then these could be added to an existing NoteEvent list (setting ownership to SCORE)?
Is list ordering important for this item?
-Dale
In reply to > we should probably expose… by DLLarson
Aren't they logically owned by "Notes", or do I not know what I'm talking about here?
In reply to Aren't they logically owned… by [DELETED] 1831606
They aren't owned by a Note until it is added to the NoteEvent list. Until then the PLUGIN owns them.
It's like creating a note element with the 'newElement()' method. Until you add it to a Chord it's not owned by the Score. This is needed to ensure memory is cleaned up properly.
It's purely an internal C++ issue though.
-Dale
Hi everyone. I've chewing on this issue for a while and decided to take a stab at the more generalized object model.
The result is I've have submitted a pull request that exposes a note's NoteEvent list along with NoteEvent objects. You can find it here:
https://github.com/musescore/MuseScore/pull/5224
I've attached my test QML plugin that illustrates its use.
The PR's commit is "tagged" such that it will keep the Windows build artifacts from Appveyor so you can test these changes on Windows before they make it to the "master" branch. Unfortunately there is no Mac equivalent so if that's required you'll have build it yourself. :(
Two things aren't addressed at this point in the PR:
* How to add NoteEvent's and,
* How to remove NoteEvents.
I'm looking for ideas for those.
Note also that with the current patch you can change the various NoteEvent values and the undo stack will track it.
A side question:
I ran my test plugin on several complicated multi-instrument scores I download from the MuseScore.com site and none of them have more than one NoteEvent in their NoteEvent lists.
Can anyone supply me with a test score that actually uses more than one NoteEvent per note?
-Dale
In reply to Hi everyone. I've been… by DLLarson
Anywhere where there are ornaments, such as here: https://musescore.com/bsg/scores/968271 Too bad we can't get a mac build....
In reply to Anywhere where there are… by [DELETED] 1831606
Thanks for that!
I still don't see them. However I'm only scanning staff 0 though. Is there a particular place in the score you can point to that I can focus on?
-Dale
In reply to Thanks for that! I still don… by DLLarson
Nope, sorry, that has an execution staff (executing ornaments in hidden staves).... have to find something else.
Sorry, that uses an execution staff. Let me find something else.
In reply to Thanks for that! I still don… by DLLarson
Here: https://musescore.com/bsg/scores/5643575
In reply to Here: https://musescore.com… by [DELETED] 1831606
Hi,
When I run my new test plugin (attached) I see this output:
Plugin Details:
Menu Path: Plugins.Walk Note Events
Version: 3.0
Description: This test plugin walks through all NoteEvents in a score
Requires Score
Debug: Hello NoteEvent Walker
Debug: ###### START STAFF 0 ######
Debug: Chord[0].notes.length=1
Debug: ===notes[0].pitch=72
Debug: ===note.noteEvents.length=1
Debug: ------noteEvents[0].pitch=0
Debug: ------noteEvents[0].ontime=1000
Debug: ------noteEvents[0].offtime=0
Debug: ------noteEvents[0].len=1000
Debug: Chord[1].notes.length=1
Debug: ===notes[0].pitch=71
Debug: ===note.noteEvents.length=1
Debug: ------noteEvents[0].pitch=0
Debug: ------noteEvents[0].ontime=1000
Debug: ------noteEvents[0].offtime=0
Debug: ------noteEvents[0].len=1000
Debug: Chord[2].notes.length=1
Debug: ===notes[0].pitch=74
Debug: ===note.noteEvents.length=1
Debug: ------noteEvents[0].pitch=0
Debug: ------noteEvents[0].ontime=1000
Debug: ------noteEvents[0].offtime=0
Debug: ------noteEvents[0].len=1000
Debug: Chord[3].notes.length=1
Debug: ===notes[0].pitch=72
Debug: ===note.noteEvents.length=1
Debug: ------noteEvents[0].pitch=0
Debug: ------noteEvents[0].ontime=1000
Debug: ------noteEvents[0].offtime=0
Debug: ------noteEvents[0].len=1000
Debug: ^^^^^^ END STAFF 0 ^^^^^^
There is only single NoteEvent per note. The values are the same as I see in the Piano Roll Editor.
-Dale
see https://github.com/musescore/MuseScore/pull/5224
In reply to Hi, When I run my new test… by DLLarson
As demetrios suggested, you have to "play it first" to realize the ornaments. Try that.
In reply to As demetrios suggested, you… by [DELETED] 1831606
Why are both len and offtime present? My memory of the structure is that it only has offtime, no?
I've made that score private "by popular demand"; it's accessible as https://musescore.com/user/1831606/scores/5643575/s/7unc9y .
In reply to I've made that score private… by [DELETED] 1831606
It won't let me download it although I can see it.
-Dale
New site rules to discourage piracy. Without a pro account, you can't download. If you send me via .org email your email address, I will email it to you. It's really trivial to produce. Just enter a couple of notes, and add those ornaments to them from the ornaments palette.
In reply to New site rules to discourage… by [DELETED] 1831606
If it hasn't changed from the original that I did download it we should be fine.
After playing the score the NoteEvent's are indeed magically created. The test plugin now shows multiple NoteEvent's per note:
Running…
Plugin Details:
Menu Path: Plugins.Walk Note Events
Version: 3.0
Description: This test plugin walks through all NoteEvents in a score
Requires Score
Debug: Hello NoteEvent Walker
Debug: Score name=IgnoreTestNoteEvents
Debug: ###### START STAFF 0 ######
Debug: Chord[0].notes.length=1
Debug: ===notes[0].pitch=72
Debug: ===note.noteEvents.length=4
Debug: ------noteEvents[0].pitch=-1
Debug: ------noteEvents[0].ontime=0
Debug: ------noteEvents[0].offtime=125
Debug: ------noteEvents[0].len=125
Debug: ------noteEvents[1].pitch=0
Debug: ------noteEvents[1].ontime=125
Debug: ------noteEvents[1].offtime=250
Debug: ------noteEvents[1].len=125
Debug: ------noteEvents[2].pitch=2
Debug: ------noteEvents[2].ontime=250
Debug: ------noteEvents[2].offtime=375
Debug: ------noteEvents[2].len=125
Debug: ------noteEvents[3].pitch=0
Debug: ------noteEvents[3].ontime=375
Debug: ------noteEvents[3].offtime=1000
Debug: ------noteEvents[3].len=625
Debug: Chord[1].notes.length=1
Debug: ===notes[0].pitch=71
Debug: ===note.noteEvents.length=8
Debug: ------noteEvents[0].pitch=1
Debug: ------noteEvents[0].ontime=0
Debug: ------noteEvents[0].offtime=125
Debug: ------noteEvents[0].len=125
Debug: ------noteEvents[1].pitch=0
Debug: ------noteEvents[1].ontime=125
Debug: ------noteEvents[1].offtime=250
Debug: ------noteEvents[1].len=125
Debug: ------noteEvents[2].pitch=1
Debug: ------noteEvents[2].ontime=250
Debug: ------noteEvents[2].offtime=375
Debug: ------noteEvents[2].len=125
Debug: ------noteEvents[3].pitch=0
Debug: ------noteEvents[3].ontime=375
Debug: ------noteEvents[3].offtime=500
Debug: ------noteEvents[3].len=125
Debug: ------noteEvents[4].pitch=1
Debug: ------noteEvents[4].ontime=500
Debug: ------noteEvents[4].offtime=625
Debug: ------noteEvents[4].len=125
Debug: ------noteEvents[5].pitch=0
Debug: ------noteEvents[5].ontime=625
Debug: ------noteEvents[5].offtime=750
Debug: ------noteEvents[5].len=125
Debug: ------noteEvents[6].pitch=1
Debug: ------noteEvents[6].ontime=750
Debug: ------noteEvents[6].offtime=875
Debug: ------noteEvents[6].len=125
Debug: ------noteEvents[7].pitch=0
Debug: ------noteEvents[7].ontime=875
Debug: ------noteEvents[7].offtime=1000
Debug: ------noteEvents[7].len=125
Debug: Chord[2].notes.length=1
Debug: ===notes[0].pitch=74
Debug: ===note.noteEvents.length=3
Debug: ------noteEvents[0].pitch=0
Debug: ------noteEvents[0].ontime=0
Debug: ------noteEvents[0].offtime=125
Debug: ------noteEvents[0].len=125
Debug: ------noteEvents[1].pitch=-2
Debug: ------noteEvents[1].ontime=125
Debug: ------noteEvents[1].offtime=250
Debug: ------noteEvents[1].len=125
Debug: ------noteEvents[2].pitch=0
Debug: ------noteEvents[2].ontime=250
Debug: ------noteEvents[2].offtime=1000
Debug: ------noteEvents[2].len=750
Debug: Chord[3].notes.length=1
Debug: ===notes[0].pitch=72
Debug: ===note.noteEvents.length=4
Debug: ------noteEvents[0].pitch=2
Debug: ------noteEvents[0].ontime=0
Debug: ------noteEvents[0].offtime=500
Debug: ------noteEvents[0].len=500
Debug: ------noteEvents[1].pitch=0
Debug: ------noteEvents[1].ontime=500
Debug: ------noteEvents[1].offtime=666
Debug: ------noteEvents[1].len=166
Debug: ------noteEvents[2].pitch=2
Debug: ------noteEvents[2].ontime=666
Debug: ------noteEvents[2].offtime=832
Debug: ------noteEvents[2].len=166
Debug: ------noteEvents[3].pitch=0
Debug: ------noteEvents[3].ontime=833
Debug: ------noteEvents[3].offtime=999
Debug: ------noteEvents[3].len=166
Debug: ^^^^^^ END STAFF 0 ^^^^^^
In order for this scripting feature to be useful it would seem we need to trigger this behavior from the plugin?
What prevents plugin changes from being wiped out on the next play?
-Dale
In reply to If it hasn't changed from… by DLLarson
The Plugin probably cannot mess with ornaments (neither can the piano editor), but changes to other notes are not wiped out (compare all behaviors of the PRE), but it can look at them. We have to figure out how it records the state of the ornament realization.
I can't even download it despite having a Pro account. I can download others though
In reply to The Plugin probably cannot… by [DELETED] 1831606
The ornamentation-delay issue is (as D notes, no pun intended), being identical for the PRE and the plugin, seems a documentation issue. An API to trigger the ornament realization wouldn't be bad, but we don't know how yet.
In reply to I can't even dowenload it… by Jojo-Schmitz
From the private link? I don't know what to say. .com breakage. I don't want to make it public again or 200 people will complain at me. But "just add some turns and trills to notes" is a simple enough formula.
I've exposed a Score.createPlayEvents() method to the Score object. If this is called the ornaments are realized into the Note's NoteEvent lists. Then walking the notes you can see the updated NoteEvents.
This raises a general question....
Internally the NoteEvent lists are called "playLists". Should my proposed QML interface also change "Note.noteEvents" to "Note.playEvents" for consistency? I'm thinking it should.
Also, should NoteEvent's also be called PlayEvent's in QML?
-Dale
In reply to I've exposed a Score… by DLLarson
I don't like the name "NoteEvents" at all, because they aren't notes, nor events, but really little sub-notes, but there is much to be said for tracking the C++ names ipso facto. I don't feel qualified to offer an opinion beyond that.
I'm going to switch the naming to be more consistent and see how things shake out.
-Dale
Proposal?
yes, from the private link
In reply to yes, from the private link by Jojo-Schmitz
Anders kann ich nicht t(h)un.
I've pushed up the the changes.
From the QML perspective all NoteEvent's are now PlayEvent's. A mid-way compromise between the two. The new name at least ties the objects with playback activity.
The new QML interfaces are:
Set's also create undo records.
A run of the new test plugin (attached) against your test score (also attached) produces this output:
Running…
Plugin Details:
Menu Path: Plugins.Walk PlayEvents
Version: 3.0
Description: This test plugin walks through all PlayEvents in a score
Requires Score
Debug: Hello PlayEvent Walker
Debug: Score name=IgnoreTestNoteEvents
Debug: ###### START STAFF 0 ######
Debug: Chord[0].notes.length=1
Debug: ===notes[0].pitch=72
Debug: ===note.playEvents.length=4
Debug: ------playEvents[0].pitch=-1
Debug: ------playEvents[0].ontime=0
Debug: ------playEvents[0].offtime=125
Debug: ------playEvents[0].len=125
Debug: ------playEvents[1].pitch=0
Debug: ------playEvents[1].ontime=125
Debug: ------playEvents[1].offtime=250
Debug: ------playEvents[1].len=125
Debug: ------playEvents[2].pitch=2
Debug: ------playEvents[2].ontime=250
Debug: ------playEvents[2].offtime=375
Debug: ------playEvents[2].len=125
Debug: ------playEvents[3].pitch=0
Debug: ------playEvents[3].ontime=375
Debug: ------playEvents[3].offtime=1000
Debug: ------playEvents[3].len=625
Debug: Chord[1].notes.length=1
Debug: ===notes[0].pitch=71
Debug: ===note.playEvents.length=8
Debug: ------playEvents[0].pitch=1
Debug: ------playEvents[0].ontime=0
Debug: ------playEvents[0].offtime=125
Debug: ------playEvents[0].len=125
Debug: ------playEvents[1].pitch=0
Debug: ------playEvents[1].ontime=125
Debug: ------playEvents[1].offtime=250
Debug: ------playEvents[1].len=125
Debug: ------playEvents[2].pitch=1
Debug: ------playEvents[2].ontime=250
Debug: ------playEvents[2].offtime=375
Debug: ------playEvents[2].len=125
Debug: ------playEvents[3].pitch=0
Debug: ------playEvents[3].ontime=375
Debug: ------playEvents[3].offtime=500
Debug: ------playEvents[3].len=125
Debug: ------playEvents[4].pitch=1
Debug: ------playEvents[4].ontime=500
Debug: ------playEvents[4].offtime=625
Debug: ------playEvents[4].len=125
Debug: ------playEvents[5].pitch=0
Debug: ------playEvents[5].ontime=625
Debug: ------playEvents[5].offtime=750
Debug: ------playEvents[5].len=125
Debug: ------playEvents[6].pitch=1
Debug: ------playEvents[6].ontime=750
Debug: ------playEvents[6].offtime=875
Debug: ------playEvents[6].len=125
Debug: ------playEvents[7].pitch=0
Debug: ------playEvents[7].ontime=875
Debug: ------playEvents[7].offtime=1000
Debug: ------playEvents[7].len=125
Debug: Chord[2].notes.length=1
Debug: ===notes[0].pitch=74
Debug: ===note.playEvents.length=3
Debug: ------playEvents[0].pitch=0
Debug: ------playEvents[0].ontime=0
Debug: ------playEvents[0].offtime=125
Debug: ------playEvents[0].len=125
Debug: ------playEvents[1].pitch=-2
Debug: ------playEvents[1].ontime=125
Debug: ------playEvents[1].offtime=250
Debug: ------playEvents[1].len=125
Debug: ------playEvents[2].pitch=0
Debug: ------playEvents[2].ontime=250
Debug: ------playEvents[2].offtime=1000
Debug: ------playEvents[2].len=750
Debug: Chord[3].notes.length=1
Debug: ===notes[0].pitch=72
Debug: ===note.playEvents.length=4
Debug: ------playEvents[0].pitch=2
Debug: ------playEvents[0].ontime=0
Debug: ------playEvents[0].offtime=500
Debug: ------playEvents[0].len=500
Debug: ------playEvents[1].pitch=0
Debug: ------playEvents[1].ontime=500
Debug: ------playEvents[1].offtime=666
Debug: ------playEvents[1].len=166
Debug: ------playEvents[2].pitch=2
Debug: ------playEvents[2].ontime=666
Debug: ------playEvents[2].offtime=832
Debug: ------playEvents[2].len=166
Debug: ------playEvents[3].pitch=0
Debug: ------playEvents[3].ontime=833
Debug: ------playEvents[3].offtime=999
Debug: ------playEvents[3].len=166
Debug: ^^^^^^ END STAFF 0 ^^^^^^
It's time for some wider feedback from other interested parties.
We also need feedback on the need to add destroy PlayEvent's from QML.
-Dale
Is there any way I can talk anyone who can do Mac builds to make one for me/us??? Setting up an environment that can do that is not a trivial or guaranteed thing, and someone who can do this can just git-fetch and build one for me....TIA.
In reply to Anders kann ich nicht t(h)un. by [DELETED] 1831606
In general it seems better to attach sample scores directly to the issue of forum topic rather that having just a hyperlink (which may break later).
In reply to In general it seems better… by Jojo-Schmitz
"D'uh!" Indeed! Thanks for reminding me.
I have made a build of PR 5224 for macOS. It can be found here: https://github.com/mattmcclinch/MuseScore/releases/download/PR5224/Muse….
Thank you so much! I will get busy with this ASAP!
>I have made a build of PR 5224 for macOS.
Fantastic! Thanks for the help!
-Dale
OK, OK, guys -- hold your NoteEvents! ...getting to it (writing the test plugin I need is nontrivial) -- I suppose I should first prove that DLL's works ...
In reply to I have made a build of PR… by mattmcclinch
This build is very broken. Try to play any score and it either stutters infinitely on one note or sounds all notes one by one but doesn't shut them off. The note events are obviously very broken. I had to ForceQuit, twice.
Mattmcc, can you reproduce my failure>
My code changes didn't modify anything about note events internally. So the first test should simply work. The second test only does read-only scans by default (if the doWriteTest is 'false') so it also should not cause playback problems.
In those cases it's something about the Mac build or install. Note that these builds are based on top of current 'master' PR's so you should check a 'nightly' build from here to sanity check those PR's.
http://prereleases.musescore.org/macosx/nightly/
-Dale
That test has already failed. I tried to load a score and play it, and that failed (note-off's weren't observed).. Didn't get to load the plugin. I suspect something changed in either the NoteEvents, their vtables, or the dependencies and things that have to be recompiled (and not enough was recompiled) or something on that order. You did add some methods to the NoteEvents, right (could change vtables)....
>You did add some methods to the NoteEvents, right (could change vtables)....
I only exposed them via the outside Plugin layer. Unless the plugin wrappers are called to modify PlayEvent data it should have no effect on normal operation. I didn't actually extend the system's internal classes. You can see this by looking at the commit. It only affects plugin level code.
>or the dependencies and things that have to be recompiled (and not enough
>was recompiled) or something on that order.
This is more likely but I'm thinking we should look at what 'master' contributed to the result. Best to try the nightly so we can see where the issue lies.
-Dale
For what it's worth, I tried the new build again creating a new score, piano solo. The first and only note I entered would not stop, and I again had to ForceQuit the app. Interestingly, the other instance of MS I had open then started experiencing similar problems until I "reset midi".
The build that I provided should allow you to run the plugin and save the result. If there are playback issues, it is unlikely that they are the result of DLLarson's changes. You can continue to use the official MuseScore release for playback.
That's a crippling restriction -- type any alphabetic key and the app crashes.... Do you reproduce my failure (can't play any notes without crashing) or not? Were all modules through-and-through everywhere recompiled? Can you play without crashing without his changes?
I am surprised that you were able to have multiple instances of MuseScore 3 open at the same time. Perhaps that is contributing to the playback problems that you are experiencing. What happens if you close all other instances of MuseScore before running my build?
I tried running his plugin in the Plugin creator and received: Running…
Creating component failed
line 24: Expected token
;'
;'line 24: Expected token
No, I cannot reproduce your failure. I can play without crashing with or without his changes.
One testing strategy I've used with MuseScore on Windows is to have the previous supported release installed and then copy only the new test executable (MuseScore.exe for Windows) directly into the 'bin' folder and run it that way. This way the overall application installation on the OS doesn't change so your dependencies should be good.
I'm note sure how the Mac is organized but it is a Unix based OS so it probably follows a similar layout which looks much like Linux even on Windows.
-Dale
In reply to I am surprised that you were… by mattmcclinch
Egg on my face; if I close the other MS before starting, it plays properly. But I have had multiple MS's open many, many times before, same and different versions, and no problem. But, indeed, we are beyond that, and sorry for the false alarm. Now have to debug why DLL's plugin doesn't load ....
In reply to Egg on my face; if I close… by [DELETED] 1831606
Dale, can you post a latest working version of the plugin? I don't understand why the posted one is claimed to lack a semicolon.
Let's make sure we're all using the same test QML so we all agree on results.
I'm attaching the current working test QML to this message. This should run without issues.
Let us know if it works. Thanks!
-Dale
In reply to Let's make sure we're all… by DLLarson
This works flawlessly! Thank you both so much. Time to do "my thing" with it ...
Running…
Plugin Details:
Menu Path: Plugins.Walk PlayEvents
Version: 3.0
Description: This test plugin walks through all PlayEvents in a score
Requires Score
Debug: Hello PlayEvent Walker
Debug: Score name=St_Anne_direct_no_SDRC
Debug: ###### START STAFF 0 ######
Debug: Chord[0].notes.length=1
Debug: ===notes[0].pitch=70
Debug: ===note.playEvents.length=1
Debug: ------playEvents[0].pitch=0
Debug: ------playEvents[0].ontime=0
Debug: ------playEvents[0].offtime=1000]]
Debug: ------playEvents[0].len=1000
Debug: Chord[24].notes.length=1
Debug: ===notes[0].pitch=51
Debug: ===note.playEvents.length=1
Debug: ------playEvents[0].pitch=0
Debug: ------playEvents[0].ontime=0
Debug: ------playEvents[0].offtime=1000
Debug: ------playEvents[0].len=1000
Debug: Chord[25].notes.length=1
[clipped for volume]
Debug: ------playEvents[0].pitch=0
Debug: ------playEvents[0].ontime=0
Debug: ------playEvents[0].offtime=850
Debug: ------playEvents[0].len=850
Debug: Chord[28].notes.length=1
Debug: ===notes[0].pitch=46
Debug: ===note.playEvents.length=1
Debug: ------playEvents[0].pitch=0
Debug: ------playEvents[0].ontime=0
Debug: ------playEvents[0].offtime=1000
Debug: ------playEvents[0].len=1000
Debug: Chord[29].notes.length=1
Debug: ===notes[0].pitch=51
Debug: ===note.playEvents.length=1
Debug: ------playEvents[0].pitch=0
Debug: ------playEvents[0].ontime=0
Debug: ------playEvents[0].offtime=1000
Debug: ------playEvents[0].len=1000
Debug: ^^^^^^ END STAFF 2 ^^^^^^
In reply to This works flawlessly! Thank… by [DELETED] 1831606
Great news!
I'll be looking forward to your experiences and feedback!
Thanks also to @mattmcclinch for your valuable assistance!
-Dale
In reply to Great news! I'll be looking… by DLLarson
I've all the rope I need now .... thanks again to both of you. Watch this space!
(del)
Here's a proof of concept. Life would be better if someone would point me to a simple example of how to issue a(n error) message box. This plugin is the paragon of simplicity; you select some notes in one or more staves (with the blue-box selection, click-on won't do), and invoke "mung offtimes". Set anything from 100 to 2000 and there you go. I skip over notes with multiple play-events (i.e., ornamented). Strangely, you may not hear the result take effect until you cancel the selection (way after the plugin is gone). Don't quite understand this. Undo works. Also attached is a recent chorale-prelude of mine, where the cantus/oboe part has been phrased, including single notes at times, solely with this new plugin. I wish I could accept keystrokes (Enter and Esc) to do the obvious.
This is a watershed. This is a significant leap in the usability of MuseScore as a tool for crafting automatic performances. Enjoy/feedback/thanks!
(Anybody else reading, this is only usable with the special builds described in this thread).
Are we to understand then that DLLarson's pull request works entirely as expected and provides all of the functionality that you are looking for?
In reply to Are we to understand then… by mattmcclinch
Well, as you see, my application is no older than your build, just born, but, "Gee whiz! It seems to work!" indeed. I was surprised that off-time was not settable (you have to use "len"), but that's small potatoes. It certainly seems to provide the functionality I was hoping for (on this round -- it's conceivable that creating and deleting play events would be nice some day, but I don't have a proposed UX use yet). For now, the answer is "yes".
In reply to Are we to understand then… by mattmcclinch
>Are we to understand then that DLLarson's pull request works entirely as expected
>and provides all of the functionality that you are looking for?
I would say no since there is no way to build a new list of PlayEvent's for a note. I'm looking at that issue right now. QML still befuddles me in how to expose automatically creatable QML objects from C++ objects.
My overall thinking is this:
Add an additional method to PlayEvents list called clear(). This already is supported by QQmlListProperty.
My implementation would clear the native NoteEvent list and add a single default NoteEvent to it. This is the default internal state of a newly created Ms::Note. Semantically it's more like a 'reset()' than 'clear()' though. There is some wiggle room here although I haven't yet found the boundaries of that room yet. ;)
I also need to be able to create a QML PlayEvent that can be append()-ed to the list--which is also supported by QQmlListProperty.
At present, I'm currently wrestling with creating a PlayEvent from QML that instantiates my internal Ms::PluginAPI::PlayEvent. The Qt docs seem to say this is possible. It's just another Qt rabbit hole to jump down.
A definitely simpler approach would be to do the PlayEvents.clear() implementation as above and also have an argument-less PlayEvents.append() method that simply adds a default NoteEvent to the list. Then the values can be manipulated as desired. This feels less "object-oriented" though.
So the process could be like:
note.playEvents.clear(); // Reduces list down to single default NoteEvent.
note.playEvents.append(); // Call n-1 times to get n-length list.
// Loop on note.playEvents to fill out the desired settings.
-Dale
I was surprised that off-time was not settable (you have to use "len")
Well that makes sense, since offtime is a computed value, equivalent to ontime + len. See https://github.com/musescore/MuseScore/blob/master/libmscore/noteevent….
In reply to >Are we to understand then… by DLLarson
I could live with that (creation paradigm). But it's not as urgent as today's stuff. Re len vs offtime, ok, but I repeat that offtime, not len, should be the user-visible artifact not only here but in the Piano Roll Editor; the current situation is a UI bug AFAIAC.
So if "offtime = ontime + len", then also" ontime = offtime - len" and "len = offtime - ontime"
No reason for having any one of those read-only IMHO
Another thing becoming possible now is the arpeggiation of a right-hand chord expressed in several voices; a plugin will be able do this now, but it is impossible in MS raw. I need this every time I realize continuo on harpsichord.
In reply to Well, as you see, my… by [DELETED] 1831606
> I was surprised that off-time was not settable (you have to use "len"), but that's small potatoes.
The offtime setting is not supported in the internal NoteEvent.
As I tried to provide it myself via PlayEvent I had problems with ensuring the object was consistent. For instance, if you set an offtime that is before the current ontime what should the code do? Should it swap the two times? Should it error? ... and so on. If you set len how would it keep the offtime consistent?
I see why it was done as a base time and length. Simple to move or set duration. I did provided the offtime as a readonly property. Just like the internal version though. I can remove it if you think it causes API confusion.
-Dale
In reply to I could live with that … by [DELETED] 1831606
> but I repeat that offtime, not len, should be the user-visible artifact not only here but in
>the Piano Roll Editor; the current situation is a UI bug AFAIAC.
The UI has complete control of the final state while you are interacting with it so I get what you're saying from a UI perspective. From a code/scripting perspective it's a mess.
I'm sure the UI code takes your final offtime selection and calculates the difference between the UI offtime and ontime and sets it as a new len internally.
-Dale
In reply to I could live with that … by [DELETED] 1831606
>I could live with that (creation paradigm).
Which? Both?
-Dale
In reply to >I could live with that … by DLLarson
Clear and append; if there's no way to delete an arbitary one, that's the only choice.
In reply to So if "offtime = ontime +… by Jojo-Schmitz
>So if "offtime = ontime + len", then also" ontime = offtime - len" and
>"len = offtime - ontime" No reason for having any one of those read-only IMHO
True mathematically but since only a single value can change at once what do you do with the others?
Basically you will have side effects on the other values depending on what you set since you have three values maintained from the user perspective.
This is not true with explicit value setting. There is no ambiguity. The onus should be on the script programmer much like the C++ programmer to map intent into implementation.
-Dale
In reply to Clear and append; if there's… by [DELETED] 1831606
>Clear and append;
There are two choices for those:
(1) One supports creating un-attached PlayEvent objects that you can set their values and THEN append them to the list one at a time using playEvent.append(myNewPlayEvent). Of course the inconsistency here is that the first PlayEvent in the list always exists even when Note.playEvents.clear() is called and has to be changed by accessing the Note.playEvents[] list anyway.
or the other one:
(2) The other was to simply call append() with no arguments at all and it simply adds another default PlayEvent to the end of the list (or it could take a count to add a number of them all at once) and you would then access the Note.playEvents[] list to modify the settings for the individual PlayEvent's. There is no inconsistency here because Note.playEvents.clear() and .append() always starts with default internal NoteEvent's that must be set by the
Those are the choices that I see right now. I'm leaning toward (2) for consistency but that's just me.
I will add that internally I see NoteEventLists' being cleared and new NoteEvents added by appended to them when rendering ornamentation. So (2) looks more like the internal stuff as well.
-Dale
In reply to >Clear and append; There are… by DLLarson
I don't really understand the dharma of the "first, default play event". You probably understand it better than do I and are in a better position to make a decision. For what it's worth, I think doing things one-at-a-time in a loop is to be preferred to pre-doing however many you need.
In reply to I don't really understand… by [DELETED] 1831606
The dharma is similar to the truth (inconvenient) that chords must have at least one note in them in internally or MS will crash. This same limitation shows up in the QML scripting. You can't delete the last note of an existing chord.
In this case it's that you can't delete the last NoteEvent. Too much internal code assumes it exists so that quirk works its way out into the scripting.
I'm heading toward solution (2).
Hi,
I've just posted my changes that enable manipulating Note.playEvents lists.
Full UNDO support is provided as well.
The best way to grok the approach is to look at the attached test QML plugin supplied with this post.
Here's a summary of Javascript use:
note.playEvents = [] // This clears the entire list. Don't blame ME! It's the way Javascript works.
var newPlayEvent = note.createPlayEvent(); // Creates a new PlayEvent with default settings.
newPlayEvent.pitch = 2 // Change a setting
note.playEvents.push(newPlayEvent) // This adds to the end of the list.
The attached test plugin QML also shows how to add a PlayEvent that is predefined in QML.
Also, it turns out that having an empty internal NoteEventList is fine so I didn't need to explain away having to keep a default entry.
Please give it a good hammering!
-Dale
In reply to Hi, I've just posted my… by DLLarson
I can't hammer nuthin' until matt gives me a hammer! I hope this will be in the nightlies soon, but I guess I have to hammer it first. I'll try Beethoven's Hammerqml Sonata...(op 106q).
The Windows and Mac targets build fine so Matt should be able to build it.
The Linux build has a weird compile error so don't count on that one for a while.
-Dale
No, it does not build on macOS. It only builds in Visual Studio. The fact that the MacOSX job passed does not mean anything. So no, I am currently not able to make a build of the PR for testing on macOS.
In reply to No, it does not build on… by mattmcclinch
Do you get same error as the Linux build shows on the PR?...
[ 98%] Building CXX object mscore/CMakeFiles/mscore.dir/plugin/api/cursor.cpp.o
In file included from /home/travis/build/musescore/MuseScore/mscore/plugin/api/elements.h:28:0,
from /home/travis/build/musescore/MuseScore/mscore/plugin/api/qmlpluginapi.cpp:15:
/home/travis/build/musescore/MuseScore/mscore/plugin/api/playevent.h: In static member function ‘static void Ms::PluginAPI::QmlPlayEventsListAccess::clear(QQmlListProperty*)’:
If so, what compiler and version are you using?
I'm putting together a Ubuntu 18.04 LTS x64 system on VMware to try to figure this out as I'm baffled. If you see something obvious I'd certainly welcome your insights!
-Dale
In reply to No, it does not build on… by mattmcclinch
The most obvious thing for which I can imagine using notelet/PlayEvent creation is ornamentation implementation to a more elaborate degree than MS allows for hardwired (say, even given what we have now (ready) we can fix appoggiatura timing -- something else to build and test). In order to realize this (ornamentation implementation) in QML, an extension would no only have to access the tonal-pitch-class (tpc) of the base note (is that now possible?) but also ask about the current key signature and accidental state ("Are A's flat, sharp or natural right here?") to compute the necessary midi pitch of the auxiliary notes to be added. Do we have anything like that exposed? Plugins that either implement complex sub-note expanses, or take a string of explicit notes in a selection and plug them in somewhere else as hidden notelets would be very, very powerful.
>The most obvious thing...
Nearly all of that is greek to me and I don't speak Greek. You'll have to layperson it down if it's important I understand all this.
>an extension would no only have to access the tonal-pitch-class (tpc) of the base note (is that now possible?)
There are these properties exposed in the Note object:
Note.tpc
Note.tpc1
Note.tpc2
which look like what you want?
>but also ask about the current key signature and accidental state ("Are A's flat, sharp or
>natural right here?") to compute the necessary midi pitch of the auxiliary notes to be added.
>Do we have anything like that exposed?
I see a Score.keysig but I don't think that's what you're looking for.
-Dale
In reply to >The most obvious thing… by DLLarson
Don't know what tpc vs tpc1 and tpc2 are, but it must be enough if they're all exposed. Keysig is a start. Note control in ornamentation leaves a bit to be desired right now. This is kind of hard to explain in laymanese without illustrating scores or even a blackboard.... I feel a bit frustrated that this channel isn't wide enough to succeed...
You know, between the key signature and being able to go back through notes in the measure and look at their accidentals, I think I may just have all the info I need (I'm sure accidentals on notes are exposed)....
Here's the link to the latest plugin auto generated docs. It doesn't contain my new stuff but is otherwise up-to-date:
https://dmitrio95.github.io/plugins/html/index.html
In the Score docs stuff it says this about tpc...
https://dmitrio95.github.io/plugins/html/class_ms_1_1_plugin_a_p_i_1_1_…
Here's the docs for the Score object:
https://dmitrio95.github.io/plugins/html/class_ms_1_1_plugin_a_p_i_1_1_…
-Dale
OK, that all makes sense.
I have modified the latest version of the PR so that it builds on Linux and macOS. Once again, the macOS build can be found here: https://github.com/mattmcclinch/MuseScore/releases/download/PR5224/Muse….
Thanks, will d/l. This will take a little time to develop a meaningful application beyond Dale's test plugin (which I will, of course, test at soon as I've downloaded).
In reply to Thanks, will d/l. This will… by [DELETED] 1831606
I'm having MuseScore Version overflow. What should the Build ID hex number in the About dialog say for this build?
It is an unstable pre-release for 3.3.0. The revision number is probably 3543170, which refers to a commit from 6 years ago, because I did not do the ‘make revision’ step. Incidentally, the previous build that I supplied would have the same revision number also.
Bleagh. I will have to watch the re-installation process more carefully to figure out which is which, but, ... thanks again in any case...
AOK; build runs, and Dale's plugin runs and adds very interesting ornamentation to otherwise healthy music, readily visible in the Piano Roll Editor ... R&D continues.
In reply to AOK; build runs, and Dale's… by [DELETED] 1831606
> Dale's plugin runs and adds very interesting ornamentation to otherwise healthy music,
>readily visible in the Piano Roll Editor.
Hey!? That hurts! I spent almost zero time picking the numbers! ;)
What's really fun is to hit play to play the score, then hit undo and play again and compare, hit redo... and so on.
One weird behavior the piano roll editor view has is that it doesn't repaint on an undo or redo. I have to click in the view and and then it repaints.
-Dale
A gotta admit, running my test QML against Canon_IV_in_hypodiapente.mscz makes it almost psychotic!
Undo...sounds great...Redo....just crazy... just do it as the piece plays.
Here's a question for BSG...
When I save the score with the altered PlayEvents I can't undo back because that info's gone. When the user creates PlayEvents they are flagged as "User" play events. In this case they are saved within the score.
Is there any way in the UI to reset all the Note's play events back to "auto" mode ?
i.e., Basically set all the notes to PlayEventType::Auto.
I don't see anything like it in the piano roller editor view.
I attached the mixed up score to this message. The music looks great but doesn't sound so good.
The undo/redo works great you can run the test plugin on enormous scores and undo/redo during playback and it's snappy (the QML took a little bit of time to run though).
-Dale
The new "ornaments" have no graphics associated with them. Normally, when you delete the graphic for an ornament, it resets (what we now know to be) the generated PlayEvents, i.e., "unornaments" the note. That is indeed a design problem here...
There may not currently be a way to reset the PlayEvents, but I'm sure you could write a plugin that could do that.
In reply to There may not currently be a… by mattmcclinch
>There may not currently be a way to reset the PlayEvents, but I'm sure you could write a
>plugin that could do that.
A plugin caused the damage... It should damn well clean it up! ;)
I don't see anything that exposes that to a plugin. Even if you do a:
note.PlayEvents = [] // clear
note.PlayEvents.push(note.createPlayEvent) // sets the list to a single default PlayEvent.
The Note.PlayEventType is still "User". From code...
enum class PlayEventType : char {
Auto, // Play events for all notes are calculated by MuseScore.
User, // Some play events are modified by user. The events must be written into the mscx file.
InvalidUser // The user modified play events must be replaced by MuseScore generated ones on
// next recalculation. The actual play events must be saved on the undo stack.
};
The most sensible thing would be to expose PlayEventType on the Note.
Then the plugin has full control to create, destroy...and recreate.
Once you set a note to "PlayEventType::Auto" calling Score.createPlayEvents() will recreate all the ornaments as it would originally.
-Dale
See [#292366] , please. https://musescore.org/en/node/292366 (don't know why ref didn't work).
that [#nnnnn] notation only works for issues, not for forum topics
I just pushed up my (and Matt's) latest work that exposes the PlayEventType via Chord.playEventType.
This property controls how PlayEvent's are managed internally when rendering ornaments.
With this change I can also fix the borked score I uploaded earlier on this thread by defining the following in the latest test plugin attached to this post. Just set "doClearUserEventsTest" to "true" as shown here and run the plugin:
The default test plugin doesn't have this value set to "true".
I've also added a plugin the just fixes the messed up score.
-Dale
In reply to I just pushed up my (and… by DLLarson
Lemme see if I understand this correctly. Note.PlayEventType is basically the long-sought flag that says "I have already realized the ornament (or whatever)"?
In reply to Lemme see if I understand… by [DELETED] 1831606
>Note.PlayEventType is basically the long-sought flag that says "I have already
>realized the ornament (or whatever)"?
(BTW, this should really be Chord.PlayEventType.)
No, from what I see in the code it says:
For this chord, if it's set to PlayEventType.User, MuseScore trusts that the playEvent lists are what you want so it'll save and restore the lists from the score file.
However, if the chord has it set to PlayEventType.Auto then MuseScore will assume it can create ornamentations if they are specified for the notes. It will leave the non-ornamented notes as-is which is the default PlayEvent. This setting is enforced at the Chord level.
If you change stuff in the PRE I believe MuseScore sets this value to PlayEventType.User so it doesn't lose your changes.
-Dale
For what-its-worth there is a test Windows build of this feature here:
https://ci.appveyor.com/api/buildjobs/yih20smfqg4b5cj8/artifacts/MuseSc…
-Dale
I've added an additional example in the test plugin (newly attached v5) that illustrates how you can create predefined lists of PlayEvent's to enable an effect for a note. The example definition looks like this:
To set them:
-Dale
In reply to I've added an additional… by DLLarson
Until there is a way to access a note the user clicks on, plugins that implement ornamentation (unfortunately) can't be useful. I hope that that problem can be addressed. Of course, the user can select any element, and most kinds of elements are probably not QML-represented.
>Until there is a way to access a note the user clicks on, plugins that implement ornamentation (unfortunately) can't be useful.
So the work I did here is of no use?
-Dale
I wouldn't go that far—remember, dmitrios himself promoted its advent on the basis of elegance/completeness, not of immediately-accessible UX. I can imagine a grievously kludgey way to select a segment (by a one-segment selection) and pick a note in it perhaps with a staff/voice number, but I anticipate that "give me the selected note" is possible, if not by you, then sooner or later by me. I can't imagine any argument against having such a thing -- anyone?
>but I anticipate that "give me the selected note" is possible,
I'm looking at it now. Clearly the notion of selecting a note exists since you can do it in the UI.
Oh, it absolutely exists and is central to the way the program is used. You select notes as you enter them, even if you don't do so explicitly. What is needed is a way of identifying the selected note (and its containing chord, segment, measure, voice, and staff (might be easy), all QML-accessible objects). The issue is that things other than notes can be selected, including texts, clefs, frames, etc., in which case "no note is selected", and that's part of the design problem.
In reply to Oh, it absolutely exists and… by [DELETED] 1831606
There are countless things already that require that a note, and not anything else, be selected, such as ornament and articulation palette elements (when double-clicked on). And several notes, in the same segment or not, can also be simultaneously selected (such as by the "Notes" button when a selection region is active).
I've just pushed up a patch to try out a new method of selection for the Cursor object called the Cursor.SELECTION_LIST,
It works like this in QML:
Any items that you just click, or ctrl-click are part of the list. If you SHIFT-click you will NOT get a list. It will do a full-throated segment select which you don't want. Note that this works with any score element as far as I can tell.
I've attached a test QML script to this post.
-Dale
In reply to I've just pushed up a patch… by DLLarson
So every type of score element is QML visible? This seems like a very, very great boon! I should certainly like to see this in a Mac build! Can you get the chord/segment/etc from the selected note?
Maybe you could even build QML code that takes the selected note and implements your "unique ornament" upon it....
>So every type of score element is QML visible? This seems like a very, very, very great boon!
Even though this makes them available (i.e., it doesn't screen any out) it doesn't mean object properties for them are necessarily exposed. I'm not clear on the implications of this.
>Maybe you could even build QML code that takes the selected note and implements your "unique ornament" upon it....
By "you" you mean you--or perhaps the universal You? ;-)
-Dale
No, I mean the specific you who alone has QML code to implement an elaborate "test" ornament and a build that can convey a note selection. The proof-of-concept is a plugin which takes the one selected note and expands that ornament (you know, the -2 -1 0 2 1 whatever) upon it.
>No, I mean the specific you who alone has QML code to implement an elaborate "test"
>ornament and a build that can convey a note selection.
Ok, I'm assuming that a build will materialize for you at some point.
My newly attached plugin file (v2) illustrates adding my custom PlayEvent thingy to the selected notes.
Just click on a note and run the plugin.
Or, control-click on several notes, run the plug-in, and it will embellish all the selected notes.
Non-notes are ignored by the script.
Code Excerpt:
-Dale
That's pretty fine! Matt? This opens whole new landscapes of how plugins can be used to supplement MS functionality. Designing a UI for this is nontrivial, but I'm up to and for it.
Now, are a Note's containing structures accessible from it (in C++, back pointers shouldn't be a problem as they are in some loop-averse languages....).
Ok, I'm assuming that a build will materialize for you at some point.
And here it is: https://github.com/mattmcclinch/MuseScore/releases/download/PR5224/Muse….
By the way, the revision number for this build is ee64627.
In reply to Ok, I'm assuming that a… by mattmcclinch
Thanks, downloading now.
In reply to Thanks, downloading now. by [DELETED] 1831606
Yup, definitely works as expected, adds exotic ornament to the selected note!
In reply to Yup, definitely works as… by [DELETED] 1831606
Could you remind me how/why such modifications are persisted through saving/reopening the file? Thanks.
In reply to Could you remind me how/why… by [DELETED] 1831606
For each note written to the file, if it has NoteEvents, and its chord’s playEventType is not set to PlayEventType::Auto, then these NoteEvents are written to the file also. It is all done in Note::write() in libmscore/note.cpp.
In reply to For each note written to the… by mattmcclinch
Plus the setting to PlayEventType::User is automatic handled when modifying the PlayEvent's so you don't have to. Removal if the setting would be another matter though as noted earlier on this thread.
-Dale
In reply to Plus the setting to… by DLLarson
Thanks, both. This will facilitate some neat plugins (e.g., adjust appoggiatura fraction with slider)!
I gather from the coloring plugin that "grace notes" (such as appoggiature) are indeed fully accessible from Notes in QML (just checking)?
Yes
>I gather from the coloring plugin that "grace notes" (such as appoggiature) are indeed fully accessible from Notes in QML (just checking)?
Yes. They show up as NOTE types as that's what they are internally. I'm not sure how you can determine if they're a grace note or not. Maybe by looking at parentage.
BTW... When you run a debug compiled version of MS and right click on a note you'll see "Debugger" on the context menu. When you select it you get this cool window with breakdowns of elements and visual parentage:
I don't think it's in the retail build. Clearly a lot of work went into it's implementation. Very slick!
-Dale
Durn! I don't have a debug build (it's not in the context menu). This sure would help ... (Oh, I bet it can't be packaged as a release for me, right?).
There's been a new feedback on the GitHub PR for this issue as to where to expose the selection list:
https://github.com/musescore/MuseScore/pull/5224#discussion_r306560473
I'm working on his suggestion. Stay tuned.
-Dale
In reply to There's been a new feedback… by DLLarson
Makes sense (decouple from cursor/next).
I've done the Selection based implementation but I'm having strange behavior with Selection exposure approach while the Cursor approach works flawlessly.
I pushed up a set of commit's that provide both solutions plus test QML and a score so they can be examined in the same debug executable together:
https://github.com/musescore/MuseScore/pull/5224/commits
I've asked for assistance in the PR:
https://github.com/musescore/MuseScore/pull/5224#discussion_r306975726
Here's hoping some fresh eyes can see my problem!
(Fingers crossed and all.)
Hi,
I think things are working much better today. The new Score.Selection exposure is working well. Some other changes for Chord.playEventType undo support have been added as requested in the PR.
The Selection support has been peeled off into another PR so it can be inspected as a standalone features so this feature is NOT available in the PlayEvent PR anymore. In order for Matt to create a test version I created a branch on my MuseScore Github repo that combines the two features here:
https://github.com/DLLarson/MuseScore/tree/qml-pr5224-pr5243-playevent-…
I've attached a new selection test script to this post that demonstrated using the score.selection object.
-Dale
Matt? Looking forward. (I suppose one day I will figure out how to build for myself) What turned out to be yesterday's problem?
Can you tell me why this line
for (let [key, value] of Object.entries(obj)) {
gets
line 12: Expected token
;'
;'line 12: Expected token
for me in each of your plugins?
A subtle problem with polymorphism. Here's the fix provided by @dmitrio on it's own:
https://github.com/dmitrio95/MuseScore/commit/344b1f3202a8463182acb384b…
I'm really not sure why it worked and how decltype() figures into it. I need to study that some. A learning opportunity. It's C++11 type stuff. My brain is still stuck some on the pre-C++11 language.
-Dale
In reply to Can you tell me why this… by [DELETED] 1831606
Specifically which of "each of my plugin's" do you mean? Do you have the new code yet?
I haven't had that issue unless you're running some older scripts.
-Dale
It happens in all code I have downloaded from this page, including gui-selection-list-test-v4.qml just posted. Complains twice about missing semicolons in that line. I'm using matt's most recent build. Perhaps you have a more advanced qml javascript than matt/I have?
In reply to It happens in all code I… by [DELETED] 1831606
This seems like new behavior on your end. Didn't this all work for you before?
I haven't changed any scripts posted here since their original posting. I wonder if it's an end-of-line issue.
PC's use , Linux uses to delimit lines. I believe Mac's used to use in the old Mac System 5 days but now Mac's are built on Unix so it should be as well.
Just checking a download of my latest script and it's in Linux, ie., 's terminate lines.
Checking my on-system scripts they are all Linux line endings. These load fine in my Windows version of MuseScore as I would expect.
-Dale
Actually, no. I had been witnessing this behavior all along (and foolishly patched around it instead of telling you about it). Oh, so you think it may be a crlf issue! Let me try that out ....
In reply to Actually, no. I had been… by [DELETED] 1831606
I've moved lines around, and it is not a crlf issue. I do not get the error on any other line. If I remove that Subroutine, it loads without problem.
I used a hex-editor to check my latest "gui-selection-list-test-v4.qml" and it's all just 's with no in there to confuse the mix. I wonder if it's a Javascript/QML engine problem.
I'm building against Qt 5.12.2. Matt will need to check his.
Let's experiment some...
First try to add a semicolon's where missing:
// For diagnostic use.
function dumpObjectEntries (obj, showUndefinedVals, title) {
console.log("VV -------- " + title + " ---------- VV");
for (let [key, value] of Object.entries(obj)) {
if (showUndefinedVals || (value != null)) {
console.log(key + "=" + value);
}
}
console.log("^^ -------- " + title + " ---------- ^^");
}
Failing that try moving the dumpObjectEntries() function to the end of the file to see if it's a sequence sensitivity.
Dale
Tried both; no change. I suspect that that ([x, y] of val) destructuring iterator is simply not supported in the interpreter I have.
>I suspect that that ([x, y] of val) destructuring iterator is simply not supported in the interpreter I have.
Except that it's old timey Javascript. If you Google "for (let [key, value] of Object.entries(obj))" you'll find many using the approach.
Regardless, it's safe to remove the function from the scripts as it's only used by me to dump objects when they complain about missing properties, or something. In the future I'll remove the function before publishing test scripts.
Still though, I'm interested what version of Qt Matt is using. Perhaps that will shed some light on the issue.
-Dale
I'm working on debugging this; it's not the destructure, but the "for" it's having trouble with. I wonder if there's a goofy character in it ...
It doesn't like "for of". This totally new function gets the same error on the "for":
function foo(bar) {
for (let o of bar) {
console.log(o)
}
}
In reply to It doesn't like "for of". … by [DELETED] 1831606
for-of is ECMAScript 6 new; it is clear my build doesn't have that. Can that same be done with forEach etc?
If you have a script with only:
var cursor = curScore.newCursor();
console.log(Object.entries(cursor));
Does the Object.entries() error?
-Dale
errs:
29:-1: TypeError: Property 'entries' of object function() { [code] } is not a function
29:-1: TypeError: Property 'entries' of object function() { [code] } is not a function
29:-1: TypeError: Property 'entries' of object function() { [code] } is not a function
29:-1: TypeError: Property 'entries' of object function() { [code] } is not a function
29:-1: TypeError: Property 'entries' of object function() { [code] } is not a function
29:-1: TypeError: Property 'entries' of object function() { [code] } is not a function
Qt 5.9.8 is what is used to produce the official builds, so that is what I have been using. (Truth be told, I used Qt 5.9.7 for the builds I provided, but whatever. I get the same error with Qt 5.9.8). The point is, your script needs to work with Qt 5.9, and it does not. If I build with Qt 5.12, the error goes away.
Could you see if attached script works in the older engine? It works on mine but that doesn't matter.
-Dale
Yes, it works in the older engine.
In reply to Yes, it works in the older… by mattmcclinch
Works for me, too.
In order for Matt to create a test version I created a branch on my MuseScore Github repo that combines the two features
And the macOs build can be found here.
I suppose one day I will figure out how to build for myself
Well, the instructions are here, and they are pretty easy to follow, I think. You will want to make sure that you install Qt WebEngine when you install Qt. (You can always go back and install it later, if you forget.)
Excellent! I'll just swap with that version to be on the safe side.
Thanks!
-Dale
Hold on. Didn't you just comment out the problematic code? Don't you want to rewrite it without using for-of?
I got up to installing Qt, v. 5.12.4, but my Qt directory has no subdirectory of that name. I have these subdirectories:
InstallationLog.txt MaintenanceTool.app MaintenanceTool.ini components.xml network.xml
Licenses MaintenanceTool.dat Qt Creator.app dist update.rcc
The installer offered me to run the "Qt Creator", which I assumed was to create an app, and I did not run it.
>Hold on. Didn't you just comment out the problematic code? Don't you want to rewrite it without using for-of?
Who is this addressed to?
-Dale
Don't you want to rewrite it without using for-of?
Changing for-of to for-in seems to work too.
That was addressed to you, Dale. And it looks like changing for-of to for-in doesn't work after all.
You both responded that the script
object-inspection-test.qml
I uploaded worked. So I replaced the non-working version with the acceptable version in thegui-selection-list-test-v4.qml
script so it'll work on all versions. That way it won't bother people in the future who stumble upon it.Did I misunderstand?
-Dale
I got up to installing Qt, v. 5.12.4, but my Qt directory has no subdirectory of that name.
I think maybe you didn't have the "macOS" checkbox under "Qt 5.12.4" checked when you installed Qt. You can use the MaintenanceTool.app to add the required component.
Did I misunderstand?
No. You did say it was safe to remove that function.
Yup, just figured that out. renamed the dir and starting again (Qt). Downloading now. And chose the webkit, too, as asked.
>You did say it was safe to remove that function.
Ah... Yes. I only used it for debugging the QML scripts. I just left it hanging around never considering it would trip someone up.
So..... I have no action items here? :)
-Dale
So..... I have no action items here?
No. But if you want to do something similar in the future, you may want to figure out how to write it using QML that works in Qt 5.9.
>Qt 5.9.8 is what is used to produce the official builds,
I didn't know that! I wonder why developer instructions point us at 5.12? It does make it harder to trust the results knowing that. I expect the Travis and Appveyor build against the earlier version to make sure all is peachy.
That wouldn't uncover behavior differences though as we've see here.
Oh well... the project actually builds cleanly and, stunningly, actually builds with the provided instructions! So I'm definitely not complaining. I'm very impressed at how well CMake works for the cross platform stuff. The code is clean as well since coding standards are enforced.
Before my recent retirement I used to work with a mega-build system called Yocto for Linux:
https://www.yoctoproject.org/
It's a builder of build systems. I know first hand it takes lots of effort to make it work so well!
A Tip of the Hat to the MuseScore developers!
-Dale
>But if you want to do something similar in the future, you may want to figure out how to write it using QML that works in Qt 5.9.
Hold on buckaroos... Now I'm back to confused... You guys said the new function in
object-inspection-test.qml
DID work with Qt 5.9.Is this true or not?
-Dale
Oh, I see what you did. You rewrote the function and commented out the old one.
Happily a-building, following instruction page exactly. What to I have to tell Git to say "drag in that branch(es)"? (I once knew, but it's been years).
In reply to >But if you want to do… by DLLarson
It worked with whatever Dale sent me. I wish I knew how to build MS with 5.9, but it wasn't offered to me by the Qt installer.
What to I have to tell Git to say "drag in that branch(es)"?
https://musescore.org/en/handbook/developers-handbook/finding-your-way-…
The app it put in applebuild seems to function correctly, and testifies that it was really built with Qt 5.12.4. It sounds better than your builds, I don't know why (yours stutter sometimes). I couldn't get the dmg to act properly, though, but this is close enough.... now to try what you just sent to me ..
Whew!.... I was beginning to think my brain was missing some connections!
Thanks!
-Dale
In reply to Whew!.... I was beginning to… by DLLarson
So suppose I have to do these
git checkout -b [branchname] master
git pull git://github.com/[someoneelse]/MuseScore.git [branchname]
to Dale's branch, and know [branchname] and [someoneelse] name; I don't have a git account, but that shouldn't matter....
This should get you to the correct code:
git clone -b qml-pr5224-pr5243-playevent-selection https://github.com/DLLarson/MuseScore.git
That way you start fresh and ready to go.
-Dale
No need to make another clone of the repository. I added DLLarson as a remote:
git remote add DLLarson git://github.com/DLLarson/MuseScore.git
To fetch his branch, I do this:
git fetch DLLarson qml-pr5224-pr5243-playevent-selection
To checkout his branch, I do this:
git checkout DLLarson/qml-pr5224-pr5243-playevent-selection
Then, if I want, I can create a local branch with the same (or different) name:
git checkout -b qml-pr5224-pr5243-playevent-selection
In reply to No need to make another… by mattmcclinch
deleted
deleted
I issued Matt's first three commands and gui-selection-list-test-v4 runs properly! Which do I re-do if Dale uploads new changes to it? How do you (Matt) test against Qt 5.9? Where do you get one?
So here is a tiny plugin extremely useful for people like myself who regularly mark up other people's scores. Assign a shortcut to it. THEN click on a note (or select/notes) press the shortcut and the notes turn red! Undoably! (although you have to move off the note to let it no longer be the selection so you can see the color change). (Anyone else besides Matt and Dale reading this, you need an unreleased MS version).
In reply to So here is a tiny plugin… by [DELETED] 1831606
I like it!
It's so simple to do when you can select actual score elements and script against them.
-Dale
In reply to I like it! It's so simple to… by DLLarson
I knew it would advance the human enterprise .... 'nother one tomorrow. I'm amazed how well the build process went, following the instructions....
> Which do I re-do if Dale uploads new changes to it?
When (or if) that becomes necessary you'll just "git pull" from the same branch and rebuild. I'll keep it up-to-date until the two PR's are in 'master'.
-Dale
>I'm amazed how well the build process went, following the instructions....
Yep. I'm glad they keep those doc's up-to-date. Next you can figure out how to build a DEBUG version and get access to the Debugger windows. ;)
If you want some PluginAPI docs on your machine that have this new stuff in them just install doxygen and graphviz.
http://www.doxygen.nl/download.html
https://graphviz.gitlab.io/download/
Make sure you can run them from the command line:
doxygen -v
dot -V
Then, at the command prompt, change to the root directory of the MuseScore workspace and run this:
doxygen Doxyfile.plugins
Finally open the file
.../MuseScore/doc/plugins/html/index.html
into your browser for the latest plugin docs direct from the source code!-Dale
In reply to >I'm amazed how well the… by DLLarson
Thanks, that can wait.
How do you (Matt) test against Qt 5.9? Where do you get one?
Run the MaintenanceTool app in your Qt directory. Choose "Add or remove components" and press "Continue". In the next screen, if only "Latest releases" is checked, earlier versions of Qt will be hidden, but if you also check "Archive" or "LTS" (or both) and then hit "Refresh" and expand the "Qt" tree item, you will be able to install Qt 5.9.8. Obviously, you will have to make sure that both "macOS" and "Qt WebEngine" are checked for the version that you are installing.
Once you have Qt 5.9.8 installed, you will have to make sure that Qt 5.9.8 (and not Qt 5.12.4) is in your PATH.
Thanks. At 6 gig of stuff per version I'm not as eager as earlier today... but the real question is whether the next MS will stay with 5.9 or go to 5.12? If not now, when will that happen? I guess a Qt version change is pretty substantial, so maybe I should back up to 9 ....
To build with 5.9.8, do I have to do anything other than change the PATH variable to it and re-make? Is some kind of "make clean" necessary before the latter?
You don't have to make clean. Just change the PATH variable and re-make. By the way, if you are not running debug builds within Xcode yet, I suggest you give that a try.
About
rednote.qml
. It wasn't coloring the accidental for me. It's a type (key bump?) here--see the 'enote':It looks really neat when the accidentals light up too.
-Dale
In reply to About rednote.qml. It wasn't… by DLLarson
Whoops. eThanks.
I changed the PATH variable, made sure it was really getting used, but it still built using 5.12.4. It cached it somewhere.