From a183ac5b6a45731e06d46581227f1d9b832eace4 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer Date: Mon, 17 Sep 2007 16:32:21 +0200 Subject: [PATCH] MusicXML: Fix small issues detected with Recordare sample MusicXML files MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit -) Open the .ly output files using utf-8 encoding so that special characters like Umlaute, ©, » «, etc. can also be written out. Otherwise, python will simply exit the script. -) Fix line break issues with sys.stderr.write (line break explicitly needed in contrast to print) -) Fix extraction of creator from the XML. In particular, don't look only at the very first creator tag, but loop through all of them. Now, a score can have a composer, a lyricist, etc. -) Extract lyrics syllables only for notes, but not for rests. In lilypond a rest can have lyrics attached, in lilypond, the lyrics are assigned to notes only. All lyrics assigned to rests in MusicXML will be lost! Signed-off-by: Reinhold Kainhofer --- python/musicxml.py | 25 ++++++++++++++----------- scripts/musicxml2ly.py | 32 +++++++++++++++++--------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/python/musicxml.py b/python/musicxml.py index 5b335baafb..3ae5954e33 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -6,7 +6,7 @@ import sys def escape_ly_output_string (input_string): return_string = input_string - needs_quotes = not re.match ("^[a-zA-ZäöüÜÄÖßñ]*$", return_string); + needs_quotes = not re.match (u"^[a-zA-ZäöüÜÄÖßñ]*$", return_string); if needs_quotes: return_string = "\"" + string.replace (return_string, "\"", "\\\"") + "\"" return return_string @@ -42,11 +42,11 @@ class Xml_node: return ''.join ([c.get_text () for c in self._children]) def message (self, msg): - sys.stderr.write (msg) + sys.stderr.write (msg+'\n') p = self while p: - sys.stderr.write (' In: <%s %s>' % (p._name, ' '.join (['%s=%s' % item for item in p._attribute_dict.items()]))) + sys.stderr.write (' In: <%s %s>\n' % (p._name, ' '.join (['%s=%s' % item for item in p._attribute_dict.items()]))) p = p.get_parent () def get_typed_children (self, klass): @@ -82,7 +82,7 @@ class Xml_node: def get_unique_typed_child (self, klass): cn = self.get_typed_children(klass) if len (cn) <> 1: - sys.stderr.write (self.__dict__) + sys.stderr.write (self.__dict__ + '\n') raise 'Child is not unique for', (klass, 'found', cn) return cn[0] @@ -122,8 +122,7 @@ class Identification (Xml_node): for i in creators: if hasattr (i, 'type') and i.type == type: return i.get_text () - else: - return '' + return None def get_composer (self): c = self.get_creator ('composer') @@ -134,13 +133,17 @@ class Identification (Xml_node): for i in creators: if not hasattr (i, 'type'): return i.get_text () - return c + return None 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') + v = self.get_creator ('lyricist') + if v: + return v + v = self.get_creator ('poet') + return v def get_encoding_information (self, type): enc = self.get_named_children ('encoding') @@ -149,7 +152,7 @@ class Identification (Xml_node): if children: return children[0].get_text () else: - return '' + return None def get_encoding_software (self): return self.get_encoding_information ('software') @@ -234,7 +237,7 @@ class Attributes (Measure_element): else: return (4, 4) except KeyError: - sys.stderr.write ('error: requested time signature, but time sig unknown') + sys.stderr.write ('error: requested time signature, but time sig unknown\n') return (4, 4) # returns clef information in the form ("cleftype", position, octave-shift) @@ -323,7 +326,7 @@ class Part_list (Music_xml_node): if instrument_name: return instrument_name else: - sys.stderr.write ("Opps, couldn't find instrument for ID=%s" % id) + sys.stderr.write ("Opps, couldn't find instrument for ID=%s\n" % id) return "Grand Piano" class Measure (Music_xml_node): diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 11527b90c1..a75eff825b 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -5,6 +5,7 @@ import sys import re import os import string +import codecs from gettext import gettext as _ """ @@ -707,19 +708,20 @@ def musicxml_voice_to_lily_voice (voice): ev_chord.append (ev) # Extract the lyrics - note_lyrics_processed = [] - note_lyrics_elements = n.get_typed_children (musicxml.Lyric) - for l in note_lyrics_elements: - if l.get_number () < 0: - for k in lyrics.keys (): - lyrics[k].append (l.lyric_to_text ()) - note_lyrics_processed.append (k) - else: - lyrics[l.number].append(l.lyric_to_text ()) - note_lyrics_processed.append (l.number) - for lnr in lyrics.keys (): - if not lnr in note_lyrics_processed: - lyrics[lnr].append ("\skip4") + if not rest: + note_lyrics_processed = [] + note_lyrics_elements = n.get_typed_children (musicxml.Lyric) + for l in note_lyrics_elements: + if l.get_number () < 0: + for k in lyrics.keys (): + lyrics[k].append (l.lyric_to_text ()) + note_lyrics_processed.append (k) + else: + lyrics[l.number].append(l.lyric_to_text ()) + note_lyrics_processed.append (l.number) + for lnr in lyrics.keys (): + if not lnr in note_lyrics_processed: + lyrics[lnr].append ("\skip4") mxl_beams = [b for b in n.get_named_children ('beam') @@ -1016,7 +1018,7 @@ def convert (filename, options): printer = musicexp.Output_printer() progress ("Output to `%s'" % defs_ly_name) - printer.set_file (open (defs_ly_name, 'w')) + printer.set_file (codecs.open (defs_ly_name, 'wb', encoding='utf-8')) print_ly_preamble (printer, filename) score_information.print_ly (printer) @@ -1027,7 +1029,7 @@ def convert (filename, options): progress ("Output to `%s'" % driver_ly_name) printer = musicexp.Output_printer() - printer.set_file (open (driver_ly_name, 'w')) + printer.set_file (codecs.open (driver_ly_name, 'wb', encoding='utf-8')) print_ly_preamble (printer, filename) printer.dump (r'\include "%s"' % os.path.basename (defs_ly_name)) print_score_setup (printer, part_list, voices) -- 2.39.5