if value:
header.set_field (field, musicxml.escape_ly_output_string (value))
+ movement_title = tree.get_maybe_exist_named_child ('movement-title')
+ if movement_title:
+ set_if_exists ('title', movement_title.get_text ())
work = tree.get_maybe_exist_named_child ('work')
if work:
+ # Overwrite the title from movement-title with work->title
set_if_exists ('title', work.get_work_title ())
set_if_exists ('worknumber', work.get_work_number ())
set_if_exists ('opus', work.get_opus ())
- else:
- movement_title = tree.get_maybe_exist_named_child ('movement-title')
- if movement_title:
- set_if_exists ('title', movement_title.get_text ())
identifications = tree.get_named_children ('identification')
for ids in identifications:
# Case 1: "Sibelius 5.1" with the "Dolet 3.4 for Sibelius" plugin
# is missing all beam ends => ignore all beaming information
- if "Dolet 3.4 for Sibelius" in software:
- conversion_settings.ignore_beaming = True
- progress (_ ("Encountered file created by Dolet 3.4 for Sibelius, containing wrong beaming information. All beaming information in the MusicXML file will be ignored"))
- # ditto for Dolet 3.5
- if "Dolet 3.5 for Sibelius" in software:
- conversion_settings.ignore_beaming = True
- progress (_ ("Encountered file created by Dolet 3.5 for Sibelius, containing wrong beaming information. All beaming information in the MusicXML file will be ignored"))
- if "Noteworthy Composer" in software:
- conversion_settings.ignore_beaming = True
- progress (_ ("Encountered file created by Noteworthy Composer's nwc2xml, containing wrong beaming information. All beaming information in the MusicXML file will be ignored"))
- # TODO: Check for other unsupported features
-
+ ignore_beaming_software = {
+ "Dolet 4 for Sibelius, Beta 2": "Dolet 4 for Sibelius, Beta 2",
+ "Dolet 3.5 for Sibelius": "Dolet 3.5 for Sibelius",
+ "Dolet 3.4 for Sibelius": "Dolet 3.4 for Sibelius",
+ "Dolet 3.3 for Sibelius": "Dolet 3.3 for Sibelius",
+ "Dolet 3.2 for Sibelius": "Dolet 3.2 for Sibelius",
+ "Dolet 3.1 for Sibelius": "Dolet 3.1 for Sibelius",
+ "Dolet for Sibelius 1.3": "Dolet for Sibelius 1.3",
+ "Noteworthy Composer": "Noteworthy Composer's nwc2xm[",
+ }
+ for s in software:
+ app_description = ignore_beaming_software.get (s, False);
+ if app_description:
+ conversion_settings.ignore_beaming = True
+ progress (_ ("Encountered file created by %s, containing wrong beaming information. All beaming information in the MusicXML file will be ignored") % app_description)
+
+ # TODO: Check for other unsupported features
return header
class PartGroupInfo:
elts.append (ev)
return elts
+
+def musicxml_print_to_lily (el):
+ # TODO: Implement other print attributes
+ # <!ELEMENT print (page-layout?, system-layout?, staff-layout*,
+ # measure-layout?, measure-numbering?, part-name-display?,
+ # part-abbreviation-display?)>
+ # <!ATTLIST print
+ # staff-spacing %tenths; #IMPLIED
+ # new-system %yes-no; #IMPLIED
+ # new-page %yes-no-number; #IMPLIED
+ # blank-page NMTOKEN #IMPLIED
+ # page-number CDATA #IMPLIED
+ # >
+ elts = []
+ if (hasattr (el, "new-system") and conversion_settings.convert_page_layout):
+ val = getattr (el, "new-system")
+ if (val == "yes"):
+ elts.append (musicexp.Break ("break"))
+ if (hasattr (el, "new-page") and conversion_settings.convert_page_layout):
+ val = getattr (el, "new-page")
+ if (val == "yes"):
+ elts.append (musicexp.Break ("pageBreak"))
+ return elts
+
class Marker (musicexp.Music):
def __init__ (self):
# TODO: How should I best convert the font-family attribute?
# TODO: How can I represent the underline, overline and line-through
- # attributes in Lilypond? Values of these attributes indicate
+ # attributes in LilyPond? Values of these attributes indicate
# the number of lines
return event
ev.bass = musicxml_chordpitch_to_lily (bass)
inversion = n.get_maybe_exist_named_child ('inversion')
if inversion:
- # TODO: Lilypond does not support inversions, does it?
+ # TODO: LilyPond does not support inversions, does it?
# Mail from Carl Sorensen on lilypond-devel, June 11, 2008:
# 4. LilyPond supports the first inversion in the form of added
voice_builder.set_measure_length (current_measure_length)
for n in voice._elements:
+ tie_started = False
if n.get_name () == 'forward':
continue
staff = n.get_maybe_exist_named_child ('staff')
chordnames_builder.add_barline (a, False)
continue
+
+ if isinstance (n, musicxml.Print):
+ for a in musicxml_print_to_lily (n):
+ voice_builder.add_command (a, False)
+ continue
+
# Continue any multimeasure-rests before trying to add bar checks!
# Don't handle new MM rests yet, because for them we want bar checks!
rest = n.get_maybe_exist_typed_child (musicxml.Rest)
if mxl_tie and mxl_tie.type == 'start':
ev_chord.append (musicexp.TieEvent ())
is_tied = True
+ tie_started = True
else:
is_tied = False
if not lnr in note_lyrics_processed:
lyrics[lnr].append ("\skip4")
- ## force trailing mm rests to be written out.
+ # Assume that a <tie> element only lasts for one note.
+ # This might not be correct MusicXML interpretation, but works for
+ # most cases and fixes broken files, which have the end tag missing
+ if is_tied and not tie_started:
+ is_tied = False
+
+ ## force trailing mm rests to be written out.
voice_builder.add_music (musicexp.ChordEvent (), Rational (0))
ly_voice = group_tuplets (voice_builder.elements, tuplet_events)
def voices_in_part_in_parts (parts):
"""return a Part -> Name -> Voice dictionary"""
- return dict([(p.id, voices_in_part (p)) for p in parts])
+ # don't crash if p doesn't have an id (that's invalid MusicXML,
+ # but such files are out in the wild!
+ dictionary = {}
+ for p in parts:
+ voices = voices_in_part (p)
+ if (hasattr (p, "id")):
+ dictionary[p.id] = voices
+ else:
+ # TODO: extract correct part id from other sources
+ dictionary[None] = voices
+ return dictionary;
def get_all_voices (parts):
dest = "convert_rest_positions",
help = _ ("do not convert exact vertical positions of rests"))
+ p.add_option ('--npl', '--no-page-layout',
+ action = "store_false",
+ default = True,
+ dest = "convert_page_layout",
+ help = _ ("do not convert the exact page layout and breaks"))
+
p.add_option ('--no-beaming',
action = "store_false",
default = True,
print_ly_additional_definitions (printer, filename)
if score_information:
score_information.print_ly (printer)
- if paper_information:
+ if paper_information and conversion_settings.convert_page_layout:
paper_information.print_ly (printer)
if layout_information:
layout_information.print_ly (printer)
needed_additional_definitions.append (options.language)
additional_definitions[options.language] = "\\include \"%s.ly\"\n" % options.language
conversion_settings.ignore_beaming = not options.convert_beaming
+ conversion_settings.convert_page_layout = options.convert_page_layout
# Allow the user to leave out the .xml or xml on the filename
basefilename = args[0].decode('utf-8')