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: + +``` +