+ 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
+
+def track_first_item (track):
+ 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)
+
+
+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)
+
+
+ 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)
+
+ i += 1
+ s = s + ' >>\n}\n'
+
+ progress (_ ("%s output to `%s'...") % ('LY', out_file))
+
+ if out_file == '-':
+ handle = sys.stdout
+ else:
+ handle = open (out_file, 'w')
+
+ handle.write (s)
+ handle.close ()
+
+
+def get_option_parser ():
+ p = ly.get_option_parser (usage=_ ("%s [OPTION]... FILE") % 'midi2ly',
+ description=_ ("Convert %s to LilyPond input.") % 'MIDI',
+ add_help_option=False)
+
+ 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("-h", "--help",
+ action="help",
+ help=_ ("show this help and exit"))
+ 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.version = "midi2ly (LilyPond) @TOPLEVEL_VERSION@"
+ p.add_option("--version",
+ action="version",
+ help=_ ("show version number and exit"))
+ p.add_option ('-w', '--warranty', help=_ ("show warranty and copyright"),
+ action='store_true',
+ ),
+ p.add_option ('-x', '--text-lyrics', help=_ ("treat every text as a lyric"),
+ action='store_true')
+
+ p.add_option_group (ly.display_encode (_ ("Examples")),
+ 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 (ly.display_encode (_ ('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 ()
+ ly.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, (options.key + ':0').split (':'))[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)
+if __name__ == '__main__':
+ main()