From 5cc2e518b105aece209de265de4b88b29e903042 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer Date: Sat, 25 Aug 2007 00:23:52 +0200 Subject: [PATCH] Convert score information into the \header{..} construct in lilypond. Also fix problem that \breathe does not accept any direction modifyer Convert some more ornaments --- python/musicxml.py | 86 +++++++++++++++++++++++++++++++++++++++++++++++- scripts/musicxml2ly.py | 63 +++++++++++++++++++++++++++++++++-- 2 files changed, 145 insertions(+), 4 deletions(-) diff --git a/python/musicxml.py b/python/musicxml.py index f7b962d..2056805 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -82,6 +82,74 @@ class Music_xml_node (Xml_node): self.duration = Rational (0) self.start = Rational (0) +class Work (Xml_node): + def get_work_information (self, tag): + wt = self.get_maybe_exist_named_child (tag) + if wt: + return wt.get_text () + else: + return self.get_text () + + def get_work_title (self): + return self.get_work_information ('work-title') + def get_work_number (self): + return self.get_work_information ('work-number') + def get_opus (self): + return self.get_work_information ('opus') + +class Identification (Xml_node): + def get_rights (self): + rights = self.get_maybe_exist_named_child ('rights') + if rights: + return rights.get_text () + else: + return '' + + def get_creator (self, type): + creators = self.get_named_children ('creator') + # 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 '' + + def get_composer (self): + c = self.get_creator ('composer') + if c: + return c + creators = self.get_named_children ('creator') + # return the first creator tag that has no type at all + for i in creators: + if not hasattr (i, 'type'): + return i.get_text () + return c + def get_arranger (self): + return self.get_creator ('arranger') + def get_editor (self): + return self.get_creator ('editor') + def get_poet (self): + return self.get_creator ('poet') + + def get_encoding_information (self, type): + enc = self.get_named_children ('encoding') + if enc: + children = enc[0].get_named_children (type) + if children: + return children[0].get_text () + else: + return '' + + def get_encoding_software (self): + return self.get_encoding_information ('software') + def get_encoding_date (self): + return self.get_encoding_information ('encoding-date') + def get_encoding_person (self): + return self.get_encoding_information ('encoder') + def get_encoding_description (self): + return self.get_encoding_information ('encoding-description') + + class Duration (Music_xml_node): def get_length (self): @@ -483,6 +551,14 @@ class DirType (Music_xml_node): class Wedge (Music_xml_node): pass +class Creator (Music_xml_node): + pass +class Rights (Music_xml_node): + pass +class Encoding (Music_xml_node): + pass +class WorkTitle (Music_xml_node): + pass ## need this, not all classes are instantiated ## for every input file. @@ -522,7 +598,15 @@ class_dict = { 'direction': Direction, 'direction-type': DirType, 'dynamics': Dynamics, - 'wedge': Wedge + 'wedge': Wedge, + + 'identification': Identification, + 'creator': Creator, + 'rights': Rights, + 'encoding': Encoding, + 'work': Work, + 'work-title': WorkTitle + } def name2class_name (name): diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 4bf9123..8bfb8bf 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -24,6 +24,59 @@ def progress (str): sys.stderr.flush () +# score information is contained in the , or tags +# extract those into a hash, indexed by proper lilypond header attributes +def extract_score_information (tree): + score_information = {} + 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 () + else: + movement_title = tree.get_maybe_exist_named_child ('movement-title') + if movement_title: + score_information['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 () + + 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 () + + 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])) + printer.newline () + printer.dump ('}') + printer.newline () + printer.newline () + + def musicxml_duration_to_lily (mxl_note): d = musicexp.Duration () if mxl_note.get_maybe_exist_typed_child (musicxml.Type): @@ -198,12 +251,12 @@ articulations_dict = { #"shake": "?", #"wavy-line": "?", "mordent": "mordent", - #"inverted-mordent": "?", + "inverted-mordent": "downmordent", #"schleifer": "?" ##### TECHNICALS "up-bow": "upbow", "down-bow": "downbow", - #"harmonic": "", + "harmonic": "flageolet", #"open-string": "", #"thumb-position": "", #"fingering": "", @@ -253,7 +306,8 @@ 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) - if dir: + # \breathe cannot have any direction modifyer (^, _, -)! + if dir and tp != "breathe": ev.force_direction = dir return ev @@ -799,6 +853,8 @@ def convert (filename, options): mxl_pl = tree.get_maybe_exist_typed_child (musicxml.Part_list) part_list = mxl_pl.get_named_children ("score-part") + # score information is contained in the , or tags + score_information = extract_score_information (tree) parts = tree.get_typed_children (musicxml.Part) voices = get_all_voices (parts) @@ -815,6 +871,7 @@ def convert (filename, options): printer.set_file (open (defs_ly_name, 'w')) print_ly_preamble (printer, filename) + print_ly_information (printer, score_information) print_voice_definitions (printer, part_list, voices) printer.close () -- 1.5.2.3