예제 #1
0
def checkMinMaxDefault(el):
    """
    check that min, max, and default values are OK
    """
    label = getText(el,'label')
    min = float(getText(el,'min'))
    max = float(getText(el,'max'))
    mapping = getText(el,'mapping')
    defaultTxt = getText(el,'default')
    # protection against non-existing defaults in controlouts
    if ("" != defaultTxt):
        default = float(defaultTxt)
    else:
        default = min
        
    if float(min) >= float(max) :
        print(T+"Error: "+label+" min > max !!!")
        return 1
    elif float(default) > float(max) :
        print(T+"Error: "+label+" default > max !!!")
        return 2
    elif float(default) < float(min) :
        print(T+"Error: "+label+" default < min !!!")
        return 3
    elif((mapping=='log') and (min <= 0)):
        print(T+"Error: "+label+" negative min is not allowed with logarithmic mapping")
        return 4
    else:
        return 0
예제 #2
0
def checkMinMaxDefault(el):
    """
    check that min, max, and default values are OK
    """
    label = getText(el, 'label')
    min = float(getText(el, 'min'))
    max = float(getText(el, 'max'))
    mapping = getText(el, 'mapping')
    defaultTxt = getText(el, 'default')
    # protection against non-existing defaults in controlouts
    if ("" != defaultTxt):
        default = float(defaultTxt)
    else:
        default = min

    if float(min) >= float(max):
        print(T + "Error: " + label + " min > max !!!")
        return 1
    elif float(default) > float(max):
        print(T + "Error: " + label + " default > max !!!")
        return 2
    elif float(default) < float(min):
        print(T + "Error: " + label + " default < min !!!")
        return 3
    elif ((mapping == 'log') and (min <= 0)):
        print(T + "Error: " + label +
              " negative min is not allowed with logarithmic mapping")
        return 4
    else:
        return 0
예제 #3
0
def writeUpdateStates(fc, states):
    if ([] != states):
        fc.write(T + "// Update the states in plugin's structure:" + '\n')
        for state_node in states:
            state_label = getText(state_node, 'label')
            state_type = getText(state_node, 'type')
            fc.write(T + 'plugin_data->' + state_label + ' = ' + state_label +
                     ';' + '\n')
    return
예제 #4
0
def writeGetStates(fc, states):
    if ([] != states):
        fc.write(T + "// Get the states from plugin's structure:" + '\n')
        for state_node in states:
            state_label = getText(state_node, 'label')
            state_type = getText(state_node, 'type')
            fc.write(T + state_type + ' ' + state_label + ' = plugin_data->' +
                     state_label + ';' + '\n')
    return
예제 #5
0
def writeCallbackCode(fc, callback):
    if callback:
        code = getText(callback, 'code')
        label = getText(callback, 'label')
        fc.write(T + '// Code from callback <' + label +
                 '> of XSPIF meta-plugin' + '\n')
        fc.write(T + '{' + '\n')
        fc.write(code)
        fc.write('\n' + T + '}' + '\n')
    return
예제 #6
0
파일: pd.py 프로젝트: vincentgoudard/xspif
def writeUpdateStates(fc, states):
    if ([] != states):
        fc.write('\n')
        fc.write(T + "// Update the states in plugin's structure:" + '\n')
        for s_node in states:
            s_label = getText(s_node, 'label')
            s_type  = getText(s_node, 'type')
            fc.write(T + 'x->' + s_label + ' = '
                     + s_label + ';' + '\n')
    return
예제 #7
0
파일: pd.py 프로젝트: vincentgoudard/xspif
def writeGetParams(fc, params):
    if ([] != params):
        fc.write('\n')
        fc.write(T + "// Get the params from plugin's structure:" + '\n')
        for p_node in params:
            p_label = getText(p_node, 'label')
            p_type  = getText(p_node, 'type')
            fc.write(T +p_type + ' ' + p_label
                     +' = x->m_f'+p_label+';' + '\n')
    return
예제 #8
0
파일: pd.py 프로젝트: vincentgoudard/xspif
def writeGetStates(fc, states):
    if ([] != states):
        fc.write('\n')
        fc.write(T + "// Get the states from plugin's structure:" + '\n')
        for s_node in states:
            s_label = getText(s_node, 'label')
            s_type  = getText(s_node, 'type')
            fc.write(T + s_type + ' ' + s_label
                     + ' = x->' + s_label + ';' + '\n')
    return
예제 #9
0
def writeGetParams(fc, params):
    if ([] != params):
        fc.write(T + "// Get the params from plugin's structure:" + '\n')
        for param_node in params:
            param_caption = getText(param_node, 'caption')
            param_label = getText(param_node, 'label')
            param_type = getText(param_node, 'type')
            fc.write(T + 'const LADSPA_Data ' + param_label +
                     ' = *(plugin_data->m_pf' + param_label + ');' + '\n')
        fc.write('\n')
    return
예제 #10
0
파일: pd.py 프로젝트: vincentgoudard/xspif
def writeCallbackCode(fc, callback):
    if callback:
        code = getText(callback, 'code')
        label = getText(callback, 'label')
        fc.write('\n')
        fc.write(T + '// Code from callback <' + label
                 + '> of XSPIF meta-plugin' + '\n')
        fc.write(T + '{' + '\n')
        fc.write(code)
        fc.write('\n'+T+ '}' + '\n')
    return
예제 #11
0
파일: pd.py 프로젝트: vincentgoudard/xspif
def writeGetControlouts(fc, controlouts):
    if ([] != controlouts):
        fc.write('\n')
        fc.write(T + "// Get the pointers to the outlets:" + '\n')
        for c_node in controlouts:
            c_label = getText(c_node, 'label')
            c_type  = getText(c_node, 'type')
            fc.write(T + 't_outlet *' + c_label
                     + ' = x->' + c_label + ';' + '\n')
            fc.write('\n')
    return
예제 #12
0
파일: au.py 프로젝트: vincentgoudard/xspif
def write(plugin,filename_prefix):
    fcpp = file(filename_prefix + '.au.cpp','w')
    xml_filename  = filename_prefix + ".xspif"
    print T+'writing : '+filename_prefix+'.au.cpp'

   ######## independent code here ############

    # Variables
    plugId        = getText(plugin,'plugId')
    manufId       = getText(plugin,'manufId')
    maker         = getText(plugin,'maker')
    pluginLabel   = getText(plugin,'label')
    pluginLabel.replace(' ', '') #remove spaces in
    pluginLabel.title(); # forces the first letter to upper case
    copyright     = getText(plugin,'copyright')
    comment = getText(plugin,'comment')+'\n'
    pluginCode = getText(plugin,'code')+'\n'
    pluginCaption = getText(plugin,'caption')

    params = plugin.getElementsByTagName('param')    
    states = plugin.getElementsByTagName("state")
    pins = plugin.getElementsByTagName("pin")
    callbacks = plugin.getElementsByTagName('callback')

    instantiate   = None
    deinstantiate = None
    process       = None
    processEvents = None
    activate      = None
    deactivate    = None
    
    if callbacks == [] : 
        print T+ "Warning: you haven't implemented any callback"+'\n'
    else :
        for callback in callbacks:
            text = str(getText(callback,'label'))
            if text == 'instantiate':
                instantiate = callback
            if text == 'deinstantiate':
                deinstantiate = callback
            if text == 'activate':
                activate = callback
            if text == 'deactivate':
                deactivate = callback
            if text == 'process':
                process = callback
            if text == 'processEvents':
                print 'XSPIF Warning: callback "processEvents" not implemented in VST for now'
                #processEvents = callback  

    instantiateCode = getText(instantiate,'code')
    deinstantiateCode = getText(deinstantiate,'code')
    activateCode = getText(activate,'code')
    deactivateCode = getText(deactivate,'code')
    processCode = getText(process,'code')
    
    #----------------------------------------------------------------------------
    # CPP file
    #----------------------------------------------------------------------------
    
    #----------------------------------------------------------------------------
    # file header

    fcpp.write(
        '/****************************************************************\n'
        + 'XSPIF: cross(X) Standard PlugIn Framework: '
        + 'XSPIF to AudioUnits\n'
        + T+filename_prefix+'.au.cpp'+'\n\n'
        + comment
        + ' This file is generated automatically from the file: '+xml_filename+'\n'
        + ' DO NOT EDIT BY HAND'+'\n'
        + T+'plugin ID: '+plugId+'\n'
        + T+'manufacturer ID: '+manufId+'\n'
        + T+'maker: '+maker+'\n'
        + T+'copyright: '+copyright+'\n'
        + ' ***************************************************************/\n'
        + '\n'
        )

    #includes and independent code
    fcpp.write('\n'
             +'#include <AUEffectBase.h>'+'\n'
             +'\n'
             +'// XSPIF macros'+'\n'
             +'#define XSPIF_GET_SAMPLE_RATE() (GetSampleRate())'+'\n'
             +'#define XSPIF_GET_VECTOR_SIZE() (vector_size)'+'\n'
             +'#define XSPIF_CONTROLOUT() (// NO control out until macosx 10.3)'+'\n'
             +'\n'
             +'// <from '+xml_filename+'>'+'\n'
             +pluginCode+'\n'
             +'// </from '+xml_filename+'>'+'\n')

    #----------------------------------------------------------------------------
    # Class declaration (TODO:change the base according to the purpose)

    fcpp.write('class '+pluginLabel+': public AUEffectBase'+'\n'
               +'{'+'\n'
               +'public:'+'\n'
               +T+pluginLabel+'(AudioUnit component);'+'\n'
               +T+'~'+pluginLabel+'();'+'\n'
               +T+''+'\n'
               +T+'virtual OSStatus ProcessBufferLists( AudioUnitRenderActionFlags & ioActionFlags,'+'\n'
               +T+'                                     const AudioBufferList & inBuffer,'+'\n'
               +T+'                                     AudioBufferList & outBuffer,'+'\n'
               +T+'                                     UInt32 inFramesToProcess);'+'\n'
               +T+''+'\n'
               +T+'virtual UInt32 SupportedNumChannels(const AUChannelInfo** outInfo);'+'\n'
               +T+'virtual ComponentResult Initialize();'+'\n'
               +T+'virtual ComponentResult GetParameterInfo( AudioUnitScope inScope,'+'\n'
               +T+'                                          AudioUnitParameterID inParameterId,'+'\n'
               +T+'                                          AudioUnitParameterInfo &outParameterInfo);'+'\n'
               +T+''+'\n'
               +'private:'+'\n'
               )
    
    # declare params
    if params != []:
        fcpp.write(T+'//params'+'\n'
                   +T+'enum Parameters'+'\n'
                   +T+'{'+'\n')
        
        for param in params:
            label   = getText(param,'label')
            fcpp.write(T*2+'k'+label+','+'\n')

        fcpp.write(T+''+'\n'
                   +T*2+'kNumParams'+'\n'
                   +T+'};'+'\n'
                   +'\n')

        for param in params:
            label   = getText(param,'label')
            default = getText(param,'default')
            min     = getText(param,'min')
            max     = getText(param,'max')
            fcpp.write(T+'static const float '+label+'Default = '+default+';'+'\n'
                     +T+'static const float '+label+'Min = '+min+';'+'\n'
                     +T+'static const float '+label+'Max = '+max+';'+'\n'
                     +T+'float '+label+';'+'\n'
                     +'\n')

    # declare supported  number of channels
    numInputs = numOutputs = 0
    
    for pin in pins:
        dir      = getText(pin,'dir')
        channels = int(str(getText(pin,'channels')))
        if dir == 'In':
            numInputs += channels
        elif dir == 'Out':
            numOutputs += channels

    if numInputs < numOutputs:
        numchannels = numInputs
    else:
        numchannels = numOutputs
        
    numchannels = str(numchannels)
    numInputs  = str(numInputs)
    numOutputs = str(numOutputs)

    
    fcpp.write(T+'enum {'+'\n'
             +T*2+'kNumSupportedNumChannels = '+numchannels+'\n'
             +T+'};'+'\n'
             +'\n'
             +T+'static AUChannelInfo m_aobSupportedNumChannels[kNumSupportedNumChannels];'+'\n'
             +'\n'
             )
    
    # process declaration
    fcpp.write(T+'OSStatus Process(const AudioBufferList& obInBuffers,'+'\n'
             +T+'                 AudioBufferList& obOutBuffers,'+'\n'
             +T+'                 UInt32 inFramesToProcess,'+'\n'
             +T+'                 AudioUnitRenderActionFlags& ioactionFlags);'+'\n'
             +'\n'
             )
    
    # states
    if states != []:
        fcpp.write(T+'// states'+'\n')
    
        for state in states:
            label = getText(state,'label')
            type  = getText(state,'type')
            fcpp.write(T+type+' '+label+';'+'\n')
                
    fcpp.write('\n'
             +T+'long vector_size;'+'\n'
             +'};'+'\n'
             +'\n'
             )
    
    #----------------------------------------------------------------------------
    # CPP file
    #--------------------------------------------------------------------------
    fcpp.write(
"""
//----------------------------------------------------------------------------
// IMPLEMENTATION 
//--------------------------------------------------------------------------
        
""")

    #--------------------------------------------------------------------------
    fcpp.write('//------------------------------------------------------'+'\n'
               +'COMPONENT_ENTRY('+pluginLabel+')'+'\n'
               +'\n'
               )
    
    #--------------------------------------------------------------------------
    # Topology

    numInputs = numOutputs = 0
    
    for pin in pins:
        dir      = getText(pin,'dir')
        channels = int(str(getText(pin,'channels')))
        if dir == 'In':
            numInputs += channels
        elif dir == 'Out':
            numOutputs += channels

    numInputs  = str(numInputs)
    numOutputs = str(numOutputs)

    fcpp.write('#define NUM_INPUTS '+numInputs+'\n'
               +'#define NUM_OUTPUTS '+numOutputs+'\n'
               )

    fcpp.write('//------------------------------------------------------'+'\n'
               +'AUChannelInfo '+pluginLabel+'::m_aobSupportedNumChannels['+pluginLabel+'::kNumSupportedNumChannels] = {{'+numInputs+','+numOutputs+'}};'+'\n'
               +'\n'
               )
    
    #--------------------------------------------------------------------------
    # Plugin Class
    # Plugin Constructor
    fcpp.write('//------------------------------------------------------'+'\n'
               +pluginLabel+'::'+pluginLabel+'(AudioUnit component): AUEffectBase(component)'+'\n'
               +'{'+'\n'
               +T+'CreateElements();'+'\n'
               +'\n')

    fcpp.write('\n'
               +T+'// instantiate callback'+'\n'
               +T+instantiateCode+'\n'
               +'\n')

    if params != []:
         for param in params:
            label   = getText(param,'label')
            fcpp.write(T+'SetParameter(k'+label+','+label+'Default);'+'\n')

    fcpp.write('}'+'\n'
               +'\n')

    # Plugin Deconstructor
    fcpp.write('//------------------------------------------------------'+'\n'
               +pluginLabel+'::~'+pluginLabel+'()'+'\n'
               +'{'+'\n'
               )
    
    fcpp.write('\n'
               +T+'// deinstantiate callback'+'\n'
               +T+deinstantiateCode+'\n'
               +'\n')

    fcpp.write('}'+'\n'
               +'\n')
    
    # Plugin infos
    fcpp.write('//------------------------------------------------------'+'\n'
               +'UInt32 '+pluginLabel+'::SupportedNumChannels(const AUChannelInfo **outInfo)'+'\n'
               +'{'+'\n'
               +T+'if(outInfo != NULL)'+'\n'
               +T*2+'*outInfo = &m_aobSupportedNumChannels[0];'+'\n'
               +T+'return kNumSupportedNumChannels;'+'\n'
               +'}'+'\n'
               +'\n'
               )

    fcpp.write('//------------------------------------------------------'+'\n'
               +'ComponentResult '+pluginLabel+'::GetParameterInfo(AudioUnitScope inScope,'+'\n'
               +'                                                  AudioUnitParameterID inParameterID,'+'\n'
               +'                                                  AudioUnitParameterInfo &outParameterInfo)'+'\n'
               +'{'+'\n'
               +T+'if(inScope != kAudioUnitScope_Global)'+'\n'
               +T*2+'return kAudioUnitErr_InvalidParameter;'+'\n'
               +'\n'
               +T+'ComponentResult result = noErr;'+'\n'
               +'\n'
               +T+'outParameterInfo.flags = kAudioUnitParameterFlag_IsWritable | kAudioUnitParameterFlag_IsReadable | kAudioUnitParameterFlag_Global;'+'\n'
               +'\n'
               +T+'char *pcName = outParameterInfo.name;'+'\n'
               +'\n'
               +T+'switch(inParameterID)'+'\n'
               +T+'{'+'\n')
    if params != []:
         for param in params:
            label   = getText(param,'label')
            caption = getText(param,'caption')
            fcpp.write(T*2+'case k'+label+':'+'\n'
                       +T*3+'strcpy(pcName,"'+caption+'");'+'\n'
                       +T*3+'outParameterInfo.unit = kAudioUnitParameterUnit_Generic;'+'\n'
                       +T*3+'outParameterInfo.minValue = '+label+'Min;'+'\n'
                       +T*3+'outParameterInfo.maxValue = '+label+'Max;'+'\n'
                       +T*3+'outParameterInfo.defaultValue = '+label+'Default;'+'\n'
                       +T*3+'break;'+'\n'
                       +'\n'
                       )
                
    fcpp.write(T*2+'default:'+'\n'
               +T*3+'result = kAudioUnitErr_InvalidParameter;'+'\n'
               +T*3+'break;'+'\n'
               +T+'}'+'\n'
               +'\n'
               +T+'return result;'+'\n'
               +T+'}'+'\n'
               )
    
    # Plugin suspend and resume
    fcpp.write('//------------------------------------------------------'+'\n'
               +'ComponentResult '+pluginLabel+'::Initialize()'+'\n'
               +'{'+'\n'
               +T+'return noErr;'+'\n'
               +'}'+'\n')
               

    #--------------------------------------------------------------------------
    # processing
    fcpp.write('//------------------------------------------------------'+'\n'
               +'OSStatus '+pluginLabel+'::ProcessBufferLists(AudioUnitRenderActionFlags &ioActionFlags,'+'\n'
               +'                                             const AudioBufferList &inBuffer,'+'\n'
               +'                                             AudioBufferList &outBuffer,'+'\n'
               +'                                             UInt32 inFramesToProcess)'+'\n'
               +'{'+'\n'
               +T+'ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;'+'\n'
               +'\n'
               +T+'UInt32 uiInBuffers = inBuffer.mNumberBuffers;'+'\n'
               +T+'UInt32 uiOutBuffers = outBuffer.mNumberBuffers;'+'\n'
               +'\n'
               +T+'if(uiInBuffers != NUM_INPUTS || uiOutBuffers != NUM_OUTPUTS)'+'\n'
               +T*2+'return kAudioUnitErr_FormatNotSupported;'+'\n'
               +'\n'
               +T+'return Process(inBuffer, outBuffer, inFramesToProcess, ioActionFlags);'+'\n'
               +'}'+'\n'
               +'\n')

    fcpp.write('#define XSPIF_WRITE_SAMPLE(dest,index,source) ((dest)[(index)] = (source))'+'\n'
               +'\n')

    fcpp.write('//------------------------------------------------------'+'\n'
               +'OSStatus '+pluginLabel+'::Process(const AudioBufferList &obInBuffers,'+'\n'
               +'                                  AudioBufferList &obOutBuffers,'+'\n'
               +'                                  UInt32 inFramesToProcess,'+'\n'
               +'                                  AudioUnitRenderActionFlags &ioActionFlags)'+'\n'
               +'{'+'\n'
               +T+'ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;'+'\n'
               +'\n')

    for i in range(0,int(numInputs)):
               fcpp.write(T+'const AudioBuffer &obInBuffer'+str(i)+' = obInBuffers.mBuffers['+str(i)+'];'+'\n')

    for i in range(0,int(numOutputs)):
               fcpp.write(T+'AudioBuffer &obOutBuffer'+str(i)+' = obOutBuffers.mBuffers['+str(i)+'];'+'\n')

    i=0
    for pin in pins:
        dir   = getText(pin,'dir')
        if dir == 'In':
            i = i+1
            label = getText(pin,'label')
            channels = int(str(getText(pin,'channels')))
            for j in range(0,channels):
                fcpp.write(T+'const Float32 *'+label+str(i+j)+' = (const Float32 *)obInBuffer'+str(i+j-1)+'.mData;'+'\n')

    i=0
    for pin in pins:
        dir   = getText(pin,'dir')
        if dir == 'Out':
            i = i+1
            label = getText(pin,'label')
            channels = int(str(getText(pin,'channels')))
            for j in range(0,channels):
                fcpp.write(T+'Float32 *'+label+str(i+j)+' = (Float32 *)obOutBuffer'+str(i+j-1)+'.mData;'+'\n')            

    fcpp.write(T+'vector_size = inFramesToProcess;'+'\n'
               +'\n'
               )

    if params != []:
        fcpp.write(T+'//retrieving params'+'\n')
        for param in params:
            label   = getText(param,'label')
            fcpp.write(T+label+' = GetParameter(k'+label+');'+'\n')

        fcpp.write(T+'//updating states'+'\n')
        for param in params:
            paramCode = getText(param,'code')
            fcpp.write(T+paramCode+'\n')

    fcpp.write(T+'//****************************************'+'\n'
               +processCode+'\n'
               +'//****************************************'+'\n'
               +'\n'
               +T+'return noErr;'+'\n'
               +'}'+'\n'
               )

    fcpp.close
    print T+'done'
    
    #--------------------------------------------------------------------------
    # r
    fr = file(filename_prefix + '.au.r','w')
    print T+'writing : '+filename_prefix+'.au.r'

    fr.write('#include <AudioUnit/AudioUnit.r>'+'\n'
             +'\n'
             +'// Note that resource IDs must be spaced 2 apart for the '+"'STR'"+' name and description'+'\n'
             +'#define kAudioUnitResID_'+pluginLabel+'				10000'+'\n'
             +'\n'
             +'// So you need to define these appropriately for your audio unit.'+'\n'
             +"// For the name the convention is to provide your company name and end it with a ':',"+'\n'
             +'// then provide the name of the AudioUnit.'+'\n'
             +'// The Description can be whatever you want.'+'\n'
             +'// For an effect unit the Type and SubType should be left the way they are defined here...'+'\n'
             +'//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'+'\n'
             +'// SampleEffectUnit'+'\n'
             +'#define RES_ID			kAudioUnitResID_'+pluginLabel+'\n'
             +'#define COMP_TYPE		'+"'aufx'"+'\n'
             +'#define COMP_SUBTYPE		'+plugId+'\n'
             +'#define COMP_MANUF		'+manufId+'\n' 	
             +'#define VERSION			0x00010000'+'\n'
             +'#define NAME			"'+maker+': '+pluginCaption+'"'+'\n'
             +'#define DESCRIPTION		"'+pluginCaption+'"'+'\n'
             +'#define ENTRY_POINT		"'+pluginLabel+'Entry"'+'\n'
             +'\n'
             +'#include "AUResources.r"'+'\n'
             )    
    fr.close

    print T+'done'

    fexp = file(filename_prefix + '.exp','w')
    print T+'writing : '+filename_prefix+'.exp'
    fexp.write('_'+pluginLabel+'Entry')
    fexp.close
    print T+'done'
    
    return
예제 #13
0
def write(domTree, filenamePrefix):
    """
    This method is called by xspif2ladspa.py
    It writes the LADSPA plugin's source file [filenamePrefix].ladspa.c
    for the linux platform with the help of the DOM tree [domTree].
    """

    #create output file(s)
    xml_filename = (filenamePrefix + '.xspif')
    c_filename = (filenamePrefix + '.ladspa.c')
    fc = file(c_filename, 'w')

    # Get the domTree direct childs
    pluginId = getText(domTree, 'plugId')
    pluginLabel = getText(domTree, 'label')
    pluginManufId = getText(domTree, "manufId")
    pluginCaption = getText(domTree, 'caption')
    pluginComments = getText(domTree, 'comment')
    pluginMaker = getText(domTree, 'maker')
    pluginCopyright = getText(domTree, 'copyright')
    pluginCode = getText(domTree, 'code')

    pins = domTree.getElementsByTagName('pin')
    params = domTree.getElementsByTagName('param')
    states = domTree.getElementsByTagName('state')
    controlouts = domTree.getElementsByTagName('controlout')

    callbacks = domTree.getElementsByTagName('callback')

    # Get the callbacks by their name
    instantiate = None
    deinstantiate = None
    process = None
    processEvents = None
    activate = None
    deactivate = None
    if callbacks == []:
        print T + "Warning: you haven't implemented any callback" + '\n'
    else:
        for callback in callbacks:
            text = str(getText(callback, 'label'))
            if text == 'instantiate':
                instantiate = callback
            elif text == 'deinstantiate':
                deinstantiate = callback
            elif text == 'activate':
                activate = callback
            elif text == 'deactivate':
                deactivate = callback
            elif text == 'process':
                process = callback
            elif text == 'processEvents':
                print 'XSPIF Warning: callback "processEvents" not implemented for LADSPA for now'
                #processEvents = callback
            else:
                print('Warning: callback ' + text +
                      ' is not known from ladspa.py' + '\n')

    # useful variables...
    separator = '\n' + '/****************************************************************/' + '\n'

    #----------------------------------------------------------------------------

    # make lists with ports
    # make a list with pins
    audio_ports = []
    for pin_node in pins:
        pin_label = getText(pin_node, 'label')
        pin_channels = int(getText(pin_node, 'channels'))
        pin_dir = getText(pin_node, 'dir')
        pin_caption = getText(pin_node, 'caption')
        for i in range(1, pin_channels + 1):
            audio_ports.append([pin_label + str(i), pin_dir, pin_caption])

    # make a list with params
    param_ports = []
    for p_node in params:
        p_label = getText(p_node, 'label')
        p_caption = getText(p_node, 'caption')
        p_type = getText(p_node, 'type')
        param_ports.append([p_label, 'param', p_caption, p_type])

    # make a list with controlouts
    controlout_ports = []
    for c_node in controlouts:
        c_label = getText(c_node, 'label')
        c_caption = getText(c_node, 'caption')
        c_type = getText(c_node, 'type')
        controlout_ports.append([c_label, 'controlout', c_caption, c_type])

    # make a list with all ports
    ports = audio_ports + param_ports + controlout_ports

    #----------------------------------------------------------------------------
    # file header

    fc.write(
        '/****************************************************************' +
        '\n' + 'XSPIF: cross(X) Standard PlugIn Framework: ' +
        'XSPIF to LADSPA' + '\n' + T + c_filename + '\n' + '\n' +
        pluginComments +
        ' This file is generated automatically from the file: ' +
        xml_filename + '\n' + T + 'plugin ID: ' + pluginId + '\n' + T +
        'manufacturer ID: ' + pluginManufId + '\n' + T + 'maker: ' +
        pluginMaker + '\n' + T + 'copyright: ' + pluginCopyright + '\n' +
        '****************************************************************/' +
        '\n' + '\n' + '\n' + '\n')

    #----------------------------------------------------------------------------
    # includes and independant code
    fc.write('#include <stdlib.h>' + '\n' + '#include <string.h>' + '\n' +
             '#include "ladspa.h"' + '\n' + '\n')
    # macros
    fc.write('\n' + '\n' + separator)
    fc.write('// Macro for getting the sample rate' + '\n')
    fc.write('#undef XSPIF_GET_SAMPLE_RATE' + '\n'
             '#define XSPIF_GET_SAMPLE_RATE() (plugin_data->sample_rate)' +
             '\n')

    fc.write('// Macro for getting the vector_size' + '\n')
    fc.write('#undef XSPIF_GET_VECTOR_SIZE' + '\n'
             '#define XSPIF_GET_VECTOR_SIZE() (sample_count)' + '\n')

    if ([] != controlouts):
        fc.write('// Macro for control output' + '\n')
        fc.write('#undef XSPIF_CONTROLOUT' + '\n'
                 '#define XSPIF_CONTROLOUT(dest, index, source)' +
                 '(*(dest) = (LADSPA_DATA(source)))' + '\n')

    fc.write('\n' + '\n' + separator)
    fc.write(pluginCode + '\n')

    #----------------------------------------------------------------------------
    # Port declaration

    # write ports declaration in the c file
    fc.write('\n' + '\n' + separator)
    fc.write('/* Audio and parameters ports */' + '\n')
    for port in ports:
        fc.write('#define PORT_' + port[0].upper() + T * 2 +
                 str(ports.index(port)) + '\n')

    #---------------------------------------------------
    # LADSPA DESCRIPTOR
    #---------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('static LADSPA_Descriptor *' + pluginLabel.lower() +
             'Descriptor = NULL;' + '\n')

    #---------------------------------------------------
    # The plugin structure contains ...
    #---------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('// The plugin structure ' + '\n')
    fc.write('typedef struct {' + '\n' + '\n')

    # the sample rate
    fc.write(T + 'LADSPA_Data sample_rate;' + '\n')

    # ...the pointers for the ports ...
    fc.write(T + '// Pointers to the ports:\n')
    for port in ports:
        fc.write(T + 'LADSPA_Data *m_pf' + port[0] + ';' + '\n')
    fc.write('\n')

    # ...a copy of the parameter and its last value for local use...
    fc.write(T + '// Internal copy of the parameters and its last value:\n')
    for port in param_ports:
        fc.write(T + port[3] + ' ' + port[0] + ';' + '\n')
        fc.write(T + port[3] + ' _last_' + port[0] + ';' + '\n')
    fc.write('\n')

    # ... and the states ...(except the code_states declared as global)
    fc.write(T + '// Internal states:\n')
    if ([] != states):
        for state_node in states:
            state_label = getText(state_node, 'label')
            state_type = getText(state_node, 'type')
            fc.write(T + state_type + ' ' + state_label + ';' + '\n')

    # run adding gain
    fc.write(T + 'LADSPA_Data run_adding_gain;' + '\n')

    fc.write('}' + pluginLabel + ';' + '\n')

    #----------------------------------------------------------------------------
    # Plugin descriptor
    # TODO: handle case with multiple plugs in a dll with a 'for' loop
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write(
        'const LADSPA_Descriptor *ladspa_descriptor(unsigned long index) {' +
        '\n' * 2 + T + 'switch (index) {' + '\n' + T + 'case 0:' + '\n' +
        T * 2 + 'return ' + pluginLabel.lower() + 'Descriptor;' + '\n' + T +
        'default:' + '\n' + T * 2 + 'return NULL;' + '\n' + T + '}' + '\n' +
        '}' + '\n')

    #---------------------------------------------------------------------------
    #  Plugin activate function
    #---------------------------------------------------------------------------
    if (activate):
        activate_code = getText(activate, 'code')
        fc.write('\n' + '\n' + separator)
        fc.write('// Initialise and activate a plugin instance.' + '\n')
        fc.write('static void activate' + pluginLabel +
                 '(LADSPA_Handle instance) {' + '\n' * 2 + T + pluginLabel +
                 ' *plugin_data = (' + pluginLabel + '*)instance;' + '\n')

        writeGetStates(fc, states)
        writeGetParams(fc, params)
        writeCallbackCode(fc, activate)
        writeUpdateStates(fc, states)

        fc.write('\n' + '}' + '\n')

    #---------------------------------------------------------------------------
    #  Plugin deactivate function
    #---------------------------------------------------------------------------
    if (deactivate):
        deactivate_code = getText(deactivate, 'code')
        fc.write('\n' + '\n' + separator)
        fc.write('// Deactivate a plugin instance.' + '\n')
        fc.write('static void deactivate' + pluginLabel +
                 '(LADSPA_Handle instance) {' + '\n' * 2 + T + pluginLabel +
                 ' *plugin_data = (' + pluginLabel + '*)instance;' + '\n')

        writeGetStates(fc, states)
        writeGetParams(fc, params)
        writeCallbackCode(fc, deactivate)
        writeUpdateStates(fc, states)

        fc.write('\n' + '}' + '\n')

    #----------------------------------------------------------------------------
    # Plugin cleanup function (=deinstantiate)
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('/* Cleanup is the "de-instantiate" function.' + '\n' +
             'Free the memory allocated in "instantiate" in this function */' +
             '\n')
    fc.write('static void cleanup' + pluginLabel +
             '(LADSPA_Handle instance) {' + '\n' * 2 + T + pluginLabel +
             '* plugin_data = (' + pluginLabel + '*)instance;' + '\n')

    # If deinstantiate is implemented in the meta-plugin
    # Get the states, so that any structure can be deleted fom memory:
    if (deinstantiate):
        writeGetStates(fc, states)
        writeGetParams(fc, params)
        writeCallbackCode(fc, deinstantiate)

    fc.write(T + 'free(instance);' + '\n' + '}' + '\n')

    #----------------------------------------------------------------------------
    # Plugin connect function
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    head = 'static void connectPort' + pluginLabel + '('
    fc.write(head + ' LADSPA_Handle instance,' + '\n' + ' ' * len(head) +
             ' unsigned long port,' + '\n' + ' ' * len(head) +
             ' LADSPA_Data *data) {' + '\n' * 2 + T + pluginLabel +
             ' *plugin;' + '\n' + '\n' + T + 'plugin = (' + pluginLabel +
             ' *)instance;' + '\n' + T + 'switch (port) {' + '\n')

    for port in ports:
        fc.write(T + 'case PORT_' + port[0].upper() + ':' + '\n' + T * 2 +
                 'plugin->m_pf' + port[0] + ' = data;' + '\n' + T * 2 +
                 'break;' + '\n')

    fc.write(T + '}' + '\n' + '}' + '\n')

    #----------------------------------------------------------------------------
    # Instantiate function
    #----------------------------------------------------------------------------
    head = 'static LADSPA_Handle instantiate' + pluginLabel + '('
    fc.write('\n' + '\n' + separator)
    fc.write(head + ' const LADSPA_Descriptor *descriptor,' + '\n' +
             ' ' * len(head) + ' unsigned long s_rate) {' + '\n' * 2 + T +
             pluginLabel + ' *plugin_data = (' + pluginLabel +
             ' *)malloc(sizeof(' + pluginLabel + '));' + '\n' * 2)

    if (instantiate):
        fc.write(T + '// States:' + '\n')
        if ([] != states):
            for state_node in states:
                state_label = getText(state_node, 'label')
                state_type = getText(state_node, 'type')
                fc.write(T + state_type + ' ' + state_label + ';' + '\n')

