ChordRest with _track == -1

• Nov 24, 2018 - 19:28

I have just merged my code with the latest master after a few months away. I get a ChordRest* via a loop that looks something like this (I sort the elements prior to the actual loop):
foreach (const Element* e, page->elements()) {}
The first Element that has a ChordRest in the loop is a NoteDot. Here is the code for getting the ChordRest from the NoteDot:
ChordRest* cr = static_cast(e->parent()->parent());
That seems to work fine. But then the problem surfaces when I use cr->actualTicks():
int DurationElement::actualTicks() const {
return actualFraction().ticks()
}
Fraction DurationElement::actualFraction() const {
return globalDuration() / staff()->timeStretch(tick()); // the line where it fails
}

The problem is that staff() is null because the CR's _track member variable is -1. What am I doing wrong? What changed in the past few months that would affect this?

I have attached the score that I am using here, in case that helps. It was recently refreshed using a "compatibility build".

Attachment Size
BBN_Score.mscz 29.71 KB

Comments

Are you sure you are actually getting a ChordRest with your use of e->parent()->parent()? My guess is something about the parenting of the NoteDot is what changed, and you actually have a segment now. I have a recollection of something happening to unify the treatment of dots on notes versus rests that would be consistent with this.

In reply to by sideways

In fact, the only place in this score that contains note dots in that score is a rest near "A1.2" rehearsal mark. You can see it by unzipping .mscz file and searching for "dot" by text in the .mscx file contained there. As follows from libmscore/notedot.h, if a dot belongs to a rest then this rest is its parent. So by getting parent of the parent you probably get not a ChordRest which is the reason of that failure. You can also check whether the retrieved element is actually a ChordRest by calling e->isChordRest() for this element. Hope this helps in your investigation of the problem!

In reply to by dmitrio95

I appreciate the suggestion, but I checked the object type in the debugger and it was ChordRest. Also, it doesn't matter if it's a note or a rest that is the parent of the NoteDot element, either way the ChordRest is the parent of that parent note or rest, AFAIK.
My current approach is to rebuild the score from scratch with a newly created file and copy/paste notes from the old score. The file went through a conversion build process that makes me suspicious, and I want to eliminate all the outside variables before I dig into debugging it in detail. It's not a fun debugging session with that many elements in play and an access violation coming so early in the sorted list.
I'll post a resolution once I find it. But don't let that stop you from offering further suggestions, as it's taking me time to get used to my whole new VS2017 configuration and get back in the swing with MuseScore after some time away. I hope to be debugging this and another issue later today.

In reply to by sideways

OK y'all are right, note dots attached to rests only go to the parent rest to get the ChordRest, and the grand-parent is a Segment.
But this is old code of mine that worked previously for this same score! I do not believe that this has changed, I believe that this has always been the case. Maybe you can correct me on that.
Anyway, the real mystery is: why did this code work previously? I'm sure I had some dotted rests in scores I passed through here, certainly this same score, pre-conversion-build.
Very, very strange, but now resolved. I've had a bug for well over a year that never showed itself.

In reply to by sideways

I can actually be 100% certain that this is not due to any recent change because just a few lines above the note dot code is my old code to deal with rests:

switch (eType) {
case EType::REST :
cr = static_cast(e);
break;

So rests have always been ChordRests, while notes have a Chord/ChordRest as their parent.
EType is my shorthand for Ms::ElementType:
using EType = Ms::ElementType;

To close the topic. Here is my new code:

case EType::NOTEDOT :
if (e->parent()->isRest()) {
cr = static_cast(e->parent());
break;
} // else falls through
case EType::ACCIDENTAL :
cr = static_cast(e->parent()->parent());
break;

I don't seem to be able to indent within the code tags, sorry about that.

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