How to change the bar line type of a measure

• Sep 1, 2021 - 23:21

I'd like to add a "End bar" in my score whenever I add a System break. However my code crashes MuseScore.

// if there is another part ("page") after this one, add a  linebreak
var lbreak = newElement(Element.LAYOUT_BREAK);
lbreak.layoutBreakType = 2;  // section break
cursor.rewindToTick(cur_time); // rewing to the last note
cursor.add(lbreak);
var bar = newElement(Element.BAR_LINE);
bar.barLineType = 32;
//cursor.rewindToTick(cur_time); // rewing to the last note
cursor.add(bar); // -- CRASH OF MUSESCORE --

Should I instead of adding the bar, search for the current bar of the current measure and try to change its type ?


Comments

In reply to by jeetee

I guess there is some kind of bug here.

In a new measure added by the API no BAR_LINE element can be found at its end by the API.

The code is basically this one:

var measure = cursor.measure;
var segment = measure.lastSegment;
var element = segment.elementAt(cursor.track);

if (element.type == Element.BAR_LINE) {
    score.startCmd();
    console.log("--BAR LINE--");
    element.barlineType = 32;
    score.endCmd();
} else {
    console.log("--NOT BAR LINE--");

}

It is working in an existing score.

For score created by the API, I've made 4 scenarios, all based on the creation of a score with one measure.

Scenario 1: Don't add any other measure, search for a bar line in the default first measure
==> OK

Scenario 2: Add a new measure at the end of the score, search for a bar line in the default first measure
==> OK

Scenario 3: Add a new measure at the end of the score, search for a bar line in the new measure
==> KO. Last element found is a Rest

Scenario 4: Add atwo new measures at the end of the score, search for a bar line in the middle measure (so in an API created one)
==> KO. Last element found is a Rest

import QtQuick 2.0
import MuseScore 3.0

MuseScore {
    version: "3.0"
    description: "This demo plugin creates a new score."
    menuPath: "Plugins.createscore"
    requiresScore: false

    onRun: {
        console.log("hello createscore");
        var score = newScore("Test-Score", "piano", 1);

        var cursor = score.newCursor();
        cursor.track = 0;

        // Scenario 1 + 2 + 3 + 4
        cursor.rewind(0);

        // Scenario 2 + 3 + 4
        score.appendMeasures(1);
        cursor.rewind(0);
        // Scenrio 3 + 4 
        cursor.nextMeasure();

        // Scenario 4
        score.appendMeasures(1);

        // All scenario  
        cursor.setDuration(1, 4);
        cursor.addNote(60);

        var measure = cursor.measure;
        var segment = measure.lastSegment;
        var element = segment.elementAt(cursor.track);

        if (element.type == Element.BAR_LINE) {
            score.startCmd();
            console.log("--BAR LINE--");
            element.barlineType = 32;
            score.endCmd();
        } else {
            console.log("--NOT BAR LINE-- ("+element.userName()+")");

        }

        Qt.quit();
    }
}

PS: other ways to get to the last segment have not worked either, such as looping from cursor.segmentwith next() and nextInMeasure(), ...

In reply to by parkingb

It's not as much a bug as wrong/incomplete usage here.

All you need to do is wrap the score.appendMeasures() call with score.startCmd() and score.endCmd(). If you don't, then the Plugin API is not obliged to fully process that command before continuing onwards. So whenever you need to rely on the result of a score-changing action to start a different kind of action (or ask information about the result) make sure to wrap said action(s) between a start/endCmd call.

In reply to by jeetee

As further example evidence.

The "end" element being retrieved before the call to endCmd is not yet the actual end of the score at that moment in time (check the tick value).

import QtQuick 2.0
import MuseScore 3.0
 
MuseScore {
      menuPath: "Plugins.addMeasuresBarline"
      description: "Get Final Barline after adding Measures"
      version: "1.0"
      onRun: {     
      var score = newScore("Test-Score", "piano", 1);
      score.startCmd();
 
      score.appendMeasures(2);
      var seg = score.lastSegment;
      console.log("Before endCmd", seg.segmentType, "isBarline: " + !!(Segment.BarLineType & seg.segmentType), seg.tick);
 
      score.endCmd();
      seg = score.lastSegment;
      console.log("After endCmd", seg.segmentType, "isBarline: " + !!(Segment.BarLineType & seg.segmentType), seg.tick);
   }
}

Which produces the following output:

Debug: STATE CHANGED HOVERED
Debug: Before endCmd ChordRest isBarline: false 3840
Debug: STATE CHANGED 
Debug: After endCmd EndBarLine isBarline: true 5760

In reply to by jeetee

Thanks. It works.

But it is very close from the bug ;-)

All my score manipulations were enclosed in one single big startCmd/endCmd.
This BAR_LINE is the only action that requires an intermediate endCmd/startCmd.
Adding measures, time signatures, staff text, notes, chords, chord symbols, layout break, ... All of these are working correctly with one single startCmd/endCmd.
It might be interesting to investigate why the BAR_LINE doesn't...

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