'''
Created on 2 oct. 2009

@author: samsam
'''
import pickle
import os.path
try :
    from MidiToSong import MidiToSong
    from mxmMidi.MidiInFile import MidiInFile
except ImportError :
    # loadSongFromMidi KO dans ce cas.
    pass

class Song:
    '''
    classdocs
    '''


    def __init__(self,scale,notesInExtendedScale=[], requiresExtendedScale = False,midiNoteNumbers = None, alterationIndexes = None, alterations = None, modulationIndexes = None, modulationScales = None, lyrics =None, noteLengths = None, quarterNoteLength = 750, name = "unknownSong"):
        '''
        Constructor
        '''
        self.name = name
        self.scale = scale
        self.notes = notesInExtendedScale
        self.lyrics = lyrics
        self.noteLengths = noteLengths
        self.quarterNoteLength = quarterNoteLength
        if midiNoteNumbers == None :
            self.midiNoteNumbers = [self.scale[note] for note in self.notes]
        else:
            self.midiNoteNumbers = midiNoteNumbers
            if self.notes == [] :
                self.assignNotesFromMidiNoteNumbers()
        self.requiresExtendedScale = requiresExtendedScale
        if alterationIndexes != None and alterations != None :
            self.alterNotes(alterationIndexes, alterations)
        if modulationIndexes != None and modulationScales != None :
            self.modulate(modulationIndexes, modulationScales)
        
    def getSongIterator(self):
        while True:
            for i in range(len(self.notes)):
                if self.lyrics :
                    lyrics = self.lyrics[i]
                else :
                    lyrics = None
                    
                if self.noteLengths :
                    noteLength = self.noteLengths[i]
                else :
                    noteLength = 1
                    
                yield [self.notes[i],self.midiNoteNumbers[i],lyrics,noteLength]
                
    def alterNotes(self,noteIndexes,alterations):
        for i in range(len(noteIndexes)) :
            self.midiNoteNumbers[noteIndexes[i]] = self.midiNoteNumbers[noteIndexes[i]] + alterations[i]
    
    def modulate(self,modulationIndexes,scales):
        for i in range(len(scales)):
            if i < len(scales)-1 :
                bound = modulationIndexes[i+1]
            else :
                bound = len(self.notes)
            for j in range(modulationIndexes[i],bound):
                self.midiNoteNumbers[j]=scales[i][self.notes[j]]
                
    def assignNotesFromMidiNoteNumbers(self):
        for i in range(len(self.midiNoteNumbers)):
            noteInExtendedScale = 0
            while self.midiNoteNumbers[i] > self.scale[noteInExtendedScale] and noteInExtendedScale < len(self.scale)-1:
                noteInExtendedScale += 1
            if self.midiNoteNumbers[i]<self.scale[noteInExtendedScale]:
                noteInExtendedScale -= 1
            self.notes.append(noteInExtendedScale)
            
    def save(self,path = None):
        if path == None :
            path = "".join(os.path.join("smwis",self.name),".swmi")      
        f = file(path, 'w')
        pickler = pickle.Pickler(f)
        pickler.dump(self)        
        f.close()
            
def loadSongFromMidi(filePath,scale):
    # get data
    test_file = '../songs/midis/test.mid'
    f = open(test_file, 'rb')
    
    # do parsing
    mts = MidiToSong()
    midiIn = MidiInFile(mts, f)
    midiIn.read()
    f.close()
    
    s = Song(scale,midiNoteNumbers = mts.midiNoteNumbers,quarterNoteLength = mts.quarterNoteLength,noteLengths = mts.noteLengths)
    for nn in s.notes :
        if nn < 3 :
            s.requiresExtendedScale = True            
    return(s)                   

def loadSong(filePath):
    f = file(filePath, 'r')
    unpickler = pickle.Unpickler(f)
    s = unpickler.load()
    f.close()
    return(s)

if __name__ == '__main__':

    # get data
    test_file = '../songs/midis/boheme.mid'
    f = open(test_file, 'rb')
    
    # do parsing
    from mxmMidi.MidiInFile import MidiInFile
    mts = MidiToSong()
    midiIn = MidiInFile(mts, f)
    midiIn.read()
    f.close()
    
    majorScale = [55, 57, 59, 60, 62, 64, 65, 67, 69, 71, 72]
        
    s = Song(majorScale,requiresExtendedScale = True, midiNoteNumbers = mts.midiNoteNumbers,quarterNoteLength = mts.quarterNoteLength,noteLengths = mts.noteLengths)
    for i in range(len(s.midiNoteNumbers)):
        print "note number :" + str(s.midiNoteNumbers[i]) + ", assigned note :" + str(s.notes[i]) + ", duration :" + str(s.noteLengths[i])
    
    s.lyrics = ["je","vous","par-","-le","d'un","temps","que","les","moins","de","vingt","ans","ne","peu-","-vent","pas","con-","-nai-","-tre","Mont-","-martre","en","ce","temps","la","ac-","-cro-","-chait","ses","li-","-las","jus-","-que","sous","nos","fe-","-netres","et","si","l'hum-","-ble","gar-","-ni","qui","nous","ser-","-vait","de","nid","ne","pay-","-yait","pas","de","mi-","-ne","c'est","la","qu'on","s'est","con-","-nus","moi","qui","cri-","-ait","fa-","-mine","et","toi","qui","po-","-sait","nue","la","bo-","-he-","-me","la","bo-","-he-","-me","ca","vou-","-lait","dire","on","est","heu-","-reux","la","bo-","-he-","-me","la","bo-","-he-","-me","nous","ne","man-","-gions","qu'un","jour","sur","deux"]
    
    #s.lyrics = ["quand","nous","chan-","-te-","-rons","le","temps","des","ce-","-rises","et","gai","ros-","-si-","-gnol","et","mer-","-le","mo-","-queur","se-","-ront","tous","en","fe-","-e-","-te","les","bel-","-les","au-","-ront","la","fo-","-lie","en","te","te","et","les","a-","-mou-","-reux","du","so-","-leil","au","coeur","quand","vous","chan-","-te-","-rez","le","temps","des","ce-","-rises","sif-","-fle-","-ra","bien","mieux","le","mer-","-le","mo-","-queur"]    
    
    #s.lyrics=["il","pleut","il","pleut","ber-","-ge-","-re","ren-","-tre","tes","blancs","mou-","-tons","al-","-lons","a","ma","chau-","-mie-","-re","ber-","-ge-","-re","vite","al-","-lons","j'en-","-tends","sur","le","feu-","-illa-","-ge","l'eau","qui","tombe","a","grand","bruit","voi-","-ci","ve-","-nir","l'o-","-ra-","-a-","-ge","voi-","-ci","l'e-","-clair","qui","luit"]
    
    #s.lyrics = ["c'est","une","chan-","-son","qui","nous","res-","-sem-","-ble","toi","tu","m'ai-","-mais","et","je","t'ai-","-mais","nous","e-","-tions","tout","les","deux","en-","-sem-","-ble","toi","qui","m'ai-","-mais","moi","qui","t'ai-","-mais","mais","la","vie","se-","-pare","ceux","qui","s'aiment","tout","dou-","-ce-","-ment","sans","faire","de","bruit","et","la","mer","ef-","-fa-","-ce","sur","le","sa-","-ble","les","pas","des","a-","-mants","de-","-su-","-nis"]

    # s.lyrics = ["quand","il","me","prend","dans","ses","bras","qu'il","me","par-","-le","tout","bas","je","vois","la","vie","en","ro-","-se","il","me","dit","des","mots","d'a-","-mour","des","mots","de","tous","les","jours","et","ca","m'fait","quel-","-que","cho-","-se","il","est","en-","-tre","dans","mon","coeur","u-","-ne","part","de","bon-","-heur","dont","je","con-","-nais","la","cau-","-se","c'est","lmui","pour","moi","moi","pour","lui","dans","la","vie","il","m'a","pro-","-mis","m'a","ju-","-re","pour","la","vie","et","des","que","je","l'a-","-per-","-cois","a-","-lors","je","sens","en","moi","mon","coeur","qui","bat"]

    s.save("smwis/boheme.smwi")    