#!python

##############################################################################
# mid2syx.py 0.1 - extracts sysex information from midi file
# (C) 2000 Michael 'Mickey' Lauer - http://www.Vanille.de
##############################################################################

import sys

class Chunk:

        def __init__( self, file = sys.stdin ):
                self.type = file.read( 4 )

                tlen = file.read( 4 )

                if len(tlen) < 4: return
                
                self.len = ( ord( tlen[0] ) << 24 ) + \
                           ( ord( tlen[1] ) << 16 ) + \
                           ( ord( tlen[2] ) << 8 ) + \
                           ord( tlen[3] )

                self.data = file.read( self.len )

        def isValid( self ): return self.type != "" and self.len != 0

        def __len__( self ): return self.len

        def dat( self, pos ): return ord( self.data[pos] )        
        
        

def getVlen( i, chunk ):

        vlen = 0        

        while chunk.dat( i ) > 127:
                vlen = vlen << 8
                vlen = vlen + chunk.dat( i ) - 128
                i = i + 1

        vlen = vlen << 7
        vlen = vlen + chunk.dat( i )
        i = i + 1

        return vlen, i        


def extract( source, destprefix ):
        
        file = open( source, "rb" )

        print "Scanning file..."

        header = Chunk( file )
        if header.type != "MThd":
                print "Error: No SMF Header found. Exiting."
                return#sys.exit()

        tracknum = 0                

        while 1:
                chunk = Chunk( file )
                if not chunk.isValid():
                        print "No more chunks found. Exiting."
                        return#sys.exit()

                print "\nFound Chunk: '%s'" % ( chunk.type ),
                
                if chunk.type == "MTrk":
                        print "is a track! Extracting...",
                        tracknum = tracknum + 1
                        dest = open( destprefix + str( tracknum ) + ".syx", "w" )

                        i = 0
                        while i < len( chunk ):

                                #while chunk.dat( i ) > 127: i = i + 1
                                #i = i + 1

                                type = chunk.dat( i )
                                if (type == 0xF0) or (type == 0xF7):
                                        if type == 0xF0:
                                                print "F0",
                                                dest.write( chr(type) )
                                        if type == 0xF7:
                                                print "F7",

                                        i = i + 1

                                        vlen, i = getVlen( i, chunk )
                                        evstop = i + vlen

                                        #print " - %d" % vlen

                                        while i < evstop :
                                                #print "%x" % chunk.dat(i),
                                                dest.write( chr( chunk.dat( i ) ) )                                               
                                                i = i + 1

                                        if chunk.dat( i-1 ) != 0xF7:
                                                #print chunk.dat( i-1 )
                                                print "w",

                                elif type > 0x80:
                                        print ".",
                                        i = i + 1
                                else:
                                        print ".",
                                        i = i + 1
                

if __name__ == "__main__":

        import sys
        if len( sys.argv ) != 3:
                print """
Usage: python mid2syx.py source destprefix

Extracts sysex messages from a standard midi file.
(C) 2000 Michael 'Mickey' Lauer - www.Vanille.de"""
                sys.exit(-1)

        extract( sys.argv[1], sys.argv[2] )
        print"\nDone.\n"