Any way to retrieve staff characteristics?

• Sep 19, 2020 - 22:52

After exhausting everything I could think of - does anyone know if the below is possible; and if so, how?

For a plugin I am working on, I need to be able to determine which staves are standard notation, which are tabs; and what their instruments (or part names) are - or some way to match up which staves belong to which parts. And this would generally be in multi-part arrangements.

There appear to be a number of properties in the 'Element' object which should enable me to do this (when combined with iterating over all the parts and staves in a loop). For example, element.staffLines, element.staffGenClef, etc. However, everthing I've tried to date returns only "undefined" for these properties. Am I missing something with respect to retrieving those properties? Or have some of these not yet been implemented perhaps?

Any help on this would be appreciated.

My console output in attempting to read the Element attributes from Chord, Measure and System elements:

Debug: Running....
Debug: Root e type: Chord | at tick: 480
Debug: --| staffLines: undefined
Debug: --| hasPitchedStaff: undefined
Debug: --| instrumentId: undefined
Debug: --| timesigNominal: 0 / 1
Debug: --| actualNotes: undefined
Debug: --| measureNumberMode: undefined
Debug: --| role: undefined
Debug: --| track: 0
Debug: --| fretStrings: undefined
Debug: --| staffGenClef: undefined
Debug: =====
Debug: Root e's parent: Segment | at tick: 480
Debug: ----| staffLines: undefined
Debug: ----| hasPitchedStaff: undefined
Debug: ----| instrumentId: undefined
Debug: ----| actualNotes: undefined
Debug: ----| measureNumberMode: undefined
Debug: ----| role: undefined
Debug: ----| track: -1
Debug: ----| fretStrings: undefined
Debug: ----| staffGenClef: undefined
Debug: =====
Debug: Root e's parent.parent: Measure | at tick: 480
Debug: ------| staffLines: undefined
Debug: ------| hasPitchedStaff: undefined
Debug: ------| instrumentId: undefined
Debug: ------| timesigNominal: 4 / 4
Debug: ------| actualNotes: undefined
Debug: ------| measureNumberMode: 0
Debug: ------| role: undefined
Debug: ------| track: -1
Debug: ------| fretStrings: undefined
Debug: ------| staffGenClef: undefined
Debug: =====
Debug: Root e's parent.parent.parent: System | at tick: 480
Debug: --------| staffLines: undefined
Debug: --------| hasPitchedStaff: undefined
Debug: --------| instrumentId: undefined
Debug: --------| actualNotes: undefined
Debug: --------| measureNumberMode: undefined
Debug: --------| role: undefined
Debug: --------| track: -1
Debug: --------| fretStrings: undefined
Debug: --------| staffGenClef: undefined

[For context: I am trying to create a plugin that will generate non-standard fretted tabulature using the notation on one of the standard staffs. I need a way for both the user, and my code, to unambigiously specify the "input" and "output" staves for the operation - again, in a multi-part score with mixed-and-matched instruments.]

Attachment Size
jeffForStudy_ElementLister.qml 4.69 KB

Comments

In reply to by jeetee

Thanks for responding jeetee. I did try to work with 'parts,' but I can't figure out any way to get just the staves that are members of a specific part. There is a bool property that will tell me if there is a standard and/or TAB staff, but I can't find a way to get their staff index values. And even if I can get them, I can't see how I'd determine which is standard and which one is the TAB given that I can't seem to get any object I can reference to return those element. staff... properties.

Maybe another approach to this question is: Could anyone show me some plugin code that references an object which does return a value for those 'staff' properties. E.g., returns a value for, say, element.staffGenClef.

(To me, as an old data-modeller, I keep expecting the equivalent of a foreign-key from a 'staff' object back to the 'part' object it belongs to. But the exposed class hierarchy in the plugin API doesn't seem to be modelled that way. Seems like it's been really flattened via the Element class. Which is fine...if only I could work out how to reference the right objects/classes to return those pesky staff properties that are listed as being available in the Element class.)

Am still trying to figure this out. I am not a C++ or Qt code expert; but have been trying to study the musescore source to see if I can work out a solution. I do see that in element.cpp there is an element type of "STAFF" [in Element* Element::create(ElementType type, Score* score) -- case ElementType::STAFF:].

But I still cannot figure out how to reference any such element in QML. If anyone knows, please help.

In reply to by jeetee

OK. Just to be clear - you are saying that, at present, there is no way to retrieve the value of the staffGenClef property of the element object from with QML. Meaning that it has been, in effect, 'hard coded' to simply return "undefined" back to QML no matter the context. Do I have this right?

I'll go ahead and explore more down your suggested path.

In reply to by rocchio

Quite the contrary in fact.

I'm saying that you can request the staffGenClef from any element using QML. But that for element types that don't have that property internally, undefined will be returned.

Now a look at the plugin API learns that this property is linked to the c++ property defined as Ms::Pid::STAFF_GEN_CLEF which in turn is only defined for a StaffTypeChange element.

So if you want that value in QML to be anything else than undefined, then make sure you're calling it on an element of the type Element.STAFFTYPE_CHANGE

In reply to by jeetee

By looking into the source to explain that property to you, I came to realize that since 3.5.0, the Staff element now should be available to the Plugin API.

See this commit for when it was added. This change view also shows you should be able to call staff() on an element to get its staff object.

In reply to by jeetee

After several hours working on this, it's still quite frustrating. Some partial success tho, which will probably be close enough for my needs. Tho it is still troublesome that I cannot work out what's going on.

Your response did enable me to obtain the Staff object using var staff = element.staff; In addition I am able to get the staffs for a part by using staff.part.partName;. So this will allow me to at least match up staffs to parts. However, the element.staff object still only returns 'undefined' for those 'staff...' element properties showing in the QML documentation. Looking at the pull request you pointed me to I was able to prove that the element.staff object in QML does return the properties defined for the class Staff object that is defined in elements.cpp. Tho, sadly, those properties aren't the ones I need.

So I will try to let this go now and move on with my plugin. The silver lining is that this has begun to pull me into the journey of understanding Qt - which I've no prior knowledge of. I spent time delving into the Q_Property construct and feel I do at least understand what's going on there. As to the rest of it; and exposing the backend code out to QML...I don't yet have a clue to how that works and am thus unable, yet, to work out these puzzles on my own.

Thanks for your help jeetee.

In reply to by jeetee

Gotcha. My need is to be able to identify which staff, if any, is the TAB staff. Am trying to make a plugin which generates a non-standard fretted TAB for the diatonic Mountain Dulcimer given a standard notation staff for the same part.

So at this point I will assume that the TAB staff in the part is always the 2nd staff in that part - when 'counting' by staffindex. So I figure I now know: how to present the user with a list of all parts that have 2 staffs, and have them select which of those parts they want to populate the TAB for. I will need to provide some text to inform them that the 3-string TAB staff must already have been added to the part, and that they need to be sure they don't select a non-TAB 2-staff part (e.g., piano).

In reply to by rocchio

I think that identification (and/or setting number of staff lines) is currently indeed not quite possible using the plugin framework.

Opting for telling your users the expected begin situation (namely, creating that staff, perhaps with instruction on how to do so) seems the sensible way forward.
That and then opening an issue in the issue tracker to include that functionality into the plugin framework in a future version.

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