ChordRest with _track == -1
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 Are you sure you are… by Marc Sabatella
Yes, it is a ChordRest. I checked that much. But your memory may still be on to something.
In reply to Yes, it is a ChordRest. I… 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 aChordRest
which is the reason of that failure. You can also check whether the retrieved element is actually aChordRest
by callinge->isChordRest()
for this element. Hope this helps in your investigation of the problem!In reply to In fact, the only place in… 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 I appreciate the suggestion,… by sideways
wait, maybe you're right and Rests are the ChordRest, not the parent. I must get this going in my debugger soon.
In reply to wait, maybe you're right and… 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 OK y'all are right, note… 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;
In reply to I can actually be 100%… by sideways
As I said, the handling of the dots changed not so long ago, as dots attached to rests were handled differently from those attached to notes and this difference was causing problems.
In reply to As I said, the handling of… by Marc Sabatella
So two strikes in one topic. At least it's less than 3, and my new code is still at the very bottom and still relevant.
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.