#   Copyright (C) 2002-2003 Yannick Gingras <ygingras@ygingras.net>
#   Copyright (C) 2002-2003 Vincent Barbin <vbarbin@openbeatbox.org>

#   This file is part of Open Beat Box.

#   Open Beat Box is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.

#   Open Beat Box is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.

#   You should have received a copy of the GNU General Public License
#   along with Open Beat Box; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


from tempfile import mktemp
import tempfile
from os import popen3, access, R_OK,remove 
from wave import open
from OBBFuncts import *

class OBBCSoundTorturer:
    def __init__(self, freq=44100, ksmps=100, filePrefix=mktemp()):
        self.fileName = filePrefix
        self.renderFreq = freq
        self.ksmps = ksmps
        
    def createOrchestraFile(self, songDoc):     
        inputText = "; Orchestra file"
        inputText += "\n    sr=%d" % self.renderFreq
        inputText += "\n    kr=%d" % (self.renderFreq/self.ksmps)
        inputText += "\n    ksmps=%d" % self.ksmps
        inputText += "\n    nchnls=2\n"  #stereo
        inputText += "\n    ga1  init 0\n"

        for i in songDoc.songOrchestra.get():
            inputText += "\n    instr %d" % (i+1)
            inputText += "\n        asource1, asource2 diskin     "
            inputText += "\"" \
            + formatPath(songDoc.songOrchestra.get()[i].getPlayFilePath(), 1) + "\", 1, 0, 1"
            inputText += "\n                outs         asource1, asource2"
            inputText += "\n                endin\n"

        file(self.fileName + ".orc", 'w+').write(inputText)
        debug(inputText)

    def createScoreFile(self, songDoc, start, length):
        returnValue = 0
        inputText = "; Score file\n;%s%8s%11s" % ( "p1", "p2", "p3" )
        songDoc.songScore.printScore()
        instrs = songDoc.songScore.Get()
        beat = 60.0/songDoc.getTempo()
        formatstring = "\n%s %10.3f %10.3f"
        for i in instrs:
            for j in instrs[i]:
                if start+length > j >= start:
                    returnValue = 1
                    inputText += formatstring % \
                        (" i%d" %(i + 1), \
                        (j - start) * beat, \
                        songDoc.getInstrument(i).duration)

        file(self.fileName + ".sco", 'w+').write(inputText + "\n")
        debug(inputText)
        return returnValue

    def createWaveFile(self, orchestraFile = None, scoreFile = None):
        if orchestraFile == None:
            orchestraFile = self.fileName
        if scoreFile == None:
            scoreFile = self.fileName
        # TODO : plug a big random value in sufix
        targetWave = tempfile.mktemp() + ".wav"

        cmd = "csound -o \"%s\" -W \"%s.orc\" \"%s.sco\""# 2>&1"
        cmd = cmd  % ( targetWave, orchestraFile, scoreFile )
        debug(cmd)
        pipes = popen3(cmd)
        output = pipes[1].read()
        erroutput = pipes[2].read()
        pipes[0].close()
        stat1 = pipes[1].close()
        stat2 = pipes[2].close()
        if (stat1 or stat2):
            raise Exception("csound died screaming : \n%s\n%s" % (output, erroutput))
        
        self.purgeFiles(orchestraFile, scoreFile)
        if access(targetWave, R_OK):
            return targetWave


    def createModifiedSampleFile(self, instrument):
        orchestraFile = tempfile.mktemp()
        wavefile = open(instrument.getFilePath(), 'r')
        inputText = "; Orchestra file"
        inputText += "\n    sr=%d" % self.renderFreq
        inputText += "\n    kr=%d" % (self.renderFreq/self.ksmps)
        inputText += "\n    ksmps=%d" % self.ksmps
        inputText += "\n    nchnls=2\n"
        inputText += "\n    ga1  init 0"
        inputText += "\n\n    instr 1"
        inputText += "\n        asig    soundin     "
        inputText += "\"" + formatPath(instrument.getFilePath(), 1) + "\""
        inputText += "\n        aout  = asig"
        inputText += "\n        a1      alpass aout, 100, %3.1f" \
            % (100.1-instrument.leftVolume)
        inputText += "\n        a2      alpass aout, 100, %3.1f" \
            % (100.1-instrument.rightVolume)
        inputText += "\n                outs         a1, a2"
        inputText += "\n                endin\n"
        file(orchestraFile + ".orc", 'w+').write(inputText)
        if not access(orchestraFile + ".orc" , R_OK):
            raise Exception("file %s was not created." % (orchestraFile))

        scoreFile = tempfile.mktemp()
        inputText = "; Score file\n;p1      p2         p3"
        duration = (1.0*wavefile.getnframes())\
            /(1.0*wavefile.getframerate())
        wavefile.close()
        inputText += "\n i1      0.000%10.3f" %( duration )
        file(scoreFile + ".sco", 'w+').write(inputText + "\n")
        if not access(scoreFile + ".sco", R_OK):
            raise Exception("file %s was not created." % (scoreFile))

        return self.createWaveFile(orchestraFile, scoreFile)

    def purgeFiles(self, orcFilePath = None, scoFilePath = None):
        if access(orcFilePath + ".orc", R_OK):
            remove(orcFilePath + ".orc")

        if access(scoFilePath + ".sco", R_OK):
            remove(scoFilePath + ".sco")
