cwFlow.cpp,cwFlowNet.h/cpp : Network preset application now occurs strictly after the entire network is created.

Added _proc_verify_required_record_fields() to allow proc desc to specify what fields an incoming record must have.
This commit is contained in:
kevin 2024-12-23 16:35:24 -05:00
parent 88ae8bd0e4
commit e3b9b82289
3 changed files with 124 additions and 64 deletions

View File

@ -78,6 +78,7 @@ namespace cw
{ "midi_merge", &midi_merge::members }, { "midi_merge", &midi_merge::members },
{ "poly_xform_ctl", &poly_xform_ctl::members }, { "poly_xform_ctl", &poly_xform_ctl::members },
{ "score_player", &score_player::members }, { "score_player", &score_player::members },
{ "vel_table", &vel_table::members },
{ "preset_select", &preset_select::members }, { "preset_select", &preset_select::members },
{ "score_follower", &score_follower::members }, { "score_follower", &score_follower::members },
{ nullptr, nullptr } { nullptr, nullptr }
@ -1068,12 +1069,17 @@ cw::rc_t cw::flow::initialize( handle_t h,
} }
// instantiate the network // instantiate the network
if((rc = network_create(p,&p->networkCfg,1,proxyVarL,1,p->init_net_preset_label,p->net)) != kOkRC ) if((rc = network_create(p,&p->networkCfg,1,proxyVarL,nullptr,1,p->net)) != kOkRC )
{ {
rc = cwLogError(rc,"Network creation failed."); rc = cwLogError(rc,"Network creation failed.");
goto errLabel; goto errLabel;
} }
// if a network preset was specified apply it here
if( p->init_net_preset_label != nullptr && p->net != nullptr )
network_apply_preset(*p->net,p->init_net_preset_label);
if( p->printNetworkFl && p->net != nullptr ) if( p->printNetworkFl && p->net != nullptr )
network_print(*p->net); network_print(*p->net);

View File

