diff --git a/cwFlow.cpp b/cwFlow.cpp index 47cf7fa..884ade0 100644 --- a/cwFlow.cpp +++ b/cwFlow.cpp @@ -310,7 +310,7 @@ namespace cw goto errLabel; } - preset_t* preset = mem::allocZ< preset_t >(); + class_preset_t* preset = mem::allocZ< class_preset_t >(); preset->label = pair->pair_label(); preset->cfg = pair->pair_value(); diff --git a/cwFlowNet.cpp b/cwFlowNet.cpp index 4eb3a47..bae0a56 100644 --- a/cwFlowNet.cpp +++ b/cwFlowNet.cpp @@ -23,6 +23,33 @@ namespace cw { + void _preset_value_destroy( preset_value_t* v ) + { + mem::release(v); + } + + void _network_preset_destroy(network_preset_t& network_preset) + { + preset_value_t* pv = network_preset.value_head; + while( pv != nullptr ) + { + preset_value_t* pv0 = pv->link; + _preset_value_destroy(pv); + pv = pv0; + } + + network_preset.value_head = nullptr; + network_preset.value_tail = nullptr; + + } + + void _network_preset_array_destroy( network_t& net ) + { + for(unsigned i=0; i T _interp_dual_value( T v0, T v1, double coeff ) @@ -315,7 +348,8 @@ namespace cw errLabel: return rc; } - + + rc_t _multi_preset_channelize_vars( proc_t* proc, const char* type_src_label, const char** presetLabelA, const object_t** preset_cfgA, unsigned presetN, double coeff ) { rc_t rc = kOkRC; @@ -406,7 +440,7 @@ namespace cw { if( class_preset_labelA[i] != nullptr ) { - const preset_t* pr; + const class_preset_t* pr; // locate the requestd preset record if((pr = class_preset_find(proc->class_desc, class_preset_labelA[i])) == nullptr ) @@ -449,11 +483,12 @@ namespace cw return rc; } +#endif rc_t _class_preset_channelize_vars( proc_t* proc, const char* preset_label ) { rc_t rc = kOkRC; - const preset_t* pr; + const class_preset_t* pr; if( preset_label == nullptr ) return kOkRC; @@ -591,63 +626,6 @@ namespace cw return idxMapA[sel_idx]; } - /* - unsigned _select_ranked_ele_by_rank_prob( const preset_order_t* rankV, unsigned rankN ) - { - unsigned threshV[ rankN ]; - unsigned uniqueRankV[ rankN ]; - unsigned uniqueRankN = 0; - unsigned sel_idx = rankN - 1; // - - if( rankN == 0 ) - return kInvalidIdx; - - if( rankN == 1 ) - return 0; - - // for each possible rank value - for(unsigned i=0; ivarDescL; vd!=nullptr; vd=vd->link) if( !_is_var_proc_already_created( proc, vd->label, pstate ) && cwIsNotFlag(vd->type,kRuntimeTFl) ) { @@ -2298,11 +2268,12 @@ namespace cw // and the chIdx of each variable is set to 'any'. // If a 'preset' field was included in the class cfg then apply the specified class preset + // Note that the 'preset' field can be a string or list of strings. if( pstate.preset_labels != nullptr ) if((rc = _class_apply_presets(proc, pstate.preset_labels )) != kOkRC ) goto errLabel; - // All the class presets values have now been set and those variables + // The requested class presets values have now been set and those variables // that were expressed with a list have numeric channel indexes assigned. // Apply the proc inst instance 'args:{}' values. @@ -2315,25 +2286,14 @@ namespace cw // All the proc instance arg values have now been set and those variables // that were expressed with a list have numeric channel indexes assigned. - - // TODO: Should the 'all' variable be removed for variables that have numeric channel indexes? - + // Connect the var's that are referenced in the in-stmt to their respective sources if((rc = _io_stmt_connect_vars(net, proc, "in", "src", pstate.iStmtA, pstate.iStmtN)) != kOkRC ) { rc = cwLogError(rc,"Input connection processing failed."); goto errLabel; } - - /* - // Connect the in-list variables to their sources. - if((rc = _in_stmt_connect_in_vars(net, proc, pstate)) != kOkRC ) - { - rc = cwLogError(rc,"Input connection processing failed."); - goto errLabel; - } - */ - // Connect the proxied vars in this subnet proc + // Connect the proxied vars in this subnet proc to their respective proxy vars. if((rc = _subnet_connect_proxy_vars( proc, proxyVarL )) != kOkRC ) { rc = cwLogError(rc,"Proxy connection processing failed."); @@ -2371,6 +2331,7 @@ namespace cw if((rc = _proc_call_value_func_on_all_variables( proc )) != kOkRC ) goto errLabel; + // validate the proc's state. if((rc = proc_validate(proc)) != kOkRC ) { rc = cwLogError(rc,"proc inst instance validation failed."); @@ -2391,6 +2352,630 @@ namespace cw return rc; } + // + // Network preset pair table + // + + rc_t _network_preset_pair_count( const network_t& net, unsigned& count_ref ) + { + rc_t rc = kOkRC; + + count_ref = 0; + unsigned n = 0; + for(unsigned i=0; ivarL; var!=nullptr; var=var->var_link) + if( var->chIdx == kAnyChIdx ) + { + unsigned varChCnt = 0; + if((rc = var_channel_count(var,varChCnt)) != kOkRC ) + { + rc = cwLogError(rc,"The network preset pair count operation failed."); + goto errLabel; + } + + n += varChCnt + 1; // Add 1 for the kAnyCh + } + } + + count_ref = n; + errLabel: + + return rc; + } + + rc_t _network_preset_pair_fill_table( const network_t& net, network_preset_pair_t* nppA, unsigned nppN) + { + rc_t rc = kOkRC; + unsigned j = 0; + for(unsigned i=0; ivarL; var!=nullptr; var=var->var_link) + if( var->chIdx == kAnyChIdx ) + { + unsigned varChCnt = 0; + if((rc = var_channel_count(var,varChCnt)) != kOkRC ) + goto errLabel; + + unsigned k=0; + for(const variable_t* ch_var=var; ch_var!=nullptr; ch_var = ch_var->ch_link, ++j,++k ) + { + if( j >= nppN ) + { + rc = cwLogError(kInvalidStateRC,"Unexpected end of preset-pair table was encountered."); + goto errLabel; + } + + nppA[j].proc = proc; + nppA[j].var = ch_var; + nppA[j].chIdx = var->chIdx;; + nppA[j].chN = varChCnt;; + } + + if( k != varChCnt+1 ) + { + rc = cwLogError(kInvalidStateRC,"An inconsistent var channel count was encountered on '%s:%i'-'%s:%i'.", + cwStringNullGuard(proc->label),proc->label_sfx_id, + cwStringNullGuard(var->label),var->label_sfx_id); + goto errLabel; + } + + } + } + + if( j != nppN ) + rc = cwLogError(kInvalidStateRC,"The expected count of entries in the preset_pair table (%i) does not match the actual count (%i).",nppN,j); + + errLabel: + if( rc != kOkRC ) + rc = cwLogError(rc,"Preset pair table fill failed."); + return rc; + } + + rc_t _network_preset_pair_create_table( network_t& net ) + { + rc_t rc = kOkRC; + unsigned pair_count = 0; + + // get the total count of variables in this network + if((rc = _network_preset_pair_count(net, pair_count )) != kOkRC ) + goto errLabel; + + // allocate the preset pair tble + net.preset_pairA = mem::allocZ(pair_count); + net.preset_pairN = pair_count; + + // fill the preset pair table + if((rc= _network_preset_pair_fill_table(net, net.preset_pairA, net.preset_pairN)) != kOkRC ) + goto errLabel; + + + errLabel: + if( rc != kOkRC ) + { + rc = cwLogError(rc,"Network preset pair table create failed."); + mem::release(net.preset_pairA); + net.preset_pairN = 0; + } + + return rc; + } + + unsigned _network_preset_pair_find_index( const network_t& net, const variable_t* var ) + { + for(unsigned i=0; iproc == npp->proc && var == npp->var ) + { + assert( var->chIdx == npp->var->chIdx ); + return i; + } + } + + return kInvalidIdx; + } + + // + // Preset processing + // + + 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; + + // parse the proc label + if((rc= _io_stmt_parse_ele( proc_label, proc_id )) != kOkRC ) + { + rc = cwLogError(kSyntaxErrorRC,"Parse failed on the proc label '%s' of preset '%s'.",cwStringNullGuard(proc_label),cwStringNullGuard(network_preset.label)); + goto errLabel; + } + + // set the proc_id base sfx id + if( proc_id.base_sfx_id == kInvalidId ) + proc_id.base_sfx_id = kBaseSfxId; + + // if not iterating + if( !proc_id.is_iter_fl ) + { + proc_id.sfx_id_count = 1; + } + else + { + if( proc_id.sfx_id_count == kInvalidCnt ) + proc_id.sfx_id_count = proc_mult_count(net, proc_label ); + } + + errLabel: + return rc; + } + + rc_t _parse_network_proc_var_label( network_t& net, const char* network_preset_label, const object_t* var_pair, const char* proc_label, unsigned proc_label_sfx_id, io_ele_t& var_id ) + { + rc_t rc = kOkRC; + const char* var_label = nullptr; + + if( var_pair==nullptr || !var_pair->is_pair() || (var_label=var_pair->pair_label())==nullptr || var_pair->pair_value() == nullptr ) + { + rc = cwLogError(kSyntaxErrorRC,"A syntax error was encountered on a preset pair value on preset '%s:%s'.",cwStringNullGuard(network_preset_label),cwStringNullGuard(proc_label)); + goto errLabel; + } + + // + if((rc= _io_stmt_parse_ele( var_label, var_id )) != kOkRC ) + { + rc = cwLogError(rc,"Parse failed on the var label of preset '%s:%s:%s'.",cwStringNullGuard(network_preset_label),cwStringNullGuard(proc_label),cwStringNullGuard(var_label)); + goto errLabel; + } + + // set the var_id base sfx id + if( var_id.base_sfx_id == kInvalidId ) + var_id.base_sfx_id = kBaseSfxId; + + // if not iterating + if( !var_id.is_iter_fl ) + { + var_id.sfx_id_count = 1; + } + else + { + + proc_t* proc; + + // find the var proc + if((proc = proc_find(net,proc_label,proc_label_sfx_id)) == nullptr ) + { + rc = cwLogError(kEleNotFoundRC,"The proc '%s' could not be found for network preset '%s'.",cwStringNullGuard(proc_label),cwStringNullGuard(network_preset_label)); + goto errLabel; + } + + if( var_id.sfx_id_count == kInvalidCnt ) + var_id.sfx_id_count = var_mult_count(proc, proc_label ); + } + + errLabel: + return rc; + + } + + rc_t _network_preset_get_class_preset( network_t& net, const char* network_preset_label, const char* proc_label, const object_t* class_preset_label_cfg, const object_t*& class_preset_cfg_ref ) + { + rc_t rc = kOkRC; + const char* class_preset_label = nullptr;; + const class_preset_t* class_preset = nullptr; + class_desc_t* class_desc = nullptr; + proc_t* proc = nullptr; + + class_preset_cfg_ref = nullptr; + + // get the label of the proc class preset + if((rc = class_preset_label_cfg->value(class_preset_label)) != kOkRC ) + { + rc = cwLogError(rc,"The preset label could not be parsed on the preset:'%s:%s'",cwStringNullGuard(network_preset_label),cwStringNullGuard(proc_label)); + goto errLabel; + } + + // locate the proc this preset will be applied to + if((proc = proc_find(net, proc_label, kBaseSfxId )) == nullptr ) + { + rc = cwLogError(rc,"The proc '%s' could not be found for the preset:'%s'",cwStringNullGuard(proc_label),cwStringNullGuard(network_preset_label)); + goto errLabel; + } + + // get the preset record for this proc/preset_label + if((class_preset = class_preset_find( proc->class_desc, class_preset_label )) == nullptr ) + { + rc = cwLogError(rc,"The class description for proc '%s' could not be found for the preset:'%s'",cwStringNullGuard(proc_label),cwStringNullGuard(network_preset_label)); + goto errLabel; + } + + class_preset_cfg_ref = class_preset->cfg; + + errLabel: + return rc; + } + + rc_t _network_preset_create_channel_value( network_t& net, network_preset_t& network_preset, proc_t* proc, variable_t* var, unsigned chN, const object_t* value_cfg ) + { + rc_t rc = kOkRC; + unsigned pairTblIdx = kInvalidIdx; + preset_value_t* preset_value = mem::allocZ(); + + // cfg to value + if((rc = cfg_to_value( value_cfg, preset_value->value )) != kOkRC ) + { + rc = cwLogError(rc,"The preset cfg to value conversion failed on '%s:%i'-'%s:%i'.",cwStringNullGuard(var->label),var->label_sfx_id,cwStringNullGuard(proc->label),proc->label_sfx_id); + goto errLabel; + } + + // locate the the + if((pairTblIdx = _network_preset_pair_find_index(net, var )) == kInvalidIdx ) + { + rc = cwLogError(rc,"The preset pair record could not be found for '%s:%i'-'%s:%i'.",cwStringNullGuard(var->label),var->label_sfx_id,cwStringNullGuard(proc->label),proc->label_sfx_id); + goto errLabel; + } + + preset_value->proc = proc; + preset_value->var = var; + preset_value->chN = chN; + preset_value->pairTblIdx = pairTblIdx; + + if( network_preset.value_head == nullptr ) + network_preset.value_head = preset_value; + else + network_preset.value_tail->link = preset_value; + + network_preset.value_tail = preset_value; + + errLabel: + if(rc != kOkRC ) + _preset_value_destroy(preset_value); + + return rc; + } + + rc_t _network_preset_find_or_create_variable( proc_t* proc, const char* var_label, unsigned var_sfx_id, unsigned chIdx, const object_t* value_cfg, bool allow_create_fl, variable_t*& var_ref ) + { + rc_t rc = kOkRC; + variable_t* var = nullptr; + var_ref = nullptr; + + // if the var was not found on 'chIdx' + if((rc = var_find(proc, var_label, var_sfx_id, chIdx, var )) != kOkRC ) + { + + if( !allow_create_fl ) + { + rc = cwLogError(kEleNotFoundRC,"The preset variable '%s:%i' ch:%i could not be found on proc: '%s:%i'.", + cwStringNullGuard(var_label),var_sfx_id,chIdx, cwStringNullGuard(proc->label),proc->label_sfx_id ); + goto errLabel; + } + else + { + variable_t* base_var = nullptr; + // get the base var + if((rc = var_find(proc, var_label, kBaseSfxId, kAnyChIdx, var)) != kOkRC ) + { + rc = cwLogError(rc,"The base variable '%s:%i' ch:%i could not be found to pre-emptively create the variable '%s:%i' ch:%i on proc: '%s:%i'.", + cwStringNullGuard(var_label),kBaseSfxId,kAnyChIdx, + cwStringNullGuard(var_label),var_sfx_id,chIdx, + cwStringNullGuard(proc->label),proc->label_sfx_id); + goto errLabel; + } + + // create the variable + if((rc = var_create( proc, var_label, var_sfx_id, kInvalidId, chIdx, value_cfg, kInvalidTFl, var )) != kOkRC ) + { + rc = cwLogError(rc,"Pre-emptive variable creation failed for '%s:%i' ch:%i on proc:'%s:%i'.", + cwStringNullGuard(var_label),var_sfx_id,chIdx, + cwStringNullGuard(proc->label),proc->label_sfx_id); + goto errLabel; + } + } + } + + var_ref = var; + + errLabel: + return rc; + } + + + rc_t _network_preset_create_value( network_t& net, + network_preset_t& network_preset, + const char* proc_label, + unsigned proc_sfx_id, + const char* var_label, + unsigned var_sfx_id, + const object_t* value_cfg ) + { + rc_t rc = kOkRC; + var_desc_t* var_desc = nullptr; + proc_t* proc = nullptr; + + + // locate the proc this preset will be applied to + if((proc = proc_find(net, proc_label, proc_sfx_id )) == nullptr ) + { + rc = cwLogError(kOpFailRC,"The proc '%s:%i' does not exist.",cwStringNullGuard(proc_label),proc_sfx_id); + goto errLabel; + } + else + { + bool is_var_cfg_type_fl = (var_desc = var_desc_find( proc->class_desc, var_label ))!=nullptr && cwIsFlag(var_desc->type,kCfgTFl); + bool is_list_fl = value_cfg->is_list(); + bool is_list_of_list_fl = is_list_fl && value_cfg->child_count() > 0 && value_cfg->child_ele(0)->is_list(); + bool parse_list_fl = (is_list_fl && !is_var_cfg_type_fl) || (is_list_of_list_fl && is_var_cfg_type_fl); + + // Case 1: By default we assume a single variable instance on channel 'kAnyChIdx' .... + unsigned valueN = 1; + unsigned chIdx = kAnyChIdx; + const object_t* vobj = value_cfg; + + // Case 2: ... however if a list of preset values was given and the var type is not a 'cfg' type or if a list of lists was given + // then we are going to iterate through a list of preset values each on a successive channel index + if( parse_list_fl ) + { + chIdx = 0; + valueN = value_cfg->child_count(); + vobj = value_cfg->child_ele(0); + } + + // Iterate over each channel + for(unsigned i = 0; ichild_ele(i); + } + } + //printf("%s %s:%i-%s:%i\n",network_preset.label,proc_label,proc_sfx_id,var_label,var_sfx_id); + } + errLabel: + + return rc; + } + + + rc_t _network_preset_parse( flow_t* p, network_t& net, const object_t* network_preset_dict_cfg, network_preset_t& network_preset ) + { + rc_t rc = kOkRC; + unsigned procN = 0; + + if( network_preset_dict_cfg==nullptr || !network_preset_dict_cfg->is_dict() ) + { + rc = cwLogError(kSyntaxErrorRC,"The proc preset dictionary is not a dictionary in network preset:'%s'.",cwStringNullGuard(network_preset.label)); + goto errLabel; + } + + procN = network_preset_dict_cfg->child_count(); + + // for each proc in the network preset + for(unsigned i=0; ichild_ele(i); + const char* proc_label = nullptr; + io_ele_t proc_id = {}; + unsigned varN = 0; + + // 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 ) + { + rc = cwLogError(kSyntaxErrorRC,"A syntax error was encountered on a preset pair on preset '%s'.",cwStringNullGuard(network_preset.label)); + goto errLabel; + } + + // parse the proc label + if((rc= _parse_network_proc_label(net, network_preset, proc_label, proc_id )) != kOkRC ) + goto errLabel; + + // if the preset refers to a proc class preset + if( proc_preset_pair->pair_value()->is_string() ) + { + // get the referenced preset cfg from the class desc + if((rc = _network_preset_get_class_preset( net, network_preset.label, proc_id.label, proc_preset_pair->pair_value(), var_dict )) != kOkRC ) + goto errLabel; + } + else // the preset is a dictionary of var/value pairs + { + // if preset is not a dictionary + if( !proc_preset_pair->pair_value()->is_dict() ) + { + rc = cwLogError(kSyntaxErrorRC,"The preset value dictionary for '%s:%s' is not valid.",cwStringNullGuard(network_preset.label),cwStringNullGuard(proc_id.label)); + goto errLabel; + } + + var_dict = proc_preset_pair->pair_value(); + } + + // var_dict now refers to a dictionary of var/value pairs for a single proc + + varN = var_dict->child_count(); + + // for each proc/sf_id (the proc label may refer to multiple proc instances) + for(unsigned j=0; jchild_ele(k); + + // parse the preset var label + if((rc = _parse_network_proc_var_label(net, network_preset.label, var_pair, proc_id.label, proc_id.base_sfx_id + j, var_id )) != kOkRC ) + goto errLabel; + + // create a preset for each var:sfx_id pair (the var label may refer to multiple var instances) + for(unsigned m=0; mpair_value() )) != kOkRC ) + goto errLabel; + + mem::release(var_id.label); + } + } + + mem::release(proc_id.label); + } + + errLabel: + return rc; + } + + + rc_t _network_preset_parse_top_level_dict( flow_t* p, network_t& net, const object_t* preset_cfg ) + { + rc_t rc = kOkRC; + unsigned presetAllocN = 0; + + if( preset_cfg == nullptr ) + return rc; + + if( !preset_cfg->is_dict() ) + { + rc = cwLogError(kSyntaxErrorRC,"The network preset list is not a dictionary."); + goto errLabel; + } + + presetAllocN = preset_cfg->child_count(); + net.presetA = mem::allocZ(presetAllocN); + net.presetN = 0; + + // parse each preset_label pair + for(unsigned i=0; ichild_ele(i); + network_preset_t& network_preset = net.presetA[i]; + + // validate the network preset pair + if( preset_pair_cfg==nullptr || !preset_pair_cfg->is_pair() || (network_preset.label = preset_pair_cfg->pair_label())==nullptr || preset_pair_cfg->pair_value()==nullptr || !preset_pair_cfg->pair_value()->is_dict() ) + { + rc = cwLogError(kSyntaxErrorRC,"Invalid syntax encountered on a network preset."); + goto errLabel; + } + + // parse the dictionary of proc presets + if((rc = _network_preset_parse(p, net, preset_pair_cfg->pair_value(), network_preset)) != kOkRC ) + { + rc = cwLogError(kSyntaxErrorRC,"Network preset parse failed on preset:'%s'.",cwStringNullGuard(network_preset.label)); + goto errLabel; + + } + + net.presetN += 1; + } + + errLabel: + if(rc != kOkRC ) + { + _network_preset_array_destroy(net); + } + + return rc; + } + + + template + rc_t _preset_set_var_from_dual_interp_1( variable_t* var, T0 v0, T1 v1, double coeff ) + { + return var_set(var, (T0)(v0 + (v1-v0)*coeff )); + } + + template< typename T > + rc_t _preset_set_var_from_dual_interp_0( variable_t* var, T v0, const value_t* v1, double coeff ) + { + rc_t rc = kOkRC; + switch( v1->tflag & kTypeMask ) + { + case kUIntTFl: + rc = _preset_set_var_from_dual_interp_1(var,v0,v1->u.u,coeff); + break; + + case kIntTFl: + rc = _preset_set_var_from_dual_interp_1(var,v0,v1->u.u,coeff); + break; + + case kFloatTFl: + rc = _preset_set_var_from_dual_interp_1(var,v0,v1->u.u,coeff); + break; + + case kDoubleTFl: + rc = _preset_set_var_from_dual_interp_1(var,v0,v1->u.u,coeff); + break; + + default: + rc = cwLogError(kInvalidDataTypeRC,"The second operand of a set by interpolation had a non-numeric data type."); + } + return rc; + } + + + + rc_t _preset_set_var_from_dual( const preset_value_t* preset_val, const value_t* value_1, double coeff ) + { + rc_t rc = kOkRC; + unsigned legalTypeMask = kUIntTFl | kIntTFl | kFloatTFl | kDoubleTFl; + + if( value_1 == nullptr || (preset_val->value.tflag & legalTypeMask)==0 ) + rc = var_set( preset_val->var, &preset_val->value ); + else + { + if( (value_1->tflag & legalTypeMask) == 0 ) + { + rc = cwLogError(kInvalidDataTypeRC,"The type of value-1 (0x%x) is not a scalar number.",value_1->tflag); + goto errLabel; + } + + switch( preset_val->value.tflag & legalTypeMask ) + { + case kUIntTFl: + rc = _preset_set_var_from_dual_interp_0( preset_val->var, preset_val->value.u.u, value_1, coeff ); + break; + + case kIntTFl: + rc = _preset_set_var_from_dual_interp_0( preset_val->var, preset_val->value.u.i, value_1, coeff ); + break; + + case kFloatTFl: + rc = _preset_set_var_from_dual_interp_0( preset_val->var, preset_val->value.u.f, value_1, coeff ); + break; + + case kDoubleTFl: + rc = _preset_set_var_from_dual_interp_0( preset_val->var, preset_val->value.u.d, value_1, coeff ); + break; + + default: + rc = cwLogError(kInvalidDataTypeRC,"The first operand of a set by interpolation had a non-numeric data type."); + + } + } + + errLabel: + if(rc != kOkRC ) + rc = cwLogError(rc,"Set variable from dual preset failed on '%s:%i'-'%s:%i' ch:0.", + cwStringNullGuard(preset_val->proc->label),preset_val->proc->label_sfx_id, + cwStringNullGuard(preset_val->var->label),preset_val->var->label_sfx_id, + preset_val->var->chIdx); + return rc; + } + } } @@ -2460,6 +3045,12 @@ cw::rc_t cw::flow::network_create( flow_t* p, } net.poly_cnt = polyCnt; + + + if((rc = _network_preset_pair_create_table(net)) != kOkRC ) + goto errLabel; + + _network_preset_parse_top_level_dict(p, net, net.presetsCfg ); errLabel: if( rc != kOkRC ) @@ -2535,7 +3126,104 @@ errLabel: return rc; } +cw::rc_t cw::flow::network_apply_preset( network_t& net, const char* preset_label, unsigned proc_label_sfx_id ) +{ + rc_t rc = kOkRC; + const network_preset_t* network_preset = nullptr; + const preset_value_t* preset_value = nullptr; + if((network_preset = network_preset_from_label(net, preset_label )) == nullptr ) + { + rc = cwLogError(kInvalidIdRC,"The network preset '%s' could not be found.", preset_label ); + goto errLabel; + } + + for(preset_value=network_preset->value_head; preset_value!=nullptr; preset_value=preset_value->link) + if( preset_value->proc->label_sfx_id == proc_label_sfx_id ) + if((rc = var_set( preset_value->var, &preset_value->value )) != kOkRC ) + { + rc = cwLogError(rc,"Preset value apply failed on '%s:%i'-'%s:%i' in the network preset:'%s'.", + cwStringNullGuard(preset_value->proc->label),preset_value->proc->label_sfx_id, + cwStringNullGuard(preset_value->var->label),preset_value->var->label_sfx_id, + cwStringNullGuard(preset_label)); + goto errLabel; + } + + cwLogInfo("Activated preset:%s",preset_label); + +errLabel: + return rc; + +} + +cw::rc_t cw::flow::network_apply_dual_preset( network_t& net, const char* preset_label_0, const char* preset_label_1, double coeff ) +{ + rc_t rc = kOkRC; + const network_preset_t* net_ps0 = nullptr; + const network_preset_t* net_ps1 = nullptr; + + if((net_ps0 = network_preset_from_label(net, preset_label_0 )) == nullptr ) + { + rc = cwLogError(kInvalidIdRC,"The network preset '%s' could not be found.", preset_label_0 ); + goto errLabel; + } + + if((net_ps1 = network_preset_from_label(net, preset_label_1 )) == nullptr ) + { + rc = cwLogError(kInvalidIdRC,"The network preset '%s' could not be found.", preset_label_1 ); + goto errLabel; + } + + // clear the value filed of the preset-pair array + for(unsigned i=0; ivalue_head; pv1!=nullptr; pv1=pv1->link) + { + if( pv1->var->chIdx != kAnyChIdx ) + net.preset_pairA[ pv1->pairTblIdx ].value = &pv1->value; + else + { + for(unsigned i=0; ipairTblIdx ].chN; ++i) + { + net.preset_pairA[ pv1->pairTblIdx+i ].value = &pv1->value; + assert( textIsEqual(net.preset_pairA[ pv1->pairTblIdx+i ].var->label,pv1->var->label) && net.preset_pairA[ pv1->pairTblIdx+i ].var->label_sfx_id == pv1->var->label_sfx_id ); + } + } + } + + // + for(const preset_value_t* pv0=net_ps0->value_head; pv0!=nullptr; pv0=pv0->link) + { + if( pv0->var->chIdx != kAnyChIdx ) + { + rc = _preset_set_var_from_dual( pv0, net.preset_pairA[ pv0->pairTblIdx ].value, coeff ); + } + else + { + for(unsigned i=0; ipairTblIdx ].chN; ++i) + { + if((rc = _preset_set_var_from_dual( pv0, net.preset_pairA[ pv0->pairTblIdx+i ].value, coeff )) != kOkRC ) + goto errLabel; + + assert( textIsEqual(net.preset_pairA[ pv0->pairTblIdx+i ].var->label,pv0->var->label) && net.preset_pairA[ pv0->pairTblIdx+i ].var->label_sfx_id == pv0->var->label_sfx_id ); + } + } + + } + +errLabel: + if( rc != kOkRC ) + rc = cwLogError(rc,"Apply dual-preset failed."); + + return rc; + +} + + + +#ifdef NOT_DEF cw::rc_t cw::flow::network_apply_preset( network_t& net, const char* presetLabel, unsigned proc_label_sfx_id ) { rc_t rc = kOkRC; @@ -2625,10 +3313,10 @@ cw::rc_t cw::flow::network_apply_dual_preset( network_t& net, const char* preset const object_t* preset_pair_0 = net_preset_value_0->child_ele(i); const char* proc_label = preset_pair_0->pair_label(); const object_t* preset_value_cfg_0 = preset_pair_0->pair_value(); - proc_t* proc = nullptr; + proc_t* proc = nullptr; const object_t* preset_value_cfg_1 = nullptr; - const int two = 2; - const char* class_preset_labelA[two]; + const int two = 2; + const char* class_preset_labelA[two]; // get the proc instance label/value pair if((preset_pair_0 = net_preset_value_0->child_ele(i)) == nullptr || !preset_pair_0->is_pair() ) @@ -2699,6 +3387,9 @@ errLabel: return rc; } +#endif + + cw::rc_t cw::flow::network_apply_preset( network_t& net, const multi_preset_selector_t& mps ) { rc_t rc = kOkRC; diff --git a/cwFlowTypes.cpp b/cwFlowTypes.cpp index 8597ac7..866918e 100644 --- a/cwFlowTypes.cpp +++ b/cwFlowTypes.cpp @@ -1347,8 +1347,8 @@ void cw::flow::class_desc_destroy( class_desc_t* class_desc) } // release the preset list - preset_t* pr0 = class_desc->presetL; - preset_t* pr1 = nullptr; + class_preset_t* pr0 = class_desc->presetL; + class_preset_t* pr1 = nullptr; while( pr0 != nullptr ) { pr1 = pr0->link; @@ -1393,9 +1393,9 @@ cw::rc_t cw::flow::var_desc_find( class_desc_t* cd, const char* label, var_desc_ return kOkRC; } -const cw::flow::preset_t* cw::flow::class_preset_find( const class_desc_t* cd, const char* preset_label ) +const cw::flow::class_preset_t* cw::flow::class_preset_find( const class_desc_t* cd, const char* preset_label ) { - const preset_t* pr; + const class_preset_t* pr; for(pr=cd->presetL; pr!=nullptr; pr=pr->link) if( textCompare(pr->label,preset_label) == 0 ) return pr; @@ -1430,6 +1430,71 @@ void cw::flow::network_print( const network_t& net ) } } + + if(net.presetN > 0 ) + { + cwLogPrint("Presets:\n"); + for(unsigned i=0; ilabel); + const preset_value_t* net_val = net_preset->value_head; + for(; net_val!=nullptr; net_val=net_val->link) + { + cwLogPrint(" %s:%i %s:%i ",cwStringNullGuard(net_val->proc->label),net_val->proc->label_sfx_id,cwStringNullGuard(net_val->var->label),net_val->var->label_sfx_id); + _value_print( &net_val->value ); + cwLogPrint("\n"); + } + } + cwLogPrint("\n"); + } +} + +const cw::flow::network_preset_t* cw::flow::network_preset_from_label( const network_t& net, const char* preset_label ) +{ + const network_preset_t* net_preset; + for(unsigned i=0; ilabel,proc_label) ) + multN += 1; + + return multN; +} + +cw::rc_t cw::flow::proc_mult_sfx_id_array( const network_t& net, const char* proc_label, unsigned* idA, unsigned idAllocN, unsigned& idN_ref ) +{ + rc_t rc = kOkRC; + unsigned multN = 0; + + idN_ref = 0; + + for(unsigned i=0; ilabel,proc_label) ) + { + if( multN >= idAllocN ) + { + rc = cwLogError(kBufTooSmallRC,"The mult-sfx-id result array is too small for the proc:'%s'.",cwStringNullGuard(proc_label)); + goto errLabel; + } + + idA[multN] = net.proc_array[i]->label_sfx_id; + multN += 1; + } + + idN_ref = multN; + +errLabel: + + return kOkRC; } void cw::flow::proc_destroy( proc_t* proc ) @@ -2162,6 +2227,71 @@ cw::rc_t cw::flow::var_get( variable_t* var, mbuf_t*& valRef ) cw::rc_t cw::flow::var_get( const variable_t* var, const object_t*& valRef ) { return _val_get_driver(var,valRef); } +cw::rc_t cw::flow::cfg_to_value( const object_t* cfg, value_t& value_ref ) +{ + rc_t rc = kOkRC; + + switch( cfg->type->id ) + { + case kCharTId: + case kUInt8TId: + case kUInt16TId: + case kUInt32TId: + value_ref.tflag = kUIntTFl; + if((rc = cfg->value(value_ref.u.u)) != kOkRC ) + rc = cwLogError(rc,"Conversion to uint failed."); + break; + + case kInt8TId: + case kInt16TId: + case kInt32TId: + value_ref.tflag = kUIntTFl; + if((rc = cfg->value(value_ref.u.i)) != kOkRC ) + rc = cwLogError(rc,"Conversion to int failed."); + break; + + case kInt64TId: + case kUInt64TId: + rc = cwLogError(kInvalidArgRC,"The flow system does not currently implement 64bit integers."); + goto errLabel; + break; + + case kFloatTId: + value_ref.tflag = kFloatTFl; + if((rc = cfg->value(value_ref.u.f)) != kOkRC ) + rc = cwLogError(rc,"Conversion to float failed."); + break; + + case kDoubleTId: + value_ref.tflag = kDoubleTFl; + if((rc = cfg->value(value_ref.u.d)) != kOkRC ) + rc = cwLogError(rc,"Conversion to double failed."); + break; + + case kBoolTId: + value_ref.tflag = kBoolTFl; + if((rc = cfg->value(value_ref.u.b)) != kOkRC ) + rc = cwLogError(rc,"Conversion to bool failed."); + break; + + case kStringTId: + case kCStringTId: + value_ref.tflag = kStringTFl; + if((rc = cfg->value(value_ref.u.s)) != kOkRC ) + rc = cwLogError(rc,"Conversion to string failed."); + break; + + default: + value_ref.tflag = kCfgTFl; + value_ref.u.cfg = cfg; + + } +errLabel: + + return rc; +} + + cw::rc_t cw::flow::var_set_from_preset( variable_t* var, const object_t* value ) { rc_t rc = kOkRC; diff --git a/cwFlowTypes.h b/cwFlowTypes.h index 9b79bd2..32b856a 100644 --- a/cwFlowTypes.h +++ b/cwFlowTypes.h @@ -164,19 +164,19 @@ namespace cw struct var_desc_str* link; // class_desc->varDescL list link } var_desc_t; - typedef struct preset_str + typedef struct class_preset_str { - const char* label; - const object_t* cfg; - struct preset_str* link; - } preset_t; + const char* label; + const object_t* cfg; + struct class_preset_str* link; + } class_preset_t; typedef struct class_desc_str { const object_t* cfg; // class cfg const char* label; // class label; var_desc_t* varDescL; // varDescL variable description linked on var_desc_t.link - preset_t* presetL; // presetA[ presetN ] + class_preset_t* presetL; // presetA[ presetN ] 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 } class_desc_t; @@ -220,26 +220,13 @@ namespace cw } variable_t; - - struct proc_str; - typedef struct network_str - { - const object_t* procsCfg; // network proc list - const object_t* presetsCfg; // presets designed for this network - unsigned poly_cnt; // count of duplicated networks in the list - - struct proc_str** proc_array; - - unsigned proc_arrayAllocN; - unsigned proc_arrayN; - - } network_t; + struct network_str; typedef struct proc_str { - struct flow_str* ctx; // global system context - network_t* net; // network which owns this proc + struct flow_str* ctx; // global system context + struct network_str* net; // network which owns this proc class_desc_t* class_desc; // @@ -260,11 +247,57 @@ namespace cw unsigned varMapN; // varMapN = varMapIdN * varMapChN variable_t** varMapA; // varMapA[ varMapN ] = allows fast lookup from ('vid','chIdx) to variable - network_t* internal_net; + struct network_str* internal_net; } proc_t; + typedef struct preset_value_str + { + proc_t* proc; + variable_t* var; + value_t value; + unsigned chN; // count of channels specified by this preset + unsigned pairTblIdx; // index into the preset pair table for this preset value + struct preset_value_str* link; + } preset_value_t; + + typedef struct network_preset_str + { + const char* label; + preset_value_t* value_head; // List of preset_value_t for this preset. + preset_value_t* value_tail; + } network_preset_t; + + typedef struct network_preset_pair_str + { + const proc_t* proc; + const variable_t* var; + unsigned chIdx; + unsigned chN; + const value_t* value; + } network_preset_pair_t; + + typedef struct network_str + { + const object_t* procsCfg; // network proc list + const object_t* presetsCfg; // presets designed for this network + unsigned poly_cnt; // count of duplicated networks in the list + + struct proc_str** proc_array; + + unsigned proc_arrayAllocN; + unsigned proc_arrayN; + + network_preset_t* presetA; + unsigned presetN; + + network_preset_pair_t* preset_pairA; + unsigned preset_pairN; + + } network_t; + + typedef struct flow_str { const object_t* flowCfg; // complete cfg used to create this flow @@ -347,7 +380,7 @@ namespace cw 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( const class_desc_t* cd, const char* preset_label ); + const class_preset_t* class_preset_find( const class_desc_t* cd, const char* preset_label ); void class_dict_print( flow_t* p ); @@ -356,11 +389,18 @@ namespace cw // // Network // - void network_print(const network_t& net ); + void network_print(const network_t& net ); + const network_preset_t* network_preset_from_label( const network_t& net, const char* preset_label ); + + unsigned proc_mult_count( const network_t& net, const char* proc_label ); + + rc_t proc_mult_sfx_id_array( const network_t& net, const char* proc_label, unsigned* idA, unsigned idAllocN, unsigned& idN_ref ); + + //------------------------------------------------------------------------------------------------------------------------ // - // Instance + // Proc // void proc_destroy( proc_t* proc ); @@ -368,7 +408,7 @@ namespace cw proc_t* proc_find( network_t& net, const char* proc_label, unsigned sfx_id ); rc_t proc_find( network_t& net, const char* proc_label, unsigned sfx_id, proc_t*& procPtrRef ); - + external_device_t* external_device_find( flow_t* p, const char* device_label, unsigned typeId, unsigned inOrOutFl, const char* midiPortLabel=nullptr ); void proc_print( proc_t* proc ); @@ -546,10 +586,12 @@ namespace cw rc_t var_find( proc_t* proc, unsigned vid, unsigned chIdx, variable_t*& varRef ); - // Count of numbered channels - does not count the kAnyChIdx variable procance. + // Count of numbered channels - does not count the kAnyChIdx variable instance. rc_t var_channel_count( proc_t* proc, const char* label, unsigned sfx_idx, unsigned& chCntRef ); rc_t var_channel_count( const variable_t* var, unsigned& chCntRef ); - + + rc_t cfg_to_value( const object_t* cfg, value_t& value_ref ); + // // var_get() coerces the value of the variable to the type of the returned value.