#    fc.write(T + 'if (plugin_data) {'+ '\n')
    fc.write(T * 2 + 'plugin_data->sample_rate =(LADSPA_Data)s_rate;' + '\n')

    if (instantiate):
        writeCallbackCode(fc, instantiate)
        writeUpdateStates(fc, states)

    fc.write('\n' + T + 'return (LADSPA_Handle)plugin_data;' + '\n' + '}' +
             '\n')

    #----------------------------------------------------------------------------
    # Define once the XSPIF_WRITE_SAMPLE macro for 'run-replacing' process
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('// Macro for run-replacing processing' + '\n')
    fc.write(
        '#undef XSPIF_WRITE_SAMPLE' + '\n'
        '#define XSPIF_WRITE_SAMPLE(dest, index, source) ((dest)[(index)] = (source))'
        + '\n')

    #----------------------------------------------------------------------------
    # Run (process) function
    #----------------------------------------------------------------------------
    head = 'static void run' + pluginLabel + '('
    fc.write('\n' + '\n' + separator)
    fc.write(head + 'LADSPA_Handle instance,' + '\n' + ' ' * len(head) +
             'unsigned long sample_count) {' + '\n' * 2 + T + pluginLabel +
             ' *plugin_data = (' + pluginLabel + '*)instance;' + '\n' + '\n')

    # get the parameters new and last values
    for param_node in params:
        param_caption = getText(param_node, 'caption')
        param_label = getText(param_node, 'label')
        param_type = getText(param_node, 'type')
        fc.write(T + '/*' + param_caption + '*/' + '\n' + T +
                 'const LADSPA_Data ' + param_label +
                 ' = *(plugin_data->m_pf' + param_label + ');' + '\n')
        fc.write(T + param_type + ' _last_' + param_label +
                 ' = plugin_data->_last_' + param_label + ';' + '\n')
    fc.write('\n')

    for port in audio_ports:
        if port[1] == 'In':
            fc.write(T + '/* Audio input: ' + port[0] + '*/' + '\n')
            fc.write(T + 'const LADSPA_Data * const ' + port[0])
        elif port[1] == 'Out':
            fc.write(T + '/* Audio output: ' + port[0] + '*/' + '\n')
            fc.write(T + 'LADSPA_Data * const ' + port[0])
        fc.write(' = plugin_data->m_pf' + port[0] + ';' + '\n' + '\n')

    for port in controlout_ports:
        fc.write(T + '/* Control output: ' + port[1] + '*/' + '\n')
        fc.write(T + 'LADSPA_Data * ' + port[0] + ' = plugin_data->m_pf' +
                 port[0] + ';' + '\n' + '\n')

    # ...the states...
    writeGetStates(fc, states)

    # check if param changed and perform necessary conversions if any:
    fc.write('\n')
    fc.write(
        T +
        '// Check if param changed and perform necessary conversions if any:' +
        '\n')
    for param_node in params:
        param_label = getText(param_node, 'label')
        fc.write(T + 'if (' + param_label + ' != _last_' + param_label +
                 ') {' + '\n')
        param_code = getText(param_node, 'code')
        if ('' != param_code):
            fc.write(param_code + '\n')
        fc.write(T * 2 + 'plugin_data->_last_' + param_label + ' = ' +
                 param_label + ';' + '\n' + T + '}' + '\n')

    fc.write('\n')
    # here is the DSP algorithm
    writeCallbackCode(fc, process)

    # Update the states in the plugin structure
    writeUpdateStates(fc, states)

    fc.write('}' + '\n')

    #----------------------------------------------------------------------------
    # Re- define then the XSPIF_WRITE_SAMPLE macro for 'run-adding' process
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('// Macro for run-adding processing' + '\n')
    fc.write(
        '#undef XSPIF_WRITE_SAMPLE' + '\n'
        '#define XSPIF_WRITE_SAMPLE(dest, index, source) ((dest)[(index)] += (source))'
        + '\n')

    #----------------------------------------------------------------------------
    # setRunAddinGain function
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('static void setRunAddingGain' + pluginLabel +
             '(LADSPA_Handle instance,' + '\n' + T * 3 +
             'LADSPA_Data gain) {' + '\n' * 2 + T + '((' + pluginLabel +
             '*)instance)->run_adding_gain = gain;' + '\n' + '}' + '\n')

    #----------------------------------------------------------------------------
    # Run_adding (process with accumulation) function
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('static void runAdding' + pluginLabel +
             '(LADSPA_Handle instance, unsigned long sample_count) {' +
             '\n' * 2 + T + pluginLabel + ' *plugin_data = (' + pluginLabel +
             '*)instance;' + '\n' + T +
             'LADSPA_Data run_adding_gain = plugin_data->run_adding_gain;' +
             '\n' + '\n')

    # get the parameters new and last values
    for param_node in params:
        param_caption = getText(param_node, 'caption')
        param_label = getText(param_node, 'label')
        param_type = getText(param_node, 'type')
        fc.write(T + '/*' + param_caption + '*/' + '\n' + T +
                 'const LADSPA_Data ' + param_label +
                 ' = *(plugin_data->m_pf' + param_label + ');' + '\n')
        fc.write(T + param_type + ' _last_' + param_label +
                 ' = plugin_data->_last_' + param_label + ';' + '\n')
    fc.write('\n')

    for port in audio_ports:
        fc.write(T + '/* Audio input: ' + port[0] + '*/' + '\n')
        if port[1] == 'In':
            fc.write(T + 'const LADSPA_Data * const ' + port[0])
        elif port[1] == 'Out':
            fc.write(T + 'LADSPA_Data * const ' + port[0])
        fc.write(' = plugin_data->m_pf' + port[0] + ';' + '\n' + '\n')

    for port in controlout_ports:
        fc.write(T + '/* Control output: ' + port[1] + '*/' + '\n')
        fc.write(T + 'LADSPA_Data * ' + port[0] + ' = plugin_data->m_pf' +
                 port[0] + ';' + '\n' + '\n')

    # ...the states...
    writeGetStates(fc, states)

    # check if param changed and perform necessary conversions if any:
    fc.write('\n')
    fc.write(
        T +
        '// Check if param changed and perform necessary conversions if any:' +
        '\n')
    for param_node in params:
        param_label = getText(param_node, 'label')
        fc.write(T + 'if (' + param_label + ' != _last_' + param_label +
                 ') {' + '\n')
        param_code = getText(param_node, 'code')
        if ('' != param_code):
            fc.write(param_code + '\n')
        fc.write(T * 2 + 'plugin_data->_last_' + param_label + ' = ' +
                 param_label + ';' + '\n' + T + '}' + '\n')
    fc.write('\n')

    # here is the DSP algorithm
    writeCallbackCode(fc, process)

    # Update the states in the plugin structure
    writeUpdateStates(fc, states)

    fc.write('}' + '\n')

    #----------------------------------------------------------------------------
    # Init function
    #----------------------------------------------------------------------------

    # define shortcuts
    pD = pluginLabel.lower() + 'Descriptor'

    fc.write('\n' + '\n' + separator)
    fc.write(
        '/* _init() is called automatically when the plugin library is first loaded. */'
        + '\n')
    fc.write('void _init() {' + '\n' * 2 + T + 'char **port_names;' + '\n' +
             T + 'LADSPA_PortDescriptor *port_descriptors;' + '\n' + T +
             'LADSPA_PortRangeHint *port_range_hints;' + '\n' + '\n' + T + pD +
             ' = ' + '\n' + T +
             '  (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));' +
             '\n' + '\n' + T + 'if (' + pD + ') {' + '\n' + T * 2 + pD +
             '->UniqueID = ' + pluginId + ';' + '\n' + T * 2 + pD +
             '->Label = strdup("' + pluginLabel + '");' + '\n' + T * 2 + pD +
             '->Name = strdup("' + pluginCaption + '");' + '\n' + T * 2 + pD +
             '->Maker = strdup("' + pluginMaker + '");' + '\n' + T * 2 + pD +
             '->Copyright = strdup("' + pluginCopyright + '");' + '\n' +
             T * 2 + pD + '->PortCount = ' + str(len(ports)) + ';' + '\n' +
             '\n' + T * 2 +
             'port_descriptors = (LADSPA_PortDescriptor *)calloc(' +
             str(len(ports)) + ',' + '\n' + T * 2 +
             ' sizeof(LADSPA_PortDescriptor));' + '\n' + T * 2 + pD +
             '->PortDescriptors =' + '\n' + T * 2 +
             '(const LADSPA_PortDescriptor *)port_descriptors;' + '\n' + '\n' +
             T * 2 + 'port_range_hints = (LADSPA_PortRangeHint *)calloc(' +
             str(len(ports)) + ',' + '\n' + T * 2 +
             ' sizeof(LADSPA_PortRangeHint));' + '\n' + T * 2 + pD +
             '->PortRangeHints =' + '\n' + T * 2 +
             ' (const LADSPA_PortRangeHint *)port_range_hints;' + '\n' + '\n' +
             T * 2 + 'port_names = (char **)calloc(' + str(len(ports)) +
             ', sizeof(char*));' + '\n' + T * 2 + pD + '->PortNames =' + '\n' +
             T * 2 + ' (const char **)port_names;' + '\n' + '\n')

    # Write descriptors for input parameters (TODO: ouput parameters in xml)
    control_nodes = params + controlouts
    for cp_node in control_nodes:
        pl = 'PORT_' + getText(cp_node, 'label').upper()  # shortcut
        fc.write(T * 2 + '/* Parameters for ' + getText(cp_node, 'caption') +
                 ' */' + '\n' + T * 2 + 'port_descriptors[' + pl + '] =' +
                 '\n')
        if ('param' == cp_node.nodeName):
            fc.write(T * 2 + ' LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;' +
                     '\n')
        elif ('controlout' == cp_node.nodeName):
            fc.write(T * 2 + ' LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;' +
                     '\n')
        fc.write(T * 2 + 'port_names[' + pl + '] =' + '\n' + T * 2 +
                 ' strdup("' + getText(cp_node, 'caption') + '");' + '\n' +
                 T * 2 + 'port_range_hints[' + pl + '].HintDescriptor =' +
                 '\n' + T * 2)

        cp_hint = 0  # for these ' | ' sake!!
        cp_min = getText(cp_node, 'min').replace('f', '', 1)
        cp_max = getText(cp_node, 'max').replace('f', '', 1)
        cp_default = getText(cp_node, 'default').replace('f', '', 1)

        if ('' != cp_min):
            fc.write(' LADSPA_HINT_BOUNDED_BELOW')
            cp_hint = 1

        if ('' != cp_max):
            if (1 == cp_hint): fc.write(' | LADSPA_HINT_BOUNDED_ABOVE')
            else:
                fc.write(' LADSPA_HINT_BOUNDED_ABOVE')
                cp_hint = 1

        if ('' != cp_default):  # TODO: add default_low and default_high
            if float(cp_default) <= float(cp_min):
                if (1 == cp_hint): fc.write(' | LADSPA_HINT_DEFAULT_MINIMUM')
                else:
                    fc.write(' LADSPA_HINT_DEFAULT_MINIMUM')
                    cp_hint = 1

            elif float(cp_default) >= float(cp_max):
                if (1 == cp_hint): fc.write(' | LADSPA_HINT_DEFAULT_MAXIMUM')
                else:
                    fc.write(' LADSPA_HINT_DEFAULT_MAXIMUM')
                    cp_hint = 1
            else:  # if default is neither 'min' nor 'max', let it be middle range
                if (1 == cp_hint):
                    fc.write(' | LADSPA_HINT_DEFAULT_MIDDLE')
                else:
                    fc.write(' LADSPA_HINT_DEFAULT_MIDDLE')
        else:
            if (1 == cp_hint): fc.write(' | LADSPA_HINT_DEFAULT_NONE')
            else:
                fc.write(' LADSPA_HINT_DEFAULT_NONE')
                cp_hint = 1

        if ('log' == getText(cp_node, 'mapping')):
            if (1 == cp_hint): fc.write(' | LADSPA_HINT_LOGARITHMIC')
            else:
                fc.write(' LADSPA_HINT_LOGARITHMIC')
                cp_hint = 1

        if ('int' == getText(cp_node, 'type')):
            if (1 == cp_hint): fc.write(' | LADSPA_HINT_INTEGER')
            else:
                fc.write(' LADSPA_HINT_INTEGER')
                cp_hint = 1
        fc.write(';' + '\n')

        if ('' != cp_min):
            fc.write(T * 2 + 'port_range_hints[' + pl + '].LowerBound = ' +
                     cp_min + ';' + '\n')
        if ('' != cp_max):
            fc.write(T * 2 + 'port_range_hints[' + pl + '].UpperBound = ' +
                     cp_max + ';' + '\n')
        fc.write('\n' * 2)

    # Write descriptors for audio pins
    for port in audio_ports:
        fc.write(T * 2 + '/* Parameters for PORT_' + port[0] + ' */' + '\n' +
                 T * 2 + 'port_descriptors[PORT_' + port[0].upper() + '] =' +
                 '\n')
        if 'In' == port[1]:
            fc.write(T * 2 + ' LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;' + '\n')
        elif 'Out' == port[1]:
            fc.write(T * 2 + ' LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;' + '\n')

        fc.write(T * 2 + 'port_names[PORT_' + port[0].upper() + '] =' + '\n' +
                 T * 2 + ' strdup("' + port[2] + '");' + '\n' + T * 2 +
                 'port_range_hints[PORT_' + port[0].upper() +
                 '].HintDescriptor = 0;' + '\n' + '\n')

    # Declare the methods
    if (instantiate):
        fc.write(T * 2 + pD + '->instantiate = instantiate' + pluginLabel +
                 ';' + '\n')
    else:
        fc.write(T * 2 + pD + '->instantiate = NULL;' + '\n')
    if (deinstantiate):
        fc.write(T * 2 + pD + '->cleanup = cleanup' + pluginLabel + ';' + '\n')
    else:
        fc.write(T * 2 + pD + '->cleanup = NULL;' + '\n')
    if (activate):
        fc.write(T * 2 + pD + '->activate = activate' + pluginLabel + ';' +
                 '\n')
    else:
        fc.write(T * 2 + pD + '->activate = NULL;' + '\n')
    if (deactivate):
        fc.write(T * 2 + pD + '->deactivate = deactivate' + pluginLabel + ';' +
                 '\n')
    else:
        fc.write(T * 2 + pD + '->deactivate = NULL;' + '\n')
    fc.write(T * 2 + pD + '->connect_port = connectPort' + pluginLabel + ';' +
             '\n' + T * 2 + pD + '->run = run' + pluginLabel + ';' + '\n' +
             T * 2 + pD + '->run_adding = runAdding' + pluginLabel + ';' +
             '\n' + T * 2 + pD + '->set_run_adding_gain = setRunAddingGain' +
             pluginLabel + ';' + '\n')

    fc.write(T + '}' + '\n' + '}' + '\n')

    #----------------------------------------------------------------------------
    # fini
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write(
        '/* _fini() is called automatically when the library is unloaded. */' +
        '\n')
    fc.write('void _fini() {' + '\n' * 2 + ' \t' * 1 + 'int i;' + '\n' +
             ' \t' * 1 + 'if (' + pD + ') {' + '\n' + ' \t' * 2 +
             'free((char *)' + pD + '->Label);' + '\n' + ' \t' * 2 +
             'free((char *)' + pD + '->Name);' + '\n' + ' \t' * 2 +
             'free((char *)' + pD + '->Maker);' + '\n' + ' \t' * 2 +
             'free((char *)' + pD + '->Copyright);' + '\n' + ' \t' * 2 +
             'free((LADSPA_PortDescriptor *)' + pD + '->PortDescriptors);' +
             '\n' + ' \t' * 2 + 'for (i = 0; i < ' + pD + '->PortCount; i++)' +
             '\n' + ' \t' * 3 + 'free((char *)(' + pD + '->PortNames[i]));' +
             '\n' + ' \t' * 2 + 'free((char **)' + pD + '->PortNames);' +
             '\n' + ' \t' * 2 + 'free((LADSPA_PortRangeHint *)' + pD +
             '->PortRangeHints);' + '\n' + ' \t' * 2 + 'free(' + pD + ');' +
             '\n' + ' \t' * 1 + '}' + '\n')

    fc.write('}' + '\n')

    #----------------------------------------------------------------------------
    # close file
    fc.close
    print T + 'done'

    #---------------------------------------------------------------------------
    # MAKFILE
    #---------------------------------------------------------------------------

    print T + 'writing : Makefile'
    fm = file('Makefile', 'w')

    fm.write('''
###############################################################################
# XSPIF: cross(X) Standard PlugIn Framework:
# This makefile is generated automatically by the module "ladspa.py"
# and from the file: ''' + xml_filename + '''
#

###############################################################################
# INSTALLATION DIRECTORIES
#
# Change these if you want to install somewhere else. In particularly
# you may wish to remove the middle "local/" part of each entry.


INSTALL_PLUGINS_DIR	=	/usr/local/lib/ladspa/
INSTALL_INCLUDE_DIR	=	/usr/include/
#INSTALL_BINARY_DIR	=	/usr/local/bin/

###############################################################################
#
# GENERAL
#

NAME		=       ''' + filenamePrefix + '''
INCLUDES	=	-I$(LADSPA_PATH) -I. -I..
LIBRARIES	=	-ldl -lm
CFLAGS		=	$(INCLUDES) -DPD -O3 -Wall -funroll-loops -fPIC -Wno-unused -Wno-parentheses -Wno-switch
CXXFLAGS	=	$(CFLAGS)
SRC		=	$(NAME).ladspa.c
OBJ		=	$(NAME).ladspa.o
PLUGIN		=	$(NAME).ladspa.so
CC		=	cc
CPP		=	c++

###############################################################################
#
# RULES TO BUILD PLUGINS FROM C OR C++ CODE
#
$(PLUGIN):	$(OBJ)
	$(LD) -o $(PLUGIN) $(OBJ) -shared

$(OBJ):	$(SRC)
	$(CC) $(CFLAGS) -o $(OBJ) -c $(SRC)


# For now, all LADSPA plugins generated with XSPIF are in C
# $(PLUGIN):	$(SRC) $(OBJ) ladspa.h
# 	$(CPP) $(CXXFLAGS) -o $*.o -c $*.cpp
# 	$(CPP) -o $*.ladspa.so $*.ladspa.o -shared

###############################################################################
#
# TARGETS
#

install:	$(PLUGIN)
	cp      $(PLUGIN) $(LADSPA_PATH)

targets:	$(PLUGIN)

###############################################################################
#
# UTILITIES
#

clean:
	-rm -f `find . -name "*.o"`
	-rm -f `find .. -name "*~"`
	-rm -f `find .. -name "core*"`

###############################################################################

''')

    fm.close
    print T + 'done'

    return
예제 #14
0
파일: vst.py 프로젝트: vincentgoudard/xspif
def write(plugin,filename_prefix):
    print T+'writing : '+filename_prefix+'.vst.cpp'
    fcpp = file(filename_prefix + '.vst.cpp','w')
    xml_filename  = filename_prefix + ".xspif"

    ######## independent code here ############

    # Variables
    plugId        = getText(plugin,'plugId')
    manufId       = getText(plugin,'manufId')
    maker         = getText(plugin,'maker')
    pluginLabel   = getText(plugin,'label')
    # forces the first letter to upper case becaus it will be used to name the C++ class
    pluginLabel.title(); 
    copyright     = getText(plugin,'copyright')
    comment = getText(plugin,'comment')+'\n'
    pluginCode = getText(plugin,'code')+'\n'
    pluginCaption = getText(plugin,'caption')
 
    params = plugin.getElementsByTagName('param')
    controlouts = plugin.getElementsByTagName('controlout')   
    states = plugin.getElementsByTagName("state")
    pins = plugin.getElementsByTagName("pin")
    callbacks = plugin.getElementsByTagName('callback')

    instantiate   = None
    deinstantiate = None
    process       = None
    processEvents = None
    activate      = None
    deactivate    = None
    
    if callbacks == [] : 
        print T+ "Warning: you haven't implemented any callback"+'\n'
    else :
        for callback in callbacks:
            text = str(getText(callback,'label'))
            if text == 'instantiate':
                instantiate = callback
            if text == 'deinstantiate':
                deinstantiate = callback
            if text == 'activate':
                activate = callback
            if text == 'deactivate':
                deactivate = callback
            if text == 'process':
                process = callback
            if text == 'processEvents':
                print 'XSPIF Warning: callback "processEvents" not implemented in VST for now'
                #processEvents = callback  

    instantiateCode = getText(instantiate,'code')
    deinstantiateCode = getText(deinstantiate,'code')
    activateCode = getText(activate,'code')
    deactivateCode = getText(deactivate,'code')
    processCode = getText(process,'code')

    #----------------------------------------------------------------------------
    # CPP file
    #----------------------------------------------------------------------------
    
    #----------------------------------------------------------------------------
    # file header

    fcpp.write(
        '/****************************************************************\n'
        + 'XSPIF: cross(X) Standard PlugIn Framework: '
        + 'XSPIF to VST\n'
        + T+filename_prefix+'.vst.cpp'+'\n\n'
        + comment
        + ' This file is generated automatically from the file: '+xml_filename+'\n'
        + ' DO NOT EDIT BY HAND'+'\n'
        + T+'plugin ID: '+plugId+'\n'
        + T+'manufacturer ID: '+manufId+'\n'
        + T+'maker: '+maker+'\n'
        + T+'copyright: '+copyright+'\n'
        + ' ***************************************************************/\n'
        + '\n'
        )

    #----------------------------------------------------------------------------
    # includes and independant code

    fcpp.write('#include "audioeffectx.h"\n'
               +'#include <string.h>\n'
               +'\n'
               +'#define XSPIF_GET_SAMPLE_RATE() (sr)'+'\n'
               +'#define XSPIF_GET_VECTOR_SIZE() (vector_size)'+'\n'
               +'#define XSPIF_CONTROLOUT(label, index, value) (controlOut(label,index,value))'+'\n'
               +'\n')

    fcpp.write('// from '+xml_filename+'\n'
               +pluginCode)
    
    #----------------------------------------------------------------------------
    # parameters constants and declaration ...
    if params != []:
        fcpp.write('\n'
                   +'//-------------------------------------------------------------\n'
                   +'// Parameters constant and declarations\n'
                   +'\n'
                   +'const double e = exp(1.0);'+'\n')

        for param in params:
            label   = getText(param,'label')
            caption = getText(param,'caption')
            comment = getText(param,'comment')
            default = getText(param,'default')
            min     = getText(param,'min')
            max     = getText(param,'max')
            mapping = getText(param,'mapping')
            fcpp.write('\n' 
                       +'// '+caption+'\n'
                       +'// '+comment+'\n'
                       +'const float '+label+'Default'+' = '+default+';\n'
                       +'const float '+label+'Min'+' = '+min+';\n'
                       +'const float '+label+'Max'+' = '+max+';\n'
                       +'\n')  
            
        # write params enumeration 
        fcpp.write('enum\n'
                   +'{\n')

        for param in params:            
            label   = getText(param,'label')
            fcpp.write(T+'k'+label+',\n')  
            
        fcpp.write('\n'
                   +T+'kNumParams'+'\n'
                   +'};\n'
                   +'\n')

    #----------------------------------------------------------------------------
    # controlouts
    if controlouts != []:
        fcpp.write('\n'
                   +'//-------------------------------------------------------------\n'
                   +'// control out ranges constant and declarations\n'
                   +'\n')

        for controlout in controlouts:
            label   = getText(controlout,'label')
            caption = getText(controlout,'caption')
            comment = getText(controlout,'comment')
            min     = getText(controlout,'min')
            max     = getText(controlout,'max')
            fcpp.write('\n' 
                       +'// '+caption+'\n'
                       +'// '+comment+'\n'
                       +'const float '+label+'Min'+' = '+min+';\n'
                       +'const float '+label+'Max'+' = '+max+';\n'
                       +'\n')  
            
        # write controlouts enumeration 
        fcpp.write('enum\n'
                   +'{\n')

        for controlout in controlouts:            
            label   = getText(controlout,'label')
            fcpp.write(T+label+',\n')  
            
        fcpp.write('\n'
                   +T+'kNumControlouts'+'\n'
                   +'};\n'
                   +'\n')
            
    #----------------------------------------------------------------------------
    # classes
    
    fcpp.write('\n'
               +'class '+pluginLabel+';\n'
               +'\n')
    
    # PluginProgram classdeclaration
    fcpp.write('//-------------------------------------------------------------\n'
               +'//'+pluginLabel+'Program'+'\n'
               +'\n'
               +'class '+pluginLabel+'Program'+'\n'
               +'{'+'\n'
               +'friend class '+pluginLabel+';'+'\n'
               +'public:'+'\n'
               +T+pluginLabel+'Program();'+'\n'
               +T+'~'+pluginLabel+'Program() {}'+'\n'
               +'private:'+'\n')

    if params != []:
        for param in params:
            label   = getText(param,'label')
            fcpp.write(T+'float f'+label+'; // normalized param'+'\n')  
            
    fcpp.write(T+'char name[24];'+'\n'
                   +'};'+'\n'
                   +'\n')

    # Plugin classdeclaration
    fcpp.write(
"""
//-------------------------------------------------------------
//"""+pluginLabel+"""

class """+pluginLabel+""" : public AudioEffectX
{
public:
  """+pluginLabel+"""(audioMasterCallback audioMaster);
  ~"""+pluginLabel+"""();

  virtual void process(float **inputs, float **outputs, long sampleframes);
  virtual void processReplacing(float **inputs, float **outputs, long sampleFrames);
  virtual void setProgram(long program);
  virtual void setProgramName(char *name);
  virtual void getProgramName(char *name);
  virtual void setParameter(long index, float value);
  virtual float getParameter(long index);
  virtual void getParameterDisplay(long index, char *text);
  virtual void getParameterName(long index, char *text);
  virtual void getParameterLabel(long index, char *label);
  virtual bool getEffectName(char *name);
  virtual bool getVendorString(char *text);
  virtual void resume();
  virtual long canDo(char *text);
  virtual void suspend();

private:
  """+pluginLabel+"""Program *programs;

""")
    if controlouts != []:
        fcpp.write('void '+pluginLabel+'::controlout(long label, long index, float value)'+'\n')
        
    if params != []:
        fcpp.write(T+'// <parameters>'+'\n')
        for param in params:
            label   = getText(param,'label')
            type    = getText(param,'type')
            default = label+'Default'
            min     = label+'Min'
            max     = label+'Max'
            fcpp.write(T+type+' '+label+'; // param'+'\n'
                       +T+'float f'+label+'; // normalized param'+'\n'
                       +'\n')  

        fcpp.write(T+'// </parameters>'+'\n'
                       +'\n')

    # macros
    fcpp.write(T+'float sr;'+'\n'
               +T+'long vector_size;'+'\n'
               +'\n')

    # states
    if states != []:
        fcpp.write(T+'// states'+'\n')
        for state in states:
            label = getText(state,'label')
            type  = getText(state,'type')
            fcpp.write(T+type+' '+label+';'+'\n')
            
    fcpp.write('};'+'\n'
               +'\n')

    fcpp.write("""
//----------------------------------------------------------------------------
// IMPLEMENTATION 
//----------------------------------------------------------------------------

""")

    #----------------------------------------------------------------------------
    # includes 
    
    fcpp.write('#include <stdio.h>\n'
               +'#include <string.h>\n')

    #----------------------------------------------------------------------------
    # Topology

    numInputs = numOutputs = 0
    
    for pin in pins:
        dir      = getText(pin,'dir')
        channels = int(str(getText(pin,'channels')))
        if dir == 'In':
            numInputs += channels
        elif dir == 'Out':
            numOutputs += channels

    numInputs  = str(numInputs)
    numOutputs = str(numOutputs)

    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'// Config'+'\n'
               +'#define NUM_INPUTS '+numInputs+'\n'
               +'#define NUM_OUTPUTS '+numOutputs+'\n'
               +'#define NUM_PRESETS '+'4'+'\n'
               +'//infos'+'\n'
               +'#define ID '+plugId+'\n'
               +'#define NAME "'+pluginCaption+'"'+'\n'
               +'#define VENDOR "'+maker+'"'+'\n'
               +'\n'
               +'#define CAN_PROCESS_REPLACING true'+'\n'
               +'#define CAN_MONO true'+'\n'
               +'\n'
               +'\n'
               )
    
    #----------------------------------------------------------------------------
    # Presets class

    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'// '+pluginLabel+'Program class implementation'+'\n'
               +'\n'
               +pluginLabel+'Program::'+pluginLabel+'Program()'+'\n'
               +'{'+'\n')
    
    if params != [] :
        for param in params:
            label   = getText(param,'label')
            default = label+'Default'
            min     = label+'Min'
            max     = label+'Max'
            mapping = getText(param,'mapping')
            type    = getText(param,'type')
            
            if mapping == 'lin':
                fcpp.write(T+'f'+label+' = ('+default+'-'+min+')/('+max+'-'+min+');'+'\n')
            elif mapping == 'log':
                # external->internal is logarithmic
                #   ( log(v)-log(min) ) / ( log(max)-log(min) )
                # = ( log(v/min) / ( log(max/min) )
                fcpp.write(T+'f'+label+' = log('+default+'/'+min+')/(log('+max+'/'+min+'));'+'\n')
            
            
    fcpp.write(T+'\n'
               +T+'strcpy(name,"'+pluginCaption+'");'+'\n'
               +'}'+'\n'
               +'\n'
               )
    #----------------------------------------------------------------------------
    # Plugin Class

    #----------------------------------------------------------------------------
    # Plugin Constructor
    
    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'// '+pluginLabel+' class implementation'+'\n'
               +'\n'
               +pluginLabel+'::'+pluginLabel+'(audioMasterCallback audioMaster)'+'\n'
               +': AudioEffectX(audioMaster, NUM_PRESETS, kNumParams)'+'\n'
               +'{'+'\n'
               +T+'programs = new '+pluginLabel+'Program[numPrograms];'+'\n'
               +T+'\n'
               +T+'sr = getSampleRate();'+'\n'
               +T+'if(sr<0.f) sr = 44100.f;'+'\n'
               +'\n'
               )
    
    if params != []:
        for param in params:
            label   = getText(param,"label")
            default = label+'Default'
            min     = label+'Min'
            max     = label+'Max'
            mapping = getText(param,'mapping')
            
            if mapping == 'lin':
                fcpp.write(T+'f'+label+' = ('+default+'-'+min+')/('+max+'-'+min+');'+'\n'
                           +T+label+' = '+default+';'+'\n')
            elif mapping == 'log':
                # external->internal is logarithmic
                #   ( log(v)-log(min) ) / ( log(max)-log(min) )
                # = ( log(v/min) / ( log(max/min) )
                fcpp.write(T+'f'+label+' = log('+default+'/'+min+')/(log('+max+'/'+min+'));'+'\n')
       
    fcpp.write('\n'
               +T+'// instantiate callback'+'\n'
               +T+instantiateCode+'\n'
               +'\n')

    fcpp.write(
"""
  if(programs) setProgram(0);

  setUniqueID(ID);
  setNumInputs(NUM_INPUTS);
  setNumOutputs(NUM_OUTPUTS);
  canProcessReplacing(CAN_PROCESS_REPLACING);
  canMono(CAN_MONO);
}

""")

    #----------------------------------------------------------------------------
    # Plugin Destructor

    fcpp.write('//-------------------------------------------------------------'+'\n'
               +pluginLabel+'::~'+pluginLabel+'()'+'\n'
               +'{'+'\n'
               +T+'if(programs)'+'\n'
               +T*2+'delete[] programs;'+'\n')
    
    fcpp.write('\n'
               +T+'// deinstantiate callback'+'\n'
               +T+deinstantiateCode+'\n'
               +'\n')

    fcpp.write('}'+'\n'
               +'\n')

    #----------------------------------------------------------------------------
    # Plugin infos
    if controlouts != []:
        fcpp.write('//-------------------------------------------------------------'+'\n'
                   +'// control out'+'\n'
                   +'\n'
                   +'void '+pluginLabel+'::controlout(long label, long index, float value)'+'\n'
                   +'{'+'\n'
                   +T+'char out=0;'+'\n'
                   +T+'char cc=0;'+'\n'
                   +T+'switch(label)'+'\n'
                   +T+'{'+'\n')

    
        i = 38 # first MIDI CC that will be used fo control out
        for controlout in controlouts:
            label = getText(controlout,'label')
            max   = label+'Max'
            min   = label+'Min'
            mapping = getText(controlout,'mapping')
            controloutCode = getText(param,'code')
            
            if i >127:
                print 'warning too much controlouts CC numbers exceed 127'
                return

            fcpp.write(T*2+'case '+label+' :'+'\n' 
                       +T*3+'cc = '+str(i)+';'+'\n')
            i = i+1
                        
            if mapping == 'lin':
                fcpp.write(T*3+'out = 127*((value-'+min+')/('+max+'-'+min+'));'+'\n')            

            elif mapping == 'log':
                #
                fcpp.write(T*3+'out = 127*(log(value/'+min+')/log('+max+'/'+min+'));'+'\n')
                        
        fcpp.write(
            '\n'
            +T*2+'default: return;'+'\n'
            +T+'}'+'\n'
            +'\n'
            +T+'if(index>vector_size)'+'\n'
            +T*2+'index = vector_size;'+'\n'
            +'\n' 
        
            +T+'VstMidiEvent vstEvent;'+'\n'  
            +T+'VstEvents vstEvents; '+'\n' 
            +T+'vstEvents.numEvents =1; '+'\n' 
            +T+'vstEvents.reserved = 0; '+'\n' 
            +T+'vstEvents.events[0] = (VstEvent*)(&vstEvent); '+'\n' 
            +T+'vstEvents.events[1]= NULL; '+'\n'
            +'\n' 
        
            +T+'memset(&vstEvent, 0, sizeof(vstEvent));'+'\n' 
            +T+'vstEvent.type = kVstMidiType;'+'\n' 
            +T+'vstEvent.byteSize = 24;'+'\n' 
                
            +T+'vstEvent.deltaFrames = index; '+'\n' 
            +T+'vstEvent.midiData[0]=0xb0; // tells it sends midi CC'+'\n' 
            +T+'vstEvent.midiData[1]=cc; '+'\n' 
            +T+'vstEvent.midiData[2]=out; '+'\n' 
            +T+'((AudioEffectX *)this)->sendVstEventsToHost(&vstEvents);'+'\n' 
            +'}'+'\n'
            )

    #----------------------------------------------------------------------------
    # Plugin infos

    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'// '+pluginLabel+' information'+'\n'
               +'\n'
               +'bool '+pluginLabel+'::getEffectName(char *name) {'+'\n'
               +T+'strcpy(name, NAME); // name max 32 char'+'\n'
               +T+'return true;}'+'\n'
               +'\n'
               +'bool '+pluginLabel+'::getVendorString(char *text) {'+'\n'
               +T+'strcpy(text, VENDOR); // vendor max 64 char'+'\n'
               +T+'return true;}'+'\n'
               +'\n')

    fcpp.write('long '+pluginLabel+'::canDo(char* text)'+'\n'
               +'\t'+'{'+'\n' )

    if controlouts != []:
        fcpp.write(
            T+'if (!strcmp (text, "sendVstMidiEvent")) return 1;'+'\n'
            +T+'if (!strcmp (text, "sendVstEvents")) return 1;'+'\n')

    fcpp.write(
        T+'//if (!strcmp (text, "receiveVstEvents")) return 1;'+'\n'
        +T+'//if (!strcmp (text, "receiveVstMidiEvent")) return 1;'+'\n'
        +T+"return 0; // explicitly can't do; 0 => don't know"+'\n'
        +'}'+'\n'
        )
    
    #----------------------------------------------------------------------------
    # Plugin suspend and resume
    
    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'void '+pluginLabel+'::resume()'+'\n'
               +'{'+'\n')
    
    if controlouts != []:
        fcpp.write(T+'wantEvents();'+'\n')

    fcpp.write(T+activateCode+'\n'
               +'}'+'\n'
               +'\n'
               +'void '+pluginLabel+'::suspend()'+'\n'
               +'{'+'\n'
               +T+deactivateCode+'\n'
               +'}'+'\n'
               +'\n')

    
    #----------------------------------------------------------------------------
    # Params handling

    #  setProgram
    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'void '+pluginLabel+'::setProgram(long program)'+'\n'
               +'{'+'\n'
               +T+pluginLabel+'Program *ap = &programs[program];'+'\n'
               +'\n'
               +T+'curProgram = program;'+'\n')

    if params != []:
        for param in params:
            label = getText(param,"label")
            fcpp.write(T+'setParameter(k'+label+', ap->f'+label+');'+'\n')
            
    fcpp.write('}'+'\n'
               +'\n')

    #setProgramName
    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'void '+pluginLabel+'::setProgramName(char *name)'+'\n'
               +'{'+'\n'
               +T+'strcpy(programs[curProgram].name, name);'+'\n'
               +'}'+'\n'
               +'\n')

    #getProgramName
    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'void '+pluginLabel+'::getProgramName(char *name)'+'\n'
               +'{'+'\n'
               +T+'strcpy(name, programs[curProgram].name);'+'\n'
               +'}'+'\n'
               +'\n')

    #setParameter
    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'void '+pluginLabel+'::setParameter(long index, float value)'+'\n'
               +'{'+'\n'
               +T+pluginLabel+'Program *ap = &programs[curProgram];'+'\n'
               +'\n'
               +T+'switch(index)'+'\n'
               +T+'{'+'\n')

    if params != []:
        for param in params:
            label = getText(param,'label')
            max   = label+'Max'
            min   = label+'Min'
            mapping = getText(param,'mapping')
            type = getText(param,'type')
            paramCode = getText(param,'code')
            
            fcpp.write(T*2+'case k'+label+' :'+'\n' 
                       +T*3+'f'+label+' = ap->f'+label+' = value;'+'\n')
            
            if mapping == 'lin':
                fcpp.write(T*3+label+' = ('+type+')(value*('+max+'-'+min+')+'+min+');'+'\n')            

            elif mapping == 'log':
                #    normalized = (log(param/min)) / (log(max/min))
                # => log(param/min) = normalized * log(max/min)
                # => param = min * (max/min)^normalized
                fcpp.write(T*3+label+' = ('+type+')'+min+'*pow('+max+'/'+min+',f'+label+');'+'\n')

            fcpp.write(paramCode
                       +T*2+'break;'+'\n'
                       +'\n')
               
    fcpp.write(T*3+'default: break;'+'\n'
               +T+'}'+'\n'
               +'}'+'\n'
               +'\n')
    
    #getParameter
    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'float '+pluginLabel+'::getParameter(long index)'+'\n'
               +'{'+'\n'
               +T+'float v = 0.f;'+'\n'
               +'\n'
               +T+'switch(index)'+'\n'
               +T+'{'+'\n')

    if params != []:
        for param in params:
            label = getText(param,'label')
            fcpp.write(T*2+'case k'+label+' : v = f'+label+'; break;'+'\n')
            
               
    fcpp.write(T*2+'default: break;'+'\n'
               +T+'}'+'\n'
               +T+'return v;'+'\n'
               +'}'+'\n'
               +'\n')

    #getParameterName
    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'void '+pluginLabel+'::getParameterName(long index, char *label)'+'\n'
               +'{'+'\n'
               +T+'switch(index)'+'\n'
               +T+'{'+'\n')

    if params != []:
        for param in params:
            label   = getText(param,'label')
            caption = getText(param,'caption')
            fcpp.write(T*2+'case k'+label+' : strcpy(label, "'+caption+'"); break;'+'\n')
                   
               
    fcpp.write(T*2+'default: break;'+'\n'
               +T+'}'+'\n'
               +'}'+'\n'
               +'\n')
    
    #getParameterDisplay
    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'void '+pluginLabel+'::getParameterDisplay(long index, char *text)'+'\n'
               +'{'+'\n'
               +T+'switch(index)'+'\n'
               +T+'{'+'\n')

    if params != []:
        for param in params:
            label   = getText(param,'label')
            type    = getText(param,'type')
            if type == 'float':
                fcpp.write(T*2+'case k'+label+' : float2string('+label+', text); break;'+'\n')
            elif type == 'int':
                fcpp.write(T*2+'case k'+label+' : long2string('+label+', text); break;'+'\n')
                                           
    fcpp.write(T*2+'default: break;'+'\n'
               +T+'}'+'\n'
               +'}'+'\n'
               +'\n')

    #getParameterLabel
    fcpp.write('//-------------------------------------------------------------'+'\n'
               +'void '+pluginLabel+'::getParameterLabel(long index, char *label)'+'\n'
               +'{'+'\n'
               +T+'switch(index)'+'\n'
               +T+'{'+'\n')

    if params != []:
        for param in params:
            label   = getText(param,'label')
            unit   = getText(param,'unit')
            fcpp.write(T*2+'case k'+label+' : strcpy(label, "'+unit+'"); break;'+'\n')
                   
               
    fcpp.write(T*2+'default: break;'+'\n'
               +T+'}'+'\n'
               +'}'+'\n'
               +'\n')    

    #----------------------------------------------------------------------------
    # processing
    # process
    fcpp.write('#define XSPIF_WRITE_SAMPLE(dest,index,source) ((dest)[(index)] += (source))'+'\n'
               +'\n'
               +'//-------------------------------------------------------------'+'\n'
               +'void '+pluginLabel+'::process(float **inputs, float **outputs, long sampleframes)'+'\n'
               +'{'+'\n')

    i=0
    for pin in pins:
        dir = getText(pin,'dir')
        if dir == 'In':            
            label = getText(pin,'label')
            channels = int(str(getText(pin,'channels')))
            for j in range(0,channels):
                i = i+1
                fcpp.write(T+'float *'+label+str(j+1)+' = inputs['+str(i-1)+'];'+'\n')
        
    i=0
    for pin in pins:
        dir = getText(pin,'dir')
        if dir == 'Out':
            label = getText(pin,'label')
            channels = int(str(getText(pin,'channels')))
            for j in range(0,channels):
                i = i + 1
                fcpp.write(T+'float *'+label+str(j+1)+' = outputs['+str(i-1)+'];'+'\n')
               
               
    fcpp.write(T+'vector_size = sampleframes;'+'\n'
               +'\n'
               +processCode+'\n'
               +'}'+'\n'
               +'\n'
               +'#undef XSPIF_WRITE_SAMPLE'+'\n'
               +'\n')

    # processReplacing
    fcpp.write('#define XSPIF_WRITE_SAMPLE(dest,index,source) ((dest)[(index)] = (source))'+'\n'
               +'\n'
               +'//-------------------------------------------------------------'+'\n'
               +'void '+pluginLabel+'::processReplacing(float **inputs, float **outputs, long sampleframes)'+'\n'
               +'{'+'\n')

    i=0
    for pin in pins:
        dir = getText(pin,'dir')
        if dir == 'In':
            label = getText(pin,'label')
            channels = int(str(getText(pin,'channels')))
            for j in range(0,channels):
                i = i+1
                fcpp.write(T+'float *'+label+str(j+1)+' = inputs['+str(i-1)+'];'+'\n')
        
    i=0
    for pin in pins:
        dir = getText(pin,'dir')
        if dir == 'Out':
            label = getText(pin,'label')
            channels = int(str(getText(pin,'channels')))
            for j in range(0,channels):
                i = i+1
                fcpp.write(T+'float *'+label+str(j+1)+' = outputs['+str(i-1)+'];'+'\n')
               
    fcpp.write(T+'vector_size = sampleframes;'+'\n'
               +'\n'
               +processCode+'\n'
               +'}'+'\n'
               +'\n'
               +'#undef XSPIF_WRITE_SAMPLE'+'\n'
               +'\n')
    
    #----------------------------------------------------------------------------
    # main entry point
    
    fcpp.write(
'''
//-------------------------------------------------------------
// main entry point
//-------------------------------------------------------------
bool oome = false;
#if MAC
#pragma export on
#endif

// prototype of the export function main
#if BEOS
#define main main_plugin
extern "C" __declspec(dllexport) AEffect *main_plugin (audioMasterCallback audioMaster);

#elif MACX
#define main main_macho
extern "C" AEffect *main_macho (audioMasterCallback audioMaster);

#else
AEffect *main (audioMasterCallback audioMaster);
#endif

AEffect *main (audioMasterCallback audioMaster)
{
  // get vst version
  if (!audioMaster (0, audioMasterVersion, 0, 0, 0, 0))
    return 0;  // old version

  AudioEffect* effect = new '''+pluginLabel+'''(audioMaster);
  if (!effect)
    return 0;
  if (oome)
  {
    delete effect;
    return 0;
  }
  return effect->getAeffect ();
}

#if MAC
#pragma export off
#endif

#if WIN32
#include <windows.h>
void* hInstance;
BOOL WINAPI DllMain (HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved)
{
  hInstance = hInst;
  return 1;
}
#endif
''')

    fcpp.close
    print T+'done'    

    # def file for windows: exports the plugins entry point
    print T+'writing : '+filename_prefix+'.vst.def'
    fdef = file(filename_prefix + '.vst.def','w')

    fdef.write('LIBRARY	'+pluginLabel+'\n'
               +"DESCRIPTION '"+pluginCaption+"'"+'\n'
               +'EXPORTS main'+'\n')
    
    fdef.close
    print T+'done'    
    
    return
