cwFlowProc.cpp, cwFlow.cpp,cwFlowNet.h/cpp : Implemented presets for het. poly nets.

This commit is contained in:
kevin 2024-12-27 15:24:44 -05:00
parent ccdac53013
commit fc94d3859d
4 changed files with 311 additions and 163 deletions

View File

@ -1037,6 +1037,7 @@ cw::rc_t cw::flow::initialize( handle_t h,
rc_t rc = kOkRC; rc_t rc = kOkRC;
variable_t* proxyVarL = nullptr; variable_t* proxyVarL = nullptr;
flow_t* p = _handleToPtr(h); flow_t* p = _handleToPtr(h);
const char* root_label = "root";
p->deviceA = deviceA; p->deviceA = deviceA;
p->deviceN = deviceN; p->deviceN = deviceN;
@ -1069,7 +1070,7 @@ cw::rc_t cw::flow::initialize( handle_t h,
} }
// instantiate the network // instantiate the network
if((rc = network_create(p,&p->networkCfg,1,proxyVarL,nullptr,1,p->net)) != kOkRC ) if((rc = network_create(p,&root_label,&p->networkCfg,1,proxyVarL,1,p->net)) != kOkRC )
{ {
rc = cwLogError(rc,"Network creation failed."); rc = cwLogError(rc,"Network creation failed.");
goto errLabel; goto errLabel;

View File

@ -48,6 +48,7 @@ namespace cw
unsigned sfx_id; // 'sfx_id' is only used by _io_stmt_connect_vars() unsigned sfx_id; // 'sfx_id' is only used by _io_stmt_connect_vars()
unsigned sfx_id_count; // Literal sfx_id_count or kInvalidCnt if not given unsigned sfx_id_count; // Literal sfx_id_count or kInvalidCnt if not given
unsigned is_iter_fl; // This id included an '_' (underscore) unsigned is_iter_fl; // This id included an '_' (underscore)
unsigned has_sfx_fl; // true if a suffix was specified (differentiates label0 from label)
} io_ele_t; } io_ele_t;
typedef struct io_stmt_str typedef struct io_stmt_str
@ -332,6 +333,7 @@ namespace cw
else else
{ {
r.is_iter_fl = true; r.is_iter_fl = true;
r.has_sfx_fl = true;
// if there is a number following the underscore then this is the secInt // if there is a number following the underscore then this is the secInt
if( textLength(underscore + 1) ) if( textLength(underscore + 1) )
@ -382,6 +384,8 @@ namespace cw
*digit = 0; // zero terminate the label *digit = 0; // zero terminate the label
r.has_sfx_fl = true;
} }
// verify that some content remains in the id string // verify that some content remains in the id string
@ -1508,7 +1512,7 @@ namespace cw
} }
// Set pstate.proc_label and pstate.label_sfx_id // Set pstate.proc_label and pstate.label_sfx_id
rc_t _proc_parse_inst_label( const char* proc_label_str, unsigned system_sfx_id, proc_inst_parse_state_t& pstate ) rc_t _proc_parse_inst_label( const network_t& net, const char* proc_label_str, proc_inst_parse_state_t& pstate )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
unsigned digitCharN = 0; unsigned digitCharN = 0;
@ -1544,16 +1548,18 @@ namespace cw
} }
} }
// if the parsed sfx-id did not exist // if the parsed sfx-id was not explicitly set then set it to the network index
if( sfx_id == kInvalidId ) if( sfx_id == kInvalidId )
{ {
sfx_id = system_sfx_id==kInvalidId ? kBaseSfxId : system_sfx_id; sfx_id = net.poly_idx;
} }
// be sure the parsed sfx-id does not conflict with the system provided sfx-id // if this net is part of a network array then the proc suffix id is used distinguish this
if( system_sfx_id != kInvalidId && sfx_id != system_sfx_id ) // proc instance from the same proc instance in sibling networks and so it can't
// be changed to some other value by providing an explicit suffix id
if( net.polyN > 1 && sfx_id != net.poly_idx )
{ {
rc = cwLogError(kInvalidStateRC,"The proc instance '%s' numeric suffix id (%i) conflicts with the system provided sfx id (%i).",cwStringNullGuard(proc_label_str),pstate.proc_label_sfx_id,system_sfx_id); rc = cwLogError(kInvalidStateRC,"The proc instance '%s' numeric suffix id (%i) conflicts with the network poly index (%i).",cwStringNullGuard(proc_label_str),pstate.proc_label_sfx_id,net.poly_idx);
goto errLabel; goto errLabel;
} }
@ -1565,7 +1571,7 @@ namespace cw
} }
rc_t _proc_parse_cfg( network_t& net, const object_t* proc_inst_cfg, unsigned system_sfx_id, proc_inst_parse_state_t& pstate ) rc_t _proc_parse_cfg( network_t& net, const object_t* proc_inst_cfg, proc_inst_parse_state_t& pstate )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
const object_t* arg_dict = nullptr; const object_t* arg_dict = nullptr;
@ -1580,7 +1586,7 @@ namespace cw
pstate.proc_label_sfx_id = kInvalidId; pstate.proc_label_sfx_id = kInvalidId;
// extract the proc instance label and (sfx-id suffix) // extract the proc instance label and (sfx-id suffix)
if((rc = _proc_parse_inst_label( proc_inst_cfg->pair_label(), system_sfx_id, pstate )) != kOkRC ) if((rc = _proc_parse_inst_label( net, proc_inst_cfg->pair_label(), pstate )) != kOkRC )
{ {
rc = cwLogError(kSyntaxErrorRC,"Parsing failed on the label and sfx-id for '%s'.",cwStringNullGuard(proc_inst_cfg->pair_label())); rc = cwLogError(kSyntaxErrorRC,"Parsing failed on the label and sfx-id for '%s'.",cwStringNullGuard(proc_inst_cfg->pair_label()));
goto errLabel; goto errLabel;
@ -1914,22 +1920,19 @@ namespace cw
rc_t _proc_create( flow_t* p, rc_t _proc_create( flow_t* p,
const object_t* proc_inst_cfg, const object_t* proc_inst_cfg,
unsigned sfx_id,
network_t& net, network_t& net,
variable_t* proxyVarL, variable_t* proxyVarL,
//const object_t* net_preset_cfgD,
proc_t*& proc_ref ) proc_t*& proc_ref )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
proc_inst_parse_state_t pstate = {}; proc_inst_parse_state_t pstate = {};
proc_t* proc = nullptr; proc_t* proc = nullptr;
class_desc_t* class_desc = nullptr; class_desc_t* class_desc = nullptr;
//const object_t* proc_preset_cfg = nullptr;
proc_ref = nullptr; proc_ref = nullptr;
// parse the proc instance configuration // parse the proc instance configuration
if((rc = _proc_parse_cfg( net, proc_inst_cfg, sfx_id, pstate )) != kOkRC ) if((rc = _proc_parse_cfg( net, proc_inst_cfg, pstate )) != kOkRC )
goto errLabel; goto errLabel;
// locate the proc class desc // locate the proc class desc
@ -2220,7 +2223,7 @@ namespace cw
// Preset processing // Preset processing
// //
rc_t _parse_network_proc_label( const network_t& net, const network_preset_t& network_preset, const char* proc_label, unsigned proc_label_sfx_id, io_ele_t& proc_id ) rc_t _parse_network_proc_label( const network_t& net, const network_preset_t& network_preset, const char* proc_label, io_ele_t& proc_id )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
@ -2231,9 +2234,9 @@ namespace cw
goto errLabel; goto errLabel;
} }
// set the proc_id base sfx id // if the proc label sfx id was not explicitely set then set it to the network poly index
if( proc_id.base_sfx_id == kInvalidId ) if( proc_id.base_sfx_id == kInvalidId )
proc_id.base_sfx_id = proc_label_sfx_id==kInvalidId ? kBaseSfxId : proc_label_sfx_id; proc_id.base_sfx_id = net.poly_idx;
// if not iterating // if not iterating
if( !proc_id.is_iter_fl ) if( !proc_id.is_iter_fl )
@ -2570,53 +2573,112 @@ namespace cw
return rc; return rc;
} }
rc_t _network_preset_handle_poly_preset_ref(network_preset_t& network_preset, network_t* poly_net, const char* preset_label )
rc_t _network_preset_handle_poly_preset_reference(network_preset_t& network_preset, proc_t* poly_proc, const char* preset_label )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
preset_value_t* preset_value = nullptr; preset_value_t* preset_value = nullptr;
network_t* poly_net = poly_proc->internal_net;
for(; poly_net!=nullptr; poly_net=poly_net->poly_link) network_preset_t* poly_net_preset = nullptr;
{
network_preset_t* poly_net_preset = nullptr;
for(unsigned i=0; i<poly_net->presetN; ++i) for(unsigned i=0; i<poly_net->presetN; ++i)
if( textIsEqual(poly_net->presetA[i].label,preset_label) ) if( textIsEqual(poly_net->presetA[i].label,preset_label) )
{
poly_net_preset = poly_net->presetA + i;
break;
}
if( poly_net_preset == nullptr )
{ {
rc = cwLogError(kEleNotFoundRC,"The preset '%s' could not be found on the poly proc '%s:%i'.",cwStringNullGuard(poly_proc->label),poly_proc->label_sfx_id); poly_net_preset = poly_net->presetA + i;
goto errLabel; break;
} }
preset_value = mem::allocZ<preset_value_t>(); if( poly_net_preset == nullptr )
{
preset_value->tid = kNetRefPresetValueTId; rc = cwLogError(kEleNotFoundRC,"The preset '%s' could not be found on the net '%s:%i'.",preset_label,cwStringNullGuard(poly_net->label),poly_net->poly_idx);
preset_value->u.npv.net_preset = poly_net_preset; goto errLabel;
preset_value->u.npv.net_preset_net = poly_net;
//preset_value->u.npv.net_preset_proc = poly_proc;
_network_preset_link_in_value( network_preset, preset_value );
} }
preset_value = mem::allocZ<preset_value_t>();
preset_value->tid = kNetRefPresetValueTId;
preset_value->u.npv.net_preset = poly_net_preset;
preset_value->u.npv.net_preset_net = poly_net;
_network_preset_link_in_value( network_preset, preset_value );
errLabel: errLabel:
return rc; return rc;
} }
rc_t _network_preset_handle_poly_preset_reference(network_preset_t& network_preset, proc_t* poly_proc, const io_ele_t& proc_id, const char* preset_label )
{
rc_t rc = kOkRC;
const class_preset_t* class_pre;
unsigned min_sfx_id = proc_id.base_sfx_id;
unsigned sfx_cnt = proc_id.is_iter_fl ? proc_id.sfx_id_count : (proc_id.has_sfx_fl ? 1 : poly_proc->internal_net->polyN);
network_t* poly_net = poly_proc->internal_net;
// for each specified poly net
for(; poly_net!=nullptr; poly_net=poly_net->poly_link)
if( min_sfx_id <= poly_net->poly_idx && poly_net->poly_idx < min_sfx_id + sfx_cnt )
{
// if this network is not a het. net then the preset can be directly found in the network preset list
if( poly_proc->internal_net_cnt == 1 )
rc = _network_preset_handle_poly_preset_ref(network_preset, poly_net, preset_label);
else
{
// the network is het. net and so the preset must be looked up first in the poly proc instance preset list
// and then mapped to each of the named networks.
if((class_pre = proc_preset_find(poly_proc,preset_label)) != nullptr )
{
// ... the referenced preset ia a poly preset instance preset ....
unsigned childN = class_pre->cfg->child_count();
// ... iterate through each of the elements of the preset dictionary
for(unsigned i=0; i<childN; ++i)
{
const object_t* pair = class_pre->cfg->child_ele(i);
const char* net_preset_label = nullptr;
const char* net_label = pair->pair_label();
// pair = (net-label:net-preset-label)
// the het. net referenced in the in preset must match the current net (poly_net) label
if( textIsEqual(net_label,poly_net->label) )
{
// get the net specific preset label
if( pair->pair_value()->value(net_preset_label) != kOkRC )
{
rc = cwLogError(kSyntaxErrorRC,"The value associated with '%s' is not a string.",pair->pair_label());
goto errLabel;
}
if((rc = _network_preset_handle_poly_preset_ref(network_preset, poly_net, net_preset_label )) != kOkRC )
{
goto errLabel;
}
}
}
}
}
}
errLabel:
if( rc != kOkRC )
rc = cwLogError(rc,"The poly processor preset '%s' on '%s:%i' is not valid.",cwStringNullGuard(preset_label),cwStringNullGuard(poly_proc->label),poly_proc->label_sfx_id);
return rc;
}
rc_t _network_preset_parse_value_list( flow_t* p, rc_t _network_preset_parse_value_list( flow_t* p,
network_t& net, network_t& net,
unsigned net_sfx_id,
const object_t* network_preset_dict_cfg, const object_t* network_preset_dict_cfg,
network_preset_t& network_preset ) network_preset_t& network_preset )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
unsigned procN = 0; unsigned pairN = 0;
if( network_preset_dict_cfg==nullptr || !network_preset_dict_cfg->is_dict() ) if( network_preset_dict_cfg==nullptr || !network_preset_dict_cfg->is_dict() )
{ {
@ -2626,10 +2688,10 @@ namespace cw
network_preset.tid = kPresetVListTId; network_preset.tid = kPresetVListTId;
procN = network_preset_dict_cfg->child_count(); pairN = network_preset_dict_cfg->child_count();
// for each proc in the network preset // for each pair in the preset value dictionary
for(unsigned i=0; i<procN; ++i) for(unsigned i=0; i<pairN; ++i)
{ {
const object_t* var_dict = nullptr; const object_t* var_dict = nullptr;
const object_t* proc_preset_pair = network_preset_dict_cfg->child_ele(i); const object_t* proc_preset_pair = network_preset_dict_cfg->child_ele(i);
@ -2637,6 +2699,7 @@ namespace cw
io_ele_t proc_id = {}; io_ele_t proc_id = {};
unsigned varN = 0; unsigned varN = 0;
// validate the process preset syntax // validate the process preset syntax
if( proc_preset_pair==nullptr || !proc_preset_pair->is_pair() || (proc_label=proc_preset_pair->pair_label())==nullptr || proc_preset_pair->pair_value()==nullptr ) if( proc_preset_pair==nullptr || !proc_preset_pair->is_pair() || (proc_label=proc_preset_pair->pair_label())==nullptr || proc_preset_pair->pair_value()==nullptr )
{ {
@ -2644,15 +2707,34 @@ namespace cw
goto errLabel; goto errLabel;
} }
// parse the proc label // each pair has the syntax:
if((rc= _parse_network_proc_label(net, network_preset, proc_label, net_sfx_id, proc_id )) != kOkRC ) // <proc-label>:<preset_value>
// where:
// <proc-label> identifies a proc inside this network where the <preset-value> will be applied.
// <preset-value> idenfifies a label or a dictionary of <var>:<value> pairs.
//
// parse the label
if((rc= _parse_network_proc_label(net, network_preset, proc_label, proc_id )) != kOkRC )
goto errLabel; goto errLabel;
// if the preset has a label // if the preset-value is a label ...
if( proc_preset_pair->pair_value()->is_string() ) if( proc_preset_pair->pair_value()->is_string() )
{ {
const char* proc_preset_label = nullptr; const char* proc_preset_label = nullptr;
proc_t* proc = nullptr; proc_t* proc = nullptr;
// ... then the label refers to a proc where the proc may be
// one of two types:
//
// 1) 'poly' proc - in which case we need to a poly_preset_value_t
// record for each poly channel -
//
// 2) a proc instance in this network
// in which case the label refers to a class or instance preset
// and we store proc_var_value_t for each variable referenced in the preset cfg.
// get the proc preset label // get the proc preset label
if((proc_preset_pair->pair_value()->value(proc_preset_label)) != kOkRC ) if((proc_preset_pair->pair_value()->value(proc_preset_label)) != kOkRC )
@ -2660,19 +2742,10 @@ namespace cw
rc = cwLogError(rc,"The proc preset label '%s' could not be parsed on the preset:'%s'",cwStringNullGuard(proc_preset_label),cwStringNullGuard(proc_label)); rc = cwLogError(rc,"The proc preset label '%s' could not be parsed on the preset:'%s'",cwStringNullGuard(proc_preset_label),cwStringNullGuard(proc_label));
goto errLabel; goto errLabel;
} }
// the label may refer to a
// 1) 'poly' proc - in which case we need to a poly_preset_value_t
// record for each poly channel -
//
// 2) a proc instance in this network
// in which case the label refers to a class or instance preset
// and we store proc_var_value_t for each variable referenced in the preset cfg.
// locate the proc this preset will be applied to // locate the proc this preset will be applied to
if((proc = proc_find(net, proc_id.label, net_sfx_id /*proc_id.sfx_id*/ )) == nullptr ) if((proc = proc_find(net, proc_id.label, net.poly_idx )) == nullptr )
{ {
rc = cwLogError(rc,"The proc '%s:%i' could not be found for the preset:'%s'",cwStringNullGuard(proc_id.label),proc_id.sfx_id,cwStringNullGuard(network_preset.label)); rc = cwLogError(rc,"The proc '%s:%i' could not be found for the preset:'%s'",cwStringNullGuard(proc_id.label),proc_id.sfx_id,cwStringNullGuard(network_preset.label));
goto errLabel; goto errLabel;
@ -2681,7 +2754,8 @@ namespace cw
// if this is a 'poly' proc // if this is a 'poly' proc
if( proc->internal_net != nullptr ) if( proc->internal_net != nullptr )
{ {
if((rc = _network_preset_handle_poly_preset_reference(network_preset,proc,proc_preset_label)) != kOkRC )
if((rc = _network_preset_handle_poly_preset_reference(network_preset,proc,proc_id,proc_preset_label)) != kOkRC )
goto errLabel; goto errLabel;
// the referenced preset was added to the network_preset.u.vlist - no further processing is required // the referenced preset was added to the network_preset.u.vlist - no further processing is required
@ -2690,10 +2764,11 @@ namespace cw
} }
else else
{ {
// get the referenced preset cfg from the class desc // get the referenced preset preset cfg
if((rc = _network_preset_get_preset_cfg_dict( net, network_preset.label, proc_id.label, proc_id.base_sfx_id, proc_preset_label, var_dict )) != kOkRC ) if((rc = _network_preset_get_preset_cfg_dict( net, network_preset.label, proc_id.label, proc_id.base_sfx_id, proc_preset_label, var_dict )) != kOkRC )
goto errLabel; goto errLabel;
} }
} }
else // the preset is a dictionary of var/value pairs else // the preset is a dictionary of var/value pairs
{ {
@ -2721,7 +2796,7 @@ namespace cw
// for each proc/sf_id (the proc label may refer to multiple proc instances) // for each proc/sf_id (the proc label may refer to multiple proc instances)
// This loop is designed to handle the case where the preset proc. label uses underscore notation // This loop is designed to handle the case where the preset proc. label uses underscore notation
// to address specific or all instances of a given named proc's. // to address specific vs all instances of a given named proc's.
// If no underscore notation is used then it addresses all instances with the // If no underscore notation is used then it addresses all instances with the
// specified name. // specified name.
@ -2735,8 +2810,8 @@ namespace cw
const object_t* var_pair = var_dict->child_ele(k); const object_t* var_pair = var_dict->child_ele(k);
unsigned proc_label_sfx_id = proc_id.base_sfx_id + j; unsigned proc_label_sfx_id = proc_id.base_sfx_id + j;
// if the net is part of a poly net // if this net is part of a poly net - but the proc sfx id does not match the poly index
if( net_sfx_id!=kInvalidId && proc_label_sfx_id != net_sfx_id ) if( net.polyN>1 && proc_label_sfx_id != net.poly_idx )
continue; continue;
// parse the preset var label - the var may use underscore notation to address multiple vars // parse the preset var label - the var may use underscore notation to address multiple vars
@ -2762,7 +2837,7 @@ namespace cw
} }
rc_t _network_preset_parse_dict( flow_t* p, network_t& net, unsigned proc_sfx_id, const object_t* preset_cfg ) rc_t _network_preset_parse_dict( flow_t* p, network_t& net, const object_t* preset_cfg )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
unsigned presetAllocN = 0; unsigned presetAllocN = 0;
@ -2796,7 +2871,7 @@ namespace cw
switch( preset_pair_cfg->pair_value()->type_id() ) switch( preset_pair_cfg->pair_value()->type_id() )
{ {
case kDictTId: // 'value-list' preset case kDictTId: // 'value-list' preset
if((rc = _network_preset_parse_value_list(p, net, proc_sfx_id, preset_pair_cfg->pair_value(), network_preset)) != kOkRC ) if((rc = _network_preset_parse_value_list(p, net, preset_pair_cfg->pair_value(), network_preset)) != kOkRC )
{ {
rc = cwLogError(kSyntaxErrorRC,"Network value-list preset parse failed on preset:'%s'.",cwStringNullGuard(network_preset.label)); rc = cwLogError(kSyntaxErrorRC,"Network value-list preset parse failed on preset:'%s'.",cwStringNullGuard(network_preset.label));
goto errLabel; goto errLabel;
@ -3253,7 +3328,6 @@ namespace cw
rc_t _network_init( flow_t* p, rc_t _network_init( flow_t* p,
const object_t* networkCfg, const object_t* networkCfg,
unsigned sfx_id,
variable_t* proxyVarL, variable_t* proxyVarL,
network_t* net ) network_t* net )
{ {
@ -3295,7 +3369,7 @@ namespace cw
const object_t* proc_cfg = net->procsCfg->child_ele(j); const object_t* proc_cfg = net->procsCfg->child_ele(j);
// create the proc inst instance // create the proc inst instance
if( (rc= _proc_create( p, proc_cfg, sfx_id, *net, proxyVarL, net->procA[j] ) ) != kOkRC ) if( (rc= _proc_create( p, proc_cfg, *net, proxyVarL, net->procA[j] ) ) != kOkRC )
{ {
rc = cwLogError(rc,"The processor instantiation at proc index %i failed.",j); rc = cwLogError(rc,"The processor instantiation at proc index %i failed.",j);
goto errLabel; goto errLabel;
@ -3309,7 +3383,7 @@ namespace cw
goto errLabel; goto errLabel;
// parse the network presets but do not apply them // parse the network presets but do not apply them
if((rc = _network_preset_parse_dict(p, *net, sfx_id, net->presetsCfg )) != kOkRC ) if((rc = _network_preset_parse_dict(p, *net, net->presetsCfg )) != kOkRC )
goto errLabel; goto errLabel;
errLabel: errLabel:
@ -3414,10 +3488,11 @@ 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* const * netCfgA, const char* const * netLabelA, // netLabel[ netCfgN ]
const object_t* const * netCfgA, // netCfgA[ netCfgA ]
unsigned netCfgN, unsigned netCfgN,
variable_t* proxyVarL, variable_t* proxyVarL,
const proc_t* owner_proc, //const proc_t* owner_proc,
unsigned polyCnt, unsigned polyCnt,
network_t*& net_ref ) network_t*& net_ref )
{ {
@ -3426,45 +3501,57 @@ cw::rc_t cw::flow::network_create( flow_t* p,
net_ref = nullptr; net_ref = nullptr;
/*
if( !(netCfgN==1 || netCfgN==polyCnt )) if( !(netCfgN==1 || netCfgN==polyCnt ))
{ {
cwLogError(kInvalidArgRC,"The count of network cfg's must be one, or must match the 'poly count'."); cwLogError(kInvalidArgRC,"The count of network cfg's must be one, or must match the 'poly count'.");
goto errLabel; goto errLabel;
} }
*/
// for each network configuration
for(unsigned i=0; i<polyCnt; ++i) for(unsigned cfg_idx=0; cfg_idx<netCfgN; ++cfg_idx)
{ {
// All procs in a poly should share the same sfx_id unsigned poly_cnt = polyCnt;
// otherwise the sfx_id can be automatically generated.
unsigned sfx_id = i; //polyCnt>1 ? i : kInvalidId;
const object_t* netCfg = i < netCfgN ? netCfgA[i] : netCfgA[0]; const object_t* netCfg = netCfgA[cfg_idx];
const char* netLabel = netLabelA[cfg_idx];
network_t* net = mem::allocZ<network_t>(); // overrride poly_cnt with the optional 'count' field passed from the caller
if((rc = netCfg->getv_opt("count",poly_cnt)) != kOkRC )
net->owner_proc = owner_proc;
net->polyN = polyCnt;
net->poly_idx = i;
if( net_ref == nullptr )
net_ref = net;
if( n0 != nullptr )
n0->poly_link = net;
n0 = net;
// create the network
if((rc = _network_init(p, netCfg, sfx_id, proxyVarL, net)) != kOkRC )
{ {
rc = cwLogError(rc,"Network create failed on poly index %i.",i); rc = cwLogError(rc,"Poly network 'count' parse failed on the network '%s'.",cwStringNullGuard(netLabel));
goto errLabel; goto errLabel;
} }
}
// for each poly network
for(unsigned i=0; i<poly_cnt; ++i)
{
// allocate the network
network_t* net = mem::allocZ<network_t>();
//net->owner_proc = owner_proc;
net->label = netLabel;
net->polyN = poly_cnt;
net->poly_idx = i;
if( net_ref == nullptr )
net_ref = net;
if( n0 != nullptr )
n0->poly_link = net;
n0 = net;
// create the network
if((rc = _network_init(p, netCfg, proxyVarL, net)) != kOkRC )
{
rc = cwLogError(rc,"Network create failed on poly index %i.",i);
goto errLabel;
}
}
}
errLabel: errLabel:
if( rc != kOkRC && net_ref != nullptr ) if( rc != kOkRC && net_ref != nullptr )

View File

@ -12,12 +12,12 @@ namespace cw
// The only time netCfgN will be greater than 1 is when a heterogenous poly network is being // The only time netCfgN will be greater than 1 is when a heterogenous poly network is being
// instantiated. // instantiated.
rc_t network_create( flow_t* p, rc_t network_create( flow_t* p,
const object_t* const * netCfgA, // netCfgA[netCfgN] const char* const * netLabelA, // netLabel[netCfgN]
unsigned netCfgN, // count of cfg. records in netCfgN const object_t* const * netCfgA, // netCfgA[netCfgN]
variable_t* proxyVarL, // unsigned netCfgN, // count of cfg. records in netCfgN
const proc_t* owner_proc, // Pointer to the proc that owns this network (or null if creating the top level network) variable_t* proxyVarL, //
unsigned polyCnt, // Count of poly subnets to create or 1 if the network is not poly unsigned polyCnt, // Count of poly subnets to create or 1 if the network is not poly
network_t*& net_ref // Returned network handle. network_t*& net_ref // Returned network handle.
); );
rc_t network_destroy( network_t*& net ); rc_t network_destroy( network_t*& net );

View File

@ -129,7 +129,7 @@ namespace cw
goto errLabel; goto errLabel;
} }
if((rc = network_create(proc->ctx,&networkCfg,1,proc->varL,proc,1,p->net)) != kOkRC ) if((rc = network_create(proc->ctx,&proc->label,&networkCfg,1,proc->varL,1,p->net)) != kOkRC )
{ {
rc = cwLogError(rc,"Creation failed on the subnet internal network."); rc = cwLogError(rc,"Creation failed on the subnet internal network.");
goto errLabel; goto errLabel;
@ -203,13 +203,13 @@ namespace cw
} voice_t; } voice_t;
typedef struct typedef struct
{ {
unsigned count; // count of subnets in 'net'
bool parallel_fl; // true if the subnets should be executed in parallel bool parallel_fl; // true if the subnets should be executed in parallel
thread_tasks::handle_t threadTasksH; // thread_tasks::handle_t threadTasksH; //
thread_tasks::task_t* taskA; // taskA[ count ] thread_tasks::task_t* taskA; // taskA[ count ]
voice_t* voiceA; // voiceA[ count ] voice_t* voiceA; // voiceA[ count ]
unsigned preset_sfx_id; unsigned voiceN;
unsigned preset_sfx_id;
} inst_t; } inst_t;
rc_t _poly_thread_func( void* arg ) rc_t _poly_thread_func( void* arg )
@ -253,17 +253,21 @@ namespace cw
} }
rc_t create( proc_t* proc ) rc_t create( proc_t* proc )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
inst_t* inst = mem::allocZ<inst_t>(); inst_t* inst = mem::allocZ<inst_t>();
const object_t* networkCfg = nullptr; const object_t* networkCfg = nullptr;
variable_t* proxyVarL = nullptr; variable_t* proxyVarL = nullptr;
const object_t** networkCfgA = nullptr; const char** netLabelA = nullptr;
unsigned networkCfgN = 1; const object_t** netCfgA = nullptr;
network_t* internal_net = nullptr; unsigned netCfgN = 1;
network_t* internal_net = nullptr;
unsigned preset_sfx_id = kInvalidId; unsigned preset_sfx_id = kInvalidId;
const char* preset_label = nullptr; const char* preset_label = nullptr;
bool het_poly_fl = false;
unsigned poly_cnt = 1;
proc->userPtr = inst; proc->userPtr = inst;
@ -283,54 +287,60 @@ namespace cw
goto errLabel; goto errLabel;
} }
het_poly_fl = networkCfg->find("procs") == nullptr;
// if the network is a list of cfgs // if the network is a list of cfgs
if( networkCfg->is_list() ) if( het_poly_fl )
{ {
inst->count = networkCfg->child_count(); netCfgN = networkCfg->child_count();
networkCfgN = inst->count;
}
else
{
// otherwise multiple networks use the same cfg
if((rc = var_register_and_get( proc, kAnyChIdx,kCountPId,"count", kBaseSfxId, inst->count )) != kOkRC )
{
goto errLabel;
}
} }
// the network cannot be empty
if( inst->count == 0 ) // get the default poly count
if((rc = var_register_and_get( proc, kAnyChIdx,kCountPId,"count", kBaseSfxId, poly_cnt )) != kOkRC )
{ {
cwLogWarning("The 'poly' %s:%i was given a count of 0.",proc->label,proc->label_sfx_id); goto errLabel;
}
// the network cannot be empty
if( netCfgN == 0 )
{
cwLogWarning("The 'poly' %s:%i does not define any networks.",proc->label,proc->label_sfx_id);
goto errLabel; goto errLabel;
} }
// allocate the network cfg array // allocate the network cfg array
networkCfgA = mem::allocZ<const object_t*>(inst->count); netCfgA = mem::allocZ<const object_t*>(netCfgN);
netLabelA = mem::allocZ<const char*>(netCfgN);
// by default there is only one cfg. // by default there is only one cfg.
networkCfgA[0] = networkCfg; netCfgA[0] = networkCfg;
// ... but if there are more than one cfg ... // ... but if there are more than one cfg ...
if( networkCfg->is_list() ) if( het_poly_fl )
{ {
// ... fill the network cfg array // ... fill the network cfg array
for(unsigned i=0; i<inst->count; ++i) for(unsigned i=0; i<netCfgN; ++i)
{ {
networkCfgA[i] = networkCfg->child_ele(i); const object_t* pair = networkCfg->child_ele(i);
if( !networkCfgA[i]->is_dict() ) if( (pair->pair_label() == nullptr) || (pair->pair_value() == nullptr) || (!pair->pair_value()->is_dict()) )
{ {
cwLogError(kSyntaxErrorRC,"The network cfg. for the network index %i is not a dictionary.",i); cwLogError(kSyntaxErrorRC,"The network cfg. for the network index %i is not a label/dictionary pair.",i);
goto errLabel; goto errLabel;
}
else
{
netCfgA[i] = pair->pair_value();
netLabelA[i] = pair->pair_label();
} }
} }
} }
proc->internal_net_cnt = netCfgN;
// create the network object - which will hold 'count' subnets - each a duplicate of the
// network described by 'networkCfg'. // create the network object
if((rc = network_create(proc->ctx,networkCfgA,networkCfgN,proxyVarL,proc,inst->count,internal_net)) != kOkRC ) if((rc = network_create(proc->ctx,netLabelA,netCfgA,netCfgN,proxyVarL,poly_cnt,internal_net)) != kOkRC )
{ {
rc = cwLogError(rc,"Creation failed on the internal network."); rc = cwLogError(rc,"Creation failed on the internal network.");
goto errLabel; goto errLabel;
@ -342,25 +352,29 @@ namespace cw
goto errLabel; goto errLabel;
} }
inst->voiceN = 0;
for(network_t* net=internal_net; net!=nullptr; net=net->poly_link)
inst->voiceN += 1;
if( inst->parallel_fl ) if( inst->parallel_fl )
{ {
network_t* net = internal_net; network_t* net = internal_net;
// create a thread_tasks object // create a thread_tasks object
if((rc = thread_tasks::create( inst->threadTasksH, inst->count )) != kOkRC ) if((rc = thread_tasks::create( inst->threadTasksH, inst->voiceN )) != kOkRC )
{ {
rc = cwLogError(rc,"Thread machine create failed."); rc = cwLogError(rc,"Thread machine create failed.");
goto errLabel; goto errLabel;
} }
// the taskA[] array is needed to hold voice specific info. for the call to thread_tasks::run() // the taskA[] array is needed to hold voice specific info. for the call to thread_tasks::run()
inst->taskA = mem::allocZ<thread_tasks::task_t>(inst->count); inst->taskA = mem::allocZ<thread_tasks::task_t>(inst->voiceN);
inst->voiceA = mem::allocZ<voice_t>(inst->count); inst->voiceA = mem::allocZ<voice_t>(inst->voiceN);
for(unsigned i=0; net !=nullptr; ++i) for(unsigned i=0; net !=nullptr; ++i)
{ {
assert(i<inst->count);
inst->voiceA[i].voice_idx = i; inst->voiceA[i].voice_idx = i;
inst->voiceA[i].net = net; inst->voiceA[i].net = net;
@ -377,7 +391,8 @@ namespace cw
proc->internal_net = internal_net; proc->internal_net = internal_net;
errLabel: errLabel:
mem::release(networkCfgA); mem::release(netCfgA);
mem::release(netLabelA);
return rc; return rc;
} }
@ -431,7 +446,7 @@ namespace cw
if( p->parallel_fl ) if( p->parallel_fl )
{ {
if((rc = thread_tasks::run(p->threadTasksH,p->taskA,p->count)) != kOkRC ) if((rc = thread_tasks::run(p->threadTasksH,p->taskA,p->voiceN)) != kOkRC )
{ {
rc = cwLogError(rc,"poly internal network parallel exec failed."); rc = cwLogError(rc,"poly internal network parallel exec failed.");
} }
@ -4029,7 +4044,7 @@ namespace cw
goto errLabel; goto errLabel;
} }
poly_cnt = p->net_proc->internal_net==nullptr ? 0 : network_poly_count(*p->net_proc->internal_net); poly_cnt = 0; //p->net_proc->internal_net==nullptr ? 0 : network_poly_count(*p->net_proc->internal_net);
if( poly_cnt < 3 ) if( poly_cnt < 3 )
{ {
@ -7966,6 +7981,7 @@ namespace cw
namespace poly_xform_ctl namespace poly_xform_ctl
{ {
enum { enum {
kTriggerPId,
kOutChCntPId, kOutChCntPId,
kOutChIdxPId, kOutChIdxPId,
kInBasePId, kInBasePId,
@ -7975,6 +7991,11 @@ namespace cw
{ {
unsigned out_idx; unsigned out_idx;
} in_var_t; } in_var_t;
typedef struct out_var_str
{
int cnt;
} out_var_t;
typedef struct typedef struct
{ {
@ -7982,10 +8003,14 @@ namespace cw
in_var_t* inVarA; in_var_t* inVarA;
unsigned outVarN; unsigned outVarN;
out_var_t* outVarA;
unsigned midiBasePId; unsigned midiBasePId;
unsigned doneFlBasePId; unsigned doneFlBasePId;
unsigned outBasePId; unsigned outBasePId;
bool trigger_fl;
unsigned out_idx;
} inst_t; } inst_t;
@ -8055,14 +8080,19 @@ namespace cw
if((rc = var_register_and_get( proc, kAnyChIdx, kOutChCntPId, "out_ch_cnt", kBaseSfxId, p->outVarN )) != kOkRC ) if((rc = var_register_and_get( proc, kAnyChIdx, kOutChCntPId, "out_ch_cnt", kBaseSfxId, p->outVarN )) != kOkRC )
goto errLabel; goto errLabel;
// register the output selector var if((rc = var_register( proc, kAnyChIdx,
if((rc = var_register( proc, kAnyChIdx, kOutChIdxPId,"out_ch_idx", kBaseSfxId )) != kOkRC ) kOutChIdxPId,"out_ch_idx", kBaseSfxId,
kTriggerPId, "trig", kBaseSfxId)) != kOkRC )
{
goto errLabel; goto errLabel;
}
// create the output audio var's // create the output audio var's
for(unsigned i=0; i<p->outVarN; ++i) for(unsigned i=0; i<p->outVarN; ++i)
if((rc = var_register_and_set( proc, "out", kBaseSfxId + i, p->outBasePId+i, kAnyChIdx, srate, chCntPerInputSignal, audioFrameN )) != kOkRC ) if((rc = var_register_and_set( proc, "out", kBaseSfxId + i, p->outBasePId+i, kAnyChIdx, srate, chCntPerInputSignal, audioFrameN )) != kOkRC )
goto errLabel; goto errLabel;
p->outVarA = mem::allocZ<out_var_t>(p->outVarN);
errLabel: errLabel:
@ -8081,6 +8111,9 @@ namespace cw
rc_t _value( proc_t* proc, inst_t* p, variable_t* var ) rc_t _value( proc_t* proc, inst_t* p, variable_t* var )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
if( proc->ctx->isInRuntimeFl && var->vid == kTriggerPId )
p->trigger_fl = true;
return rc; return rc;
} }
@ -8110,14 +8143,40 @@ namespace cw
} }
unsigned _get_next_out_index(inst_t* p)
{
int min_cnt = p->outVarA[0].cnt;
unsigned min_idx = 0;
for(unsigned i=1; i<p->outVarN; ++i)
if( p->outVarA[i].cnt < min_cnt )
{
min_cnt = p->outVarA[i].cnt;
min_idx = i;
}
cwLogPrint("%i %i\n",min_idx,min_cnt);
return min_idx;
}
rc_t _exec( proc_t* proc, inst_t* p ) rc_t _exec( proc_t* proc, inst_t* p )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
abuf_t* outAudioBufA[ p->outVarN ]; abuf_t* outAudioBufA[ p->outVarN ];
unsigned out_var_idx; unsigned out_var_idx;
if((var_get(proc,kOutChIdxPId,kAnyChIdx,out_var_idx)) != kOkRC ) if( p->trigger_fl )
goto errLabel; {
p->trigger_fl = false;
p->out_idx = _get_next_out_index(p);
var_set(proc,kOutChIdxPId,kAnyChIdx,p->out_idx);
}
//if((var_get(proc,kOutChIdxPId,kAnyChIdx,out_var_idx)) != kOkRC )
// goto errLabel;
// get the audio output buffers // get the audio output buffers
for(unsigned i=0; i<p->outVarN; ++i) for(unsigned i=0; i<p->outVarN; ++i)
@ -8141,7 +8200,8 @@ namespace cw
for(unsigned j=0; j<mbuf->msgN; ++j) for(unsigned j=0; j<mbuf->msgN; ++j)
if( midi::isNoteOn(mbuf->msgA[j].status,mbuf->msgA[j].d1) ) if( midi::isNoteOn(mbuf->msgA[j].status,mbuf->msgA[j].d1) )
{ {
p->inVarA[i].out_idx = out_var_idx; p->inVarA[i].out_idx = p->out_idx;
p->outVarA[ p->out_idx ].cnt += 1;
//printf("VA: %i->%i\n",i,out_var_idx); //printf("VA: %i->%i\n",i,out_var_idx);
} }
@ -8153,8 +8213,8 @@ namespace cw
// if this input channel is no longer active // if this input channel is no longer active
if( p->inVarA[i].out_idx != kInvalidIdx && done_fl ) if( p->inVarA[i].out_idx != kInvalidIdx && done_fl )
{ {
p->outVarA[ p->inVarA[i].out_idx ].cnt -= 1;
p->inVarA[i].out_idx = kInvalidIdx; p->inVarA[i].out_idx = kInvalidIdx;
//printf("D:%i\n",i);
} }
// if this channel has a valid out var index // if this channel has a valid out var index