Iterating through measure by measure?

• Mar 25, 2017 - 18:06

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?



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 and rewind(0) it to the start of the score. Regardless of how you want to walk the score, you can always access the current measure property.

Method 2: Get the first measure of the score (Score.firstMeasure) . Then keep calling nextMeasure() on it.

In reply to 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 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.

import QtQuick 2.0
import MuseScore 1.0

MuseScore {
      menuPath: "Plugins.pluginName"
      onRun: {
            if (!curScore) {
                  console.log(qsTranslate("QMessageBox", "No score open.\nThis plugin requires an open score to run.\n"));
            var internalMeasureNumber = -1; //we will use this to track the current measure number
            var currentMeasure = null; //we use this to keep a reference to the actual measure, so we can know when it changes

            //get a cursor to be able to run over the score
            var cursor = curScore.newCursor();
            cursor.voice = 0;
            cursor.staffIdx = 0;

            while (cursor.segment) {
                  if (cursor.measure != currentMeasure) {
                        //we moved into a new measure
                        currentMeasure = cursor.measure;
            console.log('Found ' + (internalMeasureNumber + 1) + ' measures.');

In reply to 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:

In reply to by rgos

For comparing measure pointers the is() method can be used:

if (! {
    // ...

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.

Do you still have an unanswered question? Please log in first to post your question.