]> git.donarmstrong.com Git - lilypond.git/commitdiff
(dump_score): indent of 4 for python code.
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Mon, 1 May 2006 00:00:24 +0000 (00:00 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Mon, 1 May 2006 00:00:24 +0000 (00:00 +0000)
ChangeLog
python/musicexp.py
scripts/abc2ly.py
scripts/etf2ly.py
scripts/lilypond-book.py
scripts/midi2ly.py
scripts/musicxml2ly.py

index 5ab363e9813340d21b85899c806bc8514812b5ad..4bb107f705a31b576ef4b06976aa223ecbf59af6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 2006-05-01  Han-Wen Nienhuys  <hanwen@lilypond.org>
 
+       * scripts/abc2ly.py (dump_score): indent of 4 for python code. 
+
        * configure.in (LINK_GXX_STATICALLY): remove locate() call.
 
 2006-04-30  Han-Wen Nienhuys  <hanwen@xs4all.nl>
index 5698c9f699ac870a06b3fba59929903bd13cd07f..2f54f36b7bf14ebd969251a1e35f15303814d36e 100644 (file)
@@ -6,683 +6,683 @@ import re
 from rational import Rational
 
 class Output_stack_element:
-       def __init__ (self):
-               self.factor = Rational (1)
-       def copy (self):
-               o = Output_stack_element()
-               o.factor = self.factor
-               return o
+    def __init__ (self):
+        self.factor = Rational (1)
+    def copy (self):
+        o = Output_stack_element()
+        o.factor = self.factor
+        return o
 
 class Output_printer:
 
-       """A class that takes care of formatting (eg.: indenting) a
-       Music expression as a .ly file.
-       
-       """
-       ## TODO: support for \relative.
-       
-       def __init__ (self):
-               self._line = ''
-               self._indent = 4
-               self._nesting = 0
-               self._file = sys.stdout
-               self._line_len = 72
-               self._output_state_stack = [Output_stack_element()]
-               self._skipspace = False
-               self._last_duration = None
-
-       def set_file (self, file):
-               self._file = file
-               
-       def dump_version (self):
-               self.newline ()
-               self.print_verbatim ('\\version "@TOPLEVEL_VERSION@"')
-               self.newline ()
-               
-       def get_indent (self):
-               return self._nesting * self._indent
-       
-       def override (self):
-               last = self._output_state_stack[-1]
-               self._output_state_stack.append (last.copy())
-               
-       def add_factor (self, factor):
-               self.override()
-               self._output_state_stack[-1].factor *=  factor
-
-       def revert (self):
-               del self._output_state_stack[-1]
-               if not self._output_state_stack:
-                       raise 'empty'
-
-       def duration_factor (self):
-               return self._output_state_stack[-1].factor
-
-       def print_verbatim (self, str):
-               self._line += str
-
-       def unformatted_output (self, str):
-               self._nesting += str.count ('<') + str.count ('{')
-               self._nesting -= str.count ('>') + str.count ('}')
-               self.print_verbatim (str)
-               
-       def print_duration_string (self, str):
-               if self._last_duration == str:
-                       return
-               
-               self.unformatted_output (str)
-                                    
-       def add_word (self, str):
-               if (len (str) + 1 + len (self._line) > self._line_len):
-                       self.newline()
-                       self._skipspace = True
-
-               if not self._skipspace:
-                       self._line += ' '
-               self.unformatted_output (str)
-               self._skipspace = False
-               
-       def newline (self):
-               self._file.write (self._line + '\n')
-               self._line = ' ' * self._indent * self._nesting
-               self._skipspace = True
-
-       def skipspace (self):
-               self._skipspace = True
-               
-       def __call__(self, arg):
-               self.dump (arg)
-       
-       def dump (self, str):
-               
-               if self._skipspace:
-                       self._skipspace = False
-                       self.unformatted_output (str)
-               else:
-                       words = string.split (str)
-                       for w in words:
-                               self.add_word (w)
+    """A class that takes care of formatting (eg.: indenting) a
+    Music expression as a .ly file.
+    
+    """
+    ## TODO: support for \relative.
+    
+    def __init__ (self):
+        self._line = ''
+        self._indent = 4
+        self._nesting = 0
+        self._file = sys.stdout
+        self._line_len = 72
+        self._output_state_stack = [Output_stack_element()]
+        self._skipspace = False
+        self._last_duration = None
+
+    def set_file (self, file):
+        self._file = file
+        
+    def dump_version (self):
+        self.newline ()
+        self.print_verbatim ('\\version "@TOPLEVEL_VERSION@"')
+        self.newline ()
+        
+    def get_indent (self):
+        return self._nesting * self._indent
+    
+    def override (self):
+        last = self._output_state_stack[-1]
+        self._output_state_stack.append (last.copy())
+        
+    def add_factor (self, factor):
+        self.override()
+        self._output_state_stack[-1].factor *=  factor
+
+    def revert (self):
+        del self._output_state_stack[-1]
+        if not self._output_state_stack:
+            raise 'empty'
+
+    def duration_factor (self):
+        return self._output_state_stack[-1].factor
+
+    def print_verbatim (self, str):
+        self._line += str
+
+    def unformatted_output (self, str):
+        self._nesting += str.count ('<') + str.count ('{')
+        self._nesting -= str.count ('>') + str.count ('}')
+        self.print_verbatim (str)
+        
+    def print_duration_string (self, str):
+        if self._last_duration == str:
+            return
+        
+        self.unformatted_output (str)
+                  
+    def add_word (self, str):
+        if (len (str) + 1 + len (self._line) > self._line_len):
+            self.newline()
+            self._skipspace = True
+
+        if not self._skipspace:
+            self._line += ' '
+        self.unformatted_output (str)
+        self._skipspace = False
+        
+    def newline (self):
+        self._file.write (self._line + '\n')
+        self._line = ' ' * self._indent * self._nesting
+        self._skipspace = True
+
+    def skipspace (self):
+        self._skipspace = True
+        
+    def __call__(self, arg):
+        self.dump (arg)
+    
+    def dump (self, str):
+        
+        if self._skipspace:
+            self._skipspace = False
+            self.unformatted_output (str)
+        else:
+            words = string.split (str)
+            for w in words:
+                self.add_word (w)
 
 class Duration:
-       def __init__ (self):
-               self.duration_log = 0
-               self.dots = 0
-               self.factor = Rational (1)
-               
-       def lisp_expression (self):
-               return '(ly:make-duration %d %d %d %d)' % (self.duration_log,
-                                                          self.dots,
-                                                          self.factor.numerator (),
-                                                          self.factor.denominator ())
-
-
-       def ly_expression (self, factor = None):
-               if not factor:
-                       factor = self.factor
-                       
-               str = '%d%s' % (1 << self.duration_log, '.'*self.dots)
-
-               if factor <> Rational (1,1):
-                       str += '*%d/%d' % (factor.numerator (), factor.denominator ())
-
-               return str
-       
-       def print_ly (self, outputter):
-               str = self.ly_expression (self.factor / outputter.duration_factor ())
-               outputter.print_duration_string (str)
-               
-       def __repr__(self):
-               return self.ly_expression()
-               
-       def copy (self):
-               d = Duration ()
-               d.dots = self.dots
-               d.duration_log = self.duration_log
-               d.factor = self.factor
-               return d
-
-       def get_length (self):
-               dot_fact = Rational( (1 << (1 + self.dots))-1,
-                                    1 << self.dots)
-
-               log = abs (self.duration_log)
-               dur = 1 << log
-               if self.duration_log < 0:
-                       base = Rational (dur)
-               else:
-                       base = Rational (1, dur)
-
-               return base * dot_fact * self.factor
-
-       
+    def __init__ (self):
+        self.duration_log = 0
+        self.dots = 0
+        self.factor = Rational (1)
+        
+    def lisp_expression (self):
+        return '(ly:make-duration %d %d %d %d)' % (self.duration_log,
+                             self.dots,
+                             self.factor.numerator (),
+                             self.factor.denominator ())
+
+
+    def ly_expression (self, factor = None):
+        if not factor:
+            factor = self.factor
+            
+        str = '%d%s' % (1 << self.duration_log, '.'*self.dots)
+
+        if factor <> Rational (1,1):
+            str += '*%d/%d' % (factor.numerator (), factor.denominator ())
+
+        return str
+    
+    def print_ly (self, outputter):
+        str = self.ly_expression (self.factor / outputter.duration_factor ())
+        outputter.print_duration_string (str)
+        
+    def __repr__(self):
+        return self.ly_expression()
+        
+    def copy (self):
+        d = Duration ()
+        d.dots = self.dots
+        d.duration_log = self.duration_log
+        d.factor = self.factor
+        return d
+
+    def get_length (self):
+        dot_fact = Rational( (1 << (1 + self.dots))-1,
+                  1 << self.dots)
+
+        log = abs (self.duration_log)
+        dur = 1 << log
+        if self.duration_log < 0:
+            base = Rational (dur)
+        else:
+            base = Rational (1, dur)
+
+        return base * dot_fact * self.factor
+
+    
 class Pitch:
-       def __init__ (self):
-               self.alteration = 0
-               self.step = 0
-               self.octave = 0
-               
-       def __repr__(self):
-               return self.ly_expression()
-
-       def transposed (self, interval):
-               c = self.copy ()
-               c.alteration  += interval.alteration
-               c.step += interval.step
-               c.octave += interval.octave
-               c.normalize ()
-               
-               target_st = self.semitones()  + interval.semitones()
-               c.alteration += target_st - c.semitones()
-               return c
-
-       def normalize (c):
-               while c.step < 0:
-                       c.step += 7
-                       c.octave -= 1
-               c.octave += c.step / 7
-               c.step = c.step  % 7
-
-       
-       def lisp_expression (self):
-               return '(ly:make-pitch %d %d %d)' % (self.octave,
-                                                    self.step,
-                                                    self.alteration)
-
-       def copy (self):
-               p = Pitch ()
-               p.alteration = self.alteration
-               p.step = self.step
-               p.octave = self.octave 
-               return p
-
-       def steps (self):
-               return self.step + self.octave *7
-
-       def semitones (self):
-               return self.octave * 12 + [0,2,4,5,7,9,11][self.step] + self.alteration
-       
-       def ly_step_expression (self): 
-               str = 'cdefgab'[self.step]
-               if self.alteration > 0:
-                       str += 'is'* (self.alteration)
-               elif self.alteration < 0:
-                       str += 'es'* (-self.alteration)
-
-               return str.replace ('aes', 'as').replace ('ees', 'es')
-       
-       def ly_expression (self):
-               str = self.ly_step_expression ()
-               if self.octave >= 0:
-                       str += "'" * (self.octave + 1) 
-               elif self.octave < -1:
-                       str += "," * (-self.octave - 1) 
-                       
-               return str
-       def print_ly (self, outputter):
-               outputter (self.ly_expression())
-       
+    def __init__ (self):
+        self.alteration = 0
+        self.step = 0
+        self.octave = 0
+        
+    def __repr__(self):
+        return self.ly_expression()
+
+    def transposed (self, interval):
+        c = self.copy ()
+        c.alteration  += interval.alteration
+        c.step += interval.step
+        c.octave += interval.octave
+        c.normalize ()
+        
+        target_st = self.semitones()  + interval.semitones()
+        c.alteration += target_st - c.semitones()
+        return c
+
+    def normalize (c):
+        while c.step < 0:
+            c.step += 7
+            c.octave -= 1
+        c.octave += c.step / 7
+        c.step = c.step  % 7
+
+    
+    def lisp_expression (self):
+        return '(ly:make-pitch %d %d %d)' % (self.octave,
+                          self.step,
+                          self.alteration)
+
+    def copy (self):
+        p = Pitch ()
+        p.alteration = self.alteration
+        p.step = self.step
+        p.octave = self.octave 
+        return p
+
+    def steps (self):
+        return self.step + self.octave *7
+
+    def semitones (self):
+        return self.octave * 12 + [0,2,4,5,7,9,11][self.step] + self.alteration
+    
+    def ly_step_expression (self): 
+        str = 'cdefgab'[self.step]
+        if self.alteration > 0:
+            str += 'is'* (self.alteration)
+        elif self.alteration < 0:
+            str += 'es'* (-self.alteration)
+
+        return str.replace ('aes', 'as').replace ('ees', 'es')
+    
+    def ly_expression (self):
+        str = self.ly_step_expression ()
+        if self.octave >= 0:
+            str += "'" * (self.octave + 1) 
+        elif self.octave < -1:
+            str += "," * (-self.octave - 1) 
+            
+        return str
+    def print_ly (self, outputter):
+        outputter (self.ly_expression())
+    
 class Music:
-       def __init__ (self):
-               self.parent = None
-               self.start = Rational (0)
-               self.comment = ''
-               self.identifier = None
-               
-       def get_length(self):
-               return Rational (0)
-       
-       def get_properties (self):
-               return ''
-       
-       def has_children (self):
-               return False
-       
-       def get_index (self):
-               if self.parent:
-                       return self.parent.elements.index (self)
-               else:
-                       return None
-       def name (self):
-               return self.__class__.__name__
-       
-       def lisp_expression (self):
-               name = self.name()
-
-               props = self.get_properties ()
-#              props += 'start %f ' % self.start
-               
-               return "(make-music '%s %s)" % (name,  props)
-
-       def set_start (self, start):
-               self.start = start
-
-       def find_first (self, predicate):
-               if predicate (self):
-                       return self
-               return None
-
-       def print_comment (self, printer, text = None):
-               if not text:
-                       text = self.comment
-
-               if not text:
-                       return
-
-                       
-               if text == '\n':
-                       printer.newline ()
-                       return
-               lines = string.split (text, '\n')
-               for l in lines:
-                       if l:
-                               printer.dump ('% ' + l)
-                       printer.newline ()
-                       
-
-       def print_with_identifier (self, printer):
-               if self.identifier: 
-                       printer ("\\%s" % self.identifier)
-               else:
-                       self.print_ly (printer)
-
-       def print_ly (self, printer):
-               printer (self.ly_expression ())
+    def __init__ (self):
+        self.parent = None
+        self.start = Rational (0)
+        self.comment = ''
+        self.identifier = None
+        
+    def get_length(self):
+        return Rational (0)
+    
+    def get_properties (self):
+        return ''
+    
+    def has_children (self):
+        return False
+    
+    def get_index (self):
+        if self.parent:
+            return self.parent.elements.index (self)
+        else:
+            return None
+    def name (self):
+        return self.__class__.__name__
+    
+    def lisp_expression (self):
+        name = self.name()
+
+        props = self.get_properties ()
+#                props += 'start %f ' % self.start
+        
+        return "(make-music '%s %s)" % (name,  props)
+
+    def set_start (self, start):
+        self.start = start
+
+    def find_first (self, predicate):
+        if predicate (self):
+            return self
+        return None
+
+    def print_comment (self, printer, text = None):
+        if not text:
+            text = self.comment
+
+        if not text:
+            return
+
+            
+        if text == '\n':
+            printer.newline ()
+            return
+        lines = string.split (text, '\n')
+        for l in lines:
+            if l:
+                printer.dump ('% ' + l)
+            printer.newline ()
+            
+
+    def print_with_identifier (self, printer):
+        if self.identifier: 
+            printer ("\\%s" % self.identifier)
+        else:
+            self.print_ly (printer)
+
+    def print_ly (self, printer):
+        printer (self.ly_expression ())
 
 class MusicWrapper (Music):
-       def __init__ (self):
-               Music.__init__(self)
-               self.element = None
-       def print_ly (self, func):
-               self.element.print_ly (func)
+    def __init__ (self):
+        Music.__init__(self)
+        self.element = None
+    def print_ly (self, func):
+        self.element.print_ly (func)
 
 class TimeScaledMusic (MusicWrapper):
-       def print_ly (self, func):
-               func ('\\times %d/%d ' %
-                     (self.numerator, self.denominator))
-               func.add_factor (Rational (self.numerator, self.denominator))
-               MusicWrapper.print_ly (self, func)
-               func.revert ()
+    def print_ly (self, func):
+        func ('\\times %d/%d ' %
+           (self.numerator, self.denominator))
+        func.add_factor (Rational (self.numerator, self.denominator))
+        MusicWrapper.print_ly (self, func)
+        func.revert ()
 
 class NestedMusic(Music):
-       def __init__ (self):
-               Music.__init__ (self)
-               self.elements = []
-
-       def append (self, what):
-               if what:
-                       self.elements.append (what)
-                       
-       def has_children (self):
-               return self.elements
-
-       def insert_around (self, succ, elt, dir):
-               assert elt.parent == None
-               assert succ == None or succ in self.elements
-
-               
-               idx = 0
-               if succ:
-                       idx = self.elements.index (succ)
-                       if dir > 0:
-                               idx += 1
-               else:
-                       if dir < 0:
-                               idx = 0
-                       elif dir > 0:
-                               idx = len (self.elements)
-
-               self.elements.insert (idx, elt)
-               elt.parent = self
-               
-       def get_properties (self):
-               return ("'elements (list %s)"
-                       % string.join (map (lambda x: x.lisp_expression(),
-                                           self.elements)))
-
-       def get_subset_properties (self, predicate):
-               return ("'elements (list %s)"
-                       % string.join (map (lambda x: x.lisp_expression(),
-                                           filter ( predicate,  self.elements))))
-       def get_neighbor (self, music, dir):
-               assert music.parent == self
-               idx = self.elements.index (music)
-               idx += dir
-               idx = min (idx, len (self.elements) -1)
-               idx = max (idx, 0)
-
-               return self.elements[idx]
-
-       def delete_element (self, element):
-               assert element in self.elements
-               
-               self.elements.remove (element)
-               element.parent = None
-               
-       def set_start (self, start):
-               self.start = start
-               for e in self.elements:
-                       e.set_start (start)
-
-       def find_first (self, predicate):
-               r = Music.find_first (self, predicate)
-               if r:
-                       return r
-               
-               for e in self.elements:
-                       r = e.find_first (predicate)
-                       if r:
-                               return r
-               return None
-               
+    def __init__ (self):
+        Music.__init__ (self)
+        self.elements = []
+
+    def append (self, what):
+        if what:
+            self.elements.append (what)
+            
+    def has_children (self):
+        return self.elements
+
+    def insert_around (self, succ, elt, dir):
+        assert elt.parent == None
+        assert succ == None or succ in self.elements
+
+        
+        idx = 0
+        if succ:
+            idx = self.elements.index (succ)
+            if dir > 0:
+                idx += 1
+        else:
+            if dir < 0:
+                idx = 0
+            elif dir > 0:
+                idx = len (self.elements)
+
+        self.elements.insert (idx, elt)
+        elt.parent = self
+        
+    def get_properties (self):
+        return ("'elements (list %s)"
+            % string.join (map (lambda x: x.lisp_expression(),
+                      self.elements)))
+
+    def get_subset_properties (self, predicate):
+        return ("'elements (list %s)"
+            % string.join (map (lambda x: x.lisp_expression(),
+                      filter ( predicate,  self.elements))))
+    def get_neighbor (self, music, dir):
+        assert music.parent == self
+        idx = self.elements.index (music)
+        idx += dir
+        idx = min (idx, len (self.elements) -1)
+        idx = max (idx, 0)
+
+        return self.elements[idx]
+
+    def delete_element (self, element):
+        assert element in self.elements
+        
+        self.elements.remove (element)
+        element.parent = None
+        
+    def set_start (self, start):
+        self.start = start
+        for e in self.elements:
+            e.set_start (start)
+
+    def find_first (self, predicate):
+        r = Music.find_first (self, predicate)
+        if r:
+            return r
+        
+        for e in self.elements:
+            r = e.find_first (predicate)
+            if r:
+                return r
+        return None
+        
 class SequentialMusic (NestedMusic):
-       def print_ly (self, printer):
-               printer ('{')
-               if self.comment:
-                       self.print_comment (printer)
-
-               printer.newline()
-               for e in self.elements:
-                       e.print_ly (printer)
-
-               printer ('}')
-               printer.newline()
-                       
-       def lisp_sub_expression (self, pred):
-               name = self.name()
-
-
-               props = self.get_subset_properties (pred)
-               
-               return "(make-music '%s %s)" % (name,  props)
-       
-       def set_start (self, start):
-               for e in self.elements:
-                       e.set_start (start)
-                       start += e.get_length()
-                       
+    def print_ly (self, printer):
+        printer ('{')
+        if self.comment:
+            self.print_comment (printer)
+
+        printer.newline()
+        for e in self.elements:
+            e.print_ly (printer)
+
+        printer ('}')
+        printer.newline()
+            
+    def lisp_sub_expression (self, pred):
+        name = self.name()
+
+
+        props = self.get_subset_properties (pred)
+        
+        return "(make-music '%s %s)" % (name,  props)
+    
+    def set_start (self, start):
+        for e in self.elements:
+            e.set_start (start)
+            start += e.get_length()
+            
 class EventChord(NestedMusic):
-       def get_length (self):
-               l = Rational (0)
-               for e in self.elements:
-                       l = max(l, e.get_length())
-               return l
-       
-       def print_ly (self, printer):
-               note_events = [e for e in self.elements if
-                              isinstance (e, NoteEvent)]
-
-               rest_events = [e for e in self.elements if
-                              isinstance (e, RhythmicEvent)
-                              and not isinstance (e, NoteEvent)]
-               
-               other_events = [e for e in self.elements if
-                               not isinstance (e, RhythmicEvent)]
-
-               if rest_events:
-                       rest_events[0].print_ly (printer)
-               elif len (note_events) == 1:
-                       note_events[0].print_ly (printer)
-               elif note_events:
-                       pitches = [x.pitch.ly_expression () for x in note_events]
-                       printer ('<%s>' % string.join (pitches))
-                       note_events[0].duration.print_ly (printer)
-               else:
-                       pass
-               
-               #       print  'huh', rest_events, note_events, other_events
-               for e in other_events:
-                       e.print_ly (printer)
-
-               self.print_comment (printer)
-                       
+    def get_length (self):
+        l = Rational (0)
+        for e in self.elements:
+            l = max(l, e.get_length())
+        return l
+    
+    def print_ly (self, printer):
+        note_events = [e for e in self.elements if
+               isinstance (e, NoteEvent)]
+
+        rest_events = [e for e in self.elements if
+               isinstance (e, RhythmicEvent)
+               and not isinstance (e, NoteEvent)]
+        
+        other_events = [e for e in self.elements if
+                not isinstance (e, RhythmicEvent)]
+
+        if rest_events:
+            rest_events[0].print_ly (printer)
+        elif len (note_events) == 1:
+            note_events[0].print_ly (printer)
+        elif note_events:
+            pitches = [x.pitch.ly_expression () for x in note_events]
+            printer ('<%s>' % string.join (pitches))
+            note_events[0].duration.print_ly (printer)
+        else:
+            pass
+        
+               print  'huh', rest_events, note_events, other_events
+        for e in other_events:
+            e.print_ly (printer)
+
+        self.print_comment (printer)
+            
 class Event(Music):
-       pass
+    pass
 
 class SpanEvent (Event):
-       def __init__(self):
-               Event.__init__ (self)
-               self.span_direction = 0
-       def get_properties(self):
-               return "'span-direction  %d" % self.span_direction
-       
+    def __init__(self):
+        Event.__init__ (self)
+        self.span_direction = 0
+    def get_properties(self):
+        return "'span-direction  %d" % self.span_direction
+    
 class SlurEvent (SpanEvent):
-       def ly_expression (self):
-               return {-1: '(',
-                       0:'',
-                       1:')'}[self.span_direction]
+    def ly_expression (self):
+        return {-1: '(',
+            0:'',
+            1:')'}[self.span_direction]
 
 class BeamEvent (SpanEvent):
-       def ly_expression (self):
-               return {-1: '[',
-                       0:'',
-                       1:']'}[self.span_direction]
+    def ly_expression (self):
+        return {-1: '[',
+            0:'',
+            1:']'}[self.span_direction]
 
 class ArpeggioEvent(Event):
-       def ly_expression (self):
-               return ('\\arpeggio')
+    def ly_expression (self):
+        return ('\\arpeggio')
 
 
 class TieEvent(Event):
-       def ly_expression (self):
-               return '~'
+    def ly_expression (self):
+        return '~'
 
-       
+    
 class RhythmicEvent(Event):
-       def __init__ (self):
-               Event.__init__ (self)
-               self.duration = Duration()
-               
-       def get_length (self):
-               return self.duration.get_length()
-               
-       def get_properties (self):
-               return ("'duration %s"
-                       % self.duration.lisp_expression ())
-       
+    def __init__ (self):
+        Event.__init__ (self)
+        self.duration = Duration()
+        
+    def get_length (self):
+        return self.duration.get_length()
+        
+    def get_properties (self):
+        return ("'duration %s"
+            % self.duration.lisp_expression ())
+    
 class RestEvent (RhythmicEvent):
-       def ly_expression (self):
-               return 'r%s' % self.duration.ly_expression ()
-       
-       def print_ly (self, printer):
-               printer('r')
-               self.duration.print_ly (printer)
+    def ly_expression (self):
+        return 'r%s' % self.duration.ly_expression ()
+    
+    def print_ly (self, printer):
+        printer('r')
+        self.duration.print_ly (printer)
 
 class SkipEvent (RhythmicEvent):
-       def ly_expression (self):
-               return 's%s' % self.duration.ly_expression () 
+    def ly_expression (self):
+        return 's%s' % self.duration.ly_expression () 
 
 class NoteEvent(RhythmicEvent):
-       def  __init__ (self):
-               RhythmicEvent.__init__ (self)
-               self.pitch = Pitch()
-               self.cautionary = False
-               self.forced_accidental = False
-               
-       def get_properties (self):
-               return ("'pitch %s\n 'duration %s"
-                       % (self.pitch.lisp_expression (),
-                          self.duration.lisp_expression ()))
-
-       def pitch_mods (self):
-               excl_question = ''
-               if self.cautionary:
-                       excl_question += '?'
-               if self.forced_accidental:
-                       excl_question += '!'
-
-               return excl_question
-       
-       def ly_expression (self):
-               return '%s%s%s' % (self.pitch.ly_expression (),
-                                  self.pitch_mods(),
-                                  self.duration.ly_expression ())
-
-       def print_ly (self, printer):
-               self.pitch.print_ly (printer)
-               printer (self.pitch_mods ())  
-               self.duration.print_ly (printer)
+    def  __init__ (self):
+        RhythmicEvent.__init__ (self)
+        self.pitch = Pitch()
+        self.cautionary = False
+        self.forced_accidental = False
+        
+    def get_properties (self):
+        return ("'pitch %s\n 'duration %s"
+            % (self.pitch.lisp_expression (),
+             self.duration.lisp_expression ()))
+
+    def pitch_mods (self):
+        excl_question = ''
+        if self.cautionary:
+            excl_question += '?'
+        if self.forced_accidental:
+            excl_question += '!'
+
+        return excl_question
+    
+    def ly_expression (self):
+        return '%s%s%s' % (self.pitch.ly_expression (),
+                 self.pitch_mods(),
+                 self.duration.ly_expression ())
+
+    def print_ly (self, printer):
+        self.pitch.print_ly (printer)
+        printer (self.pitch_mods ())  
+        self.duration.print_ly (printer)
 
 class KeySignatureChange (Music):
-       def __init__ (self):
-               Music.__init__ (self)
-               self.scale = []
-               self.tonic = Pitch()
-               self.mode = 'major'
-               
-       def ly_expression (self):
-               return '\\key %s \\%s' % (self.tonic.ly_step_expression (),
-                                         self.mode)
-       
-       def lisp_expression (self):
-               pairs = ['(%d . %d)' % (i , self.scale[i]) for i in range (0,7)]
-               scale_str = ("'(%s)" % string.join (pairs))
-
-               return """ (make-music 'KeyChangeEvent
-          'pitch-alist %s) """ % scale_str
+    def __init__ (self):
+        Music.__init__ (self)
+        self.scale = []
+        self.tonic = Pitch()
+        self.mode = 'major'
+        
+    def ly_expression (self):
+        return '\\key %s \\%s' % (self.tonic.ly_step_expression (),
+                     self.mode)
+    
+    def lisp_expression (self):
+        pairs = ['(%d . %d)' % (i , self.scale[i]) for i in range (0,7)]
+        scale_str = ("'(%s)" % string.join (pairs))
+
+        return """ (make-music 'KeyChangeEvent
+     'pitch-alist %s) """ % scale_str
 
 class TimeSignatureChange (Music):
-       def __init__ (self):
-               Music.__init__ (self)
-               self.fraction = (4,4)
-       def ly_expression (self):
-               return '\\time %d/%d ' % self.fraction
-       
+    def __init__ (self):
+        Music.__init__ (self)
+        self.fraction = (4,4)
+    def ly_expression (self):
+        return '\\time %d/%d ' % self.fraction
+    
 class ClefChange (Music):
-       def __init__ (self):
-               Music.__init__ (self)
-               self.type = 'G'
-               
-       
-       def ly_expression (self):
-               return '\\clef "%s"' % self.type
-       clef_dict = {
-               "G": ("clefs.G", -2, -6),
-               "C": ("clefs.C", 0, 0),
-               "F": ("clefs.F", 2, 6),
-               }
-       
-       def lisp_expression (self):
-               (glyph, pos, c0) = self.clef_dict [self.type]
-               clefsetting = """
-               (make-music 'SequentialMusic
-               'elements (list
-      (context-spec-music
-       (make-property-set 'clefGlyph "%s") 'Staff)
-      (context-spec-music
-       (make-property-set 'clefPosition %d) 'Staff)
-      (context-spec-music
-       (make-property-set 'middleCPosition %d) 'Staff)))
+    def __init__ (self):
+        Music.__init__ (self)
+        self.type = 'G'
+        
+    
+    def ly_expression (self):
+        return '\\clef "%s"' % self.type
+    clef_dict = {
+        "G": ("clefs.G", -2, -6),
+        "C": ("clefs.C", 0, 0),
+        "F": ("clefs.F", 2, 6),
+        }
+    
+    def lisp_expression (self):
+        (glyph, pos, c0) = self.clef_dict [self.type]
+        clefsetting = """
+        (make-music 'SequentialMusic
+        'elements (list
+   (context-spec-music
+   (make-property-set 'clefGlyph "%s") 'Staff)
+   (context-spec-music
+   (make-property-set 'clefPosition %d) 'Staff)
+   (context-spec-music
+   (make-property-set 'middleCPosition %d) 'Staff)))
 """ % (glyph, pos, c0)
-               return clefsetting
+        return clefsetting
 
 
 def test_pitch ():
-       bflat = Pitch()
-       bflat.alteration = -1
-       bflat.step =  6
-       bflat.octave = -1
-       fifth = Pitch()
-       fifth.step = 4
-       down = Pitch ()
-       down.step = -4
-       down.normalize ()
-       
-       
-       print bflat.semitones()
-       print bflat.transposed (fifth),  bflat.transposed (fifth).transposed (fifth)
-       print bflat.transposed (fifth).transposed (fifth).transposed (fifth)
-
-       print bflat.semitones(), 'down'
-       print bflat.transposed (down)
-       print bflat.transposed (down).transposed (down)
-       print bflat.transposed (down).transposed (down).transposed (down)
+    bflat = Pitch()
+    bflat.alteration = -1
+    bflat.step =  6
+    bflat.octave = -1
+    fifth = Pitch()
+    fifth.step = 4
+    down = Pitch ()
+    down.step = -4
+    down.normalize ()
+    
+    
+    print bflat.semitones()
+    print bflat.transposed (fifth),  bflat.transposed (fifth).transposed (fifth)
+    print bflat.transposed (fifth).transposed (fifth).transposed (fifth)
+
+    print bflat.semitones(), 'down'
+    print bflat.transposed (down)
+    print bflat.transposed (down).transposed (down)
+    print bflat.transposed (down).transposed (down).transposed (down)
 
 
 
 def test_printer ():
-       def make_note ():
-               evc = EventChord()
-               n = NoteEvent()
-               evc.append (n)
-               return n
-
-       def make_tup ():
-               m = SequentialMusic()
-               m.append (make_note ())
-               m.append (make_note ())
-               m.append (make_note ())
-
-               
-               t = TimeScaledMusic ()
-               t.numerator = 2
-               t.denominator = 3
-               t.element = m
-               return t
-
-       m = SequentialMusic ()
-       m.append (make_tup ())
-       m.append (make_tup ())
-       m.append (make_tup ())
-       
-       printer = Output_printer()
-       m.print_ly (printer)
-       printer.newline ()
-       
+    def make_note ():
+        evc = EventChord()
+        n = NoteEvent()
+        evc.append (n)
+        return n
+
+    def make_tup ():
+        m = SequentialMusic()
+        m.append (make_note ())
+        m.append (make_note ())
+        m.append (make_note ())
+
+        
+        t = TimeScaledMusic ()
+        t.numerator = 2
+        t.denominator = 3
+        t.element = m
+        return t
+
+    m = SequentialMusic ()
+    m.append (make_tup ())
+    m.append (make_tup ())
+    m.append (make_tup ())
+    
+    printer = Output_printer()
+    m.print_ly (printer)
+    printer.newline ()
+    
 def test_expr ():
-       m = SequentialMusic()
-       l = 2  
-       evc = EventChord()
-       n = NoteEvent()
-       n.duration.duration_log = l
-       n.pitch.step = 1
-       evc.insert_around (None, n, 0)
-       m.insert_around (None, evc, 0)
-
-       evc = EventChord()
-       n = NoteEvent()
-       n.duration.duration_log = l
-       n.pitch.step = 3
-       evc.insert_around (None, n, 0)
-       m.insert_around (None, evc, 0)
-
-       evc = EventChord()
-       n = NoteEvent()
-       n.duration.duration_log = l
-       n.pitch.step = 2 
-       evc.insert_around (None, n, 0)
-       m.insert_around (None, evc, 0)
-
-       evc = ClefChange()
-       evc.type = 'treble'
-       m.insert_around (None, evc, 0)
-
-       evc = EventChord()
-       tonic = Pitch ()
-       tonic.step = 2
-       tonic.alteration = -2
-       n = KeySignatureChange()
-       n.tonic=tonic.copy()
-       n.scale = [0, 0, -2, 0, 0,-2,-2]
-       
-       evc.insert_around (None, n, 0)
-       m.insert_around (None, evc, 0)
-
-       return m
+    m = SequentialMusic()
+    l = 2  
+    evc = EventChord()
+    n = NoteEvent()
+    n.duration.duration_log = l
+    n.pitch.step = 1
+    evc.insert_around (None, n, 0)
+    m.insert_around (None, evc, 0)
+
+    evc = EventChord()
+    n = NoteEvent()
+    n.duration.duration_log = l
+    n.pitch.step = 3
+    evc.insert_around (None, n, 0)
+    m.insert_around (None, evc, 0)
+
+    evc = EventChord()
+    n = NoteEvent()
+    n.duration.duration_log = l
+    n.pitch.step = 2 
+    evc.insert_around (None, n, 0)
+    m.insert_around (None, evc, 0)
+
+    evc = ClefChange()
+    evc.type = 'treble'
+    m.insert_around (None, evc, 0)
+
+    evc = EventChord()
+    tonic = Pitch ()
+    tonic.step = 2
+    tonic.alteration = -2
+    n = KeySignatureChange()
+    n.tonic=tonic.copy()
+    n.scale = [0, 0, -2, 0, 0,-2,-2]
+    
+    evc.insert_around (None, n, 0)
+    m.insert_around (None, evc, 0)
+
+    return m
 
 
 if __name__ == '__main__':
-       test_printer ()
-       raise 'bla'
-       test_pitch()
-       
-       expr = test_expr()
-       expr.set_start (Rational (0))
-       print expr.ly_expression()
-       start = Rational (0,4)
-       stop = Rational (4,2)
-       def sub(x, start=start, stop=stop):
-               ok = x.start >= start and x.start +x.get_length() <= stop
-               return ok
-       
-       print expr.lisp_sub_expression(sub)
+    test_printer ()
+    raise 'bla'
+    test_pitch()
+    
+    expr = test_expr()
+    expr.set_start (Rational (0))
+    print expr.ly_expression()
+    start = Rational (0,4)
+    stop = Rational (4,2)
+    def sub(x, start=start, stop=stop):
+        ok = x.start >= start and x.start +x.get_length() <= stop
+        return ok
+    
+    print expr.lisp_sub_expression(sub)
 
index 1257182f718cf0ae268b436a357c099d9b1c2086..664d73ec481ffebf47f1f8a640bc1d0759c7a177 100644 (file)
@@ -65,7 +65,7 @@
 #
 # UNDEF -> None
 #
-  
 
 import __main__
 import getopt
@@ -79,30 +79,30 @@ program_name = sys.argv[0]
 
 datadir = '@local_lilypond_datadir@'
 if not os.path.isdir (datadir):
-       datadir = '@lilypond_datadir@'
+    datadir = '@lilypond_datadir@'
 
 sys.path.insert (0, os.path.join (datadir, 'python'))
 
 if os.environ.has_key ('LILYPONDPREFIX'):
-       datadir = os.environ['LILYPONDPREFIX']
-       while datadir[-1] == os.sep:
-               datadir= datadir[:-1]
-               
-       datadir = os.path.join (datadir, "share/lilypond/current/")
+    datadir = os.environ['LILYPONDPREFIX']
+    while datadir[-1] == os.sep:
+        datadir= datadir[:-1]
+        
+    datadir = os.path.join (datadir, "share/lilypond/current/")
 sys.path.insert (0, os.path.join (datadir, 'python'))
 
 # dynamic relocation, for GUB binaries.
 bindir = os.path.split (sys.argv[0])[0]
 for p in ['share', 'lib']:
-       datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % p)
-       sys.path.insert (0, os.path.join (datadir))
+    datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % p)
+    sys.path.insert (0, os.path.join (datadir))
 
 import lilylib as ly
 global _;_=ly._
 
 version = '@TOPLEVEL_VERSION@'
 if version == '@' + 'TOPLEVEL_VERSION' + '@':
-       version = '(unknown version)'           # uGUHGUHGHGUGH  
+    version = '(unknown version)'                # uGUHGUHGHGUGH  
 
 UNDEF = 255
 state = UNDEF
@@ -121,7 +121,7 @@ part_names = 0
 default_len = 8
 length_specified = 0
 nobarlines = 0
-global_key = [0] * 7                   # UGH
+global_key = [0] * 7                        # UGH
 names = ["One", "Two", "Three"]
 DIGITS='0123456789'
 HSPACE=' \t'
@@ -129,959 +129,959 @@ midi_specs = ''
 
 
 def error (msg):
-       sys.stderr.write (msg)
-       if global_options.strict:
-               sys.exit (1)
-       
+    sys.stderr.write (msg)
+    if global_options.strict:
+        sys.exit (1)
+    
 
 def alphabet (i):
-       return chr (i + ord('A'))
-       
+    return chr (i + ord('A'))
+    
 def check_clef(s):
-       if not s:
-               return ''
-       if re.match('-8va', s) or re.match('treble8', s):
-               # treble8 is used by abctab2ps; -8va is used by barfly,
-               # and by my patch to abc2ps. If there's ever a standard
-               # about this we'll support that.
-               s = s[4:]
-               state.base_octave = -1
-               voices_append("\\clef \"G_8\"\n")
-       elif re.match('^treble', s):
-               s = s[6:]
-               if re.match ('^-8', s):
-                       s = s[2:]
-                       state.base_octave = -2
-                       voices_append("\\clef \"G_8\"\n")
-               else:
-                       state.base_octave = 0
-                       voices_append("\\clef treble\n")
-       elif re.match('^alto', s):
-               s = s[4:]
-               state.base_octave = -1
-               voices_append ("\\clef alto\n" )
-       elif re.match('^bass',s ):
-               s = s[4:]
-               state.base_octave = -2
-               voices_append ("\\clef bass\n" )
-       return s
+    if not s:
+        return ''
+    if re.match('-8va', s) or re.match('treble8', s):
+        # treble8 is used by abctab2ps; -8va is used by barfly,
+        # and by my patch to abc2ps. If there's ever a standard
+        # about this we'll support that.
+        s = s[4:]
+        state.base_octave = -1
+        voices_append("\\clef \"G_8\"\n")
+    elif re.match('^treble', s):
+        s = s[6:]
+        if re.match ('^-8', s):
+            s = s[2:]
+            state.base_octave = -2
+            voices_append("\\clef \"G_8\"\n")
+        else:
+            state.base_octave = 0
+            voices_append("\\clef treble\n")
+    elif re.match('^alto', s):
+        s = s[4:]
+        state.base_octave = -1
+        voices_append ("\\clef alto\n" )
+    elif re.match('^bass',s ):
+        s = s[4:]
+        state.base_octave = -2
+        voices_append ("\\clef bass\n" )
+    return s
 
 def select_voice (name, rol):
-       if not voice_idx_dict.has_key (name):
-               state_list.append(Parser_state())
-               voices.append ('')
-               slyrics.append ([])
-               voice_idx_dict[name] = len (voices) -1
-       __main__.current_voice_idx =  voice_idx_dict[name]
-       __main__.state = state_list[current_voice_idx]
-       while rol != '':
-               m = re.match ('^([^ \t=]*)=(.*)$', rol) # find keywork
-               if m:
-                       keyword = m.group(1)
-                       rol = m.group (2)
-                       a = re.match ('^("[^"]*"|[^ \t]*) *(.*)$', rol)
-                       if a:
-                               value = a.group (1)
-                               rol = a.group ( 2)
-                               if keyword == 'clef':
-                                       check_clef(value)
-                               elif keyword == "name":
-                                       value = re.sub ('\\\\','\\\\\\\\', value)
-                                       ## < 2.2
-                                       voices_append ("\\set Staff.instrument = %s\n" % value )
-                                       
-                                       __main__.part_names = 1
-                               elif keyword == "sname" or keyword == "snm":
-                                       voices_append ("\\set Staff.instr = %s\n" % value )
-               else:
-                       break
+    if not voice_idx_dict.has_key (name):
+        state_list.append(Parser_state())
+        voices.append ('')
+        slyrics.append ([])
+        voice_idx_dict[name] = len (voices) -1
+    __main__.current_voice_idx =  voice_idx_dict[name]
+    __main__.state = state_list[current_voice_idx]
+    while rol != '':
+        m = re.match ('^([^ \t=]*)=(.*)$', rol) # find keywork
+        if m:
+            keyword = m.group(1)
+            rol = m.group (2)
+            a = re.match ('^("[^"]*"|[^ \t]*) *(.*)$', rol)
+            if a:
+                value = a.group (1)
+                rol = a.group ( 2)
+                if keyword == 'clef':
+                    check_clef(value)
+                elif keyword == "name":
+                    value = re.sub ('\\\\','\\\\\\\\', value)
+                    ## < 2.2
+                    voices_append ("\\set Staff.instrument = %s\n" % value )
+                    
+                    __main__.part_names = 1
+                elif keyword == "sname" or keyword == "snm":
+                    voices_append ("\\set Staff.instr = %s\n" % value )
+        else:
+            break
 
 def dump_header (outf,hdr):
-       outf.write ('\\header {\n')
-       ks = hdr.keys ()
-       ks.sort ()
-       for k in ks:
-               hdr[k] = re.sub('"', '\\"', hdr[k])             
-               outf.write ('\t%s = "%s"\n'% (k,hdr[k]))
-       outf.write ('}')
+    outf.write ('\\header {\n')
+    ks = hdr.keys ()
+    ks.sort ()
+    for k in ks:
+        hdr[k] = re.sub('"', '\\"', hdr[k])                
+        outf.write ('\t%s = "%s"\n'% (k,hdr[k]))
+    outf.write ('}')
 
 def dump_lyrics (outf):
-       if (len(lyrics)):
-               outf.write("\n\\score\n{\n \\lyrics\n <<\n")
-               for i in range (len (lyrics)):
-                       outf.write ( lyrics [i])
-                       outf.write ("\n")
-               outf.write("    >>\n    \\layout{}\n}\n")
+    if (len(lyrics)):
+        outf.write("\n\\score\n{\n \\lyrics\n <<\n")
+        for i in range (len (lyrics)):
+            outf.write ( lyrics [i])
+            outf.write ("\n")
+        outf.write("    >>\n    \\layout{}\n}\n")
 
 def dump_default_bar (outf):
-       """
-       Nowadays abc2ly outputs explicits barlines (?)
-       """
-       ## < 2.2
-       outf.write ("\n\\set Score.defaultBarType = \"empty\"\n")
+    """
+    Nowadays abc2ly outputs explicits barlines (?)
+    """
+    ## < 2.2
+    outf.write ("\n\\set Score.defaultBarType = \"empty\"\n")
 
 
 def dump_slyrics (outf):
-       ks = voice_idx_dict.keys()
-       ks.sort ()
-       for k in ks:
-               if re.match('[1-9]', k):
-                       m = alphabet(string.atoi(k))
-               else:
-                       m = k
-               for i in range (len(slyrics[voice_idx_dict[k]])):
-                       l= alphabet(i)
-                       outf.write ("\nwords%sV%s = \lyricmode {" % (m, l))
-                       outf.write ("\n" + slyrics [voice_idx_dict[k]][i])
-                       outf.write ("\n}")
+    ks = voice_idx_dict.keys()
+    ks.sort ()
+    for k in ks:
+        if re.match('[1-9]', k):
+            m = alphabet(string.atoi(k))
+        else:
+            m = k
+        for i in range (len(slyrics[voice_idx_dict[k]])):
+            l= alphabet(i)
+            outf.write ("\nwords%sV%s = \lyricmode {" % (m, l))
+            outf.write ("\n" + slyrics [voice_idx_dict[k]][i])
+            outf.write ("\n}")
 
 def dump_voices (outf):
-       global doing_alternative, in_repeat
-       ks = voice_idx_dict.keys()
-       ks.sort ()
-       for k in ks:
-               if re.match ('[1-9]', k):
-                       m = alphabet(string.atoi(k))
-               else:
-                       m = k
-               outf.write ("\nvoice%s =  {" % m)
-               dump_default_bar(outf)
-               if repeat_state[voice_idx_dict[k]]:
-                       outf.write("\n\\repeat volta 2 {")
-               outf.write ("\n" + voices [voice_idx_dict[k]])
-               if not using_old:
-                       if doing_alternative[voice_idx_dict[k]]:
-                               outf.write("}")
-                       if in_repeat[voice_idx_dict[k]]:
-                               outf.write("}")
-               outf.write ("\n}")
+    global doing_alternative, in_repeat
+    ks = voice_idx_dict.keys()
+    ks.sort ()
+    for k in ks:
+        if re.match ('[1-9]', k):
+            m = alphabet(string.atoi(k))
+        else:
+            m = k
+        outf.write ("\nvoice%s =  {" % m)
+        dump_default_bar(outf)
+        if repeat_state[voice_idx_dict[k]]:
+            outf.write("\n\\repeat volta 2 {")
+        outf.write ("\n" + voices [voice_idx_dict[k]])
+        if not using_old:
+            if doing_alternative[voice_idx_dict[k]]:
+                outf.write("}")
+            if in_repeat[voice_idx_dict[k]]:
+                outf.write("}")
+        outf.write ("\n}")
 
 def try_parse_q(a):
-       global midi_specs
-       #assume that Q takes the form "Q:1/4=120"
-       #There are other possibilities, but they are deprecated
-       if string.count(a, '/') == 1:
-               array=string.split(a,'/')
-               numerator=array[0]
-               if numerator != 1:
-                       sys.stderr.write("abc2ly: Warning, unable to translate a Q specification with a numerator of %s: %s\n" % (numerator, a))
-               array2=string.split(array[1],'=')
-               denominator=array2[0]
-               perminute=array2[1]
-               duration=str(string.atoi(denominator)/string.atoi(numerator))
-               midi_specs=string.join(["\\tempo", duration, "=", perminute])
-       else:
-               sys.stderr.write("abc2ly: Warning, unable to parse Q specification: %s\n" % a)
-        
+    global midi_specs
+    #assume that Q takes the form "Q:1/4=120"
+    #There are other possibilities, but they are deprecated
+    if string.count(a, '/') == 1:
+        array=string.split(a,'/')
+        numerator=array[0]
+        if numerator != 1:
+            sys.stderr.write("abc2ly: Warning, unable to translate a Q specification with a numerator of %s: %s\n" % (numerator, a))
+        array2=string.split(array[1],'=')
+        denominator=array2[0]
+        perminute=array2[1]
+        duration=str(string.atoi(denominator)/string.atoi(numerator))
+        midi_specs=string.join(["\\tempo", duration, "=", perminute])
+    else:
+        sys.stderr.write("abc2ly: Warning, unable to parse Q specification: %s\n" % a)
+    
 def dump_score (outf):
-       outf.write (r"""
+    outf.write (r"""
 
 \score{
-         <<
+    <<
 """)
 
-       ks = voice_idx_dict.keys ();
-       ks.sort ()
-       for k in  ks:
-               if re.match('[1-9]', k):
-                       m = alphabet (string.atoi(k))
-               else:
-                       m = k
-               if k == 'default' and len (voice_idx_dict) > 1:
-                       break
-               outf.write ("\n\t\\context Staff=\"%s\"\n\t{\n" %k ) 
-               if k != 'default':
-                       outf.write ("\t    \\voicedefault\n")
-               outf.write ("\t    \\voice%s " % m)
-               outf.write ("\n\t}\n")
-
-               l = ord( 'A' )
-               for lyrics in slyrics [voice_idx_dict[k]]:
-                       outf.write ("\n\t\\addlyrics { \n")
-                       if re.match('[1-9]',k):
-                               m = alphabet (string.atoi(k))
-                       else:
-                               m = k
-
-                       outf.write ( " \\words%sV%s } " % ( m, chr (l)) )
-                       l += 1
-
-       outf.write ("\n    >>")
-       outf.write ("\n\t\\layout {\n")
-       outf.write ("\t}\n\t\\midi {%s}\n}\n" % midi_specs)
+    ks = voice_idx_dict.keys ();
+    ks.sort ()
+    for k in  ks:
+        if re.match('[1-9]', k):
+            m = alphabet (string.atoi(k))
+        else:
+            m = k
+        if k == 'default' and len (voice_idx_dict) > 1:
+            break
+        outf.write ("\n\t\\context Staff=\"%s\"\n\t{\n" %k ) 
+        if k != 'default':
+            outf.write ("\t    \\voicedefault\n")
+        outf.write ("\t    \\voice%s " % m)
+        outf.write ("\n\t}\n")
+
+        l = ord( 'A' )
+        for lyrics in slyrics [voice_idx_dict[k]]:
+            outf.write ("\n\t\\addlyrics { \n")
+            if re.match('[1-9]',k):
+                m = alphabet (string.atoi(k))
+            else:
+                m = k
+
+            outf.write ( " \\words%sV%s } " % ( m, chr (l)) )
+            l += 1
+
+    outf.write ("\n    >>")
+    outf.write ("\n\t\\layout {\n")
+    outf.write ("\t}\n\t\\midi {%s}\n}\n" % midi_specs)
 
 
 
 def set_default_length (s):
-       global length_specified
-       m =  re.search ('1/([0-9]+)', s)
-       if m:
-               __main__.default_len = string.atoi ( m.group (1))
-               length_specified = 1
+    global length_specified
+    m =  re.search ('1/([0-9]+)', s)
+    if m:
+        __main__.default_len = string.atoi ( m.group (1))
+        length_specified = 1
 
 def set_default_len_from_time_sig (s):
-       m =  re.search ('([0-9]+)/([0-9]+)', s)
-       if m:
-               n = string.atoi (m.group (1))
-               d = string.atoi (m.group (2))
-               if (n * 1.0 )/(d * 1.0) <  0.75:
-                       __main__.default_len =  16
-               else:
-                       __main__.default_len = 8
+    m =  re.search ('([0-9]+)/([0-9]+)', s)
+    if m:
+        n = string.atoi (m.group (1))
+        d = string.atoi (m.group (2))
+        if (n * 1.0 )/(d * 1.0) <  0.75:
+            __main__.default_len =  16
+        else:
+            __main__.default_len = 8
 
 def gulp_file(f):
-       try:
-               i = open(f)
-               i.seek (0, 2)
-               n = i.tell ()
-               i.seek (0,0)
-       except:
-               sys.stderr.write ("can't open file: `%s'\n" % f)
-               return ''
-       s = i.read (n)
-       if len (s) <= 0:
-               sys.stderr.write ("gulped empty file: `%s'\n" % f)
-       i.close ()
-       return s
+    try:
+        i = open(f)
+        i.seek (0, 2)
+        n = i.tell ()
+        i.seek (0,0)
+    except:
+        sys.stderr.write ("can't open file: `%s'\n" % f)
+        return ''
+    s = i.read (n)
+    if len (s) <= 0:
+        sys.stderr.write ("gulped empty file: `%s'\n" % f)
+    i.close ()
+    return s
 
 
 # pitch manipulation. Tuples are (name, alteration).
 # 0 is (central) C. Alteration -1 is a flat, Alteration +1 is a sharp
 # pitch in semitones. 
 def semitone_pitch  (tup):
-       p =0
-
-       t = tup[0]
-       p = p + 12 * (t / 7)
-       t = t % 7
-       
-       if t > 2:
-               p = p- 1
-               
-       p = p + t* 2 + tup[1]
-       return p
+    p =0
+
+    t = tup[0]
+    p = p + 12 * (t / 7)
+    t = t % 7
+    
+    if t > 2:
+        p = p- 1
+        
+    p = p + t* 2 + tup[1]
+    return p
 
 def fifth_above_pitch (tup):
-       (n, a)  = (tup[0] + 4, tup[1])
+    (n, a)  = (tup[0] + 4, tup[1])
 
-       difference = 7 - (semitone_pitch ((n,a)) - semitone_pitch (tup))
-       a = a + difference
-       
-       return (n,a)
+    difference = 7 - (semitone_pitch ((n,a)) - semitone_pitch (tup))
+    a = a + difference
+    
+    return (n,a)
 
 def sharp_keys ():
-       p = (0,0)
-       l = []
-       k = 0
-       while 1:
-               l.append (p)
-               (t,a) = fifth_above_pitch (p)
-               if semitone_pitch((t,a)) % 12 == 0:
-                       break
-
-               p = (t % 7, a)
-       return l
+    p = (0,0)
+    l = []
+    k = 0
+    while 1:
+        l.append (p)
+        (t,a) = fifth_above_pitch (p)
+        if semitone_pitch((t,a)) % 12 == 0:
+            break
+
+        p = (t % 7, a)
+    return l
 
 def flat_keys ():
-       p = (0,0)
-       l = []
-       k = 0
-       while 1:
-               l.append (p)
-               (t,a) = quart_above_pitch (p)
-               if semitone_pitch((t,a)) % 12 == 0:
-                       break
-
-               p = (t % 7, a)
-       return l
+    p = (0,0)
+    l = []
+    k = 0
+    while 1:
+        l.append (p)
+        (t,a) = quart_above_pitch (p)
+        if semitone_pitch((t,a)) % 12 == 0:
+            break
+
+        p = (t % 7, a)
+    return l
 
 def quart_above_pitch (tup):
-       (n, a)  = (tup[0] + 3, tup[1])
-
-       difference = 5 - (semitone_pitch ((n,a)) - semitone_pitch (tup))
-       a = a + difference
-       
-       return (n,a)
-
-key_lookup = {         # abc to lilypond key mode names
-       'm'   : 'minor',
-       'min' : 'minor',
-       'maj' : 'major',
-       'major' : 'major',      
-       'phr' : 'phrygian',
-       'ion' : 'ionian',
-       'loc' : 'locrian',
-       'aeo' : 'aeolian',
-       'mix' : 'mixolydian',
-       'mixolydian' : 'mixolydian',    
-       'lyd' : 'lydian',
-       'dor' : 'dorian',
-       'dorian' : 'dorian'     
+    (n, a)  = (tup[0] + 3, tup[1])
+
+    difference = 5 - (semitone_pitch ((n,a)) - semitone_pitch (tup))
+    a = a + difference
+    
+    return (n,a)
+
+key_lookup = {         # abc to lilypond key mode names
+    'm'   : 'minor',
+    'min' : 'minor',
+    'maj' : 'major',
+    'major' : 'major',        
+    'phr' : 'phrygian',
+    'ion' : 'ionian',
+    'loc' : 'locrian',
+    'aeo' : 'aeolian',
+    'mix' : 'mixolydian',
+    'mixolydian' : 'mixolydian',        
+    'lyd' : 'lydian',
+    'dor' : 'dorian',
+    'dorian' : 'dorian'        
 }
 
 def lily_key (k):
-       orig = "" + k
-       # UGR
-       k = string.lower (k)
-       key = k[0]
-       #UGH
-       k = k[1:]
-       if k and k[0] == '#':
-               key = key + 'is'
-               k = k[1:]
-       elif k and k[0] == 'b':
-               key = key + 'es'
-               k = k[1:]
-       if not k:
-               return '%s \\major' % key
-
-       type = k[0:3]
-       if not key_lookup.has_key (type):
-               #ugh, use lilylib, say WARNING:FILE:LINE:
-               sys.stderr.write ("abc2ly:warning:")
-               sys.stderr.write ("ignoring unknown key: `%s'" % orig)
-               sys.stderr.write ('\n')
-               return 0
-       return ("%s \\%s" % ( key, key_lookup[type]))
+    orig = "" + k
+    # UGR
+    k = string.lower (k)
+    key = k[0]
+    #UGH
+    k = k[1:]
+    if k and k[0] == '#':
+        key = key + 'is'
+        k = k[1:]
+    elif k and k[0] == 'b':
+        key = key + 'es'
+        k = k[1:]
+    if not k:
+        return '%s \\major' % key
+
+    type = k[0:3]
+    if not key_lookup.has_key (type):
+        #ugh, use lilylib, say WARNING:FILE:LINE:
+        sys.stderr.write ("abc2ly:warning:")
+        sys.stderr.write ("ignoring unknown key: `%s'" % orig)
+        sys.stderr.write ('\n')
+        return 0
+    return ("%s \\%s" % ( key, key_lookup[type]))
 
 def shift_key (note, acc, shift):
-       s = semitone_pitch((note, acc))
-       s = (s + shift + 12) % 12
-       if s <= 4:
-               n = s / 2
-               a = s % 2
-       else:
-               n = (s + 1) / 2
-               a = (s + 1) % 2
-       if a:
-               n = n + 1
-               a = -1
-       return (n,a)
+    s = semitone_pitch((note, acc))
+    s = (s + shift + 12) % 12
+    if s <= 4:
+        n = s / 2
+        a = s % 2
+    else:
+        n = (s + 1) / 2
+        a = (s + 1) % 2
+    if a:
+        n = n + 1
+        a = -1
+    return (n,a)
 
 key_shift = { # semitone shifts for key mode names
-       'm'   : 3,
-       'min' : 3,
-       'minor' : 3,
-       'maj' : 0,
-       'major' : 0,    
-       'phr' : -4,
-       'phrygian' : -4,
-       'ion' : 0,
-       'ionian' : 0,
-       'loc' : 1,
-       'locrian' : 1,  
-       'aeo' : 3,
-       'aeolian' : 3,
-       'mix' : 5,
-       'mixolydian' : 5,       
-       'lyd' : -5,
-       'lydian' : -5,  
-       'dor' : -2,
-       'dorian' :      -2      
+    'm'   : 3,
+    'min' : 3,
+    'minor' : 3,
+    'maj' : 0,
+    'major' : 0,        
+    'phr' : -4,
+    'phrygian' : -4,
+    'ion' : 0,
+    'ionian' : 0,
+    'loc' : 1,
+    'locrian' : 1,        
+    'aeo' : 3,
+    'aeolian' : 3,
+    'mix' : 5,
+    'mixolydian' : 5,        
+    'lyd' : -5,
+    'lydian' : -5,        
+    'dor' :        -2,
+    'dorian' :        -2        
 }
 def compute_key (k):
-       k = string.lower (k)
-       intkey = (ord (k[0]) - ord('a') + 5) % 7
-       intkeyacc =0
-       k = k[1:]
-       
-       if k and k[0] == 'b':
-               intkeyacc = -1
-               k = k[1:]
-       elif  k and k[0] == '#':
-               intkeyacc = 1
-               k = k[1:]
-       k = k[0:3]
-       if k and key_shift.has_key(k):
-               (intkey, intkeyacc) = shift_key(intkey, intkeyacc, key_shift[k])
-       keytup = (intkey, intkeyacc)
-       
-       sharp_key_seq = sharp_keys ()
-       flat_key_seq = flat_keys ()
-
-       accseq = None
-       accsign = 0
-       if keytup in sharp_key_seq:
-               accsign = 1
-               key_count = sharp_key_seq.index (keytup)
-               accseq = map (lambda x: (4*x -1 ) % 7, range (1, key_count + 1))
-
-       elif keytup in flat_key_seq:
-               accsign = -1
-               key_count = flat_key_seq.index (keytup)
-               accseq = map (lambda x: (3*x + 3 ) % 7, range (1, key_count + 1))
-       else:
-               error ("Huh?")
-               raise "Huh"
-       
-       key_table = [0] * 7
-       for a in accseq:
-                key_table[a] = key_table[a] + accsign
-
-       return key_table
+    k = string.lower (k)
+    intkey = (ord (k[0]) - ord('a') + 5) % 7
+    intkeyacc =0
+    k = k[1:]
+    
+    if k and k[0] == 'b':
+        intkeyacc = -1
+        k = k[1:]
+    elif  k and k[0] == '#':
+        intkeyacc = 1
+        k = k[1:]
+    k = k[0:3]
+    if k and key_shift.has_key(k):
+        (intkey, intkeyacc) = shift_key(intkey, intkeyacc, key_shift[k])
+    keytup = (intkey, intkeyacc)
+    
+    sharp_key_seq = sharp_keys ()
+    flat_key_seq = flat_keys ()
+
+    accseq = None
+    accsign = 0
+    if keytup in sharp_key_seq:
+        accsign = 1
+        key_count = sharp_key_seq.index (keytup)
+        accseq = map (lambda x: (4*x -1 ) % 7, range (1, key_count + 1))
+
+    elif keytup in flat_key_seq:
+        accsign = -1
+        key_count = flat_key_seq.index (keytup)
+        accseq = map (lambda x: (3*x + 3 ) % 7, range (1, key_count + 1))
+    else:
+        error ("Huh?")
+        raise "Huh"
+    
+    key_table = [0] * 7
+    for a in accseq:
+        key_table[a] = key_table[a] + accsign
+
+    return key_table
 
 tup_lookup = {
-       '2' : '3/2',
-       '3' : '2/3',
-       '4' : '4/3',
-       '5' : '4/5',
-       '6' : '4/6',
-       '7' : '6/7',
-       '9' : '8/9',
-       }
+    '2' : '3/2',
+    '3' : '2/3',
+    '4' : '4/3',
+    '5' : '4/5',
+    '6' : '4/6',
+    '7' : '6/7',
+    '9' : '8/9',
+    }
 
 
 def try_parse_tuplet_begin (str, state):
-       if re.match ('\([2-9]', str):
-               dig = str[1]
-               str = str[2:]
-               prev_tuplet_state = state.parsing_tuplet
-               state.parsing_tuplet = string.atoi (dig[0])
-               if prev_tuplet_state:
-                       voices_append ("}")             
-               voices_append ("\\times %s {" % tup_lookup[dig])
-       return str
+    if re.match ('\([2-9]', str):
+        dig = str[1]
+        str = str[2:]
+        prev_tuplet_state = state.parsing_tuplet
+         state.parsing_tuplet = string.atoi (dig[0])
+        if prev_tuplet_state:
+            voices_append ("}")                
+        voices_append ("\\times %s {" % tup_lookup[dig])
+    return str
 
 def  try_parse_group_end (str, state):
-       if str and str[0] in HSPACE:
-               str = str[1:]
-               close_beam_state(state)
-       return str
-       
+    if str and str[0] in HSPACE:
+        str = str[1:]
+        close_beam_state(state)
+    return str
+    
 def header_append (key, a):
-       s = ''
-       if header.has_key (key):
-               s = header[key] + "\n"
-               header [key] = s + a
+    s = ''
+    if header.has_key (key):
+        s = header[key] + "\n"
+        header [key] = s + a
 
 def wordwrap(a, v):
-       linelen = len (v) - string.rfind(v, '\n')
-       if linelen + len (a) > 80:
-               v = v + '\n'
-       return v + a + ' '
+    linelen = len (v) - string.rfind(v, '\n')
+    if linelen + len (a) > 80:
+        v = v + '\n'
+    return v + a + ' '
 
 def stuff_append (stuff, idx, a):
-       if not stuff:
-               stuff.append (a)
-       else:
-               stuff [idx] = wordwrap(a, stuff[idx])
+    if not stuff:
+        stuff.append (a)
+    else:
+        stuff [idx] = wordwrap(a, stuff[idx])
 
 # ignore wordwrap since we are adding to the previous word
 def stuff_append_back(stuff, idx, a):
-       if not stuff:
-               stuff.append (a)
-       else:
-               point = len(stuff[idx])-1
-               while stuff[idx][point] is ' ':
-                       point = point - 1
-               point = point +1
-               stuff[idx] = stuff[idx][:point] + a + stuff[idx][point:]
+    if not stuff:
+        stuff.append (a)
+    else:
+        point = len(stuff[idx])-1
+        while stuff[idx][point] is ' ':
+            point = point - 1
+        point = point +1
+        stuff[idx] = stuff[idx][:point] + a + stuff[idx][point:]
 
 def voices_append(a):
-       if current_voice_idx < 0:
-               select_voice ('default', '')
-       stuff_append (voices, current_voice_idx, a)
+    if current_voice_idx < 0:
+        select_voice ('default', '')
+    stuff_append (voices, current_voice_idx, a)
 
 # word wrap really makes it hard to bind beams to the end of notes since it
 # pushes out whitespace on every call. The _back functions do an append
 # prior to the last space, effectively tagging whatever they are given
 # onto the last note
 def voices_append_back(a):
-       if current_voice_idx < 0:
-               select_voice ('default', '')
-       stuff_append_back(voices, current_voice_idx, a)
+    if current_voice_idx < 0:
+        select_voice ('default', '')
+    stuff_append_back(voices, current_voice_idx, a)
 
 def repeat_prepend():
-       global repeat_state
-       if current_voice_idx < 0:
-               select_voice ('default', '')
-       if not using_old:
-               repeat_state[current_voice_idx] = 't'
+    global repeat_state
+    if current_voice_idx < 0:
+        select_voice ('default', '')
+    if not using_old:
+        repeat_state[current_voice_idx] = 't'
 
-       
+    
 def lyrics_append(a):
-       a = re.sub ('#', '\\#', a)      # latex does not like naked #'s
-       a = re.sub ('"', '\\"', a)      # latex does not like naked "'s
-       a = '\t{  "' + a + '" }\n'
-       stuff_append (lyrics, current_lyric_idx, a)
+    a = re.sub ('#', '\\#', a)        # latex does not like naked #'s
+    a = re.sub ('"', '\\"', a)        # latex does not like naked "'s
+    a = '\t{  "' + a + '" }\n'
+    stuff_append (lyrics, current_lyric_idx, a)
 
 # break lyrics to words and put "'s around words containing numbers and '"'s
 def fix_lyric(str):
-       ret = ''
-       while str != '':
-               m = re.match('[ \t]*([^ \t]*)[ \t]*(.*$)', str)
-               if m:
-                       word = m.group(1)
-                       str = m.group(2)
-                       word = re.sub('"', '\\"', word) # escape "
-                       if re.match('.*[0-9"\(]', word):
-                               word = re.sub('_', ' ', word) # _ causes probs inside ""
-                               ret = ret + '\"' + word + '\" '
-                       else:
-                               ret = ret + word + ' '
-               else:
-                       return (ret)
-       return (ret)
+    ret = ''
+    while str != '':
+        m = re.match('[ \t]*([^ \t]*)[ \t]*(.*$)', str)
+        if m:
+            word = m.group(1)
+            str = m.group(2)
+            word = re.sub('"', '\\"', word) # escape "
+            if re.match('.*[0-9"\(]', word):
+                word = re.sub('_', ' ', word) # _ causes probs inside ""
+                ret = ret + '\"' + word + '\" '
+            else:
+                ret = ret + word + ' '
+        else:
+            return (ret)
+    return (ret)
 
 def slyrics_append(a):
-       a = re.sub ( '_', ' _ ', a)     # _ to ' _ '
-       a = re.sub ( '-', '- ', a)      # split words with -
-       a = re.sub ( '\\\\- ', '-', a)  # unless \-
-       a = re.sub ( '~', '_', a)       # ~ to space('_')
-       a = re.sub ( '\*', '_ ', a)     # * to to space
-       a = re.sub ( '#', '\\#', a)     # latex does not like naked #'s
-       if re.match('.*[0-9"\(]', a):   # put numbers and " and ( into quoted string
-               a = fix_lyric(a)
-       a = re.sub ( '$', ' ', a)       # insure space between lines
-       __main__.lyric_idx = lyric_idx + 1
-       if len(slyrics[current_voice_idx]) <= lyric_idx:
-               slyrics[current_voice_idx].append(a)
-       else:
-               v = slyrics[current_voice_idx][lyric_idx]
-               slyrics[current_voice_idx][lyric_idx] = wordwrap(a, slyrics[current_voice_idx][lyric_idx])
+    a = re.sub ( '_', ' _ ', a)        # _ to ' _ '
+    a = re.sub ( '-', '- ', a)        # split words with -
+    a = re.sub ( '\\\\- ', '-', a)         # unless \-
+    a = re.sub ( '~', '_', a)        # ~ to space('_')
+    a = re.sub ( '\*', '_ ', a)        # * to to space
+    a = re.sub ( '#', '\\#', a)        # latex does not like naked #'s
+    if re.match('.*[0-9"\(]', a):        # put numbers and " and ( into quoted string
+        a = fix_lyric(a)
+    a = re.sub ( '$', ' ', a)        # insure space between lines
+    __main__.lyric_idx = lyric_idx + 1
+    if len(slyrics[current_voice_idx]) <= lyric_idx:
+        slyrics[current_voice_idx].append(a)
+    else:
+        v = slyrics[current_voice_idx][lyric_idx]
+        slyrics[current_voice_idx][lyric_idx] = wordwrap(a, slyrics[current_voice_idx][lyric_idx])
 
 
 def try_parse_header_line (ln, state):
-       global length_specified
-       m = re.match ('^([A-Za-z]): *(.*)$', ln)
-
-       if m:
-               g =m.group (1)
-               a = m.group (2)
-               if g == 'T':    #title
-                       a = re.sub('[ \t]*$','', a)     #strip trailing blanks
-                       if header.has_key('title'):
-                               if a:
-                                       if len(header['title']):
-                                               # the non-ascii character
-                                               # in the string below is a
-                                               # punctuation dash. (TeX ---)
-                                               header['title'] = header['title'] + ' â€” ' + a
-                                       else:
-                                               header['subtitle'] = a
-                       else:
-                               header['title'] =  a
-               if g == 'M':    # Meter
-                       if a == 'C':
-                               if not state.common_time:
-                                       state.common_time = 1
-                                       voices_append (" \\override Staff.TimeSignature #\'style = #'C\n")
-                               a = '4/4'
-                       if a == 'C|':
-                               if not state.common_time:
-                                       state.common_time = 1
-                                       voices_append ("\\override Staff.TimeSignature #\'style = #'C\n")
-                               a = '2/2'
-                       if not length_specified:
-                               set_default_len_from_time_sig (a)
-                       else:
-                               length_specified = 0
-                       if not a == 'none':
-                               voices_append ('\\time %s' % a)
-                       state.next_bar = ''
-               if g == 'K': # KEY
-                       a = check_clef(a)
-                       if a:
-                               m = re.match ('^([^ \t]*) *(.*)$', a) # seperate clef info
-                               if m:
-                                       # there may or may not be a space
-                                       # between the key letter and the mode
-                                       if key_lookup.has_key(m.group(2)[0:3]):
-                                               key_info = m.group(1) + m.group(2)[0:3]
-                                               clef_info = m.group(2)[4:]
-                                       else:
-                                               key_info = m.group(1)
-                                               clef_info = m.group(2)
-                                       __main__.global_key  = compute_key (key_info)
-                                       k = lily_key (key_info)
-                                       if k:
-                                               voices_append ('\\key %s' % k)
-                                       check_clef(clef_info)
-                               else:
-                                       __main__.global_key  = compute_key (a)
-                                       k = lily_key (a)
-                                       if k:
-                                               voices_append ('\\key %s \\major' % k)
-               if g == 'N': # Notes
-                       header ['footnotes'] = header['footnotes'] +  '\\\\\\\\' + a
-               if g == 'O': # Origin
-                       header ['origin'] = a
-               if g == 'X': # Reference Number
-                       header ['crossRefNumber'] = a
-               if g == 'A': #  Area
-                       header ['area'] = a
-               if g == 'H':    # History
-                       header_append ('history', a)
-               if g == 'B':    # Book
-                       header ['book'] = a
-               if g == 'C':    # Composer
-                       if header.has_key('composer'):
-                               if a:
-                                       header['composer'] = header['composer'] + '\\\\\\\\' + a
-                       else:
-                               header['composer'] =  a
-               if g == 'S':
-                       header ['subtitle'] = a
-               if g == 'L':    # Default note length
-                       set_default_length (ln)
-               if g == 'V':    # Voice 
-                       voice = re.sub (' .*$', '', a)
-                       rest = re.sub ('^[^ \t]*  *', '', a)
-                       if state.next_bar:
-                               voices_append(state.next_bar)
-                               state.next_bar = ''
-                       select_voice (voice, rest)
-               if g == 'W':    # Words
-                       lyrics_append(a)
-               if g == 'w':    # vocals
-                       slyrics_append (a)
-               if g == 'Q':    #tempo
-                       try_parse_q (a)
-               return ''
-       return ln
+    global length_specified
+    m = re.match ('^([A-Za-z]): *(.*)$', ln)
+
+    if m:
+        g =m.group (1)
+        a = m.group (2)
+        if g == 'T':        #title
+            a = re.sub('[ \t]*$','', a)        #strip trailing blanks
+            if header.has_key('title'):
+                if a:
+                    if len(header['title']):
+                        # the non-ascii character
+                        # in the string below is a
+                        # punctuation dash. (TeX ---)
+                        header['title'] = header['title'] + ' â€” ' + a
+                    else:
+                        header['subtitle'] = a
+            else:
+                header['title'] =  a
+        if g == 'M':        # Meter
+            if a == 'C':
+                if not state.common_time:
+                    state.common_time = 1
+                    voices_append (" \\override Staff.TimeSignature #\'style = #'C\n")
+                a = '4/4'
+            if a == 'C|':
+                if not state.common_time:
+                    state.common_time = 1
+                    voices_append ("\\override Staff.TimeSignature #\'style = #'C\n")
+                a = '2/2'
+            if not length_specified:
+                set_default_len_from_time_sig (a)
+            else:
+                length_specified = 0
+            if not a == 'none':
+                voices_append ('\\time %s' % a)
+            state.next_bar = ''
+        if g == 'K': # KEY
+            a = check_clef(a)
+            if a:
+                m = re.match ('^([^ \t]*) *(.*)$', a) # seperate clef info
+                if m:
+                    # there may or may not be a space
+                    # between the key letter and the mode
+                    if key_lookup.has_key(m.group(2)[0:3]):
+                        key_info = m.group(1) + m.group(2)[0:3]
+                        clef_info = m.group(2)[4:]
+                    else:
+                        key_info = m.group(1)
+                        clef_info = m.group(2)
+                    __main__.global_key  = compute_key (key_info)
+                    k = lily_key (key_info)
+                    if k:
+                        voices_append ('\\key %s' % k)
+                    check_clef(clef_info)
+                else:
+                    __main__.global_key  = compute_key (a)
+                    k = lily_key (a)
+                    if k:
+                        voices_append ('\\key %s \\major' % k)
+        if g == 'N': # Notes
+            header ['footnotes'] = header['footnotes'] +  '\\\\\\\\' + a
+        if g == 'O': # Origin
+            header ['origin'] = a
+        if g == 'X': # Reference Number
+            header ['crossRefNumber'] = a
+        if g == 'A': #        Area
+            header ['area'] = a
+        if g == 'H':        # History
+            header_append ('history', a)
+        if g == 'B':        # Book
+            header ['book'] = a
+        if g == 'C':        # Composer
+            if header.has_key('composer'):
+                if a:
+                    header['composer'] = header['composer'] + '\\\\\\\\' + a
+            else:
+                header['composer'] =  a
+        if g == 'S':
+            header ['subtitle'] = a
+        if g == 'L':        # Default note length
+            set_default_length (ln)
+        if g == 'V':        # Voice 
+            voice = re.sub (' .*$', '', a)
+            rest = re.sub ('^[^ \t]*  *', '', a)
+            if state.next_bar:
+                voices_append(state.next_bar)
+                state.next_bar = ''
+            select_voice (voice, rest)
+        if g == 'W':        # Words
+            lyrics_append(a)
+        if g == 'w':        # vocals
+            slyrics_append (a)
+        if g == 'Q':    #tempo
+            try_parse_q (a)
+        return ''
+    return ln
 
 # we use in this order specified accidental, active accidental for bar,
 # active accidental for key
 def pitch_to_lilypond_name (name, acc, bar_acc, key):
-       s = ''
-       if acc == UNDEF:
-               if not nobarlines:
-                       acc = bar_acc
-       if acc == UNDEF:
-               acc = key
-       if acc == -1:
-               s = 'es'
-       elif acc == 1:
-               s =  'is'
-       
-       if name > 4:
-               name = name -7
-       return(chr (name  + ord('c')) + s)
+    s = ''
+    if acc == UNDEF:
+        if not nobarlines:
+            acc = bar_acc
+    if acc == UNDEF:
+        acc = key
+    if acc == -1:
+        s = 'es'
+    elif acc == 1:
+        s =  'is'
+    
+    if name > 4:
+        name = name -7
+    return(chr (name  + ord('c')) + s)
 
 
 def octave_to_lilypond_quotes (o):
-       o = o + 2
-       s =''
-       if o < 0:
-               o = -o
-               s=','
-       else:
-               s ='\''
+    o = o + 2
+    s =''
+    if o < 0:
+        o = -o
+        s=','
+    else:
+        s ='\''
 
-       return s * o
+    return s * o
 
 def parse_num (str):
-       durstr = ''
-       while str and str[0] in DIGITS:
-               durstr = durstr + str[0]
-               str = str[1:]
+    durstr = ''
+    while str and str[0] in DIGITS:
+        durstr = durstr + str[0]
+        str = str[1:]
 
-       n = None
-       if durstr:
-               n  =string.atoi (durstr) 
-       return (str,n)
+    n = None
+    if durstr:
+        n  =string.atoi (durstr) 
+    return (str,n)
 
 
 def duration_to_lilypond_duration  (multiply_tup, defaultlen, dots):
-       base = 1
-       # (num /  den)  / defaultlen < 1/base
-       while base * multiply_tup[0] < multiply_tup[1]:
-               base = base * 2
-       if base == 1:
-               if (multiply_tup[0] / multiply_tup[1])  == 2:
-                       base = '\\breve'
-               if (multiply_tup[0] / multiply_tup[1]) == 3:
-                       base = '\\breve'
-                       dots = 1
-               if (multiply_tup[0] / multiply_tup[1]) == 4:
-                       base = '\longa'
-       return '%s%s' % ( base, '.'* dots)
+    base = 1
+    # (num /  den)  / defaultlen < 1/base
+    while base * multiply_tup[0] < multiply_tup[1]:
+        base = base * 2
+    if base == 1:
+        if (multiply_tup[0] / multiply_tup[1])  == 2:
+            base = '\\breve'
+        if (multiply_tup[0] / multiply_tup[1]) == 3:
+            base = '\\breve'
+            dots = 1
+        if (multiply_tup[0] / multiply_tup[1]) == 4:
+            base = '\longa'
+    return '%s%s' % ( base, '.'* dots)
 
 class Parser_state:
-       def __init__ (self):
-               self.in_acc = {}
-               self.next_articulation = ''
-               self.next_bar = ''
-               self.next_dots = 0
-               self.next_den = 1
-               self.parsing_tuplet = 0
-               self.plus_chord = 0
-               self.base_octave = 0
-               self.common_time = 0
-               self.parsing_beam = 0
+    def __init__ (self):
+        self.in_acc = {}
+        self.next_articulation = ''
+        self.next_bar = ''
+        self.next_dots = 0
+        self.next_den = 1
+        self.parsing_tuplet = 0
+        self.plus_chord = 0
+        self.base_octave = 0
+        self.common_time = 0
+        self.parsing_beam = 0
 
 
 
 # return (str, num,den,dots) 
 def parse_duration (str, parser_state):
-       num = 0
-       den = parser_state.next_den
-       parser_state.next_den = 1
-
-       (str, num) = parse_num (str)
-       if not num:
-               num = 1
-       if len(str):
-               if str[0] == '/':
-                       if len(str[0]):
-                               while str[:1] == '/':
-                                       str= str[1:]
-                                       d = 2
-                                       if str[0] in DIGITS:
-                                               (str, d) =parse_num (str)
-
-                                       den = den * d
-
-       den = den * default_len
-       
-       current_dots = parser_state.next_dots
-       parser_state.next_dots = 0
-       if re.match ('[ \t]*[<>]', str):
-               while str[0] in HSPACE:
-                       str = str[1:]
-               while str[0] == '>':
-                       str = str [1:]
-                       current_dots = current_dots + 1
-                       parser_state.next_den = parser_state.next_den * 2
-               
-               while str[0] == '<':
-                       str = str [1:]
-                       den = den * 2
-                       parser_state.next_dots = parser_state.next_dots + 1
-
-
-
-       try_dots = [3, 2, 1]
-       for d in try_dots:
-               f = 1 << d
-               multiplier = (2*f-1)
-               if num % multiplier == 0 and den % f == 0:
-                       num = num / multiplier
-                       den = den / f
-                       current_dots = current_dots + d
-               
-       return (str, num,den,current_dots)
+    num = 0
+    den = parser_state.next_den
+    parser_state.next_den = 1
+
+    (str, num) = parse_num (str)
+    if not num:
+        num = 1
+    if len(str):
+        if str[0] == '/':
+            if len(str[0]):
+                while str[:1] == '/':
+                    str= str[1:]
+                    d = 2
+                    if str[0] in DIGITS:
+                        (str, d) =parse_num (str)
+
+                    den = den * d
+
+    den = den * default_len
+    
+    current_dots = parser_state.next_dots
+    parser_state.next_dots = 0
+    if re.match ('[ \t]*[<>]', str):
+        while str[0] in HSPACE:
+            str = str[1:]
+        while str[0] == '>':
+            str = str [1:]
+            current_dots = current_dots + 1
+            parser_state.next_den = parser_state.next_den * 2
+        
+        while str[0] == '<':
+            str = str [1:]
+            den = den * 2
+            parser_state.next_dots = parser_state.next_dots + 1
+
+
+
+    try_dots = [3, 2, 1]
+    for d in try_dots:
+        f = 1 << d
+        multiplier = (2*f-1)
+        if num % multiplier == 0 and den % f == 0:
+            num = num / multiplier
+            den = den / f
+            current_dots = current_dots + d
+        
+    return (str, num,den,current_dots)
 
 
 def try_parse_rest (str, parser_state):
-       if not str or str[0] <> 'z' and str[0] <> 'x':
-               return str
+    if not str or str[0] <> 'z' and str[0] <> 'x':
+        return str
 
-       __main__.lyric_idx = -1
+    __main__.lyric_idx = -1
 
-       if parser_state.next_bar:
-               voices_append(parser_state.next_bar)
-               parser_state.next_bar = ''
+    if parser_state.next_bar:
+        voices_append(parser_state.next_bar)
+        parser_state.next_bar = ''
 
-       if str[0] == 'z':
-               rest = 'r'
-       else:
-               rest = 's'
-       str = str[1:]
+    if str[0] == 'z':
+        rest = 'r'
+    else:
+        rest = 's'
+    str = str[1:]
 
-       (str, num,den,d) = parse_duration (str, parser_state)
-       voices_append ('%s%s' % (rest, duration_to_lilypond_duration ((num,den), default_len, d)))
-       if parser_state.next_articulation:
-               voices_append (parser_state.next_articulation)
-               parser_state.next_articulation = ''
+    (str, num,den,d) = parse_duration (str, parser_state)
+    voices_append ('%s%s' % (rest, duration_to_lilypond_duration ((num,den), default_len, d)))
+    if parser_state.next_articulation:
+        voices_append (parser_state.next_articulation)
+        parser_state.next_articulation = ''
 
-       return str
+    return str
 
 artic_tbl = {
-       '.'  : '-.',
-        'T' : '^\\trill',
-        'H' : '^\\fermata',
-        'u' : '^\\upbow',
-        'K' : '^\\ltoe',
-        'k' : '^\\accent',
-        'M' : '^\\tenuto',
-        '~' : '^"~" ',
-        'J' : '',              # ignore slide
-        'R' : '',              # ignore roll
-        'v' : '^\\downbow'
+    '.'  : '-.',
+    'T' : '^\\trill',
+    'H' : '^\\fermata',
+    'u' : '^\\upbow',
+    'K' : '^\\ltoe',
+    'k' : '^\\accent',
+    'M' : '^\\tenuto',
+    '~' : '^"~" ',
+    'J' : '',                # ignore slide
+    'R' : '',                # ignore roll
+    'v' : '^\\downbow'
 }
-       
+    
 def try_parse_articulation (str, state):
-       while str and  artic_tbl.has_key(str[:1]):
-               state.next_articulation = state.next_articulation + artic_tbl[str[:1]]
-               if not artic_tbl[str[:1]]:
-                       sys.stderr.write("Warning: ignoring `%s'\n" % str[:1] )
-
-               str = str[1:]
-
-       
-               
-       # s7m2 input doesnt care about spaces
-       if re.match('[ \t]*\(', str):
-               str = string.lstrip (str)
-
-       slur_begin =0
-       while str[:1] =='(' and str[1] not in DIGITS:
-               slur_begin = slur_begin + 1
-               state.next_articulation = state.next_articulation + '('
-               str = str[1:]
-
-       return str
-               
+    while str and  artic_tbl.has_key(str[:1]):
+        state.next_articulation = state.next_articulation + artic_tbl[str[:1]]
+        if not artic_tbl[str[:1]]:
+            sys.stderr.write("Warning: ignoring `%s'\n" % str[:1] )
+
+        str = str[1:]
+
+    
+        
+    # s7m2 input doesnt care about spaces
+    if re.match('[ \t]*\(', str):
+        str = string.lstrip (str)
+
+    slur_begin =0
+    while str[:1] =='(' and str[1] not in DIGITS:
+        slur_begin = slur_begin + 1
+        state.next_articulation = state.next_articulation + '('
+        str = str[1:]
+
+    return str
+        
 #
 # remember accidental for rest of bar
 #
 def set_bar_acc(note, octave, acc, state):
-       if acc == UNDEF:
-               return
-       n_oct = note + octave * 7
-       state.in_acc[n_oct] = acc
+    if acc == UNDEF:
+        return
+    n_oct = note + octave * 7
+    state.in_acc[n_oct] = acc
 
 # get accidental set in this bar or UNDEF if not set
 def get_bar_acc(note, octave, state):
-       n_oct = note + octave * 7
-       if state.in_acc.has_key(n_oct):
-               return(state.in_acc[n_oct])
-       else:
-               return(UNDEF)
+    n_oct = note + octave * 7
+    if state.in_acc.has_key(n_oct):
+        return(state.in_acc[n_oct])
+    else:
+        return(UNDEF)
 
 def clear_bar_acc(state):
-       for k in state.in_acc.keys():
-               del state.in_acc[k]
-       
+    for k in state.in_acc.keys():
+        del state.in_acc[k]
+    
 
 # if we are parsing a beam, close it off
 def close_beam_state(state):
-       if state.parsing_beam and global_options.beams:
-               state.parsing_beam = 0
-               voices_append_back( ']' )
+    if state.parsing_beam and global_options.beams:
+        state.parsing_beam = 0
+        voices_append_back( ']' )
 
-               
+        
 # WAT IS ABC EEN ONTZETTENDE PROGRAMMEERPOEP  !
 def try_parse_note (str, parser_state):
-       mud = ''
-
-       slur_begin =0
-       if not str:
-               return str
-
-       articulation =''
-       acc = UNDEF
-       if str[0] in '^=_':
-               c = str[0]
-               str = str[1:]
-               if c == '^':
-                       acc = 1
-               if c == '=':
-                       acc = 0
-               if c == '_':
-                       acc = -1
-
-       octave = parser_state.base_octave
-       if str[0] in "ABCDEFG":
-               str = string.lower (str[0]) + str[1:]
-               octave = octave - 1
-
-
-       notename = 0
-       if str[0] in "abcdefg":
-               notename = (ord(str[0]) - ord('a') + 5)%7
-               str = str[1:]
-       else:
-               return str              # failed; not a note!
-
-       
-       __main__.lyric_idx = -1
-
-       if parser_state.next_bar:
-               voices_append(parser_state.next_bar)
-               parser_state.next_bar = ''
-
-       while str[0] == ',':
-                octave = octave - 1
-                str = str[1:]
-       while str[0] == '\'':
-                octave = octave + 1
-                str = str[1:]
-
-       (str, num,den,current_dots) = parse_duration (str, parser_state)
-
-       if re.match('[ \t]*\)', str):
-               str = string.lstrip (str)
-       
-       slur_end =0
-       while str[:1] ==')':
-               slur_end = slur_end + 1
-               str = str[1:]
-
-       
-       bar_acc = get_bar_acc(notename, octave, parser_state)
-       pit = pitch_to_lilypond_name(notename, acc, bar_acc, global_key[notename])
-       oct = octave_to_lilypond_quotes (octave)
-       if acc != UNDEF and (acc == global_key[notename] or acc == bar_acc):
-               mod='!'
-       else:
-               mod = ''
-       voices_append ("%s%s%s%s" %
-               (pit, oct, mod,
-                duration_to_lilypond_duration ((num,den), default_len, current_dots)))
-       
-       set_bar_acc(notename, octave, acc, parser_state)
-       if parser_state.next_articulation:
-               articulation = articulation + parser_state.next_articulation
-               parser_state.next_articulation = ''
-
-       voices_append (articulation)
-
-       if parser_state.parsing_tuplet:
-               parser_state.parsing_tuplet = parser_state.parsing_tuplet - 1
-               if not parser_state.parsing_tuplet:
-                       voices_append ("}")
-       if slur_begin:
-               voices_append ('-(' * slur_begin )
-       if slur_end:
-               voices_append ('-)' *slur_end )
-
-       if global_options.beams and \
-          str[0] in '^=_ABCDEFGabcdefg' and \
-          not parser_state.parsing_beam and \
-          not parser_state.parsing_tuplet:
-               parser_state.parsing_beam = 1
-               voices_append_back( '[' )
-               
-       return str
+    mud = ''
+
+    slur_begin =0
+    if not str:
+        return str
+
+    articulation =''
+    acc = UNDEF
+    if str[0] in '^=_':
+        c = str[0]
+        str = str[1:]
+        if c == '^':
+            acc = 1
+        if c == '=':
+            acc = 0
+        if c == '_':
+            acc = -1
+
+    octave = parser_state.base_octave
+    if str[0] in "ABCDEFG":
+        str = string.lower (str[0]) + str[1:]
+        octave = octave - 1
+
+
+    notename = 0
+    if str[0] in "abcdefg":
+        notename = (ord(str[0]) - ord('a') + 5)%7
+        str = str[1:]
+    else:
+        return str                # failed; not a note!
+
+    
+    __main__.lyric_idx = -1
+
+    if parser_state.next_bar:
+        voices_append(parser_state.next_bar)
+        parser_state.next_bar = ''
+
+    while str[0] == ',':
+        octave = octave - 1
+        str = str[1:]
+    while str[0] == '\'':
+        octave = octave + 1
+        str = str[1:]
+
+    (str, num,den,current_dots) = parse_duration (str, parser_state)
+
+    if re.match('[ \t]*\)', str):
+        str = string.lstrip (str)
+    
+    slur_end =0
+    while str[:1] ==')':
+        slur_end = slur_end + 1
+        str = str[1:]
+
+    
+    bar_acc = get_bar_acc(notename, octave, parser_state)
+    pit = pitch_to_lilypond_name(notename, acc, bar_acc, global_key[notename])
+    oct = octave_to_lilypond_quotes (octave)
+    if acc != UNDEF and (acc == global_key[notename] or acc == bar_acc):
+        mod='!'
+    else:
+        mod = ''
+    voices_append ("%s%s%s%s" %
+        (pit, oct, mod,
+         duration_to_lilypond_duration ((num,den), default_len, current_dots)))
+    
+    set_bar_acc(notename, octave, acc, parser_state)
+    if parser_state.next_articulation:
+        articulation = articulation + parser_state.next_articulation
+        parser_state.next_articulation = ''
+
+    voices_append (articulation)
+
+    if parser_state.parsing_tuplet:
+        parser_state.parsing_tuplet = parser_state.parsing_tuplet - 1
+        if not parser_state.parsing_tuplet:
+            voices_append ("}")
+    if slur_begin:
+        voices_append ('-(' * slur_begin )
+    if slur_end:
+        voices_append ('-)' *slur_end )
+
+    if global_options.beams and \
+     str[0] in '^=_ABCDEFGabcdefg' and \
+     not parser_state.parsing_beam and \
+     not parser_state.parsing_tuplet:
+        parser_state.parsing_beam = 1
+        voices_append_back( '[' )
+        
+    return str
 
 def junk_space (str,state):
-       while str and str[0] in '\t\n\r ':
-               str = str[1:]
-               close_beam_state(state)
+    while str and str[0] in '\t\n\r ':
+        str = str[1:]
+        close_beam_state(state)
 
-       return str
+    return str
 
 
 def try_parse_guitar_chord (str, state):
-       if str[:1] =='"':
-               str = str[1:]
-               gc = ''
-               if str[0] == '_' or (str[0] == '^'):
-                       position = str[0]
-                       str = str[1:]
-               else:
-                       position = '^'
-               while str and str[0] != '"':
-                       gc = gc + str[0]
-                       str = str[1:]
-                       
-               if str:
-                       str = str[1:]
-               gc = re.sub('#', '\\#', gc)     # escape '#'s
-               state.next_articulation = ("%c\"%s\"" % (position, gc)) \
-                                         + state.next_articulation
-       return str
+    if str[:1] =='"':
+        str = str[1:]
+        gc = ''
+        if str[0] == '_' or (str[0] == '^'):
+            position = str[0]
+            str = str[1:]
+        else:
+            position = '^'
+        while str and str[0] != '"':
+            gc = gc + str[0]
+            str = str[1:]
+            
+        if str:
+            str = str[1:]
+        gc = re.sub('#', '\\#', gc)        # escape '#'s
+        state.next_articulation = ("%c\"%s\"" % (position, gc)) \
+                     + state.next_articulation
+    return str
 
 def try_parse_escape (str):
-       if not str or str [0] != '\\':
-               return str
-       
-       str = str[1:]
-       if str[:1] =='K':
-               key_table = compute_key ()
-       return str
+    if not str or str [0] != '\\':
+        return str
+    
+    str = str[1:]
+    if str[:1] =='K':
+        key_table = compute_key ()
+    return str
 
 #
 # |] thin-thick double bar line
@@ -1105,17 +1105,17 @@ old_bar_dict = {
 '|' :  '|'
 }
 bar_dict = {
- '|]' : '\\bar "|."',
- '||' : '\\bar "||"',
- '[|' : '\\bar "||"',
- ':|' : '}',
- '|:' : '\\repeat volta 2 {',
- '::' : '} \\repeat volta 2 {',
- '|1' : '} \\alternative{{',
- '|2' : '} {',
- ':|2' : '} {',
- '|' :  '\\bar "|"'
 }
+'|]' : '\\bar "|."',
+'||' : '\\bar "||"',
+'[|' : '\\bar "||"',
+':|' : '}',
+'|:' : '\\repeat volta 2 {',
+'::' : '} \\repeat volta 2 {',
+'|1' : '} \\alternative{{',
+'|2' : '} {',
+':|2' : '} {',
+'|' :  '\\bar "|"'
+ }
 
 
 warn_about = ['|:', '::', ':|', '|1', ':|2', '|2']
@@ -1127,137 +1127,137 @@ doing_alternative = [''] * 8
 using_old = ''
 
 def try_parse_bar (str,state):
-       global in_repeat, doing_alternative, using_old
-       do_curly = ''
-       bs = None
-       if current_voice_idx < 0:
-               select_voice ('default', '')
-       # first try the longer one
-       for trylen in [3,2,1]:
-               if str[:trylen] and bar_dict.has_key (str[:trylen]):
-                       s = str[:trylen]
-                       if using_old:
-                               bs = "\\bar \"%s\"" % old_bar_dict[s]
-                       else:
-                               bs = "%s" % bar_dict[s]
-                       str = str[trylen:]
-                       if s in alternative_opener:
-                               if not in_repeat[current_voice_idx]:
-                                       using_old = 't'
-                                       bs = "\\bar \"%s\"" % old_bar_dict[s]
-                               else:
-                                       doing_alternative[current_voice_idx] = 't'
-
-                       if s in repeat_ender:
-                               if not in_repeat[current_voice_idx]:
-                                       sys.stderr.write("Warning: inserting repeat to beginning of notes.\n")
-                                       repeat_prepend()
-                                       in_repeat[current_voice_idx] = ''
-                               else:
-                                       if doing_alternative[current_voice_idx]:
-                                               do_curly = 't'
-                               if using_old:
-                                       bs = "\\bar \"%s\"" % old_bar_dict[s]
-                               else:
-                                       bs =  bar_dict[s]
-                               doing_alternative[current_voice_idx] = ''
-                               in_repeat[current_voice_idx] = ''
-                       if s in repeat_opener:
-                               in_repeat[current_voice_idx] = 't'
-                               if using_old:
-                                       bs = "\\bar \"%s\"" % old_bar_dict[s]
-                               else:
-                                       bs =  bar_dict[s]
-                       break
-       if str[:1] == '|':
-               state.next_bar = '|\n'
-               str = str[1:]
-               clear_bar_acc(state)
-               close_beam_state(state)
-       
-       if bs <> None or state.next_bar != '':
-               if state.parsing_tuplet:
-                       state.parsing_tuplet =0
-                       voices_append ('} ')
-               
-       if bs <> None:
-               clear_bar_acc(state)
-               close_beam_state(state)
-               voices_append (bs)
-               if do_curly != '':
-                       voices_append("} }")
-                       do_curly = ''
-       return str
+    global in_repeat, doing_alternative, using_old
+    do_curly = ''
+    bs = None
+    if current_voice_idx < 0:
+        select_voice ('default', '')
+    # first try the longer one
+    for trylen in [3,2,1]:
+        if str[:trylen] and bar_dict.has_key (str[:trylen]):
+            s = str[:trylen]
+            if using_old:
+                bs = "\\bar \"%s\"" % old_bar_dict[s]
+            else:
+                bs = "%s" % bar_dict[s]
+            str = str[trylen:]
+            if s in alternative_opener:
+                if not in_repeat[current_voice_idx]:
+                    using_old = 't'
+                    bs = "\\bar \"%s\"" % old_bar_dict[s]
+                else:
+                    doing_alternative[current_voice_idx] = 't'
+
+            if s in repeat_ender:
+                if not in_repeat[current_voice_idx]:
+                    sys.stderr.write("Warning: inserting repeat to beginning of notes.\n")
+                    repeat_prepend()
+                    in_repeat[current_voice_idx] = ''
+                else:
+                    if doing_alternative[current_voice_idx]:
+                        do_curly = 't'
+                if using_old:
+                    bs = "\\bar \"%s\"" % old_bar_dict[s]
+                else:
+                    bs =  bar_dict[s]
+                doing_alternative[current_voice_idx] = ''
+                in_repeat[current_voice_idx] = ''
+            if s in repeat_opener:
+                in_repeat[current_voice_idx] = 't'
+                if using_old:
+                    bs = "\\bar \"%s\"" % old_bar_dict[s]
+                else:
+                    bs =  bar_dict[s]
+            break
+    if str[:1] == '|':
+        state.next_bar = '|\n'
+        str = str[1:]
+        clear_bar_acc(state)
+        close_beam_state(state)
+    
+    if bs <> None or state.next_bar != '':
+        if state.parsing_tuplet:
+            state.parsing_tuplet =0
+            voices_append ('} ')
+        
+    if bs <> None:
+        clear_bar_acc(state)
+        close_beam_state(state)
+        voices_append (bs)
+        if do_curly != '':
+            voices_append("} }")
+            do_curly = ''
+    return str
 
 def try_parse_tie (str):
-       if str[:1] =='-':
-               str = str[1:]
-               voices_append (' ~ ')
-       return str
+    if str[:1] =='-':
+        str = str[1:]
+        voices_append (' ~ ')
+    return str
 
 def bracket_escape (str, state):
-       m = re.match ( '^([^\]]*)] *(.*)$', str)
-       if m:
-               cmd = m.group (1)
-               str = m.group (2)
-               try_parse_header_line (cmd, state)
-       return str
+    m = re.match ( '^([^\]]*)] *(.*)$', str)
+    if m:
+        cmd = m.group (1)
+        str = m.group (2)
+        try_parse_header_line (cmd, state)
+    return str
 
 def try_parse_chord_delims (str, state):
-       if str[:1] =='[':
-               str = str[1:]
-               if re.match('[A-Z]:', str):     # bracket escape
-                       return bracket_escape(str, state)
-               if state.next_bar:
-                       voices_append(state.next_bar)
-                       state.next_bar = ''
-               voices_append ('<<')
-
-       if str[:1] == '+':
-               str = str[1:]
-               if state.plus_chord:
-                       voices_append ('>>')
-                       state.plus_chord = 0
-               else:
-                       if state.next_bar:
-                               voices_append(state.next_bar)
-                               state.next_bar = ''
-                       voices_append ('<<')
-                       state.plus_chord = 1
-
-       ch = ''
-       if str[:1] ==']':
-               str = str[1:]
-               ch = '>>'
-
-       end = 0
-       while str[:1] ==')':
-               end = end + 1
-               str = str[1:]
-
-       
-       voices_append ("\\spanrequest \\stop \"slur\"" * end)
-       voices_append (ch)
-       return str
+    if str[:1] =='[':
+        str = str[1:]
+        if re.match('[A-Z]:', str):        # bracket escape
+            return bracket_escape(str, state)
+        if state.next_bar:
+            voices_append(state.next_bar)
+            state.next_bar = ''
+        voices_append ('<<')
+
+    if str[:1] == '+':
+        str = str[1:]
+        if state.plus_chord:
+            voices_append ('>>')
+            state.plus_chord = 0
+        else:
+            if state.next_bar:
+                voices_append(state.next_bar)
+                state.next_bar = ''
+            voices_append ('<<')
+            state.plus_chord = 1
+
+    ch = ''
+    if str[:1] ==']':
+        str = str[1:]
+        ch = '>>'
+
+    end = 0
+    while str[:1] ==')':
+        end = end + 1
+        str = str[1:]
+
+    
+    voices_append ("\\spanrequest \\stop \"slur\"" * end)
+    voices_append (ch)
+    return str
 
 def try_parse_grace_delims (str, state):
-       if str[:1] =='{':
-               if state.next_bar:
-                       voices_append(state.next_bar)
-                       state.next_bar = ''
-               str = str[1:]
-               voices_append ('\\grace { ')
+    if str[:1] =='{':
+        if state.next_bar:
+            voices_append(state.next_bar)
+            state.next_bar = ''
+        str = str[1:]
+        voices_append ('\\grace { ')
 
-       if str[:1] =='}':
-               str = str[1:]
-               voices_append ('}')
+    if str[:1] =='}':
+        str = str[1:]
+        voices_append ('}')
 
-       return str
+    return str
 
 def try_parse_comment (str):
-       global nobarlines
-       if (str[0] == '%'):
-               if str[0:5] == '%MIDI':
+    global nobarlines
+    if (str[0] == '%'):
+        if str[0:5] == '%MIDI':
 #the nobarlines option is necessary for an abc to lilypond translator for
 #exactly the same reason abc2midi needs it: abc requires the user to enter
 #the note that will be printed, and MIDI and lilypond expect entry of the
@@ -1271,77 +1271,77 @@ def try_parse_comment (str):
 #convention, such as most music written before 1700, or ethnic music in
 #non-western scales, it is necessary to be able to tell a translator that
 #the barlines should not affect its interpretation of the pitch.  
-                       if (string.find(str,'nobarlines') > 0):
-                               nobarlines = 1
-               elif str[0:3] == '%LY':
-                       p = string.find(str, 'voices')
-                       if (p > -1):
-                               voices_append(str[p+7:])
-                               voices_append("\n")
-                       p = string.find(str, 'slyrics')
-                       if (p > -1):
-                               slyrics_append(str[p+8:])
-                       
-#write other kinds of appending  if we ever need them.                 
-       return str
+            if (string.find(str,'nobarlines') > 0):
+                nobarlines = 1
+        elif str[0:3] == '%LY':
+            p = string.find(str, 'voices')
+            if (p > -1):
+                voices_append(str[p+7:])
+                voices_append("\n")
+            p = string.find(str, 'slyrics')
+            if (p > -1):
+                slyrics_append(str[p+8:])
+            
+#write other kinds of appending  if we ever need them.                        
+    return str
 
 lineno = 0
 happy_count = 100
 def parse_file (fn):
-       f = open (fn)
-       ls = f.readlines ()
-       ls = map (lambda x: re.sub ("\r$", '', x), ls)
-
-       select_voice('default', '')
-       global lineno
-       lineno = 0
-       sys.stderr.write ("Line ... ")
-       sys.stderr.flush ()
-       __main__.state = state_list[current_voice_idx]
-       
-       for ln in ls:
-               lineno = lineno + 1
-
-               if not (lineno % happy_count):
-                       sys.stderr.write ('[%d]'% lineno)
-                       sys.stderr.flush ()
-               m = re.match  ('^([^%]*)%(.*)$',ln)  # add comments to current voice
-               if m:
-                       if m.group(2):
-                               try_parse_comment(m.group(2))
-                               voices_append ('%% %s\n' % m.group(2))
-                       ln = m.group (1)
-
-               orig_ln = ln
-               
-               ln = try_parse_header_line (ln, state)
-
-               # Try nibbling characters off until the line doesn't change.
-               prev_ln = ''
-               while ln != prev_ln:
-                       prev_ln = ln
-                       ln = try_parse_chord_delims (ln, state)
-                       ln = try_parse_rest (ln, state)
-                       ln = try_parse_articulation (ln,state)
-                       ln = try_parse_note  (ln, state)
-                       ln = try_parse_bar (ln, state)
-                       ln = try_parse_tie (ln)
-                       ln = try_parse_escape (ln)
-                       ln = try_parse_guitar_chord (ln, state)
-                       ln = try_parse_tuplet_begin (ln, state)
-                       ln = try_parse_group_end (ln, state)
-                       ln = try_parse_grace_delims (ln, state)
-                       ln = junk_space (ln, state)
-
-               if ln:
-                       error ("%s: %d: Huh?  Don't understand\n" % (fn, lineno))
-                       left = orig_ln[0:-len (ln)]
-                       sys.stderr.write (left + '\n')
-                       sys.stderr.write (' ' *  len (left) + ln + '\n')        
+    f = open (fn)
+    ls = f.readlines ()
+    ls = map (lambda x: re.sub ("\r$", '', x), ls)
+
+    select_voice('default', '')
+    global lineno
+    lineno = 0
+    sys.stderr.write ("Line ... ")
+    sys.stderr.flush ()
+    __main__.state = state_list[current_voice_idx]
+    
+    for ln in ls:
+        lineno = lineno + 1
+
+        if not (lineno % happy_count):
+            sys.stderr.write ('[%d]'% lineno)
+            sys.stderr.flush ()
+        m = re.match  ('^([^%]*)%(.*)$',ln)  # add comments to current voice
+        if m:
+            if m.group(2):
+                try_parse_comment(m.group(2))
+                voices_append ('%% %s\n' % m.group(2))
+            ln = m.group (1)
+
+        orig_ln = ln
+        
+        ln = try_parse_header_line (ln, state)
+
+        # Try nibbling characters off until the line doesn't change.
+        prev_ln = ''
+        while ln != prev_ln:
+            prev_ln = ln
+            ln = try_parse_chord_delims (ln, state)
+            ln = try_parse_rest (ln, state)
+            ln = try_parse_articulation (ln,state)
+            ln = try_parse_note  (ln, state)
+            ln = try_parse_bar (ln, state)
+            ln = try_parse_tie (ln)
+            ln = try_parse_escape (ln)
+            ln = try_parse_guitar_chord (ln, state)
+            ln = try_parse_tuplet_begin (ln, state)
+            ln = try_parse_group_end (ln, state)
+            ln = try_parse_grace_delims (ln, state)
+            ln = junk_space (ln, state)
+
+        if ln:
+            error ("%s: %d: Huh?  Don't understand\n" % (fn, lineno))
+            left = orig_ln[0:-len (ln)]
+            sys.stderr.write (left + '\n')
+            sys.stderr.write (' ' *  len (left) + ln + '\n')        
 
 
 def identify():
-       sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version))
+    sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version))
 
 authors = """
 Written by Han-Wen Nienhuys <hanwen@cs.uu.nl>, Laura Conrad
@@ -1349,24 +1349,24 @@ Written by Han-Wen Nienhuys <hanwen@cs.uu.nl>, Laura Conrad
 """
 
 def print_version ():
-       print r"""abc2ly (GNU lilypond) %s""" % version
+    print r"""abc2ly (GNU lilypond) %s""" % version
 
 def get_option_parser ():
-       p = ly.get_option_parser (usage='abc2ly [OPTIONS] FILE',
-                                 version="abc2ly (LilyPond) @TOPLEVEL_VERSION@",
-                                 description=_('''This program converts ABC music files (see
+    p = ly.get_option_parser (usage='abc2ly [OPTIONS] FILE',
+                 version="abc2ly (LilyPond) @TOPLEVEL_VERSION@",
+                 description=_('''This program converts ABC music files (see
 http://www.gre.ac.uk/~c.walshaw/abc2mtex/abc.txt) to LilyPond input.'''))
 
-       p.add_option ('-o', '--output', metavar='FILE',help=_("set output filename to FILE"),
-                     action='store')
-       p.add_option ('-s', '--strict', help=_("be strict about succes"),
-                     action='store_true')
-       p.add_option ('-b', '--beams', help=_("preserve ABC's notion of beams"))
-       p.add_option_group  ('bugs',
-                            description='''Report bugs via http://post.gmane.org/post.php'''
-                            '''?group=gmane.comp.gnu.lilypond.bugs\n''')
-       
-       return p
+    p.add_option ('-o', '--output', metavar='FILE',help=_("set output filename to FILE"),
+           action='store')
+    p.add_option ('-s', '--strict', help=_("be strict about succes"),
+           action='store_true')
+    p.add_option ('-b', '--beams', help=_("preserve ABC's notion of beams"))
+    p.add_option_group  ('bugs',
+              description='''Report bugs via http://post.gmane.org/post.php'''
+              '''?group=gmane.comp.gnu.lilypond.bugs\n''')
+    
+    return p
 
 
 option_parser = get_option_parser()
@@ -1377,26 +1377,26 @@ identify()
 
 header['tagline'] = 'Lily was here %s -- automatically converted from ABC' % version
 for f in files:
-       if f == '-':
-               f = ''
+    if f == '-':
+        f = ''
 
-       sys.stderr.write ('Parsing `%s\'...\n' % f)
-       parse_file (f)
+    sys.stderr.write ('Parsing `%s\'...\n' % f)
+    parse_file (f)
 
-       if not global_options.output:
-               global_options.output = os.path.basename (os.path.splitext (f)[0]) + ".ly"
-       sys.stderr.write ('lilypond output to: `%s\'...' % global_options.output)
-       outf = open (global_options.output, 'w')
+    if not global_options.output:
+        global_options.output = os.path.basename (os.path.splitext (f)[0]) + ".ly"
+    sys.stderr.write ('lilypond output to: `%s\'...' % global_options.output)
+    outf = open (global_options.output, 'w')
 
 # don't substitute @VERSION@. We want this to reflect
 # the last version that was verified to work.
-       outf.write ('\\version "2.7.40"\n')
-
-#      dump_global (outf)
-       dump_header (outf, header)
-       dump_slyrics (outf)
-       dump_voices (outf)
-       dump_score (outf)
-       dump_lyrics (outf)
-       sys.stderr.write ('\n')
-       
+    outf.write ('\\version "2.7.40"\n')
+
+#        dump_global (outf)
+    dump_header (outf, header)
+    dump_slyrics (outf)
+    dump_voices (outf)
+    dump_score (outf)
+    dump_lyrics (outf)
+    sys.stderr.write ('\n')
+    
index 18a33a4324d1efd8562591e1ba3e1c261e1b10b0..5fb09c7333ac1df17336313134c8371b6616c6b5 100644 (file)
@@ -37,7 +37,7 @@ program_name = sys.argv[0]
 
 version = '@TOPLEVEL_VERSION@'
 if version == '@' + 'TOPLEVEL_VERSION' + '@':
-       version = '(unknown version)'      # uGUHGUHGHGUGH
+    version = '(unknown version)'           # uGUHGUHGHGUGH
 
 
 ################################################################
@@ -45,1189 +45,1189 @@ if version == '@' + 'TOPLEVEL_VERSION' + '@':
 #
 libdir = '@local_lilypond_libdir@'
 if not os.path.isdir (libdir):
-        libdir = '@lilypond_libdir@'
+    libdir = '@lilypond_libdir@'
 
 # ugh
 datadir = '@local_lilypond_datadir@'
 if os.environ.has_key ('LILYPONDPREFIX'):
-       datadir = os.environ['LILYPONDPREFIX']
-       while datadir[-1] == os.sep:
-               datadir= datadir[:-1]
-       libdir = datadir.replace ('/share/', '/lib/')
+    datadir = os.environ['LILYPONDPREFIX']
+    while datadir[-1] == os.sep:
+        datadir= datadir[:-1]
+    libdir = datadir.replace ('/share/', '/lib/')
 
 if os.path.exists (os.path.join (datadir, 'lib/lilypond/@TOPLEVEL_VERSION@/')):
-       libdir = os.path.join (libdir, 'lib/lilypond/@TOPLEVEL_VERSION@/')
-        
+    libdir = os.path.join (libdir, 'lib/lilypond/@TOPLEVEL_VERSION@/')
+    
 if os.path.exists (os.path.join (datadir, 'lib/lilypond/current/')):
-       libdir = os.path.join (libdir, 'lib/lilypond/current/')
-        
+    libdir = os.path.join (libdir, 'lib/lilypond/current/')
+    
 sys.path.insert (0, os.path.join (libdir, 'python'))
 
 # dynamic relocation, for GUB binaries.
 bindir = os.path.split (sys.argv[0])[0]
 for p in ['share', 'lib']:
-       datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % p)
-       sys.path.insert (0, datadir)
+    datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % p)
+    sys.path.insert (0, datadir)
 
 ################################################################
 
 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
 
-       if bank_number == 1:
-               # minor scale
-               p = transpose (p, (5, 0))
-       p  = (p[0] % 7, p[1])
+    if bank_number == 1:
+        # minor scale
+        p = transpose (p, (5, 0))
+    p  = (p[0] % 7, p[1])
 
-       return KeySignature (p, bank_number)
+    return KeySignature (p, bank_number)
 
 # should cache this.
 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
+    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
 
 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)      
+    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
+    (n,d) = rat
 
-       basedur = 1
-       while d and  d % 2 == 0:
-               basedur = basedur << 1
-               d = d >> 1
+    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
+    str = 's%d' % basedur
+    if n <> 1:
+        str = str + '*%d' % n
+    if d <> 1:
+        str = str + '/%d' % d
 
-       return str
+    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 = \\lyricmode {\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
-       
+    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
-               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 __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 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 = string.join (map (lambda x: '(volta %s)' % x, 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 __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 = string.join (map (lambda x: '(volta %s)' % x, 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 (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)
+
+
+
+    
 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 = string.split (gulp, '\n^')
 
-       etf_file_dict = {}
-       for k in tag_dict.keys (): 
-               etf_file_dict[k] = {}
+    etf_file_dict = {}
+    for k in tag_dict.keys (): 
+        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 (map (string.atoi, string.split (m.group (2), ',')))
+            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 += '\\version "2.3.25"\n'
-                       str = str + '<<\n  %s\n>> } ' % 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:
+            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 += '\\version "2.3.25"\n'
+            str = str + '<<\n  %s\n>> } ' % 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 identify():
-       sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version))
+    sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version))
 
 def warranty ():
-       identify ()
-       sys.stdout.write ('''
+    identify ()
+    sys.stdout.write ('''
 Copyright (c) %s by
 
 Han-Wen Nienhuys
 Jan Nieuwenhuizen
+ Han-Wen Nienhuys
+ Jan Nieuwenhuizen
 
 %s
 %s
 ''' % ( '2001--2006',
-       _('Distributed under terms of the GNU General Public License.'),
-       _('It comes with NO WARRANTY.')))
+   _('Distributed under terms of the GNU General Public License.'),
+   _('It comes with NO WARRANTY.')))
 
 
 
 def get_option_parser ():
-       p = ly.get_option_parser (usage='etf2ly [OPTIONS]... ETF-FILE',
-                                 version="etf2ly (LilyPond) @TOPLEVEL_VERSION@",
-                                 description=_("""Enigma Transport Format is a format used by Coda Music Technology's
+    p = ly.get_option_parser (usage='etf2ly [OPTIONS]... ETF-FILE',
+                 version="etf2ly (LilyPond) @TOPLEVEL_VERSION@",
+                 description=_("""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."""))
-       p.add_option ('-o', '--output', help=_("write output to FILE"),
-                     metavar=_("FILE"),
-                     action='store')
-       p.add_option ('-w', '--warranty', help=_ ("show warranty"),
-                     action='store_true',
-                     ),
-
-       p.add_option_group  ('bugs',
-                            description='''Report bugs via http://post.gmane.org/post.php'''
-                            '''?group=gmane.comp.gnu.lilypond.bugs\n''')
-       return p
+    p.add_option ('-o', '--output', help=_("write output to FILE"),
+           metavar=_("FILE"),
+           action='store')
+    p.add_option ('-w', '--warranty', help=_ ("show warranty"),
+           action='store_true',
+           ),
+
+    p.add_option_group  ('bugs',
+              description='''Report bugs via 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)
+    opt_parser = get_option_parser()
+    (options,args) = opt_parser.parse_args ()
+    if options.warranty:
+        warranty ()
+        sys.exit (0)
 
-       return (options,args)
+    return (options,args)
 
 (options, files) = do_options()
 identify()
@@ -1236,26 +1236,26 @@ 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 ()
+    
index 32829bdb47ed3941c80a5e072ccab0d0883d5d1f..2faaa9c3bfdbd042911dd55eac047d40ad771a75 100644 (file)
@@ -4,27 +4,27 @@
 Example usage:
 
 test:
-     lilypond-book --filter="tr '[a-z]' '[A-Z]'" BOOK
+  lilypond-book --filter="tr '[a-z]' '[A-Z]'" BOOK
 
 convert-ly on book:
-     lilypond-book --filter="convert-ly --no-version --from=1.6.11 -" BOOK
+  lilypond-book --filter="convert-ly --no-version --from=1.6.11 -" BOOK
 
 classic lilypond-book:
-     lilypond-book --process="lilypond" BOOK.tely
+  lilypond-book --process="lilypond" BOOK.tely
 
 TODO:
 
-    *  this script is too complex. Modularize.
-    
-    *  ly-options: intertext?
-    *  --line-width?
-    *  eps in latex / eps by lilypond -b ps?
-    *  check latex parameters, twocolumn, multicolumn?
-    *  use --png --ps --pdf for making images?
+  *  this script is too complex. Modularize.
+  
+  *  ly-options: intertext?
+  *  --line-width?
+  *  eps in latex / eps by lilypond -b ps?
+  *  check latex parameters, twocolumn, multicolumn?
+  *  use --png --ps --pdf for making images?
 
-    *  Converting from lilypond-book source, substitute:
-       @mbinclude foo.itely -> @include foo.itely
-       \mbinput -> \input
+  *  Converting from lilypond-book source, substitute:
+   @mbinclude foo.itely -> @include foo.itely
+   \mbinput -> \input
 
 '''
 
@@ -51,16 +51,16 @@ import re
 
 datadir = '@local_lilypond_datadir@'
 if not os.path.isdir (datadir):
-       datadir = '@lilypond_datadir@'
+    datadir = '@lilypond_datadir@'
 
 sys.path.insert (0, os.path.join (datadir, 'python'))
 
 if os.environ.has_key ('LILYPONDPREFIX'):
-       datadir = os.environ['LILYPONDPREFIX']
-       while datadir[-1] == os.sep:
-               datadir= datadir[:-1]
-               
-       datadir = os.path.join (datadir, "share/lilypond/current/")
+    datadir = os.environ['LILYPONDPREFIX']
+    while datadir[-1] == os.sep:
+        datadir= datadir[:-1]
+        
+    datadir = os.path.join (datadir, "share/lilypond/current/")
 sys.path.insert (0, os.path.join (datadir, 'python'))
 
 # dynamic relocation, for GUB binaries.
@@ -68,8 +68,8 @@ bindir = os.path.split (sys.argv[0])[0]
 
 
 for prefix_component in ['share', 'lib']:
-       datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % prefix_component)
-       sys.path.insert (0, datadir)
+    datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % prefix_component)
+    sys.path.insert (0, datadir)
 
 
 import lilylib as ly