@ -1022,7 +1022,7 @@ namespace cw
// locate remote variable // locate remote variable
if((rc = var_find( remote_proc, remote_var_label, remote_var_sfx_id, kAnyChIdx, remote_var)) != kOkRC ) if((rc = var_find( remote_proc, remote_var_label, remote_var_sfx_id, kAnyChIdx, remote_var)) != kOkRC )
{ {
rc = cwLogError(rc,"The %s-var '%s:i' was not found.", remote_label, io_stmt.remote_var_ele->label, remote_var_sfx_id); rc = cwLogError(rc,"The %s-var '%s:%i' was not found.", remote_label, io_stmt.remote_var_ele->label, remote_var_sfx_id);
goto errLabel; goto errLabel;
} }
@ -1457,6 +1457,55 @@ namespace cw
return rc1; return rc1;
} }
rc_t _proc_verify_required_record_fields( const proc_t* proc )
{
rc_t rc = kOkRC;
const variable_t* var;
for(var=proc->varL; var!=nullptr; var=var->var_link )
if( is_connected_to_source(var)
&& cwIsFlag(var->value->tflag,kRBufTFl)
&& var->classVarDesc->fmt.recd_fmt != nullptr
&& var->classVarDesc->fmt.recd_fmt->req_fieldL != nullptr )
{
const rbuf_t* rbuf = nullptr;
if((rc = var_get(var,rbuf)) != kOkRC )
{
rc = cwLogError(rc,"The connected rbuf field on var '%s:%i' could not be accessed.",cwStringNullGuard(var->label),var->label_sfx_id);
goto errLabel;
}
const object_t* fieldLabelL = var->classVarDesc->fmt.recd_fmt->req_fieldL;
unsigned fld_cnt = fieldLabelL->child_count();
for(unsigned i=0; i<fld_cnt; ++i)
{
const char* field_label = nullptr;
if((rc = fieldLabelL->child_ele(i)->value(field_label)) != kOkRC )
{
rc = cwLogError(rc,"Unable to parse required record field label on var '%s:%i'.",cwStringNullGuard(var->label),var->label_sfx_id);
goto errLabel;
}
if(recd_type_field_index( rbuf->type, field_label) == kInvalidIdx )
{
rc = cwLogError(rc,"The required field '%s' does not exist on var '%s:%i'.",cwStringNullGuard(field_label),cwStringNullGuard(var->label),var->label_sfx_id);
goto errLabel;
}
//printf("required field '%s' verified on '%s:%i-%s:%i'.\n",field_label,cwStringNullGuard(proc->label),proc->label_sfx_id,cwStringNullGuard(var->label),var->label_sfx_id);
}
}
errLabel:
if(rc != kOkRC )
cwLogError(rc,"Required field processing failed on '%s:%i-%s%i'.",cwStringNullGuard(proc->label),proc->label_sfx_id);
return rc;
}
// 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 char* proc_label_str, unsigned system_sfx_id, proc_inst_parse_state_t& pstate )
@ -1868,14 +1917,14 @@ namespace cw
unsigned sfx_id, unsigned sfx_id,
network_t& net, network_t& net,
variable_t* proxyVarL, variable_t* proxyVarL,
const object_t* net_preset_cfgD, //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; //const object_t* proc_preset_cfg = nullptr;
proc_ref = nullptr; proc_ref = nullptr;
@ -1960,11 +2009,11 @@ namespace cw
} }
// If the the network preset holds a preset for this proc // If the the network preset holds a preset for this proc
if( net_preset_cfgD!=nullptr && (proc_preset_cfg=net_preset_cfgD->find_child(proc->label)) != nullptr ) //if( net_preset_cfgD!=nullptr && (proc_preset_cfg=net_preset_cfgD->find_child(proc->label)) != nullptr )
{ //{
if((rc = _process_net_preset(proc,net_preset_cfgD)) != kOkRC ) // if((rc = _process_net_preset(proc,net_preset_cfgD)) != kOkRC )
goto errLabel; // goto errLabel;
} //}
// All the proc instance arg values have now been set and those variables // All the proc instance arg values have now been set and those variables
// that were expressed with a list have numeric channel indexes assigned. // that were expressed with a list have numeric channel indexes assigned.
@ -1976,7 +2025,6 @@ namespace cw
goto errLabel; goto errLabel;
} }
// Connect the proxied vars in this subnet proc to their respective proxy vars. // Connect the proxied vars in this subnet proc to their respective proxy vars.
if((rc = _subnet_connect_proxy_vars( proc, proxyVarL )) != kOkRC ) if((rc = _subnet_connect_proxy_vars( proc, proxyVarL )) != kOkRC )
{ {
@ -1984,6 +2032,10 @@ namespace cw
goto errLabel; goto errLabel;
} }
// verify that the required fields exist in all 'record' vars that act as 'src' variables
if((rc = _proc_verify_required_record_fields(proc)) != kOkRC )
goto errLabel;
// Complete the instantiation of the proc inst instance by calling the custom proc instance creation function. // Complete the instantiation of the proc inst instance by calling the custom proc instance creation function.
@ -2544,10 +2596,10 @@ namespace cw
preset_value = mem::allocZ<preset_value_t>(); preset_value = mem::allocZ<preset_value_t>();
preset_value->tid = kPolyPresetValueTId; preset_value->tid = kNetRefPresetValueTId;
preset_value->u.npv.net_preset = poly_net_preset; preset_value->u.npv.net_preset = poly_net_preset;
preset_value->u.npv.net_preset_net = poly_net; preset_value->u.npv.net_preset_net = poly_net;
preset_value->u.npv.net_preset_proc = poly_proc; //preset_value->u.npv.net_preset_proc = poly_proc;
_network_preset_link_in_value( network_preset, preset_value ); _network_preset_link_in_value( network_preset, preset_value );
} }
@ -2609,14 +2661,24 @@ namespace cw
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, proc_id.sfx_id )) == nullptr ) if((proc = proc_find(net, proc_id.label, net_sfx_id /*proc_id.sfx_id*/ )) == 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;
} }
// the label may refer to either a poly preset, a proc instance preset, or a class desc preset // 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_preset_label)) != kOkRC )
@ -2768,6 +2830,7 @@ namespace cw
} }
// Given a network preset label return the dictionary of proc presets that is associated with it. // Given a network preset label return the dictionary of proc presets that is associated with it.
/*
rc_t _get_network_preset_cfg( const object_t* presetsCfg, const char* preset_label, const object_t*& preset_ref ) rc_t _get_network_preset_cfg( const object_t* presetsCfg, const char* preset_label, const object_t*& preset_ref )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
@ -2806,7 +2869,8 @@ namespace cw
return rc; return rc;
} }
*/
template<typename T0, typename T1 > template<typename T0, typename T1 >
rc_t _preset_set_var_from_dual_interp_1( variable_t* var, T0 v0, T1 v1, double coeff ) rc_t _preset_set_var_from_dual_interp_1( variable_t* var, T0 v0, T1 v1, double coeff )
@ -2908,14 +2972,18 @@ namespace cw
for(psv=vlist->value_head; psv!=nullptr; psv=psv->link) for(psv=vlist->value_head; psv!=nullptr; psv=psv->link)
{ {
bool apply_to_all_poly_channels_fl = proc_label_sfx_id==kInvalidId;
bool apply_to_this_poly_channel_fl = psv->tid==kDirectPresetValueTId && psv->u.pvv.proc->label_sfx_id == proc_label_sfx_id;
bool psv_is_a_poly_preset_fl = psv->tid!=kDirectPresetValueTId;
// only apply the value if the proc_label_sfx_id is invalid or it matches the proc to which the value will be applied // only apply the value if the proc_label_sfx_id is invalid or it matches the proc to which the value will be applied
if( proc_label_sfx_id==kInvalidId || psv->tid!=kDirectPresetValueTId || (psv->tid==kDirectPresetValueTId && psv->u.pvv.proc->label_sfx_id == proc_label_sfx_id) ) if( apply_to_all_poly_channels_fl || apply_to_this_poly_channel_fl || psv_is_a_poly_preset_fl )
{ {
// if this preset refers to another network preset // if this preset refers to another network preset
switch( psv->tid ) switch( psv->tid )
{ {
case kPolyPresetValueTId: case kNetRefPresetValueTId:
if((rc = _network_apply_preset(*psv->u.npv.net_preset_net,psv->u.npv.net_preset,kInvalidId)) != kOkRC ) if((rc = _network_apply_preset(*psv->u.npv.net_preset_net,psv->u.npv.net_preset,proc_label_sfx_id)) != kOkRC )
{ {
rc = cwLogError(rc,"Application of network preset '%s' failed.",cwStringNullGuard(psv->u.npv.net_preset->label)); rc = cwLogError(rc,"Application of network preset '%s' failed.",cwStringNullGuard(psv->u.npv.net_preset->label));
goto errLabel; goto errLabel;
@ -3183,17 +3251,15 @@ namespace cw
// Network - Create // Network - Create
// //
rc_t _network_create( flow_t* p, rc_t _network_init( flow_t* p,
const object_t* networkCfg, const object_t* networkCfg,
unsigned sfx_id, unsigned sfx_id,
variable_t* proxyVarL, variable_t* proxyVarL,
const char* preset_label, network_t* net )
network_t*& net_ref )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
unsigned procN = 0; unsigned procN = 0;
const object_t* netPresetCfg = nullptr; //const object_t* netPresetCfg = nullptr;
network_t* net = mem::allocZ<network_t>();
// if the top level network has not been set then set it here. // if the top level network has not been set then set it here.
// (this is necessary so that proc's later in the exec order // (this is necessary so that proc's later in the exec order
@ -3214,11 +3280,11 @@ namespace cw
} }
// locate the requested network preset cfg // locate the requested network preset cfg
if((rc = _get_network_preset_cfg(net->presetsCfg,preset_label,netPresetCfg)) != kOkRC ) //if((rc = _get_network_preset_cfg(net->presetsCfg,preset_label,netPresetCfg)) != kOkRC )
{ //{
rc = cwLogError(rc,"Network create failed because the network preset resolution failed."); // rc = cwLogError(rc,"Network create failed because the network preset resolution failed.");
goto errLabel; // goto errLabel;
} //}
procN = net->procsCfg->child_count(); procN = net->procsCfg->child_count();
net->procA = mem::allocZ<proc_t*>(procN); net->procA = mem::allocZ<proc_t*>(procN);
@ -3229,7 +3295,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, netPresetCfg, net->procA[j] ) ) != kOkRC ) if( (rc= _proc_create( p, proc_cfg, sfx_id, *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;
@ -3246,21 +3312,8 @@ namespace cw
if((rc = _network_preset_parse_dict(p, *net, sfx_id, net->presetsCfg )) != kOkRC ) if((rc = _network_preset_parse_dict(p, *net, sfx_id, net->presetsCfg )) != kOkRC )
goto errLabel; goto errLabel;
net_ref = net;
errLabel: errLabel:
if( rc != kOkRC )
{
if( p->net == net )
p->net = nullptr;
net_ref = nullptr;
_network_destroy(net);
}
return rc; return rc;
} }
@ -3364,8 +3417,8 @@ cw::rc_t cw::flow::network_create( flow_t* p,
const object_t* const * netCfgA, const object_t* const * netCfgA,
unsigned netCfgN, unsigned netCfgN,
variable_t* proxyVarL, variable_t* proxyVarL,
const proc_t* owner_proc,
unsigned polyCnt, unsigned polyCnt,
const char* preset_label,
network_t*& net_ref ) network_t*& net_ref )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
@ -3378,39 +3431,40 @@ cw::rc_t cw::flow::network_create( flow_t* p,
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(unsigned i=0; i<polyCnt; ++i) for(unsigned i=0; i<polyCnt; ++i)
{ {
network_t* net = nullptr;
// All procs in a poly should share the same sfx_id // All procs in a poly should share the same sfx_id
// otherwise the sfx_id can be automatically generated. // otherwise the sfx_id can be automatically generated.
unsigned sfx_id = polyCnt>1 ? i : kInvalidId; unsigned sfx_id = i; //polyCnt>1 ? i : kInvalidId;
const object_t* netCfg = i < netCfgN ? netCfgA[i] : netCfgA[0]; const object_t* netCfg = i < netCfgN ? netCfgA[i] : netCfgA[0];
// create the network network_t* net = mem::allocZ<network_t>();
if((rc = _network_create(p, netCfg, sfx_id, proxyVarL, nullptr, net)) != kOkRC )
{ net->owner_proc = owner_proc;
rc = cwLogError(rc,"Network create failed on poly index %i.",i); net->polyN = polyCnt;
goto errLabel; net->poly_idx = i;
}
// The returned net is always the first in a poly chain
if( net_ref == nullptr ) if( net_ref == nullptr )
net_ref = net; net_ref = net;
net->poly_idx = i;
if( n0 != nullptr ) if( n0 != nullptr )
n0->poly_link = net; n0->poly_link = net;
n0 = 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);
goto errLabel;
}
} }
if( preset_label != nullptr && net_ref != nullptr )
network_apply_preset(*net_ref,preset_label);
errLabel: errLabel:
if( rc != kOkRC && net_ref != nullptr ) if( rc != kOkRC && net_ref != nullptr )
@ -3548,7 +3602,7 @@ cw::rc_t cw::flow::network_apply_preset( network_t& net, const char* preset_labe
errLabel: errLabel:
if(rc != kOkRC ) if(rc != kOkRC )
rc = cwLogError(rc,"The network application '%s' failed.", cwStringNullGuard(preset_label) ); rc = cwLogError(rc,"The network application '%s' with sfx_id '%i' failed.", cwStringNullGuard(preset_label), proc_label_sfx_id );
return rc; return rc;

View File

@ -14,9 +14,9 @@ namespace cw
rc_t network_create( flow_t* p, rc_t network_create( flow_t* p,
const object_t* const * netCfgA, // netCfgA[netCfgN] const object_t* const * netCfgA, // netCfgA[netCfgN]
unsigned netCfgN, // count of cfg. records in netCfgN unsigned netCfgN, // count of cfg. records in netCfgN
variable_t* proxyVarL, // variable_t* proxyVarL, //
const proc_t* owner_proc, // Pointer to the proc that owns this network (or null if creating the top level network)
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
const char* preset_label, // Optional top-level preset label
network_t*& net_ref // Returned network handle. network_t*& net_ref // Returned network handle.
); );