#include "cwCommon.h" #include "cwLog.h" #include "cwCommonImpl.h" #include "cwTest.h" #include "cwMem.h" #include "cwMath.h" #include "cwText.h" #include "cwObject.h" #include "cwFileSys.h" #include "cwVectOps.h" #include "cwMtx.h" #include "cwDspTypes.h" // real_t, sample_t #include "cwTime.h" #include "cwMidiDecls.h" #include "cwFlowDecl.h" #include "cwFlow.h" #include "cwFlowValue.h" #include "cwFlowTypes.h" namespace cw { namespace flow { idLabelPair_t _varDescAttrFlagsA[] = { { kSrcVarDescFl, "src" }, { kSrcOptVarDescFl, "src_opt" }, { kNoSrcVarDescFl, "no_src" }, { kInitVarDescFl, "init" }, { kMultVarDescFl, "mult" }, { kUdpOutVarDescFl, "out" }, { kInvalidVarDescFl, "" } }; template< typename T > rc_t _val_get_driver( const variable_t* var, T& valRef ) { if( var == nullptr ) return cwLogError(kInvalidArgRC,"Cannnot get the value of a non-existent variable."); if( var->value == nullptr ) return cwLogError(kInvalidStateRC,"No value has been assigned to the variable: %s:%i.%s:%i ch:%i.",cwStringNullGuard(var->proc->label),var->proc->label_sfx_id,cwStringNullGuard(var->label),var->label_sfx_id,var->chIdx); return value_get(var->value,valRef); } // Variable lookup: Exact match on vid and chIdx rc_t _var_find_on_vid_and_ch( proc_t* proc, unsigned vid, unsigned chIdx, variable_t*& varRef ) { varRef = nullptr; for(variable_t* var = proc->varL; var!=nullptr; var=var->var_link) { // the variable vid and chIdx should form a unique pair if( var->vid==vid && var->chIdx == chIdx ) { varRef = var; return kOkRC; } } return cwLogError(kInvalidIdRC,"The variable matching id:%i ch:%i on proc '%s:%i' could not be found.", vid, chIdx, proc->label, proc->label_sfx_id); } // Variable lookup: Exact match on label and chIdx variable_t* _var_find_on_label_and_ch( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned chIdx ) { for(variable_t* var = proc->varL; var!=nullptr; var=var->var_link) { // the variable vid and chIdx should form a unique pair if( var->label_sfx_id==sfx_id && textCompare(var->label,var_label)==0 && var->chIdx == chIdx ) return var; } return nullptr; } rc_t _var_find_on_label_and_ch( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned chIdx, variable_t*& var_ref ) { rc_t rc = kOkRC; if((var_ref = _var_find_on_label_and_ch(proc,var_label,sfx_id,chIdx)) == nullptr ) rc = cwLogError(kEleNotFoundRC,"The variable '%s:%i' cannot be found on the proc:%s.",cwStringNullGuard(var_label),sfx_id,cwStringNullGuard(proc->label)); return rc; } rc_t _validate_var_assignment( variable_t* var, unsigned typeFl ) { if( cwIsFlag(var->varDesc->flags, kSrcVarDescFl ) ) return cwLogError(kInvalidStateRC, "The variable '%s:%i' on proc '%s:%i' cannot be set because it is a 'src' variable.", var->label, var->label_sfx_id, var->proc->label,var->proc->label_sfx_id); /* if( !cwIsFlag(var->varDesc->type, typeFl ) ) return cwLogError(kTypeMismatchRC, "The variable '%s:%i' on proc '%s:%i' is not a '%s'.", var->label, var->label_sfx_id, var->proc->label, var->proc->label_sfx_id, _typeFlagToLabel( typeFl )); */ return kOkRC; } void _var_print_addr( const char* title, const variable_t* v ) { cwLogPrint("%s:%s:%i.%s:%i ",title,v->proc->label,v->proc->label_sfx_id,v->label,v->label_sfx_id); } void _var_print( const variable_t* var ) { const char* conn_label = is_connected_to_source(var) ? "extern" : " "; cwLogPrint(" %12s:%3i vid:%3i ch:%3i : %s : ", var->label, var->label_sfx_id, var->vid, var->chIdx, conn_label ); if( var->value == nullptr ) value_print( &var->local_value[0] ); else value_print( var->value ); if( var->src_var != nullptr ) cwLogPrint(" src:%s:%i.%s:%i",var->src_var->proc->label,var->src_var->proc->label_sfx_id,var->src_var->label,var->src_var->label_sfx_id); if( var->dst_head != nullptr ) { for(variable_t* v = var->dst_head; v!=nullptr; v=v->dst_link) cwLogPrint(" dst:%s:%i.%s:%i",v->proc->label,v->proc->label_sfx_id,v->label,v->label_sfx_id); } cwLogPrint("\n"); } rc_t _var_broadcast_new_value( variable_t* var ) { rc_t rc = kOkRC; // notify each connected var that the value has changed for(variable_t* con_var = var->dst_head; con_var!=nullptr; con_var=con_var->dst_link) { // the var->local_value[] slot used by the source variable may have changed - update the destination variable // so that it points to the correct value. con_var->value = var->value; cwLogMod("%s:%i %s:%i -> %s:%i %s:%i", var->proc->label,var->proc->label_sfx_id, var->label,var->label_sfx_id, con_var->proc->label,con_var->proc->label_sfx_id, con_var->label,con_var->label_sfx_id ); // Call the value() function on the connected variable if((rc = var_call_custom_value_func(con_var)) != kOkRC ) break; } return rc; } // 'argTypeFlag' is the type (tflag) of 'val'. template< typename T > rc_t _var_set_template( variable_t* var, unsigned argTypeFlag, T val ) { rc_t rc = kOkRC; // it is not legal to set the value of a variable that is connected to a 'source' variable. if( var->src_var != nullptr ) return cwLogError(kInvalidStateRC, "The variable '%s:%i %s:%i' cannot be set because it is connected to a source variable.", var->proc->label,var->proc->label_sfx_id, var->label, var->label_sfx_id); // var->type is the allowable type for this var's value. // It may be set to kInvalidTFl if the type has not yet been determined. unsigned value_type_flag = var->type; // Pick the slot in local_value[] that we will use to try out this new value. unsigned next_local_value_idx = (var->local_value_idx + 1) % kLocalValueN; // store the pointer to the current value of this variable value_t* original_value = var->value; unsigned original_value_idx = var->local_value_idx; // release the previous value in the next slot value_release(&var->local_value[next_local_value_idx]); // if the value type of this variable has not been established if( value_type_flag == kInvalidTFl ) { // if the var desc is a single type then use that .... if( math::isPowerOfTwo(var->varDesc->type) ) { value_type_flag = var->varDesc->type; } else // ... Otherwise select a type from the one of the possible flags given by the var desc { value_type_flag = var->varDesc->type & argTypeFlag; } // if the incoming type is not in the set of allowable types then it is an error if( value_type_flag == 0 ) { rc = cwLogError(kTypeMismatchRC,"The type 0x%x is not valid for the variable: %s:%i %s:%i type:0x%x.", argTypeFlag,var->proc->label,var->proc->label_sfx_id,var->label,var->label_sfx_id,var->varDesc->type); goto errLabel; } } // set the type of the LHS to force the incoming value to be coerced to this type var->local_value[ next_local_value_idx ].tflag = value_type_flag; // set the new local value in var->local_value[next_local_value_idx] if((rc = value_set(var->local_value + next_local_value_idx, val )) != kOkRC ) { rc = cwLogError(rc,"Value set failed on '%s:%i %s:%i",var->proc->label,var->proc->label_sfx_id,var->label,var->label_sfx_id); goto errLabel; } // make the new local value current var->value = var->local_value + next_local_value_idx; var->local_value_idx = next_local_value_idx; // If the proc is fully initialized ... if( var->proc->varMapA != nullptr ) { // ... then inform the proc. that the value changed // Note 1: We don't want to this call to occur if we are inside or prior to 'proc.create()' // call because calls' to 'proc.value()' will see the proc in a incomplete state) // Note 2: If this call returns an error then the value assignment is cancelled // and the value does not change. rc = var_call_custom_value_func( var ); } //printf("%p set: %s:%s 0x%x\n",var->value, var->proc->label,var->label,var->value->tflag); if( rc == kOkRC ) { // send the value to connected downstream proc's rc = _var_broadcast_new_value( var ); } else { // cancel the assignment and restore the original value var->value = original_value; var->local_value_idx = original_value_idx; } errLabel: return rc; } // 'valueTypeFlag' is the type (tflag) of 'value' template< typename T > rc_t _var_set_driver( variable_t* var, unsigned valueTypeFlag, T value ) { rc_t rc; // if this variable is fed from the output of an external proc - then it's local value cannot be set if(is_connected_to_source(var) ) { return cwLogError(kInvalidStateRC,"Cannot set the value on the connected variable %s:%i-%s:%i.",var->proc->label,var->proc->label_sfx_id,var->label,var->label_sfx_id); } // if this assignment targets a specific channel ... if( var->chIdx != kAnyChIdx ) { rc = _var_set_template( var, valueTypeFlag, value ); // ... then set it alone } else // ... otherwise set all channels. { for(; var!=nullptr; var=var->ch_link) if((rc = _var_set_template( var, valueTypeFlag, value )) != kOkRC) break; } if(rc != kOkRC ) rc = cwLogError(rc,"Variable value set failed on '%s:%i %s:%i",cwStringNullGuard(var->proc->label),var->proc->label_sfx_id,cwStringNullGuard(var->label),var->label_sfx_id); return rc; } rc_t _var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, abuf_t* abuf ) { rc_t rc; variable_t* var = nullptr; if((rc = var_register_and_set( proc, var_label, sfx_id, vid, chIdx, var)) != kOkRC ) return rc; if( var != nullptr ) _var_set_driver( var, kABufTFl, abuf ); return rc; } rc_t _var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, mbuf_t* mbuf ) { rc_t rc; variable_t* var = nullptr; if((rc = var_register_and_set( proc, var_label, sfx_id, vid, chIdx, var)) != kOkRC ) return rc; if( var != nullptr ) _var_set_driver( var, kMBufTFl, mbuf ); return rc; } rc_t _var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, rbuf_t* rbuf ) { rc_t rc; variable_t* var = nullptr; if((rc = var_register_and_set( proc, var_label, sfx_id, vid, chIdx, var)) != kOkRC ) return rc; if( var != nullptr ) _var_set_driver( var, kRBufTFl, rbuf ); return rc; } rc_t _var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, fbuf_t* fbuf ) { rc_t rc; variable_t* var = nullptr; if((rc = var_register_and_set( proc, var_label, sfx_id, vid, chIdx, var)) != kOkRC ) return rc; if( var != nullptr ) _var_set_driver( var, kFBufTFl, fbuf ); return rc; } rc_t _var_map_id_to_index( proc_t* proc, unsigned vid, unsigned chIdx, unsigned& idxRef ) { unsigned idx = vid * proc->varMapChN + (chIdx == kAnyChIdx ? 0 : (chIdx+1)); // verify that the map idx is valid if( idx >= proc->varMapN ) return cwLogError(kAssertFailRC,"The variable map positioning location %i is out of the range %i on proc '%s:%i' vid:%i ch:%i.", idx, proc->varMapN, proc->label,proc->label_sfx_id,vid,chIdx); idxRef = idx; return kOkRC; } rc_t _var_map_label_to_index( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned chIdx, unsigned& idxRef ) { rc_t rc = kOkRC; variable_t* var = nullptr; idxRef = kInvalidIdx; if((rc = var_find(proc, var_label, sfx_id, chIdx, var )) == kOkRC) rc = _var_map_id_to_index( proc, var->vid, chIdx, idxRef ); return rc; } rc_t _var_add_to_ch_list( proc_t* proc, variable_t* new_var ) { rc_t rc = kOkRC; variable_t* base_var = nullptr; variable_t* v0 = nullptr; variable_t* v1 = nullptr; if( new_var->chIdx == kAnyChIdx ) return kOkRC; if((base_var = _var_find_on_label_and_ch( proc, new_var->label, new_var->label_sfx_id, kAnyChIdx )) == nullptr ) { rc = cwLogError(kInvalidStateRC,"The base channel variable does not exist for '%s:%i.%s:%i'. This is an illegal state.", proc->label, proc->label_sfx_id, new_var->label, new_var->label_sfx_id ); goto errLabel; } // insert v0 in order by channel number for(v0=base_var,v1=base_var->ch_link; v1!=nullptr; v1=v1->ch_link) { if( v1->chIdx > new_var->chIdx ) break; v0 = v1; } // the new var channel index should never match the previous or next channel index assert( v0->chIdx != new_var->chIdx && (v1==nullptr || v1->chIdx != new_var->chIdx ) ); new_var->ch_link = v1; v0->ch_link = new_var; errLabel: return rc; } rc_t _var_set_type( variable_t* var, unsigned type_flag ) { rc_t rc = kOkRC; if( cwIsNotFlag(var->classVarDesc->type,kRuntimeTFl) ) { rc = cwLogError(kOpFailRC,"It is invalid to change the type of a static (non-runtime) type variable."); goto errLabel; } // Duplicate the varDesc with the 'type' field set to type_flag if( var->localVarDesc == nullptr ) { var->localVarDesc = mem::allocZ(); *(var->localVarDesc) = *(var->classVarDesc); var->localVarDesc->link = nullptr; } var->localVarDesc->type = type_flag; var->varDesc = var->localVarDesc; errLabel: return rc; } // Create a variable and set it's value from 'value_cfg'. // If 'value_cfg' is null then use the value from var->varDesc->val_cfg. rc_t _var_create( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned id, unsigned chIdx, const object_t* value_cfg, unsigned altTypeFl, variable_t*& varRef ) { rc_t rc = kOkRC; variable_t* var = nullptr; var_desc_t* vd = nullptr; varRef = nullptr; // if this var already exists - it can't be created again if((var = _var_find_on_label_and_ch(proc,var_label, sfx_id, chIdx)) != nullptr ) { rc = cwLogError(kInvalidStateRC,"The variable '%s:%i' ch:%i has already been created on the proc: '%s:%i'.",var_label,sfx_id,chIdx,proc->label,proc->label_sfx_id); goto errLabel; } // locate the var desc if((vd = var_desc_find( proc->class_desc, var_label)) == nullptr ) { rc = cwLogError(kInvalidIdRC,"Unable to locate the variable '%s:%i' in class '%s'.", var_label, sfx_id, proc->class_desc->label ); goto errLabel; } // create the var var = mem::allocZ(); var->varDesc = vd; var->classVarDesc = vd; var->proc = proc; var->label = mem::duplStr(var_label); var->label_sfx_id = sfx_id; var->vid = id; var->chIdx = chIdx; var->value = nullptr; var->type = kInvalidTFl; if( altTypeFl != kInvalidTFl ) _var_set_type(var,altTypeFl); // if no value was given then set the value to the value given in the class if( value_cfg == nullptr ) value_cfg = var->varDesc->val_cfg; // if value_cfg is valid set the variable value if( value_cfg != nullptr && cwIsNotFlag(vd->type,kRuntimeTFl)) if((rc = var_set_from_cfg( var, value_cfg )) != kOkRC ) goto errLabel; // Add the variable to the end of the chain if( proc->varL == nullptr ) proc->varL = var; else { variable_t* v = proc->varL; while( v->var_link != nullptr ) v=v->var_link; v->var_link = var; } // link the new var into the ch_link list if((rc = _var_add_to_ch_list(proc, var )) != kOkRC ) goto errLabel; errLabel: if( rc != kOkRC ) { var_destroy(var); cwLogError(kOpFailRC,"Variable creation failed on '%s:%i.%s:%i' ch:%i.", proc->label, proc->label_sfx_id, var_label, sfx_id, chIdx ); } else { varRef = var; cwLogMod("Created var: %s:%i.%s:%i ch:%i.", proc->label, proc->label_sfx_id, var_label, sfx_id, chIdx ); } return rc; } void _class_desc_print( const class_desc_t* cd ) { const var_desc_t* vd = cd->varDescL; cwLogPrint("%s\n",cwStringNullGuard(cd->label)); for(; vd!=nullptr; vd=vd->link) { const char* srcFlStr = vd->flags & kSrcVarDescFl ? "src" : " "; const char* srcOptFlStr = vd->flags & kSrcOptVarDescFl ? "srcOpt" : " "; const char* plyMltFlStr = vd->flags & kMultVarDescFl ? "mult" : " "; cwLogPrint(" %10s 0x%08x %s %s %s %s\n", cwStringNullGuard(vd->label), vd->type, srcFlStr, srcOptFlStr, plyMltFlStr, cwStringNullGuard(vd->docText) ); } } } // flow } // cw cw::flow::var_desc_t* cw::flow::var_desc_create( const char* label, const object_t* cfg ) { var_desc_t* vd = mem::allocZ(); vd->label = label; vd->cfg = cfg; return vd; } void cw::flow::var_desc_destroy( var_desc_t* var_desc ) { if( var_desc != nullptr ) { if( var_desc_has_recd_format(var_desc) ) recd_format_destroy(var_desc->fmt.recd_fmt); mem::release(var_desc->proxyProcLabel); mem::release(var_desc->proxyVarLabel); mem::release(var_desc); } } unsigned cw::flow::var_desc_attr_label_to_flag( const char* attr_label ) { return labelToId(_varDescAttrFlagsA,attr_label,kInvalidVarDescFl); } const char* cw::flow::var_desc_flag_to_attribute( unsigned flag ) { return idToLabel(_varDescAttrFlagsA,flag,kInvalidVarDescFl); } const cw::idLabelPair_t* cw::flow::var_desc_flag_array( unsigned& array_cnt_ref ) { array_cnt_ref = sizeof(_varDescAttrFlagsA)/sizeof(_varDescAttrFlagsA[0]); return _varDescAttrFlagsA; } void cw::flow::class_desc_destroy( class_desc_t* class_desc) { // release the var desc list var_desc_t* vd0 = class_desc->varDescL; var_desc_t* vd1 = nullptr; while( vd0 != nullptr ) { vd1 = vd0->link; var_desc_destroy(vd0); vd0 = vd1; } // release the preset list class_preset_t* pr0 = class_desc->presetL; class_preset_t* pr1 = nullptr; while( pr0 != nullptr ) { pr1 = pr0->link; mem::release(pr0); pr0 = pr1; } if( class_desc->ui != nullptr ) { mem::release(class_desc->ui->presetA); mem::release(class_desc->ui); } } cw::flow::class_desc_t* cw::flow::class_desc_find( flow_t* p, const char* label ) { for(unsigned i=0; iclassDescN; ++i) if( textIsEqual(p->classDescA[i].label,label)) return p->classDescA + i; for(unsigned i=0; iudpDescN; ++i) if( textIsEqual(p->udpDescA[i].label,label)) return p->udpDescA + i; return nullptr; } const cw::flow::var_desc_t* cw::flow::var_desc_find( const class_desc_t* cd, const char* label ) { const var_desc_t* vd = cd->varDescL; for(; vd != nullptr; vd=vd->link ) if( textCompare(vd->label,label) == 0 ) return vd; 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 ) { if((vdRef = var_desc_find(cd,label)) == nullptr ) return cwLogError(kInvalidArgRC,"The variable desc. named '%s' could not be found on the class '%s'.",label,cd->label); return kOkRC; } bool cw::flow::var_desc_has_recd_format( var_desc_t* vd ) { return vd!=nullptr && vd->type & kRBufTFl && vd->fmt_cfg != nullptr && vd->fmt.recd_fmt != nullptr; } const cw::flow::class_preset_t* cw::flow::class_preset_find( const class_desc_t* cd, const char* preset_label ) { const class_preset_t* pr; for(pr=cd->presetL; pr!=nullptr; pr=pr->link) if( textCompare(pr->label,preset_label) == 0 ) return pr; return nullptr; } void cw::flow::class_dict_print( flow_t* p ) { for(unsigned i=0; iclassDescN; ++i) _class_desc_print(p->classDescA+i); for(unsigned i=0; iudpDescN; ++i) _class_desc_print(p->udpDescA+i); } cw::flow::external_device_t* cw::flow::external_device_find( flow_t* p, const char* device_label, unsigned typeId, unsigned inOrOutFl, const char* midiPortLabel ) { for(unsigned i=0; ideviceN; ++i) if( (device_label==nullptr || cw::textIsEqual(p->deviceA[i].devLabel,device_label)) && p->deviceA[i].typeId==typeId && cwIsFlag(p->deviceA[i].flags,inOrOutFl) && (midiPortLabel==nullptr || cw::textIsEqual(p->deviceA[i].portLabel,midiPortLabel)) ) return p->deviceA + i; cwLogError(kInvalidArgRC,"The %s device named '%s' could not be found.", cwIsFlag(inOrOutFl,kInFl) ? "in" : "out", device_label ); return nullptr; } void cw::flow::network_print( const network_t& net ) { // for each proc in the network for(unsigned i=0; iinternal_net != nullptr ) { cwLogPrint("------- Begin Nested Network: %s -------\n",cwStringNullGuard(proc->label)); network_print(*(proc->internal_net)); cwLogPrint("------- End Nested Network: %s -------\n",cwStringNullGuard(proc->label)); } } if(net.presetN > 0 ) { cwLogPrint("Presets:\n"); for(unsigned i=0; ilabel); switch( net_preset->tid ) { case kPresetVListTId: { const preset_value_t* net_val = net_preset->u.vlist.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"); } } break; case kPresetDualTId: cwLogPrint(" %s %s %f",net_preset->u.dual.pri->label,net_preset->u.dual.sec->label,net_preset->u.dual.coeff); break; } } cwLogPrint("\n"); } } const cw::flow::network_preset_t* cw::flow::network_preset_from_label( const network_t& net, const char* preset_label ) { 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.procA[i]->label_sfx_id; multN += 1; } idN_ref = multN; errLabel: return rc; } unsigned cw::flow::network_poly_count( const network_t& net ) { unsigned n =1; for(const network_t* n0 = net.poly_link; n0!=nullptr; n0=n0->poly_link) ++n; return n; } void cw::flow::proc_destroy( proc_t* proc ) { if( proc == nullptr ) return; if( proc->class_desc->members != nullptr && proc->class_desc->members->destroy != nullptr && proc->userPtr != nullptr ) proc->class_desc->members->destroy( proc ); // destroy the proc instance variables variable_t* var0 = proc->varL; variable_t* var1 = nullptr; while( var0 != nullptr ) { var1 = var0->var_link; var_destroy(var0); var0 = var1; } proc->varL = nullptr; mem::release(proc->label); mem::release(proc->varMapA); mem::release(proc); } cw::rc_t cw::flow::proc_validate( proc_t* proc ) { rc_t rc = kOkRC; for(variable_t* var=proc->varL; var!=nullptr; var=var->var_link) { if( var->label == nullptr ) { rc = cwLogError(kInvalidStateRC,"A var with no label was encountered."); continue; } if( var->value == nullptr ) { rc = cwLogError(kInvalidStateRC,"The var '%s:%i' has no value.",var->label,var->label_sfx_id); continue; } // the assigned value must have exactly one type if(!math::isPowerOfTwo( var->value->tflag ) ) { rc = cwLogError(kInvalidStateRC,"The var '%s:%i' has the invalid type flag:0x%x",var->label,var->label_sfx_id,var->value->tflag); continue; } // if var is using a local value (not connected to a source variable) then the type of the value must be valid with the variable class if( !is_connected_to_source(var) && !(var->varDesc->type & var->value->tflag) ) { rc = cwLogError(kInvalidStateRC, "The value type flag '%s' (0x%x) of '%s:%i-%s:%i' is not found in the variable class type flags: '%s' (0x%x)", value_type_flag_to_label(var->value->tflag),var->value->tflag, var->proc->label,var->proc->label_sfx_id, var->label,var->label_sfx_id, value_type_flag_to_label(var->varDesc->type),var->varDesc->type); continue; } // By setting the var->type field all future assignments to this variable // must be coercible to this type. See _var_set_template() var->type = var->value->tflag; } return rc; } cw::flow::proc_t* cw::flow::proc_find( network_t& net, const char* proc_label, unsigned sfx_id ) { for(unsigned i=0; ilabel_sfx_id==sfx_id && textIsEqual(proc_label,net.procA[i]->label) ) return net.procA[i]; } if( net.poly_link != nullptr ) return proc_find(*net.poly_link, proc_label, sfx_id ); return nullptr; } cw::rc_t cw::flow::proc_find( network_t& net, const char* proc_label, unsigned sfx_id, proc_t*& procPtrRef ) { rc_t rc = kOkRC; if((procPtrRef = proc_find(net,proc_label,sfx_id)) != nullptr ) return rc; return cwLogError(kInvalidArgRC,"The proc '%s:%i' was not found.", proc_label, sfx_id ); } void* cw::flow::global_var( proc_t* proc, const char* var_label ) { global_var_t* gv; assert( proc->net != nullptr ); for(gv=proc->ctx->globalVarL; gv!=nullptr; gv=gv->link ) if( textIsEqual(proc->class_desc->label,gv->class_label) && textIsEqual(gv->var_label,var_label) ) return gv->blob; return nullptr; } cw::rc_t cw::flow::global_var_alloc( proc_t* proc, const char* var_label, const void* blob, unsigned blobByteN ) { rc_t rc = kOkRC; global_var_t* gv; void* v; unsigned allocWordN = 0; if((v = global_var(proc,var_label)) != nullptr ) { rc = cwLogError(kInvalidArgRC,"The global variable '%s:%s' already exists.",cwStringNullGuard(proc->class_desc->label),cwStringNullGuard(var_label)); goto errLabel; } gv = mem::allocZ(); allocWordN = std::max(blobByteN/sizeof(unsigned),1ul); gv->class_label = proc->class_desc->label; gv->var_label = mem::duplStr(var_label); gv->blob = mem::allocZ(allocWordN); gv->blobByteN = blobByteN; memcpy(gv->blob,blob,blobByteN); gv->link = proc->ctx->globalVarL; proc->ctx->globalVarL = gv; errLabel: return rc; } void cw::flow::proc_print( proc_t* proc ) { cwLogPrint("%s:%i\n", proc->label,proc->label_sfx_id); for(variable_t* var = proc->varL; var!=nullptr; var=var->var_link) if( var->chIdx == kAnyChIdx ) for(variable_t* v0 = var; v0!=nullptr; v0=v0->ch_link) _var_print(v0); if( proc->class_desc->members->report ) proc->class_desc->members->report( proc ); } unsigned cw::flow::proc_var_count( proc_t* proc ) { unsigned n = 0; for(variable_t* var=proc->varL; var!=nullptr; var=var->var_link) ++n; return n; } char* cw::flow::proc_expand_filename( const proc_t* proc, const char* fname ) { bool useProjDirFl = proc->ctx->proj_dir != nullptr && textLength(fname) > 1 && fname[0] == '$'; char* fn0 = nullptr; if( useProjDirFl ) fn0 = filesys::makeFn(proc->ctx->proj_dir,fname+1,nullptr,nullptr); char* fn1 = filesys::expandPath(useProjDirFl ? fn0 : fname); mem::release(fn0); return fn1; } cw::rc_t cw::flow::var_create( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned id, unsigned chIdx, const object_t* value_cfg, unsigned altTypeFl, variable_t*& varRef ) { rc_t rc = kOkRC; rc = _var_create( proc, var_label, sfx_id, id, chIdx, value_cfg, altTypeFl, varRef ); return rc; } void cw::flow::var_destroy( variable_t* var ) { if( var != nullptr ) { for(unsigned i=0; ilocal_value+i); if( var->localVarDesc != nullptr ) mem::release(var->localVarDesc); mem::release(var->label); mem::release(var); } } cw::rc_t cw::flow::var_channelize( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned chIdx, const object_t* value_cfg, unsigned vid, variable_t*& varRef ) { rc_t rc = kOkRC; variable_t* var = nullptr; variable_t* base_var = nullptr; varRef = nullptr; if((base_var = _var_find_on_label_and_ch( proc, var_label, sfx_id, kAnyChIdx)) == nullptr) { rc = cwLogError(kInvalidStateRC,"The base ('any') channel variable could not be located on '%s:%i.%s:%i'.",proc->label,proc->label_sfx_id,var_label,sfx_id); goto errLabel; } // locate the variable with the stated chIdx var = _var_find_on_label_and_ch( proc, var_label, sfx_id, chIdx ); // 'src' variables cannot be channelized /* if( cwIsFlag(base_var->varDesc->flags,kSrcVarFl) ) { rc = cwLogError(rc,"'src' variables cannot be channelized."); goto errLabel; } */ // if the requested var was not found then create a new variable with the requested channel index if( var == nullptr && chIdx != kAnyChIdx ) { // create the channelized var if((rc = _var_create( proc, var_label, sfx_id, vid, chIdx, value_cfg, kInvalidTFl, var )) != kOkRC ) goto errLabel; // if no value was set then set the value from the 'any' channel if( value_cfg == nullptr ) { // if the base-var is connected to a source ... if( is_connected_to_source(base_var) ) { // ... then connect the new var to a source also // Attempt to find a matching channel on the source variable_t* src_ch_var = base_var->src_var; variable_t* last_src_ch_var = base_var->src_var; unsigned src_ch_cnt = 0; bool anyChFl = false; bool zeroChFl = false; for(; src_ch_var!=nullptr; src_ch_var=src_ch_var->ch_link) { last_src_ch_var = src_ch_var; if( src_ch_var->chIdx == var->chIdx ) break; if( src_ch_var->chIdx == kAnyChIdx ) anyChFl = true; if( src_ch_var->chIdx == 0 ) zeroChFl = true; src_ch_cnt += 1; } // If there is more than one channel available, in addition to the kAnyCh, and the src and dst var's do not have matching ch indexes // then there is a possibility that this is an unexpected connection between different channels. // However if there only any-ch and/or ch=0 is available then this is simply a one channel to many channels which is common. if( src_ch_var == nullptr && (anyChFl==false || (src_ch_cnt>1 && zeroChFl==false)) && last_src_ch_var->chIdx != var->chIdx ) { cwLogWarning("A connection is being made where channel src and dst. channels don't match and more than one src channel is available. src:%s:%i-%s:%i ch:%i of %i dst:%s:%i-%s:%i ch:%i", last_src_ch_var->proc->label, last_src_ch_var->proc->label_sfx_id, last_src_ch_var->label, last_src_ch_var->label_sfx_id, last_src_ch_var->chIdx, src_ch_cnt, var->proc->label, var->proc->label_sfx_id, var->label, var->label_sfx_id, var->chIdx ); } // if no matching channel is found connect to the last valid source channel // (Connecting to the last valid source is better than connecting to base_var->src_var // because if a var has more than a base var it is unlikely to update the base_var.) var_connect( last_src_ch_var, var ); } else // the base-var is not connected, and no value was provided for the new var { // Set the value of the new variable to the value of the 'any' channel value_duplicate( var->local_value[ var->local_value_idx], base_var->local_value[ base_var->local_value_idx ] ); // If the 'any' channel value was set to point to it's local value then do same with this value if( base_var->local_value + base_var->local_value_idx == base_var->value ) var->value = var->local_value + var->local_value_idx; } } } else // the var was found - set the value { // a correctly channelized var was found - but we still may need to set the value if( value_cfg != nullptr ) { rc = var_set_from_cfg( var, value_cfg ); } else { cwLogWarning("An existing var (%s:%i.%s:%i ch:%i) was specified for channelizing but no value was provided.", cwStringNullGuard(proc->label), proc->label_sfx_id, cwStringNullGuard(var_label), sfx_id, chIdx ); } } assert( var != nullptr ); varRef = var; errLabel: if( rc != kOkRC ) rc = cwLogError(rc,"Channelize failed for variable '%s:%i' on proc '%s:%i' ch:%i.", var_label, sfx_id, proc->label, proc->label_sfx_id, chIdx ); return rc; } unsigned cw::flow::var_channel_count( proc_t* proc, const char* var_label, unsigned sfx_id ) { rc_t rc = kOkRC; unsigned chN = kInvalidCnt; variable_t* base_var = nullptr; if((rc = _var_find_on_label_and_ch( proc, var_label, sfx_id, kAnyChIdx, base_var)) != kOkRC || base_var==nullptr) { cwLogError(rc,"Var. channel count calc failed."); goto errLabel; } chN = 0; for(base_var=base_var->ch_link; base_var!=nullptr; base_var=base_var->ch_link) if( base_var->chIdx+1 > chN ) chN = base_var->chIdx + 1; errLabel: return chN; } cw::rc_t cw::flow::var_call_custom_value_func( variable_t* var ) { rc_t rc; if((rc = var->proc->class_desc->members->value( var->proc, var )) != kOkRC ) goto errLabel; if( var->flags & kLogVarFl ) { if( var->proc->ctx->printLogHdrFl ) { cwLogPrint("%s","exe cycle: process: id: variable: id vid ch : : : type:value : destination\n"); cwLogPrint("%s","---------- ----------- ----- --------------- -- --- ----- ------------: -------------\n"); //: 0 : a: 0: out: 0 vid: 2 ch: -1 : : : : var->proc->ctx->printLogHdrFl = false; } cwLogPrint("%8i ",var->proc->ctx->cycleIndex); cwLogPrint("%10s:%5i", var->proc->label,var->proc->label_sfx_id); if( var->chIdx == kAnyChIdx ) { _var_print(var); } else { printf("\n"); for(variable_t* ch_var = var; ch_var!=nullptr; ch_var=ch_var->ch_link) { _var_print(ch_var); } } } errLabel: return rc; } cw::rc_t cw::flow::var_flags( proc_t* proc, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned& flags_ref ) { rc_t rc = kOkRC; variable_t* var = nullptr; flags_ref = 0; if((rc = _var_find_on_label_and_ch(proc,var_label,sfx_id,chIdx,var)) != kOkRC ) goto errLabel; flags_ref = var->flags; errLabel: return rc; } cw::rc_t cw::flow::var_set_flags( proc_t* proc, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned flag ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = _var_find_on_label_and_ch(proc,var_label,sfx_id,chIdx,var)) != kOkRC ) goto errLabel; var->flags |= flag; errLabel: return rc; } cw::rc_t cw::flow::var_clr_flags( proc_t* proc, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned flag ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = _var_find_on_label_and_ch(proc,var_label,sfx_id,chIdx,var)) != kOkRC ) goto errLabel; var->flags = cwClrFlag(var->flags,flag); errLabel: return rc; } bool cw::flow::var_exists( proc_t* proc, const char* label, unsigned sfx_id, unsigned chIdx ) { return _var_find_on_label_and_ch(proc,label,sfx_id,chIdx) != nullptr; } bool cw::flow::var_has_value( proc_t* proc, const char* label, unsigned sfx_id, unsigned chIdx ) { variable_t* varPtr = nullptr; rc_t rc; if((rc = var_find( proc, label, sfx_id, chIdx, varPtr )) != kOkRC ) return false; return varPtr->value != nullptr; } bool cw::flow::var_is_a_source( proc_t* proc, const char* label, unsigned sfx_id, unsigned chIdx ) { rc_t rc; variable_t* varPtr = nullptr; if((rc = var_find( proc, label, sfx_id, chIdx, varPtr)) != kOkRC ) { cwLogError(kEleNotFoundRC,"The variable '%s:%i' was not found on proc:'%s:%i'. 'source' state query is invalid.",cwStringNullGuard(label),sfx_id,cwStringNullGuard(proc->label),proc->label_sfx_id); return false; } return is_a_source_var(varPtr); } bool cw::flow::var_is_a_source( proc_t* proc, unsigned vid, unsigned chIdx ) { rc_t rc; variable_t* varPtr = nullptr; if((rc = var_find( proc, vid, chIdx, varPtr)) != kOkRC ) { cwLogError(kEleNotFoundRC,"The variable with vid '%i' was not found on proc:'%s:%i'. 'source' state query is invalid.",vid,cwStringNullGuard(proc->label),proc->label_sfx_id); return false; } return is_a_source_var(varPtr); } cw::rc_t cw::flow::var_find( proc_t* proc, unsigned vid, unsigned chIdx, variable_t*& varRef ) { rc_t rc = kOkRC; unsigned idx = kInvalidIdx; variable_t* var = nullptr; varRef = nullptr; // if the varMapA[] has not yet been formed (we are inside the proc constructor) then do a slow lookup of the variable if( proc->varMapA == nullptr ) { if((rc = _var_find_on_vid_and_ch(proc,vid,chIdx,var)) != kOkRC ) goto errLabel; } else { // otherwise do a fast lookup using proc->varMapA[] if((rc = _var_map_id_to_index(proc, vid, chIdx, idx )) == kOkRC && (idx != kInvalidIdx )) var = proc->varMapA[idx]; else { rc = cwLogError(kInvalidIdRC,"The index of variable vid:%i chIdx:%i on proc '%s:%i' could not be calculated and the variable value could not be retrieved.", vid, chIdx, proc->label,proc->label_sfx_id); goto errLabel; } } // if we get here var must be non-null - (was the var registered?) assert( var != nullptr && rc == kOkRC ); varRef = var; errLabel: return rc; } cw::rc_t cw::flow::var_find( proc_t* proc, const char* label, unsigned sfx_id, unsigned chIdx, variable_t*& vRef ) { variable_t* var; vRef = nullptr; if((var = _var_find_on_label_and_ch(proc,label,sfx_id,chIdx)) != nullptr ) { vRef = var; return kOkRC; } return cwLogError(kInvalidIdRC,"The proc '%s:%i' does not have a variable named '%s:%i'.", proc->label, proc->label_sfx_id, label, sfx_id ); } cw::rc_t cw::flow::var_find( proc_t* proc, const char* label, unsigned sfx_id, unsigned chIdx, const variable_t*& vRef ) { variable_t* v = nullptr; rc_t rc = var_find(proc,label,sfx_id,chIdx,v); vRef = v; return rc; } cw::rc_t cw::flow::var_channel_count( proc_t* proc, const char* label, unsigned sfx_id, unsigned& chCntRef ) { rc_t rc = kOkRC; const variable_t* var= nullptr; if((rc = var_find(proc,label,sfx_id,kAnyChIdx,var)) != kOkRC ) return cwLogError(rc,"Channel count was not available because the variable '%s:%i.%s:%i' does not exist.",cwStringNullGuard(proc->label),proc->label_sfx_id,cwStringNullGuard(label),sfx_id); return var_channel_count(var,chCntRef); } cw::rc_t cw::flow::var_channel_count( const variable_t* var, unsigned& chCntRef ) { rc_t rc = kOkRC; const variable_t* v; chCntRef = 0; if((rc = var_find( var->proc, var->label, var->label_sfx_id, kAnyChIdx, v )) != kOkRC ) { rc = cwLogError(kInvalidStateRC,"The base channel variable proc could not be found for the variable '%s:%i.%s:%i'.",var->proc->label,var->proc->label_sfx_id,var->label,var->label_sfx_id); goto errLabel; } for(v = v->ch_link; v!=nullptr; v=v->ch_link) chCntRef += 1; errLabel: return rc; } cw::rc_t cw::flow::var_register( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef ) { rc_t rc = kOkRC; variable_t* var = nullptr; varRef = nullptr; // TODO: check for duplicate 'vid'-'chIdx' pairs on this proc // The concatenation of 'vid' and 'chIdx' should be unique // if an exact match to label/chIdx was found if((var = _var_find_on_label_and_ch(proc,var_label,sfx_id,chIdx)) != nullptr ) { // if a value was given - then update the value if( value_cfg != nullptr ) if((rc = var_set_from_cfg( var, value_cfg )) != kOkRC ) goto errLabel; } else // an exact match was not found - channelize the variable { // if the kAnyChIdx has not been created for this variable ... if((var = _var_find_on_label_and_ch(proc,var_label,sfx_id,kAnyChIdx)) == nullptr ) { variable_t* dum = nullptr; // ... then create it here if((rc = var_create( proc, var_label, sfx_id, kInvalidId, kAnyChIdx, nullptr, kInvalidTFl, dum )) != kOkRC ) { rc = cwLogError(rc,"An attempt to create the 'any-channel' for '%s:%i' failed.",cwStringNullGuard(var_label),sfx_id); goto errLabel; } // if the var being registered is on channel kAnyChIdx if( chIdx == kAnyChIdx ) var = dum; } // don't channelize kAnyChIdx because it must already exist if( chIdx != kAnyChIdx ) if((rc = var_channelize(proc,var_label,sfx_id,chIdx,value_cfg,vid,var)) != kOkRC ) goto errLabel; } assert( var != nullptr ); var->vid = vid; varRef = var; // The kAnyChIdx shares the 'vid' with channelized variables - this is by design (vids are unique across variables, but shared across channels) if((var = _var_find_on_label_and_ch(proc,var_label,sfx_id,kAnyChIdx)) == nullptr ) rc = cwLogError(kInvalidStateRC,"The variable '%s:%i' proc '%s:%i' has no base channel.", var_label, sfx_id, proc->label, proc->label_sfx_id, chIdx); else { var->vid = vid; // ... this guarantee's that the kAnyChIdx variable has a valid vid } errLabel: if( rc != kOkRC ) rc = cwLogError(rc,"Registration failed on variable '%s:%i' proc '%s:%i' ch: %i.", var_label, sfx_id, proc->label, proc->label_sfx_id, chIdx); return rc; } bool cw::flow::is_connected_to_source( const variable_t* var ) { // if this var does not have a 'src_ptr' then it can't be connected to an external proc if( var->src_var == nullptr || var->value == nullptr ) return false; // if this var is using a local value then it can't be connected to an external proc for(unsigned i=0; ivalue == var->local_value + i ) return false; return true; } bool cw::flow::is_a_source_var( const variable_t* var ) { return var->dst_head != nullptr; } bool cw::flow::var_has_recd_format( const variable_t* var ) { return var!=nullptr && var_desc_has_recd_format(var->varDesc); } void cw::flow::var_connect( variable_t* src_var, variable_t* in_var ) { assert( in_var->dst_link == nullptr ); // connect in_var into src_var's outgoing var chain if( src_var->dst_head == nullptr ) src_var->dst_head = in_var; else src_var->dst_tail->dst_link = in_var; src_var->dst_tail = in_var; in_var->value = src_var->value; in_var->src_var = src_var; } void cw::flow::var_disconnect( variable_t* in_var ) { if( in_var->src_var != nullptr ) { // remote the in_var from the src var's output list variable_t* v0 = nullptr; variable_t* v = in_var->src_var->dst_head; for(; v!=nullptr; v=v->dst_link) { if( v == in_var ) { if( v0 == nullptr ) in_var->src_var->dst_head = v->dst_link; else v0->dst_link = v->dst_link; break; } v0 = v; } // the in_var is always in the src-var's output list assert(v == in_var ); in_var->src_var = nullptr; } } unsigned cw::flow::var_mult_count( proc_t* proc, const char* var_label ) { unsigned n = 0; for(variable_t* var=proc->varL; var!=nullptr; var=var->var_link) if( textIsEqual(var->label,var_label) ) ++n; return n; } cw::rc_t cw::flow::var_mult_sfx_id_array( proc_t* proc, const char* var_label, unsigned* idA, unsigned idAllocN, unsigned& idN_ref ) { rc_t rc = kOkRC; idN_ref = 0; // for each variable whose 'label' is 'var_label' for(variable_t* var=proc->varL; var!=nullptr; var=var->var_link) if( textIsEqual(var->label,var_label) ) { // scan idA[] for a matching sfx_id unsigned i=0; for(; ilabel_sfx_id ) break; // if the sfx_id of this var has not yet been included in idA[] if( i == idN_ref ) { // ... and we still have space left in the output arrau if( idN_ref >= idAllocN ) { rc = cwLogError(kBufTooSmallRC,"The mult-sfx-id result array is too small for the var:'%s'.",cwStringNullGuard(var_label)); goto errLabel; } // store this sfx_id in idA[] idA[idN_ref++] = var->label_sfx_id; } } errLabel: if( rc != kOkRC ) idN_ref = 0; return rc; } cw::rc_t cw::flow::var_send_to_ui( variable_t* var ) { // var->ui_var_link is set to null when the var is removed from the list // 1. Atomically set _head to the new node and return 'old-head' variable_t* prev = var->proc->ctx->ui_var_head.exchange(var,std::memory_order_acq_rel); // Note that at this point only the new node may have the 'old-head' as it's predecssor. // Other threads may therefore safely interrupt at this point. // 2. Set the old-head next pointer to the new node (thereby adding the new node to the list) prev->ui_var_link.store(var,std::memory_order_release); // RELEASE 'next' to consumer return kOkRC; } cw::rc_t cw::flow::var_send_to_ui( proc_t* proc, unsigned vid, unsigned chIdx ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = var_send_to_ui(var); return rc; } cw::rc_t cw::flow::var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, variable_t*& varRef ) { return var_register( proc, var_label, sfx_id, vid, chIdx, nullptr, varRef ); } cw::rc_t cw::flow::var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned frameN ) { rc_t rc = kOkRC; abuf_t* abuf; if((abuf = abuf_create( srate, chN, frameN )) == nullptr ) return cwLogError(kOpFailRC,"abuf create failed on proc:'%s:%i' variable:'%s:%i'.", proc->label, proc->label_sfx_id, var_label,sfx_id); if((rc = _var_register_and_set( proc, var_label, sfx_id, vid, chIdx, abuf )) != kOkRC ) abuf_destroy(abuf); return rc; } cw::rc_t cw::flow::var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, const unsigned* maxBinN_V, const unsigned* binN_V, const unsigned* hopSmpN_V, const fd_sample_t** magV, const fd_sample_t** phsV, const fd_sample_t** hzV ) { rc_t rc = kOkRC; fbuf_t* fbuf; if((fbuf = fbuf_create( srate, chN, maxBinN_V, binN_V, hopSmpN_V, magV, phsV, hzV )) == nullptr ) return cwLogError(kOpFailRC,"fbuf create failed on proc:'%s:%i' variable:'%s:%i'.", proc->label, proc->label_sfx_id, var_label,sfx_id); if((rc = _var_register_and_set( proc, var_label, sfx_id, vid, chIdx, fbuf )) != kOkRC ) fbuf_destroy(fbuf); return rc; } cw::rc_t cw::flow::var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, midi::ch_msg_t* msgA, unsigned msgN ) { rc_t rc = kOkRC; mbuf_t* mbuf; if((mbuf = mbuf_create(msgA,msgN)) == nullptr ) return cwLogError(kOpFailRC,"mbuf create failed on proc:'%s:%i' variable:'%s:%i'.", proc->label, proc->label_sfx_id, var_label, sfx_id); if((rc = _var_register_and_set( proc, var_label, sfx_id, vid, chIdx, mbuf )) != kOkRC ) mbuf_destroy(mbuf); return rc; } cw::rc_t cw::flow::var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, const recd_type_t* recd_type, recd_t* recdA, unsigned recdN ) { rc_t rc = kOkRC; rbuf_t* rbuf; if((rbuf = rbuf_create(recd_type,recdA,recdN)) == nullptr ) return cwLogError(kOpFailRC,"rbuf create failed on proc:'%s:%i' variable:'%s:%i'.", proc->label, proc->label_sfx_id, var_label, sfx_id); if((rc = _var_register_and_set( proc, var_label, sfx_id, vid, chIdx, rbuf )) != kOkRC ) rbuf_destroy(rbuf); return rc; } cw::rc_t cw::flow::var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, srate_t srate, unsigned chN, unsigned maxBinN, unsigned binN, unsigned hopSmpN, const fd_sample_t** magV, const fd_sample_t** phsV, const fd_sample_t** hzV ) { unsigned maxBinN_V[ chN ]; unsigned binN_V[ chN ]; unsigned hopSmpN_V[ chN ]; vop::fill(maxBinN_V,chN,maxBinN); vop::fill(binN_V,chN,binN); vop::fill(hopSmpN_V,chN, hopSmpN ); return var_register_and_set(proc,var_label,sfx_id,vid,chIdx,srate, chN, maxBinN_V, binN_V, hopSmpN_V, magV, phsV, hzV); } cw::rc_t cw::flow::var_get( const variable_t* var, bool& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( const variable_t* var, uint_t& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( const variable_t* var, int_t& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( const variable_t* var, float& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( const variable_t* var, double& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( const variable_t* var, const char*& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( const variable_t* var, const abuf_t*& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( variable_t* var, abuf_t*& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( const variable_t* var, const fbuf_t*& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( variable_t* var, fbuf_t*& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( const variable_t* var, const mbuf_t*& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( variable_t* var, mbuf_t*& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( const variable_t* var, const rbuf_t*& valRef ) { return _val_get_driver(var,valRef); } cw::rc_t cw::flow::var_get( variable_t* var, rbuf_t*& valRef ) { return _val_get_driver(var,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::var_set_from_cfg( variable_t* var, const object_t* cfg_value ) { rc_t rc = kOkRC; value_t v; if((rc = value_from_cfg(cfg_value, v)) != kOkRC ) goto errLabel; if((rc = var_set(var,&v)) != kOkRC ) goto errLabel; errLabel: if( rc != kOkRC ) rc = cwLogError(kSyntaxErrorRC,"The %s:%i.%s:%i could not extract a type:%s from a configuration value.",var->proc->label,var->proc->label_sfx_id,var->label,var->label_sfx_id,value_type_flag_to_label(var->varDesc->type & kTypeMask)); return rc; } cw::rc_t cw::flow::var_set( variable_t* var, const value_t* val ) { rc_t rc = kOkRC; switch( val->tflag ) { case kBoolTFl: rc = _var_set_driver(var,val->tflag,val->u.b); break; case kUIntTFl: rc = _var_set_driver(var,val->tflag,val->u.u); break; case kIntTFl: rc = _var_set_driver(var,val->tflag,val->u.i); break; case kFloatTFl: rc = _var_set_driver(var,val->tflag,val->u.f); break; case kDoubleTFl: rc = _var_set_driver(var,val->tflag,val->u.d); break; case kStringTFl: rc = _var_set_driver(var,val->tflag,val->u.s); break; case kCfgTFl: rc = _var_set_driver(var,val->tflag,val->u.cfg); break; case kABufTFl: rc = _var_set_driver(var,val->tflag,val->u.abuf); break; case kFBufTFl: rc = _var_set_driver(var,val->tflag,val->u.fbuf); break; case kMBufTFl: rc = _var_set_driver(var,val->tflag,val->u.mbuf); break; case kRBufTFl: rc = _var_set_driver(var,val->tflag,val->u.rbuf); break; default: rc = cwLogError(kNotImplementedRC,"The var_set() from value_t has not been implemented for the type 0x%x.",val->tflag); } return rc; } cw::rc_t cw::flow::var_set( variable_t* var, bool val ) { return _var_set_driver(var,kBoolTFl,val); } cw::rc_t cw::flow::var_set( variable_t* var, uint_t val ) { return _var_set_driver(var,kUIntTFl,val); } cw::rc_t cw::flow::var_set( variable_t* var, int_t val ) { return _var_set_driver(var,kIntTFl,val); } cw::rc_t cw::flow::var_set( variable_t* var, float val ) { return _var_set_driver(var,kFloatTFl,val); } cw::rc_t cw::flow::var_set( variable_t* var, double val ) { return _var_set_driver(var,kDoubleTFl,val); } cw::rc_t cw::flow::var_set( variable_t* var, const char* val ) { return _var_set_driver(var,kStringTFl,val); } cw::rc_t cw::flow::var_set( variable_t* var, abuf_t* val ) { return _var_set_driver(var,kABufTFl,val); } cw::rc_t cw::flow::var_set( variable_t* var, fbuf_t* val ) { return _var_set_driver(var,kFBufTFl,val); } cw::rc_t cw::flow::var_set( variable_t* var, mbuf_t* val ) { return _var_set_driver(var,kMBufTFl,val); } cw::rc_t cw::flow::var_set( variable_t* var, rbuf_t* val ) { return _var_set_driver(var,kRBufTFl,val); } cw::rc_t cw::flow::var_set( variable_t* var, const object_t* val ) { return _var_set_driver(var,kCfgTFl,val); } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, const value_t* val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = var_set(var,val); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, bool val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver( var, kBoolTFl, val ); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, uint_t val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver( var, kUIntTFl, val ); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, int_t val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver( var, kIntTFl, val ); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, float val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver( var, kFloatTFl, val ); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, double val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver( var, kDoubleTFl, val ); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, const char* val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver( var, kStringTFl, val ); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, abuf_t* val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver(var,kABufTFl,val); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, fbuf_t* val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver(var,kFBufTFl,val); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, mbuf_t* val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver(var,kMBufTFl,val); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, rbuf_t* val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver(var,kRBufTFl,val); return rc; } cw::rc_t cw::flow::var_set( proc_t* proc, unsigned vid, unsigned chIdx, const object_t* val ) { rc_t rc = kOkRC; variable_t* var = nullptr; if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) rc = _var_set_driver( var, kCfgTFl, val ); return rc; }