예제 #15
0
def write(plugin, filename_prefix):
    print T + 'writing : ' + filename_prefix + '.vst.cpp'
    fcpp = file(filename_prefix + '.vst.cpp', 'w')
    xml_filename = filename_prefix + ".xspif"

    ######## independent code here ############

    # Variables
    plugId = getText(plugin, 'plugId')
    manufId = getText(plugin, 'manufId')
    maker = getText(plugin, 'maker')
    pluginLabel = getText(plugin, 'label')
    # forces the first letter to upper case becaus it will be used to name the C++ class
    pluginLabel.title()
    copyright = getText(plugin, 'copyright')
    comment = getText(plugin, 'comment') + '\n'
    pluginCode = getText(plugin, 'code') + '\n'
    pluginCaption = getText(plugin, 'caption')

    params = plugin.getElementsByTagName('param')
    controlouts = plugin.getElementsByTagName('controlout')
    states = plugin.getElementsByTagName("state")
    pins = plugin.getElementsByTagName("pin")
    callbacks = plugin.getElementsByTagName('callback')

    instantiate = None
    deinstantiate = None
    process = None
    processEvents = None
    activate = None
    deactivate = None

    if callbacks == []:
        print T + "Warning: you haven't implemented any callback" + '\n'
    else:
        for callback in callbacks:
            text = str(getText(callback, 'label'))
            if text == 'instantiate':
                instantiate = callback
            if text == 'deinstantiate':
                deinstantiate = callback
            if text == 'activate':
                activate = callback
            if text == 'deactivate':
                deactivate = callback
            if text == 'process':
                process = callback
            if text == 'processEvents':
                print 'XSPIF Warning: callback "processEvents" not implemented in VST for now'
                #processEvents = callback

    instantiateCode = getText(instantiate, 'code')
    deinstantiateCode = getText(deinstantiate, 'code')
    activateCode = getText(activate, 'code')
    deactivateCode = getText(deactivate, 'code')
    processCode = getText(process, 'code')

    #----------------------------------------------------------------------------
    # CPP file
    #----------------------------------------------------------------------------

    #----------------------------------------------------------------------------
    # file header

    fcpp.write(
        '/****************************************************************\n' +
        'XSPIF: cross(X) Standard PlugIn Framework: ' + 'XSPIF to VST\n' + T +
        filename_prefix + '.vst.cpp' + '\n\n' + comment +
        ' This file is generated automatically from the file: ' +
        xml_filename + '\n' + ' DO NOT EDIT BY HAND' + '\n' + T +
        'plugin ID: ' + plugId + '\n' + T + 'manufacturer ID: ' + manufId +
        '\n' + T + 'maker: ' + maker + '\n' + T + 'copyright: ' + copyright +
        '\n' +
        ' ***************************************************************/\n' +
        '\n')

    #----------------------------------------------------------------------------
    # includes and independant code

    fcpp.write(
        '#include "audioeffectx.h"\n' + '#include <string.h>\n' + '\n' +
        '#define XSPIF_GET_SAMPLE_RATE() (sr)' + '\n' +
        '#define XSPIF_GET_VECTOR_SIZE() (vector_size)' + '\n' +
        '#define XSPIF_CONTROLOUT(label, index, value) (controlOut(label,index,value))'
        + '\n' + '\n')

    fcpp.write('// from ' + xml_filename + '\n' + pluginCode)

    #----------------------------------------------------------------------------
    # parameters constants and declaration ...
    if params != []:
        fcpp.write(
            '\n' +
            '//-------------------------------------------------------------\n'
            + '// Parameters constant and declarations\n' + '\n' +
            'const double e = exp(1.0);' + '\n')

        for param in params:
            label = getText(param, 'label')
            caption = getText(param, 'caption')
            comment = getText(param, 'comment')
            default = getText(param, 'default')
            min = getText(param, 'min')
            max = getText(param, 'max')
            mapping = getText(param, 'mapping')
            fcpp.write('\n' + '// ' + caption + '\n' + '// ' + comment + '\n' +
                       'const float ' + label + 'Default' + ' = ' + default +
                       ';\n' + 'const float ' + label + 'Min' + ' = ' + min +
                       ';\n' + 'const float ' + label + 'Max' + ' = ' + max +
                       ';\n' + '\n')

        # write params enumeration
        fcpp.write('enum\n' + '{\n')

        for param in params:
            label = getText(param, 'label')
            fcpp.write(T + 'k' + label + ',\n')

        fcpp.write('\n' + T + 'kNumParams' + '\n' + '};\n' + '\n')

    #----------------------------------------------------------------------------
    # controlouts
    if controlouts != []:
        fcpp.write(
            '\n' +
            '//-------------------------------------------------------------\n'
            + '// control out ranges constant and declarations\n' + '\n')

        for controlout in controlouts:
            label = getText(controlout, 'label')
            caption = getText(controlout, 'caption')
            comment = getText(controlout, 'comment')
            min = getText(controlout, 'min')
            max = getText(controlout, 'max')
            fcpp.write('\n' + '// ' + caption + '\n' + '// ' + comment + '\n' +
                       'const float ' + label + 'Min' + ' = ' + min + ';\n' +
                       'const float ' + label + 'Max' + ' = ' + max + ';\n' +
                       '\n')

        # write controlouts enumeration
        fcpp.write('enum\n' + '{\n')

        for controlout in controlouts:
            label = getText(controlout, 'label')
            fcpp.write(T + label + ',\n')

        fcpp.write('\n' + T + 'kNumControlouts' + '\n' + '};\n' + '\n')

    #----------------------------------------------------------------------------
    # classes

    fcpp.write('\n' + 'class ' + pluginLabel + ';\n' + '\n')

    # PluginProgram classdeclaration
    fcpp.write(
        '//-------------------------------------------------------------\n' +
        '//' + pluginLabel + 'Program' + '\n' + '\n' + 'class ' + pluginLabel +
        'Program' + '\n' + '{' + '\n' + 'friend class ' + pluginLabel + ';' +
        '\n' + 'public:' + '\n' + T + pluginLabel + 'Program();' + '\n' + T +
        '~' + pluginLabel + 'Program() {}' + '\n' + 'private:' + '\n')

    if params != []:
        for param in params:
            label = getText(param, 'label')
            fcpp.write(T + 'float f' + label + '; // normalized param' + '\n')

    fcpp.write(T + 'char name[24];' + '\n' + '};' + '\n' + '\n')

    # Plugin classdeclaration
    fcpp.write("""
//-------------------------------------------------------------
//""" + pluginLabel + """

class """ + pluginLabel + """ : public AudioEffectX
{
public:
  """ + pluginLabel + """(audioMasterCallback audioMaster);
  ~""" + pluginLabel + """();

  virtual void process(float **inputs, float **outputs, long sampleframes);
  virtual void processReplacing(float **inputs, float **outputs, long sampleFrames);
  virtual void setProgram(long program);
  virtual void setProgramName(char *name);
  virtual void getProgramName(char *name);
  virtual void setParameter(long index, float value);
  virtual float getParameter(long index);
  virtual void getParameterDisplay(long index, char *text);
  virtual void getParameterName(long index, char *text);
  virtual void getParameterLabel(long index, char *label);
  virtual bool getEffectName(char *name);
  virtual bool getVendorString(char *text);
  virtual void resume();
  virtual long canDo(char *text);
  virtual void suspend();

private:
  """ + pluginLabel + """Program *programs;

""")
    if controlouts != []:
        fcpp.write('void ' + pluginLabel +
                   '::controlout(long label, long index, float value)' + '\n')

    if params != []:
        fcpp.write(T + '// <parameters>' + '\n')
        for param in params:
            label = getText(param, 'label')
            type = getText(param, 'type')
            default = label + 'Default'
            min = label + 'Min'
            max = label + 'Max'
            fcpp.write(T + type + ' ' + label + '; // param' + '\n' + T +
                       'float f' + label + '; // normalized param' + '\n' +
                       '\n')

        fcpp.write(T + '// </parameters>' + '\n' + '\n')

    # macros
    fcpp.write(T + 'float sr;' + '\n' + T + 'long vector_size;' + '\n' + '\n')

    # states
    if states != []:
        fcpp.write(T + '// states' + '\n')
        for state in states:
            label = getText(state, 'label')
            type = getText(state, 'type')
            fcpp.write(T + type + ' ' + label + ';' + '\n')

    fcpp.write('};' + '\n' + '\n')

    fcpp.write("""
//----------------------------------------------------------------------------
// IMPLEMENTATION 
//----------------------------------------------------------------------------

""")

    #----------------------------------------------------------------------------
    # includes

    fcpp.write('#include <stdio.h>\n' + '#include <string.h>\n')

    #----------------------------------------------------------------------------
    # Topology

    numInputs = numOutputs = 0

    for pin in pins:
        dir = getText(pin, 'dir')
        channels = int(str(getText(pin, 'channels')))
        if dir == 'In':
            numInputs += channels
        elif dir == 'Out':
            numOutputs += channels

    numInputs = str(numInputs)
    numOutputs = str(numOutputs)

    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + '// Config' + '\n' + '#define NUM_INPUTS ' + numInputs + '\n' +
        '#define NUM_OUTPUTS ' + numOutputs + '\n' + '#define NUM_PRESETS ' +
        '4' + '\n' + '//infos' + '\n' + '#define ID ' + plugId + '\n' +
        '#define NAME "' + pluginCaption + '"' + '\n' + '#define VENDOR "' +
        maker + '"' + '\n' + '\n' + '#define CAN_PROCESS_REPLACING true' +
        '\n' + '#define CAN_MONO true' + '\n' + '\n' + '\n')

    #----------------------------------------------------------------------------
    # Presets class

    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + '// ' + pluginLabel + 'Program class implementation' + '\n' +
        '\n' + pluginLabel + 'Program::' + pluginLabel + 'Program()' + '\n' +
        '{' + '\n')

    if params != []:
        for param in params:
            label = getText(param, 'label')
            default = label + 'Default'
            min = label + 'Min'
            max = label + 'Max'
            mapping = getText(param, 'mapping')
            type = getText(param, 'type')

            if mapping == 'lin':
                fcpp.write(T + 'f' + label + ' = (' + default + '-' + min +
                           ')/(' + max + '-' + min + ');' + '\n')
            elif mapping == 'log':
                # external->internal is logarithmic
                #   ( log(v)-log(min) ) / ( log(max)-log(min) )
                # = ( log(v/min) / ( log(max/min) )
                fcpp.write(T + 'f' + label + ' = log(' + default + '/' + min +
                           ')/(log(' + max + '/' + min + '));' + '\n')

    fcpp.write(T + '\n' + T + 'strcpy(name,"' + pluginCaption + '");' + '\n' +
               '}' + '\n' + '\n')
    #----------------------------------------------------------------------------
    # Plugin Class

    #----------------------------------------------------------------------------
    # Plugin Constructor

    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + '// ' + pluginLabel + ' class implementation' + '\n' + '\n' +
        pluginLabel + '::' + pluginLabel +
        '(audioMasterCallback audioMaster)' + '\n' +
        ': AudioEffectX(audioMaster, NUM_PRESETS, kNumParams)' + '\n' + '{' +
        '\n' + T + 'programs = new ' + pluginLabel + 'Program[numPrograms];' +
        '\n' + T + '\n' + T + 'sr = getSampleRate();' + '\n' + T +
        'if(sr<0.f) sr = 44100.f;' + '\n' + '\n')

    if params != []:
        for param in params:
            label = getText(param, "label")
            default = label + 'Default'
            min = label + 'Min'
            max = label + 'Max'
            mapping = getText(param, 'mapping')

            if mapping == 'lin':
                fcpp.write(T + 'f' + label + ' = (' + default + '-' + min +
                           ')/(' + max + '-' + min + ');' + '\n' + T + label +
                           ' = ' + default + ';' + '\n')
            elif mapping == 'log':
                # external->internal is logarithmic
                #   ( log(v)-log(min) ) / ( log(max)-log(min) )
                # = ( log(v/min) / ( log(max/min) )
                fcpp.write(T + 'f' + label + ' = log(' + default + '/' + min +
                           ')/(log(' + max + '/' + min + '));' + '\n')

    fcpp.write('\n' + T + '// instantiate callback' + '\n' + T +
               instantiateCode + '\n' + '\n')

    fcpp.write("""
  if(programs) setProgram(0);

  setUniqueID(ID);
  setNumInputs(NUM_INPUTS);
  setNumOutputs(NUM_OUTPUTS);
  canProcessReplacing(CAN_PROCESS_REPLACING);
  canMono(CAN_MONO);
}

""")

    #----------------------------------------------------------------------------
    # Plugin Destructor

    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + pluginLabel + '::~' + pluginLabel + '()' + '\n' + '{' + '\n' +
        T + 'if(programs)' + '\n' + T * 2 + 'delete[] programs;' + '\n')

    fcpp.write('\n' + T + '// deinstantiate callback' + '\n' + T +
               deinstantiateCode + '\n' + '\n')

    fcpp.write('}' + '\n' + '\n')

    #----------------------------------------------------------------------------
    # Plugin infos
    if controlouts != []:
        fcpp.write(
            '//-------------------------------------------------------------' +
            '\n' + '// control out' + '\n' + '\n' + 'void ' + pluginLabel +
            '::controlout(long label, long index, float value)' + '\n' + '{' +
            '\n' + T + 'char out=0;' + '\n' + T + 'char cc=0;' + '\n' + T +
            'switch(label)' + '\n' + T + '{' + '\n')

        i = 38  # first MIDI CC that will be used fo control out
        for controlout in controlouts:
            label = getText(controlout, 'label')
            max = label + 'Max'
            min = label + 'Min'
            mapping = getText(controlout, 'mapping')
            controloutCode = getText(param, 'code')

            if i > 127:
                print 'warning too much controlouts CC numbers exceed 127'
                return

            fcpp.write(T * 2 + 'case ' + label + ' :' + '\n' + T * 3 +
                       'cc = ' + str(i) + ';' + '\n')
            i = i + 1

            if mapping == 'lin':
                fcpp.write(T * 3 + 'out = 127*((value-' + min + ')/(' + max +
                           '-' + min + '));' + '\n')

            elif mapping == 'log':
                #
                fcpp.write(T * 3 + 'out = 127*(log(value/' + min + ')/log(' +
                           max + '/' + min + '));' + '\n')

        fcpp.write('\n' + T * 2 + 'default: return;' + '\n' + T + '}' + '\n' +
                   '\n' + T + 'if(index>vector_size)' + '\n' + T * 2 +
                   'index = vector_size;' + '\n' + '\n' + T +
                   'VstMidiEvent vstEvent;' + '\n' + T +
                   'VstEvents vstEvents; ' + '\n' + T +
                   'vstEvents.numEvents =1; ' + '\n' + T +
                   'vstEvents.reserved = 0; ' + '\n' + T +
                   'vstEvents.events[0] = (VstEvent*)(&vstEvent); ' + '\n' +
                   T + 'vstEvents.events[1]= NULL; ' + '\n' + '\n' + T +
                   'memset(&vstEvent, 0, sizeof(vstEvent));' + '\n' + T +
                   'vstEvent.type = kVstMidiType;' + '\n' + T +
                   'vstEvent.byteSize = 24;' + '\n' + T +
                   'vstEvent.deltaFrames = index; ' + '\n' + T +
                   'vstEvent.midiData[0]=0xb0; // tells it sends midi CC' +
                   '\n' + T + 'vstEvent.midiData[1]=cc; ' + '\n' + T +
                   'vstEvent.midiData[2]=out; ' + '\n' + T +
                   '((AudioEffectX *)this)->sendVstEventsToHost(&vstEvents);' +
                   '\n' + '}' + '\n')

    #----------------------------------------------------------------------------
    # Plugin infos

    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + '// ' + pluginLabel + ' information' + '\n' + '\n' + 'bool ' +
        pluginLabel + '::getEffectName(char *name) {' + '\n' + T +
        'strcpy(name, NAME); // name max 32 char' + '\n' + T +
        'return true;}' + '\n' + '\n' + 'bool ' + pluginLabel +
        '::getVendorString(char *text) {' + '\n' + T +
        'strcpy(text, VENDOR); // vendor max 64 char' + '\n' + T +
        'return true;}' + '\n' + '\n')

    fcpp.write('long ' + pluginLabel + '::canDo(char* text)' + '\n' + '\t' +
               '{' + '\n')

    if controlouts != []:
        fcpp.write(T + 'if (!strcmp (text, "sendVstMidiEvent")) return 1;' +
                   '\n' + T +
                   'if (!strcmp (text, "sendVstEvents")) return 1;' + '\n')

    fcpp.write(T + '//if (!strcmp (text, "receiveVstEvents")) return 1;' +
               '\n' + T +
               '//if (!strcmp (text, "receiveVstMidiEvent")) return 1;' +
               '\n' + T + "return 0; // explicitly can't do; 0 => don't know" +
               '\n' + '}' + '\n')

    #----------------------------------------------------------------------------
    # Plugin suspend and resume

    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + 'void ' + pluginLabel + '::resume()' + '\n' + '{' + '\n')

    if controlouts != []:
        fcpp.write(T + 'wantEvents();' + '\n')

    fcpp.write(T + activateCode + '\n' + '}' + '\n' + '\n' + 'void ' +
               pluginLabel + '::suspend()' + '\n' + '{' + '\n' + T +
               deactivateCode + '\n' + '}' + '\n' + '\n')

    #----------------------------------------------------------------------------
    # Params handling

    #  setProgram
    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + 'void ' + pluginLabel + '::setProgram(long program)' + '\n' +
        '{' + '\n' + T + pluginLabel + 'Program *ap = &programs[program];' +
        '\n' + '\n' + T + 'curProgram = program;' + '\n')

    if params != []:
        for param in params:
            label = getText(param, "label")
            fcpp.write(T + 'setParameter(k' + label + ', ap->f' + label +
                       ');' + '\n')

    fcpp.write('}' + '\n' + '\n')

    #setProgramName
    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + 'void ' + pluginLabel + '::setProgramName(char *name)' + '\n' +
        '{' + '\n' + T + 'strcpy(programs[curProgram].name, name);' + '\n' +
        '}' + '\n' + '\n')

    #getProgramName
    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + 'void ' + pluginLabel + '::getProgramName(char *name)' + '\n' +
        '{' + '\n' + T + 'strcpy(name, programs[curProgram].name);' + '\n' +
        '}' + '\n' + '\n')

    #setParameter
    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + 'void ' + pluginLabel +
        '::setParameter(long index, float value)' + '\n' + '{' + '\n' + T +
        pluginLabel + 'Program *ap = &programs[curProgram];' + '\n' + '\n' +
        T + 'switch(index)' + '\n' + T + '{' + '\n')

    if params != []:
        for param in params:
            label = getText(param, 'label')
            max = label + 'Max'
            min = label + 'Min'
            mapping = getText(param, 'mapping')
            type = getText(param, 'type')
            paramCode = getText(param, 'code')

            fcpp.write(T * 2 + 'case k' + label + ' :' + '\n' + T * 3 + 'f' +
                       label + ' = ap->f' + label + ' = value;' + '\n')

            if mapping == 'lin':
                fcpp.write(T * 3 + label + ' = (' + type + ')(value*(' + max +
                           '-' + min + ')+' + min + ');' + '\n')

            elif mapping == 'log':
                #    normalized = (log(param/min)) / (log(max/min))
                # => log(param/min) = normalized * log(max/min)
                # => param = min * (max/min)^normalized
                fcpp.write(T * 3 + label + ' = (' + type + ')' + min +
                           '*pow(' + max + '/' + min + ',f' + label + ');' +
                           '\n')

            fcpp.write(paramCode + T * 2 + 'break;' + '\n' + '\n')

    fcpp.write(T * 3 + 'default: break;' + '\n' + T + '}' + '\n' + '}' + '\n' +
               '\n')

    #getParameter
    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + 'float ' + pluginLabel + '::getParameter(long index)' + '\n' +
        '{' + '\n' + T + 'float v = 0.f;' + '\n' + '\n' + T + 'switch(index)' +
        '\n' + T + '{' + '\n')

    if params != []:
        for param in params:
            label = getText(param, 'label')
            fcpp.write(T * 2 + 'case k' + label + ' : v = f' + label +
                       '; break;' + '\n')

    fcpp.write(T * 2 + 'default: break;' + '\n' + T + '}' + '\n' + T +
               'return v;' + '\n' + '}' + '\n' + '\n')

    #getParameterName
    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + 'void ' + pluginLabel +
        '::getParameterName(long index, char *label)' + '\n' + '{' + '\n' + T +
        'switch(index)' + '\n' + T + '{' + '\n')

    if params != []:
        for param in params:
            label = getText(param, 'label')
            caption = getText(param, 'caption')
            fcpp.write(T * 2 + 'case k' + label + ' : strcpy(label, "' +
                       caption + '"); break;' + '\n')

    fcpp.write(T * 2 + 'default: break;' + '\n' + T + '}' + '\n' + '}' + '\n' +
               '\n')

    #getParameterDisplay
    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + 'void ' + pluginLabel +
        '::getParameterDisplay(long index, char *text)' + '\n' + '{' + '\n' +
        T + 'switch(index)' + '\n' + T + '{' + '\n')

    if params != []:
        for param in params:
            label = getText(param, 'label')
            type = getText(param, 'type')
            if type == 'float':
                fcpp.write(T * 2 + 'case k' + label + ' : float2string(' +
                           label + ', text); break;' + '\n')
            elif type == 'int':
                fcpp.write(T * 2 + 'case k' + label + ' : long2string(' +
                           label + ', text); break;' + '\n')

    fcpp.write(T * 2 + 'default: break;' + '\n' + T + '}' + '\n' + '}' + '\n' +
               '\n')

    #getParameterLabel
    fcpp.write(
        '//-------------------------------------------------------------' +
        '\n' + 'void ' + pluginLabel +
        '::getParameterLabel(long index, char *label)' + '\n' + '{' + '\n' +
        T + 'switch(index)' + '\n' + T + '{' + '\n')

    if params != []:
        for param in params:
            label = getText(param, 'label')
            unit = getText(param, 'unit')
            fcpp.write(T * 2 + 'case k' + label + ' : strcpy(label, "' + unit +
                       '"); break;' + '\n')

    fcpp.write(T * 2 + 'default: break;' + '\n' + T + '}' + '\n' + '}' + '\n' +
               '\n')

    #----------------------------------------------------------------------------
    # processing
    # process
    fcpp.write(
        '#define XSPIF_WRITE_SAMPLE(dest,index,source) ((dest)[(index)] += (source))'
        + '\n' + '\n' +
        '//-------------------------------------------------------------' +
        '\n' + 'void ' + pluginLabel +
        '::process(float **inputs, float **outputs, long sampleframes)' +
        '\n' + '{' + '\n')

    i = 0
    for pin in pins:
        dir = getText(pin, 'dir')
        if dir == 'In':
            label = getText(pin, 'label')
            channels = int(str(getText(pin, 'channels')))
            for j in range(0, channels):
                i = i + 1
                fcpp.write(T + 'float *' + label + str(j + 1) + ' = inputs[' +
                           str(i - 1) + '];' + '\n')

    i = 0
    for pin in pins:
        dir = getText(pin, 'dir')
        if dir == 'Out':
            label = getText(pin, 'label')
            channels = int(str(getText(pin, 'channels')))
            for j in range(0, channels):
                i = i + 1
                fcpp.write(T + 'float *' + label + str(j + 1) + ' = outputs[' +
                           str(i - 1) + '];' + '\n')

    fcpp.write(T + 'vector_size = sampleframes;' + '\n' + '\n' + processCode +
               '\n' + '}' + '\n' + '\n' + '#undef XSPIF_WRITE_SAMPLE' + '\n' +
               '\n')

    # processReplacing
    fcpp.write(
        '#define XSPIF_WRITE_SAMPLE(dest,index,source) ((dest)[(index)] = (source))'
        + '\n' + '\n' +
        '//-------------------------------------------------------------' +
        '\n' + 'void ' + pluginLabel +
        '::processReplacing(float **inputs, float **outputs, long sampleframes)'
        + '\n' + '{' + '\n')

    i = 0
    for pin in pins:
        dir = getText(pin, 'dir')
        if dir == 'In':
            label = getText(pin, 'label')
            channels = int(str(getText(pin, 'channels')))
            for j in range(0, channels):
                i = i + 1
                fcpp.write(T + 'float *' + label + str(j + 1) + ' = inputs[' +
                           str(i - 1) + '];' + '\n')

    i = 0
    for pin in pins:
        dir = getText(pin, 'dir')
        if dir == 'Out':
            label = getText(pin, 'label')
            channels = int(str(getText(pin, 'channels')))
            for j in range(0, channels):
                i = i + 1
                fcpp.write(T + 'float *' + label + str(j + 1) + ' = outputs[' +
                           str(i - 1) + '];' + '\n')

    fcpp.write(T + 'vector_size = sampleframes;' + '\n' + '\n' + processCode +
               '\n' + '}' + '\n' + '\n' + '#undef XSPIF_WRITE_SAMPLE' + '\n' +
               '\n')

    #----------------------------------------------------------------------------
    # main entry point

    fcpp.write('''
//-------------------------------------------------------------
// main entry point
//-------------------------------------------------------------
bool oome = false;
#if MAC
#pragma export on
#endif

// prototype of the export function main
#if BEOS
#define main main_plugin
extern "C" __declspec(dllexport) AEffect *main_plugin (audioMasterCallback audioMaster);

#elif MACX
#define main main_macho
extern "C" AEffect *main_macho (audioMasterCallback audioMaster);

#else
AEffect *main (audioMasterCallback audioMaster);
#endif

AEffect *main (audioMasterCallback audioMaster)
{
  // get vst version
  if (!audioMaster (0, audioMasterVersion, 0, 0, 0, 0))
    return 0;  // old version

  AudioEffect* effect = new ''' + pluginLabel + '''(audioMaster);
  if (!effect)
    return 0;
  if (oome)
  {
    delete effect;
    return 0;
  }
  return effect->getAeffect ();
}

#if MAC
#pragma export off
#endif

#if WIN32
#include <windows.h>
void* hInstance;
BOOL WINAPI DllMain (HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved)
{
  hInstance = hInst;
  return 1;
}
#endif
''')

    fcpp.close
    print T + 'done'

    # def file for windows: exports the plugins entry point
    print T + 'writing : ' + filename_prefix + '.vst.def'
    fdef = file(filename_prefix + '.vst.def', 'w')

    fdef.write('LIBRARY	' + pluginLabel + '\n' + "DESCRIPTION '" +
               pluginCaption + "'" + '\n' + 'EXPORTS main' + '\n')

    fdef.close
    print T + 'done'

    return
