#! /usr/bin/env python
# encoding: utf-8

import Task, TaskGen, Utils, Logs, os, errno, shutil, re

# task function for task "dsp"
def dsp2cc(task):
    # use the specified processor to create the output file and copy
    # the output file into faust-generated in the source tree
    src = task.inputs[0].srcpath(task.env)
    o = task.outputs[0]
    dst = o.bldpath(task.env)
    cpy = os.path.join(o.parent.srcpath(task.env)+"-generated",o.file())
    lst = [task.proc,"-o",dst] + task.proc_args + [src]
    Logs.debug("runner: system command -> %s" % " ".join(lst))
    ret = Utils.exec_command(lst,shell=False)
    if ret != 0:
        return ret
    try:
        shutil.copy2(dst, cpy)
    except (OSError, IOError), e:
        Logs.error("runner: cannot copy file -> %s" % e)
        return e.errno
    return 0

class FaustScanner(object):

    scan_re = "|".join([
        r'\bimport\s*\(\s*"(?P<I>[^"]+)"\s*\)\s*;',
        r'\bcomponent\s*\(\s*"(?P<C>[^"]+)"\s*\)',
        ])

    def scan_file(self, task, node):
        pname = node.parent.abspath(task.env)
        for m in re.finditer(self.scan_re, node.read(task.env)):
            for fname in m.groupdict().values():
                if not fname:
                    continue
                key = (pname, fname)
                if key in self.scanned:
                    continue
                self.scanned.add(key)
                n = node.parent.find_resource(fname)
                if n:
                    self.deps.append(n)
                    self.scan_file(task, n)
                    

    def scan(self, task):
        self.deps = []
        self.scanned = set()
        for node in task.inputs:
            self.scan_file(task, node)
        return self.deps, []

dsp_scanner = FaustScanner()

def scan_dsp(task):
    return dsp_scanner.scan(task)

# definition of task "dsp"
Task.task_type_from_func(
    name    = 'dsp',
    func    = dsp2cc,
    color   = 'BLUE',
    ext_in  = '.dsp',
    ext_out = '.cc',
    before  = 'cc cxx',
    ).scan = scan_dsp

@TaskGen.extension('.dsp')
def dsp_file(self, node):
    tsk = self.create_task('dsp')
    tsk.proc = self.proc
    tsk.proc_args = getattr(self, "proc_args", [])
    tsk.set_inputs(node)
    parent = node.parent
    o = node.change_ext('.cc')
    tsk.set_outputs(o)
    bld = tsk.generator.bld
    bld.add_manual_dependency(node,bld.bldnode.find_resource(self.proc))

def build(bld):
    sources = [
        # amp
        'preamp.dsp',
        'inputgain.dsp',
        'noise_shaper.dsp',
        'AntiAlias.dsp',
        'HighShelf.dsp',
        'drive.dsp',
        'osc_tube.dsp',
        'reso_tube.dsp',
        'tube.dsp',
        'tube3.dsp',
        'tubevibrato.dsp',
        #'tone.dsp',
        'multifilter.dsp',
        'eq.dsp',
        'bassbooster.dsp',
        'outputgain.dsp',
        'feed.dsp',
        'balance.dsp',
        'balance1.dsp',
        'amp2.dsp',
        'stage3.dsp',
        'tonestack_default.dsp',
        'tonestack_bassman.dsp',
        'tonestack_twin.dsp',
        'tonestack_princeton.dsp',
        'tonestack_jcm800.dsp',
        'tonestack_jcm2000.dsp',
        'tonestack_mlead.dsp',
        'tonestack_m2199.dsp',
        'tonestack_ac30.dsp',
        'tonestack_soldano.dsp',
        'tonestack_mesa.dsp',
        'tonestack_jtm45.dsp',
        'tonestack_ac15.dsp',
        'tonestack_peavey.dsp',
        'tonestack_ibanez.dsp',
        'tonestack_roland.dsp',
        'tonestack_ampeg.dsp',


        # effects
        'overdrive.dsp',
        'compressor.dsp',
        'crybaby.dsp',
        'autowah.dsp',
        'distortion.dsp',
        'distortion1.dsp',
        'freeverb.dsp',
        'flanger.dsp',
        'impulseresponse.dsp',
        'moog.dsp',
        'biquad.dsp',
        'selecteq.dsp',
        'jconv_post.dsp',
        'phaser.dsp',
        #'cabinet_impulse_former.dsp',
        #gx-2
        'gxamp.dsp',
        'gxamp2.dsp',
        'gxamp3.dsp',
        'gxamp4.dsp',
        'gxamp5.dsp',
        'gxamp10.dsp',
        'gxamp12.dsp',
        'gx_ampmodul.dsp',
        'gxfeed.dsp',
        'gx_feedback.dsp',
        #'gxdistortion.dsp',
        'low_high_pass.dsp',
        'gx_distortion.dsp',
        'gx_outputlevel.dsp',
        'gx_ampout.dsp',
        'noisegate.dsp',
        'softclip.dsp',
        'tonecontroll.dsp',
        'tremolo.dsp',
        'phaser_mono.dsp',
        'flanger_mono.dsp',
        ]

    float_sources = [ # big arrays and no sensitive processing
        'sloop.dsp',
        'echo.dsp',
        'delay.dsp',
        'chorus.dsp',
        'chorus_mono.dsp',
        'stereodelay.dsp',
        'stereoecho.dsp',
    ]

    

    if bld.env['FAUST']:
        float_arg = ["-s","40000","-float"]
        if bld.env['FAUST_DOUBLE']:
            arg = ["-double"]
        else:
            arg = ["-float"]
        task = bld.new_task_gen(
            source = sources,
            proc = "../tools/dsp2cc",
            proc_args = arg,
            )
        bld.new_task_gen(
            source = float_sources,
            proc = "../tools/dsp2cc",
            proc_args = float_arg,
            )

        
    else:
        gdir = "../faust-generated/"
        for s in sources + float_sources:
            s = s.replace(".dsp",".cc")
            bld(name = "copy-faust-cc",
                rule = "cp ${SRC} ${TGT}",
                source = gdir + s,
                target = s,
            )
    bld.add_group()

def configure(conf):
    pass