@@ -89,44 +89,44 @@ help_summary = _ (
 
 Example usage:
 
  lilypond-book --filter="tr '[a-z]' '[A-Z]'" BOOK
  lilypond-book --filter="convert-ly --no-version --from=2.0.0 -" BOOK
  lilypond-book --process='lilypond -I include' BOOK
+ lilypond-book --filter="tr '[a-z]' '[A-Z]'" BOOK
+ lilypond-book --filter="convert-ly --no-version --from=2.0.0 -" BOOK
+ lilypond-book --process='lilypond -I include' BOOK
 ''')
 
 authors = ('Jan Nieuwenhuizen <janneke@gnu.org>',
-            'Han-Wen Nienhuys <hanwen@cs.uu.nl>')
+      'Han-Wen Nienhuys <hanwen@cs.uu.nl>')
 
-       
+    
 ################################################################
 def exit (i):
-       if global_options.verbose:
-               raise _ ('Exiting (%d)...') % i
-       else:
-               sys.exit (i)
+    if global_options.verbose:
+        raise _ ('Exiting (%d)...') % i
+    else:
+        sys.exit (i)
 
 def identify ():
-       sys.stdout.write ('%s (GNU LilyPond) %s\n' % (program_name, program_version))
+    sys.stdout.write ('%s (GNU LilyPond) %s\n' % (program_name, program_version))
 
 def progress (s):
-       sys.stderr.write (s)
+    sys.stderr.write (s)
 
 def warning (s):
-       sys.stderr.write (program_name + ": " + _ ("warning: %s") % s + '\n')
+    sys.stderr.write (program_name + ": " + _ ("warning: %s") % s + '\n')
 
 def error (s):
-       sys.stderr.write (program_name + ": " + _ ("error: %s") % s + '\n')
+    sys.stderr.write (program_name + ": " + _ ("error: %s") % s + '\n')
 
 def ps_page_count (ps_name):
-       header = open (ps_name).read (1024)
-       m = re.search ('\n%%Pages: ([0-9]+)', header)
-       if m:
-               return string.atoi (m.group (1))
-       return 0
+    header = open (ps_name).read (1024)
+    m = re.search ('\n%%Pages: ([0-9]+)', header)
+    if m:
+        return string.atoi (m.group (1))
+    return 0
 
 def warranty ():
-       identify ()
-       sys.stdout.write ('''
+    identify ()
+    sys.stdout.write ('''
 %s
 
 %s
@@ -134,62 +134,62 @@ def warranty ():
 %s
 %s
 ''' % ( _('Copyright (c) %s by') % '2001--2006',
-       ' '.join (authors),
-       _('Distributed under terms of the GNU General Public License.'),
-       _('It comes with NO WARRANTY.')))
+    ' '.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='lilypond-book [OPTIONS] FILE',
-                                 version="@TOPLEVEL_VERSION@",
-                                 description=help_summary)
-
-       p.add_option ('-F', '--filter', metavar=_ ("FILTER"),
-                     action="store",
-                     dest="filter_cmd",
-                     help=_ ("pipe snippets through FILTER [convert-ly -n -]"),
-                     default=None)
-       p.add_option ('-f', '--format', help=_('''use output format FORMAT (texi [default], texi-html, latex, html)'''),
-                     action='store')
-       p.add_option ("-I", '--include', help=_('add DIR to include path'),
-                     metavar="DIR",
-                     action='append', dest='include_path',
-                     default=[os.path.abspath (os.getcwd ())])
-       
-       p.add_option ("-o", '--output', help=_('write output to DIR'),
-                     metavar="DIR",
-                     action='store', dest='output_name',
-                     default='')
-       p.add_option ('-P', '--process', metavar=_("COMMAND"),
-                     help = _ ("process ly_files using COMMAND FILE..."),
-                     action='store', 
-                     dest='process_cmd', default='lilypond -b eps')
-       
-       p.add_option ('', '--psfonts', action="store_true", dest="psfonts",
-                     help=_ ('''extract all PostScript fonts into INPUT.psfonts for LaTeX'''
-                             '''must use this with dvips -h INPUT.psfonts'''),
-                     default=None)
-       p.add_option ('-V', '--verbose', help=_("be verbose"),
-                     action="store_true",
-                     default=False,
-                     dest="verbose")
-                     
-       p.add_option ('-w', '--warranty',
-                     help=_("show warranty and copyright"),
-                     action='store_true')
-
-       
-       p.add_option_group  ('bugs',
-                            description='''Report bugs via http://post.gmane.org/post.php'''
-                            '''?group=gmane.comp.gnu.lilypond.bugs\n''')
-       
-       return p
+    p = ly.get_option_parser (usage='lilypond-book [OPTIONS] FILE',
+                 version="@TOPLEVEL_VERSION@",
+                 description=help_summary)
+
+    p.add_option ('-F', '--filter', metavar=_ ("FILTER"),
+           action="store",
+           dest="filter_cmd",
+           help=_ ("pipe snippets through FILTER [convert-ly -n -]"),
+           default=None)
+    p.add_option ('-f', '--format', help=_('''use output format FORMAT (texi [default], texi-html, latex, html)'''),
+           action='store')
+    p.add_option ("-I", '--include', help=_('add DIR to include path'),
+           metavar="DIR",
+           action='append', dest='include_path',
+           default=[os.path.abspath (os.getcwd ())])
+    
+    p.add_option ("-o", '--output', help=_('write output to DIR'),
+           metavar="DIR",
+           action='store', dest='output_name',
+           default='')
+    p.add_option ('-P', '--process', metavar=_("COMMAND"),
+           help = _ ("process ly_files using COMMAND FILE..."),
+           action='store', 
+           dest='process_cmd', default='lilypond -b eps')
+    
+    p.add_option ('', '--psfonts', action="store_true", dest="psfonts",
+           help=_ ('''extract all PostScript fonts into INPUT.psfonts for LaTeX'''
+               '''must use this with dvips -h INPUT.psfonts'''),
+           default=None)
+    p.add_option ('-V', '--verbose', help=_("be verbose"),
+           action="store_true",
+           default=False,
+           dest="verbose")
+           
+    p.add_option ('-w', '--warranty',
+           help=_("show warranty and copyright"),
+           action='store_true')
+
+    
+    p.add_option_group  ('bugs',
+              description='''Report bugs via http://post.gmane.org/post.php'''
+              '''?group=gmane.comp.gnu.lilypond.bugs\n''')
+    
+    return p
 
 lilypond_binary = os.path.join ('@bindir@', 'lilypond')
 
 # Only use installed binary when we are installed too.
 if '@bindir@' == ('@' + 'bindir@') or not os.path.exists (lilypond_binary):
-       lilypond_binary = 'lilypond'
+    lilypond_binary = 'lilypond'
 
 global_options = None
 
@@ -235,8 +235,8 @@ ALT = 'alt'
 # NOTIME has no opposite so it isn't part of this dictionary.
 # NOQUOTE is used internally only.
 no_options = {
-       NOFRAGMENT: FRAGMENT,
-       NOINDENT: INDENT,
+    NOFRAGMENT: FRAGMENT,
+    NOINDENT: INDENT,
 }
 
 
