Hi Han-Wen! Attached are two more patches, which already address some of the points you mention.
-) 2007-09-01_0008-MusicXML-Conversion-of-various-types-of-spanners-o.patch converts some more spanners from MusicXML to lilypond. In particular, octave shifts, trill spanners, glissando and bends. -) 2007-09-01_0009-MusicXML-Convert-all-clefs-escape-in-header-fiel.patch Convert all available clefs to lilypond. Also address the issues by Han-Wen mentioned below. Don't be so strict about quoting in lyrics: Only wrap the lyrics syllables in quotes if necessary (but then also escape " in lyrics and header fields!). Am Samstag, 1. September 2007 schrieben Sie: > if you intend to work on this more, I could give you write access to the > repository. It would require you to sign up for savannah.gnu.org. Yes, I'm planning to do some more work on musicxml2ly, at least until it is in a state that it's easier for me to scan a score, export it to MusicXML and run musicxml2ly than to write it from scratch in lilypond. My username at savannah is kainhofer. Getting write access would be nice, but I also appreciate the feedback that I got here for my patches! > I am traveling the next 2 weeks, so I am won't have much time to look/ > I'm applying your patches. Could you address my comments in follow up > patches? Okay, will do. > * In general, git commit messages should have the following form > > 1-line summary > > background - typically the reason why you are doing it, or the > general idea behind it. Okay, in KDE we don't have any such requirement > Keep the 80 column limit in mind here. Okay, again, with KDE svn that limit is no issue. > * You have replaced almost all dict accesses with .get() ; this is only > desired if the default case makes sense. Sometime throwing a KeyError > actually does make sense. > > For example > > - (glyph, pos, c0) = self.clef_dict [self.type] > + (glyph, pos, c0) = self.clef_dict.get (self.type) > > doesn't really make sense, because the assignment will fail the default, > None. Ah, right, I thought I had left all [..], where an exception makes sense. Will revert this particular change in a later patch. This code is dead,though, anyway. I've redone the clef conversion code in the attached patch, so now almost all clefs are correctly converted from Finale 2007 to lilypond (the only problem I still have is the "None" key, which means that no key should be used. Lilypond does not seems to support this :-((( ). > If you have to check for the default value > > if key in dict: > ..do stuff.. > > is clearer then > > foo = dict.get(key, None) > if foo: > ... Agreed, it's clearer, but if I need to access foo later on, the second is more efficient (only one lookup instead of two). > * Also fix problem that \breathe does not accept any direction modifyer > > modifier got me! > # return the first creator tag that has type 'editor' > + for i in creators: > + if hasattr (i, 'type') and i.type == type: > + return i.get_text () > + else: > + return '' > > I don't understand the comment, do you mean "type" iso. editor? This happens when you write code, then restructure and outsource some parts to external funcitons... The comment should rather be: # return the first creator tag that has the particular type > + if ids.get_rights (): > + score_information['copyright'] = ids.get_rights () > > you could shorten this a little, > removing the duplicate call of ids.get_XXX() Done. > + printer.dump ('%s = "%s"' % (k, score_information[k])) > > this probably needs some escaping. What if there is a " in the title? Right! > + for k in score_information.keys (): > > slightly simpler: > > for (k, v) in score_information.items(): > printer.dump ('%s = "%s"' % (k, v)) Thanks! Cheers, Reinhold -- ------------------------------------------------------------------ Reinhold Kainhofer, Vienna University of Technology, Austria email: [EMAIL PROTECTED], http://reinhold.kainhofer.com/ * Financial and Actuarial Mathematics, TU Wien, http://www.fam.tuwien.ac.at/ * K Desktop Environment, http://www.kde.org, KOrganizer maintainer * Chorvereinigung "Jung-Wien", http://www.jung-wien.at/
From 330f0c0b84b0d1a5fbc87da52f1d906a8fddbf65 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer <[EMAIL PROTECTED]> Date: Sat, 1 Sep 2007 12:38:02 +0200 Subject: [PATCH] MusicXML: Conversion of various types of spanners (octave, pedals, trills) -) Implement Octave-shift (8va, 8vb, 15ma, 15mb) and pedal spanners -) Implement trill spanners. It seems that in MusicXML, a trill span does not include the trill sign, so they are duplicated in many cases. -) Attempt to implement dashed slurs. Does not work yet, because the corresponding \slurDashed needs to be before the note, which the current code structure does not allow. -) Implement Glissando. Explicitly setting the type to wavy does not work yet, because that command needs to be before the note in lilypond which is not yet supported by the structure of the musicxml2ly application. -) Implement bends ("-\bendAfter #nr" in lilypond) -) Use short notation where appropriate for articulations (e.g. "-." instead of "\staccato" or "->" instead of "\accent") Open problem: In MusicXML, a trill span consists of a trill sign plus a wavy-line spanner, while in Lilypond \startTrillSpan will create both. This means that in the future musicxml2ly needs to be changed to combine various kinds of Events. Also, MusicXML allows a trill spanner to start and end at the same note, which is not possible in lilypond. --- python/musicexp.py | 93 ++++++++++++++++++++++++++++++++++++++++-- python/musicxml.py | 49 +++++++++++++++++++++- scripts/musicxml2ly.py | 105 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 224 insertions(+), 23 deletions(-) diff --git a/python/musicexp.py b/python/musicexp.py index abe3125..6d7bc94 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -492,12 +492,28 @@ class SpanEvent (Event): def __init__(self): Event.__init__ (self) self.span_direction = 0 + self.line_type = 0 + self.size = 0 + def wait_for_note (self): + return True def get_properties(self): return "'span-direction %d" % self.span_direction class SlurEvent (SpanEvent): def ly_expression (self): - return {-1: '(', + before = '' + after = '' + # TODO: setting dashed/dotted line style does not work, because that + # command needs to be written before the note, not when the + # event is observed after the note! + #if self.line_type == 1: + #before = '\\slurDotted' + #elif self.line_type == 2: + #before = '\\slurDashed' + #if before: + #after = '\\slurSolid' + + return {-1: before + '(' + after, 0:'', 1:')'}.get (self.span_direction, '') @@ -507,7 +523,58 @@ class BeamEvent (SpanEvent): 0:'', 1:']'}.get (self.span_direction, '') +class PedalEvent (SpanEvent): + def ly_expression (self): + return {-1: '\\sustainDown', + 0:'', + 1:'\\sustainUp'}.get (self.span_direction, '') + +# type==-1 means octave up, type==-2 means octave down +class OctaveShiftEvent (SpanEvent): + def wait_for_note (self): + return False; + def ly_octave_shift_indicator (self): + if self.size == 8: + value = 1 + elif self.size == 15: + value = 2 + else: + value = 0 + # -2 means up + if self.span_direction == -2: + value = -value + return value + def ly_expression (self): + dir = self.ly_octave_shift_indicator () + value = '' + if dir: + value = '#(set-octavation %s)' % dir + return {-2: value, + -1: value, + 0: '', + 1: '#(set-octavation 0)'}.get (self.span_direction, '') + +class TrillSpanEvent (SpanEvent): + def ly_expression (self): + return {-1: '\\startTrillSpan', + 0:'', + 1:'\\stopTrillSpan'}.get (self.span_direction, '') + +class GlissandoEvent (SpanEvent): + def ly_expression (self): + style = '' + # TODO: wavy-line glissandos don't work, becasue the style has to be + # set before the note, at the \glissando it's already too late! + #if self.line_type == 3: # wavy-line: + #style = "\once\override Glissando #'style = #'zigzag" + # In lilypond, glissando is NOT a spanner, unlike MusicXML. + return {-1: style + '\\glissando', + 0:'', + 1:''}.get (self.span_direction, '') + class ArpeggioEvent(Event): + def wait_for_note (self): + return True; def ly_expression (self): return ('\\arpeggio') @@ -517,7 +584,7 @@ class TieEvent(Event): return '~' -class HairpinEvent (Event): +class HairpinEvent (SpanEvent): def __init__ (self, type): self.type = type def hairpin_to_ly (self): @@ -540,6 +607,8 @@ class DynamicsEvent (Event): "mp", "mf", "f", "ff", "fff", "ffff", "fp", "sf", "sff", "sp", "spp", "sfz", "rfz" ]; + def wait_for_note (self): + return True; def ly_expression (self): if self.type == None: return; @@ -568,17 +637,33 @@ class ArticulationEvent (Event): def ly_expression (self): return '%s\\%s' % (self.direction_mod (), self.type) +class ShortArticulationEvent (ArticulationEvent): + def direction_mod (self): + # default is - + return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-') + def ly_expression (self): + return '%s%s' % (self.direction_mod (), self.type) class TremoloEvent (Event): def __init__ (self): - self.bars = 0; + Event.__init__ (self) + self.bars = 0 def ly_expression (self): str='' if self.bars > 0: str += ':%s' % (2 ** (2 + string.atoi (self.bars))) return str - + +class BendEvent (Event): + def __init__ (self): + Event.__init__ (self) + self.alter = 0 + def ly_expression (self): + if self.alter: + return "-\\bendAfter #%s" % self.alter + else: + return '' class RhythmicEvent(Event): def __init__ (self): diff --git a/python/musicxml.py b/python/musicxml.py index 0430661..fe8dd60 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -536,20 +536,48 @@ class Accidental (Music_xml_node): self.editorial = False self.cautionary = False +class Music_xml_spanner (Music_xml_node): + def get_type (self): + if hasattr (self, 'type'): + return self.type + else: + return 0 + def get_size (self): + if hasattr (self, 'size'): + return string.atoi (self.size) + else: + return 0 -class Tuplet(Music_xml_node): +class Tuplet(Music_xml_spanner): pass -class Slur (Music_xml_node): +class Slur (Music_xml_spanner): def get_type (self): return self.type -class Beam (Music_xml_node): +class Beam (Music_xml_spanner): def get_type (self): return self.get_text () def is_primary (self): return self.number == "1" + +class Wavy_line (Music_xml_spanner): + pass +class Pedal (Music_xml_spanner): + pass + +class Glissando (Music_xml_spanner): + pass + +class Octave_shift (Music_xml_spanner): + # default is 8 for the octave-shift! + def get_size (self): + if hasattr (self, 'size'): + return string.atoi (self.size) + else: + return 8 + class Chord (Music_xml_node): pass @@ -575,6 +603,15 @@ class Direction (Music_xml_node): class DirType (Music_xml_node): pass +class Bend (Music_xml_node): + def bend_alter (self): + alter = self.get_maybe_exist_named_child ('bend-alter') + if alter: + return alter.get_text() + else: + return 0 + + ## need this, not all classes are instantiated ## for every input file. Only add those classes, that are either directly @@ -584,26 +621,32 @@ class_dict = { 'accidental': Accidental, 'attributes': Attributes, 'beam' : Beam, + 'bend' : Bend, 'chord': Chord, 'dot': Dot, 'direction': Direction, 'direction-type': DirType, 'duration': Duration, + 'glissando': Glissando, 'grace': Grace, 'identification': Identification, 'lyric': Lyric, 'measure': Measure, 'notations': Notations, 'note': Note, + 'octave-shift': Octave_shift, 'part': Part, 'part-list': Part_list, + 'pedal': Pedal, 'pitch': Pitch, 'rest': Rest, 'slur': Slur, 'syllabic': Syllabic, 'text': Text, 'time-modification': Time_modification, + 'tuplet': Tuplet, 'type': Type, + 'wavy-line': Wavy_line, 'work': Work, } diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index ed57e29..46f3da3 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -195,13 +195,25 @@ def musicxml_attributes_to_lily (attrs): spanner_event_dict = { 'slur' : musicexp.SlurEvent, 'beam' : musicexp.BeamEvent, -} + 'glissando' : musicexp.GlissandoEvent, + 'pedal' : musicexp.PedalEvent, + 'wavy-line' : musicexp.TrillSpanEvent, + 'octave-shift' : musicexp.OctaveShiftEvent +} spanner_type_dict = { 'start': -1, 'begin': -1, + 'up': -2, + 'down': -1, 'stop': 1, 'end' : 1 } +spanner_line_type_dict = { + 'solid': 0, + 'dashed': 1, + 'dotted': 2, + 'wavy': 3 +} def musicxml_spanner_to_lily_event (mxl_event): ev = None @@ -212,6 +224,7 @@ def musicxml_spanner_to_lily_event (mxl_event): ev = func() else: print 'unknown span event ', mxl_event + key = mxl_event.get_type () span_direction = spanner_type_dict.get (key) @@ -219,6 +232,13 @@ def musicxml_spanner_to_lily_event (mxl_event): ev.span_direction = span_direction else: print 'unknown span type', key, 'for', name + + if hasattr (mxl_event, 'line-type'): + span_line_type = spanner_line_type_dict.get (getattr (mxl_event, 'line-type')) + if span_line_type: + ev.line_type = span_line_type + # assign the size, which is used for octave-shift, etc. + ev.size = mxl_event.get_size () return ev @@ -234,14 +254,32 @@ def musicxml_fermata_to_lily_event (mxl_event): ev.force_direction = dir return ev -def musicxml_tremolo_to_lily_event(mxl_event): +def musicxml_tremolo_to_lily_event (mxl_event): if mxl_event.get_name () != "tremolo": return ev = musicexp.TremoloEvent () ev.bars = mxl_event.get_text () return ev +def musicxml_bend_to_lily_event (mxl_event): + if mxl_event.get_name () != "bend": + return + ev = musicexp.BendEvent () + ev.alter = mxl_event.bend_alter () + return ev + + # TODO: Some translations are missing! +short_articulations_dict = { + "staccato": ".", + "tenuto": "-", + "stopped": "+", + "staccatissimo": "|", + "accent": ">", + "strong-accent": "^", + #"portato": "_", # does not exist in MusicXML + #"fingering": "", # fingering is special cased, as get_text() will be the event's name +} articulations_dict = { ##### ORNAMENTS "trill-mark": "trill", @@ -251,7 +289,7 @@ articulations_dict = { #"shake": "?", #"wavy-line": "?", "mordent": "mordent", - "inverted-mordent": "downmordent", + "inverted-mordent": "prall", #"schleifer": "?" ##### TECHNICALS "up-bow": "upbow", @@ -259,28 +297,21 @@ articulations_dict = { "harmonic": "flageolet", #"open-string": "", #"thumb-position": "", - #"fingering": "", #"pluck": "", #"double-tongue": "", #"triple-tongue": "", - #"stopped": "", #"snap-pizzicato": "", #"fret": "", #"string": "", #"hammer-on": "", #"pull-off": "", - #"bend": "", + #"bend": "bendAfter #%s", # bend is special-cased, as we need to process the bend-alter subelement! #"tap": "", #"heel": "", #"toe": "", #"fingernails": "" ##### ARTICULATIONS - "accent": "accent", - "strong-accent": "marcato", - "staccato": "staccato", - "tenuto": "tenuto", #"detached-legato": "", - "staccatissimo": "staccatissimo", #"spiccato": "", #"scoop": "", #"plop": "", @@ -291,10 +322,29 @@ articulations_dict = { #"stress": "", #"unstress": "" } +articulation_spanners = [ "wavy-line" ] -def musicxml_articulation_to_lily_event(mxl_event): - ev = musicexp.ArticulationEvent () - tp = articulations_dict.get (mxl_event.get_name ()) +def musicxml_articulation_to_lily_event (mxl_event): + # wavy-line elements are treated as trill spanners, not as articulation ornaments + if mxl_event.get_name () in articulation_spanners: + return musicxml_spanner_to_lily_event (mxl_event) + + # special case, because of the bend-alter subelement + if mxl_event.get_name() == "bend": + return musicxml_bend_to_lily_event (mxl_event) + + # If we can write a shorthand, use them! + if mxl_event.get_name() == "fingering": + ev = musicexp.ShortArticulationEvent () + tp = mxl_event.get_text() + # In all other cases, use the dicts to translate the xml tag name to a proper lilypond command + elif short_articulations_dict.get (mxl_event.get_name ()): + ev = musicexp.ShortArticulationEvent () + tp = short_articulations_dict.get (mxl_event.get_name ()) + else: + ev = musicexp.ArticulationEvent () + tp = articulations_dict.get (mxl_event.get_name ()) + if not tp: return @@ -318,6 +368,8 @@ def musicxml_direction_to_lily( n ): dirtype = n.get_maybe_exist_typed_child (musicxml.DirType) if not dirtype: return res + + direction_spanners = [ 'octave-shift', 'pedal' ] for entry in dirtype.get_all_children (): if entry.get_name () == "dynamics": @@ -342,6 +394,14 @@ def musicxml_direction_to_lily( n ): if wedgetypeval != None: event = musicexp.HairpinEvent (wedgetypeval) res.append (event) + + + # octave shifts. pedal marks etc. are spanners: + if entry.get_name() in direction_spanners: + event = musicxml_spanner_to_lily_event (entry) + if event: + res.append (event) + return res @@ -491,7 +551,10 @@ def musicxml_voice_to_lily_voice (voice): if isinstance (n, musicxml.Direction): for a in musicxml_direction_to_lily (n): - voice_builder.add_dynamics (a) + if a.wait_for_note (): + voice_builder.add_dynamics (a) + else: + voice_builder.add_music (a, 0) continue if not n.get_maybe_exist_named_child ('chord'): @@ -578,9 +641,19 @@ def musicxml_voice_to_lily_voice (voice): fermatas = notations.get_named_children ('fermata') for a in fermatas: - ev = musicxml_fermata_to_lily_event (a); + ev = musicxml_fermata_to_lily_event (a) if ev: ev_chord.append (ev) + + arpeggiate = notations.get_named_children ('arpeggiate') + for a in arpeggiate: + ev_chord.append (musicexp.ArpeggioEvent ()) + + glissandos = notations.get_named_children ('glissando') + for a in glissandos: + ev = musicxml_spanner_to_lily_event (a) + if ev: + ev_chord.append (ev) # Articulations can contain the following child elements: # accent | strong-accent | staccato | tenuto | -- 1.5.2.3
From 664becdedd4d52c72217c241ec18fe4bf913285d Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer <[EMAIL PROTECTED]> Date: Sat, 1 Sep 2007 14:36:38 +0200 Subject: [PATCH] MusicXML: Convert all clefs, escape " in header fields, code simplification -) Extend the ClefChange class to convert all different clefs (G,C,F, percussion,tab) to the corresponding lilypond clef names. MusicXML also allows a "None" key, which lilypond does not :-( -) In the header fields and the lyrics, escape all quotes by \". Only wrap the whole string in quotes if it is necessary (string contains numbers, spaces, quotes, or starts with a period or comma). This makes it much easier to edit the lyrics later on. -) Several coding style issued pointed out by Han-Wen --- python/musicexp.py | 29 ++++++++++++++++++++++--- python/musicxml.py | 34 +++++++++++++++++++++++------- scripts/musicxml2ly.py | 53 ++++++++++++++++++++--------------------------- 3 files changed, 74 insertions(+), 42 deletions(-) diff --git a/python/musicexp.py b/python/musicexp.py index 6d7bc94..cf29aa6 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -5,6 +5,7 @@ import re from rational import Rational + class Output_stack_element: def __init__ (self): self.factor = Rational (1) @@ -763,10 +764,27 @@ class ClefChange (Music): def __init__ (self): Music.__init__ (self) self.type = 'G' - - + self.position = 2 + self.octave = 0 + + def octave_modifier (self): + return {1: "^8", 2: "^15", -1: "_8", -2: "_15"}.get (self.octave, '') + def clef_name (self): + return {('G', 2): "treble", + ('G', 1): "french", + ('C', 1): "soprano", + ('C', 2): "mezzosoprano", + ('C', 3): "alto", + ('C', 4): "tenor", + ('C', 5): "baritone", + ('F', 3): "varbaritone", + ('F', 4): "bass", + ('F', 5): "subbass", + ("percussion", 2): "percussion", + ("TAB", 5): "tab"}.get ((self.type, self.position), None) def ly_expression (self): - return '\\clef "%s"' % self.type + return '\\clef "%s%s"' % (self.clef_name (), self.octave_modifier ()) + clef_dict = { "G": ("clefs.G", -2, -6), "C": ("clefs.C", 0, 0), @@ -774,7 +792,10 @@ class ClefChange (Music): } def lisp_expression (self): - (glyph, pos, c0) = self.clef_dict.get (self.type) + try: + (glyph, pos, c0) = self.clef_dict[self.type] + except KeyError: + return "" clefsetting = """ (make-music 'SequentialMusic 'elements (list diff --git a/python/musicxml.py b/python/musicxml.py index fe8dd60..a24cb53 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -1,6 +1,16 @@ import new import string from rational import * +import re + +def escape_ly_output_string (input_string): + return_string = input_string + needs_quotes = re.search ("[0-9\" ]", return_string) or re.search ("^[,.]", return_string); + return_string = string.replace (return_string, "\"", "\\\"") + if needs_quotes: + return_string = "\"" + return_string + "\"" + return return_string + class Xml_node: def __init__ (self): @@ -108,7 +118,7 @@ class Identification (Xml_node): def get_creator (self, type): creators = self.get_named_children ('creator') - # return the first creator tag that has type 'editor' + # return the first creator tag that has the particular type for i in creators: if hasattr (i, 'type') and i.type == type: return i.get_text () @@ -223,14 +233,22 @@ class Attributes (Measure_element): print 'error: requested time signature, but time sig unknown' return (4, 4) - def get_clef_sign (self): + # returns clef information in the form ("cleftype", position, octave-shift) + def get_clef_information (self): + clefinfo = ['G', 2, 0] mxl = self.get_named_attribute ('clef') + if not mxl: + return clefinfo sign = mxl.get_maybe_exist_named_child ('sign') if sign: - return sign.get_text () - else: - print 'clef requested, but unknow' - return 'G' + clefinfo[0] = sign.get_text() + line = mxl.get_maybe_exist_named_child ('line') + if line: + clefinfo[1] = string.atoi (line.get_text ()) + octave = mxl.get_maybe_exist_named_child ('clef-octave-change') + if octave: + clefinfo[2] = string.atoi (octave.get_text ()) + return clefinfo def get_key_signature (self): "return (fifths, mode) tuple" @@ -336,11 +354,11 @@ class Lyric (Music_xml_node): elif text == "_" and continued: return "__" elif continued and text: - return "\"" + text + "\" --" + return escape_ly_output_string (text) + " --" elif continued: return "--" elif text: - return "\"" + text + "\"" + return escape_ly_output_string (text) else: return "" diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 46f3da3..fbc7525 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -28,49 +28,42 @@ def progress (str): # extract those into a hash, indexed by proper lilypond header attributes def extract_score_information (tree): score_information = {} + def set_if_exists (field, value): + if value: + score_information[field] = value + work = tree.get_maybe_exist_named_child ('work') if work: - if work.get_work_title (): - score_information['title'] = work.get_work_title () - if work.get_work_number (): - score_information['worknumber'] = work.get_work_number () - if work.get_opus (): - score_information['opus'] = work.get_opus () + 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: - score_information['title'] = movement_title.get_text () + set_if_exists ('title', movement_title.get_text ()) identifications = tree.get_named_children ('identification') for ids in identifications: - if ids.get_rights (): - score_information['copyright'] = ids.get_rights () - if ids.get_composer (): - score_information['composer'] = ids.get_composer () - if ids.get_arranger (): - score_information['arranger'] = ids.get_arranger () - if ids.get_editor (): - score_information['editor'] = ids.get_editor () - if ids.get_poet (): - score_information['poet'] = ids.get_poet () + set_if_exists ('copyright', ids.get_rights ()) + set_if_exists ('composer', ids.get_composer ()) + set_if_exists ('arranger', ids.get_arranger ()) + set_if_exists ('editor', ids.get_editor ()) + set_if_exists ('poet', ids.get_poet ()) - if ids.get_encoding_software (): - score_information['tagline'] = ids.get_encoding_software () - score_information['encodingsoftware'] = ids.get_encoding_software () - if ids.get_encoding_date (): - score_information['encodingdate'] = ids.get_encoding_date () - if ids.get_encoding_person (): - score_information['encoder'] = ids.get_encoding_person () - if ids.get_encoding_description (): - score_information['encodingdescription'] = ids.get_encoding_description () + set_if_exists ('tagline', ids.get_encoding_software ()) + set_if_exists ('encodingsoftware', ids.get_encoding_software ()) + set_if_exists ('encodingdate', ids.get_encoding_date ()) + set_if_exists ('encoder', ids.get_encoding_person ()) + set_if_exists ('encodingdescription', ids.get_encoding_description ()) return score_information + def print_ly_information (printer, score_information): printer.dump ('\header {') printer.newline () - for k in score_information.keys (): - printer.dump ('%s = "%s"' % (k, score_information[k])) + for (k, text) in score_information.items (): + printer.dump ('%s = %s' % (k, musicxml.escape_ly_output_string (text))) printer.newline () printer.dump ('}') printer.newline () @@ -135,7 +128,7 @@ def group_tuplets (music_list, events): def musicxml_clef_to_lily (attributes): change = musicexp.ClefChange () - change.type = attributes.get_clef_sign () + (change.type, change.position, change.octave) = attributes.get_clef_information () return change def musicxml_time_to_lily (attributes): @@ -356,7 +349,7 @@ def musicxml_articulation_to_lily_event (mxl_event): dir = musicxml_direction_to_indicator (mxl_event.type) if hasattr (mxl_event, 'placement'): dir = musicxml_direction_to_indicator (mxl_event.placement) - # \breathe cannot have any direction modifyer (^, _, -)! + # \breathe cannot have any direction modifier (^, _, -)! if dir and tp != "breathe": ev.force_direction = dir return ev -- 1.5.2.3
_______________________________________________ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel