Skip to content

Commit

Permalink
Add support for diffing RepeatBrackets (e.g. first and second endings).
Browse files Browse the repository at this point in the history
  • Loading branch information
gregchapman-dev committed Aug 27, 2022
1 parent 0f0542e commit 5745cb2
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 7 deletions.
6 changes: 3 additions & 3 deletions musicdiff/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
import sys
import argparse

from musicdiff import diff
from musicdiff import DetailLevel

import music21 as m21
from converter21 import HumdrumConverter

from musicdiff import diff
from musicdiff import DetailLevel

# ------------------------------------------------------------------------------

'''
Expand Down
14 changes: 14 additions & 0 deletions musicdiff/m21utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,14 @@ def get_extras(measure: m21.stream.Measure, spannerBundle: m21.spanner.SpannerBu
if sp.isFirst(gn):
output.append(sp)

# Add any RepeatBracket spanners that start on this measure
rbList: List[m21.spanner.Spanner] = measure.getSpannerSites(m21.spanner.RepeatBracket)
for rb in rbList:
if rb not in spannerBundle:
continue
if rb.isFirst(measure):
output.append(rb)

return output

@staticmethod
Expand Down Expand Up @@ -708,6 +716,10 @@ def arpeggiomark_to_string(
return f'ARPS:{arp.type}:len={len(arp)}'
return ''

@staticmethod
def repeatbracket_to_string(rb: m21.spanner.RepeatBracket) -> str:
return f'END:{rb.number}:len={len(rb)}'

@staticmethod
def extra_to_string(extra: m21.base.Music21Object) -> str:
if isinstance(extra, (m21.key.Key, m21.key.KeySignature)):
Expand All @@ -726,6 +738,8 @@ def extra_to_string(extra: m21.base.Music21Object) -> str:
return M21Utils.tempo_to_string(extra)
if isinstance(extra, m21.bar.Barline):
return M21Utils.barline_to_string(extra)
if isinstance(extra, m21.spanner.RepeatBracket):
return M21Utils.repeatbracket_to_string(extra)
if (hasattr(m21.expressions, 'ArpeggioMark')
and hasattr(m21.expressions, 'ArpeggioMarkSpanner')):
if isinstance(extra, (m21.expressions.ArpeggioMark, m21.expressions.ArpeggioMarkSpanner)):
Expand Down
35 changes: 31 additions & 4 deletions musicdiff/visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,15 @@ def mark_diffs(
textExp.style.color = Visualization.INSERTED_COLOR
if isinstance(extra2, m21.spanner.Spanner):
insertionPoint = extra2.getFirst()
insertionPoint.activeSite.insert(insertionPoint.offset, textExp)
if isinstance(insertionPoint, m21.stream.Measure):
# insertionPoint is a measure, put the textExp at offset 0
# inside the measure
insertionPoint.insert(0, textExp)
else:
# insertionPoint is something else, put the textExp right next to it.
insertionPoint.activeSite.insert(insertionPoint.offset, textExp)
else:
# extra2 is not a spanner, put the textExp right next to it
extra2.activeSite.insert(extra2.offset, textExp)

elif op[0] == "extradel":
Expand All @@ -131,8 +138,15 @@ def mark_diffs(
textExp.style.color = Visualization.DELETED_COLOR
if isinstance(extra1, m21.spanner.Spanner):
insertionPoint = extra1.getFirst()
insertionPoint.activeSite.insert(insertionPoint.offset, textExp)
if isinstance(insertionPoint, m21.stream.Measure):
# insertionPoint is a measure, put the textExp at offset 0
# inside the measure
insertionPoint.insert(0, textExp)
else:
# insertionPoint is something else, put the textExp right next to it.
insertionPoint.activeSite.insert(insertionPoint.offset, textExp)
else:
# extra1 is not a spanner, put the textExp right next to it
extra1.activeSite.insert(extra1.offset, textExp)

elif op[0] == "extrasub":
Expand All @@ -155,9 +169,22 @@ def mark_diffs(
if isinstance(extra1, m21.spanner.Spanner):
insertionPoint1 = extra1.getFirst()
insertionPoint2 = extra2.getFirst()
insertionPoint1.activeSite.insert(insertionPoint1.offset, textExp1)
insertionPoint2.activeSite.insert(insertionPoint2.offset, textExp2)
if isinstance(insertionPoint1, m21.stream.Measure):
# insertionPoint1 is a measure, put the textExp at offset 0
# inside the measure
insertionPoint1.insert(0, textExp)
else:
# insertionPoint1 is something else, put the textExp right next to it.
insertionPoint1.activeSite.insert(insertionPoint1.offset, textExp)
if isinstance(insertionPoint2, m21.stream.Measure):
# insertionPoint2 is a measure, put the textExp at offset 0
# inside the measure
insertionPoint2.insert(0, textExp)
else:
# insertionPoint2 is something else, put the textExp right next to it.
insertionPoint2.activeSite.insert(insertionPoint2.offset, textExp)
else:
# extra is not a spanner, put the textExp right next to it
extra1.activeSite.insert(extra1.offset, textExp1)
extra2.activeSite.insert(extra2.offset, textExp2)

Expand Down

0 comments on commit 5745cb2

Please sign in to comment.