@@ -249,361 +249,361 @@ no_options = {
 #   (?x) -- Ignore whitespace in patterns.
 no_match = 'a\ba'
 snippet_res = {
-       ##
-       HTML: {
-               'include':
-                 no_match,
-
-               'lilypond':
-                 r'''(?mx)
-                   (?P<match>
-                   <lilypond
-                     (\s*(?P<options>.*?)\s*:)?\s*
-                     (?P<code>.*?)
-                   />)''',
-
-               'lilypond_block':
-                 r'''(?msx)
-                   (?P<match>
-                   <lilypond
-                     \s*(?P<options>.*?)\s*
-                   >
-                   (?P<code>.*?)
-                   </lilypond>)''',
-
-               'lilypond_file':
-                 r'''(?mx)
-                   (?P<match>
-                   <lilypondfile
-                     \s*(?P<options>.*?)\s*
-                   >
-                   \s*(?P<filename>.*?)\s*
-                   </lilypondfile>)''',
-
-               'multiline_comment':
-                 r'''(?smx)
-                   (?P<match>
-                   \s*(?!@c\s+)
-                   (?P<code><!--\s.*?!-->)
-                   \s)''',
-
-               'singleline_comment':
-                 no_match,
-
-               'verb':
-                 r'''(?x)
-                   (?P<match>
-                     (?P<code><pre>.*?</pre>))''',
-
-               'verbatim':
-                 r'''(?x)
-                   (?s)
-                   (?P<match>
-                     (?P<code><pre>\s.*?</pre>\s))''',
-       },
-
-       ##
-       LATEX: {
-               'include':
-                 r'''(?smx)
-                   ^[^%\n]*?
-                   (?P<match>
-                   \\input\s*{
-                     (?P<filename>\S+?)
-                   })''',
-
-               'lilypond':
-                 r'''(?smx)
-                   ^[^%\n]*?
-                   (?P<match>
-                   \\lilypond\s*(
-                   \[
-                     \s*(?P<options>.*?)\s*
-                   \])?\s*{
-                     (?P<code>.*?)
-                   })''',
-
-               'lilypond_block':
-                 r'''(?smx)
-                   ^[^%\n]*?
-                   (?P<match>
-                   \\begin\s*(
-                   \[
-                     \s*(?P<options>.*?)\s*
-                   \])?\s*{lilypond}
-                     (?P<code>.*?)
-                   ^[^%\n]*?
-                   \\end\s*{lilypond})''',
-
-               'lilypond_file':
-                 r'''(?smx)
-                   ^[^%\n]*?
-                   (?P<match>
-                   \\lilypondfile\s*(
-                   \[
-                     \s*(?P<options>.*?)\s*
-                   \])?\s*\{
-                     (?P<filename>\S+?)
-                   })''',
-
-               'multiline_comment':
-                 no_match,
-
-               'singleline_comment':
-                 r'''(?mx)
-                   ^.*?
-                   (?P<match>
-                     (?P<code>
-                     %.*$\n+))''',
-
-               'verb':
-                 r'''(?mx)
-                   ^[^%\n]*?
-                   (?P<match>
-                     (?P<code>
-                     \\verb(?P<del>.)
-                       .*?
-                     (?P=del)))''',
-
-               'verbatim':
-                 r'''(?msx)
-                   ^[^%\n]*?
-                   (?P<match>
-                     (?P<code>
-                     \\begin\s*{verbatim}
-                       .*?
-                     \\end\s*{verbatim}))''',
-       },
-
-       ##
-       TEXINFO: {
-               'include':
-                 r'''(?mx)
-                   ^(?P<match>
-                   @include\s+
-                     (?P<filename>\S+))''',
-
-               'lilypond':
-                 r'''(?smx)
-                   ^[^\n]*?(?!@c\s+)[^\n]*?
-                   (?P<match>
-                   @lilypond\s*(
-                   \[
-                     \s*(?P<options>.*?)\s*
-                   \])?\s*{
-                     (?P<code>.*?)
-                   })''',
-
-               'lilypond_block':
-                 r'''(?msx)
-                   ^(?P<match>
-                   @lilypond\s*(
-                   \[
-                     \s*(?P<options>.*?)\s*
-                   \])?\s+?
-                   ^(?P<code>.*?)
-                   ^@end\s+lilypond)\s''',
-
-               'lilypond_file':
-                 r'''(?mx)
-                   ^(?P<match>
-                   @lilypondfile\s*(
-                   \[
-                     \s*(?P<options>.*?)\s*
-                   \])?\s*{
-                     (?P<filename>\S+)
-                   })''',
-
-               'multiline_comment':
-                 r'''(?smx)
-                   ^(?P<match>
-                     (?P<code>
-                     @ignore\s
-                       .*?
-                     @end\s+ignore))\s''',
-
-               'singleline_comment':
-                 r'''(?mx)
-                   ^.*
-                   (?P<match>
-                     (?P<code>
-                     @c([ \t][^\n]*|)\n))''',
-
-       # Don't do this: It interferes with @code{@{}.
-       #       'verb': r'''(?P<code>@code{.*?})''',
-
-               'verbatim':
-                 r'''(?sx)
-                   (?P<match>
-                     (?P<code>
-                     @example
-                       \s.*?
-                     @end\s+example\s))''',
-       },
+    ##
+    HTML: {
+        'include':
+         no_match,
+
+        'lilypond':
+         r'''(?mx)
+          (?P<match>
+          <lilypond
+           (\s*(?P<options>.*?)\s*:)?\s*
+           (?P<code>.*?)
+          />)''',
+
+        'lilypond_block':
+         r'''(?msx)
+          (?P<match>
+          <lilypond
+           \s*(?P<options>.*?)\s*
+          >
+          (?P<code>.*?)
+          </lilypond>)''',
+
+        'lilypond_file':
+         r'''(?mx)
+          (?P<match>
+          <lilypondfile
+           \s*(?P<options>.*?)\s*
+          >
+          \s*(?P<filename>.*?)\s*
+          </lilypondfile>)''',
+
+        'multiline_comment':
+         r'''(?smx)
+          (?P<match>
+          \s*(?!@c\s+)
+          (?P<code><!--\s.*?!-->)
+          \s)''',
+
+        'singleline_comment':
+         no_match,
+
+        'verb':
+         r'''(?x)
+          (?P<match>
+           (?P<code><pre>.*?</pre>))''',
+
+        'verbatim':
+         r'''(?x)
+          (?s)
+          (?P<match>
+           (?P<code><pre>\s.*?</pre>\s))''',
+    },
+
+    ##
+    LATEX: {
+        'include':
+         r'''(?smx)
+          ^[^%\n]*?
+          (?P<match>
+          \\input\s*{
+           (?P<filename>\S+?)
+          })''',
+
+        'lilypond':
+         r'''(?smx)
+          ^[^%\n]*?
+          (?P<match>
+          \\lilypond\s*(
+          \[
+           \s*(?P<options>.*?)\s*
+          \])?\s*{
+           (?P<code>.*?)
+          })''',
+
+        'lilypond_block':
+         r'''(?smx)
+          ^[^%\n]*?
+          (?P<match>
+          \\begin\s*(
+          \[
+           \s*(?P<options>.*?)\s*
+          \])?\s*{lilypond}
+           (?P<code>.*?)
+          ^[^%\n]*?
+          \\end\s*{lilypond})''',
+
+        'lilypond_file':
+         r'''(?smx)
+          ^[^%\n]*?
+          (?P<match>
+          \\lilypondfile\s*(
+          \[
+           \s*(?P<options>.*?)\s*
+          \])?\s*\{
+           (?P<filename>\S+?)
+          })''',
+
+        'multiline_comment':
+         no_match,
+
+        'singleline_comment':
+         r'''(?mx)
+          ^.*?
+          (?P<match>
+           (?P<code>
+           %.*$\n+))''',
+
+        'verb':
+         r'''(?mx)
+          ^[^%\n]*?
+          (?P<match>
+           (?P<code>
+           \\verb(?P<del>.)
+            .*?
+           (?P=del)))''',
+
+        'verbatim':
+         r'''(?msx)
+          ^[^%\n]*?
+          (?P<match>
+           (?P<code>
+           \\begin\s*{verbatim}
+            .*?
+           \\end\s*{verbatim}))''',
+    },
+
+    ##
+    TEXINFO: {
+        'include':
+         r'''(?mx)
+          ^(?P<match>
+          @include\s+
+           (?P<filename>\S+))''',
+
+        'lilypond':
+         r'''(?smx)
+          ^[^\n]*?(?!@c\s+)[^\n]*?
+          (?P<match>
+          @lilypond\s*(
+          \[
+           \s*(?P<options>.*?)\s*
+          \])?\s*{
+           (?P<code>.*?)
+          })''',
+
+        'lilypond_block':
+         r'''(?msx)
+          ^(?P<match>
+          @lilypond\s*(
+          \[
+           \s*(?P<options>.*?)\s*
+          \])?\s+?
+          ^(?P<code>.*?)
+          ^@end\s+lilypond)\s''',
+
+        'lilypond_file':
+         r'''(?mx)
+          ^(?P<match>
+          @lilypondfile\s*(
+          \[
+           \s*(?P<options>.*?)\s*
+          \])?\s*{
+           (?P<filename>\S+)
+          })''',
+
+        'multiline_comment':
+         r'''(?smx)
+          ^(?P<match>
+           (?P<code>
+           @ignore\s
+            .*?
+           @end\s+ignore))\s''',
+
+        'singleline_comment':
+         r'''(?mx)
+          ^.*
+          (?P<match>
+           (?P<code>
+           @c([ \t][^\n]*|)\n))''',
+
+    # Don't do this: It interferes with @code{@{}.
+           'verb': r'''(?P<code>@code{.*?})''',
+
+        'verbatim':
+         r'''(?sx)
+          (?P<match>
+           (?P<code>
+           @example
+            \s.*?
+           @end\s+example\s))''',
+    },
 }
 
 
 
 
 format_res = {
-       HTML: {
-               'intertext': r',?\s*intertext=\".*?\"',
-               'option_sep': '\s*',
-       },
-
-       LATEX: {
-               'intertext': r',?\s*intertext=\".*?\"',
-               'option_sep': '\s*,\s*',
-       },
-
-       TEXINFO: {
-               'intertext': r',?\s*intertext=\".*?\"',
-               'option_sep': '\s*,\s*',
-       },
+    HTML: {
+        'intertext': r',?\s*intertext=\".*?\"',
+        'option_sep': '\s*',
+    },
+
+    LATEX: {
+        'intertext': r',?\s*intertext=\".*?\"',
+        'option_sep': '\s*,\s*',
+    },
+
+    TEXINFO: {
+        'intertext': r',?\s*intertext=\".*?\"',
+        'option_sep': '\s*,\s*',
+    },
 }
 
 # Options without a pattern in ly_options.
 simple_options = [
-       EXAMPLEINDENT,
-       FRAGMENT,
-       NOFRAGMENT,
-       NOINDENT,
-       PRINTFILENAME,
-       TEXIDOC,
-       VERBATIM,
-       FONTLOAD,
-       FILENAME,
-       ALT
+    EXAMPLEINDENT,
+    FRAGMENT,
+    NOFRAGMENT,
+    NOINDENT,
+    PRINTFILENAME,
+    TEXIDOC,
+    VERBATIM,
+    FONTLOAD,
+    FILENAME,
+    ALT
 ]
 
 ly_options = {
-       ##
-       NOTES: {
-               RELATIVE: r'''\relative c%(relative_quotes)s''',
-       },
-
-       ##
-       PAPER: {
-               INDENT: r'''indent = %(indent)s''',
-
-               LINE_WIDTH: r'''line-width = %(line-width)s''',
-
-               QUOTE: r'''line-width = %(line-width)s - 2.0 * %(exampleindent)s''',
-
-               RAGGED_RIGHT: r'''ragged-right = ##t''',
-
-               PACKED: r'''packed = ##t''',
-       },
-
-       ##
-       LAYOUT: {
-               NOTIME: r'''
 \context {
-    \Score
-    timing = ##f
 }
 \context {
-    \Staff
-    \remove Time_signature_engraver
 }''',
-       },
-
-       ##
-       PREAMBLE: {
-               STAFFSIZE: r'''#(set-global-staff-size %(staffsize)s)''',
-       },
+    ##
+    NOTES: {
+        RELATIVE: r'''\relative c%(relative_quotes)s''',
+    },
+
+    ##
+    PAPER: {
+        INDENT: r'''indent = %(indent)s''',
+
+        LINE_WIDTH: r'''line-width = %(line-width)s''',
+
+        QUOTE: r'''line-width = %(line-width)s - 2.0 * %(exampleindent)s''',
+
+        RAGGED_RIGHT: r'''ragged-right = ##t''',
+
+        PACKED: r'''packed = ##t''',
+    },
+
+    ##
+    LAYOUT: {
+        NOTIME: r'''
+ \context {
+  \Score
+  timing = ##f
+ }
+ \context {
+  \Staff
+  \remove Time_signature_engraver
+ }''',
+    },
+
+    ##
+    PREAMBLE: {
+        STAFFSIZE: r'''#(set-global-staff-size %(staffsize)s)''',
+    },
 }
 
 output = {
-       ##
-       HTML: {
-               FILTER: r'''<lilypond %(options)s>
+    ##
+    HTML: {
+        FILTER: r'''<lilypond %(options)s>
 %(code)s
 </lilypond>
 ''',
 
-               AFTER: r'''
 </a>
+        AFTER: r'''
+ </a>
 </p>''',
 
-               BEFORE: r'''<p>
 <a href="%(base)s.ly">''',
+        BEFORE: r'''<p>
+ <a href="%(base)s.ly">''',
 
-               OUTPUT: r'''
-    <img align="center" valign="center"
-        border="0" src="%(image)s" alt="%(alt)s">''',
+        OUTPUT: r'''
+  <img align="center" valign="center"
+    border="0" src="%(image)s" alt="%(alt)s">''',
 
-               PRINTFILENAME: '<p><tt><a href="%(base)s.ly">%(filename)s</a></tt></p>',
+        PRINTFILENAME: '<p><tt><a href="%(base)s.ly">%(filename)s</a></tt></p>',
 
-               QUOTE: r'''<blockquote>
+        QUOTE: r'''<blockquote>
 %(str)s
 </blockquote>
 ''',
 
-               VERBATIM: r'''<pre>
+        VERBATIM: r'''<pre>
 %(verb)s</pre>''',
-       },
+    },
 
-       ##
-       LATEX: {
-               OUTPUT: r'''{%%
+    ##
+    LATEX: {
+        OUTPUT: r'''{%%
 \parindent 0pt%%
 \catcode`\@=12%%
 \ifx\preLilyPondExample \undefined%%
 \relax%%
+ \relax%%
 \else%%
 \preLilyPondExample%%
+ \preLilyPondExample%%
 \fi%%
 \def\lilypondbook{}%%
 \input %(base)s-systems.tex%%
 \ifx\postLilyPondExample \undefined%%
 \relax%%
+ \relax%%
 \else%%
 \postLilyPondExample%%
+ \postLilyPondExample%%
 \fi%%
 }''',
 
-               PRINTFILENAME: '''\\texttt{%(filename)s}
-       ''',
+        PRINTFILENAME: '''\\texttt{%(filename)s}
+    ''',
 
-               QUOTE: r'''\begin{quotation}%(str)s
+        QUOTE: r'''\begin{quotation}%(str)s
 \end{quotation}''',
 
-               VERBATIM: r'''\noindent
+        VERBATIM: r'''\noindent
 \begin{verbatim}%(verb)s\end{verbatim}''',
 
-               FILTER: r'''\begin{lilypond}[%(options)s]
+        FILTER: r'''\begin{lilypond}[%(options)s]
 %(code)s
 \end{lilypond}''',
-       },
+    },
 
-       ##
-       TEXINFO: {
-               FILTER: r'''@lilypond[%(options)s]
+    ##
+    TEXINFO: {
+        FILTER: r'''@lilypond[%(options)s]
 %(code)s
 @lilypond''',
 
-               OUTPUT: r'''
+        OUTPUT: r'''
 @iftex
 @include %(base)s-systems.texi
 @end iftex
 ''',
 
-               OUTPUTIMAGE: r'''@noindent
+        OUTPUTIMAGE: r'''@noindent
 @ifinfo
 @image{%(base)s,,,%(alt)s,%(ext)s}
 @end ifinfo
 @html
 <p>
 <a href="%(base)s.ly">
-    <img align="center" valign="center"
-        border="0" src="%(image)s" alt="%(alt)s">
 </a>
+ <a href="%(base)s.ly">
+  <img align="center" valign="center"
+    border="0" src="%(image)s" alt="%(alt)s">
+ </a>
 </p>
 @end html
 ''',
 
-               PRINTFILENAME: '''
+        PRINTFILENAME: '''
 @html
 <a href="%(base)s.ly">
 @end html
@@ -611,21 +611,21 @@ output = {
 @html
 </a>
 @end html
-       ''',
+    ''',
 
-               QUOTE: r'''@quotation
+        QUOTE: r'''@quotation
 %(str)s@end quotation
 ''',
 
-               NOQUOTE: r'''@format
+        NOQUOTE: r'''@format
 %(str)s@end format
 ''',
 
-               VERBATIM: r'''@exampleindent 0
+        VERBATIM: r'''@exampleindent 0
 @verbatim
 %(verb)s@end verbatim
 ''',
-       },
+    },
 }
 
 #
@@ -634,9 +634,9 @@ output = {
 
 ## TODO
 if 0:
-       for f in [HTML, LATEX]:
-               for s in (QUOTE, VERBATIM):
-                       output[f][s] = output[f][s].replace("\n"," ")
+    for f in [HTML, LATEX]:
+        for s in (QUOTE, VERBATIM):
+            output[f][s] = output[f][s].replace("\n"," ")
 
 
 PREAMBLE_LY = '''%%%% Generated by %(program_name)s
@@ -644,10 +644,10 @@ PREAMBLE_LY = '''%%%% Generated by %(program_name)s
 
 #(set! toplevel-score-handler print-score-with-defaults)
 #(set! toplevel-music-handler
 (lambda (p m)
  (if (not (eq? (ly:music-property m \'void) #t))
-        (print-score-with-defaults
-         p (scorify-music m p)))))
+ (lambda (p m)
+ (if (not (eq? (ly:music-property m \'void) #t))
+    (print-score-with-defaults
+    p (scorify-music m p)))))
 
 #(ly:set-option (quote no-point-and-click))
 #(define inside-lilypond-book #t)
@@ -664,13 +664,13 @@ PREAMBLE_LY = '''%%%% Generated by %(program_name)s
 %% ****************************************************************
 
 \paper {
 #(define dump-extents #t)
 %(font_dump_setting)s
 %(paper_string)s
+ #(define dump-extents #t)
+ %(font_dump_setting)s
+ %(paper_string)s
 }
 
 \layout {
 %(layout_string)s
+ %(layout_string)s
 }
 '''
 
@@ -706,696 +706,696 @@ FULL_LY = '''
 '''
 
 texinfo_line_widths = {
-       '@afourpaper': '160\\mm',
-       '@afourwide': '6.5\\in',
-       '@afourlatex': '150\\mm',
-       '@smallbook': '5\\in',
-       '@letterpaper': '6\\in',
+    '@afourpaper': '160\\mm',
+    '@afourwide': '6.5\\in',
+    '@afourlatex': '150\\mm',
+    '@smallbook': '5\\in',
+    '@letterpaper': '6\\in',
 }
 
 def classic_lilypond_book_compatibility (key, value):
-       if key == 'singleline' and value == None:
-               return (RAGGED_RIGHT, None)
+    if key == 'singleline' and value == None:
+        return (RAGGED_RIGHT, None)
 
-       m = re.search ('relative\s*([-0-9])', key)
-       if m:
-               return ('relative', m.group (1))
+    m = re.search ('relative\s*([-0-9])', key)
+    if m:
+        return ('relative', m.group (1))
 
-       m = re.match ('([0-9]+)pt', key)
-       if m:
-               return ('staffsize', m.group (1))
+    m = re.match ('([0-9]+)pt', key)
+    if m:
+        return ('staffsize', m.group (1))
 
-       if key == 'indent' or key == 'line-width':
-               m = re.match ('([-.0-9]+)(cm|in|mm|pt|staffspace)', value)
-               if m:
-                       f = float (m.group (1))
-                       return (key, '%f\\%s' % (f, m.group (2)))
+    if key == 'indent' or key == 'line-width':
+        m = re.match ('([-.0-9]+)(cm|in|mm|pt|staffspace)', value)
+        if m:
+            f = float (m.group (1))
+            return (key, '%f\\%s' % (f, m.group (2)))
 
-       return (None, None)
+    return (None, None)
 
 def find_file (name):
-       for i in global_options.include_path:
-               full = os.path.join (i, name)
-               if os.path.exists (full):
-                       return full
-               
-       error (_ ("file not found: %s") % name + '\n')
-       exit (1)
-       return ''
+    for i in global_options.include_path:
+        full = os.path.join (i, name)
+        if os.path.exists (full):
+            return full
+        
+    error (_ ("file not found: %s") % name + '\n')
+    exit (1)
+    return ''
 
 def verbatim_html (s):
-       return re.sub ('>', '&gt;',
-                      re.sub ('<', '&lt;',
-                              re.sub ('&', '&amp;', s)))
+    return re.sub ('>', '&gt;',
+           re.sub ('<', '&lt;',
+               re.sub ('&', '&amp;', s)))
 
 def split_options (option_string):
-       if option_string:
-               if global_options.format == HTML:
-                       options = re.findall('[\w\.-:]+(?:\s*=\s*(?:"[^"]*"|\'[^\']*\'|\S+))?',option_string)
-                       for i in range(len(options)):
-                               options[i] = re.sub('^([^=]+=\s*)(?P<q>["\'])(.*)(?P=q)','\g<1>\g<3>',options[i])
-                       return options
-               else:
-                       return re.split (format_res[global_options.format]['option_sep'],
-                                        option_string)
-       return []
+    if option_string:
+        if global_options.format == HTML:
+            options = re.findall('[\w\.-:]+(?:\s*=\s*(?:"[^"]*"|\'[^\']*\'|\S+))?',option_string)
+            for i in range(len(options)):
+                options[i] = re.sub('^([^=]+=\s*)(?P<q>["\'])(.*)(?P=q)','\g<1>\g<3>',options[i])
+            return options
+        else:
+            return re.split (format_res[global_options.format]['option_sep'],
+                    option_string)
+    return []
 
 def set_default_options (source):
-       global default_ly_options
-       if not default_ly_options.has_key (LINE_WIDTH):
-               if global_options.format == LATEX:
-                       textwidth = get_latex_textwidth (source)
-                       default_ly_options[LINE_WIDTH] = \
-                         '''%.0f\\pt''' % textwidth
-               elif global_options.format == TEXINFO:
-                       for (k, v) in texinfo_line_widths.items ():
-                               # FIXME: @layout is usually not in
-                               # chunk #0:
-                               #
-                               #  \input texinfo @c -*-texinfo-*-
-                               #
-                               # Bluntly search first K items of
-                               # source.
-                               # s = chunks[0].replacement_text ()
-                               if re.search (k, source[:1024]):
-                                       default_ly_options[LINE_WIDTH] = v
-                                       break
+    global default_ly_options
+    if not default_ly_options.has_key (LINE_WIDTH):
+        if global_options.format == LATEX:
+            textwidth = get_latex_textwidth (source)
+            default_ly_options[LINE_WIDTH] = \
+             '''%.0f\\pt''' % textwidth
+        elif global_options.format == TEXINFO:
+            for (k, v) in texinfo_line_widths.items ():
+                # FIXME: @layout is usually not in
+                # chunk #0:
+                #
+                #  \input texinfo @c -*-texinfo-*-
+                #
+                # Bluntly search first K items of
+                # source.
+                # s = chunks[0].replacement_text ()
+                if re.search (k, source[:1024]):
+                    default_ly_options[LINE_WIDTH] = v
+                    break
 
 class Chunk:
-       def replacement_text (self):
-               return ''
+    def replacement_text (self):
+        return ''
 
-       def filter_text (self):
-               return self.replacement_text ()
+    def filter_text (self):
+        return self.replacement_text ()
 
-       def ly_is_outdated (self):
-               return 0
+    def ly_is_outdated (self):
+        return 0
 
-       def png_is_outdated (self):
-               return 0
+    def png_is_outdated (self):
+        return 0
 
-       def is_plain (self):
-               return False
-       
+    def is_plain (self):
+        return False
+    
 class Substring (Chunk):
-       def __init__ (self, source, start, end, line_number):
-               self.source = source
-               self.start = start
-               self.end = end
-               self.line_number = line_number
-               self.override_text = None
-               
-       def is_plain (self):
-               return True
-
-       def replacement_text (self):
-               if self.override_text:
-                       return self.override_text
-               else:
-                       return self.source[self.start:self.end]
+    def __init__ (self, source, start, end, line_number):
+        self.source = source
+        self.start = start
+        self.end = end
+        self.line_number = line_number
+        self.override_text = None
+        
+    def is_plain (self):
+        return True
+
+    def replacement_text (self):
+        if self.override_text:
+            return self.override_text
+        else:
+            return self.source[self.start:self.end]
 
 class Snippet (Chunk):
-       def __init__ (self, type, match, format, line_number):
-               self.type = type
-               self.match = match
-               self.hash = 0
-               self.option_dict = {}
-               self.format = format
-               self.line_number = line_number
+    def __init__ (self, type, match, format, line_number):
+        self.type = type
+        self.match = match
+        self.hash = 0
+        self.option_dict = {}
+        self.format = format
+        self.line_number = line_number
 
-       def replacement_text (self):
-               return self.match.group ('match')
+    def replacement_text (self):
+        return self.match.group ('match')
 
-       def substring (self, s):
-               return self.match.group (s)
+    def substring (self, s):
+        return self.match.group (s)
 
-       def __repr__ (self):
-               return `self.__class__` + ' type = ' + self.type
+    def __repr__ (self):
+        return `self.__class__` + ' type = ' + self.type
 
 class Include_snippet (Snippet):
-       def processed_filename (self):
-               f = self.substring ('filename')
-               return os.path.splitext (f)[0] + format2ext[global_options.format]
+    def processed_filename (self):
+        f = self.substring ('filename')
+        return os.path.splitext (f)[0] + format2ext[global_options.format]
 
-       def replacement_text (self):
-               s = self.match.group ('match')
-               f = self.substring ('filename')
+    def replacement_text (self):
+        s = self.match.group ('match')
+        f = self.substring ('filename')
 
-               return re.sub (f, self.processed_filename (), s)
+        return re.sub (f, self.processed_filename (), s)
 
 class Lilypond_snippet (Snippet):
-       def __init__ (self, type, match, format, line_number):
-               Snippet.__init__ (self, type, match, format, line_number)
-               os = match.group ('options')
-               self.do_options (os, self.type)
-
-       def ly (self):
-               return self.substring ('code')
-
-       def full_ly (self):
-               s = self.ly ()
-               if s:
-                       return self.compose_ly (s)
-               return ''
-
-       def do_options (self, option_string, type):
-               self.option_dict = {}
-
-               options = split_options (option_string)
-
-               for i in options:
-                       if string.find (i, '=') > 0:
-                               (key, value) = re.split ('\s*=\s*', i)
-                               self.option_dict[key] = value
-                       else:
-                               if i in no_options.keys ():
-                                       if no_options[i] in self.option_dict.keys ():
-                                               del self.option_dict[no_options[i]]
-                               else:
-                                       self.option_dict[i] = None
-
-               has_line_width = self.option_dict.has_key (LINE_WIDTH)
-               no_line_width_value = 0
-
-               # If LINE_WIDTH is used without parameter, set it to default.
-               if has_line_width and self.option_dict[LINE_WIDTH] == None:
-                       no_line_width_value = 1
-                       del self.option_dict[LINE_WIDTH]
-
-               for i in default_ly_options.keys ():
-                       if i not in self.option_dict.keys ():
-                               self.option_dict[i] = default_ly_options[i]
-
-               if not has_line_width:
-                       if type == 'lilypond' or FRAGMENT in self.option_dict.keys ():
-                               self.option_dict[RAGGED_RIGHT] = None
-
-                       if type == 'lilypond':
-                               if LINE_WIDTH in self.option_dict.keys ():
-                                       del self.option_dict[LINE_WIDTH]
-                       else:
-                               if RAGGED_RIGHT in self.option_dict.keys ():
-                                       if LINE_WIDTH in self.option_dict.keys ():
-                                               del self.option_dict[LINE_WIDTH]
-
-                       if QUOTE in self.option_dict.keys () or type == 'lilypond':
-                               if LINE_WIDTH in self.option_dict.keys ():
-                                       del self.option_dict[LINE_WIDTH]
-
-               if not INDENT in self.option_dict.keys ():
-                       self.option_dict[INDENT] = '0\\mm'
-
-               # The QUOTE pattern from ly_options only emits the `line-width'
-               # keyword.
-               if has_line_width and QUOTE in self.option_dict.keys ():
-                       if no_line_width_value:
-                               del self.option_dict[LINE_WIDTH]
-                       else:
-                               del self.option_dict[QUOTE]
-
-       def compose_ly (self, code):
-               if FRAGMENT in self.option_dict.keys ():
-                       body = FRAGMENT_LY
-               else:
-                       body = FULL_LY
-
-               # Defaults.
-               relative = 1
-               override = {}
-               # The original concept of the `exampleindent' option is broken.
-               # It is not possible to get a sane value for @exampleindent at all
-               # without processing the document itself.  Saying
-               #
-               #   @exampleindent 0
-               #   @example
-               #   ...
-               #   @end example
-               #   @exampleindent 5
-               #
-               # causes ugly results with the DVI backend of texinfo since the
-               # default value for @exampleindent isn't 5em but 0.4in (or a smaller
-               # value).  Executing the above code changes the environment
-               # indentation to an unknown value because we don't know the amount
-               # of 1em in advance since it is font-dependent.  Modifying
-               # @exampleindent in the middle of a document is simply not
-               # supported within texinfo.
-               #
-               # As a consequence, the only function of @exampleindent is now to
-               # specify the amount of indentation for the `quote' option.
-               #
-               # To set @exampleindent locally to zero, we use the @format
-               # environment for non-quoted snippets.
-               override[EXAMPLEINDENT] = r'0.4\in'
-               override[LINE_WIDTH] = texinfo_line_widths['@smallbook']
-               override.update (default_ly_options)
-
-               option_list = []
-               for (key, value) in self.option_dict.items ():
-                       if value == None:
-                               option_list.append (key)
-                       else:
-                               option_list.append (key + '=' + value)
-               option_string = string.join (option_list, ',')
-
-               compose_dict = {}
-               compose_types = [NOTES, PREAMBLE, LAYOUT, PAPER]
-               for a in compose_types:
-                       compose_dict[a] = []
-
-               for (key, value) in self.option_dict.items ():
-                       (c_key, c_value) = \
-                         classic_lilypond_book_compatibility (key, value)
-                       if c_key:
-                               if c_value:
-                                       warning \
-                                         (_ ("deprecated ly-option used: %s=%s" \
-                                           % (key, value)))
-                                       warning \
-                                         (_ ("compatibility mode translation: %s=%s" \
-                                           % (c_key, c_value)))
-                               else:
-                                       warning \
-                                         (_ ("deprecated ly-option used: %s" \
-                                           % key))
-                                       warning \
-                                         (_ ("compatibility mode translation: %s" \
-                                           % c_key))
-
-                               (key, value) = (c_key, c_value)
-
-                       if value:
-                               override[key] = value
-                       else:
-                               if not override.has_key (key):
-                                       override[key] = None
-
-                       found = 0
-                       for type in compose_types:
-                               if ly_options[type].has_key (key):
-                                       compose_dict[type].append (ly_options[type][key])
-                                       found = 1
-                                       break
-
-                       if not found and key not in simple_options:
-                               warning (_ ("ignoring unknown ly option: %s") % key)
-
-               # URGS
-               if RELATIVE in override.keys () and override[RELATIVE]:
-                       relative = int (override[RELATIVE])
-
-               relative_quotes = ''
-
-               # 1 = central C
-               if relative < 0:
-                       relative_quotes += ',' * (- relative)
-               elif relative > 0:
-                       relative_quotes += "'" * relative
-
-               paper_string = string.join (compose_dict[PAPER],
-                                           '\n  ') % override
-               layout_string = string.join (compose_dict[LAYOUT],
-                                            '\n  ') % override
-               notes_string = string.join (compose_dict[NOTES],
-                                           '\n  ') % vars ()
-               preamble_string = string.join (compose_dict[PREAMBLE],
-                                              '\n  ') % override
-               
-               font_dump_setting = ''
-               if FONTLOAD in self.option_dict:
-                       font_dump_setting = '#(define-public force-eps-font-include #t)\n'
-
-               d = globals().copy()
-               d.update (locals())
-               return (PREAMBLE_LY + body) % d
-
-       # TODO: Use md5?
-       def get_hash (self):
-               if not self.hash:
-                       self.hash = abs (hash (self.full_ly ()))
-               return self.hash
-
-       def basename (self):
-               if FILENAME in self.option_dict:
-                       return self.option_dict[FILENAME]
-               if global_options.use_hash:
-                       return 'lily-%d' % self.get_hash ()
-               raise 'to be done'
-
-       def write_ly (self):
-               outf = open (self.basename () + '.ly', 'w')
-               outf.write (self.full_ly ())
-
-               open (self.basename () + '.txt', 'w').write ('image of music')
-
-       def ly_is_outdated (self):
-               base = self.basename ()
-
-               tex_file = '%s.tex' % base
-               eps_file = '%s.eps' % base
-               system_file = '%s-systems.tex' % base
-               ly_file = '%s.ly' % base
-               ok = os.path.exists (ly_file) \
-                    and os.path.exists (system_file)\
-                    and os.stat (system_file)[stat.ST_SIZE] \
-                    and re.match ('% eof', open (system_file).readlines ()[-1])
-               if ok and (not global_options.use_hash or FILENAME in self.option_dict):
-                       ok = (self.full_ly () == open (ly_file).read ())
-               if ok:
-                       # TODO: Do something smart with target formats
-                       #       (ps, png) and m/ctimes.
-                       return None
-               return self
-
-       def png_is_outdated (self):
-               base = self.basename ()
-               ok = self.ly_is_outdated ()
-               if global_options.format in (HTML, TEXINFO):
-                       ok = ok and os.path.exists (base + '.eps')
-
-                       page_count = 0
-                       if ok:
-                               page_count = ps_page_count (base + '.eps')
-                       
-                       if page_count == 1:
-                               ok = ok and os.path.exists (base + '.png')
-                       elif page_count > 1:
-                               for a in range (1, page_count + 1):
-                                               ok = ok and os.path.exists (base + '-page%d.png' % a)
-                               
-               return not ok
-       
-       def texstr_is_outdated (self):
-               if backend == 'ps':
-                       return 0
-
-               base = self.basename ()
-               ok = self.ly_is_outdated ()
-               ok = ok and (os.path.exists (base + '.texstr'))
-               return not ok
-
-       def filter_text (self):
-               code = self.substring ('code')
-               s = run_filter (code)
-               d = {
-                       'code': s,
-                       'options': self.match.group ('options')
-               }
-               # TODO
-               return output[self.format][FILTER] % d
-
-       def replacement_text (self):
-               func = Lilypond_snippet.__dict__['output_' + self.format]
-               return func (self)
-
-       def get_images (self):
-               base = self.basename ()
-               # URGUGHUGHUGUGH
-               single = '%(base)s.png' % vars ()
-               multiple = '%(base)s-page1.png' % vars ()
-               images = (single,)
-               if os.path.exists (multiple) \
-                  and (not os.path.exists (single) \
-                       or (os.stat (multiple)[stat.ST_MTIME] \
-                           > os.stat (single)[stat.ST_MTIME])):
-                       count = ps_page_count ('%(base)s.eps' % vars ())
-                       images = ['%s-page%d.png' % (base, a) for a in range (1, count+1)]
-                       images = tuple (images)
-               return images
-
-       def output_html (self):
-               str = ''
-               base = self.basename ()
-               if global_options.format == HTML:
-                       str += self.output_print_filename (HTML)
-                       if VERBATIM in self.option_dict:
-                               verb = verbatim_html (self.substring ('code'))
-                               str += output[HTML][VERBATIM] % vars ()
-                       if QUOTE in self.option_dict:
-                               str = output[HTML][QUOTE] % vars ()
-
-               str += output[HTML][BEFORE] % vars ()
-               for image in self.get_images ():
-                       (base, ext) = os.path.splitext (image)
-                       alt = self.option_dict[ALT]
-                       str += output[HTML][OUTPUT] % vars ()
-               str += output[HTML][AFTER] % vars ()
-               return str
-
-       def output_info (self):
-               str = ''
-               for image in self.get_images ():
-                       (base, ext) = os.path.splitext (image)
-
-                       # URG, makeinfo implicitly prepends dot to extension.
-                       # Specifying no extension is most robust.
-                       ext = ''
-                       alt = self.option_dict[ALT]
-                       str += output[TEXINFO][OUTPUTIMAGE] % vars ()
-
-               base = self.basename ()
-               str += output[global_options.format][OUTPUT] % vars ()
-               return str
-
-       def output_latex (self):
-               str = ''
-               base = self.basename ()
-               if global_options.format == LATEX:
-                       str += self.output_print_filename (LATEX)
-                       if VERBATIM in self.option_dict:
-                               verb = self.substring ('code')
-                               str += (output[LATEX][VERBATIM] % vars ())
-               
-               str += (output[LATEX][OUTPUT] % vars ())
-
-               ## todo: maintain breaks
-               if 0:
-                       breaks = self.ly ().count ("\n")
-                       str += "".ljust (breaks, "\n").replace ("\n","%\n")
-               
-               if QUOTE in self.option_dict:
-                       str = output[LATEX][QUOTE] % vars ()
-               return str
-
-       def output_print_filename (self, format):
-               str = ''
-               if PRINTFILENAME in self.option_dict:
-                       base = self.basename ()
-                       filename = self.substring ('filename')
-                       str = output[global_options.format][PRINTFILENAME] % vars ()
-
-               return str
-
-       def output_texinfo (self):
-               str = ''
-               if self.output_print_filename (TEXINFO):
-                       str += ('@html\n'
-                               + self.output_print_filename (HTML)
-                               + '\n@end html\n')
-                       str += ('@tex\n'
-                               + self.output_print_filename (LATEX)
-                               + '\n@end tex\n')
-               base = self.basename ()
-               if TEXIDOC in self.option_dict:
-                       texidoc = base + '.texidoc'
-                       if os.path.exists (texidoc):
-                               str += '@include %(texidoc)s\n\n' % vars ()
-
-               if VERBATIM in self.option_dict:
-                       verb = self.substring ('code')
-                       str += (output[TEXINFO][VERBATIM] % vars ())
-                       if not QUOTE in self.option_dict:
-                               str = output[TEXINFO][NOQUOTE] % vars ()
-
-               str += self.output_info ()
-
-#              str += ('@ifinfo\n' + self.output_info () + '\n@end ifinfo\n')
-#              str += ('@tex\n' + self.output_latex () + '\n@end tex\n')
-#              str += ('@html\n' + self.output_html () + '\n@end html\n')
-
-               if QUOTE in self.option_dict:
-                       str = output[TEXINFO][QUOTE] % vars ()
-
-               # need par after image
-               str += '\n'
-
-               return str
+    def __init__ (self, type, match, format, line_number):
+        Snippet.__init__ (self, type, match, format, line_number)
+        os = match.group ('options')
+        self.do_options (os, self.type)
+
+    def ly (self):
+        return self.substring ('code')
+
+    def full_ly (self):
+        s = self.ly ()
+        if s:
+            return self.compose_ly (s)
+        return ''
+
+    def do_options (self, option_string, type):
+        self.option_dict = {}
+
+        options = split_options (option_string)
+
+        for i in options:
+            if string.find (i, '=') > 0:
+                (key, value) = re.split ('\s*=\s*', i)
+                self.option_dict[key] = value
+            else:
+                if i in no_options.keys ():
+                    if no_options[i] in self.option_dict.keys ():
+                        del self.option_dict[no_options[i]]
+                else:
+                    self.option_dict[i] = None
+
+        has_line_width = self.option_dict.has_key (LINE_WIDTH)
+        no_line_width_value = 0
+
+        # If LINE_WIDTH is used without parameter, set it to default.
+        if has_line_width and self.option_dict[LINE_WIDTH] == None:
+            no_line_width_value = 1
+            del self.option_dict[LINE_WIDTH]
+
+        for i in default_ly_options.keys ():
+            if i not in self.option_dict.keys ():
+                self.option_dict[i] = default_ly_options[i]
+
+        if not has_line_width:
+            if type == 'lilypond' or FRAGMENT in self.option_dict.keys ():
+                self.option_dict[RAGGED_RIGHT] = None
+
+            if type == 'lilypond':
+                if LINE_WIDTH in self.option_dict.keys ():
+                    del self.option_dict[LINE_WIDTH]
+            else:
+                if RAGGED_RIGHT in self.option_dict.keys ():
+                    if LINE_WIDTH in self.option_dict.keys ():
+                        del self.option_dict[LINE_WIDTH]
+
+            if QUOTE in self.option_dict.keys () or type == 'lilypond':
+                if LINE_WIDTH in self.option_dict.keys ():
+                    del self.option_dict[LINE_WIDTH]
+
+        if not INDENT in self.option_dict.keys ():
+            self.option_dict[INDENT] = '0\\mm'
+
+        # The QUOTE pattern from ly_options only emits the `line-width'
+        # keyword.
+        if has_line_width and QUOTE in self.option_dict.keys ():
+            if no_line_width_value:
+                del self.option_dict[LINE_WIDTH]
+            else:
+                del self.option_dict[QUOTE]
+
+    def compose_ly (self, code):
+        if FRAGMENT in self.option_dict.keys ():
+            body = FRAGMENT_LY
+        else:
+            body = FULL_LY
+
+        # Defaults.
+        relative = 1
+        override = {}
+        # The original concept of the `exampleindent' option is broken.
+        # It is not possible to get a sane value for @exampleindent at all
+        # without processing the document itself.  Saying
+        #
+        #   @exampleindent 0
+        #   @example
+        #   ...
+        #   @end example
+        #   @exampleindent 5
+        #
+        # causes ugly results with the DVI backend of texinfo since the
+        # default value for @exampleindent isn't 5em but 0.4in (or a smaller
+        # value).  Executing the above code changes the environment
+        # indentation to an unknown value because we don't know the amount
+        # of 1em in advance since it is font-dependent.  Modifying
+        # @exampleindent in the middle of a document is simply not
+        # supported within texinfo.
+        #
+        # As a consequence, the only function of @exampleindent is now to
+        # specify the amount of indentation for the `quote' option.
+        #
+        # To set @exampleindent locally to zero, we use the @format
+        # environment for non-quoted snippets.
+        override[EXAMPLEINDENT] = r'0.4\in'
+        override[LINE_WIDTH] = texinfo_line_widths['@smallbook']
+        override.update (default_ly_options)
+
+        option_list = []
+        for (key, value) in self.option_dict.items ():
+            if value == None:
+                option_list.append (key)
+            else:
+                option_list.append (key + '=' + value)
+        option_string = string.join (option_list, ',')
+
+        compose_dict = {}
+        compose_types = [NOTES, PREAMBLE, LAYOUT, PAPER]
+        for a in compose_types:
+            compose_dict[a] = []
+
+        for (key, value) in self.option_dict.items ():
+            (c_key, c_value) = \
+             classic_lilypond_book_compatibility (key, value)
+            if c_key:
+                if c_value:
+                    warning \
+                     (_ ("deprecated ly-option used: %s=%s" \
+                      % (key, value)))
+                    warning \
+                     (_ ("compatibility mode translation: %s=%s" \
+                      % (c_key, c_value)))
+                else:
+                    warning \
+                     (_ ("deprecated ly-option used: %s" \
+                      % key))
+                    warning \
+                     (_ ("compatibility mode translation: %s" \
+                      % c_key))
+
+                (key, value) = (c_key, c_value)
+
+            if value:
+                override[key] = value
+            else:
+                if not override.has_key (key):
+                    override[key] = None
+
+            found = 0
+            for type in compose_types:
+                if ly_options[type].has_key (key):
+                    compose_dict[type].append (ly_options[type][key])
+                    found = 1
+                    break
+
+            if not found and key not in simple_options:
+                warning (_ ("ignoring unknown ly option: %s") % key)
+
+        # URGS
+        if RELATIVE in override.keys () and override[RELATIVE]:
+            relative = int (override[RELATIVE])
+
+        relative_quotes = ''
+
+        # 1 = central C
+        if relative < 0:
+            relative_quotes += ',' * (- relative)
+        elif relative > 0:
+            relative_quotes += "'" * relative
+
+        paper_string = string.join (compose_dict[PAPER],
+                      '\n  ') % override
+        layout_string = string.join (compose_dict[LAYOUT],
+                      '\n  ') % override
+        notes_string = string.join (compose_dict[NOTES],
+                      '\n  ') % vars ()
+        preamble_string = string.join (compose_dict[PREAMBLE],
+                       '\n  ') % override
+        
+        font_dump_setting = ''
+        if FONTLOAD in self.option_dict:
+            font_dump_setting = '#(define-public force-eps-font-include #t)\n'
+
+        d = globals().copy()
+        d.update (locals())
+        return (PREAMBLE_LY + body) % d
+
+    # TODO: Use md5?
+    def get_hash (self):
+        if not self.hash:
+            self.hash = abs (hash (self.full_ly ()))
+        return self.hash
+
+    def basename (self):
+        if FILENAME in self.option_dict:
+            return self.option_dict[FILENAME]
+        if global_options.use_hash:
+            return 'lily-%d' % self.get_hash ()
+        raise 'to be done'
+
+    def write_ly (self):
+        outf = open (self.basename () + '.ly', 'w')
+        outf.write (self.full_ly ())
+
+        open (self.basename () + '.txt', 'w').write ('image of music')
+
+    def ly_is_outdated (self):
+        base = self.basename ()
+
+        tex_file = '%s.tex' % base
+        eps_file = '%s.eps' % base
+        system_file = '%s-systems.tex' % base
+        ly_file = '%s.ly' % base
+        ok = os.path.exists (ly_file) \
+          and os.path.exists (system_file)\
+          and os.stat (system_file)[stat.ST_SIZE] \
+          and re.match ('% eof', open (system_file).readlines ()[-1])
+        if ok and (not global_options.use_hash or FILENAME in self.option_dict):
+            ok = (self.full_ly () == open (ly_file).read ())
+        if ok:
+            # TODO: Do something smart with target formats
+            #       (ps, png) and m/ctimes.
+            return None
+        return self
+
+    def png_is_outdated (self):
+        base = self.basename ()
+        ok = self.ly_is_outdated ()
+        if global_options.format in (HTML, TEXINFO):
+            ok = ok and os.path.exists (base + '.eps')
+
+            page_count = 0
+            if ok:
+                page_count = ps_page_count (base + '.eps')
+            
+            if page_count == 1:
+                ok = ok and os.path.exists (base + '.png')
+            elif page_count > 1:
+                for a in range (1, page_count + 1):
+                        ok = ok and os.path.exists (base + '-page%d.png' % a)
+                
+        return not ok
+    
+    def texstr_is_outdated (self):
+        if backend == 'ps':
+            return 0
+
+        base = self.basename ()
+        ok = self.ly_is_outdated ()
+        ok = ok and (os.path.exists (base + '.texstr'))
+        return not ok
+
+    def filter_text (self):
+        code = self.substring ('code')
+        s = run_filter (code)
+        d = {
+            'code': s,
+            'options': self.match.group ('options')
+        }
+        # TODO
+        return output[self.format][FILTER] % d
+
+    def replacement_text (self):
+        func = Lilypond_snippet.__dict__['output_' + self.format]
+        return func (self)
+
+    def get_images (self):
+        base = self.basename ()
+        # URGUGHUGHUGUGH
+        single = '%(base)s.png' % vars ()
+        multiple = '%(base)s-page1.png' % vars ()
+        images = (single,)
+        if os.path.exists (multiple) \
+         and (not os.path.exists (single) \
+            or (os.stat (multiple)[stat.ST_MTIME] \
+              > os.stat (single)[stat.ST_MTIME])):
+            count = ps_page_count ('%(base)s.eps' % vars ())
+            images = ['%s-page%d.png' % (base, a) for a in range (1, count+1)]
+            images = tuple (images)
+        return images
+
+    def output_html (self):
+        str = ''
+        base = self.basename ()
+        if global_options.format == HTML:
+            str += self.output_print_filename (HTML)
+            if VERBATIM in self.option_dict:
+                verb = verbatim_html (self.substring ('code'))
+                str += output[HTML][VERBATIM] % vars ()
+            if QUOTE in self.option_dict:
+                str = output[HTML][QUOTE] % vars ()
+
+        str += output[HTML][BEFORE] % vars ()
+        for image in self.get_images ():
+            (base, ext) = os.path.splitext (image)
+            alt = self.option_dict[ALT]
+            str += output[HTML][OUTPUT] % vars ()
+        str += output[HTML][AFTER] % vars ()
+        return str
+
+    def output_info (self):
+        str = ''
+        for image in self.get_images ():
+            (base, ext) = os.path.splitext (image)
+
+            # URG, makeinfo implicitly prepends dot to extension.
+            # Specifying no extension is most robust.
+            ext = ''
+            alt = self.option_dict[ALT]
+            str += output[TEXINFO][OUTPUTIMAGE] % vars ()
+
+        base = self.basename ()
+        str += output[global_options.format][OUTPUT] % vars ()
+        return str
+
+    def output_latex (self):
+        str = ''
+        base = self.basename ()
+        if global_options.format == LATEX:
+            str += self.output_print_filename (LATEX)
+            if VERBATIM in self.option_dict:
+                verb = self.substring ('code')
+                str += (output[LATEX][VERBATIM] % vars ())
+        
+        str += (output[LATEX][OUTPUT] % vars ())
+
+        ## todo: maintain breaks
+        if 0:
+            breaks = self.ly ().count ("\n")
+            str += "".ljust (breaks, "\n").replace ("\n","%\n")
+        
+        if QUOTE in self.option_dict:
+            str = output[LATEX][QUOTE] % vars ()
+        return str
+
+    def output_print_filename (self, format):
+        str = ''
+        if PRINTFILENAME in self.option_dict:
+            base = self.basename ()
+            filename = self.substring ('filename')
+            str = output[global_options.format][PRINTFILENAME] % vars ()
+
+        return str
+
+    def output_texinfo (self):
+        str = ''
+        if self.output_print_filename (TEXINFO):
+            str += ('@html\n'
+                + self.output_print_filename (HTML)
+                + '\n@end html\n')
+            str += ('@tex\n'
+                + self.output_print_filename (LATEX)
+                + '\n@end tex\n')
+        base = self.basename ()
+        if TEXIDOC in self.option_dict:
+            texidoc = base + '.texidoc'
+            if os.path.exists (texidoc):
+                str += '@include %(texidoc)s\n\n' % vars ()
+
+        if VERBATIM in self.option_dict:
+            verb = self.substring ('code')
+            str += (output[TEXINFO][VERBATIM] % vars ())
+            if not QUOTE in self.option_dict:
+                str = output[TEXINFO][NOQUOTE] % vars ()
+
+        str += self.output_info ()
+
+#                str += ('@ifinfo\n' + self.output_info () + '\n@end ifinfo\n')
+#                str += ('@tex\n' + self.output_latex () + '\n@end tex\n')
+#                str += ('@html\n' + self.output_html () + '\n@end html\n')
+
+        if QUOTE in self.option_dict:
+            str = output[TEXINFO][QUOTE] % vars ()
+
+        # need par after image
+        str += '\n'
+
+        return str
 
 class Lilypond_file_snippet (Lilypond_snippet):
-       def ly (self):
-               name = self.substring ('filename')
-               return '\\sourcefilename \"%s\"\n%s' \
-                        % (name, open (find_file (name)).read ())
+    def ly (self):
+        name = self.substring ('filename')
+        return '\\sourcefilename \"%s\"\n%s' \
+            % (name, open (find_file (name)).read ())
 
 snippet_type_to_class = {
-       'lilypond_file': Lilypond_file_snippet,
-       'lilypond_block': Lilypond_snippet,
-       'lilypond': Lilypond_snippet,
-       'include': Include_snippet,
+    'lilypond_file': Lilypond_file_snippet,
+    'lilypond_block': Lilypond_snippet,
+    'lilypond': Lilypond_snippet,
+    'include': Include_snippet,
 }
 
 def find_linestarts (s):
-       nls = [0]
-       start = 0
-       end = len (s)
-       while 1:
-               i = s.find ('\n', start)
-               if i < 0:
-                       break
+    nls = [0]
+    start = 0
+    end = len (s)
+    while 1:
+        i = s.find ('\n', start)
+        if i < 0:
+            break
 
-               i = i + 1
-               nls.append (i)
-               start = i
+        i = i + 1
+        nls.append (i)
+        start = i
 
-       nls.append (len (s))
-       return nls
+    nls.append (len (s))
+    return nls
 
 def find_toplevel_snippets (s, types):
-       res = {}
-       for i in types:
-               res[i] = ly.re.compile (snippet_res[global_options.format][i])
-
-       snippets = []
-       index = 0
-       ## found = dict (map (lambda x: (x, None),
-       ##                    types))
-       ## urg python2.1
-       found = {}
-       map (lambda x, f = found: f.setdefault (x, None),
-            types)
-
-       line_starts = find_linestarts (s)
-       line_start_idx = 0
-       # We want to search for multiple regexes, without searching
-       # the string multiple times for one regex.
-       # Hence, we use earlier results to limit the string portion
-       # where we search.
-       # Since every part of the string is traversed at most once for
-       # every type of snippet, this is linear.
-
-       while 1:
-               first = None
-               endex = 1 << 30
-               for type in types:
-                       if not found[type] or found[type][0] < index:
-                               found[type] = None
-                               
-                               m = res[type].search (s[index:endex])
-                               if not m:
-                                       continue
-
-                               cl = Snippet
-                               if snippet_type_to_class.has_key (type):
-                                       cl = snippet_type_to_class[type]
-
-
-                               start = index + m.start ('match')
-                               line_number = line_start_idx
-                               while (line_starts[line_number] < start):
-                                       line_number += 1
-
-                               line_number += 1
-                               snip = cl (type, m, global_options.format, line_number)
-
-                               found[type] = (start, snip)
-
-                       if found[type] \
-                          and (not first \
-                               or found[type][0] < found[first][0]):
-                               first = type
-
-                               # FIXME.
-
-                               # Limiting the search space is a cute
-                               # idea, but this *requires* to search
-                               # for possible containing blocks
-                               # first, at least as long as we do not
-                               # search for the start of blocks, but
-                               # always/directly for the entire
-                               # @block ... @end block.
-
-                               endex = found[first][0]
-
-               if not first:
-                       snippets.append (Substring (s, index, len (s), line_start_idx))
-                       break
-
-               while (start > line_starts[line_start_idx+1]):
-                       line_start_idx += 1
-
-               (start, snip) = found[first]
-               snippets.append (Substring (s, index, start, line_start_idx + 1))
-               snippets.append (snip)
-               found[first] = None
-               index = start + len (snip.match.group ('match'))
-
-       return snippets
+    res = {}
+    for i in types:
+        res[i] = ly.re.compile (snippet_res[global_options.format][i])
+
+    snippets = []
+    index = 0
+    ## found = dict (map (lambda x: (x, None),
+    ##                      types))
+    ## urg python2.1
+    found = {}
+    map (lambda x, f = found: f.setdefault (x, None),
+      types)
+
+    line_starts = find_linestarts (s)
+    line_start_idx = 0
+    # We want to search for multiple regexes, without searching
+    # the string multiple times for one regex.
+    # Hence, we use earlier results to limit the string portion
+    # where we search.
+    # Since every part of the string is traversed at most once for
+    # every type of snippet, this is linear.
+
+    while 1:
+        first = None
+        endex = 1 << 30
+        for type in types:
+            if not found[type] or found[type][0] < index:
+                found[type] = None
+                
+                m = res[type].search (s[index:endex])
+                if not m:
+                    continue
+
+                cl = Snippet
+                if snippet_type_to_class.has_key (type):
+                    cl = snippet_type_to_class[type]
+
+
+                start = index + m.start ('match')
+                line_number = line_start_idx
+                while (line_starts[line_number] < start):
+                    line_number += 1
+
+                line_number += 1
+                snip = cl (type, m, global_options.format, line_number)
+
+                found[type] = (start, snip)
+
+            if found[type] \
+             and (not first \
+                or found[type][0] < found[first][0]):
+                first = type
+
+                # FIXME.
+
+                # Limiting the search space is a cute
+                # idea, but this *requires* to search
+                # for possible containing blocks
+                # first, at least as long as we do not
+                # search for the start of blocks, but
+                # always/directly for the entire
+                # @block ... @end block.
+
+                endex = found[first][0]
+
+        if not first:
+            snippets.append (Substring (s, index, len (s), line_start_idx))
+            break
+
+        while (start > line_starts[line_start_idx+1]):
+            line_start_idx += 1
+
+        (start, snip) = found[first]
+        snippets.append (Substring (s, index, start, line_start_idx + 1))
+        snippets.append (snip)
+        found[first] = None
+        index = start + len (snip.match.group ('match'))
+
+    return snippets
 
 def filter_pipe (input, cmd):
-       if global_options.verbose:
-               progress (_ ("Opening filter `%s'") % cmd)
-
-       (stdin, stdout, stderr) = os.popen3 (cmd)
-       stdin.write (input)
-       status = stdin.close ()
-
-       if not status:
-               status = 0
-               output = stdout.read ()
-               status = stdout.close ()
-               error = stderr.read ()
-
-       if not status:
-               status = 0
-       signal = 0x0f & status
-       if status or (not output and error):
-               exit_status = status >> 8
-               error (_ ("`%s' failed (%d)") % (cmd, exit_status))
-               error (_ ("The error log is as follows:"))
-               sys.stderr.write (error)
-               sys.stderr.write (stderr.read ())
-               exit (status)
-
-       if global_options.verbose:
-               progress ('\n')
-
-       return output
+    if global_options.verbose:
+        progress (_ ("Opening filter `%s'") % cmd)
+
+    (stdin, stdout, stderr) = os.popen3 (cmd)
+    stdin.write (input)
+    status = stdin.close ()
+
+    if not status:
+        status = 0
+        output = stdout.read ()
+        status = stdout.close ()
+        error = stderr.read ()
+
+    if not status:
+        status = 0
+    signal = 0x0f & status
+    if status or (not output and error):
+        exit_status = status >> 8
+        error (_ ("`%s' failed (%d)") % (cmd, exit_status))
+        error (_ ("The error log is as follows:"))
+        sys.stderr.write (error)
+        sys.stderr.write (stderr.read ())
+        exit (status)
+
+    if global_options.verbose:
+        progress ('\n')
+
+    return output
 
 def run_filter (s):
-       return filter_pipe (s, global_options.filter_cmd)
+    return filter_pipe (s, global_options.filter_cmd)
 
 def is_derived_class (cl, baseclass):
-       if cl == baseclass:
-               return 1
-       for b in cl.__bases__:
-               if is_derived_class (b, baseclass):
-                       return 1
-       return 0
+    if cl == baseclass:
+        return 1
+    for b in cl.__bases__:
+        if is_derived_class (b, baseclass):
+            return 1
+    return 0
 
 def process_snippets (cmd, ly_snippets, texstr_snippets, png_snippets):
-       ly_names = filter (lambda x: x,
-                          map (Lilypond_snippet.basename, ly_snippets))
-       texstr_names = filter (lambda x: x,
-                          map (Lilypond_snippet.basename, texstr_snippets))
-       png_names = filter (lambda x: x,
-                           map (Lilypond_snippet.basename, png_snippets))
-
-       status = 0
-       def my_system (cmd):
-               status = ly.system (cmd,
-                                   be_verbose=global_options.verbose, 
-                                   progress_p= 1)
-
-       # UGH
-       # the --process=CMD switch is a bad idea
-       # it is too generic for lilypond-book.
-       if texstr_names:
-               my_system (string.join ([cmd, '--backend texstr',
-                                        'snippet-map.ly'] + texstr_names))
-               for l in texstr_names:
-                       my_system ('latex %s.texstr' % l)
-
-       if ly_names:
-               my_system (string.join ([cmd, 'snippet-map.ly'] + ly_names))
+    ly_names = filter (lambda x: x,
+             map (Lilypond_snippet.basename, ly_snippets))
+    texstr_names = filter (lambda x: x,
+             map (Lilypond_snippet.basename, texstr_snippets))
+    png_names = filter (lambda x: x,
+              map (Lilypond_snippet.basename, png_snippets))
+
+    status = 0
+    def my_system (cmd):
+        status = ly.system (cmd,
+                  be_verbose=global_options.verbose, 
+                  progress_p= 1)
+
+    # UGH
+    # the --process=CMD switch is a bad idea
+    # it is too generic for lilypond-book.
+    if texstr_names:
+        my_system (string.join ([cmd, '--backend texstr',
+                    'snippet-map.ly'] + texstr_names))
+        for l in texstr_names:
+            my_system ('latex %s.texstr' % l)
+
+    if ly_names:
+        my_system (string.join ([cmd, 'snippet-map.ly'] + ly_names))
 
 LATEX_INSPECTION_DOCUMENT = r'''
 \nonstopmode
@@ -1409,368 +1409,368 @@ LATEX_INSPECTION_DOCUMENT = r'''
 
 # Do we need anything else besides `textwidth'?
 def get_latex_textwidth (source):
-       m = re.search (r'''(?P<preamble>\\begin\s*{document})''', source)
-       if m == None:
-               warning (_ ("Can't find \\begin{document} in LaTeX document"))
-               
-               ## what's a sensible default?
-               return 550.0
-       
-       preamble = source[:m.start (0)]
-       latex_document = LATEX_INSPECTION_DOCUMENT % vars ()
-       
-       (handle, tmpfile) = tempfile.mkstemp('.tex')
-       logfile = os.path.splitext (tmpfile)[0] + '.log'
-       logfile = os.path.split (logfile)[1]
-
-       tmp_handle = os.fdopen (handle,'w')
-       tmp_handle.write (latex_document)
-       tmp_handle.close ()
-       
-       ly.system ('latex %s' % tmpfile, be_verbose=global_options.verbose)
-       parameter_string = open (logfile).read()
-       
-       os.unlink (tmpfile)
-       os.unlink (logfile)
-
-       columns = 0
-       m = re.search ('columns=([0-9.]*)', parameter_string)
-       if m:
-               columns = int (m.group (1))
-
-       columnsep = 0
-       m = re.search ('columnsep=([0-9.]*)pt', parameter_string)
-       if m:
-               columnsep = float (m.group (1))
-
-       textwidth = 0
-       m = re.search ('textwidth=([0-9.]*)pt', parameter_string)
-       if m:
-               textwidth = float (m.group (1))
-               if columns:
-                       textwidth = (textwidth - columnsep) / columns
-
-       return textwidth
+    m = re.search (r'''(?P<preamble>\\begin\s*{document})''', source)
+    if m == None:
+        warning (_ ("Can't find \\begin{document} in LaTeX document"))
+        
+        ## what's a sensible default?
+        return 550.0
+    
+    preamble = source[:m.start (0)]
+    latex_document = LATEX_INSPECTION_DOCUMENT % vars ()
+    
+    (handle, tmpfile) = tempfile.mkstemp('.tex')
+    logfile = os.path.splitext (tmpfile)[0] + '.log'
+    logfile = os.path.split (logfile)[1]
+
+    tmp_handle = os.fdopen (handle,'w')
+    tmp_handle.write (latex_document)
+    tmp_handle.close ()
+    
+    ly.system ('latex %s' % tmpfile, be_verbose=global_options.verbose)
+    parameter_string = open (logfile).read()
+    
+    os.unlink (tmpfile)
+    os.unlink (logfile)
+
+    columns = 0
+    m = re.search ('columns=([0-9.]*)', parameter_string)
+    if m:
+        columns = int (m.group (1))
+
+    columnsep = 0
+    m = re.search ('columnsep=([0-9.]*)pt', parameter_string)
+    if m:
+        columnsep = float (m.group (1))
+
+    textwidth = 0
+    m = re.search ('textwidth=([0-9.]*)pt', parameter_string)
+    if m:
+        textwidth = float (m.group (1))
+        if columns:
+            textwidth = (textwidth - columnsep) / columns
+
+    return textwidth
 
 def modify_preamble (chunk):
-       str = chunk.replacement_text ()
-       if (re.search (r"\\begin *{document}", str)
-           and not re.search ("{graphic[sx]", str)):
-               str = re.sub (r"\\begin{document}",
-                             r"\\usepackage{graphics}" + '\n'
-                             + r"\\begin{document}",
-                             str)
-               chunk.override_text = str 
-               
-       
+    str = chunk.replacement_text ()
+    if (re.search (r"\\begin *{document}", str)
+      and not re.search ("{graphic[sx]", str)):
+        str = re.sub (r"\\begin{document}",
+               r"\\usepackage{graphics}" + '\n'
+               + r"\\begin{document}",
+               str)
+        chunk.override_text = str 
+        
+    
 
 ext2format = {
-       '.html': HTML,
-       '.itely': TEXINFO,
-       '.latex': LATEX,
-       '.lytex': LATEX,
-       '.tely': TEXINFO,
-       '.tex': LATEX,
-       '.texi': TEXINFO,
-       '.texinfo': TEXINFO,
-       '.xml': HTML,
+    '.html': HTML,
+    '.itely': TEXINFO,
+    '.latex': LATEX,
+    '.lytex': LATEX,
+    '.tely': TEXINFO,
+    '.tex': LATEX,
+    '.texi': TEXINFO,
+    '.texinfo': TEXINFO,
+    '.xml': HTML,
 }
 
 format2ext = {
-       HTML: '.html',
-       # TEXINFO: '.texinfo',
-       TEXINFO: '.texi',
-       LATEX: '.tex',
+    HTML: '.html',
+    # TEXINFO: '.texinfo',
+    TEXINFO: '.texi',
+    LATEX: '.tex',
 }
 
 class Compile_error:
-       pass
+    pass
 
 def write_file_map (lys, name):
-       snippet_map = open ('snippet-map.ly', 'w')
-       snippet_map.write ("""
+    snippet_map = open ('snippet-map.ly', 'w')
+    snippet_map.write ("""
 #(define version-seen? #t)
 #(ly:add-file-name-alist '(
 """)
-       for ly in lys:
-               snippet_map.write ('("%s.ly" . "%s:%d (%s.ly)")\n'
-                                  % (ly.basename (),
-                                     name,
-                                     ly.line_number,
-                                     ly.basename ()))
+    for ly in lys:
+        snippet_map.write ('("%s.ly" . "%s:%d (%s.ly)")\n'
+                 % (ly.basename (),
+                   name,
+                   ly.line_number,
+                   ly.basename ()))
 
-       snippet_map.write ('))\n')
+    snippet_map.write ('))\n')
 
 def do_process_cmd (chunks, input_name):
-       all_lys = filter (lambda x: is_derived_class (x.__class__,
-                                                     Lilypond_snippet),
-                         chunks)
-
-       write_file_map (all_lys, input_name)
-       ly_outdated = \
-         filter (lambda x: is_derived_class (x.__class__,
-                                             Lilypond_snippet)
-                           and x.ly_is_outdated (),
-                 chunks)
-       texstr_outdated = \
-         filter (lambda x: is_derived_class (x.__class__,
-                                             Lilypond_snippet)
-                           and x.texstr_is_outdated (),
-                 chunks)
-       png_outdated = \
-         filter (lambda x: is_derived_class (x.__class__,
-                                             Lilypond_snippet)
-                           and x.png_is_outdated (),
-                 chunks)
-
-       progress (_ ("Writing snippets..."))
-       map (Lilypond_snippet.write_ly, ly_outdated)
-       progress ('\n')
-
-       if ly_outdated:
-               progress (_ ("Processing..."))
-               progress ('\n')
-               process_snippets (global_options.process_cmd, ly_outdated, texstr_outdated, png_outdated)
-       else:
-               progress (_ ("All snippets are up to date..."))
-       progress ('\n')
+    all_lys = filter (lambda x: is_derived_class (x.__class__,
+                           Lilypond_snippet),
+             chunks)
+
+    write_file_map (all_lys, input_name)
+    ly_outdated = \
+     filter (lambda x: is_derived_class (x.__class__,
+                       Lilypond_snippet)
+              and x.ly_is_outdated (),
+         chunks)
+    texstr_outdated = \
+     filter (lambda x: is_derived_class (x.__class__,
+                       Lilypond_snippet)
+              and x.texstr_is_outdated (),
+         chunks)
+    png_outdated = \
+     filter (lambda x: is_derived_class (x.__class__,
+                       Lilypond_snippet)
+              and x.png_is_outdated (),
+         chunks)
+
+    progress (_ ("Writing snippets..."))
+    map (Lilypond_snippet.write_ly, ly_outdated)
+    progress ('\n')
+
+    if ly_outdated:
+        progress (_ ("Processing..."))
+        progress ('\n')
+        process_snippets (global_options.process_cmd, ly_outdated, texstr_outdated, png_outdated)
+    else:
+        progress (_ ("All snippets are up to date..."))
+    progress ('\n')
 
 def guess_format (input_filename):
-       format = None
-       e = os.path.splitext (input_filename)[1]
-       if e in ext2format.keys ():
-               # FIXME
-               format = ext2format[e]
-       else:
-               error (_ ("can't determine format for: %s" \
-                            % input_filename))
-               exit (1)
-       return format
+    format = None
+    e = os.path.splitext (input_filename)[1]
+    if e in ext2format.keys ():
+        # FIXME
+        format = ext2format[e]
+    else:
+        error (_ ("can't determine format for: %s" \
+              % input_filename))
+        exit (1)
+    return format
 
 def write_if_updated (file_name, lines):
-       try:
-               f = open (file_name)
-               oldstr = f.read ()
-               new_str = string.join (lines, '')
-               if oldstr == new_str:
-                       progress (_ ("%s is up to date.") % file_name)
-                       progress ('\n')
-                       return
-       except:
-               pass
-
-       progress (_ ("Writing `%s'...") % file_name)
-       open (file_name, 'w').writelines (lines)
-       progress ('\n')
+    try:
+        f = open (file_name)
+        oldstr = f.read ()
+        new_str = string.join (lines, '')
+        if oldstr == new_str:
+            progress (_ ("%s is up to date.") % file_name)
+            progress ('\n')
+            return
+    except:
+        pass
+
+    progress (_ ("Writing `%s'...") % file_name)
+    open (file_name, 'w').writelines (lines)
+    progress ('\n')
 
 def note_input_file (name, inputs=[]):
-       ## hack: inputs is mutable!
-       inputs.append (name)
-       return inputs
+    ## hack: inputs is mutable!
+    inputs.append (name)
+    return inputs
 
 def samefile (f1, f2):
-       try:
-               return os.path.samefile (f1, f2)
-       except AttributeError:          # Windoze
-               f1 = re.sub ("//*", "/", f1)
-               f2 = re.sub ("//*", "/", f2)
-               return f1 == f2
+    try:
+        return os.path.samefile (f1, f2)
+    except AttributeError:                # Windoze
+        f1 = re.sub ("//*", "/", f1)
+        f2 = re.sub ("//*", "/", f2)
+        return f1 == f2
 
 def do_file (input_filename):
-       # Ugh.
-       if not input_filename or input_filename == '-':
-               in_handle = sys.stdin
-               input_fullname = '<stdin>'
-       else:
-               if os.path.exists (input_filename):
-                       input_fullname = input_filename
-               elif global_options.format == LATEX and ly.search_exe_path ('kpsewhich'):
-                       input_fullname = os.popen ('kpsewhich ' + input_filename).read()[:-1]
-               else:
-                       input_fullname = find_file (input_filename)
-
-               note_input_file (input_fullname)
-               in_handle = open (input_fullname)
-
-       if input_filename == '-':
-               input_base = 'stdin'
-       else:
-               input_base = os.path.basename \
-                            (os.path.splitext (input_filename)[0])
-
-       # Only default to stdout when filtering.
-       if global_options.output_name == '-' or (not global_options.output_name and global_options.filter_cmd):
-               output_filename = '-'
-               output_file = sys.stdout
-       else:
-               # don't complain when global_options.output_name is existing
-               output_filename = input_base + format2ext[global_options.format]
-               if global_options.output_name:
-                       if not os.path.isdir (global_options.output_name):
-                               os.mkdir (global_options.output_name, 0777)
-                       os.chdir (global_options.output_name)
-               else: 
-                       if os.path.exists (input_filename) \
-                          and os.path.exists (output_filename) \
-                          and samefile (output_filename, input_fullname):
-                          error (
-                          _ ("Output would overwrite input file; use --output."))
-                          exit (2)
-
-       try:
-               progress (_ ("Reading %s...") % input_fullname)
-               source = in_handle.read ()
-               progress ('\n')
-
-               set_default_options (source)
-
-
-               # FIXME: Containing blocks must be first, see
-               #        find_toplevel_snippets.
-               snippet_types = (
-                       'multiline_comment',
-                       'verbatim',
-                       'lilypond_block',
-       #               'verb',
-                       'singleline_comment',
-                       'lilypond_file',
-                       'include',
-                       'lilypond',
-               )
-               progress (_ ("Dissecting..."))
-               chunks = find_toplevel_snippets (source, snippet_types)
-
-               if global_options.format == LATEX:
-                       for c in chunks:
-                               if (c.is_plain () and
-                                   re.search (r"\\begin *{document}", c.replacement_text())):
-                                       modify_preamble (c)
-                                       break
-               progress ('\n')
-
-               if global_options.filter_cmd:
-                       write_if_updated (output_filename,
-                                         [c.filter_text () for c in chunks])
-               elif global_options.process_cmd:
-                       do_process_cmd (chunks, input_fullname)
-                       progress (_ ("Compiling %s...") % output_filename)
-                       progress ('\n')
-                       write_if_updated (output_filename,
-                                         [s.replacement_text ()
-                                          for s in chunks])
-               
-               def process_include (snippet):
-                       os.chdir (original_dir)
-                       name = snippet.substring ('filename')
-                       progress (_ ("Processing include: %s") % name)
-                       progress ('\n')
-                       return do_file (name)
-
-               include_chunks = map (process_include,
-                                     filter (lambda x: is_derived_class (x.__class__,
-                                                                         Include_snippet),
-                                             chunks))
-
-
-               return chunks + reduce (lambda x,y: x + y, include_chunks, [])
-               
-       except Compile_error:
-               os.chdir (original_dir)
-               progress (_ ("Removing `%s'") % output_filename)
-               progress ('\n')
-               raise Compile_error
+    # Ugh.
+    if not input_filename or input_filename == '-':
+        in_handle = sys.stdin
+        input_fullname = '<stdin>'
+    else:
+        if os.path.exists (input_filename):
+            input_fullname = input_filename
+        elif global_options.format == LATEX and ly.search_exe_path ('kpsewhich'):
+            input_fullname = os.popen ('kpsewhich ' + input_filename).read()[:-1]
+        else:
+            input_fullname = find_file (input_filename)
+
+        note_input_file (input_fullname)
+        in_handle = open (input_fullname)
+
+    if input_filename == '-':
+        input_base = 'stdin'
+    else:
+        input_base = os.path.basename \
+              (os.path.splitext (input_filename)[0])
+
+    # Only default to stdout when filtering.
+    if global_options.output_name == '-' or (not global_options.output_name and global_options.filter_cmd):
+        output_filename = '-'
+        output_file = sys.stdout
+    else:
+        # don't complain when global_options.output_name is existing
+        output_filename = input_base + format2ext[global_options.format]
+        if global_options.output_name:
+            if not os.path.isdir (global_options.output_name):
+                os.mkdir (global_options.output_name, 0777)
+            os.chdir (global_options.output_name)
+        else: 
+            if os.path.exists (input_filename) \
+             and os.path.exists (output_filename) \
+             and samefile (output_filename, input_fullname):
+             error (
+             _ ("Output would overwrite input file; use --output."))
+             exit (2)
+
+    try:
+        progress (_ ("Reading %s...") % input_fullname)
+        source = in_handle.read ()
+        progress ('\n')
+
+        set_default_options (source)
+
+
+        # FIXME: Containing blocks must be first, see
+        #        find_toplevel_snippets.
+        snippet_types = (
+            'multiline_comment',
+            'verbatim',
+            'lilypond_block',
+                   'verb',
+            'singleline_comment',
+            'lilypond_file',
+            'include',
+            'lilypond',
+        )
+        progress (_ ("Dissecting..."))
+        chunks = find_toplevel_snippets (source, snippet_types)
+
+        if global_options.format == LATEX:
+            for c in chunks:
+                if (c.is_plain () and
+                  re.search (r"\\begin *{document}", c.replacement_text())):
+                    modify_preamble (c)
+                    break
+        progress ('\n')
+
+        if global_options.filter_cmd:
+            write_if_updated (output_filename,
+                     [c.filter_text () for c in chunks])
+        elif global_options.process_cmd:
+            do_process_cmd (chunks, input_fullname)
+            progress (_ ("Compiling %s...") % output_filename)
+            progress ('\n')
+            write_if_updated (output_filename,
+                     [s.replacement_text ()
+                     for s in chunks])
+        
+        def process_include (snippet):
+            os.chdir (original_dir)
+            name = snippet.substring ('filename')
+            progress (_ ("Processing include: %s") % name)
+            progress ('\n')
+            return do_file (name)
+
+        include_chunks = map (process_include,
+                   filter (lambda x: is_derived_class (x.__class__,
+                                     Include_snippet),
+                       chunks))
+
+
+        return chunks + reduce (lambda x,y: x + y, include_chunks, [])
+        
+    except Compile_error:
+        os.chdir (original_dir)
+        progress (_ ("Removing `%s'") % output_filename)
+        progress ('\n')
+        raise Compile_error
 
 def do_options ():
 
-       global global_options
+    global global_options
 
-       opt_parser = get_option_parser()
-       (global_options, args) = opt_parser.parse_args ()
+    opt_parser = get_option_parser()
+    (global_options, args) = opt_parser.parse_args ()
 
-       if global_options.format in ('texi-html', 'texi'):
-               global_options.format = TEXINFO
-       global_options.use_hash = True
+    if global_options.format in ('texi-html', 'texi'):
+        global_options.format = TEXINFO
+    global_options.use_hash = True
 
-       global_options.include_path =  map (os.path.abspath, global_options.include_path)
-       
-       if global_options.warranty:
-               warranty ()
-               exit (0)
-       if not args or len (args) > 1:
-               opt_parser.print_help ()
-               exit (2)
-               
-       return args
+    global_options.include_path =  map (os.path.abspath, global_options.include_path)
+    
+    if global_options.warranty:
+        warranty ()
+        exit (0)
+    if not args or len (args) > 1:
+        opt_parser.print_help ()
+        exit (2)
+        
+    return args
 
 def main ():
-       files = do_options ()
-
-       file = files[0]
-
-       basename = os.path.splitext (file)[0]
-       basename = os.path.split (basename)[1]
-       
-       if not global_options.format:
-               global_options.format = guess_format (files[0])
-
-       formats = 'ps'
-       if global_options.format in (TEXINFO, HTML):
-               formats += ',png'
-       if global_options.process_cmd == '':
-               global_options.process_cmd = lilypond_binary \
-                             + ' --formats=%s --backend eps ' % formats
-
-       if global_options.process_cmd:
-               global_options.process_cmd += string.join ([(' -I %s' % commands.mkarg (p))
-                                                           for p in global_options.include_path])
-
-       identify ()
-
-       try:
-               chunks = do_file (file)
-               if global_options.psfonts:
-                       fontextract.verbose = global_options.verbose
-                       snippet_chunks = filter (lambda x: is_derived_class (x.__class__,
-                                                                             Lilypond_snippet),
-                                                chunks)
-
-                       psfonts_file = basename + '.psfonts' 
-                       if not global_options.verbose:
-                               progress (_ ("Writing fonts to %s...") % psfonts_file)
-                       fontextract.extract_fonts (psfonts_file,
-                                                  [x.basename() + '.eps'
-                                                   for x in snippet_chunks])
-                       if not global_options.verbose:
-                               progress ('\n')
-                       
-       except Compile_error:
-               exit (1)
-
-       if global_options.format in (TEXINFO, LATEX):
-               if not global_options.psfonts:
-                       warning (_ ("option --psfonts not used"))
-                       warning (_ ("processing with dvips will have no fonts"))
-
-               psfonts_file = os.path.join (global_options.output_name, basename + '.psfonts')
-               output = os.path.join (global_options.output_name, basename +  '.dvi' )
-               
-               progress ('\n')
-               progress (_ ("DVIPS usage:"))
-               progress ('\n')
-               progress ("    dvips -h %(psfonts_file)s %(output)s" % vars ())
-               progress ('\n')
-
-       inputs = note_input_file ('')
-       inputs.pop ()
-
-       base_file_name = os.path.splitext (os.path.basename (file))[0]
-       dep_file = os.path.join (global_options.output_name, base_file_name + '.dep')
-       final_output_file = os.path.join (global_options.output_name,
-                                         base_file_name
-                                         + '.%s' % global_options.format)
-       
-       os.chdir (original_dir)
-       open (dep_file, 'w').write ('%s: %s' % (final_output_file, ' '.join (inputs)))
+    files = do_options ()
+
+    file = files[0]
+
+    basename = os.path.splitext (file)[0]
+    basename = os.path.split (basename)[1]
+    
+    if not global_options.format:
+        global_options.format = guess_format (files[0])
+
+    formats = 'ps'
+    if global_options.format in (TEXINFO, HTML):
+        formats += ',png'
+    if global_options.process_cmd == '':
+        global_options.process_cmd = lilypond_binary \
+               + ' --formats=%s --backend eps ' % formats
+
+    if global_options.process_cmd:
+        global_options.process_cmd += string.join ([(' -I %s' % commands.mkarg (p))
+                              for p in global_options.include_path])
+
+    identify ()
+
+    try:
+        chunks = do_file (file)
+        if global_options.psfonts:
+            fontextract.verbose = global_options.verbose
+            snippet_chunks = filter (lambda x: is_derived_class (x.__class__,
+                                       Lilypond_snippet),
+                        chunks)
+
+            psfonts_file = basename + '.psfonts' 
+            if not global_options.verbose:
+                progress (_ ("Writing fonts to %s...") % psfonts_file)
+            fontextract.extract_fonts (psfonts_file,
+                         [x.basename() + '.eps'
+                          for x in snippet_chunks])
+            if not global_options.verbose:
+                progress ('\n')
+            
+    except Compile_error:
+        exit (1)
+
+    if global_options.format in (TEXINFO, LATEX):
+        if not global_options.psfonts:
+            warning (_ ("option --psfonts not used"))
+            warning (_ ("processing with dvips will have no fonts"))
+
+        psfonts_file = os.path.join (global_options.output_name, basename + '.psfonts')
+        output = os.path.join (global_options.output_name, basename +  '.dvi' )
+        
+        progress ('\n')
+        progress (_ ("DVIPS usage:"))
+        progress ('\n')
+        progress ("    dvips -h %(psfonts_file)s %(output)s" % vars ())
+        progress ('\n')
+
+    inputs = note_input_file ('')
+    inputs.pop ()
+
+    base_file_name = os.path.splitext (os.path.basename (file))[0]
+    dep_file = os.path.join (global_options.output_name, base_file_name + '.dep')
+    final_output_file = os.path.join (global_options.output_name,
+                     base_file_name
+                     + '.%s' % global_options.format)
+    
+    os.chdir (original_dir)
+    open (dep_file, 'w').write ('%s: %s' % (final_output_file, ' '.join (inputs)))
 
 if __name__ == '__main__':
-       main ()
+    main ()
index c61cce84ed610a43b00ca60a74eec4450bfaf886..a3b53d8fa244d743689cd624511ebd1596ec260d 100644 (file)
 
 '''
 TODO:
-       * test on weird and unquantised midi input (lily-devel)
-       * update doc and manpage
-
-       * simply insert clef changes whenever too many ledger lines
-               [to avoid tex capacity exceeded]
-       * do not ever quant skips
-       * better lyrics handling
-       * [see if it is feasible to] move ly-classes to library for use in
-               other converters, while leaving midi specific stuff here
+    * test on weird and unquantised midi input (lily-devel)
+    * update doc and manpage
+
+    * simply insert clef changes whenever too many ledger lines
+        [to avoid tex capacity exceeded]
+    * do not ever quant skips
+    * better lyrics handling
+    * [see if it is feasible to] move ly-classes to library for use in
+        other converters, while leaving midi specific stuff here
 '''
 
 import os
@@ -31,21 +31,21 @@ import sys
 #
 libdir = '@local_lilypond_libdir@'
 if not os.path.isdir (libdir):
-        libdir = '@lilypond_libdir@'
+    libdir = '@lilypond_libdir@'
 
 # ugh
 datadir = '@local_lilypond_datadir@'
 if os.environ.has_key ('LILYPONDPREFIX'):
-       datadir = os.environ['LILYPONDPREFIX']
-       while datadir[-1] == os.sep:
-               datadir= datadir[:-1]
-       libdir = datadir.replace ('/share/', '/lib/')
+    datadir = os.environ['LILYPONDPREFIX']
+    while datadir[-1] == os.sep:
+        datadir= datadir[:-1]
+    libdir = datadir.replace ('/share/', '/lib/')
 
 if os.path.exists (os.path.join (datadir, 'lib/lilypond/@TOPLEVEL_VERSION@/')):
-       libdir = os.path.join (libdir, 'lib/lilypond/@TOPLEVEL_VERSION@/')
+    libdir = os.path.join (libdir, 'lib/lilypond/@TOPLEVEL_VERSION@/')
 
 if os.path.exists (os.path.join (datadir, 'lib/lilypond/current/')):
-       libdir = os.path.join (libdir, 'lib/lilypond/current/')
+    libdir = os.path.join (libdir, 'lib/lilypond/current/')
 
 sys.path.insert (0, os.path.join (libdir, 'python'))
 
@@ -53,8 +53,8 @@ sys.path.insert (0, os.path.join (libdir, 'python'))
 bindir = os.path.split (sys.argv[0])[0]
 
 for prefix_component in ['share', 'lib']:
-       datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % prefix_component)
-       sys.path.insert (0, datadir)
+    datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % prefix_component)
+    sys.path.insert (0, datadir)
 
 import midi
 import lilylib as ly
@@ -84,13 +84,13 @@ allowed_tuplet_clocks = []
 
 localedir = '@localedir@'
 try:
-       import gettext
-       gettext.bindtextdomain ('lilypond', localedir)
-       gettext.textdomain ('lilypond')
-       _ = gettext.gettext
+    import gettext
+    gettext.bindtextdomain ('lilypond', localedir)
+    gettext.textdomain ('lilypond')
+    _ = gettext.gettext
 except:
-       def _ (s):
-               return s
+    def _ (s):
+        return s
 
 program_name = sys.argv[0]
 program_version = '@TOPLEVEL_VERSION@'
@@ -98,907 +98,907 @@ program_version = '@TOPLEVEL_VERSION@'
 errorport = sys.stderr
 
 def identify ():
-       sys.stdout.write ('%s (GNU LilyPond) %s\n' % (program_name, program_version))
+    sys.stdout.write ('%s (GNU LilyPond) %s\n' % (program_name, program_version))
 
 def warranty ():
-       identify ()
-       sys.stdout.write ('''
+    identify ()
+    sys.stdout.write ('''
 Copyright (c) %s by
 
 Han-Wen Nienhuys
 Jan Nieuwenhuizen
+ Han-Wen Nienhuys
+ Jan Nieuwenhuizen
 
 %s
 %s
 '''  ( '2001--2006',
-       _('Distributed under terms of the GNU General Public License.'),
-       _('It comes with NO WARRANTY.')))
+   _('Distributed under terms of the GNU General Public License.'),
+   _('It comes with NO WARRANTY.')))
 
 
 def progress (s):
-       errorport.write (s + '\n')
+    errorport.write (s + '\n')
 
 def warning (s):
-       progress (_ ("warning: ") + s)
-               
+    progress (_ ("warning: ") + s)
+        
 def error (s):
-       progress (_ ("error: ") + s)
-       raise _ ("Exiting ... ")
+    progress (_ ("error: ") + s)
+    raise _ ("Exiting ... ")
 
 def system (cmd, ignore_error = 0):
-       return ly.system (cmd, ignore_error=ignore_error)
+    return ly.system (cmd, ignore_error=ignore_error)
 
 def strip_extension (f, ext):
-       (p, e) = os.path.splitext (f)
-       if e == ext:
-               e = ''
-       return p + e
+    (p, e) = os.path.splitext (f)
+    if e == ext:
+        e = ''
+    return p + e
 
 \f
 
 
 class Duration:
-       allowed_durs = (1, 2, 4, 8, 16, 32, 64, 128)
-       def __init__ (self, clocks):
-               self.clocks = clocks
-               if clocks <= 0:
-                       self.clocks = duration_quant_clocks
-               (self.dur, self.num, self.den) = self.dur_num_den (clocks)
-               
-       def dur_num_den (self, clocks):
-               for i in range (len (allowed_tuplet_clocks)):
-                       if clocks == allowed_tuplet_clocks[i]:
-                               return global_options.allowed_tuplets[i]
-
-               dur = 0; num = 1; den = 1;
-               g = gcd (clocks, clocks_per_1)
-               if g:
-                       (dur, num) = (clocks_per_1 / g, clocks / g)
-               if not dur in self.allowed_durs:
-                       dur = 4; num = clocks; den = clocks_per_4
-               return (dur, num, den)
-
-       def dump (self):
-               if self.den == 1:
-                       if self.num == 1:
-                               s = '%d' % self.dur
-                       elif self.num == 3 and self.dur != 1:
-                               s = '%d.' % (self.dur / 2)
-                       else:
-                               s = '%d*%d' % (self.dur, self.num)
-               else:
-                       s = '%d*%d/%d' % (self.dur, self.num, self.den)
-                       
-               global reference_note
-               reference_note.duration = self
-
-               return s
-
-       def compare (self, other):
-               return self.clocks - other.clocks
+    allowed_durs = (1, 2, 4, 8, 16, 32, 64, 128)
+    def __init__ (self, clocks):
+        self.clocks = clocks
+        if clocks <= 0:
+            self.clocks = duration_quant_clocks
+        (self.dur, self.num, self.den) = self.dur_num_den (clocks)
+        
+    def dur_num_den (self, clocks):
+        for i in range (len (allowed_tuplet_clocks)):
+            if clocks == allowed_tuplet_clocks[i]:
+                return global_options.allowed_tuplets[i]
+
+        dur = 0; num = 1; den = 1;
+        g = gcd (clocks, clocks_per_1)
+        if g:
+            (dur, num) = (clocks_per_1 / g, clocks / g)
+        if not dur in self.allowed_durs:
+            dur = 4; num = clocks; den = clocks_per_4
+        return (dur, num, den)
+
+    def dump (self):
+        if self.den == 1:
+            if self.num == 1:
+                s = '%d' % self.dur
+            elif self.num == 3 and self.dur != 1:
+                s = '%d.' % (self.dur / 2)
+            else:
+                s = '%d*%d' % (self.dur, self.num)
+        else:
+            s = '%d*%d/%d' % (self.dur, self.num, self.den)
+            
+        global reference_note
+        reference_note.duration = self
+
+        return s
+
+    def compare (self, other):
+        return self.clocks - other.clocks
 
 def sign (x):
-       if x >= 0:
-               return 1
-       else:
-               return -1
+    if x >= 0:
+        return 1
+    else:
+        return -1
 
 class Note:
-       names = (0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6)
-       alterations = (0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0)
-       alteration_names = ('eses', 'es', '', 'is' , 'isis')
-       def __init__ (self, clocks, pitch, velocity):
-               self.pitch = pitch
-               self.velocity = velocity
-               # hmm
-               self.clocks = clocks
-               self.duration = Duration (clocks)
-               (self.octave, self.notename, self.alteration) = self.o_n_a ()
-
-       def o_n_a (self):
-               # major scale: do-do
-               # minor scale: la-la  (= + 5) '''
-
-               n = self.names[(self.pitch) % 12]
-               a = self.alterations[(self.pitch) % 12]
-
-               if a and global_options.key.flats:
-                       a = - self.alterations[(self.pitch) % 12]
-                       n = (n - a) % 7
-
-               #  By tradition, all scales now consist of a sequence
-               #  of 7 notes each with a distinct name, from amongst
-               #  a b c d e f g.  But, minor scales have a wide
-               #  second interval at the top - the 'leading note' is
-               #  sharped. (Why? it just works that way! Anything
-               #  else doesn't sound as good and isn't as flexible at
-               #  saying things. In medieval times, scales only had 6
-               #  notes to avoid this problem - the hexachords.)
-
-               #  So, the d minor scale is d e f g a b-flat c-sharp d
-               #  - using d-flat for the leading note would skip the
-               #  name c and duplicate the name d.  Why isn't c-sharp
-               #  put in the key signature? Tradition. (It's also
-               #  supposedly based on the Pythagorean theory of the
-               #  cycle of fifths, but that really only applies to
-               #  major scales...)  Anyway, g minor is g a b-flat c d
-               #  e-flat f-sharp g, and all the other flat minor keys
-               #  end up with a natural leading note. And there you
-               #  have it.
-
-               #  John Sankey <bf250@freenet.carleton.ca>
-               #
-               #  Let's also do a-minor: a b c d e f gis a
-               #
-               #  --jcn
-
-               o = self.pitch / 12 - 4
-
-               key = global_options.key
-               if key.minor:
-                       # as -> gis
-                       if key.sharps == 0 and key.flats == 0 \
-                          and n == 5 and a == -1:
-                               n = 4; a = 1
-                       # des -> cis
-                               elif key.flats == 1 and n == 1 and a == -1:
-                               n = 0; a = 1
-                       # ges -> fis
-                       elif key.flats == 2 and n == 4 and a == -1:
-                               n = 3; a = 1
-                       # g -> fisis
-                       elif key.sharps == 5 and n == 4 and a == 0:
-                               n = 3; a = 2
-                       # d -> cisis
-                       elif key.sharps == 6 and n == 1 and a == 0:
-                               n = 0; a = 2
-                       # a -> gisis
-                       elif key.sharps == 7 and n == 5 and a == 0:
-                               n = 4; a = 2
-
-               # b -> ces
-               if key.flats >= 6 and n == 6 and a == 0:
-                       n = 0; a = -1; o = o + 1
-               # e -> fes
-               if key.flats >= 7 and n == 2 and a == 0:
-                       n = 3; a = -1
-
-               # f -> eis
-               if key.sharps >= 3 and n == 3 and a == 0:
-                       n = 2; a = 1
-               # c -> bis
-               if key.sharps >= 4 and n == 0 and a == 0:
-                       n = 6; a = 1; o = o - 1
-
-               return (o, n, a)
-               
-        def __repr__ (self):
-               s = chr ((self.notename + 2)  % 7 + ord ('a'))
-                return 'Note(%s %s)' % (s, self.duration.dump())
-
-       def dump (self, dump_dur = 1):
-               global reference_note
-               s = chr ((self.notename + 2)  % 7 + ord ('a'))
-               s = s + self.alteration_names[self.alteration + 2]
-               if global_options.absolute_pitches:
-                       commas = self.octave
-               else:
-                       delta = self.pitch - reference_note.pitch
-                       commas = sign (delta) * (abs (delta) / 12)
-                       if ((sign (delta) \
-                            * (self.notename - reference_note.notename) + 7) \
-                           % 7 >= 4) \
-                           or ((self.notename == reference_note.notename) \
-                               and (abs (delta) > 4) and (abs (delta) < 12)):
-                               commas = commas + sign (delta)
-                       
-               if commas > 0:
-                       s = s + "'" * commas
-               elif commas < 0:
-                       s = s + "," * -commas
-
-               ## FIXME: compile fix --jcn
-               if dump_dur and (global_options.explicit_durations \
-                  or self.duration.compare (reference_note.duration)):
-                       s = s + self.duration.dump ()
-
-               reference_note = self
-               
-               # TODO: move space
-               return s + ' '
+    names = (0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6)
+    alterations = (0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0)
+    alteration_names = ('eses', 'es', '', 'is' , 'isis')
+    def __init__ (self, clocks, pitch, velocity):
+        self.pitch = pitch
+        self.velocity = velocity
+        # hmm
+        self.clocks = clocks
+        self.duration = Duration (clocks)
+        (self.octave, self.notename, self.alteration) = self.o_n_a ()
+
+    def o_n_a (self):
+        # major scale: do-do
+        # minor scale: la-la  (= + 5) '''
+
+        n = self.names[(self.pitch) % 12]
+        a = self.alterations[(self.pitch) % 12]
+
+        if a and global_options.key.flats:
+            a = - self.alterations[(self.pitch) % 12]
+            n = (n - a) % 7
+
+        #  By tradition, all scales now consist of a sequence
+        #  of 7 notes each with a distinct name, from amongst
+        #  a b c d e f g.  But, minor scales have a wide
+        #  second interval at the top - the 'leading note' is
+        #  sharped. (Why? it just works that way! Anything
+        #  else doesn't sound as good and isn't as flexible at
+        #  saying things. In medieval times, scales only had 6
+        #  notes to avoid this problem - the hexachords.)
+
+        #  So, the d minor scale is d e f g a b-flat c-sharp d
+        #  - using d-flat for the leading note would skip the
+        #  name c and duplicate the name d.  Why isn't c-sharp
+        #  put in the key signature? Tradition. (It's also
+        #  supposedly based on the Pythagorean theory of the
+        #  cycle of fifths, but that really only applies to
+        #  major scales...)  Anyway, g minor is g a b-flat c d
+        #  e-flat f-sharp g, and all the other flat minor keys
+        #  end up with a natural leading note. And there you
+        #  have it.
+
+        #  John Sankey <bf250@freenet.carleton.ca>
+        #
+        #  Let's also do a-minor: a b c d e f gis a
+        #
+        #  --jcn
+
+        o = self.pitch / 12 - 4
+
+        key = global_options.key
+        if key.minor:
+            # as -> gis
+            if key.sharps == 0 and key.flats == 0 \
+             and n == 5 and a == -1:
+                n = 4; a = 1
+            # des -> cis
+               elif key.flats == 1 and n == 1 and a == -1:
+                n = 0; a = 1
+            # ges -> fis
+            elif key.flats == 2 and n == 4 and a == -1:
+                n = 3; a = 1
+            # g -> fisis
+            elif key.sharps == 5 and n == 4 and a == 0:
+                n = 3; a = 2
+            # d -> cisis
+            elif key.sharps == 6 and n == 1 and a == 0:
+                n = 0; a = 2
+            # a -> gisis
+            elif key.sharps == 7 and n == 5 and a == 0:
+                n = 4; a = 2
+
+        # b -> ces
+        if key.flats >= 6 and n == 6 and a == 0:
+            n = 0; a = -1; o = o + 1
+        # e -> fes
+        if key.flats >= 7 and n == 2 and a == 0:
+            n = 3; a = -1
+
+        # f -> eis
+        if key.sharps >= 3 and n == 3 and a == 0:
+            n = 2; a = 1
+        # c -> bis
+        if key.sharps >= 4 and n == 0 and a == 0:
+            n = 6; a = 1; o = o - 1
+
+        return (o, n, a)
+        
+    def __repr__ (self):
+        s = chr ((self.notename + 2)  % 7 + ord ('a'))
+        return 'Note(%s %s)' % (s, self.duration.dump())
+
+    def dump (self, dump_dur = 1):
+        global reference_note
+        s = chr ((self.notename + 2)  % 7 + ord ('a'))
+        s = s + self.alteration_names[self.alteration + 2]
+        if global_options.absolute_pitches:
+            commas = self.octave
+        else:
+            delta = self.pitch - reference_note.pitch
+            commas = sign (delta) * (abs (delta) / 12)
+            if ((sign (delta) \
+              * (self.notename - reference_note.notename) + 7) \
+              % 7 >= 4) \
+              or ((self.notename == reference_note.notename) \
+                and (abs (delta) > 4) and (abs (delta) < 12)):
+                commas = commas + sign (delta)
+            
+        if commas > 0:
+            s = s + "'" * commas
+        elif commas < 0:
+            s = s + "," * -commas
+
+        ## FIXME: compile fix --jcn
+        if dump_dur and (global_options.explicit_durations \
+         or self.duration.compare (reference_note.duration)):
+            s = s + self.duration.dump ()
+
+        reference_note = self
+        
+        # TODO: move space
+        return s + ' '
 
 
 class Time:
-       def __init__ (self, num, den):
-               self.clocks = 0
-               self.num = num
-               self.den = den
-
-       def bar_clocks (self):
-               return clocks_per_1 * self.num / self.den
-
-        def __repr__ (self):
-                return 'Time(%d/%d)' % (self.num, self.den)
-        
-       def dump (self):
-               global time
-               time = self
-               return '\n  ' + '\\time %d/%d ' % (self.num, self.den) + '\n  '
+    def __init__ (self, num, den):
+        self.clocks = 0
+        self.num = num
+        self.den = den
+
+    def bar_clocks (self):
+        return clocks_per_1 * self.num / self.den
+
+    def __repr__ (self):
+        return 'Time(%d/%d)' % (self.num, self.den)
+    
+    def dump (self):
+        global time
+        time = self
+        return '\n  ' + '\\time %d/%d ' % (self.num, self.den) + '\n  '
 
 class Tempo:
-       def __init__ (self, seconds_per_1):
-               self.clocks = 0
-               self.seconds_per_1 = seconds_per_1
-
-        def __repr__ (self):
-                return 'Tempo(%d)' % self.bpm ()
-        
-        def bpm (self):
-                return 4 * 60 / self.seconds_per_1
-        
-       def dump (self):
-               return '\n  ' + '\\tempo 4 = %d ' % (self.bpm()) + '\n  '
+    def __init__ (self, seconds_per_1):
+        self.clocks = 0
+        self.seconds_per_1 = seconds_per_1
+
+    def __repr__ (self):
+        return 'Tempo(%d)' % self.bpm ()
+    
+    def bpm (self):
+        return 4 * 60 / self.seconds_per_1
+    
+    def dump (self):
+        return '\n  ' + '\\tempo 4 = %d ' % (self.bpm()) + '\n  '
 
 class Clef:
-       clefs = ('"bass_8"', 'bass', 'violin', '"violin^8"')
-       def __init__ (self, type):
-               self.type = type
+    clefs = ('"bass_8"', 'bass', 'violin', '"violin^8"')
+    def __init__ (self, type):
+        self.type = type
 
-       def __repr__ (self):
-                return 'Clef(%s)' % self.clefs[self.type]
-        
-       def dump (self):
-               return '\n  \\clef %s\n  ' % self.clefs[self.type]
+    def __repr__ (self):
+        return 'Clef(%s)' % self.clefs[self.type]
+    
+    def dump (self):
+        return '\n  \\clef %s\n  ' % self.clefs[self.type]
 
 class Key:
-       key_sharps = ('c', 'g', 'd', 'a', 'e', 'b', 'fis')
-       key_flats = ('BUG', 'f', 'bes', 'es', 'as', 'des', 'ges')
-
-       def __init__ (self, sharps, flats, minor):
-               self.clocks = 0
-               self.flats = flats
-               self.sharps = sharps
-               self.minor = minor
-
-       def dump (self):
-               global_options.key = self
-
-               s = ''
-               if self.sharps and self.flats:
-                        pass
-               else:
-                        if self.flats:
-                               k = (ord ('cfbeadg'[self.flats % 7]) - ord ('a') - 2 -2 * self.minor + 7) % 7
-                       else:
-                               k = (ord ('cgdaebf'[self.sharps % 7]) - ord ('a') - 2 -2 * self.minor + 7) % 7
-  
-                       if not self.minor:
-                               name = chr ((k + 2) % 7 + ord ('a'))
-                       else:
-                               name = chr ((k + 2) % 7 + ord ('a'))
-
-                       # fis cis gis dis ais eis bis
-                       sharps = (2, 4, 6, 1, 3, 5, 7)
-                       # bes es as des ges ces fes
-                       flats = (6, 4, 2, 7, 5, 3, 1)
-                       a = 0
-                       if self.flats:
-                               if flats[k] <= self.flats:
-                                       a = -1
-                       else:
-                               if sharps[k] <= self.sharps:
-                                       a = 1
-
-                       if a:
-                               name = name + Note.alteration_names[a + 2]
-
-                       s = '\\key ' + name
-                       if self.minor:
-                               s = s + ' \\minor'
-                       else:
-                               s = s + ' \\major'
-
-               return '\n\n  ' + s + '\n  '
+    key_sharps = ('c', 'g', 'd', 'a', 'e', 'b', 'fis')
+    key_flats = ('BUG', 'f', 'bes', 'es', 'as', 'des', 'ges')
+
+    def __init__ (self, sharps, flats, minor):
+        self.clocks = 0
+        self.flats = flats
+        self.sharps = sharps
+        self.minor = minor
+
+    def dump (self):
+        global_options.key = self
+
+        s = ''
+        if self.sharps and self.flats:
+            pass
+        else:
+            if self.flats:
+                k = (ord ('cfbeadg'[self.flats % 7]) - ord ('a') - 2 -2 * self.minor + 7) % 7
+            else:
+                k = (ord ('cgdaebf'[self.sharps % 7]) - ord ('a') - 2 -2 * self.minor + 7) % 7
+            if not self.minor:
+                name = chr ((k + 2) % 7 + ord ('a'))
+            else:
+                name = chr ((k + 2) % 7 + ord ('a'))
+
+            # fis cis gis dis ais eis bis
+            sharps = (2, 4, 6, 1, 3, 5, 7)
+            # bes es as des ges ces fes
+            flats = (6, 4, 2, 7, 5, 3, 1)
+            a = 0
+            if self.flats:
+                if flats[k] <= self.flats:
+                    a = -1
+            else:
+                if sharps[k] <= self.sharps:
+                    a = 1
+
+            if a:
+                name = name + Note.alteration_names[a + 2]
+
+            s = '\\key ' + name
+            if self.minor:
+                s = s + ' \\minor'
+            else:
+                s = s + ' \\major'
+
+        return '\n\n  ' + s + '\n  '
 
 
 class Text:
-       text_types = (
-               'SEQUENCE_NUMBER',
-               'TEXT_EVENT',
-               'COPYRIGHT_NOTICE',
-               'SEQUENCE_TRACK_NAME',
-               'INSTRUMENT_NAME',
-               'LYRIC',
-               'MARKER',
-               'CUE_POINT',)
-       
-       def __init__ (self, type, text):
-               self.clocks = 0
-               self.type = type
-               self.text = text
-
-       def dump (self):
-               # urg, we should be sure that we're in a lyrics staff
-               if self.type == midi.LYRIC:
-                       s = '"%s"' % self.text
-                       d = Duration (self.clocks)
-                       if global_options.explicit_durations \
-                          or d.compare (reference_note.duration):
-                               s = s + Duration (self.clocks).dump ()
-                       s = s + ' '
-               else:
-                       s = '\n  % [' + self.text_types[self.type] + '] ' + self.text + '\n  '
-               return s
-
-        def __repr__ (self):
-                return 'Text(%d=%s)' % (self.type, self.text)
+    text_types = (
+        'SEQUENCE_NUMBER',
+        'TEXT_EVENT',
+        'COPYRIGHT_NOTICE',
+        'SEQUENCE_TRACK_NAME',
+        'INSTRUMENT_NAME',
+        'LYRIC',
+        'MARKER',
+        'CUE_POINT',)
+    
+    def __init__ (self, type, text):
+        self.clocks = 0
+        self.type = type
+        self.text = text
+
+    def dump (self):
+        # urg, we should be sure that we're in a lyrics staff
+        if self.type == midi.LYRIC:
+            s = '"%s"' % self.text
+            d = Duration (self.clocks)
+            if global_options.explicit_durations \
+             or d.compare (reference_note.duration):
+                s = s + Duration (self.clocks).dump ()
+            s = s + ' '
+        else:
+            s = '\n  % [' + self.text_types[self.type] + '] ' + self.text + '\n  '
+        return s
+
+    def __repr__ (self):
+        return 'Text(%d=%s)' % (self.type, self.text)
 
 
 
 def split_track (track):
-       chs = {}
-       for i in range(16):
-               chs[i] = []
-               
-       for e in track:
-               data = list (e[1])
-               if data[0] > 0x7f and data[0] < 0xf0:
-                       c = data[0] & 0x0f
-                       e = (e[0], tuple ([data[0] & 0xf0] + data[1:]))
-                       chs[c].append (e)
-               else:
-                       chs[0].append (e)
-
-       for i in range (16):
-               if chs[i] == []:
-                       del chs[i]
-
-       threads = []
-       for v in chs.values ():
-               events = events_on_channel (v)
-               thread = unthread_notes (events)
-               if len (thread):
-                       threads.append (thread)
-       return threads
+    chs = {}
+    for i in range(16):
+        chs[i] = []
+        
+    for e in track:
+        data = list (e[1])
+        if data[0] > 0x7f and data[0] < 0xf0:
+            c = data[0] & 0x0f
+            e = (e[0], tuple ([data[0] & 0xf0] + data[1:]))
+            chs[c].append (e)
+        else:
+            chs[0].append (e)
+
+    for i in range (16):
+        if chs[i] == []:
+            del chs[i]
+
+    threads = []
+    for v in chs.values ():
+        events = events_on_channel (v)
+        thread = unthread_notes (events)
+        if len (thread):
+            threads.append (thread)
+    return threads
 
 
 def quantise_clocks (clocks, quant):
-       q = int (clocks / quant) * quant
-       if q != clocks:
-               for tquant in allowed_tuplet_clocks:
-                       if int (clocks / tquant) * tquant == clocks:
-                               return clocks
-               if 2 * (clocks - q) > quant:
-                       q = q + quant
-       return q
+    q = int (clocks / quant) * quant
+    if q != clocks:
+        for tquant in allowed_tuplet_clocks:
+            if int (clocks / tquant) * tquant == clocks:
+                return clocks
+        if 2 * (clocks - q) > quant:
+            q = q + quant
+    return q
 
 def end_note (pitches, notes, t, e):
-       try:
-               (lt, vel) = pitches[e]
-               del pitches[e]
-
-               i = len (notes) - 1 
-               while i > 0:
-                       if notes[i][0] > lt:
-                               i = i -1
-                       else:
-                               break
-               d = t - lt
-               if duration_quant_clocks:
-                       d = quantise_clocks (d, duration_quant_clocks)
-                       if not d:
-                               d = duration_quant_clocks
-
-               notes.insert (i + 1,
-                           (lt, Note (d, e, vel)))
-
-       except KeyError:
-               pass
+    try:
+        (lt, vel) = pitches[e]
+        del pitches[e]
+
+        i = len (notes) - 1 
+        while i > 0:
+            if notes[i][0] > lt:
+                i = i -1
+            else:
+                break
+        d = t - lt
+        if duration_quant_clocks:
+            d = quantise_clocks (d, duration_quant_clocks)
+            if not d:
+                d = duration_quant_clocks
+
+        notes.insert (i + 1,
+              (lt, Note (d, e, vel)))
+
+    except KeyError:
+        pass
 
 def events_on_channel (channel):
-       pitches = {}
-
-       notes = []
-       events = []
-       last_lyric = 0
-       last_time = 0
-       for e in channel:
-               t = e[0]
-
-               if start_quant_clocks:
-                       t = quantise_clocks (t, start_quant_clocks)
-
-
-               if e[1][0] == midi.NOTE_OFF \
-                  or (e[1][0] == midi.NOTE_ON and e[1][2] == 0):
-                       end_note (pitches, notes, t, e[1][1])
-                       
-               elif e[1][0] == midi.NOTE_ON:
-                       if not pitches.has_key (e[1][1]):
-                               pitches[e[1][1]] = (t, e[1][2])
-                               
-               # all include ALL_NOTES_OFF
-               elif e[1][0] >= midi.ALL_SOUND_OFF \
-                    and e[1][0] <= midi.POLY_MODE_ON:
-                       for i in pitches.keys ():
-                               end_note (pitches, notes, t, i)
-                               
-               elif e[1][0] == midi.META_EVENT:
-                       if e[1][1] == midi.END_OF_TRACK:
-                               for i in pitches.keys ():
-                                       end_note (pitches, notes, t, i)
-                               break
-
-                       elif e[1][1] == midi.SET_TEMPO:
-                               (u0, u1, u2) = map (ord, e[1][2])
-                               us_per_4 = u2 + 256 * (u1 + 256 * u0)
-                               seconds_per_1 = us_per_4 * 4 / 1e6
-                               events.append ((t, Tempo (seconds_per_1)))
-                       elif e[1][1] == midi.TIME_SIGNATURE:
-                               (num, dur, clocks4, count32) = map (ord, e[1][2])
-                               den = 2 ** dur 
-                               events.append ((t, Time (num, den)))
-                       elif e[1][1] == midi.KEY_SIGNATURE:
-                               (alterations, minor) = map (ord, e[1][2])
-                               sharps = 0
-                               flats = 0
-                               if alterations < 127:
-                                       sharps = alterations
-                               else:
-                                       flats = 256 - alterations
-
-                               k = Key (sharps, flats, minor)
-                               events.append ((t, k))
-
-                               # ugh, must set key while parsing
-                               # because Note init uses key
-                               # Better do Note.calc () at dump time?
-                               global_options.key = k
-
-                       elif e[1][1] == midi.LYRIC \
-                            or (global_options.text_lyrics and e[1][1] == midi.TEXT_EVENT):
-                               if last_lyric:
-                                       last_lyric.clocks = t - last_time
-                                       events.append ((last_time, last_lyric))
-                               last_time = t
-                               last_lyric = Text (midi.LYRIC, e[1][2])
-
-                       elif e[1][1] >= midi.SEQUENCE_NUMBER \
-                            and e[1][1] <= midi.CUE_POINT:
-                               events.append ((t, Text (e[1][1], e[1][2])))
-                       else:
-                               if global_options.verbose:
-                                       sys.stderr.write ("SKIP: %s\n" % `e`)
-                               pass
-               else:
-                       if global_options.verbose:
-                               sys.stderr.write ("SKIP: %s\n" % `e`)
-                       pass
-
-       if last_lyric:
-               # last_lyric.clocks = t - last_time
-               # hmm
-               last_lyric.clocks = clocks_per_4
-               events.append ((last_time, last_lyric))
-               last_lyric = 0
-               
-       i = 0
-       while len (notes):
-               if i < len (events) and notes[0][0] >= events[i][0]:
-                       i = i + 1
-               else:
-                       events.insert (i, notes[0])
-                       del notes[0]
-       return events
+    pitches = {}
+
+    notes = []
+    events = []
+    last_lyric = 0
+    last_time = 0
+    for e in channel:
+        t = e[0]
+
+        if start_quant_clocks:
+            t = quantise_clocks (t, start_quant_clocks)
+
+
+        if e[1][0] == midi.NOTE_OFF \
+         or (e[1][0] == midi.NOTE_ON and e[1][2] == 0):
+            end_note (pitches, notes, t, e[1][1])
+            
+        elif e[1][0] == midi.NOTE_ON:
+            if not pitches.has_key (e[1][1]):
+                pitches[e[1][1]] = (t, e[1][2])
+                
+        # all include ALL_NOTES_OFF
+        elif e[1][0] >= midi.ALL_SOUND_OFF \
+          and e[1][0] <= midi.POLY_MODE_ON:
+            for i in pitches.keys ():
+                end_note (pitches, notes, t, i)
+                
+        elif e[1][0] == midi.META_EVENT:
+            if e[1][1] == midi.END_OF_TRACK:
+                for i in pitches.keys ():
+                    end_note (pitches, notes, t, i)
+                break
+
+            elif e[1][1] == midi.SET_TEMPO:
+                (u0, u1, u2) = map (ord, e[1][2])
+                us_per_4 = u2 + 256 * (u1 + 256 * u0)
+                seconds_per_1 = us_per_4 * 4 / 1e6
+                events.append ((t, Tempo (seconds_per_1)))
+            elif e[1][1] == midi.TIME_SIGNATURE:
+                (num, dur, clocks4, count32) = map (ord, e[1][2])
+                den = 2 ** dur 
+                events.append ((t, Time (num, den)))
+            elif e[1][1] == midi.KEY_SIGNATURE:
+                (alterations, minor) = map (ord, e[1][2])
+                sharps = 0
+                flats = 0
+                if alterations < 127:
+                    sharps = alterations
+                else:
+                    flats = 256 - alterations
+
+                k = Key (sharps, flats, minor)
+                events.append ((t, k))
+
+                # ugh, must set key while parsing
+                # because Note init uses key
+                # Better do Note.calc () at dump time?
+                global_options.key = k
+
+            elif e[1][1] == midi.LYRIC \
+              or (global_options.text_lyrics and e[1][1] == midi.TEXT_EVENT):
+                if last_lyric:
+                    last_lyric.clocks = t - last_time
+                    events.append ((last_time, last_lyric))
+                last_time = t
+                last_lyric = Text (midi.LYRIC, e[1][2])
+
+            elif e[1][1] >= midi.SEQUENCE_NUMBER \
+              and e[1][1] <= midi.CUE_POINT:
+                events.append ((t, Text (e[1][1], e[1][2])))
+            else:
+                if global_options.verbose:
+                    sys.stderr.write ("SKIP: %s\n" % `e`)
+                pass
+        else:
+            if global_options.verbose:
+                sys.stderr.write ("SKIP: %s\n" % `e`)
+            pass
+
+    if last_lyric:
+        # last_lyric.clocks = t - last_time
+        # hmm
+        last_lyric.clocks = clocks_per_4
+        events.append ((last_time, last_lyric))
+        last_lyric = 0
+        
+    i = 0
+    while len (notes):
+        if i < len (events) and notes[0][0] >= events[i][0]:
+            i = i + 1
+        else:
+            events.insert (i, notes[0])
+            del notes[0]
+    return events
 
 def unthread_notes (channel):
-       threads = []
-       while channel:
-               thread = []
-               end_busy_t = 0
-               start_busy_t = 0
-               todo = []
-               for e in channel:
-                       t = e[0]
-                       if e[1].__class__ == Note \
-                          and ((t == start_busy_t \
-                                and e[1].clocks + t == end_busy_t) \
-                           or t >= end_busy_t):
-                               thread.append (e)
-                               start_busy_t = t
-                               end_busy_t = t + e[1].clocks
-                       elif e[1].__class__ == Time \
-                            or e[1].__class__ == Key \
-                            or e[1].__class__ == Text \
-                            or e[1].__class__ == Tempo:
-                               thread.append (e)
-                       else:
-                               todo.append (e)
-               threads.append (thread)
-               channel = todo
-
-       return threads
+    threads = []
+    while channel:
+        thread = []
+        end_busy_t = 0
+        start_busy_t = 0
+        todo = []
+        for e in channel:
+            t = e[0]
+            if e[1].__class__ == Note \
+             and ((t == start_busy_t \
+                and e[1].clocks + t == end_busy_t) \
+              or t >= end_busy_t):
+                thread.append (e)
+                start_busy_t = t
+                end_busy_t = t + e[1].clocks
+            elif e[1].__class__ == Time \
+              or e[1].__class__ == Key \
+              or e[1].__class__ == Text \
+              or e[1].__class__ == Tempo:
+                thread.append (e)
+            else:
+                todo.append (e)
+        threads.append (thread)
+        channel = todo
+
+    return threads
 
 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 dump_skip (skip, clocks):
-       return skip + Duration (clocks).dump () + ' '
+    return skip + Duration (clocks).dump () + ' '
 
 def dump (d):
-       return d.dump ()
+    return d.dump ()
 
 def dump_chord (ch):
-       s = ''
-       notes = []
-       for i in ch:
-               if i.__class__ == Note:
-                       notes.append (i)
-               else:
-                       s = s + i.dump ()
-       if len (notes) == 1:
-               s = s + dump (notes[0])
-       elif len (notes) > 1:
-               global reference_note
-               s = s + '<'
-               s = s + notes[0].dump (dump_dur = 0)
-               r = reference_note
-               for i in notes[1:]:
-                       s = s + i.dump (dump_dur = 0 )
-               s = s + '>'
-
-               s = s + notes[0].duration.dump() + ' '
-               reference_note = r
-       return s
+    s = ''
+    notes = []
+    for i in ch:
+        if i.__class__ == Note:
+            notes.append (i)
+        else:
+            s = s + i.dump ()
+    if len (notes) == 1:
+        s = s + dump (notes[0])
+    elif len (notes) > 1:
+        global reference_note
+        s = s + '<'
+        s = s + notes[0].dump (dump_dur = 0)
+        r = reference_note
+        for i in notes[1:]:
+            s = s + i.dump (dump_dur = 0 )
+        s = s + '>'
+
+        s = s + notes[0].duration.dump() + ' '
+        reference_note = r
+    return s
 
 def dump_bar_line (last_bar_t, t, bar_count):
-       s = ''
-       bar_t = time.bar_clocks ()
-       if t - last_bar_t >= bar_t:
-               bar_count = bar_count + (t - last_bar_t) / bar_t
-               
-               if t - last_bar_t == bar_t:
-                       s = '|\n  %% %d\n  ' % bar_count
-                       last_bar_t = t
-               else:
-                       # urg, this will barf at meter changes
-                       last_bar_t = last_bar_t + (t - last_bar_t) / bar_t * bar_t
-                       
-       return (s, last_bar_t, bar_count)
-
-                       
+    s = ''
+    bar_t = time.bar_clocks ()
+    if t - last_bar_t >= bar_t:
+        bar_count = bar_count + (t - last_bar_t) / bar_t
+        
+        if t - last_bar_t == bar_t:
+            s = '|\n  %% %d\n  ' % bar_count
+            last_bar_t = t
+        else:
+            # urg, this will barf at meter changes
+            last_bar_t = last_bar_t + (t - last_bar_t) / bar_t * bar_t
+            
+    return (s, last_bar_t, bar_count)
+
+            
 def dump_channel (thread, skip):
-       global reference_note, time
-
-       global_options.key = Key (0, 0, 0)
-       time = Time (4, 4)
-       # urg LilyPond doesn't start at c4, but
-       # remembers from previous tracks!
-       # reference_note = Note (clocks_per_4, 4*12, 0)
-       reference_note = Note (0, 4*12, 0)
-       last_e = None
-       chs = []
-       ch = []
-
-       for e in thread:
-               if last_e and last_e[0] == e[0]:
-                       ch.append (e[1])
-               else:
-                       if ch:
-                               chs.append ((last_e[0], ch))
-                               
-                       ch = [e[1]]
-                       
-               last_e = e
-
-       if ch:
-               chs.append ((last_e[0], ch))
-       t = 0
-       last_t = 0
-       last_bar_t = 0
-       bar_count = 1
-       
-       lines = ['']
-       for ch in chs: 
-               t = ch[0]
-
-               i = string.rfind (lines[-1], '\n') + 1
-               if len (lines[-1][i:]) > LINE_BELL:
-                       lines.append ('')
-                       
-               if t - last_t > 0:
-                       lines[-1] = lines[-1] + dump_skip (skip, t-last_t)
-               elif t - last_t < 0:
-                       errorport.write ('BUG: time skew')
-
-               (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t,
-                                                           t, bar_count)
-               lines[-1] = lines[-1] + s
-               
-               lines[-1] = lines[-1] + dump_chord (ch[1])
-
-               clocks = 0
-               for i in ch[1]:
-                       if i.clocks > clocks:
-                               clocks = i.clocks
-                               
-               last_t = t + clocks
-               
-               (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t,
-                                                           last_t, bar_count)
-               lines[-1] = lines[-1] + s
-
-       return string.join (lines, '\n  ') + '\n'
+    global reference_note, time
+
+    global_options.key = Key (0, 0, 0)
+    time = Time (4, 4)
+    # urg LilyPond doesn't start at c4, but
+    # remembers from previous tracks!
+    # reference_note = Note (clocks_per_4, 4*12, 0)
+    reference_note = Note (0, 4*12, 0)
+    last_e = None
+    chs = []
+    ch = []
+
+    for e in thread:
+        if last_e and last_e[0] == e[0]:
+            ch.append (e[1])
+        else:
+            if ch:
+                chs.append ((last_e[0], ch))
+                
+            ch = [e[1]]
+            
+        last_e = e
+
+    if ch:
+        chs.append ((last_e[0], ch))
+    t = 0
+    last_t = 0
+    last_bar_t = 0
+    bar_count = 1
+    
+    lines = ['']
+    for ch in chs: 
+        t = ch[0]
+
+        i = string.rfind (lines[-1], '\n') + 1
+        if len (lines[-1][i:]) > LINE_BELL:
+            lines.append ('')
+            
+        if t - last_t > 0:
+            lines[-1] = lines[-1] + dump_skip (skip, t-last_t)
+        elif t - last_t < 0:
+            errorport.write ('BUG: time skew')
+
+        (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t,
+                              t, bar_count)
+        lines[-1] = lines[-1] + s
+        
+        lines[-1] = lines[-1] + dump_chord (ch[1])
+
+        clocks = 0
+        for i in ch[1]:
+            if i.clocks > clocks:
+                clocks = i.clocks
+                
+        last_t = t + clocks
+        
+        (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t,
+                              last_t, bar_count)
+        lines[-1] = lines[-1] + s
+
+    return string.join (lines, '\n  ') + '\n'
 
 def track_name (i):
-       return 'track%c' % (i + ord ('A'))
+    return 'track%c' % (i + ord ('A'))
 
 def channel_name (i):
-       return 'channel%c' % (i + ord ('A'))
+    return 'channel%c' % (i + ord ('A'))
 
 def dump_track (channels, n):
-       s = '\n'
-       track = track_name (n)
-       clef = guess_clef (channels)
-
-       for i in range (len (channels)):
-               channel = channel_name (i)
-               item = thread_first_item (channels[i])
-
-               if item and item.__class__ == Note:
-                       skip = 's'
-                       s = s + '%s = ' % (track + channel)
-                       if not global_options.absolute_pitches:
-                               s = s + '\\relative c '
-               elif item and item.__class__ == Text:
-                       skip = '" "'
-                       s = s + '%s = \\lyricmode ' % (track + channel)
-               else:
-                       skip = '\\skip '
-                       s = s + '%s =  ' % (track + channel)
-               s = s + '{\n'
-               s = s + '  ' + dump_channel (channels[i][0], skip)
-               s = s + '}\n\n'
-
-       s = s + '%s = <<\n' % track
-
-       if clef.type != 2:
-               s = s + clef.dump () + '\n'
-
-       for i in range (len (channels)):
-               channel = channel_name (i)
-               item = thread_first_item (channels[i])
-               if item and item.__class__ == Text:
-                       s = s + '  \\context Lyrics = %s \\%s\n' % (channel,
-                                                                   track + channel)
-               else:
-                       s = s + '  \\context Voice = %s \\%s\n' % (channel,
-                                                                  track + channel)
-       s = s + '>>\n\n'
-       return s
+    s = '\n'
+    track = track_name (n)
+    clef = guess_clef (channels)
+
+    for i in range (len (channels)):
+        channel = channel_name (i)
+        item = thread_first_item (channels[i])
+
+        if item and item.__class__ == Note:
+            skip = 's'
+            s = s + '%s = ' % (track + channel)
+            if not global_options.absolute_pitches:
+                s = s + '\\relative c '
+        elif item and item.__class__ == Text:
+            skip = '" "'
+            s = s + '%s = \\lyricmode ' % (track + channel)
+        else:
+            skip = '\\skip '
+            s = s + '%s =  ' % (track + channel)
+        s = s + '{\n'
+        s = s + '  ' + dump_channel (channels[i][0], skip)
+        s = s + '}\n\n'
+
+    s = s + '%s = <<\n' % track
+
+    if clef.type != 2:
+        s = s + clef.dump () + '\n'
+
+    for i in range (len (channels)):
+        channel = channel_name (i)
+        item = thread_first_item (channels[i])
+        if item and item.__class__ == Text:
+            s = s + '  \\context Lyrics = %s \\%s\n' % (channel,
+                                  track + channel)
+        else:
+            s = s + '  \\context Voice = %s \\%s\n' % (channel,
+                                 track + channel)
+    s = s + '>>\n\n'
+    return s
 
 def thread_first_item (thread):
-       for chord in thread:
-               for event in chord:
-                       if (event[1].__class__ == Note 
-                            or (event[1].__class__ == Text 
-                                and event[1].type == midi.LYRIC)):
-                                
-                            return event[1]
-       return None
+    for chord in thread:
+        for event in chord:
+            if (event[1].__class__ == Note 
+              or (event[1].__class__ == Text 
+                and event[1].type == midi.LYRIC)):
+                
+              return event[1]
+    return None
 
 def track_first_item (track):
-       for thread in track:
-               first = thread_first_item (thread)
-                if first:
-                        return first
-        return None
+    for thread in track:
+        first = thread_first_item (thread)
+        if first:
+            return first
+    return None
 
 def guess_clef (track):
-       i = 0
-       p = 0
-       for thread in track:
-               for chord in thread:
-                       for event in chord:
-                               if event[1].__class__ == Note:
-                                       i = i + 1
-                                       p = p + event[1].pitch
-       if i and p / i <= 3*12:
-               return Clef (0)
-       elif i and p / i <= 5*12:
-               return Clef (1)
-       elif i and p / i >= 7*12:
-               return Clef (3)
-       else:
-               return Clef (2)
-       
+    i = 0
+    p = 0
+    for thread in track:
+        for chord in thread:
+            for event in chord:
+                if event[1].__class__ == Note:
+                    i = i + 1
+                    p = p + event[1].pitch
+    if i and p / i <= 3*12:
+        return Clef (0)
+    elif i and p / i <= 5*12:
+        return Clef (1)
+    elif i and p / i >= 7*12:
+        return Clef (3)
+    else:
+        return Clef (2)
+    
 
 def convert_midi (in_file, out_file):
-       global clocks_per_1, clocks_per_4, key
-       global start_quant_clocks
-       global  duration_quant_clocks
-       global allowed_tuplet_clocks
-
-       str = open (in_file).read ()
-       midi_dump = midi.parse (str)
-        
-       clocks_per_1 = midi_dump[0][1]
-       clocks_per_4 = clocks_per_1 / 4
-       
-       if global_options.start_quant:
-               start_quant_clocks = clocks_per_1 / global_options.start_quant
-
-       if global_options.duration_quant:
-               duration_quant_clocks = clocks_per_1 / global_options.duration_quant
-
-       allowed_tuplet_clocks = []
-       for (dur, num, den) in global_options.allowed_tuplets:
-               allowed_tuplet_clocks.append (clocks_per_1 / den)
-
-       tracks = []
-       for t in midi_dump[1]:
-               global_options.key = Key (0, 0, 0)
-               tracks.append (split_track (t))
-
-       tag = '%% Lily was here -- automatically converted by %s from %s' % ( program_name, in_file)
-
+    global clocks_per_1, clocks_per_4, key
+    global start_quant_clocks
+    global  duration_quant_clocks
+    global allowed_tuplet_clocks
+
+    str = open (in_file).read ()
+    midi_dump = midi.parse (str)
+    
+    clocks_per_1 = midi_dump[0][1]
+    clocks_per_4 = clocks_per_1 / 4
+    
+    if global_options.start_quant:
+        start_quant_clocks = clocks_per_1 / global_options.start_quant
+
+    if global_options.duration_quant:
+        duration_quant_clocks = clocks_per_1 / global_options.duration_quant
+
+    allowed_tuplet_clocks = []
+    for (dur, num, den) in global_options.allowed_tuplets:
+        allowed_tuplet_clocks.append (clocks_per_1 / den)
+
+    tracks = []
+    for t in midi_dump[1]:
+        global_options.key = Key (0, 0, 0)
+        tracks.append (split_track (t))
+
+    tag = '%% Lily was here -- automatically converted by %s from %s' % ( program_name, in_file)
+
+    
+    s = ''
+    s = tag + '\n\\version "2.7.18"\n\n'
+    for i in range (len (tracks)):
+        s = s + dump_track (tracks[i], i)
+
+    s = s + '\n\\score {\n  <<\n'
+    
+    i = 0
+    for t in tracks:
+        track = track_name (i)
+        item = track_first_item (t)
         
-       s = ''
-       s = tag + '\n\\version "2.7.18"\n\n'
-       for i in range (len (tracks)):
-               s = s + dump_track (tracks[i], i)
-
-       s = s + '\n\\score {\n  <<\n'
-        
-        i = 0
-       for t in tracks:
-               track = track_name (i)
-               item = track_first_item (t)
-                
-               if item and item.__class__ == Note:
-                       s = s + '    \\context Staff=%s \\%s\n' % (track, track)
-               elif item and item.__class__ == Text:
-                       s = s + '    \\context Lyrics=%s \\%s\n' % (track, track)
+        if item and item.__class__ == Note:
+            s = s + '    \\context Staff=%s \\%s\n' % (track, track)
+        elif item and item.__class__ == Text:
+            s = s + '    \\context Lyrics=%s \\%s\n' % (track, track)
 
-                i += 1
-       s = s + '  >>\n}\n'
+        i += 1
+    s = s + '  >>\n}\n'
 
-       progress (_ ("%s output to `%s'...") % ('LY', out_file))
+    progress (_ ("%s output to `%s'...") % ('LY', out_file))
 
-       if out_file == '-':
-               handle = sys.stdout
-       else:
-               handle = open (out_file, 'w')
+    if out_file == '-':
+        handle = sys.stdout
+    else:
+        handle = open (out_file, 'w')
 
-       handle.write (s)
-       handle.close ()
+    handle.write (s)
+    handle.close ()
 
 
 def get_option_parser ():
-       p = ly.get_option_parser (usage='midi2ly [OPTIONS] FILE',
-                                 version="midi2ly (LilyPond) @TOPLEVEL_VERSION@",
-                                 description=_('''Convert MIDI to LilyPond source.'''))
-
-       p.add_option ('-a', '--absolute-pitches',
-                     action='store_true',
-                     help=_ ("print absolute pitches"))
-       p.add_option ('-d', '--duration-quant',
-                     metavar= _("DUR"),
-                     help=_("quantise note durations on DUR"))
-       p.add_option ('-e', '--explicit-durations',
-                     action='store_true',
-                     help=_ ("print explicit durations"))
-       p.add_option('-k', '--key', help=_ ("set key: ALT=+sharps|-flats; MINOR=1"),
-                    metavar=_ ("ALT[:MINOR]"),
-                    default='0'),
-       p.add_option ('-o', '--output', help=_("write output to FILE"),
-                     metavar=_("FILE"),
-                     action='store')
-       p.add_option ('-s', '--start-quant',help= _ ("quantise note starts on DUR"),
-                     metavar=_ ("DUR"))
-       p.add_option ('-t', '--allow-tuplet',
-                     metavar=_ ("DUR*NUM/DEN"),
-                     action = "append",
-                     dest="allowed_tuplets",
-                     help=_ ("allow tuplet durations DUR*NUM/DEN"),
-                     default=[])
-       p.add_option ('-V', '--verbose', help=_("be verbose"),
-                     action='store_true'
-                     ),
-       p.add_option ('-w', '--warranty', help=_("show warranty"),
-                     action='store_true',
-                     ),
-       p.add_option ('-x', '--text-lyrics', help=_("treat every text as a lyric"),
-                     action='store_true')
-
-       p.add_option_group (_ ("example"),
-                           description = r'''
-    midi2ly --key=-2:1 --duration-quant=32 \
-        --allow-tuplet=4*2/3 --allow-tuplet=2*4/3 foo.midi
+    p = ly.get_option_parser (usage='midi2ly [OPTIONS] FILE',
+                 version="midi2ly (LilyPond) @TOPLEVEL_VERSION@",
+                 description=_('''Convert MIDI to LilyPond source.'''))
+
+    p.add_option ('-a', '--absolute-pitches',
+           action='store_true',
+           help=_ ("print absolute pitches"))
+    p.add_option ('-d', '--duration-quant',
+           metavar= _("DUR"),
+           help=_("quantise note durations on DUR"))
+    p.add_option ('-e', '--explicit-durations',
+           action='store_true',
+           help=_ ("print explicit durations"))
+    p.add_option('-k', '--key', help=_ ("set key: ALT=+sharps|-flats; MINOR=1"),
+          metavar=_ ("ALT[:MINOR]"),
+          default='0'),
+    p.add_option ('-o', '--output', help=_("write output to FILE"),
+           metavar=_("FILE"),
+           action='store')
+    p.add_option ('-s', '--start-quant',help= _ ("quantise note starts on DUR"),
+           metavar=_ ("DUR"))
+    p.add_option ('-t', '--allow-tuplet',
+           metavar=_ ("DUR*NUM/DEN"),
+           action = "append",
+           dest="allowed_tuplets",
+           help=_ ("allow tuplet durations DUR*NUM/DEN"),
+           default=[])
+    p.add_option ('-V', '--verbose', help=_("be verbose"),
+           action='store_true'
+           ),
+    p.add_option ('-w', '--warranty', help=_("show warranty"),
+           action='store_true',
+           ),
+    p.add_option ('-x', '--text-lyrics', help=_("treat every text as a lyric"),
+           action='store_true')
+
+    p.add_option_group (_ ("example"),
+              description = r'''
+  midi2ly --key=-2:1 --duration-quant=32 \
+    --allow-tuplet=4*2/3 --allow-tuplet=2*4/3 foo.midi
 ''')
-       
-       p.add_option_group  ('bugs',
-                            description='''Report bugs via http://post.gmane.org/post.php'''
-                            '''?group=gmane.comp.gnu.lilypond.bugs\n''')
-       
-       return p
+    
+    p.add_option_group  ('bugs',
+              description='''Report bugs via 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 not args or args[0] == '-':
-               opt_parser.print_help ()
-               sys.stderr.write ('\n%s: %s %s\n' % (program_name, _ ("error: "),
-                                                    _ ("no files specified on command line.")))
-               sys.exit (2)
-
-       if options.duration_quant:
-               options.duration_quant = int (options.duration_quant)
-
-       if options.warranty:
-               warranty ()
-               sys.exit (0)
-       if 1:
-               (alterations, minor) = map (int, string.split (options.key + ':0', ':'))[0:2]
-               sharps = 0
-               flats = 0
-               if alterations >= 0:
-                       sharps = alterations
-               else:
-                       flats = - alterations
-
-               options.key = Key (sharps, flats, minor)
-
-               
-       if options.start_quant:
-               options.start_quant = int (options.start_quant)
-               
-       options.allowed_tuplets = [map (int, a.replace ('/','*').split ('*'))
-                               for a in options.allowed_tuplets]
-       
-       global global_options
-       global_options = options
-
-       return args
+    opt_parser = get_option_parser()
+    (options, args) = opt_parser.parse_args ()
+
+    if not args or args[0] == '-':
+        opt_parser.print_help ()
+        sys.stderr.write ('\n%s: %s %s\n' % (program_name, _ ("error: "),
+                          _ ("no files specified on command line.")))
+        sys.exit (2)
+
+    if options.duration_quant:
+        options.duration_quant = int (options.duration_quant)
+
+    if options.warranty:
+        warranty ()
+        sys.exit (0)
+    if 1:
+        (alterations, minor) = map (int, string.split (options.key + ':0', ':'))[0:2]
+        sharps = 0
+        flats = 0
+        if alterations >= 0:
+            sharps = alterations
+        else:
+            flats = - alterations
+
+        options.key = Key (sharps, flats, minor)
+
+        
+    if options.start_quant:
+        options.start_quant = int (options.start_quant)
+        
+    options.allowed_tuplets = [map (int, a.replace ('/','*').split ('*'))
+                for a in options.allowed_tuplets]
+    
+    global global_options
+    global_options = options
+
+    return args
 
 def main():
-       files = do_options()
-
-       for f in files:
-               g = f
-               g = strip_extension (g, '.midi')
-               g = strip_extension (g, '.mid')
-               g = strip_extension (g, '.MID')
-               (outdir, outbase) = ('','')
-
-               if not output_name:
-                       outdir = '.'
-                       outbase = os.path.basename (g)
-                       o = os.path.join (outdir, outbase + '-midi.ly')
-               elif output_name[-1] == os.sep:
-                       outdir = output_name
-                       outbase = os.path.basename (g)
-                       os.path.join (outdir, outbase + '-gen.ly')
-               else:
-                       o = output_name
-                       (outdir, outbase) = os.path.split (o)
-
-               if outdir != '.' and outdir != '':
-                       try:
-                               os.mkdir (outdir, 0777)
-                       except OSError:
-                               pass
-
-               convert_midi (f, o)
+    files = do_options()
+
+    for f in files:
+        g = f
+        g = strip_extension (g, '.midi')
+        g = strip_extension (g, '.mid')
+        g = strip_extension (g, '.MID')
+        (outdir, outbase) = ('','')
+
+        if not output_name:
+            outdir = '.'
+            outbase = os.path.basename (g)
+            o = os.path.join (outdir, outbase + '-midi.ly')
+        elif output_name[-1] == os.sep:
+            outdir = output_name
+            outbase = os.path.basename (g)
+            os.path.join (outdir, outbase + '-gen.ly')
+        else:
+            o = output_name
+            (outdir, outbase) = os.path.split (o)
+
+        if outdir != '.' and outdir != '':
+            try:
+                os.mkdir (outdir, 0777)
+            except OSError:
+                pass
+
+        convert_midi (f, o)
 if __name__ == '__main__':
-       main()
+    main()
index 15bbb2ba6582cbabf5703886e18ca2eed6026414..71b41d9dc35e9359d1a1c333a750a20ccafddcbc 100644 (file)
@@ -10,16 +10,16 @@ from gettext import gettext as _
 
 datadir = '@local_lilypond_datadir@'
 if not os.path.isdir (datadir):
-       datadir = '@lilypond_datadir@'
+    datadir = '@lilypond_datadir@'
 if os.environ.has_key ('LILYPONDPREFIX'):
-       datadir = os.environ['LILYPONDPREFIX']
-       while datadir[-1] == os.sep:
-               datadir = datadir[:-1]
+    datadir = os.environ['LILYPONDPREFIX']
+    while datadir[-1] == os.sep:
+        datadir = datadir[:-1]
 
 if os.path.exists (os.path.join (datadir, 'share/lilypond/@TOPLEVEL_VERSION@/')):
-       datadir = os.path.join (datadir, 'share/lilypond/@TOPLEVEL_VERSION@/')
+    datadir = os.path.join (datadir, 'share/lilypond/@TOPLEVEL_VERSION@/')
 elif os.path.exists (os.path.join (datadir, 'share/lilypond/current/')):
-       datadir = os.path.join (datadir, 'share/lilypond/current/')
+    datadir = os.path.join (datadir, 'share/lilypond/current/')
 
 sys.path.insert (0, os.path.join (datadir, 'python'))
 
@@ -27,8 +27,8 @@ sys.path.insert (0, os.path.join (datadir, 'python'))
 bindir = os.path.split (sys.argv[0])[0]
 
 for prefix_component in ['share', 'lib']:
-       datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % prefix_component)
-       sys.path.insert (0, datadir)
+    datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % prefix_component)
+    sys.path.insert (0, datadir)
 
 
 
@@ -40,349 +40,349 @@ from rational import Rational
 
 
 def progress (str):
-       sys.stderr.write (str + '\n')
-       sys.stderr.flush ()
-       
+    sys.stderr.write (str + '\n')
+    sys.stderr.flush ()
+    
 
 def musicxml_duration_to_lily (mxl_note):
-       d = musicexp.Duration ()
-       if mxl_note.get_maybe_exist_typed_child (musicxml.Type):
-               d.duration_log = mxl_note.get_duration_log ()
-       else:
-               d.duration_log = 0
+    d = musicexp.Duration ()
+    if mxl_note.get_maybe_exist_typed_child (musicxml.Type):
+        d.duration_log = mxl_note.get_duration_log ()
+    else:
+        d.duration_log = 0
 
-       d.dots = len (mxl_note.get_typed_children (musicxml.Dot))
-       d.factor = mxl_note._duration / d.get_length ()
+    d.dots = len (mxl_note.get_typed_children (musicxml.Dot))
+    d.factor = mxl_note._duration / d.get_length ()
 
-       return d        
+    return d         
 
 def group_tuplets (music_list, events):
 
 
-       """Collect Musics from
-       MUSIC_LIST demarcated by EVENTS_LIST in TimeScaledMusic objects.
-       """
+    """Collect Musics from
+    MUSIC_LIST demarcated by EVENTS_LIST in TimeScaledMusic objects.
+    """
 
-       
-       indices = []
+    
+    indices = []
 
-       j = 0
-       for (ev_chord, tuplet_elt, fraction) in events:
-               while (j < len (music_list)):
-                       if music_list[j]== ev_chord:
-                               break
-                       j += 1
-               if tuplet_elt.type == 'start':
-                       indices.append ((j, None, fraction))
-               elif tuplet_elt.type == 'stop':
-                       indices[-1] = (indices[-1][0], j, indices[-1][2])
+    j = 0
+    for (ev_chord, tuplet_elt, fraction) in events:
+        while (j < len (music_list)):
+            if music_list[j]== ev_chord:
+                break
+            j += 1
+        if tuplet_elt.type == 'start':
+            indices.append ((j, None, fraction))
+        elif tuplet_elt.type == 'stop':
+            indices[-1] = (indices[-1][0], j, indices[-1][2])
 
-       new_list = []
-       last = 0
-       for (i1, i2, frac) in indices:
-               if i1 >= i2:
-                       continue
+    new_list = []
+    last = 0
+    for (i1, i2, frac) in indices:
+        if i1 >= i2:
+            continue
 
-               new_list.extend (music_list[last:i1])
-               seq = musicexp.SequentialMusic ()
-               last = i2 + 1
-               seq.elements = music_list[i1:last]
+        new_list.extend (music_list[last:i1])
+        seq = musicexp.SequentialMusic ()
+        last = i2 + 1
+        seq.elements = music_list[i1:last]
 
-               tsm = musicexp.TimeScaledMusic ()
-               tsm.element = seq
+        tsm = musicexp.TimeScaledMusic ()
+        tsm.element = seq
 
-               tsm.numerator = frac[0]
-               tsm.denominator  = frac[1]
+        tsm.numerator = frac[0]
+        tsm.denominator  = frac[1]
 
-               new_list.append (tsm)
+        new_list.append (tsm)
 
-       new_list.extend (music_list[last:])
-       return new_list
+    new_list.extend (music_list[last:])
+    return new_list
 
 
 def musicxml_clef_to_lily (mxl):
-       sign = mxl.get_maybe_exist_named_child ('sign')
-       change = musicexp.ClefChange ()
-       if sign:
-               change.type = sign.get_text ()
-       return change
+    sign = mxl.get_maybe_exist_named_child ('sign')
+    change = musicexp.ClefChange ()
+    if sign:
+        change.type = sign.get_text ()
+    return change
 
-       
+    
 def musicxml_time_to_lily (mxl):
-       beats = mxl.get_maybe_exist_named_child ('beats')
-       type = mxl.get_maybe_exist_named_child ('beat-type')
-       change = musicexp.TimeSignatureChange()
-       change.fraction = (string.atoi(beats.get_text ()),
-                          string.atoi(type.get_text ()))
-       
-       return change
+    beats = mxl.get_maybe_exist_named_child ('beats')
+    type = mxl.get_maybe_exist_named_child ('beat-type')
+    change = musicexp.TimeSignatureChange()
+    change.fraction = (string.atoi(beats.get_text ()),
+             string.atoi(type.get_text ()))
+    
+    return change
 
 def musicxml_key_to_lily (mxl):
-       start_pitch  = musicexp.Pitch ()
-       try:
-               mode = mxl.get_maybe_exist_named_child ('mode')
-               if mode:
-                       mode = mode.get_text ()
-               else:
-                       mode = 'major'
-                       
-               (n,a) = { 'major' : (0,0),
-                         'minor' : (6,0),
-                       }[mode]
-               start_pitch.step = n
-               start_pitch.alteration = a
-       except  KeyError:
-               print 'unknown mode', mode
-               
-       fifths = string.atoi (mxl.get_maybe_exist_named_child ('fifths').get_text ())
-
-       fifth = musicexp.Pitch()
-       fifth.step = 4
-       if fifths < 0:
-               fifths *= -1
-               fifth.step *= -1
-               fifth.normalize ()
-       
-       start_pitch = musicexp.Pitch()
-       for x in range (fifths):
-               start_pitch = start_pitch.transposed (fifth)
-
-       start_pitch.octave = 0
-
-       change = musicexp.KeySignatureChange()
-       change.mode = mode
-       change.tonic = start_pitch
-       return change
-       
+    start_pitch  = musicexp.Pitch ()
+    try:
+        mode = mxl.get_maybe_exist_named_child ('mode')
+        if mode:
+            mode = mode.get_text ()
+        else:
+            mode = 'major'
+            
+        (n,a) = { 'major' : (0,0),
+             'minor' : (6,0),
+            }[mode]
+        start_pitch.step = n
+        start_pitch.alteration = a
+    except  KeyError:
+        print 'unknown mode', mode
+        
+    fifths = string.atoi (mxl.get_maybe_exist_named_child ('fifths').get_text ())
+
+    fifth = musicexp.Pitch()
+    fifth.step = 4
+    if fifths < 0:
+        fifths *= -1
+        fifth.step *= -1
+        fifth.normalize ()
+    
+    start_pitch = musicexp.Pitch()
+    for x in range (fifths):
+        start_pitch = start_pitch.transposed (fifth)
+
+    start_pitch.octave = 0
+
+    change = musicexp.KeySignatureChange()
+    change.mode = mode
+    change.tonic = start_pitch
+    return change
+    
 def musicxml_attributes_to_lily (attrs):
-       elts = []
-       attr_dispatch =  {
-               'clef': musicxml_clef_to_lily,
-               'time': musicxml_time_to_lily,
-               'key': musicxml_key_to_lily
-       }
-       for (k, func) in attr_dispatch.items ():
-               childs = attrs.get_named_children (k)
-
-               ## ugh: you get clefs spread over staves for piano
-               if childs:
-                       elts.append (func (childs[0]))
-       
-       return elts
+    elts = []
+    attr_dispatch =  {
+        'clef': musicxml_clef_to_lily,
+        'time': musicxml_time_to_lily,
+        'key': musicxml_key_to_lily
+    }
+    for (k, func) in attr_dispatch.items ():
+        childs = attrs.get_named_children (k)
+
+        ## ugh: you get clefs spread over staves for piano
+        if childs:
+            elts.append (func (childs[0]))
+    
+    return elts
 
 def create_skip_music (duration):
-       skip = musicexp.SkipEvent()
-       skip.duration.duration_log = 0
-       skip.duration.factor = duration
+    skip = musicexp.SkipEvent()
+    skip.duration.duration_log = 0
+    skip.duration.factor = duration
 
-       evc = musicexp.EventChord ()
-       evc.append (skip)
-       return evc
+    evc = musicexp.EventChord ()
+    evc.append (skip)
+    return evc
 
 spanner_event_dict = {
-       'slur' : musicexp.SlurEvent,
-       'beam' : musicexp.BeamEvent,
-}      
+    'slur' : musicexp.SlurEvent,
+    'beam' : musicexp.BeamEvent,
+}        
 spanner_type_dict = {
-       'start': -1,
-       'begin': -1,
-       'stop': 1,
-       'end' : 1
+    'start': -1,
+    'begin': -1,
+    'stop': 1,
+    'end' : 1
 }
 
 def musicxml_spanner_to_lily_event (mxl_event):
-       ev = None
-       
-       name = mxl_event.get_name()
-       try:
-               func = spanner_event_dict[name]
-               ev = func()
-       except KeyError:
-               print 'unknown span event ', mxl_event
-
-       try:
-               key = mxl_event.get_type ()
-               ev.span_direction = spanner_type_dict[key]
-       except KeyError:
-               print 'unknown span type', key, 'for', name
-
-       return ev
+    ev = None
+    
+    name = mxl_event.get_name()
+    try:
+        func = spanner_event_dict[name]
+        ev = func()
+    except KeyError:
+        print 'unknown span event ', mxl_event
+
+    try:
+        key = mxl_event.get_type ()
+        ev.span_direction = spanner_type_dict[key]
+    except KeyError:
+        print 'unknown span type', key, 'for', name
+
+    return ev
 
 def musicxml_note_to_lily_main_event (n):
-       pitch  = None
-       duration = None
-               
-       mxl_pitch = n.get_maybe_exist_typed_child (musicxml.Pitch)
-       event = None
-       if mxl_pitch:
-               pitch = musicxml_pitch_to_lily (mxl_pitch)
-               event = musicexp.NoteEvent()
-               event.pitch = pitch
-
-               acc = n.get_maybe_exist_named_child ('accidental')
-               if acc:
-                       # let's not force accs everywhere. 
-                       event.cautionary = acc.editorial
-               
-       elif n.get_maybe_exist_typed_child (musicxml.Rest):
-               event = musicexp.RestEvent()
-
-       event.duration = musicxml_duration_to_lily (n)
-       return event
+    pitch  = None
+    duration = None
+        
+    mxl_pitch = n.get_maybe_exist_typed_child (musicxml.Pitch)
+    event = None
+    if mxl_pitch:
+        pitch = musicxml_pitch_to_lily (mxl_pitch)
+        event = musicexp.NoteEvent()
+        event.pitch = pitch
+
+        acc = n.get_maybe_exist_named_child ('accidental')
+        if acc:
+            # let's not force accs everywhere. 
+            event.cautionary = acc.editorial
+        
+    elif n.get_maybe_exist_typed_child (musicxml.Rest):
+        event = musicexp.RestEvent()
+
+    event.duration = musicxml_duration_to_lily (n)
+    return event
 
 def musicxml_voice_to_lily_voice (voice):
-       ly_voice = []
-       ly_now = Rational (0)
-       pending_skip = Rational (0) 
-
-       tuplet_events = []
-
-       for n in voice._elements:
-               if n.get_name () == 'forward':
-                       continue
-               
-               if isinstance (n, musicxml.Attributes):
-                       ly_now += pending_skip
-                       pending_skip = Rational (0)
-                       
-                       ly_voice.extend (musicxml_attributes_to_lily (n))
-                       continue
-               
-               if not n.__class__.__name__ == 'Note':
-                       print 'not a Note or Attributes?', n
-                       continue
-
-               if n.is_first () and ly_voice:
-                       ly_voice[-1].comment += '\n'
-               
-
-               main_event = musicxml_note_to_lily_main_event (n)
-
-               ev_chord = None
-               if None ==  n.get_maybe_exist_typed_child (musicxml.Chord):
-                       ly_now += pending_skip
-                       pending_skip = main_event.get_length ()
-
-                       if ly_now <> n._when:
-                               diff = n._when - ly_now
-
-                               if diff < Rational (0):
-                                       print 'huh: negative skip', n._when, ly_now, n._duration
-                                       diff = Rational (1,314159265)
-
-                               ly_voice.append (create_skip_music (diff))
-                               ly_now = n._when
-                               
-                       ly_voice.append (musicexp.EventChord())
-               else:
-                       pass
-               
-               ev_chord = ly_voice[-1]
-               ev_chord.append (main_event)
-               
-               notations = n.get_maybe_exist_typed_child (musicxml.Notations)
-               tuplet_event = None
-               span_events = []
-               if notations:
-                       if notations.get_tuplet():
-                               tuplet_event = notations.get_tuplet()
-                               mod = n.get_maybe_exist_typed_child (musicxml.Time_modification)
-                               frac = (1,1)
-                               if mod:
-                                       frac = mod.get_fraction ()
-                               
-                               tuplet_events.append ((ev_chord, tuplet_event, frac))
-
-                       slurs = [s for s in notations.get_named_children ('slur')
-                                if s.get_type () in ('start','stop')]
-                       if slurs:
-                               if len (slurs) > 1:
-                                       print 'more than 1 slur?'
-
-                               lily_ev = musicxml_spanner_to_lily_event (slurs[0])
-                               ev_chord.append (lily_ev)
-
-                       mxl_tie = notations.get_tie ()
-                       if mxl_tie and mxl_tie.type == 'start':
-                               ev_chord.append (musicexp.TieEvent ())
-
-               mxl_beams = [b for b in n.get_named_children ('beam')
-                            if b.get_type () in ('begin', 'end')] 
-               if mxl_beams:
-                       beam_ev = musicxml_spanner_to_lily_event (mxl_beams[0])
-                       if beam_ev:
-                               ev_chord.append (beam_ev)
-                       
-               if tuplet_event:
-                       mod = n.get_maybe_exist_typed_child (musicxml.Time_modification)
-                       frac = (1,1)
-                       if mod:
-                               frac = mod.get_fraction ()
-                               
-                       tuplet_events.append ((ev_chord, tuplet_event, frac))
-
-       ly_voice = group_tuplets (ly_voice, tuplet_events)
-
-       seq_music = musicexp.SequentialMusic()
-       
-       seq_music.elements = ly_voice
-       return seq_music
+    ly_voice = []
+    ly_now = Rational (0)
+    pending_skip = Rational (0) 
+
+    tuplet_events = []
+
+    for n in voice._elements:
+        if n.get_name () == 'forward':
+            continue
+        
+        if isinstance (n, musicxml.Attributes):
+            ly_now += pending_skip
+            pending_skip = Rational (0)
+            
+            ly_voice.extend (musicxml_attributes_to_lily (n))
+            continue
+        
+        if not n.__class__.__name__ == 'Note':
+            print 'not a Note or Attributes?', n
+            continue
+
+        if n.is_first () and ly_voice:
+            ly_voice[-1].comment += '\n'
+        
+
+        main_event = musicxml_note_to_lily_main_event (n)
+
+        ev_chord = None
+        if None ==  n.get_maybe_exist_typed_child (musicxml.Chord):
+            ly_now += pending_skip
+            pending_skip = main_event.get_length ()
+
+            if ly_now <> n._when:
+                diff = n._when - ly_now
+
+                if diff < Rational (0):
+                    print 'huh: negative skip', n._when, ly_now, n._duration
+                    diff = Rational (1,314159265)
+
+                ly_voice.append (create_skip_music (diff))
+                ly_now = n._when
+                
+            ly_voice.append (musicexp.EventChord())
+        else:
+            pass
+        
+        ev_chord = ly_voice[-1]
+        ev_chord.append (main_event)
+        
+        notations = n.get_maybe_exist_typed_child (musicxml.Notations)
+        tuplet_event = None
+        span_events = []
+        if notations:
+            if notations.get_tuplet():
+                tuplet_event = notations.get_tuplet()
+                mod = n.get_maybe_exist_typed_child (musicxml.Time_modification)
+                frac = (1,1)
+                if mod:
+                    frac = mod.get_fraction ()
+                
+                tuplet_events.append ((ev_chord, tuplet_event, frac))
+
+            slurs = [s for s in notations.get_named_children ('slur')
+                if s.get_type () in ('start','stop')]
+            if slurs:
+                if len (slurs) > 1:
+                    print 'more than 1 slur?'
+
+                lily_ev = musicxml_spanner_to_lily_event (slurs[0])
+                ev_chord.append (lily_ev)
+
+            mxl_tie = notations.get_tie ()
+            if mxl_tie and mxl_tie.type == 'start':
+                ev_chord.append (musicexp.TieEvent ())
+
+        mxl_beams = [b for b in n.get_named_children ('beam')
+              if b.get_type () in ('begin', 'end')] 
+        if mxl_beams:
+            beam_ev = musicxml_spanner_to_lily_event (mxl_beams[0])
+            if beam_ev:
+                ev_chord.append (beam_ev)
+            
+        if tuplet_event:
+            mod = n.get_maybe_exist_typed_child (musicxml.Time_modification)
+            frac = (1,1)
+            if mod:
+                frac = mod.get_fraction ()
+                
+            tuplet_events.append ((ev_chord, tuplet_event, frac))
+
+    ly_voice = group_tuplets (ly_voice, tuplet_events)
+
+    seq_music = musicexp.SequentialMusic()
+    
+    seq_music.elements = ly_voice
+    return seq_music
 
 
 def musicxml_id_to_lily (id):
-       digits = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
-                 'nine', 'ten']
-       
-       for dig in digits:
-               d = digits.index (dig) + 1
-               dig = dig[0].upper() + dig[1:]
-               id = re.sub ('%d' % d, dig, id)
+    digits = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
+         'nine', 'ten']
+    
+    for dig in digits:
+        d = digits.index (dig) + 1
+        dig = dig[0].upper() + dig[1:]
+        id = re.sub ('%d' % d, dig, id)
 
-       id = re.sub  ('[^a-zA-Z]', 'X', id)
-       return id
+    id = re.sub  ('[^a-zA-Z]', 'X', id)
+    return id
 
 
 def musicxml_pitch_to_lily (mxl_pitch):
-       p = musicexp.Pitch()
-       p.alteration = mxl_pitch.get_alteration ()
-       p.step = (ord (mxl_pitch.get_step ()) - ord ('A') + 7 - 2) % 7
-       p.octave = mxl_pitch.get_octave () - 4
-       return p
+    p = musicexp.Pitch()
+    p.alteration = mxl_pitch.get_alteration ()
+    p.step = (ord (mxl_pitch.get_step ()) - ord ('A') + 7 - 2) % 7
+    p.octave = mxl_pitch.get_octave () - 4
+    return p
 
 
 
 def voices_in_part (part):
-       """Return a Name -> Voice dictionary for PART"""
-       part.interpret ()
-       part.extract_voices ()          
-       voice_dict = part.get_voices ()
+    """Return a Name -> Voice dictionary for PART"""
+    part.interpret ()
+    part.extract_voices ()                
+    voice_dict = part.get_voices ()
 
-       return voice_dict
+    return voice_dict
 
 def voices_in_part_in_parts (parts):
-       """return a Part -> Name -> Voice dictionary"""
-       return dict([(p, voices_in_part (p)) for p in parts])
+    """return a Part -> Name -> Voice dictionary"""
+    return dict([(p, voices_in_part (p)) for p in parts])
 
 
 def get_all_voices (parts):
-       all_voices = voices_in_part_in_parts (parts)
+    all_voices = voices_in_part_in_parts (parts)
 
-       all_ly_voices = {}
-       for p, name_voice in all_voices.items ():
+    all_ly_voices = {}
+    for p, name_voice in all_voices.items ():
 
-               part_ly_voices = {}
-               for n, v in name_voice.items ():
-                       progress ("Converting to LilyPond expressions...")
-                       part_ly_voices[n] = (musicxml_voice_to_lily_voice (v), v)
+        part_ly_voices = {}
+        for n, v in name_voice.items ():
+            progress ("Converting to LilyPond expressions...")
+            part_ly_voices[n] = (musicxml_voice_to_lily_voice (v), v)
 
-               all_ly_voices[p] = part_ly_voices
-               
-       return all_ly_voices
+        all_ly_voices[p] = part_ly_voices
+        
+    return all_ly_voices
 
 
 def option_parser ():
-       p = ly.get_option_parser(usage='musicxml2ly FILE.xml',
-                                 version = """%prog (LilyPond) @TOPLEVEL_VERSION@
+    p = ly.get_option_parser(usage='musicxml2ly FILE.xml',
+                 version = """%prog (LilyPond) @TOPLEVEL_VERSION@
 
 This program 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
@@ -390,145 +390,145 @@ under certain conditions.  Invoke as `lilypond --warranty' for more
 information.
 
 Copyright (c) 2005--2006 by
 Han-Wen Nienhuys <hanwen@xs4all.nl> and
 Jan Nieuwenhuizen <janneke@gnu.org>
+ Han-Wen Nienhuys <hanwen@xs4all.nl> and
+ Jan Nieuwenhuizen <janneke@gnu.org>
 """,
 
-                                 description  =
-                                 """Convert MusicXML file to LilyPond input.
+                 description  =
+                 """Convert MusicXML file to LilyPond input.
 """
-                                 )
-       p.add_option ('-v', '--verbose',
-                     action = "store_true",
-                     dest = 'verbose',
-                     help = 'be verbose')
-       p.add_option ('-o', '--output',
-                     metavar = 'FILE',
-                     action = "store",
-                     default = None,
-                     type = 'string',
-                     dest = 'output',
-                     help = 'set output file')
-
-       p.add_option_group  ('', description = '''Report bugs via http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs
+                 )
+    p.add_option ('-v', '--verbose',
+           action = "store_true",
+           dest = 'verbose',
+           help = 'be verbose')
+    p.add_option ('-o', '--output',
+           metavar = 'FILE',
+           action = "store",
+           default = None,
+           type = 'string',
+           dest = 'output',
+           help = 'set output file')
+
+    p.add_option_group  ('', description = '''Report bugs via http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs
 ''')
-       return p
+    return p
 
 def music_xml_voice_name_to_lily_name (part, name):
-       str = "Part%sVoice%s" % (part.id, name)
-       return musicxml_id_to_lily (str) 
+    str = "Part%sVoice%s" % (part.id, name)
+    return musicxml_id_to_lily (str) 
 
 def print_voice_definitions (printer, voices):
-       for (part, nv_dict) in voices.items():
-               for (name, (voice, mxlvoice)) in nv_dict.items ():
-                       k = music_xml_voice_name_to_lily_name (part, name)
-                       printer.dump ('%s = ' % k)
-                       voice.print_ly (printer)
-                       printer.newline()
+    for (part, nv_dict) in voices.items():
+        for (name, (voice, mxlvoice)) in nv_dict.items ():
+            k = music_xml_voice_name_to_lily_name (part, name)
+            printer.dump ('%s = ' % k)
+            voice.print_ly (printer)
+            printer.newline()
 def uniq_list (l):
-       return dict ([(elt,1) for elt in l]).keys ()
-       
+    return dict ([(elt,1) for elt in l]).keys ()
+    
 def print_score_setup (printer, part_list, voices):
-       part_dict = dict ([(p.id, p) for p in voices.keys ()]) 
-
-       printer ('<<')
-       printer.newline ()
-       for part_definition in part_list:
-               part_name = part_definition.id
-               try:
-                       part = part_dict[part_name]
-               except KeyError:
-                       print 'unknown part in part-list:', part_name
-                       continue
-
-               nv_dict = voices[part]
-               staves = reduce (lambda x,y: x+ y,
-                                [mxlvoice._staves.keys ()
-                                 for (v, mxlvoice) in nv_dict.values ()],
-                                [])
-
-               if len (staves) > 1:
-                       staves = uniq_list (staves)
-                       staves.sort ()
-                       printer ('\\context PianoStaff << ')
-                       printer.newline ()
-                       
-                       for s in staves:
-                               staff_voices = [music_xml_voice_name_to_lily_name (part, voice_name)
-                                               for (voice_name, (v, mxlvoice)) in nv_dict.items ()
-                                               if mxlvoice._start_staff == s]
-                               
-                               printer ('\\context Staff = "%s" << ' % s)
-                               printer.newline ()
-                               for v in staff_voices:
-                                       printer ('\\context Voice = "%s"  \\%s' % (v,v))
-                                       printer.newline ()
-                               printer ('>>')
-                               printer.newline ()
-                               
-                       printer ('>>')
-                       printer.newline ()
-                       
-               else:
-                       printer ('\\new Staff <<')
-                       printer.newline ()
-                       for (n,v) in nv_dict.items ():
-
-                               n = music_xml_voice_name_to_lily_name (part, n) 
-                               printer ('\\context Voice = "%s"  \\%s' % (n,n))
-                       printer ('>>')
-                       printer.newline ()
-                       
-
-       printer ('>>')
-       printer.newline ()
-
-                               
+    part_dict = dict ([(p.id, p) for p in voices.keys ()]) 
+
+    printer ('<<')
+    printer.newline ()
+    for part_definition in part_list:
+        part_name = part_definition.id
+        try:
+            part = part_dict[part_name]
+        except KeyError:
+            print 'unknown part in part-list:', part_name
+            continue
+
+        nv_dict = voices[part]
+        staves = reduce (lambda x,y: x+ y,
+                [mxlvoice._staves.keys ()
+                 for (v, mxlvoice) in nv_dict.values ()],
+                [])
+
+        if len (staves) > 1:
+            staves = uniq_list (staves)
+            staves.sort ()
+            printer ('\\context PianoStaff << ')
+            printer.newline ()
+            
+            for s in staves:
+                staff_voices = [music_xml_voice_name_to_lily_name (part, voice_name)
+                        for (voice_name, (v, mxlvoice)) in nv_dict.items ()
+                        if mxlvoice._start_staff == s]
+                
+                printer ('\\context Staff = "%s" << ' % s)
+                printer.newline ()
+                for v in staff_voices:
+                    printer ('\\context Voice = "%s"  \\%s' % (v,v))
+                    printer.newline ()
+                printer ('>>')
+                printer.newline ()
+                
+            printer ('>>')
+            printer.newline ()
+            
+        else:
+            printer ('\\new Staff <<')
+            printer.newline ()
+            for (n,v) in nv_dict.items ():
+
+                n = music_xml_voice_name_to_lily_name (part, n) 
+                printer ('\\context Voice = "%s"  \\%s' % (n,n))
+            printer ('>>')
+            printer.newline ()
+            
+
+    printer ('>>')
+    printer.newline ()
+
+                
 
 def print_ly_preamble (printer, filename):
-       printer.dump_version ()
-       printer.print_verbatim ('%% converted from %s\n' % filename)
+    printer.dump_version ()
+    printer.print_verbatim ('%% converted from %s\n' % filename)
 
 def convert (filename, output_name):
-       printer = musicexp.Output_printer()
-       progress ("Reading MusicXML...")
-       
-       tree = musicxml.read_musicxml (filename)
-       parts = tree.get_typed_children (musicxml.Part)
-       voices = get_all_voices (parts)
-
-       part_list = []
-       if tree.get_maybe_exist_typed_child (musicxml.Part_list):
-               pl = tree.get_maybe_exist_typed_child (musicxml.Part_list)
-               part_list = pl.get_named_children ("score-part")
-               
-       if not output_name:
-               output_name = os.path.basename (filename)
-               output_name = os.path.splitext (output_name)[0] + '.ly'
-
-               
-       if output_name:
-               progress ("Output to `%s'" % output_name)
-               printer.set_file (open (output_name, 'w'))
-       
-       progress ("Printing as .ly...")
-
-       print_ly_preamble (printer, filename)
-       print_voice_definitions (printer,  voices)
-       print_score_setup (printer, part_list, voices)
-       printer.newline ()
-       return voices
+    printer = musicexp.Output_printer()
+    progress ("Reading MusicXML...")
+    
+    tree = musicxml.read_musicxml (filename)
+    parts = tree.get_typed_children (musicxml.Part)
+    voices = get_all_voices (parts)
+
+    part_list = []
+    if tree.get_maybe_exist_typed_child (musicxml.Part_list):
+        pl = tree.get_maybe_exist_typed_child (musicxml.Part_list)
+        part_list = pl.get_named_children ("score-part")
+        
+    if not output_name:
+        output_name = os.path.basename (filename)
+        output_name = os.path.splitext (output_name)[0] + '.ly'
+
+        
+    if output_name:
+        progress ("Output to `%s'" % output_name)
+        printer.set_file (open (output_name, 'w'))
+    
+    progress ("Printing as .ly...")
+
+    print_ly_preamble (printer, filename)
+    print_voice_definitions (printer,  voices)
+    print_score_setup (printer, part_list, voices)
+    printer.newline ()
+    return voices
 
 
 def main ():
-       opt_parser = option_parser()
+    opt_parser = option_parser()
 
-       (options, args) = opt_parser.parse_args ()
-       if not args:
-               opt_parser.print_usage()
-               sys.exit (2)
+    (options, args) = opt_parser.parse_args ()
+    if not args:
+        opt_parser.print_usage()
+        sys.exit (2)
 
-       voices = convert (args[0], options.output)
+    voices = convert (args[0], options.output)
 
 if __name__ == '__main__':
-       main()
+    main()