예제 #16
0
def generalCheck(domTree):
    """
    method to check the validity of the XSPIF meta-plugin with
    respect to  all constraints that are NOT handled by the DTD.
    
    """

    # Get the elements
    pluginId = getText(domTree, 'plugId')
    pluginLabel = getText(domTree, 'label')
    pluginManufId = getText(domTree, "manufId")
    pluginCaption = getText(domTree, 'caption')
    pluginComments = getText(domTree, 'comment')
    pluginMaker = getText(domTree, 'maker')
    pluginCopyright = getText(domTree, 'copyright')
    pluginCode = getText(domTree, 'code')

    pins = domTree.getElementsByTagName('pin')
    params = domTree.getElementsByTagName('param')
    states = domTree.getElementsByTagName('state')
    controlouts = domTree.getElementsByTagName('controlout')
    callbacks = domTree.getElementsByTagName('callback')
    
    process = 0
    processEvents = 0
    instantiate = 0
    deinstantiate = 0
    activate = 0
    deactivate = 0

    for cb in domTree.getElementsByTagName('callback'):
        label = getText(cb, 'label')
        if ('process' == label):
            process = cb
        elif ('processEvents' == label):
            processEvents = cb
        elif ('instantiate' == label):
            instantiate = cb
        elif ('deinstantiate' == label):
            deinstantiate = cb
        elif ('activate' == label):
            activate = cb
        elif ('deactivate' == label):
            deactivate = cb
        else:
            print(T+'Warning: callback '+label+' is not known from ladspa.py')

############################################################        

    # Check the ID:
    for Id in [pluginId, pluginManufId]:
        if (len(Id) != 6)or(Id.find("'")!=0)or(Id.rfind("'")!=5):
            print(T+ 'Warning: '+Id+': you have to specify a 32 bit label.')
            print(T+ '         you can give it as 4 characters between simple quotes.')
            return -1

    # Check every label is unique
    # Checking callback's label is unecessary because
    #  already forced by the DTD
    labels = []
    for tag in [pins, params, states, controlouts]:
        for el in tag:
            labels.append(getText(el,'label'))
    labels.append(pluginLabel)

    extraLabel = checkNotTwiceSameElement(labels)
    if (0 != extraLabel):
        print(T+"Error: label "+extraLabel+" was used more than once")
        return -1

    # Check labels do not contain bad characters
    WrongCharList = [" ","&","'",'"',"&","#","@","-","*"]
    for myString in labels:
        if ("" == myString):
            print(T+'Error: One of the labels is null!!!')
        WrongChar = stringHasChar(myString, WrongCharList)
        if (WrongChar):
            print(T+"Error: Label '"+l+"' contains bad characher '"+WrongChar+"'")
            return -1
        

    # check Min, max, and default and mapping values are OK.
    #  Warning: min, max, and mapping are here supposed to be
    #  REQUIRED by the DTD, thus we know that they exists.
    for tag in  [params, controlouts]:
        if (0 != tag.length):
            for el in tag:
                if (0 != checkMinMaxDefault(el)):
                    return -1
     
            
    if (0 == pins.length):
        print(T+"Error: The plugin you build has no audio pin!")
        return -1
    if (0 == callbacks.length):
        print(T+"Warning: The plugin you build has no callback!")
    if (0 == states.length):
        print(T+"Warning: The plugin you build has no state.")

    return
예제 #17
0
파일: pd.py 프로젝트: vincentgoudard/xspif
def write(domTree, filenamePrefix):
    """
    This method is called by xspif2pd_linux.py
    It writes the PureData object's source file [filenamePrefix].pd_linux.c
    for the linux platform with the help of the DOM tree [x_plugin].
    """
   
    # Get the domTree direct childs
    pluginId = getText(domTree, 'plugId')
    pluginLabel = getText(domTree, 'label')
    pluginManufId = getText(domTree, "manufId")
    pluginCaption = getText(domTree, 'caption')
    pluginComments = getText(domTree, 'comment')
    pluginMaker = getText(domTree, 'maker')
    pluginCopyright = getText(domTree, 'copyright')
    pluginCode = getText(domTree, 'code')

    pins = domTree.getElementsByTagName('pin')
    params = domTree.getElementsByTagName('param')
    states = domTree.getElementsByTagName('state')
    controlouts = domTree.getElementsByTagName('controlout')
    callbacks = domTree.getElementsByTagName('callback')

    # Get the callbacks by their name
    instantiate   = None
    deinstantiate = None
    process       = None
    processEvents = None
    activate      = None
    deactivate    = None

    if callbacks == [] : 
        print T+ "Warning: you haven't implemented any callback"+'\n'
    else :
        for callback in callbacks:
            text = str(getText(callback,'label'))
            if text == 'instantiate':
                instantiate = callback
            elif text == 'deinstantiate':
                deinstantiate = callback
            elif text == 'activate':
                activate = callback
            elif text == 'deactivate':
                deactivate = callback
            elif text == 'process':
                process = callback
            elif text == 'processEvents':
                print 'XSPIF Warning: callback "processEvents" not implemented for PD for now'
                #processEvents = callback
            else:
                print('Warning: callback ' + text
                      +' is not known from pd.py' + '\n')
            
    # useful variables...
    separator = '\n' + '/****************************************************************/' + '\n'
    pluginLabelTilde =  pluginLabel + '_tilde'
    t_pluginLabel = 't_' + pluginLabelTilde

    # make a list with pins
    in_ports = []
    out_ports = []
    for pin_node in pins:
        pin_label = getText(pin_node, 'label')
        pin_channels = int(getText(pin_node, 'channels'))
        pin_dir = getText(pin_node, 'dir')
        pin_caption = getText(pin_node, 'pin_caption')
        for i in range(1, pin_channels + 1):
            if ('In' == pin_dir):
                in_ports.append([pin_label + str(i), pin_caption])
            elif ('Out' == pin_dir):
                out_ports.append([pin_label + str(i), pin_caption])

    # ports clockwise sorted W.R.T. the graphical representation of the object.
    out_ports.reverse()
    out_ports_cw = out_ports[:]
    out_ports.reverse()
    ports_cw = in_ports + out_ports_cw
   
    #create output file(s)
    xspif_filename = (filenamePrefix + '.xspif')
    c_filename = (pluginLabel + '~.c')
    print T+'writing : '+c_filename
    fc = file(c_filename,'w')


    #----------------------------------------------------------------------------
    # file header

    fc.write(
        '/****************************************************************' + '\n'
        + 'XSPIF: cross(X) Standard PlugIn Framework: '
        + 'XSPIF to PD' + '\n'
        + T+ c_filename+'\n' + '\n'
        + pluginComments + '\n'
        + ' This file is generated automatically from the file: '+xspif_filename+'\n'
        + T+'plugin ID: '+pluginId+'\n'
        + T+'manufacturer ID: '+pluginManufId+'\n'
        + T+'maker: '+pluginMaker+'\n'
        + T+'copyright: '+pluginCopyright+'\n'
        + '****************************************************************/' + '\n'
        + '\n' + '\n' + '\n')


    #----------------------------------------------------------------------------
    # includes

    fc.write('#include <stdlib.h>'+'\n'
             +'#include <string.h>'+'\n'
             +'#ifndef PD_VERSION'+'\n'
             +'#include "m_pd.h"'+'\n'
             +'#endif'+'\n')


    #----------------------------------------------------------------------------
    # macros

    fc.write('\n' + '\n' + separator)
    fc.write('''
// Macro for getting the sample rate
#undef XSPIF_GET_SAMPLE_RATE
#define XSPIF_GET_SAMPLE_RATE()(sys_getsr())

// Macro for getting the vector_size
#undef XSPIF_GET_VECTOR_SIZE
#define XSPIF_GET_VECTOR_SIZE()(vector_size)

// Macro for control outputs
#undef XSPIF_CONTROLOUT
#define XSPIF_CONTROLOUT(dest, index, value)(outlet_float(dest, value))

// Macros for checking parameter fit in its range
#undef FIT_RANGE
#define FIT_RANGE(value, min, max)(((value) < min) ? min : (((value) > max) ? max : (value)))
''')

    
    #----------------------------------------------------------------------------
    # independant routines
    fc.write('\n' + '\n' + separator)
    fc.write('// add independant code here' + '\n')
    fc.write(pluginCode)


    #----------------------------------------------------------------------------
    # Class declaration

    fc.write('\n' + '\n' + separator)
    fc.write('static t_class *' + pluginLabelTilde + '_class;' + '\n')
    fc.write('\n')

    # ...a t_object as first entry!! ...
    fc.write('typedef struct _' + pluginLabelTilde + ' {' + '\n'
             + T + 't_object  x_obj;' + '\n')
    
    # ...the sample rate ...
    fc.write(T + 't_float sample_rate;' + '\n'
             + T + 't_int active;' + '\n')

    fc.write('\n')
        
    # ...a copy of the parameter for local use...
    # Note: don't care about type: all numbers are float in a PD graph
    fc.write(T + '// Internal copy of the parameters:\n')
    for p_node in params:
        p_label = getText(p_node, 'label')
        p_type  = getText(p_node, 'type')
        fc.write(T + 't_float m_f' + p_label + ';' + '\n')
    fc.write('\n')

    # ... the states ...(except the code_states declared as global)
    fc.write(T + '// Internal states:\n')
    if ([] != states):
        for s_node in states:
            s_label = getText(s_node, 'label')
            s_type  = getText(s_node, 'type')
            fc.write(T + s_type + ' ' + s_label + ';' + '\n')
        fc.write('\n')

    # ...the pointers to the controlouts...
    fc.write(T + '// Pointers to the outlets:\n')
    for c_node in controlouts:
        c_label = getText(c_node, 'label')
        c_type  = getText(c_node, 'type')
        fc.write(T + c_type+' '+ c_label+'Value;'+ '\n')
        fc.write(T + 't_outlet *' + c_label + ';' + '\n')
        fc.write(T + 't_clock *p_'+c_label+'Clock;'+ '\n')
    fc.write('\n')

    # ... and a dummy variable for signal object.
    fc.write(T + '//  Dummy variable needed for ~ objects:\n')
    fc.write(T + 't_sample dummy_f;' + '\n')
    fc.write('\n')


    fc.write('} t_' + pluginLabelTilde + ';' + '\n')



    #----------------------------------------------------------------------------
    # Methods prototypes
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('// Prototypes' + '\n')
    if (deinstantiate):
        fc.write('void ' + pluginLabelTilde + '_free('+ t_pluginLabel +' *x);' + '\n')

#    if (activate):
    fc.write('void ' + pluginLabelTilde + '_activate('+ t_pluginLabel +' *x);' + '\n')
