From b57693f4e4f71813d5701367f13096214a1d5d72 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 30 Apr 2024 19:58:10 -0400 Subject: [PATCH] cwFlow,cwFlowNet,cwFlowTypes,cwFlowProc : Many changes. Added ability to set types at proc instantiation time. Added ability to have multi-type variables which get resolved at proc. instantiation time. Added ability to proc 'log' attribute to print selected variables as they change. Values are now coerced to the variable type in var_set(). Added new proc's : list,add,preset. --- cwFlow.cpp | 9 +- cwFlowNet.cpp | 138 +++++-- cwFlowProc.cpp | 859 ++++++++++++++++++++++++++++++++++------- cwFlowProc.h | 7 +- cwFlowTypes.cpp | 965 +++++++++++++++++++++++++++++++++++++---------- cwFlowTypes.h | 143 ++++--- flow/flow_doc.md | 38 +- 7 files changed, 1745 insertions(+), 414 deletions(-) diff --git a/cwFlow.cpp b/cwFlow.cpp index cdea341..078ff79 100644 --- a/cwFlow.cpp +++ b/cwFlow.cpp @@ -34,8 +34,8 @@ namespace cw { "midi_out", &midi_out::members }, { "audio_in", &audio_in::members }, { "audio_out", &audio_out::members }, - { "audioFileIn", &audioFileIn::members }, - { "audioFileOut", &audioFileOut::members }, + { "audio_file_in", &audio_file_in::members }, + { "audio_file_out", &audio_file_out::members }, { "audio_gain", &audio_gain::members }, { "audio_split", &audio_split::members }, { "audio_duplicate", &audio_duplicate::members }, @@ -58,6 +58,9 @@ namespace cw { "number", &number::members }, { "timer", &timer::members }, { "counter", &counter::members }, + { "list", &list::members }, + { "add", &add::members }, + { "preset", &preset::members }, { nullptr, nullptr } }; @@ -621,7 +624,7 @@ cw::rc_t cw::flow::test( const object_t* cfg, int argc, const char* argv[] ) // find the user requested test case if((test_cfg = test_cases_cfg->find_child(argv[1])) == nullptr ) { - rc = cwLogError(kInvalidArgRC,"The test case named '%s' was not found.",argv[0]); + rc = cwLogError(kInvalidArgRC,"The test case named '%s' was not found.",argv[1]); goto errLabel; } diff --git a/cwFlowNet.cpp b/cwFlowNet.cpp index 1a4c5e2..01f2cd8 100644 --- a/cwFlowNet.cpp +++ b/cwFlowNet.cpp @@ -66,8 +66,10 @@ namespace cw void _connect_vars( variable_t* src_var, variable_t* in_var ) { // connect in_var into src_var's outgoing var chain - in_var->connect_link = src_var->connect_link; - src_var->connect_link = in_var; + in_var->dst_link = src_var->dst_tail; + src_var->dst_tail = in_var; + if( src_var->dst_head == nullptr ) + src_var->dst_head = in_var; assert( src_var->value != nullptr ); @@ -171,7 +173,42 @@ namespace cw } } } - + + rc_t _set_log_flags(instance_t* proc, const object_t* log_labels) + { + rc_t rc = kOkRC; + + if( log_labels == nullptr ) + return rc; + + if( !log_labels->is_dict() ) + { + rc = cwLogError(kSyntaxErrorRC,"The log spec on '%s:%i' is not a dictionary.",cwStringNullGuard(proc->label),proc->label_sfx_id); + goto errLabel; + } + + for(unsigned i=0; ichild_count(); ++i) + { + const object_t* pair; + unsigned sfx_id; + + if((pair = log_labels->child_ele(i)) == nullptr || pair->pair_label()==nullptr || pair->pair_value()==nullptr || (rc=pair->pair_value()->value(sfx_id))!=kOkRC ) + { + rc = cwLogError(kSyntaxErrorRC,"Syntax error on log var identifier."); + goto errLabel; + } + + if((rc = var_set_flags( proc, kAnyChIdx, pair->pair_label(), sfx_id, kLogVarFl )) != kOkRC ) + { + rc = cwLogError(rc,"Unable to set var flags on '%s:%i' var:'%s:%i'.",cwStringNullGuard(proc->label),proc->label_sfx_id,pair->pair_label(),sfx_id); + goto errLabel; + } + } + + errLabel: + return rc; + } + rc_t _call_value_func_on_all_variables( instance_t* inst ) { rc_t rc = kOkRC; @@ -181,40 +218,49 @@ namespace cw if( inst->varMapA[i] != nullptr && inst->varMapA[i]->vid != kInvalidId ) { variable_t* var = inst->varMapA[i]; - - if((rc = var->inst->class_desc->members->value( var->inst, var )) != kOkRC ) + + if((rc = var_call_custom_value_func( var )) != kOkRC ) rc1 = cwLogError(rc,"The proc instance '%s:%i' reported an invalid valid on variable:%s chIdx:%i.", var->inst->label, var->inst->label_sfx_id, var->label, var->chIdx ); } return rc1; } - rc_t _var_channelize( instance_t* inst, const char* preset_label, const char* type_src_label, const char* value_label, const object_t* value ) + rc_t _var_channelize( instance_t* inst, const char* preset_label, const char* type_src_label, const char* var_label, const object_t* value ) { rc_t rc = kOkRC; - variable_t* dummy = nullptr; + variable_t* dummy = nullptr; + var_desc_t* vd = nullptr; // verify that a valid value exists if( value == nullptr ) { - rc = cwLogError(kSyntaxErrorRC,"Unexpected missig value on %s preset '%s' instance '%s' variable '%s'.", type_src_label, preset_label, inst->label, cwStringNullGuard(value_label) ); + rc = cwLogError(kSyntaxErrorRC,"Unexpected missig value on %s preset '%s' instance '%s' variable '%s'.", type_src_label, preset_label, inst->label, cwStringNullGuard(var_label) ); goto errLabel; } - - // if a list of values was given - if( value->is_list() ) + else { - for(unsigned chIdx=0; chIdxchild_count(); ++chIdx) - if((rc = var_channelize( inst, value_label, kBaseSfxId, chIdx, value->child_ele(chIdx), kInvalidId, dummy )) != kOkRC ) - goto errLabel; - } - else // otherwise a single value was given - { - if((rc = var_channelize( inst, value_label, kBaseSfxId, kAnyChIdx, value, kInvalidId, dummy )) != kOkRC ) - goto errLabel; - } + bool is_var_cfg_type_fl = (vd = var_desc_find( inst->class_desc, var_label ))!=nullptr && cwIsFlag(vd->type,kCfgTFl); + bool is_list_fl = value->is_list(); + bool is_list_of_list_fl = is_list_fl && value->child_count() > 0 && value->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); + // if a list of values was given and the var type is not a 'cfg' type or if a list of lists was given + if( parse_list_fl ) + { + // then each value in the list is assigned to the associated channel + for(unsigned chIdx=0; chIdxchild_count(); ++chIdx) + if((rc = var_channelize( inst, var_label, kBaseSfxId, chIdx, value->child_ele(chIdx), kInvalidId, dummy )) != kOkRC ) + goto errLabel; + } + else // otherwise a single value was given + { + if((rc = var_channelize( inst, var_label, kBaseSfxId, kAnyChIdx, value, kInvalidId, dummy )) != kOkRC ) + goto errLabel; + } + } + errLabel: return rc; } @@ -236,12 +282,12 @@ namespace cw // for each preset variable for(unsigned i=0; ichild_count(); ++i) { - const object_t* value = preset_cfg->child_ele(i)->pair_value(); - const char* value_label = preset_cfg->child_ele(i)->pair_label(); + const object_t* value = preset_cfg->child_ele(i)->pair_value(); + const char* var_label = preset_cfg->child_ele(i)->pair_label(); //cwLogInfo("variable:%s",value_label); - if((rc = _var_channelize( inst, preset_label, type_src_label, value_label, value )) != kOkRC ) + if((rc = _var_channelize( inst, preset_label, type_src_label, var_label, value )) != kOkRC ) goto errLabel; @@ -707,6 +753,7 @@ namespace cw const char* arg_label; // const object_t* preset_labels; // const object_t* arg_cfg; // + const object_t* log_labels; // const object_t* in_dict; // cfg. node to the in-list in_stmt_t* in_array; // in_array[ in_arrayN ] in-stmt array unsigned in_arrayN; // count of in-stmt's in the in-list. @@ -1253,9 +1300,16 @@ namespace cw { in_stmt_t& in_stmt = pstate.in_array[i]; const object_t* in_pair = pstate.in_dict->child_ele(i); // in:src pair - const char* in_var_str = in_pair->pair_label(); // 'in' var string + const char* in_var_str = nullptr; const char* src_proc_var_str = nullptr; + // validate the basic syntax + if( in_pair == nullptr || (in_var_str = in_pair->pair_label()) == nullptr || in_pair->pair_value()==nullptr ) + { + cwLogError(rc,"Malformed dictionary encountered in 'in' statement."); + goto errLabel; + } + // get the src net/proc/var string if((rc = in_pair->pair_value()->value(src_proc_var_str)) != kOkRC ) { @@ -1282,6 +1336,7 @@ namespace cw kInvalidId, kAnyChIdx, in_stmt.in_var_desc->val_cfg, + kInvalidTFl, dum )) != kOkRC ) { rc = cwLogError(rc,"in-stmt var create failed on '%s:%s'.",cwStringNullGuard(in_var_str),cwStringNullGuard(src_proc_var_str)); @@ -1432,9 +1487,10 @@ namespace cw // parse the optional args if((rc = proc_inst_cfg->pair_value()->getv_opt("args", arg_dict, - "in", pstate.in_dict, - "argLabel", pstate.arg_label, - "preset", pstate.preset_labels)) != kOkRC ) + "in", pstate.in_dict, + "argLabel", pstate.arg_label, + "preset", pstate.preset_labels, + "log", pstate.log_labels )) != kOkRC ) { rc = cwLogError(kSyntaxErrorRC,"The instance cfg. '%s' missing: 'type'.",pstate.inst_label); goto errLabel; @@ -1550,16 +1606,16 @@ namespace cw // Instantiate all the variables in the class description - that were not already created in _parse_in_list() for(var_desc_t* vd=class_desc->varDescL; vd!=nullptr; vd=vd->link) - if( !_is_var_inst_already_created( vd->label, pstate ) ) + if( !_is_var_inst_already_created( vd->label, pstate ) && cwIsNotFlag(vd->type,kRuntimeTFl) ) { variable_t* var = nullptr; - if((rc = var_create( inst, vd->label, kBaseSfxId, kInvalidId, kAnyChIdx, vd->val_cfg, var )) != kOkRC ) + if((rc = var_create( inst, vd->label, kBaseSfxId, kInvalidId, kAnyChIdx, vd->val_cfg, kInvalidTFl, var )) != kOkRC ) goto errLabel; } // All the variables that can be used by this instance have now been created // 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 if( pstate.preset_labels != nullptr ) if((rc = _class_apply_presets(inst, pstate.preset_labels )) != kOkRC ) @@ -1584,36 +1640,52 @@ namespace cw // Connect the in-list variables to their sources. if((rc = _connect_in_vars(net, inst, pstate)) != kOkRC ) { - rc = cwLogError(rc,"Creation of the proc instance '%s:%i' failed during input connection processing.",cwStringNullGuard(inst->label),inst->label_sfx_id); + rc = cwLogError(rc,"Input connection processing failed."); goto errLabel; } - + // Complete the instantiation of the proc instance by calling the custom instance creation function. // Call the custom instance create() function. if((rc = class_desc->members->create( inst )) != kOkRC ) { - rc = cwLogError(kInvalidArgRC,"Instantiation failed on instance '%s:%i'.", inst->label,inst->label_sfx_id ); + rc = cwLogError(kInvalidArgRC,"Custom instantiation failed." ); goto errLabel; } // Create the instance->varMap[] lookup array if((rc =_create_instance_var_map( inst )) != kOkRC ) + { + rc = cwLogError(rc,"Variable map creation failed."); goto errLabel; + } // the custom creation function may have added channels to in-list vars fix up those connections here. _complete_input_connections(inst); + // set the log flags again so that vars created by the instance can be included in the log output + if((rc = _set_log_flags(inst,pstate.log_labels)) != kOkRC ) + goto errLabel; + // call the 'value()' function to inform the instance of the current value of all of it's variables. if((rc = _call_value_func_on_all_variables( inst )) != kOkRC ) goto errLabel; + if((rc = instance_validate(inst)) != kOkRC ) + { + rc = cwLogError(rc,"Proc instance validation failed."); + goto errLabel; + } inst_ref = inst; errLabel: if( rc != kOkRC ) + { + rc = cwLogError(rc,"Proc instantiation failed on '%s:%i'.",cwStringNullGuard(pstate.inst_label),sfx_id); _destroy_inst(inst); + } + _destroy_pstate(pstate); return rc; diff --git a/cwFlowProc.cpp b/cwFlowProc.cpp index a0695b0..e9f640a 100644 --- a/cwFlowProc.cpp +++ b/cwFlowProc.cpp @@ -724,10 +724,10 @@ namespace cw //------------------------------------------------------------------------------------------------------------------ // - // AudioFileIn + // audio_file_in // - namespace audioFileIn + namespace audio_file_in { enum { @@ -881,10 +881,10 @@ namespace cw //------------------------------------------------------------------------------------------------------------------ // - // AudioFileOut + // audio_file_out // - namespace audioFileOut + namespace audio_file_out { enum { @@ -1753,6 +1753,7 @@ namespace cw inst_t* inst = (inst_t*)ctx->userPtr; + mem::release(inst->phaseA); mem::release(inst); return rc; @@ -3346,7 +3347,7 @@ namespace cw bool trigFl = false; variable_t* gainVar = nullptr; abuf_t* srateSrc = nullptr; - double dum; + double dum_dbl; inst_t* p = mem::allocZ(); @@ -3360,7 +3361,7 @@ namespace cw kSrateRefPId, "srateSrc", kBaseSfxId, srateSrc, kDurMsPId, "durMs", kBaseSfxId, p->xfadeDurMs, kTriggerPId, "trigger", kBaseSfxId, trigFl, - kGainPId, "gain", kBaseSfxId, dum)) != kOkRC ) + kGainPId, "gain", kBaseSfxId, dum_dbl)) != kOkRC ) { goto errLabel; } @@ -3383,7 +3384,7 @@ namespace cw for(unsigned i=1; inet_proc->internal_net->poly_cnt; ++i) { variable_t* dum; - if((rc = var_create(ctx, "gain", i, kGainPId+i, kAnyChIdx, nullptr, dum )) != kOkRC ) + if((rc = var_create(ctx, "gain", i, kGainPId+i, kAnyChIdx, nullptr, kInvalidTFl, dum )) != kOkRC ) { cwLogError(rc,"'gain:%i' create failed.",i); goto errLabel; @@ -3790,44 +3791,21 @@ namespace cw namespace number { enum { - kInPId, - kBoolPId, - kUIntPId, - kIntPId, - kFloatPId, - kOutPId + kValuePId, }; - typedef struct - { - bool delta_fl; - double value; - } inst_t; rc_t create( instance_t* proc ) { - rc_t rc = kOkRC; - inst_t* p = mem::allocZ(); - proc->userPtr = p; + rc_t rc = kOkRC; + double value = 0; if((rc = var_register_and_get(proc,kAnyChIdx, - kInPId,"in",kBaseSfxId,p->value)) != kOkRC ) + kValuePId,"value",kBaseSfxId,value)) != kOkRC ) { goto errLabel; } - - if((rc = var_register_and_set(proc,kAnyChIdx, - kBoolPId,"bool",kBaseSfxId,p->value != 0, - kUIntPId,"uint",kBaseSfxId,(unsigned)p->value, - kIntPId,"int",kBaseSfxId,(int)p->value, - kFloatPId,"float",kBaseSfxId,(float)p->value, - kOutPId,"out",kBaseSfxId,p->value )) != kOkRC ) - { - goto errLabel; - } - - p->delta_fl = true; errLabel: return rc; @@ -3836,45 +3814,18 @@ namespace cw rc_t destroy( instance_t* proc ) { rc_t rc = kOkRC; - - inst_t* p = (inst_t*)proc->userPtr; - mem::release(p); return rc; } rc_t value( instance_t* proc, variable_t* var ) { rc_t rc = kOkRC; - if( var->vid == kInPId ) - { - double v; - if((rc = var_get(var,v)) == kOkRC ) - { - inst_t* p = (inst_t*)proc->userPtr; - if( !p->delta_fl ) - p->delta_fl = v != p->value; - p->value = v; - - } - } return rc; } rc_t exec( instance_t* proc ) { rc_t rc = kOkRC; - inst_t* p = (inst_t*)proc->userPtr; - - if( p->delta_fl ) - { - p->delta_fl = false; - var_set(proc,kBoolPId,kAnyChIdx,p->value!=0); - var_set(proc,kUIntPId,kAnyChIdx,(unsigned)fabs(p->value)); - var_set(proc,kIntPId,kAnyChIdx,(int)p->value); - var_set(proc,kFloatPId,kAnyChIdx,(float)p->value); - var_set(proc,kOutPId,kAnyChIdx,p->value); - } - return rc; } @@ -3978,6 +3929,7 @@ namespace cw p->periodPhase += proc->ctx->framesPerCycle; + //printf("%i %i\n",p->periodPhase,p->periodFrmN); if( p->periodPhase >= p->periodFrmN ) { @@ -4020,6 +3972,7 @@ namespace cw kIncPId, kRepeatPId, kModePId, + kOutTypePId, kOutPId }; @@ -4075,12 +4028,16 @@ namespace cw proc->userPtr = p; double init_val; const char* mode_label; + variable_t* dum = nullptr; + const char* out_type_label; + unsigned out_type_fl; if((rc = var_register_and_get(proc, kAnyChIdx, kTriggerPId, "trigger", kBaseSfxId, p->trig_val, kResetPId, "reset", kBaseSfxId, p->reset_val, kInitPId, "init", kBaseSfxId, init_val, - kModePId, "mode", kBaseSfxId, mode_label)) != kOkRC ) + kModePId, "mode", kBaseSfxId, mode_label, + kOutTypePId, "out_type",kBaseSfxId, out_type_label)) != kOkRC ) { goto errLabel; } @@ -4095,12 +4052,25 @@ namespace cw goto errLabel; } - if((rc = var_register_and_set(proc,kAnyChIdx, - kOutPId,"out",kBaseSfxId,init_val)) != kOkRC ) + // get the type of the output + if(out_type_label==nullptr || (out_type_fl = value_type_label_to_flag( out_type_label )) == kInvalidTFl ) + { + rc = cwLogError(kInvalidArgRC,"The output type '%s' is not a valid type.",cwStringNullGuard(out_type_label)); + goto errLabel; + } + + + if((rc = var_create( proc, "out", kBaseSfxId, kOutPId, kAnyChIdx, nullptr, out_type_fl, dum )) != kOkRC ) { goto errLabel; } - + + if((rc = var_set( proc, kOutPId, kAnyChIdx, 0u )) != kOkRC ) + { + rc = cwLogError(rc,"Unable to set the initial counter value to %f.",init_val); + goto errLabel; + } + if((rc = _string_to_mode_id(mode_label,p->mode_id)) != kOkRC ) goto errLabel; @@ -4131,7 +4101,6 @@ namespace cw case kTriggerPId: { bool v; - if((rc = var_get(var,v)) == kOkRC ) { if( !p->delta_fl ) @@ -4159,98 +4128,93 @@ namespace cw { rc_t rc = kOkRC; inst_t* p = (inst_t*)proc->userPtr; - - + double cnt,inc,minv,maxv; bool v; + + if( !p->delta_fl ) + return rc; + + p->delta_fl = false; if((rc = var_get(proc,kTriggerPId,kAnyChIdx,v)) != kOkRC ) { cwLogError(rc,"Fail!"); goto errLabel; } - - p->delta_fl = v != p->trig_val; + p->trig_val = v; - if( p->delta_fl ) + var_get(proc,kOutPId,kAnyChIdx,cnt); + var_get(proc,kIncPId,kAnyChIdx,inc); + var_get(proc,kMinPId,kAnyChIdx,minv); + var_get(proc,kMaxPId,kAnyChIdx,maxv); + + cnt += p->dir * inc; + + if( minv > cnt || cnt > maxv ) { - p->delta_fl = false; - - double cnt,inc,minv,maxv; - var_get(proc,kOutPId,kAnyChIdx,cnt); - var_get(proc,kIncPId,kAnyChIdx,inc); - var_get(proc,kMinPId,kAnyChIdx,minv); - var_get(proc,kMaxPId,kAnyChIdx,maxv); + bool repeat_fl; + var_get(proc,kRepeatPId,kAnyChIdx,repeat_fl); - double incr = p->dir * inc; - cnt += incr; - - if( minv > cnt || cnt > maxv ) + if( !repeat_fl ) + p->done_fl = true; + else { - bool repeat_fl; - var_get(proc,kRepeatPId,kAnyChIdx,repeat_fl); - - if( !repeat_fl ) - p->done_fl = true; - else + if( cnt > maxv) { - if( cnt > maxv) + switch( p->mode_id ) { - switch( p->mode_id ) - { - case kModuloModeId: - while(cnt > maxv ) - cnt = minv + (cnt-maxv); - break; + case kModuloModeId: + while(cnt > maxv ) + cnt = minv + (cnt-maxv); + break; - case kReverseModeId: - p->dir = -1 * p->dir; - while( cnt > maxv ) - cnt = maxv - (cnt-maxv); - break; + case kReverseModeId: + p->dir = -1 * p->dir; + while( cnt > maxv ) + cnt = maxv - (cnt-maxv); + break; - case kClipModeId: - cnt = maxv; - break; + case kClipModeId: + cnt = maxv; + break; - default: - assert(0); + default: + assert(0); - } - } - - if( cnt < minv) - { - switch( p->mode_id ) - { - case kModuloModeId: - while( cnt < minv ) - cnt = maxv - (minv-cnt); - break; - - case kReverseModeId: - p->dir = -1 * p->dir; - while(cnt < minv ) - cnt = minv + (minv-cnt); - break; - - case kClipModeId: - cnt = minv; - break; - - default: - assert(0); - } } } - } - if( !p->done_fl ) - { - printf("cnt:%f\n",cnt); - var_set(proc,kOutPId,kAnyChIdx,cnt); + if( cnt < minv) + { + switch( p->mode_id ) + { + case kModuloModeId: + while( cnt < minv ) + cnt = maxv - (minv-cnt); + break; + + case kReverseModeId: + p->dir = -1 * p->dir; + while(cnt < minv ) + cnt = minv + (minv-cnt); + break; + + case kClipModeId: + cnt = minv; + break; + + default: + assert(0); + } + } } } + // if the counter has not reached it's terminal state + if( !p->done_fl ) + var_set(proc,kOutPId,kAnyChIdx,cnt); + + errLabel: return rc; } @@ -4264,6 +4228,631 @@ namespace cw }; } + + //------------------------------------------------------------------------------------------------------------------ + // + // List + // + namespace list + { + enum + { + kInPId, + kListPId, + kOutPId + }; + + typedef struct + { + unsigned listN; // the length of the list + const object_t* list; // the list + unsigned typeFl; // the output type + unsigned index; // the last index referenced + bool deltaFl; + } inst_t; + + rc_t _determine_type( const object_t* list, unsigned& typeFl_ref ) + { + rc_t rc = kOkRC; + + typeFl_ref = kInvalidTFl; + + enum { bool_idx, uint_idx, int_idx, float_idx, double_idx, string_idx, cfg_idx, typeN }; + typedef struct type_map_str + { + unsigned idx; + unsigned typeFl; + unsigned cnt; + } type_map_t; + + type_map_t typeA[] = { + { bool_idx, kBoolTFl, 0 }, + { uint_idx, kUIntTFl, 0 }, + { int_idx, kIntTFl, 0 }, + { float_idx, kFloatTFl, 0 }, + { double_idx, kDoubleTFl, 0 }, + { string_idx, kStringTFl, 0 }, + { cfg_idx, kCfgTFl, 0 }, + }; + + + // count the number of each type of element in the list. + for(unsigned i=0; ichild_count(); ++i) + { + const object_t* c = list->child_ele(i); + + switch( c->type->id ) + { + case kCharTId: typeA[uint_idx].cnt+=1; break; + case kInt8TId: typeA[int_idx].cnt +=1; break; + case kUInt8TId: typeA[uint_idx].cnt+=1; break; + case kInt16TId: typeA[int_idx].cnt +=1; break; + case kUInt16TId: typeA[uint_idx].cnt+=1; break; + case kInt32TId: typeA[int_idx].cnt +=1; break; + case kUInt32TId: typeA[uint_idx].cnt+=1; break; + case kFloatTId: typeA[float_idx].cnt+=1; break; + case kDoubleTId: typeA[double_idx].cnt+=1; break; + case kBoolTId: typeA[bool_idx].cnt+=1; break; + case kStringTId: typeA[string_idx].cnt+=1; break; + case kCStringTId:typeA[string_idx].cnt+=1; break; + break; + + default: + switch( c->type->id ) + { + case kVectTId: + case kPairTId: + case kListTId: + case kDictTId: + typeA[cfg_idx].cnt +=1; + break; + + default: + rc = cwLogError(kSyntaxErrorRC,"The object type '0x%x' is not a valid list entry type. %i",c->type->flags,list->child_count()); + goto errLabel; + } + } + + unsigned type_flag = kInvalidTFl; // type flag of one of the reference types + unsigned type_cnt = 0; // count of types + + for(unsigned i=0; i 0 ) + { + type_cnt += 1; + type_flag = typeA[i].typeFl; + } + + // it is an error if more than one type of element was included in the list - + // and one of those types was string or cfg - having multiple numeric types + // is ok because they can be converted between each other - but string, and cfg's + // cannot be converted to numbers, nor can the be converted between each other. + if( type_cnt > 1 && (typeA[string_idx].cnt>0 || typeA[cfg_idx].cnt>0) ) + { + rc = cwLogError(kInvalidArgRC,"The list types. The list must be all numerics, all strings, or all cfg. types."); + for(unsigned i=0; i 0 ) + cwLogInfo("%i %s",typeA[i].cnt, value_type_flag_to_label(typeA[i].typeFl)); + + goto errLabel; + } + + typeFl_ref = type_flag; + } + + + errLabel: + return rc; + } + + template< typename T > + rc_t _set_out_tmpl( instance_t* proc, inst_t* p, unsigned idx, T& v ) + { + rc_t rc; + const object_t* ele; + + // get the list element to output + if((ele = p->list->child_ele(idx)) == nullptr ) + { + rc = cwLogError(kEleNotFoundRC,"The list element at index %i could not be accessed.",idx); + goto errLabel; + } + + // get the value of the list element + if((rc = ele->value(v)) != kOkRC ) + { + rc = cwLogError(rc,"List value access failed on index %i",idx); + goto errLabel; + } + + // set the output + if((rc = var_set(proc,kOutPId,kAnyChIdx,v)) != kOkRC ) + { + rc = cwLogError(rc,"List output failed on index %i",idx); + goto errLabel; + } + + errLabel: + return rc; + } + + rc_t _set_output( instance_t* proc, inst_t* p ) + { + rc_t rc; + unsigned idx; + + if((rc = var_get(proc,kInPId,kAnyChIdx,idx)) != kOkRC ) + { + rc = cwLogError(rc,"Unable to get the list index."); + goto errLabel; + } + + // if the index has not changed then there is nothing to do + if( idx == p->index ) + goto errLabel; + + switch( p->typeFl ) + { + case kUIntTFl: + { + unsigned v; + rc = _set_out_tmpl(proc,p,idx,v); + } + break; + + case kIntTFl: + { + int v; + rc = _set_out_tmpl(proc,p,idx,v); + } + break; + + case kFloatTFl: + { + float v; + rc = _set_out_tmpl(proc,p,idx,v); + } + break; + + case kDoubleTFl: + { + double v; + rc = _set_out_tmpl(proc,p,idx,v); + } + break; + + case kStringTFl: + { + const char* v; + rc = _set_out_tmpl(proc,p,idx,v); + } + break; + + case kCfgTFl: + { + const object_t* v; + rc = _set_out_tmpl(proc,p,idx,v); + } + break; + + default: + rc = cwLogError(kInvalidArgRC,"The list type flag %s (0x%x) is not valid.",value_type_flag_to_label(p->typeFl),p->typeFl); + break; + + } + + if(rc != kOkRC ) + goto errLabel; + + p->index = idx; + + errLabel: + return rc; + } + + rc_t create( instance_t* proc ) + { + rc_t rc = kOkRC; + inst_t* p = mem::allocZ(); + unsigned index; + proc->userPtr = p; + + variable_t* dum = nullptr; + + p->index = kInvalidIdx; + p->typeFl = kInvalidTFl; + p->deltaFl = false; + + if((rc = var_register_and_get(proc, kAnyChIdx, + kInPId, "in", kBaseSfxId, index, + kListPId,"list", kBaseSfxId, p->list)) != kOkRC ) + { + goto errLabel; + } + + if( !p->list->is_list() ) + { + cwLogError(kSyntaxErrorRC,"The list cfg. value is not a list."); + goto errLabel; + } + + p->listN = p->list->child_count(); + + // determine what type of element is in the list + // (all elements in the this list must be of the same type: numeric,string,cfg) + if((rc = _determine_type( p->list, p->typeFl )) != kOkRC ) + goto errLabel; + + // create the output variable + if((rc = var_create( proc, "out", kBaseSfxId, kOutPId, kAnyChIdx, nullptr, p->typeFl, dum )) != kOkRC ) + { + rc = cwLogError(rc,"'out' var create failed."); + goto errLabel; + } + + // set the initial value of the output + if((rc = _set_output(proc,p)) != kOkRC ) + goto errLabel; + + errLabel: + return rc; + } + + rc_t destroy( instance_t* proc ) + { + rc_t rc = kOkRC; + + inst_t* p = (inst_t*)proc->userPtr; + + mem::release(p); + + return rc; + } + + rc_t value( instance_t* proc, variable_t* var ) + { + rc_t rc = kOkRC; + if( var->vid == kInPId ) + { + inst_t* p = (inst_t*)proc->userPtr; + unsigned idx; + if( var_get(var,idx) == kOkRC && idx != p->index) + p->deltaFl = true; + } + return rc; + } + + rc_t exec( instance_t* proc ) + { + rc_t rc = kOkRC; + inst_t* p = (inst_t*)proc->userPtr; + + if( p->deltaFl ) + { + rc = _set_output(proc, p ); + p->deltaFl = false; + } + return rc; + } + + class_members_t members = { + .create = create, + .destroy = destroy, + .value = value, + .exec = exec, + .report = nullptr + }; + + } + + //------------------------------------------------------------------------------------------------------------------ + // + // add + // + namespace add + { + enum { + kOutPId, + kOTypePId, + kInPId + }; + + typedef struct + { + bool delta_fl; + unsigned inN; + } inst_t; + + + template< typename T > + rc_t _sum( instance_t* proc, variable_t* var ) + { + rc_t rc = kOkRC; + inst_t* p = (inst_t*)proc->userPtr; + + T sum = 0; + + // read and sum the inputs + for(unsigned i=0; iinN; ++i) + { + T val; + if((rc = var_get(proc,kInPId+i,kAnyChIdx,val)) == kOkRC ) + sum += val; + else + { + rc = cwLogError(rc,"Operand index %i read failed.",i); + goto errLabel; + } + } + + // set the output + if((rc = var_set(var,sum)) != kOkRC ) + { + rc = cwLogError(rc,"Result set failed."); + goto errLabel; + } + + errLabel: + return rc; + } + + rc_t _exec( instance_t* proc, variable_t* out_var=nullptr ) + { + rc_t rc = kOkRC; + inst_t* p = (inst_t*)(proc->userPtr); + + if( !p->delta_fl ) + return rc; + + p->delta_fl = false; + + if( out_var == nullptr ) + if((rc = var_find(proc,kOutPId,kAnyChIdx,out_var)) != kOkRC ) + { + rc = cwLogError(rc,"The output variable could not be found."); + goto errLabel; + } + + switch( out_var->varDesc->type ) + { + case kBoolTFl: rc = _sum(proc,out_var); break; + case kUIntTFl: rc = _sum(proc,out_var); break; + case kIntTFl: rc = _sum(proc,out_var); break; + case kFloatTFl: rc = _sum(proc,out_var); break; + case kDoubleTFl: rc = _sum(proc,out_var); break; + default: + rc = cwLogError(kInvalidArgRC,"The output type %s (0x%x) is not valid.",value_type_flag_to_label(out_var->value->tflag),out_var->value->tflag); + goto errLabel; + } + + if(rc != kOkRC ) + rc = cwLogError(kOpFailRC,"Sum failed."); + + errLabel: + return rc; + + } + + rc_t create( instance_t* proc ) + { + rc_t rc = kOkRC; + inst_t* p = mem::allocZ(); + proc->userPtr = p; + + variable_t* out_var = nullptr; + const char* out_type_label = nullptr; + unsigned out_type_flag = kInvalidTFl; + unsigned sfxIdAllocN = instance_var_count(proc); + unsigned sfxIdA[ sfxIdAllocN ]; + p->inN = 0; + + // get a count of the number of input variables + if((rc = var_mult_sfx_id_array(proc, "in", sfxIdA, sfxIdAllocN, p->inN )) != kOkRC ) + { + rc = cwLogError(rc,"Unable to obtain the array of mult label-sfx-id's for the variable 'in'."); + goto errLabel; + } + + // if the adder has no inputs + if( p->inN == 0 ) + { + rc = cwLogError(rc,"The 'add' unit '%s' appears to not have any inputs.",cwStringNullGuard(proc->label)); + goto errLabel; + } + + // sort the input id's in ascending order + std::sort(sfxIdA, sfxIdA + p->inN, [](unsigned& a,unsigned& b){ return ainN; ++i) + { + variable_t* dum; + if((rc = var_register(proc, "in", sfxIdA[i], kInPId+i, kAnyChIdx, nullptr, dum )) != kOkRC ) + { + rc = cwLogError(rc,"Variable registration failed for the variable 'in:%i'.",sfxIdA[i]);; + goto errLabel; + } + } + + // Get the output type label as a string + if((rc = var_register_and_get(proc,kAnyChIdx,kOTypePId,"otype",kBaseSfxId,out_type_label)) != kOkRC ) + { + rc = cwLogError(rc,"Variable registration failed for the variable 'otype:0'.");; + goto errLabel; + } + + // Convert the output type label into a flag + if((out_type_flag = value_type_label_to_flag(out_type_label)) == kInvalidTFl ) + { + rc = cwLogError(rc,"The type label '%s' does not identify a valid type.",cwStringNullGuard(out_type_label));; + goto errLabel; + } + + // Create the output var + if((rc = var_create( proc, "out", kBaseSfxId, kOutPId, kAnyChIdx, nullptr, out_type_flag, out_var )) != kOkRC ) + { + rc = cwLogError(rc,"The output variable create failed."); + goto errLabel; + } + + /* + if((rc = var_set(proc,kOutPId,kAnyChIdx,0.0)) != kOkRC ) + { + rc = cwLogError(rc,"Initial output variable set failed."); + goto errLabel; + } + */ + + p->delta_fl=true; + _exec(proc,out_var); + errLabel: + return rc; + } + + rc_t destroy( instance_t* proc ) + { + rc_t rc = kOkRC; + + inst_t* p = (inst_t*)proc->userPtr; + + mem::release(p); + + return rc; + } + + rc_t value( instance_t* proc, variable_t* var ) + { + rc_t rc = kOkRC; + inst_t* p = (inst_t*)(proc->userPtr); + + if( kInPId <= var->vid && var->vid < kInPId+p->inN ) + p->delta_fl = true; + + return rc; + } + + rc_t exec( instance_t* proc ) + { + return _exec(proc); + } + + class_members_t members = { + .create = create, + .destroy = destroy, + .value = value, + .exec = exec, + .report = nullptr + }; + } + + //------------------------------------------------------------------------------------------------------------------ + // + // preset + // + namespace preset + { + enum { kInPId }; + + enum { kPresetLabelCharN=255 }; + + typedef struct + { + char preset_label[ kPresetLabelCharN+1]; + } inst_t; + + + rc_t _set_preset( instance_t* proc, inst_t* p, const char* preset_label ) + { + rc_t rc = kOkRC; + + if( preset_label == nullptr ) + { + if((rc = var_get(proc, kInPId, kAnyChIdx, preset_label)) != kOkRC ) + { + rc = cwLogError(rc,"The variable 'in read failed."); + goto errLabel; + } + } + + if( preset_label == nullptr ) + { + rc = cwLogError(kInvalidArgRC,"Preset application failed due to blank preset label."); + goto errLabel; + } + + if((rc = network_apply_preset(*proc->net, preset_label)) != kOkRC ) + { + rc = cwLogError(rc,"Appy preset '%s' failed.",cwStringNullGuard(preset_label)); + goto errLabel; + } + + if( textLength(preset_label) >= kPresetLabelCharN ) + strncpy(p->preset_label,preset_label,kPresetLabelCharN); + else + { + rc = cwLogError(kBufTooSmallRC,"The preset label '%s' is to long.",cwStringNullGuard(preset_label)); + goto errLabel; + } + + errLabel: + return rc; + + } + + rc_t create( instance_t* proc ) + { + rc_t rc = kOkRC; + inst_t* p = mem::allocZ(); + proc->userPtr = p; + const char* label = nullptr; + + p->preset_label[0] = 0; + + if((rc = var_register_and_get(proc,kAnyChIdx,kInPId,"in",kBaseSfxId,label)) != kOkRC ) + goto errLabel; + + errLabel: + return rc; + } + + rc_t destroy( instance_t* proc ) + { + rc_t rc = kOkRC; + + inst_t* p = (inst_t*)proc->userPtr; + + // Custom clean-up code goes here + + mem::release(p); + + return rc; + } + + rc_t value( instance_t* proc, variable_t* var ) + { + rc_t rc = kOkRC; + return rc; + } + + rc_t exec( instance_t* proc ) + { + rc_t rc = kOkRC; + //inst_t* p = (inst_t*)proc->userPtr; + + return rc; + } + + class_members_t members = { + .create = create, + .destroy = destroy, + .value = value, + .exec = exec, + .report = nullptr + }; + + } + + } // flow } // cw diff --git a/cwFlowProc.h b/cwFlowProc.h index d09b0e0..30e3588 100644 --- a/cwFlowProc.h +++ b/cwFlowProc.h @@ -7,8 +7,8 @@ namespace cw namespace midi_out { extern class_members_t members; } namespace audio_in { extern class_members_t members; } namespace audio_out { extern class_members_t members; } - namespace audioFileIn { extern class_members_t members; } - namespace audioFileOut { extern class_members_t members; } + namespace audio_file_in { extern class_members_t members; } + namespace audio_file_out { extern class_members_t members; } namespace audio_gain { extern class_members_t members; } namespace audio_split { extern class_members_t members; } namespace audio_merge { extern class_members_t members; } @@ -31,6 +31,9 @@ namespace cw namespace number { extern class_members_t members; } namespace timer { extern class_members_t members; } namespace counter { extern class_members_t members; } + namespace list { extern class_members_t members; } + namespace add { extern class_members_t members; } + namespace preset { extern class_members_t members; } } } diff --git a/cwFlowTypes.cpp b/cwFlowTypes.cpp index eada7df..6474233 100644 --- a/cwFlowTypes.cpp +++ b/cwFlowTypes.cpp @@ -2,6 +2,7 @@ #include "cwLog.h" #include "cwCommonImpl.h" #include "cwMem.h" +#include "cwMath.h" #include "cwText.h" #include "cwObject.h" #include "cwVectOps.h" @@ -45,6 +46,10 @@ namespace cw { kFloatTFl, "coeff"}, { kDoubleTFl, "ftime" }, + { kUIntTFl | kIntTFl | kFloatTFl | kDoubleTFl, "numeric" }, + + { kRuntimeTFl, "runtime" }, + { kInvalidTFl, nullptr } }; @@ -63,7 +68,7 @@ namespace cw if( v == nullptr ) return; - switch( v->flags & kTypeMask ) + switch( v->tflag & kTypeMask ) { case kInvalidTFl: break; @@ -98,22 +103,25 @@ namespace cw case kStringTFl: mem::release( v->u.s ); break; - + case kTimeTFl: assert(0); break; + case kCfgTFl: + break; + default: assert(0); break; } - v->flags = kInvalidTFl; + v->tflag = kInvalidTFl; } void _value_duplicate( value_t& dst, const value_t& src ) { - switch( src.flags & kTypeMask ) + switch( src.tflag & kTypeMask ) { case kInvalidTFl: break; @@ -129,17 +137,17 @@ namespace cw case kABufTFl: dst.u.abuf = src.u.abuf == nullptr ? nullptr : abuf_duplicate(src.u.abuf); - dst.flags = src.flags; + dst.tflag = src.tflag; break; case kFBufTFl: dst.u.fbuf = src.u.fbuf == nullptr ? nullptr : fbuf_duplicate(src.u.fbuf); - dst.flags = src.flags; + dst.tflag = src.tflag; break; case kMBufTFl: dst.u.mbuf = src.u.mbuf == nullptr ? nullptr : mbuf_duplicate(src.u.mbuf); - dst.flags = src.flags; + dst.tflag = src.tflag; break; case kBoolMtxTFl: @@ -152,13 +160,17 @@ namespace cw case kStringTFl: dst.u.s = mem::duplStr( dst.u.s ); - dst.flags = src.flags; + dst.tflag = src.tflag; break; case kTimeTFl: assert(0); break; + case kCfgTFl: + dst = src; + break; + default: assert(0); break; @@ -171,16 +183,16 @@ namespace cw if( v == nullptr ) return; - switch( v->flags & kTypeMask ) + switch( v->tflag & kTypeMask ) { case kInvalidTFl: break; - case kBoolTFl: printf("%s ", v->u.b ? "True" : "False" ); break; - case kUIntTFl: printf("%i ", v->u.u ); break; - case kIntTFl: printf("%i ", v->u.i ); break; - case kFloatTFl: printf("%f ", v->u.f ); break; - case kDoubleTFl:printf("%f ", v->u.d ); break; + case kBoolTFl: printf("b:%s ", v->u.b ? "true" : "false" ); break; + case kUIntTFl: printf("u:%i ", v->u.u ); break; + case kIntTFl: printf("i:%i ", v->u.i ); break; + case kFloatTFl: printf("f:%f ", v->u.f ); break; + case kDoubleTFl:printf("d:%f ", v->u.d ); break; case kABufTFl: if( v->u.abuf == nullptr ) printf("abuf: "); @@ -224,6 +236,11 @@ namespace cw assert(0); break; + case kCfgTFl: + if( v->u.cfg != nullptr ) + v->u.cfg->print(); + break; + default: assert(0); break; @@ -235,23 +252,46 @@ namespace cw rc_t _val_get( const value_t* val, bool& valRef ) { rc_t rc = kOkRC; - switch( val->flags & kTypeMask ) + switch( val->tflag & kTypeMask ) { case kBoolTFl: valRef = val->u.b; break; case kUIntTFl: valRef = val->u.u!=0; break; case kIntTFl: valRef = val->u.i!=0; break; case kFloatTFl: valRef = val->u.f!=0; break; - case kDoubleTFl: valRef = val->u.d!=0; break; + case kDoubleTFl: valRef = val->u.d!=0; break; default: - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a bool.",val->flags); + rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to a bool.",_typeFlagToLabel(val->tflag),val->tflag); } return rc; } + + rc_t _val_set( value_t* val, bool v ) + { + rc_t rc = kOkRC; + + switch( val->tflag & kTypeMask ) + { + case kBoolTFl: val->u.b=v; break; + case kUIntTFl: val->u.u=v; break; + case kIntTFl: val->u.i=v; break; + case kFloatTFl: val->u.f=v; break; + case kDoubleTFl: val->u.d=v; break; + case kInvalidTFl: + val->u.b = v; + val->tflag = kBoolTFl; + break; + + default: + rc = cwLogError(kTypeMismatchRC,"A bool could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag); + } + + return rc; + } rc_t _val_get( const value_t* val, uint_t& valRef ) { rc_t rc = kOkRC; - switch( val->flags & kTypeMask ) + switch( val->tflag & kTypeMask ) { case kBoolTFl: valRef = val->u.b ? 1 : 0; break; case kUIntTFl: valRef = val->u.u; break; @@ -259,15 +299,38 @@ namespace cw case kFloatTFl: valRef = (uint_t)val->u.f; break; case kDoubleTFl: valRef = (uint_t)val->u.d; break; default: - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a uint_t.",val->flags); + rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to a uint.",_typeFlagToLabel(val->tflag),val->tflag); } return rc; } + + rc_t _val_set( value_t* val, uint_t v ) + { + rc_t rc = kOkRC; + switch( val->tflag & kTypeMask ) + { + case kBoolTFl: val->u.b=v!=0; break; + case kUIntTFl: val->u.u=v; break; + case kIntTFl: val->u.i=v; break; + case kFloatTFl: val->u.f=v; break; + case kDoubleTFl: val->u.d=v; break; + case kInvalidTFl: + val->u.u = v; + val->tflag = kUIntTFl; + break; + + default: + rc = cwLogError(kTypeMismatchRC,"A uint could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag); + } + + return rc; + } + rc_t _val_get( const value_t* val, int_t& valRef ) { rc_t rc = kOkRC; - switch( val->flags & kTypeMask ) + switch( val->tflag & kTypeMask ) { case kBoolTFl: valRef = val->u.b ? 1 : 0; break; case kUIntTFl: valRef = (int_t)val->u.u; break; @@ -275,15 +338,40 @@ namespace cw case kFloatTFl: valRef = (int_t)val->u.f; break; case kDoubleTFl: valRef = (int_t)val->u.d; break; default: - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a int_t.",val->flags); + rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to an int.",_typeFlagToLabel(val->tflag),val->tflag); + } return rc; } + rc_t _val_set( value_t* val, int_t v ) + { + rc_t rc = kOkRC; + + switch( val->tflag & kTypeMask ) + { + case kBoolTFl: val->u.b=v!=0; break; + case kUIntTFl: val->u.u=v; break; + case kIntTFl: val->u.i=v; break; + case kFloatTFl: val->u.f=v; break; + case kDoubleTFl: val->u.d=v; break; + case kInvalidTFl: + val->u.i = v; + val->tflag = kIntTFl; + break; + + default: + rc = cwLogError(kTypeMismatchRC,"An int could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag); + } + + return rc; + } + + rc_t _val_get( const value_t* val, float& valRef ) { rc_t rc = kOkRC; - switch( val->flags & kTypeMask ) + switch( val->tflag & kTypeMask ) { case kBoolTFl: valRef = val->u.b ? 1 : 0; break; case kUIntTFl: valRef = (float)val->u.u; break; @@ -291,15 +379,38 @@ namespace cw case kFloatTFl: valRef = (float)val->u.f; break; case kDoubleTFl: valRef = (float)val->u.d; break; default: - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a float.", val->flags); + rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to a float.",_typeFlagToLabel(val->tflag),val->tflag); } return rc; } + rc_t _val_set( value_t* val, float v ) + { + rc_t rc = kOkRC; + + switch( val->tflag & kTypeMask ) + { + case kBoolTFl: val->u.b=v!=0; break; + case kUIntTFl: val->u.u=(unsigned)v; break; + case kIntTFl: val->u.i=(int)v; break; + case kFloatTFl: val->u.f=v; break; + case kDoubleTFl: val->u.d=v; break; + case kInvalidTFl: + val->u.f = v; + val->tflag = kFloatTFl; + break; + + default: + rc = cwLogError(kTypeMismatchRC,"A float could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag); + } + + return rc; + } + rc_t _val_get( const value_t* val, double& valRef ) { rc_t rc = kOkRC; - switch( val->flags & kTypeMask ) + switch( val->tflag & kTypeMask ) { case kBoolTFl: valRef = val->u.b ? 1 : 0; break; case kUIntTFl: valRef = (double)val->u.u; break; @@ -307,33 +418,77 @@ namespace cw case kFloatTFl: valRef = (double)val->u.f; break; case kDoubleTFl: valRef = val->u.d; break; default: - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a double.",val->flags); + rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to a double.",_typeFlagToLabel(val->tflag),val->tflag); } return rc; } + rc_t _val_set( value_t* val, double v ) + { + rc_t rc = kOkRC; + + switch( val->tflag & kTypeMask ) + { + case kBoolTFl: val->u.b=v!=0; break; + case kUIntTFl: val->u.u=(unsigned)v; break; + case kIntTFl: val->u.i=(int)v; break; + case kFloatTFl: val->u.f=(float)v; break; + case kDoubleTFl: val->u.d=v; break; + case kInvalidTFl: + val->u.d = v; + val->tflag = kDoubleTFl; + break; + + default: + rc = cwLogError(kTypeMismatchRC,"A double could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag); + } + + return rc; + } + rc_t _val_get( const value_t* val, const char*& valRef ) { rc_t rc = kOkRC; - if( cwIsFlag(val->flags & kTypeMask, kStringTFl) ) + if( cwIsFlag(val->tflag & kTypeMask, kStringTFl) ) valRef = val->u.s; else { - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to a string.",val->flags); + rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to a string.",_typeFlagToLabel(val->tflag),val->tflag); valRef = nullptr; } return rc; } + rc_t _val_set( value_t* val, const char* v ) + { + rc_t rc = kOkRC; + + switch( val->tflag & kTypeMask ) + { + case kStringTFl: + val->u.s=mem::duplStr(v); break; + + case kInvalidTFl: + val->u.s = mem::duplStr(v); + val->tflag = kStringTFl; + break; + + default: + rc = cwLogError(kTypeMismatchRC,"A string could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag); + } + + return rc; + } + rc_t _val_get( value_t* val, abuf_t*& valRef ) { rc_t rc = kOkRC; - if( cwIsFlag(val->flags & kTypeMask, kABufTFl) ) + if( cwIsFlag(val->tflag & kTypeMask, kABufTFl) ) valRef = val->u.abuf; else { - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to an abuf_t.",val->flags); + rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to an abuf.",_typeFlagToLabel(val->tflag),val->tflag); valRef = nullptr; } return rc; @@ -348,15 +503,37 @@ namespace cw return rc; } + rc_t _val_set( value_t* val, abuf_t* v ) + { + rc_t rc = kOkRC; + + switch( val->tflag & kTypeMask ) + { + case kABufTFl: + val->u.abuf=v; + break; + + case kInvalidTFl: + val->u.abuf=v; + val->tflag = kABufTFl; + break; + + default: + rc = cwLogError(kTypeMismatchRC,"A audio signal could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag); + } + + return rc; + } + rc_t _val_get( value_t* val, fbuf_t*& valRef ) { rc_t rc = kOkRC; - if( cwIsFlag(val->flags & kTypeMask, kFBufTFl) ) + if( cwIsFlag(val->tflag & kTypeMask, kFBufTFl) ) valRef = val->u.fbuf; else { valRef = nullptr; - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to an fbuf_t.",val->flags); + rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to an fbuf.",_typeFlagToLabel(val->tflag),val->tflag); } return rc; } @@ -370,18 +547,63 @@ namespace cw return rc; } + rc_t _val_set( value_t* val, fbuf_t* v ) + { + rc_t rc = kOkRC; + + switch( val->tflag & kTypeMask ) + { + case kFBufTFl: + val->u.fbuf=v; + break; + + case kInvalidTFl: + val->u.fbuf=v; + val->tflag = kFBufTFl; + break; + + default: + rc = cwLogError(kTypeMismatchRC,"A spectrum signal could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag); + } + + return rc; + } + rc_t _val_get( value_t* val, mbuf_t*& valRef ) { rc_t rc = kOkRC; - if( cwIsFlag(val->flags & kTypeMask, kMBufTFl) ) + if( cwIsFlag(val->tflag & kTypeMask, kMBufTFl) ) valRef = val->u.mbuf; else { valRef = nullptr; - rc = cwLogError(kTypeMismatchRC,"The type 0x%x could not be converted to an mbuf_t.",val->flags); + rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to an mbuf.",_typeFlagToLabel(val->tflag),val->tflag); } return rc; } + + rc_t _val_set( value_t* val, mbuf_t* v ) + { + rc_t rc = kOkRC; + + switch( val->tflag & kTypeMask ) + { + case kMBufTFl: + val->u.mbuf=v; + break; + + case kInvalidTFl: + val->u.mbuf=v; + val->tflag = kMBufTFl; + break; + + default: + rc = cwLogError(kTypeMismatchRC,"A MIDI signal could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag); + } + + return rc; + } + rc_t _val_get( value_t* val, const mbuf_t*& valRef ) { @@ -391,7 +613,43 @@ namespace cw valRef = non_const_val; return rc; } + + rc_t _val_get( value_t* val, const object_t*& valRef ) + { + rc_t rc = kOkRC; + + if( cwIsFlag(val->tflag & kTypeMask, kCfgTFl) ) + valRef = val->u.cfg; + else + { + valRef = nullptr; + rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to a cfg.",_typeFlagToLabel(val->tflag),val->tflag); + + } + return rc; + } + rc_t _val_set( value_t* val, const object_t* v ) + { + rc_t rc = kOkRC; + + switch( val->tflag & kTypeMask ) + { + case kCfgTFl: + val->u.cfg=v; + break; + + case kInvalidTFl: + val->u.cfg=v; + val->tflag = kCfgTFl; + break; + + default: + rc = cwLogError(kTypeMismatchRC,"A cfg. could not be converted to a %s (0x%x).",_typeFlagToLabel(val->tflag),val->tflag); + } + + return rc; + } template< typename T > rc_t _val_get_driver( const variable_t* var, T& valRef ) @@ -403,8 +661,8 @@ namespace cw return cwLogError(kInvalidStateRC,"No value has been assigned to the variable: %s:%i.%s:%i ch:%i.",cwStringNullGuard(var->inst->label),var->inst->label_sfx_id,cwStringNullGuard(var->label),var->label_sfx_id,var->chIdx); return _val_get(var->value,valRef); - } - + +} rc_t _var_find_to_set( instance_t* inst, unsigned vid, unsigned chIdx, unsigned typeFl, variable_t*& varRef ) { rc_t rc = kOkRC; @@ -414,8 +672,14 @@ namespace cw if((rc = var_find(inst,vid,chIdx,varRef)) == kOkRC ) { // validate the type of the variable against the description + /* if( !cwIsFlag(varRef->varDesc->type,typeFl ) ) - rc = cwLogError(kTypeMismatchRC,"Type mismatch. Instance:%s:%i variable:%s:%i with type 0x%x does not match requested type:0x%x.",varRef->inst->label,varRef->inst->label_sfx_id,varRef->label,varRef->label_sfx_id,varRef->varDesc->type,typeFl); + rc = cwLogError(kTypeMismatchRC,"Type mismatch. Instance:%s:%i variable:%s:%i with type %s (0x%x) does not match requested type: %s (0x%x).", + varRef->inst->label,varRef->inst->label_sfx_id, + varRef->label, + varRef->label_sfx_id,_typeFlagToLabel(varRef->varDesc->type),varRef->varDesc->type, + _typeFlagToLabel(typeFl),typeFl); + */ } @@ -453,137 +717,119 @@ namespace cw return nullptr; } + rc_t _var_find_on_label_and_ch( instance_t* inst, 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(inst,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(inst->label)); + return rc; + } rc_t _validate_var_assignment( variable_t* var, unsigned typeFl ) { if( cwIsFlag(var->varDesc->flags, kSrcVarFl ) ) return cwLogError(kInvalidStateRC, "The variable '%s:%i' on instance '%s:%i' cannot be set because it is a 'src' variable.", var->label, var->label_sfx_id, var->inst->label,var->inst->label_sfx_id); - + /* if( !cwIsFlag(var->varDesc->type, typeFl ) ) return cwLogError(kTypeMismatchRC, "The variable '%s:%i' on instance '%s:%i' is not a '%s'.", var->label, var->label_sfx_id, var->inst->label, var->inst->label_sfx_id, _typeFlagToLabel( typeFl )); - + */ + return kOkRC; } + void _var_print( const variable_t* var ) + { + const char* conn_label = is_connected_to_source_proc(var) ? "extern" : " "; + + printf(" %20s:%5i id:%4i 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 ) + printf(" src:%s:%i.%s:%i",var->src_var->inst->label,var->src_var->inst->label_sfx_id,var->src_var->label,var->src_var->label_sfx_id); + + printf("\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->connect_link; con_var!=nullptr; con_var=con_var->connect_link) + 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; - - //if((rc = con_var->inst->class_desc->members->value( con_var->inst, con_var )) != kOkRC ) - // break; - + + cwLogMod("%s:%i %s:%i -> %s:%i %s:%i\n", + var->inst->label,var->inst->label_sfx_id, + var->label,var->label_sfx_id, + con_var->inst->label,con_var->inst->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; } - template< typename T > - void _var_setter( variable_t* var, unsigned local_value_idx, T val ) - { - cwLogError(kAssertFailRC,"Unimplemented variable setter."); - assert(0); - } - template<> - void _var_setter( variable_t* var, unsigned local_value_idx, bool val ) - { - var->local_value[ local_value_idx ].u.b = val; - var->local_value[ local_value_idx ].flags = kBoolTFl; - cwLogMod("%s:%i.%s:%i ch:%i %i (bool).",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,var->chIdx,val); - } - - template<> - void _var_setter( variable_t* var, unsigned local_value_idx, unsigned val ) - { - var->local_value[ local_value_idx ].u.u = val; - var->local_value[ local_value_idx ].flags = kUIntTFl; - cwLogMod("%s:%i.%s:%i ch:%i %i (uint).",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,var->chIdx,val); - } - - template<> - void _var_setter( variable_t* var, unsigned local_value_idx, int val ) - { - var->local_value[ local_value_idx ].u.i = val; - var->local_value[ local_value_idx ].flags = kIntTFl; - cwLogMod("%s:%i.%s:%i ch:%i %i (int).",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,var->chIdx,val); - } - - template<> - void _var_setter( variable_t* var, unsigned local_value_idx, float val ) - { - var->local_value[ local_value_idx ].u.f = val; - var->local_value[ local_value_idx ].flags = kFloatTFl; - cwLogMod("%s:%i.%s:%i ch:%i %f (float).",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,var->chIdx,val); - } - - template<> - void _var_setter( variable_t* var, unsigned local_value_idx, double val ) - { - var->local_value[ local_value_idx ].u.d = val; - var->local_value[ local_value_idx ].flags = kDoubleTFl; - cwLogMod("%s:%i.%s:%i ch:%i %f (double).",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,var->chIdx,val); - } - - template<> - void _var_setter( variable_t* var, unsigned local_value_idx, const char* val ) - { - var->local_value[ local_value_idx ].u.s = mem::duplStr(val); - var->local_value[ local_value_idx ].flags = kStringTFl; - cwLogMod("%s:%i.%s:%i ch:%i %s (string).",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,var->chIdx,val); - } - - template<> - void _var_setter( variable_t* var, unsigned local_value_idx, abuf_t* val ) - { - var->local_value[ local_value_idx ].u.abuf = val; - var->local_value[ local_value_idx ].flags = kABufTFl; - cwLogMod("%s:%i.%s:%i ch:%i %s (abuf).",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,var->chIdx,abuf==nullptr ? "null" : "valid"); - } - - template<> - void _var_setter( variable_t* var, unsigned local_value_idx, mbuf_t* val ) - { - var->local_value[ local_value_idx ].u.mbuf = val; - var->local_value[ local_value_idx ].flags = kMBufTFl; - cwLogMod("%s:%i.%s:%i ch:%i %s (abuf).",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,var->chIdx,mbuf==nullptr ? "null" : "valid"); - } - template<> - void _var_setter( variable_t* var, unsigned local_value_idx, fbuf_t* val ) - { - var->local_value[ local_value_idx ].u.fbuf = val; - var->local_value[ local_value_idx ].flags = kFBufTFl; - cwLogMod("%s:%i.%s:%i ch:%i %s (fbuf).",var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,var->chIdx,fbuf==nullptr ? "null" : "valid"); - } - - template< typename T > - rc_t _var_set_template( variable_t* var, unsigned typeFlag, T val ) + // 'typeFlag' is the type (tflag) of 'val'. + template< typename T > + rc_t _var_set_template( variable_t* var, unsigned argTypeFlag, T val ) { rc_t rc; - + // var->type is the allowable type for this var's value. + unsigned value_type_flag = var->type; + 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; - + // verify that this is a legal assignment - if((rc = _validate_var_assignment( var, typeFlag )) != kOkRC ) - { + if((rc = _validate_var_assignment( var, argTypeFlag )) != kOkRC ) goto errLabel; - } // 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->inst->label,var->inst->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 - _var_setter(var,next_local_value_idx,val); + if((rc = _val_set(var->local_value + next_local_value_idx, val )) != kOkRC ) + { + rc = cwLogError(rc,"Value set failed on '%s:%i %s:%i",var->inst->label,var->inst->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; @@ -597,9 +843,11 @@ namespace cw // call because calls' to 'proc.value()' will see the instance 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->inst->class_desc->members->value( var->inst, var ); + var_call_custom_value_func( var ); } + //printf("%p set: %s:%s 0x%x\n",var->value, var->inst->label,var->label,var->value->tflag); + if( rc == kOkRC ) { // send the value to connected downstream proc's @@ -617,25 +865,11 @@ namespace cw } - bool is_connected_to_source_proc( 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 is_a_source_var( const variable_t* var ) - { return var->connect_link != nullptr; } + + // 'valueTypeFlag' is the type (tflag) of 'value' template< typename T > - rc_t _var_set_driver( variable_t* var, unsigned typeFlag, T value ) + rc_t _var_set_driver( variable_t* var, unsigned valueTypeFlag, T value ) { rc_t rc; @@ -647,15 +881,18 @@ namespace cw // if this assignment targets a specific channel ... if( var->chIdx != kAnyChIdx ) { - rc = _var_set_template( var, typeFlag, value ); // ... then set it alone + 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, typeFlag, value )) != kOkRC) + 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->inst->label),var->inst->label_sfx_id,cwStringNullGuard(var->label),var->label_sfx_id); + return rc; } @@ -703,24 +940,77 @@ namespace cw { rc_t rc = kOkRC; - // get the variable type - note that the value type (value->flags) may be differnt - unsigned typeFlag = var->varDesc->type & kTypeMask; + // Determine the flow variable type of cfg. argument 'value'. + unsigned value_flag = 0; - switch( typeFlag ) + switch( value->type->id ) + { + case kCharTId: + case kUInt8TId: + case kUInt16TId: + case kUInt32TId: + value_flag = kUIntTFl; + break; + + case kInt8TId: + case kInt16TId: + case kInt32TId: + value_flag = kIntTFl; + break; + + case kInt64TId: + case kUInt64TId: + rc = cwLogError(kInvalidArgRC,"The flow system does not currently implement 64bit integers."); + goto errLabel; + break; + + case kFloatTId: + value_flag = kFloatTFl; + break; + + case kDoubleTId: + value_flag = kDoubleTFl; + break; + + case kBoolTId: + value_flag = kBoolTFl; + break; + + case kStringTId: + case kCStringTId: + value_flag = kStringTFl; + break; + + default: + value_flag = kCfgTFl; + + } + + /* + if( !cwIsFlag(var->varDesc->type & kTypeMask, value_flag) ) + { + rc = cwLogError(kTypeMismatchRC,"The var desc class type 0x%x does not permit the var to be instantiated with the type %s (0x%x).",var->varDesc->type,_typeFlagToLabel(value_flag),value_flag); + goto errLabel; + } + */ + + switch( value_flag ) { case kBoolTFl: { bool v; + // assign the value of 'value' to to 'v' (do type conversion if necessary) if((rc = value->value(v)) == kOkRC ) - rc = _var_set_driver( var, typeFlag, v ); + // set the value of 'var' where 'v' is the new value and 'value_flag' is the type of 'v'. + rc = _var_set_driver( var, value_flag, v ); } - break; + break; case kUIntTFl: { unsigned v; if((rc = value->value(v)) == kOkRC ) - rc = _var_set_driver( var, typeFlag, v ); + rc = _var_set_driver( var, value_flag, v ); } break; @@ -728,7 +1018,7 @@ namespace cw { int v; if((rc = value->value(v)) == kOkRC ) - rc = _var_set_driver( var, typeFlag, v ); + rc = _var_set_driver( var, value_flag, v ); } break; @@ -736,7 +1026,7 @@ namespace cw { float v; if((rc = value->value(v)) == kOkRC ) - rc = _var_set_driver( var, typeFlag, v ); + rc = _var_set_driver( var, value_flag, v ); } break; @@ -744,7 +1034,7 @@ namespace cw { double v; if((rc = value->value(v)) == kOkRC ) - rc = _var_set_driver( var, typeFlag, v ); + rc = _var_set_driver( var, value_flag, v ); } break; @@ -752,21 +1042,31 @@ namespace cw { const char* v; if((rc = value->value(v)) == kOkRC ) - rc = _var_set_driver( var, typeFlag, v ); + rc = _var_set_driver( var, value_flag, v ); } break; - default: - rc = cwLogError(kOpFailRC,"The variable type 0x%x cannot yet be set via a preset.", var->varDesc->type ); + case kCfgTFl: + { + //const object_t* v; + //if((rc = value->value(v)) == kOkRC ) + rc = _var_set_driver( var, value_flag, value ); + } + break; + + default: + rc = cwLogError(kOpFailRC,"The variable type 0x%x cannot yet be set via a cfg.", var->varDesc->type ); 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->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id,_typeFlagToLabel(var->varDesc->type & kTypeMask)); + return rc; } + rc_t _var_map_id_to_index( instance_t* inst, unsigned vid, unsigned chIdx, unsigned& idxRef ) { @@ -830,9 +1130,51 @@ namespace cw } + /* + void _var_set_value_to_typed_null( variable_t* var, unsigned type_flag ) + { + for(unsigned i=0; ilocal_value[i].tflag == kInvalidTFl ); + + // set the var-value to a typed null value - this will force later settings to be coerced to this type + set_null( var->local_value[i], type_flag ); + } + + var->value = var->local_value; + + } + */ + + 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 statically (non-runtime) type variable."); + goto errLabel; + } + + 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; + + //_var_set_value_to_typed_null(var,type_flag); + + 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( instance_t* inst, const char* var_label, unsigned sfx_id, unsigned id, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef ) + rc_t _var_create( instance_t* inst, 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; @@ -858,19 +1200,24 @@ namespace cw var = mem::allocZ(); var->varDesc = vd; + var->classVarDesc = vd; var->inst = inst; 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 ) + if( value_cfg != nullptr && cwIsNotFlag(vd->type,kRuntimeTFl)) if((rc = _set_var_value_from_cfg( var, value_cfg )) != kOkRC ) goto errLabel; @@ -897,23 +1244,6 @@ namespace cw return rc; } - void _var_print( const variable_t* var ) - { - const char* conn_label = is_connected_to_source_proc(var) ? "extern" : " "; - - printf(" %20s:%5i id:%4i 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 ) - printf(" src:%s:%i.%s:%i",var->src_var->inst->label,var->src_var->inst->label_sfx_id,var->src_var->label,var->src_var->label_sfx_id); - - printf("\n"); - } - rc_t _preset_set_var_value( instance_t* inst, const char* var_label, unsigned sfx_id, unsigned chIdx, const object_t* value ) { @@ -932,9 +1262,6 @@ namespace cw return rc; } - - - } } @@ -1042,7 +1369,6 @@ cw::flow::fbuf_t* cw::flow::fbuf_create( srate_t srate, unsigned chN, const unsi return f; } - cw::flow::fbuf_t* cw::flow::fbuf_create( 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 ]; @@ -1053,11 +1379,8 @@ cw::flow::fbuf_t* cw::flow::fbuf_create( srate_t srate, unsigned chN, unsigned vop::fill( binN_V, chN, binN ); vop::fill( hopSmpN_V, chN, binN ); return fbuf_create( srate, chN, maxBinN_V, binN_V, hopSmpN_V, magV, phsV, hzV ); - } - - void cw::flow::fbuf_destroy( fbuf_t*& fbuf ) { if( fbuf == nullptr ) @@ -1120,6 +1443,9 @@ unsigned cw::flow::value_type_label_to_flag( const char* s ) return flags; } +const char* cw::flow::value_type_flag_to_label( unsigned flag ) +{ return _typeFlagToLabel(flag); } + cw::flow::class_desc_t* cw::flow::class_desc_find( flow_t* p, const char* label ) { @@ -1186,6 +1512,48 @@ void cw::flow::network_print( const network_t& net ) } } +cw::rc_t cw::flow::instance_validate( instance_t* inst ) +{ + rc_t rc = kOkRC; + + for(variable_t* var=inst->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; + } + + 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->varDesc->type & var->value->tflag) ) + { + rc = cwLogError(kInvalidStateRC, "The value type flag '%s' (0x%x) of the var '%s:%i' is not found in the variable class type flags: '%s' (0x%x)", + _typeFlagToLabel(var->value->tflag),var->value->tflag, + var->label,var->label_sfx_id, + _typeFlagToLabel(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::instance_t* cw::flow::instance_find( network_t& net, const char* inst_label, unsigned sfx_id ) { for(unsigned i=0; iclass_desc->members->report( inst ); } +unsigned cw::flow::instance_var_count( instance_t* inst ) +{ + unsigned n = 0; + for(variable_t* var=inst->varL; var!=nullptr; var=var->var_link) + ++n; + + return n; +} void cw::flow::_var_destroy( variable_t* var ) @@ -1239,17 +1615,21 @@ void cw::flow::_var_destroy( variable_t* var ) { 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_create( instance_t* inst, const char* var_label, unsigned sfx_id, unsigned id, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef ) +cw::rc_t cw::flow::var_create( instance_t* inst, 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( inst, var_label, sfx_id, id, chIdx, value_cfg, varRef ); + + rc = _var_create( inst, var_label, sfx_id, id, chIdx, value_cfg, altTypeFl, varRef ); return rc; } @@ -1281,7 +1661,7 @@ cw::rc_t cw::flow::var_channelize( instance_t* inst, const char* var_label, uns if( var == nullptr && chIdx != kAnyChIdx ) { // create the channelized var - if((rc = _var_create( inst, var_label, sfx_id, vid, chIdx, value_cfg, var )) != kOkRC ) + if((rc = _var_create( inst, 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 @@ -1321,6 +1701,85 @@ cw::rc_t cw::flow::var_channelize( instance_t* inst, const char* var_label, uns return rc; } +cw::rc_t cw::flow::var_call_custom_value_func( variable_t* var ) +{ + rc_t rc; + if((rc = var->inst->class_desc->members->value( var->inst, var )) != kOkRC ) + goto errLabel; + + if( var->flags & kLogVarFl ) + { + printf("%10s:%5i", var->inst->label,var->inst->label_sfx_id); + _var_print(var); + } + +errLabel: + return rc; + +} + +cw::rc_t cw::flow::var_flags( instance_t* inst, 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(inst,var_label,sfx_id,chIdx,var)) != kOkRC ) + goto errLabel; + + flags_ref = var->flags; + +errLabel: + return rc; +} + +cw::rc_t cw::flow::var_set_flags( instance_t* inst, 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(inst,var_label,sfx_id,chIdx,var)) != kOkRC ) + goto errLabel; + + + var->flags |= flag; + +errLabel: + return rc; +} + +cw::rc_t cw::flow::var_clr_flags( instance_t* inst, 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(inst,var_label,sfx_id,chIdx,var)) != kOkRC ) + goto errLabel; + + var->flags = cwClrFlag(var->flags,flag); +errLabel: + return rc; +} +/* +cw::rc_t cw::flow::var_set_type( instance_t* inst, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned type_flag ) +{ + rc_t rc = kOkRC; + variable_t* var = nullptr; + + if((rc = _var_find_on_label_and_ch(inst,var_label,sfx_id,chIdx,var)) != kOkRC ) + goto errLabel; + + rc = _var_set_type(var,type_flag); + +errLabel: + if( rc != kOkRC ) + rc = cwLogError(rc,"Type set failed on the variable:'%s:%i",cwStringNullGuard(var_label),sfx_id); + + return rc; +} +*/ + bool cw::flow::var_exists( instance_t* inst, const char* label, unsigned sfx_id, unsigned chIdx ) { return _var_find_on_label_and_ch(inst,label,sfx_id,chIdx) != nullptr; } @@ -1492,6 +1951,60 @@ cw::rc_t cw::flow::var_register( instance_t* inst, const char* var_label, unsign return rc; } +bool cw::flow::is_connected_to_source_proc( 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; } + +cw::rc_t cw::flow::var_mult_sfx_id_array( instance_t* inst, 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=inst->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_register_and_set( instance_t* inst, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, variable_t*& varRef ) { @@ -1588,6 +2101,54 @@ cw::rc_t cw::flow::var_get( const variable_t* var, const mbuf_t*& 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 object_t*& valRef ) +{ return _val_get_driver(var,valRef); } + +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; + 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, const object_t* val ) { return _var_set_driver(var,kCfgTFl,val); } + +cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, const value_t* val ) +{ + rc_t rc = kOkRC; + variable_t* var = nullptr; + + if((rc = _var_find_to_set(inst, vid, chIdx, val->tflag, var )) == kOkRC ) + rc = var_set(var,val); + + return rc; +} cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, bool val ) { @@ -1595,7 +2156,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, bool variable_t* var = nullptr; if((rc = _var_find_to_set(inst, vid, chIdx, kBoolTFl, var )) == kOkRC ) - _var_set_driver( var, kBoolTFl, val ); + rc = _var_set_driver( var, kBoolTFl, val ); return rc; } @@ -1606,7 +2167,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, uint variable_t* var = nullptr; if((rc = _var_find_to_set(inst, vid, chIdx, kUIntTFl, var )) == kOkRC ) - _var_set_driver( var, kUIntTFl, val ); + rc = _var_set_driver( var, kUIntTFl, val ); return rc; } @@ -1617,7 +2178,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, int_ variable_t* var = nullptr; if((rc = _var_find_to_set(inst, vid, chIdx, kIntTFl, var )) == kOkRC ) - _var_set_driver( var, kIntTFl, val ); + rc = _var_set_driver( var, kIntTFl, val ); return rc; } @@ -1628,7 +2189,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, floa variable_t* var = nullptr; if((rc = _var_find_to_set(inst, vid, chIdx, kFloatTFl, var )) == kOkRC ) - _var_set_driver( var, kFloatTFl, val ); + rc = _var_set_driver( var, kFloatTFl, val ); return rc; } @@ -1639,7 +2200,7 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, doub variable_t* var = nullptr; if((rc = _var_find_to_set(inst, vid, chIdx, kDoubleTFl, var )) == kOkRC ) - _var_set_driver( var, kDoubleTFl, val ); + rc = _var_set_driver( var, kDoubleTFl, val ); return rc; } @@ -1650,11 +2211,23 @@ cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, cons variable_t* var = nullptr; if((rc = _var_find_to_set(inst, vid, chIdx, kStringTFl, var )) == kOkRC ) - _var_set_driver( var, kStringTFl, val ); + rc = _var_set_driver( var, kStringTFl, val ); return rc; } +cw::rc_t cw::flow::var_set( instance_t* inst, unsigned vid, unsigned chIdx, const object_t* val ) +{ + rc_t rc = kOkRC; + variable_t* var = nullptr; + + if((rc = _var_find_to_set(inst, vid, chIdx, kCfgTFl, var )) == kOkRC ) + rc = _var_set_driver( var, kCfgTFl, val ); + + return rc; +} + + const cw::flow::preset_t* cw::flow::class_preset_find( class_desc_t* cd, const char* preset_label ) { const preset_t* pr; diff --git a/cwFlowTypes.h b/cwFlowTypes.h index a0ae0c7..3116516 100644 --- a/cwFlowTypes.h +++ b/cwFlowTypes.h @@ -40,11 +40,11 @@ namespace cw unsigned* maxBinN_V; // max value that binN_V[i] is allowed to take unsigned* binN_V; // binN_V[ chN ] count of sample frames per channel unsigned* hopSmpN_V; // hopSmpN_V[ chN ] hop sample count - fd_sample_t** magV; // magV[ chN ][ binN ] - fd_sample_t** phsV; // phsV[ chN ][ binN ] - fd_sample_t** hzV; // hzV[ chN ][ binN ] + fd_sample_t** magV; // magV[ chN ][ binN ] + fd_sample_t** phsV; // phsV[ chN ][ binN ] + fd_sample_t** hzV; // hzV[ chN ][ binN ] bool* readyFlV; // readyFlV[chN] true if this channel is ready to be processed (used to sync. fbuf rate to abuf rate) - fd_sample_t* buf; // memory used by this buffer (or NULL if magV,phsV,hzV point are proxied to another buffer) + fd_sample_t* buf; // memory used by this buffer (or NULL if magV,phsV,hzV point are proxied to another buffer) } fbuf_t; typedef struct mbuf_str @@ -78,6 +78,8 @@ namespace cw kTypeMask = 0x0000ffff, + kRuntimeTFl = 0x80000000 + }; typedef struct mtx_str @@ -92,7 +94,8 @@ namespace cw typedef struct value_str { - unsigned flags; + unsigned tflag; + union { bool b; uint_t u; @@ -108,6 +111,7 @@ namespace cw char* s; const object_t* cfg; + void* p; } u; @@ -116,8 +120,9 @@ namespace cw } value_t; - inline bool is_numeric( const value_t* v ) { return cwIsFlag(v->flags,kBoolTFl|kUIntTFl|kIntTFl|kFloatTFl|kDoubleTFl); } - inline bool is_matrix( const value_t* v ) { return cwIsFlag(v->flags,kBoolMtxTFl|kUIntMtxTFl|kIntMtxTFl|kFloatMtxTFl|kDoubleMtxTFl); } + inline void set_null( value_t& v, unsigned tflag ) { v.tflag=tflag; v.u.p=nullptr; } + inline bool is_numeric( const value_t* v ) { return cwIsFlag(v->tflag,kBoolTFl|kUIntTFl|kIntTFl|kFloatTFl|kDoubleTFl); } + inline bool is_matrix( const value_t* v ) { return cwIsFlag(v->tflag,kBoolMtxTFl|kUIntMtxTFl|kIntMtxTFl|kFloatMtxTFl|kDoubleMtxTFl); } struct instance_str; struct variable_str; @@ -170,24 +175,40 @@ namespace cw unsigned polyLimitN; // max. poly copies of this class per network_t or 0 if no limit } class_desc_t; + enum { + kInvalidVarFl = 0x00, + kLogVarFl = 0x01 + }; // Note: The concatenation of 'vid' and 'chIdx' should form a unique identifier among all variables // on a given 'instance'. typedef struct variable_str { struct instance_str* inst; // pointer to this variables instance + char* label; // this variables label - unsigned label_sfx_id; // the label suffix id of this variable or kInvalidIdx if this has no suffix - unsigned vid; // this variables numeric id ( cat(vid,chIdx) forms a unique variable identifier on this 'inst' - var_desc_t* varDesc; // the variable description for this variable - value_t local_value[ kLocalValueN ]; // the local value instance (actual value if this is not a 'src' variable) - unsigned local_value_idx; // local_value[] is double buffered to allow the cur value of the buf[] to be held while the next value is validated (see _var_set_template()) - value_t* value; // pointer to the value associated with this variable + unsigned label_sfx_id; // the label suffix id of this variable or kInvalidIdx if this has no suffix + unsigned vid; // this variables numeric id ( cat(vid,chIdx) forms a unique variable identifier on this 'inst' unsigned chIdx; // channel index - struct variable_str* src_var; // pointer to this input variables source link (or null if it uses the local_value) - struct variable_str* var_link; // instance.varL link list - struct variable_str* connect_link; // list of outgoing connections + unsigned flags; // kLogVarFl + unsigned type; // This is the value type as established when the var is initialized - it never changes for the life of the var. + + var_desc_t* classVarDesc; // pointer to this variables class var desc + var_desc_t* localVarDesc; // pointer to this variables local var desc - if it doesn't match classVarDesc. + var_desc_t* varDesc; // the effective variable description for this variable (set to classVarDesc or localVarDesc) + + value_t local_value[ kLocalValueN ]; // the local value instance (actual value if this is not a 'src' variable) + unsigned local_value_idx; // local_value[] is double buffered to allow the cur value of the buf[] to be held while the next value is validated (see _var_set_template()) + struct variable_str* src_var; // pointer to this input variables source link (or null if it uses the local_value) + value_t* value; // pointer to the value associated with this variable + + struct variable_str* var_link; // instance.varL list link struct variable_str* ch_link; // list of channels that share this variable (rooted on 'any' channel - in order by channel number) + + struct variable_str* dst_head; // Pointer to list of out-going connections (null on var's that do not have out-going connections) + struct variable_str* dst_tail; // + struct variable_str* dst_link; // Link used by dst_head list. + } variable_t; @@ -277,11 +298,13 @@ namespace cw void mbuf_destroy( mbuf_t*& buf ); mbuf_t* mbuf_duplicate( const mbuf_t* src ); - inline bool value_is_abuf( const value_t* v ) { return v->flags & kABufTFl; } - inline bool value_is_fbuf( const value_t* v ) { return v->flags & kFBufTFl; } + inline bool value_is_abuf( const value_t* v ) { return v->tflag & kABufTFl; } + inline bool value_is_fbuf( const value_t* v ) { return v->tflag & kFBufTFl; } unsigned value_type_label_to_flag( const char* type_desc ); - + const char* value_type_flag_to_label( unsigned flag ); + + //------------------------------------------------------------------------------------------------------------------------ // // Class and Variable Description @@ -305,6 +328,8 @@ namespace cw // // Instance // + + rc_t instance_validate( instance_t* inst ); instance_t* instance_find( network_t& net, const char* inst_label, unsigned sfx_id ); rc_t instance_find( network_t& net, const char* inst_label, unsigned sfx_id, instance_t*& instPtrRef ); @@ -313,6 +338,9 @@ namespace cw void instance_print( instance_t* inst ); + // Count of all var instances on this proc. This is a count of the length of inst->varL. + unsigned instance_var_count( instance_t* inst ); + //------------------------------------------------------------------------------------------------------------------------ @@ -321,13 +349,26 @@ namespace cw // // Create a variable but do not assign it a value. Return a pointer to the new variable. - // Note: `value_cfg` is optional. Set it to NULL to ignore - rc_t var_create( instance_t* inst, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef ); + // Notes: + // 1) `value_cfg` is optional. Set it to NULL to ignore + // 2) If `altTypeFl` is not set to kInvalidTFl then the var is assigned this type. + rc_t var_create( instance_t* inst, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, const object_t* value_cfg, unsigned altTypeFlag, variable_t*& varRef ); // Channelizing creates a new var record with an explicit channel index to replace the // automatically generated variable whose channel index is set to 'all'. rc_t var_channelize( instance_t* inst, const char* var_label, unsigned sfx_id, unsigned chIdx, const object_t* value_cfg, unsigned vid, variable_t*& varRef ); + // Set the var. type at runtime. + //rc_t var_set_type( instance_t* inst, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned type_flags ); + + // Wrapper around call to var->inst->members->value() + rc_t var_call_custom_value_func( variable_t* var ); + + // Sets and get the var->flags field + unsigned var_flags( instance_t* inst, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned& flags_ref ); + rc_t var_set_flags( instance_t* inst, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned flags ); + rc_t var_clr_flags( instance_t* inst, unsigned chIdx, const char* var_label, unsigned sfx_id, unsigned flags ); + // `value_cfg` is optional. Set it to NULL to ignore rc_t var_register( instance_t* inst, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, const object_t* value_cfg, variable_t*& varRef ); @@ -336,8 +377,9 @@ namespace cw // Return true if this var is acting as a source for another var. bool is_a_source_var( const variable_t* var ); - - + + rc_t var_mult_sfx_id_array( instance_t* inst, const char* var_label, unsigned* idA, unsigned idAllocN, unsigned& idN_ref ); + //----------------- // // var_register @@ -461,18 +503,19 @@ namespace cw rc_t var_channel_count( const variable_t* var, unsigned& chCntRef ); - rc_t var_get( const variable_t* var, bool& valRef ); - rc_t var_get( const variable_t* var, uint_t& valRef ); - rc_t var_get( const variable_t* var, int_t& valRef ); - rc_t var_get( const variable_t* var, float& valRef ); - rc_t var_get( const variable_t* var, double& valRef ); - rc_t var_get( const variable_t* var, const char*& valRef ); - rc_t var_get( const variable_t* var, const abuf_t*& valRef ); - rc_t var_get( variable_t* var, abuf_t*& valRef ); - rc_t var_get( const variable_t* var, const fbuf_t*& valRef ); - rc_t var_get( variable_t* var, fbuf_t*& valRef ); - rc_t var_get( const variable_t* var, const mbuf_t*& valRef ); - rc_t var_get( variable_t* var, mbuf_t*& valRef ); + rc_t var_get( const variable_t* var, bool& valRef ); + rc_t var_get( const variable_t* var, uint_t& valRef ); + rc_t var_get( const variable_t* var, int_t& valRef ); + rc_t var_get( const variable_t* var, float& valRef ); + rc_t var_get( const variable_t* var, double& valRef ); + rc_t var_get( const variable_t* var, const char*& valRef ); + rc_t var_get( const variable_t* var, const abuf_t*& valRef ); + rc_t var_get( variable_t* var, abuf_t*& valRef ); + rc_t var_get( const variable_t* var, const fbuf_t*& valRef ); + rc_t var_get( variable_t* var, fbuf_t*& valRef ); + rc_t var_get( const variable_t* var, const mbuf_t*& valRef ); + rc_t var_get( variable_t* var, mbuf_t*& valRef ); + rc_t var_get( const variable_t* var, const object_t*& valRef ); template< typename T> rc_t var_get( instance_t* inst, unsigned vid, unsigned chIdx, T& valRef) @@ -494,14 +537,28 @@ namespace cw return value; } - rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, bool val ); - rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, uint_t val ); - rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, int_t val ); - rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, float val ); - rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, double val ); - rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, const char* val ); - rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, abuf_t* val ); - rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, fbuf_t* val ); + rc_t var_set( variable_t* var, const value_t* val ); + rc_t var_set( variable_t* var, bool val ); + rc_t var_set( variable_t* var, uint_t val ); + rc_t var_set( variable_t* var, int_t val ); + rc_t var_set( variable_t* var, float val ); + rc_t var_set( variable_t* var, double val ); + rc_t var_set( variable_t* var, const char* val ); + rc_t var_set( variable_t* var, abuf_t* val ); + rc_t var_set( variable_t* var, fbuf_t* val ); + rc_t var_set( variable_t* var, mbuf_t* val ); + rc_t var_set( variable_t* var, const object_t* val ); + + rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, const value_t* val ); + rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, bool val ); + rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, uint_t val ); + rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, int_t val ); + rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, float val ); + rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, double val ); + rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, const char* val ); + rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, abuf_t* val ); + rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, fbuf_t* val ); + rc_t var_set( instance_t* inst, unsigned vid, unsigned chIdx, const object_t* val ); const preset_t* class_preset_find( class_desc_t* cd, const char* preset_label ); diff --git a/flow/flow_doc.md b/flow/flow_doc.md index 45eac60..798f8bc 100644 --- a/flow/flow_doc.md +++ b/flow/flow_doc.md @@ -23,7 +23,32 @@ and audio processing networks and the application of network state data. ### Polyphonic Network. -3. Network with sub-nets. +### Network with sub-nets. + +## Proc Instance Syntax: + +``` +