diff --git a/ly/musicxml/ly2xml_mediator.py b/ly/musicxml/ly2xml_mediator.py index e8c7d72..fa65549 100644 --- a/ly/musicxml/ly2xml_mediator.py +++ b/ly/musicxml/ly2xml_mediator.py @@ -117,6 +117,14 @@ def new_lyric_section(self, name, voice_id): self.insert_into = lyrics self.lyric_sections[name] = lyrics + def new_addlyrics_section(self): + r"""Collect \addlyrics into a lyrics section that is merged + into the preceding music when the lyrics end.""" + lyrics = xml_objs.LyricsSection('addlyrics', None) + lyrics.merge_into = self.insert_into + self.insert_into = lyrics + self.lyric = None + def check_name(self, name, nr=1): n = self.get_var_byname(name) if n: @@ -275,6 +283,14 @@ def check_lyrics(self, voice_id): else: print("Warning can't merge in lyrics!", voice_section) + def check_addlyrics(self): + r"""Merge the finished \addlyrics section into the music it follows.""" + lyrics_section = self.insert_into + if self.lyric and self.lyric[1] == 'middle': + self.lyric[1] = 'end' + self.insert_into = lyrics_section.merge_into + self.insert_into.merge_lyrics(lyrics_section) + def check_part(self): """Adds the latest active section to the part.""" if len(self.sections)>1: diff --git a/ly/musicxml/lymus2musxml.py b/ly/musicxml/lymus2musxml.py index 11ed001..8a30750 100644 --- a/ly/musicxml/lymus2musxml.py +++ b/ly/musicxml/lymus2musxml.py @@ -580,6 +580,9 @@ def FigureMode(self, figmode): def LyricMode(self, lyricmode): r"""A \lyricmode, \lyrics or \addlyrics expression.""" self.alt_mode = 'lyric' + if lyricmode.token == '\\addlyrics': + self.mediator.new_addlyrics_section() + self.sims_and_seqs.append('lyrics') def Override(self, override): r"""An \override command.""" @@ -665,6 +668,9 @@ def End(self, end): elif end.node.token == '\\lyricsto': self.mediator.check_lyrics(end.node.context_id()) self.sims_and_seqs.pop() + elif end.node.token == '\\addlyrics': + self.mediator.check_addlyrics() + self.sims_and_seqs.pop() elif end.node.token == '\\with': self.with_contxt = None elif end.node.token == '\\drums': diff --git a/tests/test_xml.py b/tests/test_xml.py index e5ca26b..68b379e 100644 --- a/tests/test_xml.py +++ b/tests/test_xml.py @@ -80,6 +80,10 @@ def test_chord_duration(): compare_output('chord_duration') +def test_addlyrics(): + compare_output('addlyrics') + + def ly_to_xml(filename): """Read Lilypond file and return XML string.""" writer = ly.musicxml.writer() diff --git a/tests/test_xml_files/addlyrics.ly b/tests/test_xml_files/addlyrics.ly new file mode 100644 index 0000000..974f468 --- /dev/null +++ b/tests/test_xml_files/addlyrics.ly @@ -0,0 +1,8 @@ +\version "2.18.2" + +\score { + \new Staff { + \relative c' { d2 c | bes4 bes c8 bes a4 } + } + \addlyrics { Du tout plon -- giet au de -- ses } +} diff --git a/tests/test_xml_files/addlyrics.xml b/tests/test_xml_files/addlyrics.xml new file mode 100644 index 0000000..bf40726 --- /dev/null +++ b/tests/test_xml_files/addlyrics.xml @@ -0,0 +1,130 @@ + + + + + + python-ly 0.9.10 + 2026-09-26 + + + + + + + + + + + 2 + + + G + 2 + + + + + D + 4 + + 4 + 1 + half + + single + Du + + + + + C + 4 + + 4 + 1 + half + + single + tout + + + + + + + B + -1 + 3 + + 2 + 1 + quarter + flat + + begin + plon + + + + + B + -1 + 3 + + 2 + 1 + quarter + flat + + end + giet + + + + + C + 4 + + 1 + 1 + eighth + + single + au + + + + + B + -1 + 3 + + 1 + 1 + eighth + flat + + begin + de + + + + + A + 3 + + 2 + 1 + quarter + + end + ses + + + + +