Iterating through measure by measure?
Hi, I'm hoping someone knows a good way to iterate through the score measure by measure. I found loops in other plugins that iterate through the score note by note, but I would like my plugin to use a variable that gets reset every measure. Does anyone know anything about how one might go about this?
Thanks!!
Comments
The closest MuseScore comes to that is the playback loop. From the Play Panel (F11) you can select the first note with the [ and last note with the ] and it will loop in that range only. To cancel the loop press the round arrow.
Method 1: Get a
Cursor
on the score andrewind(0)
it to the start of the score. Regardless of how you want to walk the score, you can always access the currentmeasure
property.Method 2: Get the first measure of the score (
Score.firstMeasure
) . Then keep callingnextMeasure()
on it.In reply to Method 1: Get a Cursor on the by jeetee
Great, thank you! One more question, sorry, how exactly would I access the measure property, and what does it return? It would be awesome if it returned the int measure number (or if there's something else that does), since then I could just test for when it changed. Calling Element.MEASURE seems to return 57 for all my measures, and I found a no() function in MeasureBase that returns the measure number, but I'm not sure how to call it.
Thank you so much!
In reply to Great, thank you! One more by katie07
Element.MEASURE will always return the same value. It is the numerical representation of the Type of Element. (so all measures are of the type Element.MEASURE)
To find out what you can call and or which properties exist: Open up the Plugin Creator and in there open up the Manual under its Help menu. You'll find that the no() function doesn't exist there, meaning it is not available to a plugin.
For your direct question, I've created this small sample plugin that counts measures whilst walking over the elements in voice 1 of the top staff of a score.
In reply to Element.MEASURE will always by jeetee
Wow, thank you SO MUCH!! This makes sense and I got it working! Thanks again!!
In reply to Element.MEASURE will always by jeetee
NOTE: This goes totally wrong when there are more segments in a measure because the measure pointer will be different for every segment causing overcount!
In reply to NOTE: This goes totally… by rgos
Note that this changed somewhere between 2017 and now (I think in 3.5) as the Measure object is now wrapped by the plugin API when requesting it, indeed resulting in a different new object each time.
So if you need measure-based score traversing use the other (preferred) method mentioned here:
Start from score.firstMeasure and then use nextMeasure calls on it.
This technique is also used in the recently improved walk.qml example plugin: https://github.com/musescore/MuseScore/pull/9601
In reply to Note that this changed… by jeetee
Ah, I see, I was reacting to old code. It was causing me massive headaches when writing a measure traversing plugin. OTOH the buildMeasureMap function did the trick. Is that the standard way to traverse measures and find out measure number and beats?
See: https://github.com/mirabilos/mscore-plugins/blob/master/count-note-beat…
In reply to Ah, I see, I was reacting to… by rgos
There is no standard way (or there would be an API function for it); but if you for some reason need measure number logic, then that map function is as good as any; just be aware that it doesn't count irregular measures.
In reply to NOTE: This goes totally… by rgos
For comparing measure pointers the
is()
method can be used:This method compares the underlying internal object pointers rather than wrappers that may indeed be different.
Wrappers are here since the version 3.0, the plugin API for MuseScore 3 was initially re-implemented that way.
In reply to For comparing measure… by dmitrio95
Thanks a lot, @dmitrio95, that worked perfectly!