#    if (activate):
    fc.write('void ' + pluginLabelTilde + '_deactivate('+ t_pluginLabel +' *x);' + '\n')

    fc.write('static void ' + pluginLabelTilde + '_print('+ t_pluginLabel +' *x);' + '\n')


    #----------------------------------------------------------------------------
    # Print methods to show infos about the plugin
    #----------------------------------------------------------------------------
    # TODO: write the correct index for inlet number#
    fc.write('\n' + '\n' + separator)
    fc.write(
'''
// Output information about the plugin
static void ''' + pluginLabelTilde + '''_print('''+t_pluginLabel+''' *x){

// General info about the plugin

post("\nThis file has been automatically generated  with XSPIF:
a (X)cross Standard PlugIn Framework
from the XML file : ''' + xspif_filename +'''
Plugin name : ''' + pluginCaption +'''
Plugin label : ''' + pluginLabel + '''
Maker : ''' + pluginMaker + '''
Copyright : ''' + pluginCopyright + '''
Description :''' + pluginComments+ '''\n");
'''+ '\n'*2)

    fc.write('post("Control input(s):");' + '\n')
    fc.write('post("(Index for controls with a dedicated inlet are hinted with a #)");'+'\n')
    i = 0 # TODO: try to change increment: this is no true python
    for p_node in params:
        p_label = getText(p_node, 'label')
        p_min = getText(p_node, 'min')
        p_max = getText(p_node, 'max')
        p_type = getText(p_node, 'type')
        p_mapping = getText(p_node, 'mapping')
        p_unit = getText(p_node, 'unit')
        p_caption = getText(p_node, 'caption')
        p_comment = getText(p_node, 'comment')
        p_noinlet = getText(p_node, 'noinlet')
        if ('true' != p_noinlet):
            p_ind ='#'+ str(i)
        else:
            p_ind = str(i)
        fc.write('post(" ' + p_ind + ' ' + p_caption + ' = %f ('+ p_unit+')", x->m_f'
                 +p_label+ ');' + '\n')
        fc.write('post("    '+ p_label + ', type: ' + p_type
                 + ', in range [' + p_min + ' ; ' + p_max+ ']");' + '\n')
        fc.write('post("    with mapping (suggested): ' + p_mapping+'");' + '\n')
        fc.write('post("    Note:' +p_comment+'");' + '\n')
        i = i+1
                 
    fc.write('post("Control output(s):");' + '\n')
    i = 0 # TODO: try to change increment: this is no true python
    for c_node in controlouts:
        c_label = getText(c_node, 'label')
        c_min = getText(c_node, 'min')
        c_max = getText(c_node, 'max')
        c_type = getText(c_node, 'type')
        c_mapping = getText(c_node, 'mapping')
        c_unit = getText(c_node, 'unit')
        c_caption = getText(c_node, 'caption')
        c_comment = getText(c_node, 'comments')
        c_ind = str(i)
        fc.write('post(" #' + c_ind + ' ' + c_caption + ' (' + c_unit + ')");' + '\n')
        fc.write('post("    '+ c_label + ', type: ' + c_type
                 + ', in range [' + c_min + ' ; ' + c_max+ ']");' + '\n')
        fc.write('post("    with mapping (suggested): ' + c_mapping+'");'+'\n')
        fc.write('post("    Note:' +c_comment+'");' + '\n')
        i = i+1

    
    fc.write('post("Audio input(s):");' + '\n')
    for port in in_ports:
        ind = str(ports_cw.index(port) + 2)
        fc.write('post(" #' + ind + ' ' + port[0] + '");' + '\n')
                 
    fc.write('post("Audio output(s):");' + '\n')    
    for port in out_ports:
        ind = str(ports_cw.index(port) + 2)
        fc.write('post(" #' + ind + ' ' + port[0] + '");' + '\n')

    fc.write('if (x->active)' + '\n'
             +T+'post("Plugin ACTIVATED!");' + '\n'
             +'else'+'\n'
             +T+'post("Plugin DEACTIVATED!");' + '\n')    
    

    fc.write('}' + '\n')


    #----------------------------------------------------------------------------
    # Define methods for parameters which modifies any state
    #----------------------------------------------------------------------------

    fc.write('\n')
    for p_node in params:
        p_label = getText(p_node, 'label')
        p_type = getText(p_node, 'type')
        p_min = getText(p_node, 'min')
        p_max = getText(p_node, 'max')
        p_code =  getText(p_node, 'code')
        

        fc.write('\n' + '\n' + separator)
        fc.write('// Method responding to a change in parameter ' + p_label +  '\n')
        fc.write('static void ' + pluginLabelTilde + '_' + p_label
                 + '('+ t_pluginLabel +' *x, t_floatarg f){' + '\n' *2)
            
        if ('' != p_code):
            #... a copy of the states ...
            writeGetStates(fc, states)
            #... get pointers to the outlets...
            writeGetControlouts(fc, controlouts)
            # ...a copy of the parameters for local use...
            writeGetParams(fc, params)
        else:
            # ...just a copy of the parameter for update...
            fc.write(T +p_type + ' ' + p_label
                     +' = x->m_f'+p_label+';' + '\n')
           
        
        fc.write('\n')
        
        fc.write(T + ' // Check the parameter fits its range and actualize it' + '\n'
                 + T + p_label + ' = FIT_RANGE(f, '+p_min+', '+p_max+');'+'\n'*2)
           
        # Here is the state update code
        if ('' != p_code):
            fc.write('\n' + T + '{' + '\n' )
            fc.write(p_code)    
            fc.write('\n' + T + '}' + '\n'*2 )

        # Update the states and THIS parameter in the plugin structure
        fc.write(T + '// Update ' + p_label + ' and states in the plugin structure:' + '\n')
        fc.write(T + 'x->m_f'+p_label+ ' = '+p_label+';' + '\n')
        if ('' != p_code):
            writeUpdateStates(fc, states)
                    
        fc.write('}' + '\n')

            
    #----------------------------------------------------------------------------
    # Function for controlouts called by clock
    if ([]!=controlouts):
        fc.write('\n' + '\n' + separator)
        fc.write('// Function for the control outlets called by clocks'  + '\n')
       
        for c_node in controlouts:
            c_label = getText(c_node, 'label')
            fc.write('static void '+pluginLabelTilde+'_'+c_label+'('
                     +t_pluginLabel+' *x){'+'\n')
        
            fc.write(T+'outlet_float(x->'+c_label+', x->'+c_label+'Value);'+'\n')
            fc.write('}' + '\n')
        
    #----------------------------------------------------------------------------
    # Function for controlouts : setting the clock
        fc.write('\n' + '\n' + separator)
        fc.write('// Function for controlouts : setting the clock'  + '\n')
        fc.write('static void '+pluginLabelTilde+'_controlouts('
                 +t_pluginLabel+' *x, t_outlet *dest, t_float index, t_float value){'+'\n')

        for c_node in controlouts:
            c_label = getText(c_node, 'label')
            fc.write(T + 'if (dest == x->'+c_label+'){'+'\n')
            fc.write(T*2+'clock_delay(x->p_'+c_label+'Clock, index*1000/XSPIF_GET_SAMPLE_RATE());'+'\n')
            fc.write(T*2+'x->'+c_label+'Value = value;'+'\n')
            fc.write(T+'}' + '\n')
        fc.write('}' + '\n')
           

    #----------------------------------------------------------------------------
    # Define once the XSPIF_WRITE_SAMPLE macro for 'run-replacing' process
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('// Macro for process-replacing' + '\n')
    fc.write('#undef XSPIF_WRITE_SAMPLE'+ '\n'
             '#define XSPIF_WRITE_SAMPLE(dest, index, value) ((dest)[(index)] = (value))'+ '\n'
             )

    #----------------------------------------------------------------------------
    # Define XSPIF_CONTROLOUTS so that it sets the clock, and does not
    # outlet_float during the thread-safe 'perform' routine.
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('// Macro for control outputs in the perform method : use clock' + '\n')
    fc.write('#undef XSPIF_CONTROLOUT'+ '\n'
             '#define XSPIF_CONTROLOUT(dest, index, value)('
             +pluginLabelTilde+'_controlouts(x, dest, index*1000/XSPIF_GET_SAMPLE_RATE(), value)) '+ '\n')


    #----------------------------------------------------------------------------
    # Plugin's 'perform' (DSP processing) function
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('t_int *' + pluginLabelTilde + '_perform(t_int *w)' + '\n'
         + '{' +  '\n'
         + T + t_pluginLabel + ' *x = (' + t_pluginLabel + ' *)(w[1]);' + '\n')

    for port in ports_cw:
        fc.write(T + 't_sample *' + port[0]
                 + ' = (t_sample *)(w[' + str(ports_cw.index(port) + 2) + ']);' + '\n')
        
    fc.write(T + 'int vector_size = (int)(w[' + str(len(ports_cw) + 2)  + ']);' + '\n')
    
    # process only if plugin is active
    fc.write(T+'if (x->active)'+'\n'+T*2+'{'+'\n')
    
    # ... get a copy of the parameters ...
    writeGetParams(fc, params)
    
    # ...get a copy of the states ...
    writeGetStates(fc, states)

    # ...get the pointers to the outlets
    writeGetControlouts(fc, controlouts)

    # here is the DSP algorithm
    writeCallbackCode(fc, process)

    # Update the states in the plugin structure
    writeUpdateStates(fc, states)

    fc.write(T*2+'}'+'\n')
           
    fc.write(T + 'return (w+' + str(len(ports_cw) + 3)  + ');' + '\n')
    fc.write('}' + '\n')
          

    #----------------------------------------------------------------------------
    # Plugin's 'DSP' function: declare dsp method
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('// Plugin DSP method'+'\n')
    fc.write('void ' + pluginLabelTilde + '_dsp(' + t_pluginLabel +' *x, t_signal **sp)' + '\n')
    fc.write('{' + '\n')
    fc.write(T + 'dsp_add(' + pluginLabelTilde + '_perform, ' + str(len(ports_cw) + 2) + ', x,' + '\n' + T * 2 )
    for port in ports_cw:
        fc.write(' sp[' + str(ports_cw.index(port)) + ']->s_vec,')
    fc.write('sp[0]->s_n);' + '\n')
    
    fc.write('}' + '\n')

    
    #----------------------------------------------------------------------------
    # Plugin's new (instantiate) function
    #----------------------------------------------------------------------------
    fc.write('\n' + '\n' + separator)
    fc.write('// Plugin new method' + '\n')
    fc.write('void *' + pluginLabelTilde + '_new('
             + 't_symbol *s, int argc, t_atom *argv)' + '\n' #get the params as varargs
             + '{' +  '\n'
             )
    # declare variables
    fc.write(T+'int i;'+'\n'
             +T+'t_float val;'+'\n')
        
    # declare states
    if ([] != states):
        for s_node in states:
            s_label = getText(s_node, 'label')
            s_type  = getText(s_node, 'type')
            if (-1 != s_type.find('*')):
                fc.write(T + s_type + ' ' + s_label + ' = NULL;' + '\n')
            else:
                fc.write(T + s_type + ' ' + s_label + ';' + '\n')
        fc.write('\n')

    # create the object
    fc.write(T + t_pluginLabel + ' *x = (' + t_pluginLabel + ' *)pd_new('
             + pluginLabelTilde + '_class);' + '\n')

    # set the sample rate:
    fc.write(T + 'x->sample_rate = XSPIF_GET_SAMPLE_RATE();' + '\n')

    # Declare the inlet for the audio ports
    fc.write('\n')
    fc.write(T + '// Declare the in/out-lets for the audio ports' + '\n')
    fc.write(T + '// Beware: 1 inlet already declared in the "CLASS_DEFAULT"' + '\n')
    for port in in_ports[0 : (len(in_ports)-1)]:
        fc.write(T + 'inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);' + '\n')
    for port in out_ports:
        fc.write(T + 'outlet_new(&x->x_obj, &s_signal);' + '\n')

    # Declare inlets for params with no tag "noinlet"
    fc.write('\n')
    for p_node in params:
       p_label = getText(p_node, 'label')
       p_noinlet = getText(p_node, 'noinlet')
       if ('true' != p_noinlet):
#          if ('' != getText(p_node, 'code')):
#              declare a new inlet (with dedicated method)
#              TODO: make it no only for &s_float taking param type in account
           fc.write(T + '// ' + p_label + ' calls a dedicated method' + '\n')
           fc.write(T + 'inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, '
                        + 'gensym("' + p_label + '")' + ');' + '\n')
#            else:
#                #declare un floatinlet_new (without dedicated method)
#                fc.write(T + '// ' + p_label + ' is written directly' + '\n')
#                fc.write(T + 'floatinlet_new (&x->x_obj, &x->m_f' + p_label + ');' + '\n')
           
    # Declare outlets for controlouts
    fc.write('\n')
    for c_node in controlouts:
        c_label = getText(c_node, 'label')
        # TODO: make it no only for &s_float taking param type in account
        fc.write(T + '//  controlout ' + c_label + '\n')
        fc.write(T+'x->'+c_label+' = outlet_new(&x->x_obj,  &s_float);'+'\n')
        fc.write(T+'x->p_'+c_label+'Clock = clock_new(x, (t_method)'+pluginLabelTilde+'_'+c_label+');'+'\n')
        
    # Put the instanciation code here:
    writeCallbackCode(fc, instantiate)
    
    # Update the states in the plugin structure
    writeUpdateStates(fc, states)

    # Getting the parameters given at instanciation
    # Only the exact number of parameters can be given here
    if ([]!=params):
        fc.write(
            '\n'+T+'// Get the parameters'+'\n'
            +T+'switch (argc)'+'\n'
            +T*2+'{' + '\n'
            +T*2+'case 0:'+'\n')

        for p_node in params:
            p_label = getText(p_node, 'label')
            p_code = getText(p_node, 'code')
            p_default = getText(p_node, 'default')
            fc.write(T*4+pluginLabelTilde+'_' +p_label+'(x, '+p_default+');'+'\n')
            
        fc.write(
            T*3+'break;'+'\n'
            +T*2+'case '+str(len(params))+':'+'\n'+T*3+'{'+'\n'
            +T*4+'// Check all parameters are float'+'\n'
            +T*4+'for (i=0; i <= argc-1;i++)'+'\n'
            +T*5+'if (argv[i].a_type != A_FLOAT)'+'\n'
            +T*6+'{'+'\n'
            +T*7+'post("'+pluginLabelTilde+' : wrong arguments");'+'\n'                     
            +T*7+'return NULL;'+'\n'
            +T*6+'}'+'\n')
            
        p_index = 0
        for p_node in params:
            p_label = getText(p_node, 'label')
            p_min = getText(p_node, 'min')
            p_max = getText(p_node, 'max')
            p_code = getText(p_node, 'code')
            p_default = getText(p_node, 'default')
            fc.write(T*4+'val= atom_getfloatarg('+str(p_index)+', argc, argv);'+'\n')
            fc.write(T*4+pluginLabelTilde+'_' +p_label+'(x, val);'+'\n')
            p_index += 1

        fc.write(T*3+'}'+'\n'
                 +T*3+'break;'+'\n')
        fc.write(T*2+'default:'+'\n'
                 +T*3+'{'+'\n'
                 +T*4+'post( "'+pluginLabel+' : error in the number of arguments ( %d )", argc );' + '\n'
                 +T*4+'return NULL;'+ '\n'
                 +T*3+'}' + '\n'
                 +T*2+'}' + '\n')


    # call method activate
    fc.write('\n')
#   if (activate):
    fc.write(T + pluginLabelTilde + '_activate(x);' + '\n')

    fc.write(T + 'return (void *)x;' + '\n')
    fc.write('}' + '\n')


    #---------------------------------------------------------------------------
    # Plugin activate function
    #---------------------------------------------------------------------------
#    if (activate):
    fc.write('\n' + '\n' + separator)
    fc.write('// Initialise and activate a plugin instance.'+ '\n')
    fc.write(
        'void ' + pluginLabelTilde + '_activate('+ t_pluginLabel +' *x) {' + '\n' * 2)
    
    # Get the states and params
    writeGetStates(fc, states)
    writeGetParams(fc, params)
    
    #... get pointers to the outlets...
    writeGetControlouts(fc, controlouts)
    
    # Put the activate code here:
    writeCallbackCode(fc, activate)

    # Update the states in the plugin structure
    writeUpdateStates(fc, states)

    # Activate the plugin
    fc.write(T+'x->active = 1;'+'\n')
    
    fc.write('}' + '\n')


    #---------------------------------------------------------------------------
    # Plugin deactivate function
    #---------------------------------------------------------------------------
#    if (activate):
    fc.write('\n' + '\n' + separator)
    fc.write('// Deactivate a plugin instance (bypass).'+ '\n')
    fc.write(
        'void ' + pluginLabelTilde + '_deactivate('+ t_pluginLabel +' *x) {' + '\n' * 2)
    
    # Get the states and params
    writeGetStates(fc, states)
    writeGetParams(fc, params)
    
    #... get pointers to the outlets...
    writeGetControlouts(fc, controlouts)
    
    # Put the activate code here:
    writeCallbackCode(fc, deactivate)

    # Update the states in the plugin structure
    writeUpdateStates(fc, states)

    # Deactivate the plugin
    fc.write(T+'x->active = 0;'+'\n')
    
    fc.write('}' + '\n')


    #----------------------------------------------------------------------------
    # Plugin's free (deinstantiate) method
    # (only implemented if the plugin need it)
    #----------------------------------------------------------------------------
    if (deinstantiate  or [] != controlouts):
        fc.write('\n' + '\n' + separator)
        fc.write('// Plugin cleanup method' + '\n')
        fc.write('void ' + pluginLabelTilde + '_free('+t_pluginLabel+' *x){' + '\n')
        
        # Get the states, so that any structure can be deleted fom memory
        writeGetStates(fc, states)
        writeGetParams(fc, params)
        
        if (deinstantiate):
            # Put the deinstantiate code here        
            writeCallbackCode(fc, deinstantiate)

        for c_node in controlouts:
            c_label = getText(c_node, 'label')
            fc.write(T+'clock_free(x->p_'+c_label+'Clock);'+'\n')
            

        fc.write('}' + '\n')


    #----------------------------------------------------------------------------
    # Plugin's setup function
    #----------------------------------------------------------------------------
    
    fc.write('\n' + '\n' + separator)
    fc.write('// Plugin setup method' + '\n')
    fc.write('void ' + pluginLabelTilde + '_setup(void) {' +  '\n'
             + T + pluginLabelTilde + '_class = class_new(gensym("' + pluginLabel+ '~"),' +  '\n'
             + T *2 + '(t_newmethod)' + pluginLabelTilde + '_new,' +  '\n')
    #if plugin needs a destructor, it should be declared here
    if (deinstantiate or [] != controlouts):
        fc.write(T *2 + '(t_method)' + pluginLabelTilde + '_free,' + '\n')
    else:
        fc.write(T *2 + '0,' + '\n')
    fc.write(T *2 + 'sizeof(' + t_pluginLabel + '),' +  '\n'
             + T *2 + 'CLASS_DEFAULT,' +  '\n'
             + T *2 + 'A_GIMME, 0);' +  '\n') #a list of argument can be given representing all parameters

    
    fc.write('\n')
    fc.write(T + 'class_addmethod(' + pluginLabelTilde + '_class,' + '\n'
             + T*2 + '(t_method)' + pluginLabelTilde + '_dsp, gensym("dsp"), 0);' + '\n')
    fc.write(T + 'class_addmethod(' + pluginLabelTilde + '_class,' + '\n'
             + T*2 + '(t_method)' + pluginLabelTilde + '_print, gensym("print"), 0);' + '\n')
    fc.write(T + 'class_addmethod(' + pluginLabelTilde + '_class,' + '\n'
             + T*2 + '(t_method)' + pluginLabelTilde + '_activate, gensym("on"), 0);' + '\n')
    fc.write(T + 'class_addmethod(' + pluginLabelTilde + '_class,' + '\n'
             + T*2 + '(t_method)' + pluginLabelTilde + '_deactivate, gensym("off"), 0);' + '\n')

    fc.write('\n')
    for p_node in params:
        p_label = getText(p_node, 'label')
#        if ('' != getText(p_node, 'code')):
            # declare a new inlet (with dedicated method)
            # TODO: make it no only for &s_float taking param type in account
        fc.write(T + '// Declare a method for the parameter ' + p_label +  '\n')
        fc.write(T + 'class_addmethod(' + pluginLabelTilde + '_class,' + '\n'
                 + T*2 + '(t_method)' + pluginLabelTilde + '_' + p_label
                 + ', gensym("' + p_label + '"), A_FLOAT, 0);' + '\n')


    fc.write(T + '' + '\n')
    fc.write(T + 'CLASS_MAINSIGNALIN(' + pluginLabelTilde + '_class, '
             + t_pluginLabel + ', dummy_f);' + '\n')

    fc.write('}' + '\n')


# float ParameterCheck (char* name, float value, float min, float max )
# {

#     if (value > max)
#     {
# 	printf("Parameter: %s out of range [%.1f...%.1f]. Value limited.\n", name,
# 	       min, max );
# 	return(max);
#     }

#     if(value < min)
#     {
# 	printf("Parameter: %s out of range [%.1f...%.1f]. Value limited.\n", name,
# 	       min, max );
# 	return(min);	
#     }
#     return(value);
# }

    fc.close
    print T+'done'



    #---------------------------------------------------------------------------
    # MAKFILE
    #---------------------------------------------------------------------------

    print T+'writing : Makefile'
    fm = file('Makefile','w')

    fm.write('''
NAME = '''+pluginLabel+'''

current:
	echo make pd_linux, pd_nt, pd_irix5, or pd_irix6

clean: ; rm -f *.pd_linux *.o

# ----------------------- NT -----------------------

pd_nt: $(NAME)~.dll

.SUFFIXES: .dll

# Change this to match you pd path:
PD_NT_PATH = "C:/pd"

PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
VC="C:\Program Files\Microsoft Visual Studio\Vc98"

PDNTINCLUDE = /I. /I\tcl\include /I$(PD_NT_PATH)\src /I$(VC)\include

PDNTLDIR = $(VC)\lib
PDNTLIB = $(PDNTLDIR)\libc.lib $(PDNTLDIR)\oldnames.lib $(PDNTLDIR)\kernel32.lib $(PD_NT_PATH)/bin/pd.lib 

.c.dll:
	cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $(NAME)~.c
	link /dll /export:$(NAME)_tilde_setup $(NAME)~.obj $(PDNTLIB)

# ----------------------- IRIX 5.x -----------------------

pd_irix5: $(NAME)~.pd_irix5

.SUFFIXES: .pd_irix5

SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2


SGIINCLUDE =  -I../../src/

.c.pd_irix5:
	cc $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
	ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
	rm $*.o

# ----------------------- IRIX 6.x -----------------------

pd_irix6: $(NAME)~.pd_irix6

.SUFFIXES: .pd_irix6

SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
	-OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
	-Ofast=ip32

.c.pd_irix6:
	cc $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
	ld -IPA -n32 -shared -rdata_shared -o $*.pd_irix6 $*.o
	rm $*.o

# ----------------------- LINUX i386 -----------------------

pd_linux: $(NAME)~.pd_linux

.SUFFIXES: .pd_linux

LINUXCFLAGS = -DPD -O6 -funroll-loops -fomit-frame-pointer \
    -Wall -W -Wshadow -Wstrict-prototypes \
    -Wno-unused -Wno-parentheses -Wno-switch

LINUXINCLUDE =  -I/usr/local/lib/pd/include

.c.pd_linux:
	cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
	ld -export_dynamic  -shared -o $*.pd_linux $*.o -lc -lm
	strip --strip-unneeded $*.pd_linux
	rm $*.o

# ----------------------- Mac OSX -----------------------

pd_darwin: $(NAME)~.pd_darwin

.SUFFIXES: .pd_darwin

DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
    -Wno-unused -Wno-parentheses -Wno-switch

.c.pd_darwin:
	cc $(DARWINCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
	cc -bundle -undefined suppress  -flat_namespace -o $*.pd_darwin $*.o 
	rm -f $*.o ../$*.pd_darwin
	ln -s $*/$*.pd_darwin ..

''')

    fm.close
    print T+'done'

    return
