-
Notifications
You must be signed in to change notification settings - Fork 439
Interpret empty <forward> tags as rests on Finale documents only (derived from PR #1636, thanks @TimFelixBeyer!) #1777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
3e9bfd0
1a64621
8b02acd
acbf273
c6a6870
4d01fba
c6b7607
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -769,6 +769,7 @@ def __init__(self): | |||||
| self.parts = [] | ||||||
|
|
||||||
| self.musicXmlVersion = defaults.musicxmlVersion | ||||||
| self.wasWrittenByFinale = False | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be better to localize this in xmlForward() along the lines I suggested here, checking I see from your commit message you tried this and found that Checking in xmlForward should be fast, since we can depend on the metadata object always existing at the the top of the stream (no long O(n) searches finding no metadatas anywhere): music21/music21/musicxml/xmlToM21.py Lines 822 to 823 in 52fc784
You'd have to change that coreInsert (as modeled in that diff I linked). @mscuthbert do you agree that would achieve better "locality of behavior" than adding more parser attributes for edge cases?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assuming I'm understanding this correctly, I'm not sure much simplicity is gained by replacing self.wasWrittenByFinale with self.music21WasActuallyInTheDocsSoftwareMetadata (or some other better name). Maybe a rename with the existing semantics? self.applyFinaleWorkarounds, or something like that, that feels more like it is a legit parser-level variable.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm also going to argue that performing the "loop over the software metadata" for every
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, do it once. I believe that the order of software tags written out by
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
|
|
||||||
| def scoreFromFile(self, filename): | ||||||
| ''' | ||||||
|
|
@@ -1326,9 +1327,17 @@ def processEncoding(self, encoding: ET.Element, md: metadata.Metadata) -> None: | |||||
| # TODO: encoder (text + type = role) multiple | ||||||
| # TODO: encoding date multiple | ||||||
| # TODO: encoding-description (string) multiple | ||||||
| finaleFound: bool = False | ||||||
| nonFinaleFound: bool = False | ||||||
| for software in encoding.findall('software'): | ||||||
| if softwareText := strippedText(software): | ||||||
| if 'Finale' in softwareText: | ||||||
| finaleFound = True | ||||||
| else: | ||||||
| nonFinaleFound = True | ||||||
| md.add('software', softwareText) | ||||||
| if finaleFound and not nonFinaleFound: | ||||||
| self.wasWrittenByFinale = True | ||||||
|
|
||||||
| for supports in encoding.findall('supports'): | ||||||
| # todo: element: required | ||||||
|
|
@@ -2575,16 +2584,7 @@ def parse(self): | |||||
|
|
||||||
| if self.useVoices is True: | ||||||
| for v in self.stream.iter().voices: | ||||||
| if v: # do not bother with empty voices | ||||||
| # the musicDataMethods use insertCore, thus the voices need to run | ||||||
| # coreElementsChanged | ||||||
| v.coreElementsChanged() | ||||||
| # Fill mid-measure gaps, and find end of measure gaps by ref to measure stream | ||||||
| # https://github.com/cuthbertlab/music21/issues/444 | ||||||
| v.makeRests(refStreamOrTimeRange=self.stream, | ||||||
|
gregchapman-dev marked this conversation as resolved.
|
||||||
| fillGaps=True, | ||||||
| inPlace=True, | ||||||
| hideRests=True) | ||||||
| v.coreElementsChanged() | ||||||
|
gregchapman-dev marked this conversation as resolved.
Outdated
|
||||||
| self.stream.coreElementsChanged() | ||||||
|
|
||||||
| if (self.restAndNoteCount['rest'] == 1 | ||||||
|
|
@@ -2630,18 +2630,19 @@ def xmlForward(self, mxObj: ET.Element): | |||||
| if durationText := strippedText(mxDuration): | ||||||
| change = opFrac(float(durationText) / self.divisions) | ||||||
|
|
||||||
| # Create hidden rest (in other words, a spacer) | ||||||
| # old Finale documents close incomplete final measures with <forward> | ||||||
| # this will be removed afterward by removeEndForwardRest() | ||||||
| r = note.Rest(quarterLength=change) | ||||||
| r.style.hideObjectOnPrint = True | ||||||
| self.addToStaffReference(mxObj, r) | ||||||
| self.insertInMeasureOrVoice(mxObj, r) | ||||||
| if self.parent.parent.wasWrittenByFinale: | ||||||
|
gregchapman-dev marked this conversation as resolved.
Outdated
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One of the few times I wish Python were Javascript -- need to check for grandparent existence... Vote YES on PEP 505 |
||||||
| # Create hidden rest (in other words, a spacer) | ||||||
| # old Finale documents close incomplete final measures with <forward> | ||||||
| # this will be removed afterward by removeEndForwardRest() | ||||||
| r = note.Rest(quarterLength=change) | ||||||
| r.style.hideObjectOnPrint = True | ||||||
| self.addToStaffReference(mxObj, r) | ||||||
| self.insertInMeasureOrVoice(mxObj, r) | ||||||
| # xmlToNote() sets None | ||||||
| self.endedWithForwardTag = r | ||||||
|
|
||||||
| # Allow overfilled measures for now -- TODO(someday): warn? | ||||||
| self.offsetMeasureNote += change | ||||||
| # xmlToNote() sets None | ||||||
| self.endedWithForwardTag = r | ||||||
|
|
||||||
| def xmlPrint(self, mxPrint: ET.Element): | ||||||
| ''' | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.