Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions ly/musicxml/create_musicxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,25 @@ def create_measure(self, pickup = False, **bar_attrs):
if bar_attrs:
self.new_bar_attr(**bar_attrs)

def get_previous_bar(self):
""" Return the previous bar or False if we're in the first. """
siblings = self.current_part.getchildren()
curr_index = siblings.index(self.current_bar)
if curr_index == 0:
return False
else:
return siblings[curr_index - 1]

def get_next_bar(self):
""" Return the next bar or False if we're in the last. """
siblings = self.current_part.getchildren()
curr_index = siblings.index(self.current_bar)
if curr_index == len(siblings) - 1:
return False
else:
return siblings[curr_index + 1]


##
# High-level node creation
##
Expand Down Expand Up @@ -504,6 +523,21 @@ def create_bar_attr(self):
"""Create node attributes """
self.bar_attr = etree.SubElement(self.current_bar, "attributes")

def create_barline(self, bar_style, ends_bar):
"""Create a barline, either at the current position
or at the end of the previous bar. """
if ends_bar:
# This is necessary because when the user writes \bar as a bar end
# we are already in the next measure.
bar = self.get_previous_bar()
location = 'right'
else:
bar = self.current_bar
location = 'middle'
bl = etree.SubElement(bar, "barline", {'location': location})
bs = etree.SubElement(bl, 'bar-style')
bs.text = bar_style

def add_divisions(self, div):
division = etree.SubElement(self.bar_attr, "divisions")
division.text = str(div)
Expand Down
11 changes: 6 additions & 5 deletions ly/musicxml/ly2xml_mediator.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,12 @@ def add_to_bar(self, obj):
self.new_bar()
self.bar.add(obj)

def create_barline(self, bl):
barline = xml_objs.BarAttr()
barline.set_barline(bl)
self.bar.add(barline)
self.new_bar()
def new_barline(self, bl):
if not self.bar:
# \bar at the very beginning is ignored
return
ends_bar = not self.bar.has_music()
self.bar.add(xml_objs.BarLine(bl, ends_bar))

def new_repeat(self, rep):
barline = xml_objs.BarAttr()
Expand Down
12 changes: 6 additions & 6 deletions ly/musicxml/lymus2musxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,22 @@ def __init__(self):

def parse_text(self, ly_text, filename=None):
"""Parse the LilyPond source specified as text.

If you specify a filename, it can be used to resolve \\include commands
correctly.

"""
doc = ly.document.Document(ly_text)
doc.filename = filename
self.parse_document(doc)

def parse_document(self, ly_doc, relative_first_pitch_absolute=False):
"""Parse the LilyPond source specified as a ly.document document.

If relative_first_pitch_absolute is set to True, the first pitch in a
\relative expression without startpitch is considered to be absolute
(LilyPond 2.18+ behaviour).

"""
# The document is copied and the copy is converted to absolute mode to
# facilitate the export. The original document is unchanged.
Expand Down Expand Up @@ -540,7 +540,7 @@ def MarkupList(self, markuplist):
def String(self, string):
prev = self.get_previous_node(string)
if prev and prev.token == '\\bar':
self.mediator.create_barline(string.value())
self.mediator.new_barline(string.value())

def LyricsTo(self, lyrics_to):
r"""A \lyricsto expression. """
Expand Down Expand Up @@ -682,7 +682,7 @@ def End(self, end):

def get_previous_node(self, node):
""" Returns the nodes previous node
or false if the node is first in its branch. """
or False if the node is first in its branch. """
parent = node.parent()
i = parent.index(node)
if i > 0:
Expand Down
15 changes: 14 additions & 1 deletion ly/musicxml/xml_objs.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,13 @@ def iterate_bar(self, bar):
elif isinstance(obj, BarBackup):
divdur = self.count_duration(obj.duration, self.divisions)
self.musxml.add_backup(divdur)
elif isinstance(obj, BarLine):
self.musxml.create_barline(obj.bar_style, obj.ends_bar)

def new_xml_bar_attr(self, obj):
"""Create bar attribute xml-nodes."""
if obj.has_attr():
self.musxml.new_bar_attr(obj.clef, obj.time, obj.key, obj.mode,
self.musxml.new_bar_attr(obj.clef, obj.time, obj.key, obj.mode,
obj.divs, obj.multirest)
if obj.new_system:
self.musxml.new_system(obj.new_system)
Expand Down Expand Up @@ -523,6 +525,17 @@ def inject_voice(self, new_voice, override=False):
self.add(bl)


class BarLine():
""" Represents a manual bar line, needed for in-measure barlines
or for special-style barlines."""
def __init__(self, bar_style, ends_bar):
self.bar_style = convert_barl(bar_style)
self.ends_bar = ends_bar

def __repr__(self):
return '<{0} {1}>'.format(self.__class__.__name__, self.bar_style)


class BarMus():
""" Common class for notes and rests. """
def __init__(self, duration, voice=1):
Expand Down
13 changes: 13 additions & 0 deletions tests/test_xml_files/barline.ly
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
\version "2.18.2"

\relative {
% Ignored:
\bar ":"
a'1
a4 a
% mid-measure
\bar "||"
a a |
g g g g
\bar "|."
}
123 changes: 123 additions & 0 deletions tests/test_xml_files/barline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN"
"http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise version="3.0">
<identification>
<encoding>
<software>python-ly 0.9.5</software>
<encoding-date>2018-05-07</encoding-date>
</encoding>
</identification>
<part-list>
<score-part id="P1">
<part-name />
</score-part>
</part-list>
<part id="P1">
<measure number="1">
<attributes>
<divisions>1</divisions>
<time symbol="common">
<beats>4</beats>
<beat-type>4</beat-type>
</time>
<clef>
<sign>G</sign>
<line>2</line>
</clef>
</attributes>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>4</duration>
<voice>1</voice>
<type>whole</type>
</note>
</measure>
<measure number="2">
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>1</duration>
<voice>1</voice>
<type>quarter</type>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>1</duration>
<voice>1</voice>
<type>quarter</type>
</note>
<barline location="middle">
<bar-style>light-light</bar-style>
</barline>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>1</duration>
<voice>1</voice>
<type>quarter</type>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>1</duration>
<voice>1</voice>
<type>quarter</type>
</note>
</measure>
<measure number="3">
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>1</duration>
<voice>1</voice>
<type>quarter</type>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>1</duration>
<voice>1</voice>
<type>quarter</type>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>1</duration>
<voice>1</voice>
<type>quarter</type>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>1</duration>
<voice>1</voice>
<type>quarter</type>
</note>
<barline location="right">
<bar-style>light-heavy</bar-style>
</barline>
</measure>
<measure number="4" />
</part>
</score-partwise>