diff --git a/ly/musicxml/create_musicxml.py b/ly/musicxml/create_musicxml.py index 8fb82b7b..0d956417 100644 --- a/ly/musicxml/create_musicxml.py +++ b/ly/musicxml/create_musicxml.py @@ -115,6 +115,7 @@ def create_part(self, name="unnamed", abbr=False, midi=False): def create_measure(self, **bar_attrs): """Create new measure """ self.current_bar = etree.SubElement(self.current_part, "measure", number=str(self.bar_nr)) + self.current_print = None self.bar_nr +=1 if bar_attrs: self.new_bar_attr(**bar_attrs) @@ -627,6 +628,13 @@ def add_lyric(self, txt, syll, nr, ext=False): if ext: etree.SubElement(lyricnode, "extend") + def new_system(self): + if not self.current_print: + self.create_print() + self.current_print.attrib["new-system"] = "yes" + + def create_print(self): + self.current_print = etree.SubElement(self.current_bar, "print") ## # Create the XML document diff --git a/ly/musicxml/ly2xml_mediator.py b/ly/musicxml/ly2xml_mediator.py index a9ec6951..5e8b9658 100644 --- a/ly/musicxml/ly2xml_mediator.py +++ b/ly/musicxml/ly2xml_mediator.py @@ -829,6 +829,10 @@ def new_lyrics_item(self, item): elif item == '\\skip': self.insert_into.barlist.append("skip") + def line_break(self): + if self.bar: + self.bar.line_break = True + def duration_from_tokens(self, tokens): """Calculate dots and multibar rests from tokens.""" dots = 0 diff --git a/ly/musicxml/lymus2musxml.py b/ly/musicxml/lymus2musxml.py index 13dfb733..955ad399 100644 --- a/ly/musicxml/lymus2musxml.py +++ b/ly/musicxml/lymus2musxml.py @@ -497,6 +497,8 @@ def Command(self, command): if self.tupl_span: self.mediator.unset_tuplspan_dur() self.tupl_span = False + elif command.token == '\\break': + self.mediator.line_break() else: if command.token not in excls: print("Unknown command:", command.token) diff --git a/ly/musicxml/xml_objs.py b/ly/musicxml/xml_objs.py index bad1e057..d49629df 100644 --- a/ly/musicxml/xml_objs.py +++ b/ly/musicxml/xml_objs.py @@ -103,6 +103,10 @@ def iterate_part(self, part): def iterate_bar(self, bar): """The objects in the bar are output to the xml-file.""" self.musxml.create_measure() + + if bar.line_break: + self.musxml.new_system() + for obj in bar.obj_list: if isinstance(obj, BarAttr): self.new_xml_bar_attr(obj) @@ -433,6 +437,7 @@ class Bar(): def __init__(self): self.obj_list = [] self.list_full = False + self.line_break = False def __repr__(self): return '<{0} {1}>'.format(self.__class__.__name__, self.obj_list) @@ -478,6 +483,10 @@ def inject_voice(self, new_voice, override=False): """ Adding new voice to bar. Omitting double or conflicting bar attributes as long as override is false. Omitting also bars with only skips.""" + + if new_voice.line_break: + self.line_break = True + if new_voice.obj_list[0].has_attr(): if self.obj_list[0].has_attr(): self.obj_list[0].merge_attr(new_voice.obj_list[0], override) diff --git a/tests/test_xml.py b/tests/test_xml.py index e25f6ae5..d3054360 100644 --- a/tests/test_xml.py +++ b/tests/test_xml.py @@ -31,6 +31,9 @@ def test_tuplet(): compare_output('tuplet') +def test_break(): + compare_output('break') + def ly_to_xml(filename): """Read Lilypond file and return XML string.""" writer = ly.musicxml.writer() diff --git a/tests/test_xml_files/break.ly b/tests/test_xml_files/break.ly new file mode 100644 index 00000000..5c72a9c5 --- /dev/null +++ b/tests/test_xml_files/break.ly @@ -0,0 +1,8 @@ +\score { + \relative c' { + c1 | \break + c | c | \break + c | c | c 1 + } + \layout{} +} diff --git a/tests/test_xml_files/break.xml b/tests/test_xml_files/break.xml new file mode 100644 index 00000000..09e8f5f0 --- /dev/null +++ b/tests/test_xml_files/break.xml @@ -0,0 +1,97 @@ + + + + + + python-ly 0.9.5 + 2017-03-25 + + + + + + + + + + + 1 + + + G + 2 + + + + + C + 4 + + 4 + 1 + whole + + + + + + + C + 4 + + 4 + 1 + whole + + + + + + C + 4 + + 4 + 1 + whole + + + + + + + C + 4 + + 4 + 1 + whole + + + + + + C + 4 + + 4 + 1 + whole + + + + + + C + 4 + + 4 + 1 + whole + + + +