예제 #18
0
def generalCheck(domTree):
    """
    method to check the validity of the XSPIF meta-plugin with
    respect to  all constraints that are NOT handled by the DTD.
    
    """

    # Get the elements
    pluginId = getText(domTree, 'plugId')
    pluginLabel = getText(domTree, 'label')
    pluginManufId = getText(domTree, "manufId")
    pluginCaption = getText(domTree, 'caption')
    pluginComments = getText(domTree, 'comment')
    pluginMaker = getText(domTree, 'maker')
    pluginCopyright = getText(domTree, 'copyright')
    pluginCode = getText(domTree, 'code')

    pins = domTree.getElementsByTagName('pin')
    params = domTree.getElementsByTagName('param')
    states = domTree.getElementsByTagName('state')
    controlouts = domTree.getElementsByTagName('controlout')
    callbacks = domTree.getElementsByTagName('callback')

    process = 0
    processEvents = 0
    instantiate = 0
    deinstantiate = 0
    activate = 0
    deactivate = 0

    for cb in domTree.getElementsByTagName('callback'):
        label = getText(cb, 'label')
        if ('process' == label):
            process = cb
        elif ('processEvents' == label):
            processEvents = cb
        elif ('instantiate' == label):
            instantiate = cb
        elif ('deinstantiate' == label):
            deinstantiate = cb
        elif ('activate' == label):
            activate = cb
        elif ('deactivate' == label):
            deactivate = cb
        else:
            print(T + 'Warning: callback ' + label +
                  ' is not known from ladspa.py')


############################################################

# Check the ID:
    for Id in [pluginId, pluginManufId]:
        if (len(Id) != 6) or (Id.find("'") != 0) or (Id.rfind("'") != 5):
            print(T + 'Warning: ' + Id +
                  ': you have to specify a 32 bit label.')
            print(
                T +
                '         you can give it as 4 characters between simple quotes.'
            )
            return -1

    # Check every label is unique
    # Checking callback's label is unecessary because
    #  already forced by the DTD
    labels = []
    for tag in [pins, params, states, controlouts]:
        for el in tag:
            labels.append(getText(el, 'label'))
    labels.append(pluginLabel)

    extraLabel = checkNotTwiceSameElement(labels)
    if (0 != extraLabel):
        print(T + "Error: label " + extraLabel + " was used more than once")
        return -1

    # Check labels do not contain bad characters
    WrongCharList = [" ", "&", "'", '"', "&", "#", "@", "-", "*"]
    for myString in labels:
        if ("" == myString):
            print(T + 'Error: One of the labels is null!!!')
        WrongChar = stringHasChar(myString, WrongCharList)
        if (WrongChar):
            print(T + "Error: Label '" + l + "' contains bad characher '" +
                  WrongChar + "'")
            return -1

    # check Min, max, and default and mapping values are OK.
    #  Warning: min, max, and mapping are here supposed to be
    #  REQUIRED by the DTD, thus we know that they exists.
    for tag in [params, controlouts]:
        if (0 != tag.length):
            for el in tag:
                if (0 != checkMinMaxDefault(el)):
                    return -1

    if (0 == pins.length):
        print(T + "Error: The plugin you build has no audio pin!")
        return -1
    if (0 == callbacks.length):
        print(T + "Warning: The plugin you build has no callback!")
    if (0 == states.length):
        print(T + "Warning: The plugin you build has no state.")

    return
예제 #19
0
def write(plugin, filename_prefix):
    fcpp = file(filename_prefix + '.au.cpp', 'w')
    xml_filename = filename_prefix + ".xspif"
    print T + 'writing : ' + filename_prefix + '.au.cpp'

    ######## independent code here ############

    # Variables
    plugId = getText(plugin, 'plugId')
    manufId = getText(plugin, 'manufId')
    maker = getText(plugin, 'maker')
    pluginLabel = getText(plugin, 'label')
    pluginLabel.replace(' ', '')  #remove spaces in
    pluginLabel.title()
    # forces the first letter to upper case
    copyright = getText(plugin, 'copyright')
    comment = getText(plugin, 'comment') + '\n'
    pluginCode = getText(plugin, 'code') + '\n'
    pluginCaption = getText(plugin, 'caption')

    params = plugin.getElementsByTagName('param')
    states = plugin.getElementsByTagName("state")
    pins = plugin.getElementsByTagName("pin")
    callbacks = plugin.getElementsByTagName('callback')

    instantiate = None
    deinstantiate = None
    process = None
    processEvents = None
    activate = None
    deactivate = None

    if callbacks == []:
        print T + "Warning: you haven't implemented any callback" + '\n'
    else:
        for callback in callbacks:
            text = str(getText(callback, 'label'))
            if text == 'instantiate':
                instantiate = callback
            if text == 'deinstantiate':
                deinstantiate = callback
            if text == 'activate':
                activate = callback
            if text == 'deactivate':
                deactivate = callback
            if text == 'process':
                process = callback
            if text == 'processEvents':
                print 'XSPIF Warning: callback "processEvents" not implemented in VST for now'
                #processEvents = callback

    instantiateCode = getText(instantiate, 'code')
    deinstantiateCode = getText(deinstantiate, 'code')
    activateCode = getText(activate, 'code')
    deactivateCode = getText(deactivate, 'code')
    processCode = getText(process, 'code')

    #----------------------------------------------------------------------------
    # CPP file
    #----------------------------------------------------------------------------

    #----------------------------------------------------------------------------
    # file header

    fcpp.write(
        '/****************************************************************\n' +
        'XSPIF: cross(X) Standard PlugIn Framework: ' +
        'XSPIF to AudioUnits\n' + T + filename_prefix + '.au.cpp' + '\n\n' +
        comment + ' This file is generated automatically from the file: ' +
        xml_filename + '\n' + ' DO NOT EDIT BY HAND' + '\n' + T +
        'plugin ID: ' + plugId + '\n' + T + 'manufacturer ID: ' + manufId +
        '\n' + T + 'maker: ' + maker + '\n' + T + 'copyright: ' + copyright +
        '\n' +
        ' ***************************************************************/\n' +
        '\n')

    #includes and independent code
    fcpp.write(
        '\n' + '#include <AUEffectBase.h>' + '\n' + '\n' + '// XSPIF macros' +
        '\n' + '#define XSPIF_GET_SAMPLE_RATE() (GetSampleRate())' + '\n' +
        '#define XSPIF_GET_VECTOR_SIZE() (vector_size)' + '\n' +
        '#define XSPIF_CONTROLOUT() (// NO control out until macosx 10.3)' +
        '\n' + '\n' + '// <from ' + xml_filename + '>' + '\n' + pluginCode +
        '\n' + '// </from ' + xml_filename + '>' + '\n')

    #----------------------------------------------------------------------------
    # Class declaration (TODO:change the base according to the purpose)

    fcpp.write(
        'class ' + pluginLabel + ': public AUEffectBase' + '\n' + '{' + '\n' +
        'public:' + '\n' + T + pluginLabel + '(AudioUnit component);' + '\n' +
        T + '~' + pluginLabel + '();' + '\n' + T + '' + '\n' + T +
        'virtual OSStatus ProcessBufferLists( AudioUnitRenderActionFlags & ioActionFlags,'
        + '\n' + T +
        '                                     const AudioBufferList & inBuffer,'
        + '\n' + T +
        '                                     AudioBufferList & outBuffer,' +
        '\n' + T +
        '                                     UInt32 inFramesToProcess);' +
        '\n' + T + '' + '\n' + T +
        'virtual UInt32 SupportedNumChannels(const AUChannelInfo** outInfo);' +
        '\n' + T + 'virtual ComponentResult Initialize();' + '\n' + T +
        'virtual ComponentResult GetParameterInfo( AudioUnitScope inScope,' +
        '\n' + T +
        '                                          AudioUnitParameterID inParameterId,'
        + '\n' + T +
        '                                          AudioUnitParameterInfo &outParameterInfo);'
        + '\n' + T + '' + '\n' + 'private:' + '\n')

    # declare params
    if params != []:
        fcpp.write(T + '//params' + '\n' + T + 'enum Parameters' + '\n' + T +
                   '{' + '\n')

        for param in params:
            label = getText(param, 'label')
            fcpp.write(T * 2 + 'k' + label + ',' + '\n')

        fcpp.write(T + '' + '\n' + T * 2 + 'kNumParams' + '\n' + T + '};' +
                   '\n' + '\n')

        for param in params:
            label = getText(param, 'label')
            default = getText(param, 'default')
            min = getText(param, 'min')
            max = getText(param, 'max')
            fcpp.write(T + 'static const float ' + label + 'Default = ' +
                       default + ';' + '\n' + T + 'static const float ' +
                       label + 'Min = ' + min + ';' + '\n' + T +
                       'static const float ' + label + 'Max = ' + max + ';' +
                       '\n' + T + 'float ' + label + ';' + '\n' + '\n')

    # declare supported  number of channels
    numInputs = numOutputs = 0

    for pin in pins:
        dir = getText(pin, 'dir')
        channels = int(str(getText(pin, 'channels')))
        if dir == 'In':
            numInputs += channels
        elif dir == 'Out':
            numOutputs += channels

    if numInputs < numOutputs:
        numchannels = numInputs
    else:
        numchannels = numOutputs

    numchannels = str(numchannels)
    numInputs = str(numInputs)
    numOutputs = str(numOutputs)

    fcpp.write(
        T + 'enum {' + '\n' + T * 2 + 'kNumSupportedNumChannels = ' +
        numchannels + '\n' + T + '};' + '\n' + '\n' + T +
        'static AUChannelInfo m_aobSupportedNumChannels[kNumSupportedNumChannels];'
        + '\n' + '\n')

    # process declaration
    fcpp.write(T + 'OSStatus Process(const AudioBufferList& obInBuffers,' +
               '\n' + T + '                 AudioBufferList& obOutBuffers,' +
               '\n' + T + '                 UInt32 inFramesToProcess,' + '\n' +
               T +
               '                 AudioUnitRenderActionFlags& ioactionFlags);' +
               '\n' + '\n')

    # states
    if states != []:
        fcpp.write(T + '// states' + '\n')

        for state in states:
            label = getText(state, 'label')
            type = getText(state, 'type')
            fcpp.write(T + type + ' ' + label + ';' + '\n')

    fcpp.write('\n' + T + 'long vector_size;' + '\n' + '};' + '\n' + '\n')

    #----------------------------------------------------------------------------
    # CPP file
    #--------------------------------------------------------------------------
    fcpp.write("""
//----------------------------------------------------------------------------
// IMPLEMENTATION 
//--------------------------------------------------------------------------
        
""")

    #--------------------------------------------------------------------------
    fcpp.write('//------------------------------------------------------' +
               '\n' + 'COMPONENT_ENTRY(' + pluginLabel + ')' + '\n' + '\n')

    #--------------------------------------------------------------------------
    # Topology

    numInputs = numOutputs = 0

    for pin in pins:
        dir = getText(pin, 'dir')
        channels = int(str(getText(pin, 'channels')))
        if dir == 'In':
            numInputs += channels
        elif dir == 'Out':
            numOutputs += channels

    numInputs = str(numInputs)
    numOutputs = str(numOutputs)

    fcpp.write('#define NUM_INPUTS ' + numInputs + '\n' +
               '#define NUM_OUTPUTS ' + numOutputs + '\n')

    fcpp.write('//------------------------------------------------------' +
               '\n' + 'AUChannelInfo ' + pluginLabel +
               '::m_aobSupportedNumChannels[' + pluginLabel +
               '::kNumSupportedNumChannels] = {{' + numInputs + ',' +
               numOutputs + '}};' + '\n' + '\n')

    #--------------------------------------------------------------------------
    # Plugin Class
    # Plugin Constructor
    fcpp.write('//------------------------------------------------------' +
               '\n' + pluginLabel + '::' + pluginLabel +
               '(AudioUnit component): AUEffectBase(component)' + '\n' + '{' +
               '\n' + T + 'CreateElements();' + '\n' + '\n')

    fcpp.write('\n' + T + '// instantiate callback' + '\n' + T +
               instantiateCode + '\n' + '\n')

    if params != []:
        for param in params:
            label = getText(param, 'label')
            fcpp.write(T + 'SetParameter(k' + label + ',' + label +
                       'Default);' + '\n')

    fcpp.write('}' + '\n' + '\n')

    # Plugin Deconstructor
    fcpp.write('//------------------------------------------------------' +
               '\n' + pluginLabel + '::~' + pluginLabel + '()' + '\n' + '{' +
               '\n')

    fcpp.write('\n' + T + '// deinstantiate callback' + '\n' + T +
               deinstantiateCode + '\n' + '\n')

    fcpp.write('}' + '\n' + '\n')

    # Plugin infos
    fcpp.write('//------------------------------------------------------' +
               '\n' + 'UInt32 ' + pluginLabel +
               '::SupportedNumChannels(const AUChannelInfo **outInfo)' + '\n' +
               '{' + '\n' + T + 'if(outInfo != NULL)' + '\n' + T * 2 +
               '*outInfo = &m_aobSupportedNumChannels[0];' + '\n' + T +
               'return kNumSupportedNumChannels;' + '\n' + '}' + '\n' + '\n')

    fcpp.write(
        '//------------------------------------------------------' + '\n' +
        'ComponentResult ' + pluginLabel +
        '::GetParameterInfo(AudioUnitScope inScope,' + '\n' +
        '                                                  AudioUnitParameterID inParameterID,'
        + '\n' +
        '                                                  AudioUnitParameterInfo &outParameterInfo)'
        + '\n' + '{' + '\n' + T + 'if(inScope != kAudioUnitScope_Global)' +
        '\n' + T * 2 + 'return kAudioUnitErr_InvalidParameter;' + '\n' + '\n' +
        T + 'ComponentResult result = noErr;' + '\n' + '\n' + T +
        'outParameterInfo.flags = kAudioUnitParameterFlag_IsWritable | kAudioUnitParameterFlag_IsReadable | kAudioUnitParameterFlag_Global;'
        + '\n' + '\n' + T + 'char *pcName = outParameterInfo.name;' + '\n' +
        '\n' + T + 'switch(inParameterID)' + '\n' + T + '{' + '\n')
    if params != []:
        for param in params:
            label = getText(param, 'label')
            caption = getText(param, 'caption')
            fcpp.write(
                T * 2 + 'case k' + label + ':' + '\n' + T * 3 +
                'strcpy(pcName,"' + caption + '");' + '\n' + T * 3 +
                'outParameterInfo.unit = kAudioUnitParameterUnit_Generic;' +
                '\n' + T * 3 + 'outParameterInfo.minValue = ' + label +
                'Min;' + '\n' + T * 3 + 'outParameterInfo.maxValue = ' +
                label + 'Max;' + '\n' + T * 3 +
                'outParameterInfo.defaultValue = ' + label + 'Default;' +
                '\n' + T * 3 + 'break;' + '\n' + '\n')

    fcpp.write(T * 2 + 'default:' + '\n' + T * 3 +
               'result = kAudioUnitErr_InvalidParameter;' + '\n' + T * 3 +
               'break;' + '\n' + T + '}' + '\n' + '\n' + T + 'return result;' +
               '\n' + T + '}' + '\n')

    # Plugin suspend and resume
    fcpp.write('//------------------------------------------------------' +
               '\n' + 'ComponentResult ' + pluginLabel + '::Initialize()' +
               '\n' + '{' + '\n' + T + 'return noErr;' + '\n' + '}' + '\n')

    #--------------------------------------------------------------------------
    # processing
    fcpp.write(
        '//------------------------------------------------------' + '\n' +
        'OSStatus ' + pluginLabel +
        '::ProcessBufferLists(AudioUnitRenderActionFlags &ioActionFlags,' +
        '\n' +
        '                                             const AudioBufferList &inBuffer,'
        + '\n' +
        '                                             AudioBufferList &outBuffer,'
        + '\n' +
        '                                             UInt32 inFramesToProcess)'
        + '\n' + '{' + '\n' + T +
        'ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;' + '\n' +
        '\n' + T + 'UInt32 uiInBuffers = inBuffer.mNumberBuffers;' + '\n' + T +
        'UInt32 uiOutBuffers = outBuffer.mNumberBuffers;' + '\n' + '\n' + T +
        'if(uiInBuffers != NUM_INPUTS || uiOutBuffers != NUM_OUTPUTS)' + '\n' +
        T * 2 + 'return kAudioUnitErr_FormatNotSupported;' + '\n' + '\n' + T +
        'return Process(inBuffer, outBuffer, inFramesToProcess, ioActionFlags);'
        + '\n' + '}' + '\n' + '\n')

    fcpp.write(
        '#define XSPIF_WRITE_SAMPLE(dest,index,source) ((dest)[(index)] = (source))'
        + '\n' + '\n')

    fcpp.write(
        '//------------------------------------------------------' + '\n' +
        'OSStatus ' + pluginLabel +
        '::Process(const AudioBufferList &obInBuffers,' + '\n' +
        '                                  AudioBufferList &obOutBuffers,' +
        '\n' + '                                  UInt32 inFramesToProcess,' +
        '\n' +
        '                                  AudioUnitRenderActionFlags &ioActionFlags)'
        + '\n' + '{' + '\n' + T +
        'ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;' + '\n' +
        '\n')

    for i in range(0, int(numInputs)):
        fcpp.write(T + 'const AudioBuffer &obInBuffer' + str(i) +
                   ' = obInBuffers.mBuffers[' + str(i) + '];' + '\n')

    for i in range(0, int(numOutputs)):
        fcpp.write(T + 'AudioBuffer &obOutBuffer' + str(i) +
                   ' = obOutBuffers.mBuffers[' + str(i) + '];' + '\n')

    i = 0
    for pin in pins:
        dir = getText(pin, 'dir')
        if dir == 'In':
            i = i + 1
            label = getText(pin, 'label')
            channels = int(str(getText(pin, 'channels')))
            for j in range(0, channels):
                fcpp.write(T + 'const Float32 *' + label + str(i + j) +
                           ' = (const Float32 *)obInBuffer' + str(i + j - 1) +
                           '.mData;' + '\n')

    i = 0
    for pin in pins:
        dir = getText(pin, 'dir')
        if dir == 'Out':
            i = i + 1
            label = getText(pin, 'label')
            channels = int(str(getText(pin, 'channels')))
            for j in range(0, channels):
                fcpp.write(T + 'Float32 *' + label + str(i + j) +
                           ' = (Float32 *)obOutBuffer' + str(i + j - 1) +
                           '.mData;' + '\n')

    fcpp.write(T + 'vector_size = inFramesToProcess;' + '\n' + '\n')

    if params != []:
        fcpp.write(T + '//retrieving params' + '\n')
        for param in params:
            label = getText(param, 'label')
            fcpp.write(T + label + ' = GetParameter(k' + label + ');' + '\n')

        fcpp.write(T + '//updating states' + '\n')
        for param in params:
            paramCode = getText(param, 'code')
            fcpp.write(T + paramCode + '\n')

    fcpp.write(T + '//****************************************' + '\n' +
               processCode + '\n' +
               '//****************************************' + '\n' + '\n' + T +
               'return noErr;' + '\n' + '}' + '\n')

    fcpp.close
    print T + 'done'

    #--------------------------------------------------------------------------
    # r
    fr = file(filename_prefix + '.au.r', 'w')
    print T + 'writing : ' + filename_prefix + '.au.r'

    fr.write(
        '#include <AudioUnit/AudioUnit.r>' + '\n' + '\n' +
        '// Note that resource IDs must be spaced 2 apart for the ' + "'STR'" +
        ' name and description' + '\n' + '#define kAudioUnitResID_' +
        pluginLabel + '				10000' + '\n' + '\n' +
        '// So you need to define these appropriately for your audio unit.' +
        '\n' +
        "// For the name the convention is to provide your company name and end it with a ':',"
        + '\n' + '// then provide the name of the AudioUnit.' + '\n' +
        '// The Description can be whatever you want.' + '\n' +
        '// For an effect unit the Type and SubType should be left the way they are defined here...'
        + '\n' +
        '//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
        + '\n' + '// SampleEffectUnit' + '\n' +
        '#define RES_ID			kAudioUnitResID_' + pluginLabel + '\n' +
        '#define COMP_TYPE		' + "'aufx'" + '\n' + '#define COMP_SUBTYPE		' +
        plugId + '\n' + '#define COMP_MANUF		' + manufId + '\n' +
        '#define VERSION			0x00010000' + '\n' + '#define NAME			"' + maker +
        ': ' + pluginCaption + '"' + '\n' + '#define DESCRIPTION		"' +
        pluginCaption + '"' + '\n' + '#define ENTRY_POINT		"' + pluginLabel +
        'Entry"' + '\n' + '\n' + '#include "AUResources.r"' + '\n')
    fr.close

    print T + 'done'

    fexp = file(filename_prefix + '.exp', 'w')
    print T + 'writing : ' + filename_prefix + '.exp'
    fexp.write('_' + pluginLabel + 'Entry')
    fexp.close
    print T + 'done'

    return