cwFlow,cwFlowNet,cwFlowTypes,cwFlowProc : Initial working subnet.

This commit is contained in:
kevin 2024-05-05 17:31:42 -04:00
parent 4a90b6b1b6
commit e86451b7a2
10 changed files with 661 additions and 86 deletions

View File

@ -29,6 +29,7 @@ namespace cw
} library_t; } library_t;
library_t g_library[] = { library_t g_library[] = {
{ "subnet", &subnet::members },
{ "poly", &poly::members }, { "poly", &poly::members },
{ "midi_in", &midi_in::members }, { "midi_in", &midi_in::members },
{ "midi_out", &midi_out::members }, { "midi_out", &midi_out::members },
@ -175,7 +176,7 @@ namespace cw
// get the class member functions // get the class member functions
if((cd->members = _find_library_record(cd->label)) == nullptr ) if((cd->members = _find_library_record(cd->label)) == nullptr )
{ {
rc = cwLogError(kSyntaxErrorRC,"The '%s' class member function record could not be found..", cd->label ); rc = cwLogError(kSyntaxErrorRC,"The '%s' class member function record could not be found.", cd->label );
goto errLabel; goto errLabel;
} }
@ -243,21 +244,319 @@ namespace cw
return rc; return rc;
} }
rc_t _find_subnet_proc_class_desc( flow_t* p, const object_t* subnetProcD, const char* procInstLabel, const class_desc_t*& class_desc_ref )
{
rc_t rc = kOkRC;
const object_t* procInstD = nullptr;
const object_t* classStr = nullptr;
const class_desc_t* class_desc = nullptr;
const char* class_label = nullptr;
class_desc_ref = nullptr;
// find the proc inst dict in the subnet
if((procInstD = subnetProcD->find_child(procInstLabel)) == nullptr )
{
rc = cwLogError(kSyntaxErrorRC,"The proc instance '%s' from the proxy var list could not be foud in the subnet.",cwStringNullGuard(procInstLabel));
goto errLabel;
}
// find the proc class label of the proc inst
if((classStr = procInstD->find_child("class")) == nullptr || (rc = classStr->value(class_label))!=kOkRC)
{
rc = cwLogError(kSyntaxErrorRC,"The 'class' field could not be found in the '%s' proc instance record.", cwStringNullGuard(procInstLabel));
goto errLabel;
}
// find the associated class desc record
if((class_desc_ref = class_desc_find(p,class_label)) == nullptr)
{
rc = cwLogError(kEleNotFoundRC,"The class desc record '%s' for the proc instance '%s' could not be found.",class_label,cwStringNullGuard(procInstLabel));
goto errLabel;
}
errLabel:
return rc;
}
rc_t _destroy( flow_t* p) rc_t _parse_subnet_var_proxy_string( const char* proxyStr, char*& procLabel_ref, char*& varLabel_ref )
{
rc_t rc = kOkRC;
procLabel_ref = nullptr;
varLabel_ref = nullptr;
const char* period;
// find the separating period
if((period = firstMatchChar(proxyStr,'.')) == nullptr )
{
rc = cwLogError(kSyntaxErrorRC,"The separating '.' could not be found in the proxy string '%s'.",cwStringNullGuard(proxyStr));
goto errLabel;
}
// validate the length of the proc inst label
if( period-proxyStr == 0 )
{
rc = cwLogError(kSyntaxErrorRC,"No proxy proc instance was found in the proxy string '%s'.",cwStringNullGuard(proxyStr));
goto errLabel;
}
// validate the length of the var label
if( textLength(period+1) == 0 )
{
rc = cwLogError(kSyntaxErrorRC,"No proxy var was found in the proxy string '%s'.",cwStringNullGuard(proxyStr));
goto errLabel;
}
procLabel_ref = mem::duplStr(proxyStr,period-proxyStr);
varLabel_ref = mem::duplStr(period+1);
errLabel:
return rc;
}
void _var_desc_release( var_desc_t*& vd )
{
mem::release(vd->proxyProcLabel);
mem::release(vd->proxyVarLabel);
mem::release(vd);
}
rc_t _create_subnet_var_desc( flow_t* p, class_desc_t* wrapProcClassDesc, const object_t* subnetProcD, const object_t* varDescPair, var_desc_t*& vd_ref )
{
rc_t rc = kOkRC;
const object_t* flagsCfg = nullptr;
const char* proxyStr = nullptr;
const char* docStr = nullptr;
const char* varLabel = nullptr;
char* proxyProcLabel = nullptr;
char* proxyVarLabel = nullptr;
unsigned proxyVarFlags = 0;
const class_desc_t* proxy_class_desc = nullptr;
const var_desc_t* proxy_var_desc = nullptr;
bool subnetOutVarFl = false;
var_desc_t* var_desc = mem::allocZ<var_desc_t>();
vd_ref = nullptr;
// verify that the var label is valid
if(!varDescPair->is_pair() || (varLabel=varDescPair->pair_label())==nullptr || varDescPair->pair_value()==nullptr || !varDescPair->pair_value()->is_dict() )
{
rc = cwLogError(kSyntaxErrorRC,"The proxy var entry is not valid.");
goto errLabel;
}
// parse the var desc dictionary
if((rc = varDescPair->pair_value()->getv("proxy",proxyStr,
"doc", docStr)) != kOkRC )
{
rc = cwLogError(rc,"Parsing failed on the proxy var dictionary.");
goto errLabel;
}
// parse the var desc dictionary optional fields
if((rc = varDescPair->pair_value()->getv_opt("flags", flagsCfg)) != kOkRC )
{
rc = cwLogError(rc,"Optional attribute parsing failed on the proxy var dictionary.");
goto errLabel;
}
// parse the proxy string into it's two parts: <proc>.<var>
if((rc = _parse_subnet_var_proxy_string( proxyStr, proxyProcLabel, proxyVarLabel )) != kOkRC )
{
goto errLabel;
}
// locate the class desc associated with proxy proc
if((rc = _find_subnet_proc_class_desc( p, subnetProcD, proxyProcLabel, proxy_class_desc )) != kOkRC )
{
goto errLabel;
}
// locate the var desc associated with the proxy proc var
if((proxy_var_desc = var_desc_find( proxy_class_desc, proxyVarLabel)) == nullptr )
{
rc = cwLogError(kEleNotFoundRC,"The variable desc '%s.%s' could not be found.",cwStringNullGuard(proxyProcLabel),cwStringNullGuard(proxyVarLabel));
goto errLabel;
}
// most of the fields for the proxy are taken directly from the the actual var ...
*var_desc = *proxy_var_desc;
var_desc->label = varLabel; // ... but the label and doc are overwritten from subnet desc.
var_desc->docText = docStr;
var_desc->proxyProcLabel = proxyProcLabel;
var_desc->proxyVarLabel = proxyVarLabel;
var_desc->link = nullptr;
if((rc = _is_var_flag_set( flagsCfg, "out", wrapProcClassDesc->label, var_desc->label, subnetOutVarFl )) != kOkRC )
goto errLabel;
var_desc->flags = cwEnaFlag(var_desc->flags, kSubnetOutVarFl, subnetOutVarFl);
vd_ref = var_desc;
errLabel:
if( rc != kOkRC )
{
rc = cwLogError(rc,"The creation of proxy var '%s' failed.",cwStringNullGuard(varLabel));
_var_desc_release(var_desc);
}
return rc;
}
rc_t _parse_subnet_vars( flow_t* p, class_desc_t* class_desc, const object_t* subnetProcD, const object_t* varD )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
if( p == nullptr ) unsigned varN = 0;
if( !varD->is_dict() )
{
rc = cwLogError(kSyntaxErrorRC,"The proxy variable dictionary is invalid.");
goto errLabel;
}
varN = varD->child_count();
// Fill the class_Desc.varDescL list from the subnet 'vars' dictioanry
for(unsigned i=0; i<varN; ++i)
{
const object_t* child_pair = varD->child_ele(i);
var_desc_t* var_desc = nullptr;
if((rc = _create_subnet_var_desc( p, class_desc, subnetProcD, child_pair, var_desc )) != kOkRC )
goto errLabel;
var_desc->link = class_desc->varDescL;
class_desc->varDescL = var_desc;
//printf("Wrapper var-desc created: %i of %i : %s:%s proxy:%s:%s flags:%i.\n", i, varN, class_desc->label, var_desc->label, var_desc->proxyProcLabel,var_desc->proxyVarLabel,var_desc->flags);
}
errLabel:
return rc;
}
rc_t _create_subnet_class_desc( flow_t* p, const object_t* class_obj, class_desc_t* class_desc )
{
rc_t rc = kOkRC;
const object_t* varD = nullptr;
const object_t* subnetD = nullptr;
const object_t* subnetProcD = nullptr;
const object_t* subnetPresetD = nullptr;
const char* subnetProcDescLabel = nullptr;
// Validate the subnet proc desc label and value
if( class_obj==nullptr || !class_obj->is_pair() || class_obj->pair_value()==nullptr || !class_obj->pair_value()->is_dict() || (subnetProcDescLabel = class_obj->pair_label()) == nullptr )
{
rc = cwLogError(kInvalidArgRC,"An invalid subnet description '%s' was encountered.",cwStringNullGuard(subnetProcDescLabel));
goto errLabel;
}
// verify that another subnet with the same name does not already exist
if( class_desc_find(p,subnetProcDescLabel) != nullptr )
{
rc = cwLogError(kInvalidStateRC,"A subnet named '%s' already exists.",subnetProcDescLabel);
goto errLabel;
}
class_desc->cfg = class_obj->pair_value();
class_desc->label = class_obj->pair_label();
// get the 'subnet' members record
if((class_desc->members = _find_library_record("subnet")) == nullptr )
{
rc = cwLogError(kSyntaxErrorRC,"The 'subnet' class member function record could not be found." );
goto errLabel;
}
// get the variable description
if((rc = class_desc->cfg->getv_opt("vars", varD,
"network", subnetD)) != kOkRC )
{
rc = cwLogError(rc,"Parse failed while parsing subnet desc:'%s'", cwStringNullGuard(class_desc->label) );
goto errLabel;
}
// get the subnet proc and preset dictionaries
if((rc = subnetD->getv("procs", subnetProcD,
"presets", subnetPresetD)) != kOkRC )
{
rc = cwLogError(rc,"Parse failed on the 'network' element.");
goto errLabel;
}
// fill class_desc.varDescL from the subnet vars dictionary
if((rc = _parse_subnet_vars( p, class_desc, subnetProcD, varD )) != kOkRC )
{
rc = cwLogError(rc,"Subnet 'vars' processing failed.");
goto errLabel;
}
errLabel:
if(rc != kOkRC )
rc = cwLogError(rc,"'proc' class description creation failed for the subnet '%s'. ",cwStringNullGuard(subnetProcDescLabel));
return rc;
}
rc_t _parse_subnet_cfg(flow_t* p, const object_t* subnetCfg)
{
rc_t rc = kOkRC;
if( !subnetCfg->is_dict() )
return cwLogError(kSyntaxErrorRC,"The subnet class description dictionary does not have dictionary syntax.");
unsigned subnetDescN = subnetCfg->child_count();
p->subnetDescA = mem::allocZ<class_desc_t>( subnetDescN );
// for each subnet description
for(unsigned i=0; i<subnetDescN; ++i)
{
const object_t* subnet_obj = subnetCfg->child_ele(i);
if((rc = _create_subnet_class_desc(p, subnet_obj, p->subnetDescA + i )) != kOkRC )
{
rc = cwLogError(rc,"Subnet class description create failed on the subnet at index:%i.",i);
goto errLabel;
}
// we have to update the size of the subnet class array
// as we go because we may want to find subnets classes within
// subnets which are definted later and so the length p->subnetA[]
// must be correct
p->subnetDescN += 1;
}
assert( subnetDescN == p->subnetDescN );
errLabel:
if( rc != kOkRC )
{
rc = cwLogError(rc,"Subnet processing failed.");
}
return rc; return rc;
network_destroy(p->net); }
// release the class records void _release_class_desc_array( class_desc_t*& classDescA, unsigned classDescN )
for(unsigned i=0; i<p->classDescN; ++i)
{ {
class_desc_t* cd = p->classDescA + i; // release the class records
for(unsigned i=0; i<classDescN; ++i)
{
class_desc_t* cd = classDescA + i;
// release the var desc list // release the var desc list
var_desc_t* vd0 = cd->varDescL; var_desc_t* vd0 = cd->varDescL;
@ -265,7 +564,7 @@ namespace cw
while( vd0 != nullptr ) while( vd0 != nullptr )
{ {
vd1 = vd0->link; vd1 = vd0->link;
mem::release(vd0); _var_desc_release(vd0);
vd0 = vd1; vd0 = vd1;
} }
@ -280,8 +579,20 @@ namespace cw
} }
} }
mem::release(p->classDescA); mem::release(classDescA);
}
rc_t _destroy( flow_t* p)
{
rc_t rc = kOkRC;
if( p == nullptr )
return rc;
network_destroy(p->net);
_release_class_desc_array(p->classDescA,p->classDescN);
_release_class_desc_array(p->subnetDescA,p->subnetDescN);
mem::release(p); mem::release(p);
@ -308,8 +619,9 @@ void cw::flow::print_external_device( const external_device_t* dev )
cw::rc_t cw::flow::create( handle_t& hRef, cw::rc_t cw::flow::create( handle_t& hRef,
const object_t& classCfg, const object_t* classCfg,
const object_t& flowCfg, const object_t* flowCfg,
const object_t* subnetCfg,
external_device_t* deviceA, external_device_t* deviceA,
unsigned deviceN ) unsigned deviceN )
{ {
@ -317,24 +629,32 @@ cw::rc_t cw::flow::create( handle_t& hRef,
const object_t* networkCfg = nullptr; const object_t* networkCfg = nullptr;
bool printClassDictFl = false; bool printClassDictFl = false;
bool printNetworkFl = false; bool printNetworkFl = false;
variable_t* proxyVarL = nullptr;
if(( rc = destroy(hRef)) != kOkRC ) if(( rc = destroy(hRef)) != kOkRC )
return rc; return rc;
flow_t* p = mem::allocZ<flow_t>(); flow_t* p = mem::allocZ<flow_t>();
p->flowCfg = &flowCfg; // TODO: duplicate cfg? p->flowCfg = flowCfg; // TODO: duplicate cfg?
p->deviceA = deviceA; p->deviceA = deviceA;
p->deviceN = deviceN; p->deviceN = deviceN;
// parse the class description array // parse the class description array
if((rc = _parse_class_cfg(p,&classCfg)) != kOkRC ) if((rc = _parse_class_cfg(p,classCfg)) != kOkRC )
{ {
rc = cwLogError(kSyntaxErrorRC,"Error parsing the class description list."); rc = cwLogError(kSyntaxErrorRC,"Error parsing the class description list.");
goto errLabel; goto errLabel;
} }
if( subnetCfg != nullptr )
if((rc = _parse_subnet_cfg(p,subnetCfg)) != kOkRC )
{
rc = cwLogError(kSyntaxErrorRC,"Error parsing the subnet list.");
goto errLabel;
}
// parse the main audio file processor cfg record // parse the main audio file processor cfg record
if((rc = flowCfg.getv("network", networkCfg)) != kOkRC ) if((rc = flowCfg->getv("network", networkCfg)) != kOkRC )
{ {
rc = cwLogError(kSyntaxErrorRC,"Error parsing the required flow configuration parameters."); rc = cwLogError(kSyntaxErrorRC,"Error parsing the required flow configuration parameters.");
goto errLabel; goto errLabel;
@ -344,7 +664,7 @@ cw::rc_t cw::flow::create( handle_t& hRef,
p->sample_rate = kDefaultSampleRate; p->sample_rate = kDefaultSampleRate;
// parse the optional args // parse the optional args
if((rc = flowCfg.getv_opt("framesPerCycle", p->framesPerCycle, if((rc = flowCfg->getv_opt("framesPerCycle", p->framesPerCycle,
"sample_rate", p->sample_rate, "sample_rate", p->sample_rate,
"maxCycleCount", p->maxCycleCount, "maxCycleCount", p->maxCycleCount,
"multiPriPresetProbFl", p->multiPriPresetProbFl, "multiPriPresetProbFl", p->multiPriPresetProbFl,
@ -375,7 +695,7 @@ cw::rc_t cw::flow::create( handle_t& hRef,
class_dict_print( p ); class_dict_print( p );
// instantiate the network // instantiate the network
if((rc = network_create(p,networkCfg,p->net)) != kOkRC ) if((rc = network_create(p,networkCfg,p->net,proxyVarL)) != kOkRC )
{ {
rc = cwLogError(rc,"Network creation failed."); rc = cwLogError(rc,"Network creation failed.");
goto errLabel; goto errLabel;
@ -535,10 +855,12 @@ cw::rc_t cw::flow::test( const object_t* cfg, int argc, const char* argv[] )
rc_t rc = kOkRC; rc_t rc = kOkRC;
handle_t flowH; handle_t flowH;
object_t* class_cfg = nullptr; const char* proc_cfg_fname = nullptr;
const char* subnet_cfg_fname = nullptr;
const object_t* test_cases_cfg = nullptr; const object_t* test_cases_cfg = nullptr;
object_t* class_cfg = nullptr;
object_t* subnet_cfg = nullptr;
const object_t* test_cfg = nullptr; const object_t* test_cfg = nullptr;
const char* flow_proc_fname;
if( argc < 2 || textLength(argv[1]) == 0 ) if( argc < 2 || textLength(argv[1]) == 0 )
{ {
@ -546,13 +868,20 @@ cw::rc_t cw::flow::test( const object_t* cfg, int argc, const char* argv[] )
goto errLabel; goto errLabel;
} }
if((rc = cfg->getv("flow_proc_fname",flow_proc_fname, if((rc = cfg->getv("proc_cfg_fname",proc_cfg_fname,
"test_cases",test_cases_cfg)) != kOkRC ) "test_cases", test_cases_cfg)) != kOkRC )
{ {
rc = cwLogError(rc,"The name of the flow_proc_dict file could not be parsed."); rc = cwLogError(rc,"The name of the flow_proc_dict file could not be parsed.");
goto errLabel; goto errLabel;
} }
// get the subnet cfg filename
if((rc = cfg->getv_opt("subnet_cfg_fname",subnet_cfg_fname)) != kOkRC )
{
rc = cwLogError(rc,"The name of the subnet file could not be parsed.");
goto errLabel;
}
// find the user requested test case // find the user requested test case
if((test_cfg = test_cases_cfg->find_child(argv[1])) == nullptr ) if((test_cfg = test_cases_cfg->find_child(argv[1])) == nullptr )
{ {
@ -560,15 +889,22 @@ cw::rc_t cw::flow::test( const object_t* cfg, int argc, const char* argv[] )
goto errLabel; goto errLabel;
} }
// parse the flow-proc-cfg // parse the proc dict. file
if((rc = objectFromFile(flow_proc_fname,class_cfg)) != kOkRC ) if((rc = objectFromFile(proc_cfg_fname,class_cfg)) != kOkRC )
{ {
rc = cwLogError(rc,"The flow proc dict could not be read from '%s'.",cwStringNullGuard(flow_proc_fname)); rc = cwLogError(rc,"The proc dictionary could not be read from '%s'.",cwStringNullGuard(proc_cfg_fname));
goto errLabel;
}
// parse the subnet dict file
if((rc = objectFromFile(subnet_cfg_fname,subnet_cfg)) != kOkRC )
{
rc = cwLogError(rc,"The subnet dictionary could not be read from '%s'.",cwStringNullGuard(subnet_cfg_fname));
goto errLabel; goto errLabel;
} }
// create the flow object // create the flow object
if((rc = create( flowH, *class_cfg, *test_cfg)) != kOkRC ) if((rc = create( flowH, class_cfg, test_cfg, subnet_cfg)) != kOkRC )
{ {
rc = cwLogError(rc,"Flow object create failed."); rc = cwLogError(rc,"Flow object create failed.");
goto errLabel; goto errLabel;

View File

@ -15,8 +15,9 @@ namespace cw
rc_t create( handle_t& hRef, rc_t create( handle_t& hRef,
const object_t& classCfg, const object_t* classCfg,
const object_t& networkCfg, const object_t* networkCfg,
const object_t* subnetCfg = nullptr,
external_device_t* deviceA = nullptr, external_device_t* deviceA = nullptr,
unsigned deviceN = 0); unsigned deviceN = 0);

View File

@ -146,7 +146,7 @@ namespace cw
net->stateId = net_idx == 0 ? kActiveStateId : kInactiveStateId; net->stateId = net_idx == 0 ? kActiveStateId : kInactiveStateId;
net->net_idx = net_idx; net->net_idx = net_idx;
if((rc = flow::create( net->flowH, classCfg, networkCfg, net->deviceA, deviceN )) == kOkRC ) if((rc = flow::create( net->flowH, &classCfg, &networkCfg, nullptr, net->deviceA, deviceN )) == kOkRC )
net->deviceN = deviceN; net->deviceN = deviceN;
else else
{ {

View File

@ -1264,7 +1264,15 @@ namespace cw
return rc; return rc;
} }
rc_t _parse_in_list( network_t& net, instance_t* inst, proc_inst_parse_state_t& pstate ) const variable_t* _find_proxy_var( const char* procInstLabel, const char* varLabel, const variable_t* proxyVarL )
{
for(const variable_t* proxyVar=proxyVarL; proxyVar!=nullptr; proxyVar=proxyVar->var_link)
if( textIsEqual(proxyVar->varDesc->proxyProcLabel,procInstLabel) && textIsEqual(proxyVar->varDesc->proxyVarLabel,varLabel) )
return proxyVar;
return nullptr;
}
rc_t _parse_in_list( network_t& net, instance_t* inst, variable_t* proxyVarL, proc_inst_parse_state_t& pstate )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
@ -1315,6 +1323,16 @@ namespace cw
// create the var // create the var
if( in_stmt.create_in_fl ) if( in_stmt.create_in_fl )
{ {
const variable_t* proxy_var;
// a variable cannot be in the 'in' list if it is used a a subnet variable
if((proxy_var = _find_proxy_var(inst->label, in_stmt.in_var_ele.label, proxyVarL)) != nullptr )
{
rc = cwLogError(kSyntaxErrorRC,"The variable:'%s' cannot be used as the in-var of an 'in' statement if it is a subnet variable: '%s'.",cwStringNullGuard(in_stmt.in_var_ele.label),cwStringNullGuard(proxy_var->label));
goto errLabel;
}
for(unsigned i=0; i<in_stmt.iter_cnt; ++i) for(unsigned i=0; i<in_stmt.iter_cnt; ++i)
{ {
variable_t* dum = nullptr; variable_t* dum = nullptr;
@ -1339,12 +1357,105 @@ namespace cw
return rc; return rc;
} }
bool _is_var_inst_already_created( const char* var_label, const proc_inst_parse_state_t& pstate ) // This function is used to create the variables on procs
// inside subnets which are represented by interface variables
// on the subnet wrapper.
// 'inst' is a proc on the subnet's internal proc list
// 'wrap_varL' is a list of all the variables on the wrapper proc.
// These wrapper variables mirror variables on some of the internal subnet proc's.
// The function finds the variables in wrap_varL that mirror
// variables in 'inst' and instantiates them. It then connects the wrapper
// variable to the proc-inst variable for input variables or
// proc-inst variable to the wrapper variable for output variables.
rc_t _create_proxied_vars( instance_t* inst, variable_t* wrap_varL )
{
rc_t rc = kOkRC;
for(variable_t* wrap_var=wrap_varL; wrap_var!=nullptr; wrap_var=wrap_var->var_link )
{
// if this wrap_var is on this proc (inst->label)
if( textIsEqual(wrap_var->varDesc->proxyProcLabel,inst->label) )
{
variable_t* var;
if((rc = var_create( inst, wrap_var->varDesc->proxyVarLabel, wrap_var->label_sfx_id, kInvalidId, wrap_var->chIdx, nullptr, kInvalidTFl, var )) != kOkRC )
{
rc = cwLogError(rc,"Subnet variable creation failed for %s:%s on wrapper variable:%s:%s.",cwStringNullGuard(wrap_var->varDesc->proxyProcLabel),cwStringNullGuard(wrap_var->varDesc->proxyVarLabel),cwStringNullGuard(wrap_var->inst->label),cwStringNullGuard(wrap_var->label));
goto errLabel;
}
//printf("Proxy matched: %s %s %s : flags:%i.\n",inst->label, wrap_var->varDesc->proxyVarLabel, wrap_var->label,wrap_var->varDesc->flags );
var->flags |= kProxiedVarFl;
if( cwIsFlag(wrap_var->varDesc->flags,kSubnetOutVarFl) )
var->flags |= kProxiedOutVarFl;
}
}
errLabel:
return rc;
}
variable_t* _find_wrap_var( variable_t* wrap_varL, variable_t* var )
{
for(variable_t* wrap_var=wrap_varL; wrap_var!=nullptr; wrap_var=wrap_var->var_link)
if( textIsEqual(wrap_var->varDesc->proxyProcLabel,var->inst->label) && textIsEqual(wrap_var->varDesc->proxyVarLabel,var->label) && (wrap_var->label_sfx_id==var->label_sfx_id) )
return wrap_var;
return nullptr;
}
rc_t _connect_wrapped_vars( instance_t* inst, variable_t* wrap_varL )
{
rc_t rc = kOkRC;
for(variable_t* var=inst->varL; var!=nullptr; var=var->var_link)
{
if( cwIsFlag(var->flags,kProxiedVarFl) )
{
variable_t* wrap_var;
if((wrap_var = _find_wrap_var(wrap_varL,var)) == nullptr )
{
rc = cwLogError(kEleNotFoundRC,"The wrapped variable '%s:%i' not found on '%s:%i'.",var->label,var->label_sfx_id,inst->label,inst->label_sfx_id);
goto errLabel;
}
if( cwIsFlag(var->flags,kProxiedOutVarFl) )
{
//printf("Proxy connection: %i %s:%i-%s:%i -> %s:%i-%s:%i\n",var->flags,
// var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,
// wrap_var->inst->label,wrap_var->inst->label_sfx_id,wrap_var->label,wrap_var->label_sfx_id );
var_connect(var,wrap_var);
}
else
{
//printf("Proxy connection: %i %s:%i-%s:%i -> %s:%i-%s:%i\n",var->flags,
// wrap_var->inst->label,wrap_var->inst->label_sfx_id,wrap_var->label,wrap_var->label_sfx_id,
// var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id );
var_connect(wrap_var,var);
}
}
}
errLabel:
return rc;
}
bool _is_var_inst_already_created( instance_t* inst, const char* var_label, const proc_inst_parse_state_t& pstate )
{ {
for(unsigned i=0; i<pstate.in_arrayN; ++i) for(unsigned i=0; i<pstate.in_arrayN; ++i)
if( textIsEqual(pstate.in_array[i].in_var_ele.label,var_label) && pstate.in_array[i].create_in_fl ) if( textIsEqual(pstate.in_array[i].in_var_ele.label,var_label) && pstate.in_array[i].create_in_fl )
return true; return true;
for(variable_t* var=inst->varL; var!=nullptr; var=var->var_link)
if( textIsEqual(var->label,var_label) )
return true;
return false; return false;
} }
@ -1545,7 +1656,12 @@ namespace cw
return n; return n;
} }
rc_t _create_instance( flow_t* p, const object_t* proc_inst_cfg, unsigned sfx_id, network_t& net, instance_t*& inst_ref ) rc_t _create_instance( flow_t* p,
const object_t* proc_inst_cfg,
unsigned sfx_id,
network_t& net,
variable_t* proxyVarL,
instance_t*& inst_ref )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
proc_inst_parse_state_t pstate = {}; proc_inst_parse_state_t pstate = {};
@ -1558,7 +1674,7 @@ namespace cw
if((rc = _parse_proc_inst_cfg( net, proc_inst_cfg, sfx_id, pstate )) != kOkRC ) if((rc = _parse_proc_inst_cfg( net, proc_inst_cfg, sfx_id, pstate )) != kOkRC )
goto errLabel; goto errLabel;
// locate the class desc // locate the proc class desc
if(( class_desc = class_desc_find(p,pstate.inst_clas_label)) == nullptr ) if(( class_desc = class_desc_find(p,pstate.inst_clas_label)) == nullptr )
{ {
rc = cwLogError(kSyntaxErrorRC,"The flow class '%s' was not found.",cwStringNullGuard(pstate.inst_clas_label)); rc = cwLogError(kSyntaxErrorRC,"The flow class '%s' was not found.",cwStringNullGuard(pstate.inst_clas_label));
@ -1586,15 +1702,22 @@ namespace cw
inst->net = &net; inst->net = &net;
// parse the in-list ,fill in pstate.in_array, and create var instances for var's referenced by in-list // parse the in-list ,fill in pstate.in_array, and create var instances for var's referenced by in-list
if((rc = _parse_in_list( net, inst, pstate )) != kOkRC ) if((rc = _parse_in_list( net, inst, proxyVarL, pstate )) != kOkRC )
{ {
rc = cwLogError(rc,"in-list parse failed on proc instance '%s:%i'.",cwStringNullGuard(inst->label),sfx_id); rc = cwLogError(rc,"in-list parse failed on proc instance '%s:%i'.",cwStringNullGuard(inst->label),sfx_id);
goto errLabel; goto errLabel;
} }
// create the vars that are connected to the wrapper proxy vars
if((rc = _create_proxied_vars( inst, proxyVarL )) != kOkRC )
{
rc = cwLogError(rc,"Proxy vars create failed on proc instance '%s:%i'.",cwStringNullGuard(inst->label),sfx_id);
goto errLabel;
}
// Instantiate all the variables in the class description - that were not already created in _parse_in_list() // Instantiate all the variables in the class description - that were not already created in _parse_in_list()
for(var_desc_t* vd=class_desc->varDescL; vd!=nullptr; vd=vd->link) for(var_desc_t* vd=class_desc->varDescL; vd!=nullptr; vd=vd->link)
if( !_is_var_inst_already_created( vd->label, pstate ) && cwIsNotFlag(vd->type,kRuntimeTFl) ) if( !_is_var_inst_already_created( inst, vd->label, pstate ) && cwIsNotFlag(vd->type,kRuntimeTFl) )
{ {
variable_t* var = nullptr; variable_t* var = nullptr;
if((rc = var_create( inst, vd->label, kBaseSfxId, kInvalidId, kAnyChIdx, vd->val_cfg, kInvalidTFl, var )) != kOkRC ) if((rc = var_create( inst, vd->label, kBaseSfxId, kInvalidId, kAnyChIdx, vd->val_cfg, kInvalidTFl, var )) != kOkRC )
@ -1632,6 +1755,14 @@ namespace cw
goto errLabel; goto errLabel;
} }
// Connect the wrapped vars in this subnet proc
if((rc = _connect_wrapped_vars( inst, proxyVarL )) != kOkRC )
{
rc = cwLogError(rc,"Wrapped connection processing failed.");
goto errLabel;
}
// Complete the instantiation of the proc instance by calling the custom instance creation function. // Complete the instantiation of the proc instance by calling the custom instance creation function.
// Call the custom instance create() function. // Call the custom instance create() function.
@ -1927,6 +2058,7 @@ namespace cw
cw::rc_t cw::flow::network_create( flow_t* p, cw::rc_t cw::flow::network_create( flow_t* p,
const object_t* networkCfg, const object_t* networkCfg,
network_t& net, network_t& net,
variable_t* proxyVarL,
unsigned polyCnt, unsigned polyCnt,
network_order_id_t orderId ) network_order_id_t orderId )
{ {
@ -1973,7 +2105,7 @@ cw::rc_t cw::flow::network_create( flow_t* p,
assert(net.proc_arrayN < net.proc_arrayAllocN ); assert(net.proc_arrayN < net.proc_arrayAllocN );
// create the proc instance // create the proc instance
if( (rc= _create_instance( p, proc_cfg, sfx_id, net, net.proc_array[net.proc_arrayN] ) ) != kOkRC ) if( (rc= _create_instance( p, proc_cfg, sfx_id, net, proxyVarL, net.proc_array[net.proc_arrayN] ) ) != kOkRC )
{ {
//rc = cwLogError(rc,"The instantiation at proc index %i is invalid.",net.proc_arrayN); //rc = cwLogError(rc,"The instantiation at proc index %i is invalid.",net.proc_arrayN);
goto errLabel; goto errLabel;

View File

@ -13,6 +13,7 @@ namespace cw
rc_t network_create( flow_t* p, rc_t network_create( flow_t* p,
const object_t* networkCfg, const object_t* networkCfg,
network_t& net, // Network object to be filled with new proc instances network_t& net, // Network object to be filled with new proc instances
variable_t* proxyVarL, //
unsigned polyCnt = 1, // Count of networks to create unsigned polyCnt = 1, // Count of networks to create
network_order_id_t orderId = kNetFirstPolyOrderId // Set the network exec order. network_order_id_t orderId = kNetFirstPolyOrderId // Set the network exec order.
); );

View File

@ -120,6 +120,80 @@ namespace cw
} }
//------------------------------------------------------------------------------------------------------------------
//
// subnet
//
namespace subnet
{
typedef struct
{
network_t net;
} inst_t;
rc_t _create( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
const object_t* networkCfg = nullptr;
if((rc = proc->class_desc->cfg->getv("network",networkCfg)) != kOkRC )
{
rc = cwLogError(rc,"The subnet 'network' cfg. was not found.");
goto errLabel;
}
if((rc = network_create(proc->ctx,networkCfg,p->net,proc->varL)) != kOkRC )
{
rc = cwLogError(rc,"Creation failed on the subnet internal network.");
goto errLabel;
}
// Set the internal net pointer in the base proc instance
// so that network based utilities can scan it
proc->internal_net = &p->net;
errLabel:
return rc;
}
rc_t _destroy( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
network_destroy(p->net);
return rc;
}
rc_t _value( instance_t* proc, inst_t* p, variable_t* var )
{
rc_t rc = kOkRC;
return rc;
}
rc_t _exec( instance_t* proc, inst_t* p )
{
rc_t rc = kOkRC;
if((rc = exec_cycle(p->net)) != kOkRC )
rc = cwLogError(rc,"poly internal network exec failed.");
return rc;
}
rc_t _report( instance_t* proc, inst_t* p )
{ return kOkRC; }
class_members_t members = {
.create = std_create<inst_t>,
.destroy = std_destroy<inst_t>,
.value = std_value<inst_t>,
.exec = std_exec<inst_t>,
.report = std_report<inst_t>
};
}
//------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------
// //
@ -147,6 +221,7 @@ namespace cw
inst_t* inst = mem::allocZ<inst_t>(); inst_t* inst = mem::allocZ<inst_t>();
const object_t* networkCfg = nullptr; const object_t* networkCfg = nullptr;
const char* order_label = nullptr; const char* order_label = nullptr;
variable_t* proxyVarL = nullptr;
proc->userPtr = inst; proc->userPtr = inst;
@ -181,7 +256,7 @@ namespace cw
} }
} }
if((rc = network_create(proc->ctx,networkCfg,inst->net,inst->count )) != kOkRC ) if((rc = network_create(proc->ctx,networkCfg,inst->net,proxyVarL,inst->count)) != kOkRC )
{ {
rc = cwLogError(rc,"Creation failed on the internal network."); rc = cwLogError(rc,"Creation failed on the internal network.");
goto errLabel; goto errLabel;
@ -1004,6 +1079,8 @@ namespace cw
if( src_abuf->srate!=0 && inst->durSmpN % ((unsigned)src_abuf->srate*60) == 0 ) if( src_abuf->srate!=0 && inst->durSmpN % ((unsigned)src_abuf->srate*60) == 0 )
printf("audio file out: %5.1f min\n", inst->durSmpN/(src_abuf->srate*60)); printf("audio file out: %5.1f min\n", inst->durSmpN/(src_abuf->srate*60));
//if( 48000 <= inst->durSmpN && inst->durSmpN < 49000 )
// printf("break\n");
} }
return rc; return rc;
@ -1786,6 +1863,8 @@ namespace cw
goto errLabel; goto errLabel;
} }
printf("%s: sr:%f hz:%f phs:%f dc:%f gain:%f\n",ctx->label,srate,hz,phase,dc,gain);
// create one output audio buffer // create one output audio buffer
rc = var_register_and_set( ctx, "out", kBaseSfxId, rc = var_register_and_set( ctx, "out", kBaseSfxId,
kOutPId, kAnyChIdx, srate, chCnt, ctx->ctx->framesPerCycle ); kOutPId, kAnyChIdx, srate, chCnt, ctx->ctx->framesPerCycle );
@ -1841,6 +1920,9 @@ namespace cw
v[j] = (sample_t)((gain * sin( inst->phaseA[i] + phase + (2.0 * M_PI * j * hz/srate)))+dc); v[j] = (sample_t)((gain * sin( inst->phaseA[i] + phase + (2.0 * M_PI * j * hz/srate)))+dc);
inst->phaseA[i] += 2.0 * M_PI * abuf->frameN * hz/srate; inst->phaseA[i] += 2.0 * M_PI * abuf->frameN * hz/srate;
//if( i==0 )
// printf("hz:%f gain:%f phs:%f : %f\n",hz,gain,inst->phaseA[i],v[0]);
} }
} }

View File

@ -2,6 +2,7 @@ namespace cw
{ {
namespace flow namespace flow
{ {
namespace subnet { extern class_members_t members; }
namespace poly { extern class_members_t members; } namespace poly { extern class_members_t members; }
namespace midi_in { extern class_members_t members; } namespace midi_in { extern class_members_t members; }
namespace midi_out { extern class_members_t members; } namespace midi_out { extern class_members_t members; }

View File

@ -1093,6 +1093,21 @@ namespace cw
return rc; return rc;
} }
void _class_desc_print( const class_desc_t* cd )
{
const var_desc_t* vd = cd->varDescL;
printf("%s\n",cwStringNullGuard(cd->label));
for(; vd!=nullptr; vd=vd->link)
{
const char* srcFlStr = vd->flags & kSrcVarFl ? "src" : " ";
const char* srcOptFlStr = vd->flags & kSrcOptVarFl ? "srcOpt" : " ";
const char* plyMltFlStr = vd->flags & kMultVarFl ? "mult" : " ";
printf(" %10s 0x%08x %s %s %s %s\n", cwStringNullGuard(vd->label), vd->type, srcFlStr, srcOptFlStr, plyMltFlStr, cwStringNullGuard(vd->docText) );
}
}
} }
} }
@ -1280,15 +1295,19 @@ const char* cw::flow::value_type_flag_to_label( unsigned flag )
cw::flow::class_desc_t* cw::flow::class_desc_find( flow_t* p, const char* label ) cw::flow::class_desc_t* cw::flow::class_desc_find( flow_t* p, const char* label )
{ {
for(unsigned i=0; i<p->classDescN; ++i) for(unsigned i=0; i<p->classDescN; ++i)
if( textCompare(p->classDescA[i].label,label) == 0 ) if( textIsEqual(p->classDescA[i].label,label))
return p->classDescA + i; return p->classDescA + i;
for(unsigned i=0; i<p->subnetDescN; ++i)
if( textIsEqual(p->subnetDescA[i].label,label))
return p->subnetDescA + i;
return nullptr; return nullptr;
} }
const cw::flow::var_desc_t* cw::flow::var_desc_find( const class_desc_t* cd, const char* label )
cw::flow::var_desc_t* cw::flow::var_desc_find( class_desc_t* cd, const char* label )
{ {
var_desc_t* vd = cd->varDescL; const var_desc_t* vd = cd->varDescL;
for(; vd != nullptr; vd=vd->link ) for(; vd != nullptr; vd=vd->link )
if( textCompare(vd->label,label) == 0 ) if( textCompare(vd->label,label) == 0 )
@ -1296,6 +1315,11 @@ cw::flow::var_desc_t* cw::flow::var_desc_find( class_desc_t* cd, const char* lab
return nullptr; return nullptr;
} }
cw::flow::var_desc_t* cw::flow::var_desc_find( class_desc_t* cd, const char* label )
{
return (var_desc_t*)var_desc_find( (const class_desc_t*)cd, label);
}
cw::rc_t cw::flow::var_desc_find( class_desc_t* cd, const char* label, var_desc_t*& vdRef ) cw::rc_t cw::flow::var_desc_find( class_desc_t* cd, const char* label, var_desc_t*& vdRef )
{ {
if((vdRef = var_desc_find(cd,label)) == nullptr ) if((vdRef = var_desc_find(cd,label)) == nullptr )
@ -1303,7 +1327,7 @@ cw::rc_t cw::flow::var_desc_find( class_desc_t* cd, const char* label, var_desc_
return kOkRC; return kOkRC;
} }
const cw::flow::preset_t* cw::flow::class_preset_find( class_desc_t* cd, const char* preset_label ) const cw::flow::preset_t* cw::flow::class_preset_find( const class_desc_t* cd, const char* preset_label )
{ {
const preset_t* pr; const preset_t* pr;
for(pr=cd->presetL; pr!=nullptr; pr=pr->link) for(pr=cd->presetL; pr!=nullptr; pr=pr->link)
@ -1316,20 +1340,10 @@ const cw::flow::preset_t* cw::flow::class_preset_find( class_desc_t* cd, const c
void cw::flow::class_dict_print( flow_t* p ) void cw::flow::class_dict_print( flow_t* p )
{ {
for(unsigned i=0; i<p->classDescN; ++i) for(unsigned i=0; i<p->classDescN; ++i)
{ _class_desc_print(p->classDescA+i);
class_desc_t* cd = p->classDescA + i;
var_desc_t* vd = cd->varDescL;
printf("%s\n",cwStringNullGuard(cd->label));
for(; vd!=nullptr; vd=vd->link) for(unsigned i=0; i<p->subnetDescN; ++i)
{ _class_desc_print(p->subnetDescA+i);
const char* srcFlStr = vd->flags & kSrcVarFl ? "src" : " ";
const char* srcOptFlStr = vd->flags & kSrcOptVarFl ? "srcOpt" : " ";
const char* plyMltFlStr = vd->flags & kMultVarFl ? "mult" : " ";
printf(" %10s 0x%08x %s %s %s %s\n", cwStringNullGuard(vd->label), vd->type, srcFlStr, srcOptFlStr, plyMltFlStr, cwStringNullGuard(vd->docText) );
}
}
} }

View File

@ -25,7 +25,6 @@ namespace cw
typedef struct abuf_str typedef struct abuf_str
{ {
struct value_str* base;
srate_t srate; // signal sample rate srate_t srate; // signal sample rate
unsigned chN; // count of channels unsigned chN; // count of channels
unsigned frameN; // count of sample frames per channel unsigned frameN; // count of sample frames per channel
@ -35,7 +34,6 @@ namespace cw
typedef struct fbuf_str typedef struct fbuf_str
{ {
struct value_str* base;
srate_t srate; // signal sample rate srate_t srate; // signal sample rate
unsigned flags; // See kXXXFbufFl unsigned flags; // See kXXXFbufFl
unsigned chN; // count of channels unsigned chN; // count of channels
@ -51,7 +49,6 @@ namespace cw
typedef struct mbuf_str typedef struct mbuf_str
{ {
struct value_str* base;
const midi::ch_msg_t* msgA; const midi::ch_msg_t* msgA;
unsigned msgN; unsigned msgN;
} mbuf_t; } mbuf_t;
@ -136,7 +133,8 @@ namespace cw
kNoVarFl = 0x00, kNoVarFl = 0x00,
kSrcVarFl = 0x01, kSrcVarFl = 0x01,
kSrcOptVarFl = 0x02, kSrcOptVarFl = 0x02,
kMultVarFl = 0x04 kMultVarFl = 0x04,
kSubnetOutVarFl = 0x08
}; };
typedef struct class_members_str typedef struct class_members_str
@ -156,6 +154,10 @@ namespace cw
unsigned type; // Value type id (e.g. kBoolTFl, kIntTFl, ...) unsigned type; // Value type id (e.g. kBoolTFl, kIntTFl, ...)
unsigned flags; // Attributes for this var. (e.g. kSrcVarFl ) unsigned flags; // Attributes for this var. (e.g. kSrcVarFl )
const char* docText; // User help string for this var. const char* docText; // User help string for this var.
char* proxyProcLabel;
char* proxyVarLabel;
struct var_desc_str* link; // class_desc->varDescL list link struct var_desc_str* link; // class_desc->varDescL list link
} var_desc_t; } var_desc_t;
@ -168,9 +170,9 @@ namespace cw
typedef struct class_desc_str typedef struct class_desc_str
{ {
const object_t* cfg; // const object_t* cfg; // class cfg
const char* label; // class label; const char* label; // class label;
var_desc_t* varDescL; // varDescA[varDescN] value description list var_desc_t* varDescL; // varDescL variable description linked on var_desc_t.link
preset_t* presetL; // presetA[ presetN ] preset_t* presetL; // presetA[ presetN ]
class_members_t* members; // member functions for this class class_members_t* members; // member functions for this class
unsigned polyLimitN; // max. poly copies of this class per network_t or 0 if no limit unsigned polyLimitN; // max. poly copies of this class per network_t or 0 if no limit
@ -178,7 +180,9 @@ namespace cw
enum { enum {
kInvalidVarFl = 0x00, kInvalidVarFl = 0x00,
kLogVarFl = 0x01 kLogVarFl = 0x01,
kProxiedVarFl = 0x02,
kProxiedOutVarFl = 0x04
}; };
// Note: The concatenation of 'vid' and 'chIdx' should form a unique identifier among all variables // Note: The concatenation of 'vid' and 'chIdx' should form a unique identifier among all variables
@ -274,6 +278,10 @@ namespace cw
class_desc_t* classDescA; // class_desc_t* classDescA; //
unsigned classDescN; // unsigned classDescN; //
class_desc_t* subnetDescA; //
unsigned subnetDescN; //
external_device_t* deviceA; // deviceA[ deviceN ] external device description array external_device_t* deviceA; // deviceA[ deviceN ] external device description array
unsigned deviceN; // unsigned deviceN; //
@ -324,9 +332,10 @@ namespace cw
class_desc_t* class_desc_find( flow_t* p, const char* class_desc_label ); class_desc_t* class_desc_find( flow_t* p, const char* class_desc_label );
var_desc_t* var_desc_find( class_desc_t* cd, const char* var_label ); var_desc_t* var_desc_find( class_desc_t* cd, const char* var_label );
rc_t var_desc_find( class_desc_t* cd, const char* label, var_desc_t*& vdRef ); const var_desc_t* var_desc_find( const class_desc_t* cd, const char* var_label );
rc_t var_desc_find( class_desc_t* cd, const char* var_label, var_desc_t*& vdRef );
const preset_t* class_preset_find( class_desc_t* cd, const char* preset_label ); const preset_t* class_preset_find( const class_desc_t* cd, const char* preset_label );
void class_dict_print( flow_t* p ); void class_dict_print( flow_t* p );

View File

@ -114,7 +114,6 @@ namespace cw
{ {
dev->ioDevIdx = ioDevIdx; dev->ioDevIdx = ioDevIdx;
dev->ioDevId = audioDeviceUserId( p->ioH, ioDevIdx ); dev->ioDevId = audioDeviceUserId( p->ioH, ioDevIdx );
dev->abuf.base = nullptr;
dev->abuf.srate = audioDeviceSampleRate( p->ioH, ioDevIdx ); dev->abuf.srate = audioDeviceSampleRate( p->ioH, ioDevIdx );
dev->abuf.chN = audioDeviceChannelCount( p->ioH, ioDevIdx, inOrOutFl ); dev->abuf.chN = audioDeviceChannelCount( p->ioH, ioDevIdx, inOrOutFl );
dev->abuf.frameN = dspFrameCnt; dev->abuf.frameN = dspFrameCnt;