X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Fetf2ly.py;h=24dc562871abdb74590cde5cb8cd8063969fcde0;hb=HEAD;hp=4e287d014805567137c90b5ab11f72fd174a88f1;hpb=a8e32d8cfb884862aea3ed94291264ff4cc85eca;p=lilypond.git diff --git a/scripts/etf2ly.py b/scripts/etf2ly.py index 4e287d0148..24dc562871 100644 --- a/scripts/etf2ly.py +++ b/scripts/etf2ly.py @@ -1,4 +1,19 @@ -#!@PYTHON@ +#!@TARGET_PYTHON@ + +# This file is part of LilyPond, the GNU music typesetter. +# +# LilyPond is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# LilyPond is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with LilyPond. If not, see . # info mostly taken from looking at files. See also # http://lilypond.org/wiki/?EnigmaTransportFormat @@ -26,1166 +41,1219 @@ # -program_name = 'etf2ly' -version = '@TOPLEVEL_VERSION@' -if version == '@' + 'TOPLEVEL_VERSION' + '@': - version = '(unknown version)' # uGUHGUHGHGUGH - import __main__ import getopt import sys import re -import string import os +program_name = sys.argv[0] + +authors = ('Jan Nieuwenhuizen ', + 'Han-Wen Nienhuys ') + +version = '@TOPLEVEL_VERSION@' +if version == '@' + 'TOPLEVEL_VERSION' + '@': + version = '(unknown version)' # uGUHGUHGHGUGH + +""" +@relocate-preamble@ +""" + +################################################################ + +import lilylib as ly +_ = ly._ + finale_clefs= ['treble', 'alto', 'tenor', 'bass', 'percussion', 'treble_8', 'bass_8', 'baritone'] def lily_clef (fin): - try: - return finale_clefs[fin] - except IndexError: - sys.stderr.write ( '\nHuh? Found clef number %d\n' % fin) + try: + return finale_clefs[fin] + except IndexError: + sys.stderr.write ( '\nHuh? Found clef number %d\n' % fin) - return 'treble' - - + return 'treble' + + def gulp_file(f): - return open (f).read () + return open (f).read () # notename 0 == central C distances = [0, 2, 4, 5, 7, 9, 11, 12] def semitones (name, acc): - return (name / 7 ) * 12 + distances[name % 7] + acc + return (name / 7 ) * 12 + distances[name % 7] + acc # represent pitches as (notename, alteration), relative to C-major scale def transpose(orig, delta): - (oname, oacc) = orig - (dname, dacc) = delta - - old_pitch =semitones (oname, oacc) - delta_pitch = semitones (dname, dacc) - nname = (oname + dname) - nacc = oacc - new_pitch = semitones (nname, nacc) + (oname, oacc) = orig + (dname, dacc) = delta + + old_pitch =semitones (oname, oacc) + delta_pitch = semitones (dname, dacc) + nname = (oname + dname) + nacc = oacc + new_pitch = semitones (nname, nacc) - nacc = nacc - (new_pitch - old_pitch - delta_pitch) + nacc = nacc - (new_pitch - old_pitch - delta_pitch) - return (nname, nacc) + return (nname, nacc) def interpret_finale_key_sig (finale_id): - """ + """ find the transposition of C-major scale that belongs here. we are not going to insert the correct major/minor, we only want to have the correct number of accidentals """ - p = (0,0) + p = (0,0) + + + bank_number = finale_id >> 8 + accidental_bits = finale_id & 0xff - - bank_number = finale_id >> 8 - accidental_bits = finale_id & 0xff + if 0 <= accidental_bits < 7: + while accidental_bits > 0: + p = transpose (p, (4,0)) # a fifth up + accidental_bits = accidental_bits - 1 + elif 248 < accidental_bits <= 255: + while accidental_bits < 256: + p = transpose (p, (3,0)) + accidental_bits = accidental_bits + 1 - if 0 <= accidental_bits < 7: - while accidental_bits > 0: - p = transpose (p, (4,0)) # a fifth up - accidental_bits = accidental_bits - 1 - elif 248 < accidental_bits <= 255: - while accidental_bits < 256: - p = transpose (p, (3,0)) - accidental_bits = accidental_bits + 1 - - p = (p[0] % 7, p[1]) + if bank_number == 1: + # minor scale + p = transpose (p, (5, 0)) + p = (p[0] % 7, p[1]) - return p + return KeySignature (p, bank_number) # should cache this. -def find_scale (transposition): - cscale = map (lambda x: (x,0), range (0,7)) - trscale = map(lambda x, k=transposition: transpose(x, k), cscale) +def find_scale (keysig): + cscale = map (lambda x: (x,0), range (0,7)) +# print "cscale: ", cscale + ascale = map (lambda x: (x,0), range (-2,5)) +# print "ascale: ", ascale + transposition = keysig.pitch + if keysig.sig_type == 1: + transposition = transpose(transposition, (2, -1)) + transposition = (transposition[0] % 7, transposition[1]) + trscale = map(lambda x, k=transposition: transpose(x, k), ascale) + else: + trscale = map(lambda x, k=transposition: transpose(x, k), cscale) +# print "trscale: ", trscale + return trscale - return trscale def EDU_to_duration (edu): - log = 1 - d = 4096 - while d > edu: - d = d >> 1 - log = log << 1 - - edu = edu - d - dots = 0 - if edu == d /2: - dots = 1 - elif edu == d*3/4: - dots = 2 - return (log, dots) - -def rat_to_lily_duration (rat): - (n,d) = rat - - basedur = 1 - while d and d % 2 == 0: - basedur = basedur << 1 - d = d >> 1 - - str = 's%d' % basedur - if n <> 1: - str = str + '*%d' % n - if d <> 1: - str = str + '/%d' % d - - return str + log = 1 + d = 4096 + while d > edu: + d = d >> 1 + log = log << 1 + + edu = edu - d + dots = 0 + if edu == d /2: + dots = 1 + elif edu == d*3/4: + dots = 2 + return (log, dots) + +def rational_to_lily_skip (rat): + (n,d) = rat + + basedur = 1 + while d and d % 2 == 0: + basedur = basedur << 1 + d = d >> 1 + + str = 's%d' % basedur + if n <> 1: + str = str + '*%d' % n + if d <> 1: + str = str + '/%d' % d + + return str def gcd (a,b): - if b == 0: - return a - c = a - while c: - c = a % b - a = b - b = c - return a - + if b == 0: + return a + c = a + while c: + c = a % b + a = b + b = c + return a + def rat_simplify (r): - (n,d) = r - if d < 0: - d = -d - n = -n - if n == 0: - return (0,1) - else: - g = gcd (n, d) - return (n/g, d/g) - + (n,d) = r + if d < 0: + d = -d + n = -n + if n == 0: + return (0,1) + else: + g = gcd (n, d) + return (n/g, d/g) + def rat_multiply (a,b): - (x,y) = a - (p,q) = b + (x,y) = a + (p,q) = b - return rat_simplify ((x*p, y*q)) + return rat_simplify ((x*p, y*q)) def rat_add (a,b): - (x,y) = a - (p,q) = b + (x,y) = a + (p,q) = b - return rat_simplify ((x*q + p*y, y*q)) + return rat_simplify ((x*q + p*y, y*q)) def rat_neg (a): - (p,q) = a - return (-p,q) + (p,q) = a + return (-p,q) def rat_subtract (a,b ): - return rat_add (a, rat_neg (b)) + return rat_add (a, rat_neg (b)) def lily_notename (tuple2): - (n, a) = tuple2 - nn = chr ((n+ 2)%7 + ord ('a')) + (n, a) = tuple2 + nn = chr ((n+ 2)%7 + ord ('a')) - return nn + {-2:'eses', -1:'es', 0:'', 1:'is', 2:'isis'}[a] + return nn + {-2:'eses', -1:'es', 0:'', 1:'is', 2:'isis'}[a] class Tuplet: - def __init__ (self, number): - self.start_note = number - self.finale = [] - - def append_finale (self, fin): - self.finale.append (fin) - - def factor (self): - n = self.finale[0][2]*self.finale[0][3] - d = self.finale[0][0]*self.finale[0][1] - return rat_simplify( (n, d)) - - def dump_start (self): - return '\\times %d/%d { ' % self.factor () - - def dump_end (self): - return ' }' - - def calculate (self, chords): - edu_left = self.finale[0][0] * self.finale[0][1] - - startch = chords[self.start_note] - c = startch - while c and edu_left: - c.tuplet = self - if c == startch: - c.chord_prefix = self.dump_start () + c.chord_prefix - - if not c.grace: - edu_left = edu_left - c.EDU_duration () - if edu_left == 0: - c.chord_suffix = c.chord_suffix+ self.dump_end () - c = c.next - - if edu_left: - sys.stderr.write ("\nHuh? Tuplet starting at entry %d was too short." % self.start_note) - + def __init__ (self, number): + self.start_note = number + self.finale = [] + + def append_finale (self, fin): + self.finale.append (fin) + + def factor (self): + n = self.finale[0][2]*self.finale[0][3] + d = self.finale[0][0]*self.finale[0][1] + return rat_simplify( (n, d)) + + def dump_start (self): + return '\\times %d/%d { ' % self.factor () + + def dump_end (self): + return ' }' + + def calculate (self, chords): + edu_left = self.finale[0][0] * self.finale[0][1] + + startch = chords[self.start_note] + c = startch + while c and edu_left: + c.tuplet = self + if c == startch: + c.chord_prefix = self.dump_start () + c.chord_prefix + + if not c.grace: + edu_left = edu_left - c.EDU_duration () + if edu_left == 0: + c.chord_suffix = c.chord_suffix+ self.dump_end () + c = c.next + + if edu_left: + sys.stderr.write ("\nHuh? Tuplet starting at entry %d was too short." % self.start_note) + class Slur: - def __init__ (self, number, params): - self.number = number - self.finale = params - - def append_entry (self, finale_e): - self.finale.append (finale_e) - - def calculate (self, chords): - startnote = self.finale[5] - endnote = self.finale[3*6 + 2] - try: - cs = chords[startnote] - ce = chords[endnote] - - if not cs or not ce: - raise IndexError - - cs.note_suffix = '-(' + cs.note_suffix - ce.note_suffix = ce.note_suffix + '-)' - - except IndexError: - sys.stderr.write ("""\nHuh? Slur no %d between (%d,%d), with %d notes""" % (self.number, startnote, endnote, len (chords))) - - + def __init__ (self, number, params): + self.number = number + self.finale = params + + def append_entry (self, finale_e): + self.finale.append (finale_e) + + def calculate (self, chords): + startnote = self.finale[5] + endnote = self.finale[3*6 + 2] + try: + cs = chords[startnote] + ce = chords[endnote] + + if not cs or not ce: + raise IndexError + + cs.note_suffix = '-(' + cs.note_suffix + ce.note_suffix = ce.note_suffix + '-)' + + except IndexError: + sys.stderr.write ("""\nHuh? Slur no %d between (%d,%d), with %d notes""" % (self.number, startnote, endnote, len (chords))) + + class Global_measure: - def __init__ (self, number): - self.timesig = '' - self.number = number - self.key_signature = None - self.scale = None - self.force_break = 0 - - self.repeats = [] - self.finale = [] - - def __str__ (self): - return `self.finale ` - - def set_timesig (self, finale): - (beats, fdur) = finale - (log, dots) = EDU_to_duration (fdur) - - if dots == 1: - beats = beats * 3 - log = log * 2 - dots = 0 - - if dots <> 0: - sys.stderr.write ("\nHuh? Beat duration has dots? (EDU Duration = %d)" % fdur) - self.timesig = (beats, log) - - def length (self): - return self.timesig - - def set_key_sig (self, finale): - k = interpret_finale_key_sig (finale) - self.key_signature = k - self.scale = find_scale (k) - - def set_flags (self,flag1, flag2): - - # flag1 isn't all that interesting. - if flag2 & 0x8000: - self.force_break = 1 - - if flag2 & 0x0008: - self.repeats.append ('start') - if flag2 & 0x0004: - self.repeats.append ('stop') - - if flag2 & 0x0002: - if flag2 & 0x0004: - self.repeats.append ('bracket') + def __init__ (self, number): + self.timesig = '' + self.number = number + self.key_signature = None + self.scale = None + self.force_break = 0 + + self.repeats = [] + self.finale = [] + + def __str__ (self): + return `self.finale ` + + def set_timesig (self, finale): + (beats, fdur) = finale + (log, dots) = EDU_to_duration (fdur) + + if dots == 1: + beats = beats * 3 + log = log * 2 + dots = 0 + + if dots <> 0: + sys.stderr.write ("\nHuh? Beat duration has dots? (EDU Duration = %d)" % fdur) + self.timesig = (beats, log) + + def length (self): + return self.timesig + + def set_key_sig (self, finale): + k = interpret_finale_key_sig (finale) + self.key_signature = k + self.scale = find_scale (k) + + def set_flags (self,flag1, flag2): + + # flag1 isn't all that interesting. + if flag2 & 0x8000: + self.force_break = 1 + + if flag2 & 0x0008: + self.repeats.append ('start') + if flag2 & 0x0004: + self.repeats.append ('stop') + + if flag2 & 0x0002: + if flag2 & 0x0004: + self.repeats.append ('bracket') articulation_dict ={ - 94: '^', - 109: '\\prall', - 84: '\\turn', - 62: '\\mordent', - 85: '\\fermata', - 46: '.', -# 3: '>', -# 18: '\arpeggio' , + 94: '^', + 109: '\\prall', + 84: '\\turn', + 62: '\\mordent', + 85: '\\fermata', + 46: '.', +# 3: '>', +# 18: '\arpeggio' , } class Articulation_def: - def __init__ (self, n, a, b): - self.finale_glyph = a & 0xff - self.number = n - - def dump (self): - try: - return articulation_dict[self.finale_glyph] - except KeyError: - sys.stderr.write ("\nUnknown articulation no. %d" % self.finale_glyph) - sys.stderr.write ("\nPlease add an entry to articulation_dict in the Python source") - return None - + def __init__ (self, n, a, b): + self.finale_glyph = a & 0xff + self.number = n + + def dump (self): + try: + return articulation_dict[self.finale_glyph] + except KeyError: + sys.stderr.write ("\nUnknown articulation no. %d" % self.finale_glyph) + sys.stderr.write ("\nPlease add an entry to articulation_dict in the Python source") + return None + class Articulation: - def __init__ (self, a,b, finale): - self.definition = finale[0] - self.notenumber = b - - def calculate (self, chords, defs): - c = chords[self.notenumber] + def __init__ (self, a,b, finale): + self.definition = finale[0] + self.notenumber = b + + def calculate (self, chords, defs): + c = chords[self.notenumber] - adef = defs[self.definition] - lystr =adef.dump() - if lystr == None: - lystr = '"art"' - sys.stderr.write ("\nThis happened on note %d" % self.notenumber) + adef = defs[self.definition] + lystr =adef.dump() + if lystr == None: + lystr = '"art"' + sys.stderr.write ("\nThis happened on note %d" % self.notenumber) - c.note_suffix = '-' + lystr + c.note_suffix = '-' + lystr class Syllable: - def __init__ (self, a,b , finale): - self.chordnum = b - self.syllable = finale[1] - self.verse = finale[0] - def calculate (self, chords, lyrics): - self.chord = chords[self.chordnum] + def __init__ (self, a,b , finale): + self.chordnum = b + self.syllable = finale[1] + self.verse = finale[0] + def calculate (self, chords, lyrics): + self.chord = chords[self.chordnum] class Verse: - def __init__ (self, number, body): - self.body = body - self.number = number - self.split_syllables () - def split_syllables (self): - ss = re.split ('(-| +)', self.body) - - sep = 0 - syls = [None] - for s in ss: - if sep: - septor = re.sub (" +", "", s) - septor = re.sub ("-", " -- ", septor) - syls[-1] = syls[-1] + septor - else: - syls.append (s) - - sep = not sep - - self.syllables = syls - - def dump (self): - str = '' - line = '' - for s in self.syllables[1:]: - line = line + ' ' + s - if len (line) > 72: - str = str + ' ' * 4 + line + '\n' - line = '' - - str = """\nverse%s = \\lyrics {\n %s}\n""" % (encodeint (self.number - 1) ,str) - return str - - + def __init__ (self, number, body): + self.body = body + self.number = number + self.split_syllables () + def split_syllables (self): + ss = re.split ('(-| +)', self.body) + + sep = 0 + syls = [None] + for s in ss: + if sep: + septor = re.sub (" +", "", s) + septor = re.sub ("-", " -- ", septor) + syls[-1] = syls[-1] + septor + else: + syls.append (s) + + sep = not sep + + self.syllables = syls + + def dump (self): + str = '' + line = '' + for s in self.syllables[1:]: + line = line + ' ' + s + if len (line) > 72: + str = str + ' ' * 4 + line + '\n' + line = '' + + str = """\nverse%s = \\lyricmode {\n %s }\n""" % (encodeint (self.number - 1) ,str) + return str + +class KeySignature: + def __init__(self, pitch, sig_type = 0): + self.pitch = pitch + self.sig_type = sig_type + + def signature_type (self): + if self.sig_type == 1: + return "\\minor" + else: + # really only for 0, but we only know about 0 and 1 + return "\\major" + + def equal (self, other): + if other and other.pitch == self.pitch and other.sig_type == self.sig_type: + return 1 + else: + return 0 + + class Measure: - def __init__(self, no): - self.number = no - self.frames = [0] * 4 - self.flags = 0 - self.clef = 0 - self.finale = [] - self.global_measure = None - self.staff = None - self.valid = 1 - - - def valid (self): - return self.valid - def calculate (self): - fs = [] - - if len (self.finale) < 2: - fs = self.finale[0] - - self.clef = fs[1] - self.frames = [fs[0]] - else: - fs = self.finale - self.clef = fs[0] - self.flags = fs[1] - self.frames = fs[2:] + def __init__(self, no): + self.number = no + self.frames = [0] * 4 + self.flags = 0 + self.clef = 0 + self.finale = [] + self.global_measure = None + self.staff = None + self.valid = 1 + + + def valid (self): + return self.valid + def calculate (self): + fs = [] + + if len (self.finale) < 2: + fs = self.finale[0] + + self.clef = fs[1] + self.frames = [fs[0]] + else: + fs = self.finale + self.clef = fs[0] + self.flags = fs[1] + self.frames = fs[2:] class Frame: - def __init__ (self, finale): - self.measure = None - self.finale = finale - (number, start, end ) = finale - self.number = number - self.start = start - self.end = end - self.chords = [] - - def set_measure (self, m): - self.measure = m - - def calculate (self): - - # do grace notes. - lastch = None - for c in self.chords: - if c.grace and (lastch == None or (not lastch.grace)): - c.chord_prefix = r'\grace {' + c.chord_prefix - elif not c.grace and lastch and lastch.grace: - lastch.chord_suffix = lastch.chord_suffix + ' } ' - - lastch = c - - - - def dump (self): - str = '%% FR(%d)\n' % self.number - left = self.measure.global_measure.length () - - - ln = '' - for c in self.chords: - add = c.ly_string () + ' ' - if len (ln) + len(add) > 72: - str = str + ln + '\n' - ln = '' - ln = ln + add - left = rat_subtract (left, c.length ()) - - str = str + ln - - if left[0] < 0: - sys.stderr.write ("""\nHuh? Going backwards in frame no %d, start/end (%d,%d)""" % (self.number, self.start, self.end)) - left = (0,1) - if left[0]: - str = str + rat_to_lily_duration (left) - - str = str + ' | \n' - return str - + def __init__ (self, finale): + self.measure = None + self.finale = finale + (number, start, end ) = finale + self.number = number + self.start = start + self.end = end + self.chords = [] + + def set_measure (self, m): + self.measure = m + + def calculate (self): + + # do grace notes. + lastch = None + in_grace = 0 + for c in self.chords: + if c.grace and (lastch == None or (not lastch.grace)): + c.chord_prefix = r'\grace {' + c.chord_prefix + in_grace = 1 + elif not c.grace and lastch and lastch.grace: + lastch.chord_suffix = lastch.chord_suffix + ' } ' + in_grace = 0 + + lastch = c + + if lastch and in_grace: + lastch.chord_suffix += '}' + + + def dump (self): + str = '%% FR(%d)\n' % self.number + left = self.measure.global_measure.length () + + + ln = '' + for c in self.chords: + add = c.ly_string () + ' ' + if len (ln) + len(add) > 72: + str = str + ln + '\n' + ln = '' + ln = ln + add + left = rat_subtract (left, c.length ()) + + str = str + ln + + if left[0] < 0: + sys.stderr.write ("""\nHuh? Going backwards in frame no %d, start/end (%d,%d)""" % (self.number, self.start, self.end)) + left = (0,1) + if left[0]: + str = str + rational_to_lily_skip (left) + + str = str + ' |\n' + return str + def encodeint (i): - return chr ( i + ord ('A')) + return chr ( i + ord ('A')) class Staff: - def __init__ (self, number): - self.number = number - self.measures = [] - - def get_measure (self, no): - fill_list_to (self.measures, no) - - if self.measures[no] == None: - m = Measure (no) - self.measures [no] =m - m.staff = self - - return self.measures[no] - def staffid (self): - return 'staff' + encodeint (self.number - 1) - def layerid (self, l): - return self.staffid() + 'layer%s' % chr (l -1 + ord ('A')) - - def dump_time_key_sigs (self): - k = '' - last_key = None - last_time = None - last_clef = None - gap = (0,1) - for m in self.measures[1:]: - if not m or not m.valid: - continue # ugh. - - g = m.global_measure - e = '' - - if g: - if last_key <> g.key_signature: - pitch= g.key_signature - e = e + "\\key %s \\major " % (lily_notename (pitch)) - - last_key = g.key_signature - if last_time <> g.timesig : - e = e + "\\time %d/%d " % g.timesig - last_time = g.timesig - - if 'start' in g.repeats: - e = e + ' \\bar "|:" ' - - - # we don't attempt voltas since they fail easily. - if 0 : # and g.repeat_bar == '|:' or g.repeat_bar == ':|:' or g.bracket: - strs = [] - if g.repeat_bar == '|:' or g.repeat_bar == ':|:' or g.bracket == 'end': - strs.append ('#f') - - - if g.bracket == 'start': - strs.append ('"0."') - - str = string.join (map (lambda x: '(volta %s)' % x, strs)) - - e = e + ' \\property Score.repeatCommands = #\'(%s) ' % str - - if g.force_break: - e = e + ' \\break ' - - if last_clef <> m.clef : - e = e + '\\clef "%s"' % lily_clef (m.clef) - last_clef = m.clef - if e: - if gap <> (0,1): - k = k +' ' + rat_to_lily_duration (gap) + '\n' - gap = (0,1) - k = k + e - - if g: - gap = rat_add (gap, g.length ()) - if 'stop' in g.repeats: - k = k + ' \\bar ":|" ' - - k = '%sglobal = \\notes { %s }\n\n ' % (self.staffid (), k) - return k - - def dump (self): - str = '' - - - layerids = [] - for x in range (1,5): # 4 layers. - laystr = '' - last_frame = None - first_frame = None - gap = (0,1) - for m in self.measures[1:]: - if not m or not m.valid: - sys.stderr.write ("Skipping non-existant or invalid measure\n") - continue - - fr = None - try: - fr = m.frames[x] - except IndexError: - sys.stderr.write ("Skipping nonexistent frame %d\n" % x) - laystr = laystr + "%% non existent frame %d (skipped) \n" % x - if fr: - first_frame = fr - if gap <> (0,1): - laystr = laystr +'} %s {\n ' % rat_to_lily_duration (gap) - gap = (0,1) - laystr = laystr + fr.dump () - else: - if m.global_measure : - gap = rat_add (gap, m.global_measure.length ()) - else: - sys.stderr.write ( \ - "No global measure for staff %d measure %d\n" - % (self.number, m.number)) - if first_frame: - l = self.layerid (x) - laystr = '%s = \\notes { { %s } }\n\n' % (l, laystr) - str = str + laystr - layerids.append (l) - - str = str + self.dump_time_key_sigs () - stafdef = '\\%sglobal' % self.staffid () - for i in layerids: - stafdef = stafdef + ' \\' + i - - - str = str + '%s = \\context Staff = %s <\n %s\n >\n' % \ - (self.staffid (), self.staffid (), stafdef) - return str - - + def __init__ (self, number): + self.number = number + self.measures = [] + + def get_measure (self, no): + fill_list_to (self.measures, no) + + if self.measures[no] == None: + m = Measure (no) + self.measures [no] =m + m.staff = self + + return self.measures[no] + def staffid (self): + return 'staff' + encodeint (self.number - 1) + def layerid (self, l): + return self.staffid() + 'layer%s' % chr (l -1 + ord ('A')) + + def dump_time_key_sigs (self): + k = '' + last_key = None + last_time = None + last_clef = None + gap = (0,1) + for m in self.measures[1:]: + if not m or not m.valid: + continue # ugh. + + g = m.global_measure + e = '' + + if g: + if g.key_signature and not g.key_signature.equal(last_key): + pitch= g.key_signature.pitch + e = e + "\\key %s %s " % (lily_notename (pitch), + g.key_signature.signature_type()) + + last_key = g.key_signature + if last_time <> g.timesig : + e = e + "\\time %d/%d " % g.timesig + last_time = g.timesig + + if 'start' in g.repeats: + e = e + ' \\bar ".|:" ' + + + # we don't attempt voltas since they fail easily. + if 0 : # and g.repeat_bar == '|:' or g.repeat_bar == ':|:' or g.bracket: + strs = [] + if g.repeat_bar == '|:' or g.repeat_bar == ':|:' or g.bracket == 'end': + strs.append ('#f') + + + if g.bracket == 'start': + strs.append ('"0."') + + str = ' '.join (['(volta %s)' % x for x in strs]) + + e = e + ' \\set Score.repeatCommands = #\'(%s) ' % str + + if g.force_break: + e = e + ' \\break ' + + if last_clef <> m.clef : + e = e + '\\clef "%s"' % lily_clef (m.clef) + last_clef = m.clef + if e: + if gap <> (0,1): + k = k +' ' + rational_to_lily_skip (gap) + '\n' + gap = (0,1) + k = k + e + + if g: + gap = rat_add (gap, g.length ()) + if 'stop' in g.repeats: + k = k + ' \\bar ":|." ' + + k = '%sglobal = { %s }\n\n ' % (self.staffid (), k) + return k + + def dump (self): + str = '' + + + layerids = [] + for x in range (1,5): # 4 layers. + laystr = '' + last_frame = None + first_frame = None + gap = (0,1) + for m in self.measures[1:]: + if not m or not m.valid: + sys.stderr.write ("Skipping non-existant or invalid measure\n") + continue + + fr = None + try: + fr = m.frames[x] + except IndexError: + sys.stderr.write ("Skipping nonexistent frame %d\n" % x) + laystr = laystr + "%% non existent frame %d (skipped)\n" % x + if fr: + first_frame = fr + if gap <> (0,1): + laystr = laystr +'} %s {\n ' % rational_to_lily_skip (gap) + gap = (0,1) + laystr = laystr + fr.dump () + else: + if m.global_measure : + gap = rat_add (gap, m.global_measure.length ()) + else: + sys.stderr.write ( \ + "No global measure for staff %d measure %d\n" + % (self.number, m.number)) + if first_frame: + l = self.layerid (x) + laystr = '%s = { { %s } }\n\n' % (l, laystr) + str = str + laystr + layerids.append (l) + + str = str + self.dump_time_key_sigs () + stafdef = '\\%sglobal' % self.staffid () + for i in layerids: + stafdef = stafdef + ' \\' + i + + + str = str + '%s = \\context Staff = %s <<\n %s\n >>\n' % \ + (self.staffid (), self.staffid (), stafdef) + return str + + def ziplist (l): - if len (l) < 2: - return [] - else: - return [(l[0], l[1])] + ziplist (l[2:]) + if len (l) < 2: + return [] + else: + return [(l[0], l[1])] + ziplist (l[2:]) class Chord: - def __init__ (self, number, contents): - self.pitches = [] - self.frame = None - self.finale = contents[:7] - - self.notelist = ziplist (contents[7:]) - self.duration = None - self.next = None - self.prev = None - self.number = number - self.note_prefix= '' - self.note_suffix = '' - self.chord_suffix = '' - self.chord_prefix = '' - self.tuplet = None - self.grace = 0 - - def measure (self): - if not self.frame: - return None - return self.frame.measure - - def length (self): - if self.grace: - return (0,1) - - l = (1, self.duration[0]) - - d = 1 << self.duration[1] - - dotfact = rat_subtract ((2,1), (1,d)) - mylen = rat_multiply (dotfact, l) - - if self.tuplet: - mylen = rat_multiply (mylen, self.tuplet.factor()) - return mylen - - - def EDU_duration (self): - return self.finale[2] - def set_duration (self): - self.duration = EDU_to_duration(self.EDU_duration ()) - - def calculate (self): - self.find_realpitch () - self.set_duration () - - flag = self.finale[4] - if Chord.GRACE_MASK & flag: - self.grace = 1 - - - def find_realpitch (self): - - meas = self.measure () - tiestart = 0 - if not meas or not meas.global_measure : - sys.stderr.write ('note %d not in measure\n' % self.number) - elif not meas.global_measure.scale: - sys.stderr.write ('note %d: no scale in this measure.' % self.number) - else: - - for p in self.notelist: - (pitch, flag) = p - - - nib1 = pitch & 0x0f - - if nib1 > 8: - nib1 = -(nib1 - 8) - rest = pitch / 16 - - scale = meas.global_measure.scale - (sn, sa) =scale[rest % 7] - sn = sn + (rest - (rest%7)) + 7 - acc = sa + nib1 - self.pitches.append ((sn, acc)) - tiestart = tiestart or (flag & Chord.TIE_START_MASK) - if tiestart : - self.chord_suffix = self.chord_suffix + ' ~ ' - - REST_MASK = 0x40000000L - TIE_START_MASK = 0x40000000L - GRACE_MASK = 0x00800000L - - def ly_string (self): - s = '' - - rest = '' - - - if not (self.finale[4] & Chord.REST_MASK): - rest = 'r' - - for p in self.pitches: - (n,a) = p - o = n/ 7 - n = n % 7 - - nn = lily_notename ((n,a)) - - if o < 0: - nn = nn + (',' * -o) - elif o > 0: - nn = nn + ('\'' * o) - - if s: - s = s + ' ' - - if rest: - nn = rest - - s = s + nn - - if not self.pitches: - s = 'r' - if len (self.pitches) > 1: - s = '<< %s >>' % s - - s = s + '%d%s' % (self.duration[0], '.'* self.duration[1]) - s = self.note_prefix + s + self.note_suffix - - s = self.chord_prefix + s + self.chord_suffix - - return s + def __init__ (self, number, contents): + self.pitches = [] + self.frame = None + self.finale = contents[:7] + + self.notelist = ziplist (contents[7:]) + self.duration = None + self.next = None + self.prev = None + self.number = number + self.note_prefix= '' + self.note_suffix = '' + self.chord_suffix = '' + self.chord_prefix = '' + self.tuplet = None + self.grace = 0 + + def measure (self): + if not self.frame: + return None + return self.frame.measure + + def length (self): + if self.grace: + return (0,1) + + l = (1, self.duration[0]) + + d = 1 << self.duration[1] + + dotfact = rat_subtract ((2,1), (1,d)) + mylen = rat_multiply (dotfact, l) + + if self.tuplet: + mylen = rat_multiply (mylen, self.tuplet.factor()) + return mylen + + + def EDU_duration (self): + return self.finale[2] + def set_duration (self): + self.duration = EDU_to_duration(self.EDU_duration ()) + + def calculate (self): + self.find_realpitch () + self.set_duration () + + flag = self.finale[4] + if Chord.GRACE_MASK & flag: + self.grace = 1 + + + def find_realpitch (self): + + meas = self.measure () + tiestart = 0 + if not meas or not meas.global_measure : + sys.stderr.write ('note %d not in measure\n' % self.number) + elif not meas.global_measure.scale: + sys.stderr.write ('note %d: no scale in this measure.' % self.number) + else: + + for p in self.notelist: + (pitch, flag) = p + + + nib1 = pitch & 0x0f + + if nib1 > 8: + nib1 = -(nib1 - 8) + rest = pitch / 16 + + scale = meas.global_measure.scale + (sn, sa) =scale[rest % 7] + sn = sn + (rest - (rest%7)) + 7 + acc = sa + nib1 + self.pitches.append ((sn, acc)) + tiestart = tiestart or (flag & Chord.TIE_START_MASK) + if tiestart : + self.chord_suffix = self.chord_suffix + ' ~ ' + + REST_MASK = 0x40000000L + TIE_START_MASK = 0x40000000L + GRACE_MASK = 0x00800000L + + def ly_string (self): + s = '' + + rest = '' + + + if not (self.finale[4] & Chord.REST_MASK): + rest = 'r' + + for p in self.pitches: + (n,a) = p + o = n/ 7 + n = n % 7 + + nn = lily_notename ((n,a)) + + if o < 0: + nn = nn + (',' * -o) + elif o > 0: + nn = nn + ('\'' * o) + + if s: + s = s + ' ' + + if rest: + nn = rest + + s = s + nn + + if not self.pitches: + s = 'r' + if len (self.pitches) > 1: + s = '<%s>' % s + + s = s + '%d%s' % (self.duration[0], '.'* self.duration[1]) + s = self.note_prefix + s + self.note_suffix + + s = self.chord_prefix + s + self.chord_suffix + + return s def fill_list_to (list, no): - """ + """ Add None to LIST until it contains entry number NO. - """ - while len (list) <= no: - list.extend ([None] * (no - len(list) + 1)) - return list + """ + while len (list) <= no: + list.extend ([None] * (no - len(list) + 1)) + return list def read_finale_value (str): - """ + """ Pry off one value from STR. The value may be $hex, decimal, or "string". Return: (value, rest-of-STR) - """ - while str and str[0] in ' \t\n': - str = str[1:] - - if not str: - return (None,str) - - if str[0] == '$': - str = str [1:] - - hex = '' - while str and str[0] in '0123456789ABCDEF': - hex = hex + str[0] - str = str[1:] - - - return (string.atol (hex, 16), str) - elif str[0] == '"': - str = str[1:] - s = '' - while str and str[0] <> '"': - s = s + str[0] - str = str[1:] - - return (s,str) - elif str[0] in '-0123456789': - dec = '' - while str and str[0] in '-0123456789': - dec = dec + str[0] - str = str[1:] - - return (string.atoi (dec), str) - else: - sys.stderr.write ("Can't convert `%s'\n" % str) - return (None, str) - - - - + """ + while str and str[0] in ' \t\n': + str = str[1:] + + if not str: + return (None,str) + + if str[0] == '$': + str = str [1:] + + hex = '' + while str and str[0] in '0123456789ABCDEF': + hex = hex + str[0] + str = str[1:] + + + return (long (hex, 16), str) + elif str[0] == '"': + str = str[1:] + s = '' + while str and str[0] <> '"': + s = s + str[0] + str = str[1:] + + return (s,str) + elif str[0] in '-0123456789': + dec = '' + while str and str[0] in '-0123456789': + dec = dec + str[0] + str = str[1:] + + return (int (dec), str) + else: + sys.stderr.write ("cannot convert `%s'\n" % str) + return (None, str) + + + + def parse_etf_file (fn, tag_dict): - """ Read FN, putting ETF info into - a giant dictionary. The keys of TAG_DICT indicate which tags - to put into the dict. - """ - - sys.stderr.write ('parsing ... ' ) - f = open (fn) - - gulp = re.sub ('[\n\r]+', '\n', f.read ()) - ls = string.split (gulp, '\n^') + """ Read FN, putting ETF info into + a giant dictionary. The keys of TAG_DICT indicate which tags + to put into the dict. + """ + + sys.stderr.write ('parsing ... ' ) + f = open (fn) + + gulp = re.sub ('[\n\r]+', '\n', f.read ()) + ls = gulp.split ('\n^') - etf_file_dict = {} - for k in tag_dict.keys (): - etf_file_dict[k] = {} + etf_file_dict = {} + for k in tag_dict: + etf_file_dict[k] = {} - last_tag = None - last_numbers = None + last_tag = None + last_numbers = None - for l in ls: - m = re.match ('^([a-zA-Z0-9&]+)\(([^)]+)\)', l) - if m and tag_dict.has_key (m.group (1)): - tag = m.group (1) + for l in ls: + m = re.match ('^([a-zA-Z0-9&]+)\(([^)]+)\)', l) + if m and tag_dict.has_key (m.group (1)): + tag = m.group (1) - indices = tuple (map (string.atoi, string.split (m.group (2), ','))) - content = l[m.end (2)+1:] + indices = tuple ([int (s) for s in m.group (2).split (',')]) + content = l[m.end (2)+1:] - tdict = etf_file_dict[tag] - if not tdict.has_key (indices): - tdict[indices] = [] + tdict = etf_file_dict[tag] + if not tdict.has_key (indices): + tdict[indices] = [] - parsed = [] + parsed = [] - if tag == 'verse' or tag == 'block': - m2 = re.match ('(.*)\^end', content) - if m2: - parsed = [m2.group (1)] - else: - while content: - (v, content) = read_finale_value (content) - if v <> None: - parsed.append (v) + if tag == 'verse' or tag == 'block': + m2 = re.match ('(.*)\^end', content) + if m2: + parsed = [m2.group (1)] + else: + while content: + (v, content) = read_finale_value (content) + if v <> None: + parsed.append (v) - tdict [indices].extend (parsed) + tdict [indices].extend (parsed) - last_indices = indices - last_tag = tag + last_indices = indices + last_tag = tag - continue + continue # let's not do this: this really confuses when eE happens to be before a ^text. -# if last_tag and last_indices: -# etf_file_dict[last_tag][last_indices].append (l) - - sys.stderr.write ('\n') - return etf_file_dict +# if last_tag and last_indices: +# etf_file_dict[last_tag][last_indices].append (l) + + sys.stderr.write ('\n') + return etf_file_dict - + class Etf_file: - def __init__ (self, name): - self.measures = [None] - self.chords = [None] - self.frames = [None] - self.tuplets = [None] - self.staffs = [None] - self.slurs = [None] - self.articulations = [None] - self.syllables = [None] - self.verses = [None] - self.articulation_defs = [None] - - ## do it - self.parse (name) - - def get_global_measure (self, no): - fill_list_to (self.measures, no) - if self.measures[no] == None: - self.measures [no] = Global_measure (no) - - return self.measures[no] - - - def get_staff(self,staffno): - fill_list_to (self.staffs, staffno) - if self.staffs[staffno] == None: - self.staffs[staffno] = Staff (staffno) - - return self.staffs[staffno] - - # staff-spec - def try_IS (self, indices, contents): - pass - - def try_BC (self, indices, contents): - bn = indices[0] - where = contents[0] / 1024.0 - def try_TP(self, indices, contents): - (nil, num) = indices - - if self.tuplets[-1] == None or num <> self.tuplets[-1].start_note: - self.tuplets.append (Tuplet (num)) - - self.tuplets[-1].append_finale (contents) - - def try_IM (self, indices, contents): - (a,b) = indices - fin = contents - self.articulations.append (Articulation (a,b,fin)) - def try_verse (self, indices, contents): - a = indices[0] - body = contents[0] - - body = re.sub (r"""\^[a-z]+\([^)]+\)""", "", body) - body = re.sub ("\^[a-z]+", "", body) - self.verses.append (Verse (a, body)) - def try_ve (self,indices, contents): - (a,b) = indices - self.syllables.append (Syllable (a,b,contents)) - - def try_eE (self,indices, contents): - no = indices[0] - (prev, next, dur, pos, entryflag, extended, follow) = contents[:7] - - fill_list_to (self.chords, no) - self.chords[no] =Chord (no, contents) - - def try_Sx(self,indices, contents): - slurno = indices[0] - fill_list_to (self.slurs, slurno) - self.slurs[slurno] = Slur(slurno, contents) - - def try_IX (self, indices, contents): - n = indices[0] - a = contents[0] - b = contents[1] - - ix= None - try: - ix = self.articulation_defs[n] - except IndexError: - ix = Articulation_def (n,a,b) - self.articulation_defs.append (Articulation_def (n, a, b)) - - def try_GF(self, indices, contents): - (staffno,measno) = indices - - st = self.get_staff (staffno) - meas = st.get_measure (measno) - meas.finale = contents - - def try_FR(self, indices, contents): - frameno = indices [0] - - startnote = contents[0] - endnote = contents[1] - - fill_list_to (self.frames, frameno) - - self.frames[frameno] = Frame ((frameno, startnote, endnote)) - - def try_MS (self, indices, contents): - measno = indices[0] - keynum = contents[1] - meas =self. get_global_measure (measno) - - meas.set_key_sig (keynum) - - beats = contents[2] - beatlen = contents[3] - meas.set_timesig ((beats, beatlen)) - - meas_flag1 = contents[4] - meas_flag2 = contents[5] - - meas.set_flags (meas_flag1, meas_flag2); - - - routine_dict = { - 'MS': try_MS, - 'FR': try_FR, - 'GF': try_GF, - 'IX': try_IX, - 'Sx' : try_Sx, - 'eE' : try_eE, - 'verse' : try_verse, - 've' : try_ve, - 'IM' : try_IM, - 'TP' : try_TP, - 'BC' : try_BC, - 'IS' : try_IS, - } - - def parse (self, etf_dict): - sys.stderr.write ('reconstructing ...') - sys.stderr.flush () - - for (tag,routine) in Etf_file.routine_dict.items (): - ks = etf_dict[tag].keys () - ks.sort () - for k in ks: - routine (self, k, etf_dict[tag][k]) - - sys.stderr.write ('processing ...') - sys.stderr.flush () - - self.unthread_entries () - - for st in self.staffs[1:]: - if not st: - continue - mno = 1 - for m in st.measures[1:]: - if not m: - continue - - m.calculate() - try: - m.global_measure = self.measures[mno] - except IndexError: - sys.stderr.write ("Non-existent global measure %d" % mno) - continue - - frame_obj_list = [None] - for frno in m.frames: - try: - fr = self.frames[frno] - frame_obj_list.append (fr) - except IndexError: - sys.stderr.write ("\nNon-existent frame %d" % frno) - - m.frames = frame_obj_list - for fr in frame_obj_list[1:]: - if not fr: - continue - - fr.set_measure (m) - - fr.chords = self.get_thread (fr.start, fr.end) - for c in fr.chords: - c.frame = fr - mno = mno + 1 - - for c in self.chords[1:]: - if c: - c.calculate() - - for f in self.frames[1:]: - if f: - f.calculate () - - for t in self.tuplets[1:]: - t.calculate (self.chords) - - for s in self.slurs[1:]: - if s: - s.calculate (self.chords) - - for s in self.articulations[1:]: - s.calculate (self.chords, self.articulation_defs) - - def get_thread (self, startno, endno): - - thread = [] - - c = None - try: - c = self.chords[startno] - except IndexError: - sys.stderr.write ("Huh? Frame has invalid bounds (%d,%d)\n" % (startno, endno)) - return [] - - - while c and c.number <> endno: - thread.append (c) - c = c.next - - if c: - thread.append (c) - - return thread - - def dump (self): - str = '' - staffs = [] - for s in self.staffs[1:]: - if s: - str = str + '\n\n' + s.dump () - staffs.append ('\\' + s.staffid ()) - - - # should use \addlyrics ? - - for v in self.verses[1:]: - str = str + v.dump() - - if len (self.verses) > 1: - sys.stderr.write ("\nLyrics found; edit to use \\addlyrics to couple to a staff\n") - - if staffs: - str = str + '\\score { < %s > } ' % string.join (staffs) - - return str - - - def __str__ (self): - return 'ETF FILE %s %s' % (self.measures, self.entries) - - def unthread_entries (self): - for e in self.chords[1:]: - if not e: - continue - - e.prev = self.chords[e.finale[0]] - e.next = self.chords[e.finale[1]] + def __init__ (self, name): + self.measures = [None] + self.chords = [None] + self.frames = [None] + self.tuplets = [None] + self.staffs = [None] + self.slurs = [None] + self.articulations = [None] + self.syllables = [None] + self.verses = [None] + self.articulation_defs = [None] + + ## do it + self.parse (name) + + def get_global_measure (self, no): + fill_list_to (self.measures, no) + if self.measures[no] == None: + self.measures [no] = Global_measure (no) + + return self.measures[no] + + + def get_staff(self,staffno): + fill_list_to (self.staffs, staffno) + if self.staffs[staffno] == None: + self.staffs[staffno] = Staff (staffno) + + return self.staffs[staffno] + + # staff-spec + def try_IS (self, indices, contents): + pass + + def try_BC (self, indices, contents): + bn = indices[0] + where = contents[0] / 1024.0 + def try_TP(self, indices, contents): + (nil, num) = indices + + if self.tuplets[-1] == None or num <> self.tuplets[-1].start_note: + self.tuplets.append (Tuplet (num)) + + self.tuplets[-1].append_finale (contents) + + def try_IM (self, indices, contents): + (a,b) = indices + fin = contents + self.articulations.append (Articulation (a,b,fin)) + def try_verse (self, indices, contents): + a = indices[0] + body = contents[0] + + body = re.sub (r"""\^[a-z]+\([^)]+\)""", "", body) + body = re.sub ("\^[a-z]+", "", body) + self.verses.append (Verse (a, body)) + def try_ve (self,indices, contents): + (a,b) = indices + self.syllables.append (Syllable (a,b,contents)) + + def try_eE (self,indices, contents): + no = indices[0] + (prev, next, dur, pos, entryflag, extended, follow) = contents[:7] + + fill_list_to (self.chords, no) + self.chords[no] =Chord (no, contents) + + def try_Sx(self,indices, contents): + slurno = indices[0] + fill_list_to (self.slurs, slurno) + self.slurs[slurno] = Slur(slurno, contents) + + def try_IX (self, indices, contents): + n = indices[0] + a = contents[0] + b = contents[1] + + ix= None + try: + ix = self.articulation_defs[n] + except IndexError: + ix = Articulation_def (n,a,b) + self.articulation_defs.append (Articulation_def (n, a, b)) + + def try_GF(self, indices, contents): + (staffno,measno) = indices + + st = self.get_staff (staffno) + meas = st.get_measure (measno) + meas.finale = contents + + def try_FR(self, indices, contents): + frameno = indices [0] + + startnote = contents[0] + endnote = contents[1] + + fill_list_to (self.frames, frameno) + + self.frames[frameno] = Frame ((frameno, startnote, endnote)) + + def try_MS (self, indices, contents): + measno = indices[0] + keynum = contents[1] + meas =self. get_global_measure (measno) + + meas.set_key_sig (keynum) + + beats = contents[2] + beatlen = contents[3] + meas.set_timesig ((beats, beatlen)) + + meas_flag1 = contents[4] + meas_flag2 = contents[5] + + meas.set_flags (meas_flag1, meas_flag2); + + + routine_dict = { + 'MS': try_MS, + 'FR': try_FR, + 'GF': try_GF, + 'IX': try_IX, + 'Sx' : try_Sx, + 'eE' : try_eE, + 'verse' : try_verse, + 've' : try_ve, + 'IM' : try_IM, + 'TP' : try_TP, + 'BC' : try_BC, + 'IS' : try_IS, + } + + def parse (self, etf_dict): + sys.stderr.write ('reconstructing ...') + sys.stderr.flush () + + for (tag,routine) in Etf_file.routine_dict.items (): + ks = etf_dict[tag].keys () + ks.sort () + for k in ks: + routine (self, k, etf_dict[tag][k]) + + sys.stderr.write ('processing ...') + sys.stderr.flush () + + self.unthread_entries () + + for st in self.staffs[1:]: + if not st: + continue + mno = 1 + for m in st.measures[1:]: + if not m: + continue + + m.calculate() + try: + m.global_measure = self.measures[mno] + except IndexError: + sys.stderr.write ("Non-existent global measure %d" % mno) + continue + + frame_obj_list = [None] + for frno in m.frames: + try: + fr = self.frames[frno] + frame_obj_list.append (fr) + except IndexError: + sys.stderr.write ("\nNon-existent frame %d" % frno) + + m.frames = frame_obj_list + for fr in frame_obj_list[1:]: + if not fr: + continue + + fr.set_measure (m) + + fr.chords = self.get_thread (fr.start, fr.end) + for c in fr.chords: + c.frame = fr + mno = mno + 1 + + for c in self.chords[1:]: + if c: + c.calculate() + + for f in self.frames[1:]: + if f: + f.calculate () + + for t in self.tuplets[1:]: + t.calculate (self.chords) + + for s in self.slurs[1:]: + if s: + s.calculate (self.chords) + + for s in self.articulations[1:]: + s.calculate (self.chords, self.articulation_defs) + + def get_thread (self, startno, endno): + + thread = [] + + c = None + try: + c = self.chords[startno] + except IndexError: + sys.stderr.write ("Huh? Frame has invalid bounds (%d,%d)\n" % (startno, endno)) + return [] + + + while c and c.number <> endno: + d = c # hack to avoid problem with scripts/build/grand-replace.py + thread.append (d) + c = c.next + + if c: + d = c # hack to avoid problem with scripts/build/grand-replace.py + thread.append (d) + + return thread + + def dump (self): + str = '' + staffs = [] + for s in self.staffs[1:]: + if s: + str = str + '\n\n' + s.dump () + staffs.append ('\\' + s.staffid ()) + + + # should use \addlyrics ? + + for v in self.verses[1:]: + str = str + v.dump() + + if len (self.verses) > 1: + sys.stderr.write ("\nLyrics found; edit to use \\addlyrics to couple to a staff\n") + + if staffs: + str += '\\version "2.3.25"\n' + str = str + '<<\n %s\n>> } ' % ' '.join (staffs) + + return str + + + def __str__ (self): + return 'ETF FILE %s %s' % (self.measures, self.entries) + + def unthread_entries (self): + for e in self.chords[1:]: + if not e: + continue + + e.prev = self.chords[e.finale[0]] + e.next = self.chords[e.finale[1]] def identify(): - sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version)) - -def help (): - sys.stdout.write("""Usage: etf2ly [OPTION]... ETF-FILE - -Convert ETF to LilyPond. - -Options: - -h,--help print this help - -o,--output=FILE set output filename to FILE - -v,--version show version information - -Enigma Transport Format is a format used by Coda Music Technology's -Finale product. This program will convert a subset of ETF to a -ready-to-use lilypond file. - -Report bugs to bug-lilypond@gnu.org - -Written by Han-Wen Nienhuys -""") - -def print_version (): - sys.stdout.write (r"""etf2ly (GNU lilypond) %s - -This is free software. It is covered by the GNU General Public License, -and you are welcome to change it and/or distribute copies of it under -certain conditions. Invoke as `midi2ly --warranty' for more information. - -Copyright (c) 2000--2003 by Han-Wen Nienhuys -""" % version) - - - -(options, files) = getopt.getopt (sys.argv[1:], 'vo:h', ['help','version', 'output=']) -out_filename = None - -for opt in options: - o = opt[0] - a = opt[1] - if o== '--help' or o == '-h': - help () - sys.exit (0) - if o == '--version' or o == '-v': - print_version () - sys.exit(0) - - if o == '--output' or o == '-o': - out_filename = a - else: - print o - raise getopt.error - + sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version)) + +def warranty (): + identify () + sys.stdout.write (''' +%s + + %s + +%s +%s +''' % ( _ ('Copyright (c) %s by') % '2001--2015', + '\n '.join (authors), + _ ('Distributed under terms of the GNU General Public License.'), + _ ('It comes with NO WARRANTY.'))) + +def get_option_parser (): + p = ly.get_option_parser (usage=_ ("%s [OPTION]... ETF-FILE") % 'etf2ly', + description=_ ("""Enigma Transport Format is a format used by Coda Music Technology's +Finale product. etf2ly converts a subset of ETF to a ready-to-use LilyPond file. +"""), + add_help_option=False) + p.add_option("-h", "--help", + action="help", + help=_ ("show this help and exit")) + p.version = "etf2ly (LilyPond) @TOPLEVEL_VERSION@" + p.add_option("--version", + action="version", + help=_ ("show version number and exit")) + p.add_option ('-o', '--output', help=_ ("write output to FILE"), + metavar=_("FILE"), + action='store') + p.add_option ('-w', '--warranty', help=_ ("show warranty and copyright"), + action='store_true', + ), + + p.add_option_group ('', + description=( + _ ('Report bugs via %s') + % 'http://post.gmane.org/post.php' + '?group=gmane.comp.gnu.lilypond.bugs') + '\n') + return p + +def do_options (): + opt_parser = get_option_parser() + (options,args) = opt_parser.parse_args () + if options.warranty: + warranty () + sys.exit (0) + + return (options,args) + +(options, files) = do_options() identify() +out_filename = options.output + e = None for f in files: - if f == '-': - f = '' - - sys.stderr.write ('Processing `%s\'\n' % f) - - dict = parse_etf_file (f, Etf_file.routine_dict) - e = Etf_file(dict) - if not out_filename: - out_filename = os.path.basename (re.sub ('(?i).etf$', '.ly', f)) - - if out_filename == f: - out_filename = os.path.basename (f + '.ly') - - sys.stderr.write ('Writing `%s\'' % out_filename) - ly = e.dump() - - - - fo = open (out_filename, 'w') - fo.write ('%% lily was here -- automatically converted by etf2ly from %s\n' % f) - fo.write(ly) - fo.close () - + if f == '-': + f = '' + + sys.stderr.write ('Processing `%s\'\n' % f) + + dict = parse_etf_file (f, Etf_file.routine_dict) + e = Etf_file(dict) + if not out_filename: + out_filename = os.path.basename (re.sub ('(?i).etf$', '.ly', f)) + + if out_filename == f: + out_filename = os.path.basename (f + '.ly') + + sys.stderr.write ('Writing `%s\'' % out_filename) + ly = e.dump() + + fo = open (out_filename, 'w') + fo.write ('%% lily was here -- automatically converted by etf2ly from %s\n' % f) + fo.write(ly) + fo.close () +