wishing more information about plugin syntax

• Jun 15, 2018 - 09:05

Actually the only source of information about the plugin syntax is the built-in help that lists the score elements with their properties and methods.
Unfortunately the description is often very basic (or just: "inherits ....")
Ok, in many cases the user can guess from the name...

My concrete problem concerns the "duration" element that allows to set the the duration of a chord (hopefully it is meant for this). It uses a unit "fraction", but I cannot find any documentation about this. I tried to output the duration of a chord using the console, but here I only get "Ms::FractionWrapper(0xdb5c268)"
I also tried "durationType", but here I get "undefined".


Comments

In reply to by Jojo-Schmitz

Yes, V2.2
I understood how to add a chord (I'm just working on a little improvement of the plugin "chordsToNotes" which I find very useful. Here I like to change the duration of the chords in order to fill the time until the next chord appears.

Additional question:
the standard way to go through a score is the usage of "cursor" with cursor.next().
By this way the selected staff can be handled chord by chord.
In some cases, the harmony changes during a longer note (e.g. full note, but 2 harmonies, first on the chord, 2nd on tick 3).
Is there a different mechanism to go through a score that will allow to access harmonies that are not bound to a chord?

In reply to by Bacchushlg

All harmonies are bound to a 'chord'.

A chord object is the object that holds the duration and one or more notes(/noteheads). From what you're telling me, you're likely trying to walk over a given voice. In order to do so, make sure to set the correct track of the Cursor

track = 4*staffIdx + voice

In reply to by Bacchushlg

Apologies… I had misread your question.

First things first: opening that score in 2.2.1 shows it has several corruptions on the 2nd staff. Select it and exchanges voices 1-2 twice, then remove all voice 2 rests. Now save the no longer corrupted score.

The Harmony object is an annotation on a Segment, not necessarily on a Chord/ChordRest. It's been a while since I've navigated using Cursor, so if it is set to only navigate ChordRests, then yes you won't find those Harmony objects.
In this scenario I'd advise you to make use of segment.next for traversal instead.

Have a look at the following plugin I've just now written to demonstrate this (meant as an update for walk.qml in the future):

//=============================================================================
//  MuseScore
//  Music Composition & Notation
//
//  Copyright (C) 2012 Werner Schweer
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License version 2
//  as published by the Free Software Foundation and appearing in
//  the file LICENCE.GPL
//=============================================================================
import QtQuick 2.2
import MuseScore 1.0
 
MuseScore {
    menuPath: "Plugins.Examples.SegmentWalk"
    version:  "0.0.1"
    description: qsTr("Walks over all segments of a score")
    pluginType: "dialog"
    //requiresScore: true //not supported before 2.1.0, manual checking onRun
 
    onRun: {
        if (!curScore) {
            console.log(qsTranslate("QMessageBox", "No score open.\nThis plugin requires an open score to run.\n"));
            Qt.quit();
        }
 
        //fixed the running to just voice 1 of staff 1 now, as the console.log only keeps last 1000 messages anyway
        for (var track = 0; track < /*curScore.ntracks*/1; ++track) {
            console.log('===== Track ' + track + ' =====');
            var segment = curScore.firstSegment();
            while (segment) {
                console.log(segment.tick + ": segment: " + segment + "  type " + segmentTypeToString(segment.segmentType) + ' (' + segment.segmentType + ')');
                var element = segment.elementAt(track);
                if (element) {
                    var type     = element.type;
                    var duration = element.duration;
                    var durationString = "";
                    if (duration) {
                        durationString = ' ' + duration.numerator + '/' + duration.denominator + ' ' + duration.ticks;
                    }
                    console.log(elementTypeToString(type) + ' (' + type + ')' + durationString);
                }
 
                var anns = segment.annotations;
                if (anns && anns.length) {
                    var len = anns.length;
                    for (var annc = 0; (annc < len); annc++) {
                        console.log('Annc = ' + annc);
                        console.log(anns[annc]);
                        if (anns[annc] && anns[annc].type) {
                            console.log("\tAnnotation: " + elementTypeToString(anns[annc].type));
                        }
                    }
                }
                segment = segment.next;
            }
        }
        Qt.quit();
    }
 
    function segmentTypeToString(segType) {
        var segmentTypes = Object.freeze({
            0x0000: 'Invalid',
            0x0001: 'Clef',
            0x0002: 'KeySig',
            0x0004: 'Ambitus',
            0x0008: 'TimeSig',
            0x0010: 'StartRepeatBarLine',
            0x0020: 'BarLine',
            0x0040: 'Breath',
            0x0080: 'ChordRest',
            0x0100: 'EndBarLine',
            0x0200: 'KeySigAnnounce',
            0x0400: 'TimeSigAnnounce'
        });
        return segmentTypes[segType];
    }
 
    function elementTypeToString(elType) {
        var elementTypes = Object.freeze([
            'Invalid',
            'Symbol',
            'Text',
            'Instrument Name',
            'Slur Segment',
            'Staff Lines',
            'Bar Line',
            'Stem Slash',
            'Line',
 
            'Arpeggio',
            'Accidental',
            'Stem',
            'Note',
            'Clef',
            'Keysig',
            'Ambitus',
            'Timesig',
            'Rest',
            'Breath',
 
            'Repeat Measure',
            'Image',
            'Tie',
            'Articulation',
            'Chordline',
            'Dynamic',
            'Beam',
            'Hook',
            'Lyrics',
            'Figured Bass',
 
            'Marker',
            'Jump',
            'Fingering',
            'Tuplet',
            'Tempo Text',
            'Staff Text',
            'Rehearsal Mark',
            'Instrument Change',
            'Harmony',
            'Fret Diagram',
            'Bend',
            'Tremolobar',
            'Volta',
            'Hairpin segment',
            'Ottava segment',
            'Trill segment',
            'Textline segment',
            'Volta segment',
            'Pedal segment',
            'Lyricsline segment',
            'Glissando segment',
            'Layout Break',
            'Spacer',
            'Staff State',
            'Ledger Line',
            'Notehead',
            'Notedot',
            'Tremolo',
            'Measure',
            'Selection',
            'Lasso',
            'Shadow Note',
            'Tab Duration Symbol',
            'FSymbol',
            'Page',
            'Hairpin',
            'Ottava',
            'Pedal',
            'Trill',
            'Textline',
            'Noteline',
            'Lyricsline',
            'Glissando',
            'Bracket',
 
            'Segment',
            'System',
            'Compound',
            'Chord',
            'Slur',
            'Element',
            'Element list',
            'Staff list',
            'Measure list',
            'Hbox',
            'Vbox',
            'Tbox',
            'Fbox',
            'Icon',
            'Ossia',
            'Bagpipe Embellishment',
 
            'MAXTYPE'
        ]);
        return elementTypes[elType];
    }
}

This way you will encounter all expected Harmony elements in your score. (verified in measure 1)

In reply to by jeetee

Thanx a lot for this extensive help example!
Unfortunately I now come to a new problem: how to access the position in the score where to add the calculated chord.
In the former way, the cursor object provided the "add" method to add the chord. But the "segment" object does not provide such a method. What I would need is a function the sets the cursor to the position of the segment. But how?

In reply to by Bacchushlg

Hmm.. I don't think this readily exists.

My first guess approach would be: use the Segment approach to find the tick value of the Harmony.
Then use the cursor approach (from the start and using next) to browse through the score on the track you wish to edit:
1. Call next while cursor.tick < harmonyTick
2. if cursor.tick === harmonyTick --> found location
3. if cursor.tick > harmonyTick
3a. cursor.prev
3b. cursor.setDuration([required duration to reach tick next])
3c. cursor.next

I'm unsure wether setDuration and then calling next without first writing something of that duration (addNote for example) will work. It may be that the duration is only applied when an element with that duration is then added to the score.

In reply to by jeetee

I tried to realize your proposal, but with no success.
My main problem is the very basic documentation of the available objects, their methods and properties.
I work with a lot of debugging outputs to find out, what information can be found in the available objects - but finally I give up.

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