]> git.donarmstrong.com Git - lilypond.git/blobdiff - scripts/midi2ly.py
Midi2ly: fix --warranty. Thank Martin Tarenskeen.
[lilypond.git] / scripts / midi2ly.py
index af47460a96471092e5d83024374e565976806163..6aa331ab8e2e434b222b8908906af9a90e0ed889 100644 (file)
@@ -56,7 +56,7 @@ global_options = None
 clocks_per_1 = 1536
 clocks_per_4 = 0
 
-time = 0
+time = None
 reference_note = 0
 start_quant_clocks = 0
 
@@ -103,7 +103,7 @@ def error (s):
     raise Exception (_ ("Exiting... "))
 
 def debug (s):
-    if 0:
+    if global_options.debug:
         progress ("debug: " + s)
 
 def system (cmd, ignore_error = 0):
@@ -181,7 +181,11 @@ class Note:
         n = self.names[(self.pitch) % 12]
         a = self.alterations[(self.pitch) % 12]
 
-        if a and global_options.key.flats:
+        key = global_options.key
+        if not key:
+            key = Key (0, 0, 0)
+
+        if a and key.flats:
             a = - self.alterations[(self.pitch) % 12]
             n = (n - a) % 7
 
@@ -213,7 +217,6 @@ class Note:
 
         o = self.pitch / 12 - 4
 
-        key = global_options.key
         if key.minor:
             # as -> gis
             if (key.sharps == 0 and key.flats == 0
@@ -405,7 +408,9 @@ class Text:
                 or d.compare (reference_note.duration)):
                 s = s + Duration (self.clocks).dump ()
             s = s + ' '
-        elif self.text and self.type == midi.SEQUENCE_TRACK_NAME:
+        elif (self.text
+              and self.type == midi.SEQUENCE_TRACK_NAME
+              and not self.text == 'control track'):
             text = self.text.replace ('(MIDI)', '').strip ()
             if text:
                 s = '\n  \\set Staff.instrumentName = "%(text)s"\n  ' % locals ()
@@ -432,12 +437,13 @@ def split_track (track):
         else:
             chs[0].append (e)
 
-    for i in range (16):
-        if chs[i] == []:
-            del chs[i]
-
     threads = []
+    i = 0
     for v in chs.values ():
+        i += 1
+        if not v:
+            continue
+        debug ('channel: %d\n' % i)
         events = events_on_channel (v)
         t = unthread_notes (events)
         if len (t):
@@ -536,6 +542,9 @@ def events_on_channel (channel):
                     flats = 256 - alterations
 
                 k = Key (sharps, flats, minor)
+                if not t and global_options.key:
+                    # At t == 0, a set --key overrides us
+                    k = global_options.key
                 events.append ((t, k))
 
                 # ugh, must set key while parsing
@@ -665,8 +674,6 @@ def dump_bar_line (last_bar_t, t, bar_count):
 def dump_voice (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)
@@ -802,6 +809,8 @@ def dump_track (track, n):
                 skip = '\\skip '
                 s += '%(voice_id)s = ' % locals ()
             s += '{\n'
+            if not n and not v and global_options.key:
+                s += global_options.key.dump ()
             if average_pitch[v+1] and voices > 1:
                 s += '  \\voice' + get_voice_layout (average_pitch[1:])[v] + '\n'
             s += '  ' + dump_voice (voice, skip)
@@ -888,6 +897,7 @@ def convert_midi (in_file, out_file):
     global start_quant_clocks
     global duration_quant_clocks
     global allowed_tuplet_clocks
+    global time
 
     str = open (in_file, 'rb').read ()
     clocks_max = bar_max * clocks_per_1 * 2
@@ -895,6 +905,7 @@ def convert_midi (in_file, out_file):
 
     clocks_per_1 = midi_dump[0][1]
     clocks_per_4 = clocks_per_1 / 4
+    time = Time (4, 4)
 
     if global_options.start_quant:
         start_quant_clocks = clocks_per_1 / global_options.start_quant
@@ -911,16 +922,15 @@ def convert_midi (in_file, out_file):
 
     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.38"\n\n'
-    for i in range (len (tracks)):
-        s = s + dump_track (tracks[i], i)
+    s = tag
+    s += r'''
+\version "2.7.38"
+'''
 
     s += r'''
 \layout {
@@ -932,18 +942,34 @@ def convert_midi (in_file, out_file):
 }
 '''
 
+    for i in global_options.include_header:
+        s += '\n%% included from %(i)s\n' % locals ()
+        s += open (i).read ()
+        if s[-1] != '\n':
+            s += '\n'
+        s += '% end\n'
+
+    for i in range (len (tracks)):
+        s = s + dump_track (tracks[i], i)
+
     s += '\n\\score {\n  <<\n'
 
     i = 0
     for t in tracks:
         track_name = get_track_name (i)
         item = track_first_item (t)
-
-        if item and item.__class__ == Note:
-            s += '    \\context Staff=%(track_name)s \\%(track_name)s\n' % locals ()
+        staff_name = track_name
+        context = None
+        if not i and not item and len (tracks) > 1:
+            # control track
+            staff_name = get_track_name (1)
+            context = 'Staff'
+        elif (item and item.__class__ == Note):
+            context = 'Staff'
         elif item and item.__class__ == Text:
-            s += '    \\context Lyrics=%(track_name)s \\%(track_name)s\n' % locals ()
-
+            context = 'Lyrics'
+        if context:
+            s += '    \\context %(context)s=%(staff_name)s \\%(track_name)s\n' % locals ()
         i += 1
     s = s + '  >>\n}\n'
 
@@ -969,15 +995,23 @@ def get_option_parser ():
     p.add_option ('-d', '--duration-quant',
            metavar=_ ('DUR'),
            help=_ ('quantise note durations on DUR'))
+    p.add_option ('-D', '--debug',
+                  action='store_true',
+                  help=_ ('debug printing'))
     p.add_option ('-e', '--explicit-durations',
            action='store_true',
            help=_ ('print explicit durations'))
     p.add_option('-h', '--help',
                  action='help',
                  help=_ ('show this help and exit'))
+    p.add_option('-i', '--include-header',
+                 help=_ ('prepend FILE to output'),
+                 action='append',
+                 default=[],
+                 metavar=_ ('FILE'))
     p.add_option('-k', '--key', help=_ ('set key: ALT=+sharps|-flats; MINOR=1'),
           metavar=_ ('ALT[:MINOR]'),
-          default='0'),
+          default=None),
     p.add_option ('-o', '--output', help=_ ('write output to FILE'),
            metavar=_ ('FILE'),
            action='store')
@@ -1021,6 +1055,10 @@ def do_options ():
     opt_parser = get_option_parser ()
     (options, args) = opt_parser.parse_args ()
 
+    if options.warranty:
+        warranty ()
+        sys.exit (0)
+
     if not args or args[0] == '-':
         opt_parser.print_help ()
         ly.stderr_write ('\n%s: %s %s\n' % (program_name, _ ('error: '),
@@ -1030,10 +1068,7 @@ def do_options ():
     if options.duration_quant:
         options.duration_quant = int (options.duration_quant)
 
-    if options.warranty:
-        warranty ()
-        sys.exit (0)
-    if 1:
+    if options.key:
         (alterations, minor) = map (int, (options.key + ':0').split (':'))[0:2]
         sharps = 0
         flats = 0
@@ -1041,7 +1076,6 @@ def do_options ():
             sharps = alterations
         else:
             flats = - alterations
-
         options.key = Key (sharps, flats, minor)
 
     if options.start_quant: