From e86451b7a27fda5a7163312557fd0addd44e64f1 Mon Sep 17 00:00:00 2001 From: kevin Date: Sun, 5 May 2024 17:31:42 -0400 Subject: [PATCH] cwFlow,cwFlowNet,cwFlowTypes,cwFlowProc : Initial working subnet. --- cwFlow.cpp | 392 ++++++++++++++++++++++++++++++++++++++++++++---- cwFlow.h | 11 +- cwFlowCross.cpp | 2 +- cwFlowNet.cpp | 158 +++++++++++++++++-- cwFlowNet.h | 7 +- cwFlowProc.cpp | 88 ++++++++++- cwFlowProc.h | 1 + cwFlowTypes.cpp | 52 ++++--- cwFlowTypes.h | 35 +++-- cwIoFlow.cpp | 1 - 10 files changed, 661 insertions(+), 86 deletions(-) diff --git a/cwFlow.cpp b/cwFlow.cpp index 16e0f73..c846b76 100644 --- a/cwFlow.cpp +++ b/cwFlow.cpp @@ -29,6 +29,7 @@ namespace cw } library_t; library_t g_library[] = { + { "subnet", &subnet::members }, { "poly", &poly::members }, { "midi_in", &midi_in::members }, { "midi_out", &midi_out::members }, @@ -175,7 +176,7 @@ namespace cw // get the class member functions if((cd->members = _find_library_record(cd->label)) == nullptr ) { - rc = cwLogError(kSyntaxErrorRC,"The '%s' class member function record could not be found..", cd->label ); + rc = cwLogError(kSyntaxErrorRC,"The '%s' class member function record could not be found.", cd->label ); goto errLabel; } @@ -243,21 +244,319 @@ namespace cw return rc; } + rc_t _find_subnet_proc_class_desc( flow_t* p, const object_t* subnetProcD, const char* procInstLabel, const class_desc_t*& class_desc_ref ) + { + rc_t rc = kOkRC; + const object_t* procInstD = nullptr; + const object_t* classStr = nullptr; + const class_desc_t* class_desc = nullptr; + const char* class_label = nullptr; + class_desc_ref = nullptr; + + // find the proc inst dict in the subnet + if((procInstD = subnetProcD->find_child(procInstLabel)) == nullptr ) + { + rc = cwLogError(kSyntaxErrorRC,"The proc instance '%s' from the proxy var list could not be foud in the subnet.",cwStringNullGuard(procInstLabel)); + goto errLabel; + } + + // find the proc class label of the proc inst + if((classStr = procInstD->find_child("class")) == nullptr || (rc = classStr->value(class_label))!=kOkRC) + { + rc = cwLogError(kSyntaxErrorRC,"The 'class' field could not be found in the '%s' proc instance record.", cwStringNullGuard(procInstLabel)); + goto errLabel; + } + + // find the associated class desc record + if((class_desc_ref = class_desc_find(p,class_label)) == nullptr) + { + rc = cwLogError(kEleNotFoundRC,"The class desc record '%s' for the proc instance '%s' could not be found.",class_label,cwStringNullGuard(procInstLabel)); + goto errLabel; + } + + errLabel: + + return rc; + } + + + rc_t _parse_subnet_var_proxy_string( const char* proxyStr, char*& procLabel_ref, char*& varLabel_ref ) + { + rc_t rc = kOkRC; + procLabel_ref = nullptr; + varLabel_ref = nullptr; + + const char* period; + + // find the separating period + if((period = firstMatchChar(proxyStr,'.')) == nullptr ) + { + rc = cwLogError(kSyntaxErrorRC,"The separating '.' could not be found in the proxy string '%s'.",cwStringNullGuard(proxyStr)); + goto errLabel; + } + + // validate the length of the proc inst label + if( period-proxyStr == 0 ) + { + rc = cwLogError(kSyntaxErrorRC,"No proxy proc instance was found in the proxy string '%s'.",cwStringNullGuard(proxyStr)); + goto errLabel; + } + + // validate the length of the var label + if( textLength(period+1) == 0 ) + { + rc = cwLogError(kSyntaxErrorRC,"No proxy var was found in the proxy string '%s'.",cwStringNullGuard(proxyStr)); + goto errLabel; + } + + + procLabel_ref = mem::duplStr(proxyStr,period-proxyStr); + varLabel_ref = mem::duplStr(period+1); + + errLabel: + return rc; + } + + void _var_desc_release( var_desc_t*& vd ) + { + mem::release(vd->proxyProcLabel); + mem::release(vd->proxyVarLabel); + mem::release(vd); + } + + rc_t _create_subnet_var_desc( flow_t* p, class_desc_t* wrapProcClassDesc, const object_t* subnetProcD, const object_t* varDescPair, var_desc_t*& vd_ref ) + { + rc_t rc = kOkRC; + const object_t* flagsCfg = nullptr; + const char* proxyStr = nullptr; + const char* docStr = nullptr; + const char* varLabel = nullptr; + char* proxyProcLabel = nullptr; + char* proxyVarLabel = nullptr; + unsigned proxyVarFlags = 0; + const class_desc_t* proxy_class_desc = nullptr; + const var_desc_t* proxy_var_desc = nullptr; + bool subnetOutVarFl = false; + var_desc_t* var_desc = mem::allocZ(); + + vd_ref = nullptr; + + // verify that the var label is valid + if(!varDescPair->is_pair() || (varLabel=varDescPair->pair_label())==nullptr || varDescPair->pair_value()==nullptr || !varDescPair->pair_value()->is_dict() ) + { + rc = cwLogError(kSyntaxErrorRC,"The proxy var entry is not valid."); + goto errLabel; + } + + // parse the var desc dictionary + if((rc = varDescPair->pair_value()->getv("proxy",proxyStr, + "doc", docStr)) != kOkRC ) + { + rc = cwLogError(rc,"Parsing failed on the proxy var dictionary."); + goto errLabel; + } + + // parse the var desc dictionary optional fields + if((rc = varDescPair->pair_value()->getv_opt("flags", flagsCfg)) != kOkRC ) + { + rc = cwLogError(rc,"Optional attribute parsing failed on the proxy var dictionary."); + goto errLabel; + } + + // parse the proxy string into it's two parts: . + if((rc = _parse_subnet_var_proxy_string( proxyStr, proxyProcLabel, proxyVarLabel )) != kOkRC ) + { + goto errLabel; + } + + // locate the class desc associated with proxy proc + if((rc = _find_subnet_proc_class_desc( p, subnetProcD, proxyProcLabel, proxy_class_desc )) != kOkRC ) + { + goto errLabel; + } + + // locate the var desc associated with the proxy proc var + if((proxy_var_desc = var_desc_find( proxy_class_desc, proxyVarLabel)) == nullptr ) + { + rc = cwLogError(kEleNotFoundRC,"The variable desc '%s.%s' could not be found.",cwStringNullGuard(proxyProcLabel),cwStringNullGuard(proxyVarLabel)); + goto errLabel; + } + + // most of the fields for the proxy are taken directly from the the actual var ... + *var_desc = *proxy_var_desc; + + var_desc->label = varLabel; // ... but the label and doc are overwritten from subnet desc. + var_desc->docText = docStr; + var_desc->proxyProcLabel = proxyProcLabel; + var_desc->proxyVarLabel = proxyVarLabel; + var_desc->link = nullptr; + + if((rc = _is_var_flag_set( flagsCfg, "out", wrapProcClassDesc->label, var_desc->label, subnetOutVarFl )) != kOkRC ) + goto errLabel; + + var_desc->flags = cwEnaFlag(var_desc->flags, kSubnetOutVarFl, subnetOutVarFl); + + vd_ref = var_desc; + + errLabel: + + if( rc != kOkRC ) + { + rc = cwLogError(rc,"The creation of proxy var '%s' failed.",cwStringNullGuard(varLabel)); + _var_desc_release(var_desc); + } + + return rc; + } - rc_t _destroy( flow_t* p) + rc_t _parse_subnet_vars( flow_t* p, class_desc_t* class_desc, const object_t* subnetProcD, const object_t* varD ) { rc_t rc = kOkRC; - if( p == nullptr ) - return rc; - - network_destroy(p->net); + unsigned varN = 0; - // release the class records - for(unsigned i=0; iclassDescN; ++i) + if( !varD->is_dict() ) { - class_desc_t* cd = p->classDescA + i; + rc = cwLogError(kSyntaxErrorRC,"The proxy variable dictionary is invalid."); + goto errLabel; + } + + varN = varD->child_count(); + + // Fill the class_Desc.varDescL list from the subnet 'vars' dictioanry + for(unsigned i=0; ichild_ele(i); + var_desc_t* var_desc = nullptr; + + if((rc = _create_subnet_var_desc( p, class_desc, subnetProcD, child_pair, var_desc )) != kOkRC ) + goto errLabel; + + + var_desc->link = class_desc->varDescL; + class_desc->varDescL = var_desc; + + //printf("Wrapper var-desc created: %i of %i : %s:%s proxy:%s:%s flags:%i.\n", i, varN, class_desc->label, var_desc->label, var_desc->proxyProcLabel,var_desc->proxyVarLabel,var_desc->flags); + + } + + errLabel: + return rc; + } + + rc_t _create_subnet_class_desc( flow_t* p, const object_t* class_obj, class_desc_t* class_desc ) + { + rc_t rc = kOkRC; + const object_t* varD = nullptr; + const object_t* subnetD = nullptr; + const object_t* subnetProcD = nullptr; + const object_t* subnetPresetD = nullptr; + const char* subnetProcDescLabel = nullptr; + + // Validate the subnet proc desc label and value + if( class_obj==nullptr || !class_obj->is_pair() || class_obj->pair_value()==nullptr || !class_obj->pair_value()->is_dict() || (subnetProcDescLabel = class_obj->pair_label()) == nullptr ) + { + rc = cwLogError(kInvalidArgRC,"An invalid subnet description '%s' was encountered.",cwStringNullGuard(subnetProcDescLabel)); + goto errLabel; + } + + // verify that another subnet with the same name does not already exist + if( class_desc_find(p,subnetProcDescLabel) != nullptr ) + { + rc = cwLogError(kInvalidStateRC,"A subnet named '%s' already exists.",subnetProcDescLabel); + goto errLabel; + } + + class_desc->cfg = class_obj->pair_value(); + class_desc->label = class_obj->pair_label(); + + // get the 'subnet' members record + if((class_desc->members = _find_library_record("subnet")) == nullptr ) + { + rc = cwLogError(kSyntaxErrorRC,"The 'subnet' class member function record could not be found." ); + goto errLabel; + } + + // get the variable description + if((rc = class_desc->cfg->getv_opt("vars", varD, + "network", subnetD)) != kOkRC ) + { + rc = cwLogError(rc,"Parse failed while parsing subnet desc:'%s'", cwStringNullGuard(class_desc->label) ); + goto errLabel; + } + + // get the subnet proc and preset dictionaries + if((rc = subnetD->getv("procs", subnetProcD, + "presets", subnetPresetD)) != kOkRC ) + { + rc = cwLogError(rc,"Parse failed on the 'network' element."); + goto errLabel; + } + + // fill class_desc.varDescL from the subnet vars dictionary + if((rc = _parse_subnet_vars( p, class_desc, subnetProcD, varD )) != kOkRC ) + { + rc = cwLogError(rc,"Subnet 'vars' processing failed."); + goto errLabel; + } + + + errLabel: + if(rc != kOkRC ) + rc = cwLogError(rc,"'proc' class description creation failed for the subnet '%s'. ",cwStringNullGuard(subnetProcDescLabel)); + + return rc; + } + + + rc_t _parse_subnet_cfg(flow_t* p, const object_t* subnetCfg) + { + rc_t rc = kOkRC; + + if( !subnetCfg->is_dict() ) + return cwLogError(kSyntaxErrorRC,"The subnet class description dictionary does not have dictionary syntax."); + + unsigned subnetDescN = subnetCfg->child_count(); + p->subnetDescA = mem::allocZ( subnetDescN ); + + // for each subnet description + for(unsigned i=0; ichild_ele(i); + + if((rc = _create_subnet_class_desc(p, subnet_obj, p->subnetDescA + i )) != kOkRC ) + { + rc = cwLogError(rc,"Subnet class description create failed on the subnet at index:%i.",i); + goto errLabel; + } + + // we have to update the size of the subnet class array + // as we go because we may want to find subnets classes within + // subnets which are definted later and so the length p->subnetA[] + // must be correct + p->subnetDescN += 1; + } + + assert( subnetDescN == p->subnetDescN ); + errLabel: + + if( rc != kOkRC ) + { + rc = cwLogError(rc,"Subnet processing failed."); + + } + + return rc; + + } + + void _release_class_desc_array( class_desc_t*& classDescA, unsigned classDescN ) + { + // release the class records + for(unsigned i=0; ivarDescL; @@ -265,7 +564,7 @@ namespace cw while( vd0 != nullptr ) { vd1 = vd0->link; - mem::release(vd0); + _var_desc_release(vd0); vd0 = vd1; } @@ -280,8 +579,20 @@ namespace cw } } - mem::release(p->classDescA); + mem::release(classDescA); + } + + rc_t _destroy( flow_t* p) + { + rc_t rc = kOkRC; + if( p == nullptr ) + return rc; + + network_destroy(p->net); + + _release_class_desc_array(p->classDescA,p->classDescN); + _release_class_desc_array(p->subnetDescA,p->subnetDescN); mem::release(p); @@ -308,8 +619,9 @@ void cw::flow::print_external_device( const external_device_t* dev ) cw::rc_t cw::flow::create( handle_t& hRef, - const object_t& classCfg, - const object_t& flowCfg, + const object_t* classCfg, + const object_t* flowCfg, + const object_t* subnetCfg, external_device_t* deviceA, unsigned deviceN ) { @@ -317,24 +629,32 @@ cw::rc_t cw::flow::create( handle_t& hRef, const object_t* networkCfg = nullptr; bool printClassDictFl = false; bool printNetworkFl = false; + variable_t* proxyVarL = nullptr; if(( rc = destroy(hRef)) != kOkRC ) return rc; flow_t* p = mem::allocZ(); - p->flowCfg = &flowCfg; // TODO: duplicate cfg? + p->flowCfg = flowCfg; // TODO: duplicate cfg? p->deviceA = deviceA; p->deviceN = deviceN; // parse the class description array - if((rc = _parse_class_cfg(p,&classCfg)) != kOkRC ) + if((rc = _parse_class_cfg(p,classCfg)) != kOkRC ) { rc = cwLogError(kSyntaxErrorRC,"Error parsing the class description list."); goto errLabel; } + if( subnetCfg != nullptr ) + if((rc = _parse_subnet_cfg(p,subnetCfg)) != kOkRC ) + { + rc = cwLogError(kSyntaxErrorRC,"Error parsing the subnet list."); + goto errLabel; + } + // parse the main audio file processor cfg record - if((rc = flowCfg.getv("network", networkCfg)) != kOkRC ) + if((rc = flowCfg->getv("network", networkCfg)) != kOkRC ) { rc = cwLogError(kSyntaxErrorRC,"Error parsing the required flow configuration parameters."); goto errLabel; @@ -344,7 +664,7 @@ cw::rc_t cw::flow::create( handle_t& hRef, p->sample_rate = kDefaultSampleRate; // parse the optional args - if((rc = flowCfg.getv_opt("framesPerCycle", p->framesPerCycle, + if((rc = flowCfg->getv_opt("framesPerCycle", p->framesPerCycle, "sample_rate", p->sample_rate, "maxCycleCount", p->maxCycleCount, "multiPriPresetProbFl", p->multiPriPresetProbFl, @@ -375,7 +695,7 @@ cw::rc_t cw::flow::create( handle_t& hRef, class_dict_print( p ); // instantiate the network - if((rc = network_create(p,networkCfg,p->net)) != kOkRC ) + if((rc = network_create(p,networkCfg,p->net,proxyVarL)) != kOkRC ) { rc = cwLogError(rc,"Network creation failed."); goto errLabel; @@ -535,10 +855,12 @@ cw::rc_t cw::flow::test( const object_t* cfg, int argc, const char* argv[] ) rc_t rc = kOkRC; handle_t flowH; - object_t* class_cfg = nullptr; - const object_t* test_cases_cfg = nullptr; - const object_t* test_cfg = nullptr; - const char* flow_proc_fname; + const char* proc_cfg_fname = nullptr; + const char* subnet_cfg_fname = nullptr; + const object_t* test_cases_cfg = nullptr; + object_t* class_cfg = nullptr; + object_t* subnet_cfg = nullptr; + const object_t* test_cfg = nullptr; if( argc < 2 || textLength(argv[1]) == 0 ) { @@ -546,13 +868,20 @@ cw::rc_t cw::flow::test( const object_t* cfg, int argc, const char* argv[] ) goto errLabel; } - if((rc = cfg->getv("flow_proc_fname",flow_proc_fname, - "test_cases",test_cases_cfg)) != kOkRC ) + if((rc = cfg->getv("proc_cfg_fname",proc_cfg_fname, + "test_cases", test_cases_cfg)) != kOkRC ) { rc = cwLogError(rc,"The name of the flow_proc_dict file could not be parsed."); goto errLabel; } + // get the subnet cfg filename + if((rc = cfg->getv_opt("subnet_cfg_fname",subnet_cfg_fname)) != kOkRC ) + { + rc = cwLogError(rc,"The name of the subnet file could not be parsed."); + goto errLabel; + } + // find the user requested test case if((test_cfg = test_cases_cfg->find_child(argv[1])) == nullptr ) { @@ -560,15 +889,22 @@ cw::rc_t cw::flow::test( const object_t* cfg, int argc, const char* argv[] ) goto errLabel; } - // parse the flow-proc-cfg - if((rc = objectFromFile(flow_proc_fname,class_cfg)) != kOkRC ) + // parse the proc dict. file + if((rc = objectFromFile(proc_cfg_fname,class_cfg)) != kOkRC ) { - rc = cwLogError(rc,"The flow proc dict could not be read from '%s'.",cwStringNullGuard(flow_proc_fname)); + rc = cwLogError(rc,"The proc dictionary could not be read from '%s'.",cwStringNullGuard(proc_cfg_fname)); goto errLabel; } + // parse the subnet dict file + if((rc = objectFromFile(subnet_cfg_fname,subnet_cfg)) != kOkRC ) + { + rc = cwLogError(rc,"The subnet dictionary could not be read from '%s'.",cwStringNullGuard(subnet_cfg_fname)); + goto errLabel; + } + // create the flow object - if((rc = create( flowH, *class_cfg, *test_cfg)) != kOkRC ) + if((rc = create( flowH, class_cfg, test_cfg, subnet_cfg)) != kOkRC ) { rc = cwLogError(rc,"Flow object create failed."); goto errLabel; diff --git a/cwFlow.h b/cwFlow.h index 722775a..17fc29b 100644 --- a/cwFlow.h +++ b/cwFlow.h @@ -14,11 +14,12 @@ namespace cw void print_external_device( const external_device_t* dev ); - rc_t create( handle_t& hRef, - const object_t& classCfg, - const object_t& networkCfg, - external_device_t* deviceA = nullptr, - unsigned deviceN = 0); + rc_t create( handle_t& hRef, + const object_t* classCfg, + const object_t* networkCfg, + const object_t* subnetCfg = nullptr, + external_device_t* deviceA = nullptr, + unsigned deviceN = 0); rc_t destroy( handle_t& hRef ); diff --git a/cwFlowCross.cpp b/cwFlowCross.cpp index c47afc7..330ebed 100644 --- a/cwFlowCross.cpp +++ b/cwFlowCross.cpp @@ -146,7 +146,7 @@ namespace cw net->stateId = net_idx == 0 ? kActiveStateId : kInactiveStateId; net->net_idx = net_idx; - if((rc = flow::create( net->flowH, classCfg, networkCfg, net->deviceA, deviceN )) == kOkRC ) + if((rc = flow::create( net->flowH, &classCfg, &networkCfg, nullptr, net->deviceA, deviceN )) == kOkRC ) net->deviceN = deviceN; else { diff --git a/cwFlowNet.cpp b/cwFlowNet.cpp index f0b769a..3fe0ef8 100644 --- a/cwFlowNet.cpp +++ b/cwFlowNet.cpp @@ -1263,8 +1263,16 @@ namespace cw return rc; } + + const variable_t* _find_proxy_var( const char* procInstLabel, const char* varLabel, const variable_t* proxyVarL ) + { + for(const variable_t* proxyVar=proxyVarL; proxyVar!=nullptr; proxyVar=proxyVar->var_link) + if( textIsEqual(proxyVar->varDesc->proxyProcLabel,procInstLabel) && textIsEqual(proxyVar->varDesc->proxyVarLabel,varLabel) ) + return proxyVar; + return nullptr; + } - rc_t _parse_in_list( network_t& net, instance_t* inst, proc_inst_parse_state_t& pstate ) + rc_t _parse_in_list( network_t& net, instance_t* inst, variable_t* proxyVarL, proc_inst_parse_state_t& pstate ) { rc_t rc = kOkRC; @@ -1315,6 +1323,16 @@ namespace cw // create the var if( in_stmt.create_in_fl ) { + const variable_t* proxy_var; + + // a variable cannot be in the 'in' list if it is used a a subnet variable + if((proxy_var = _find_proxy_var(inst->label, in_stmt.in_var_ele.label, proxyVarL)) != nullptr ) + { + rc = cwLogError(kSyntaxErrorRC,"The variable:'%s' cannot be used as the in-var of an 'in' statement if it is a subnet variable: '%s'.",cwStringNullGuard(in_stmt.in_var_ele.label),cwStringNullGuard(proxy_var->label)); + goto errLabel; + } + + for(unsigned i=0; ivar_link ) + { + // if this wrap_var is on this proc (inst->label) + if( textIsEqual(wrap_var->varDesc->proxyProcLabel,inst->label) ) + { + + variable_t* var; + + if((rc = var_create( inst, wrap_var->varDesc->proxyVarLabel, wrap_var->label_sfx_id, kInvalidId, wrap_var->chIdx, nullptr, kInvalidTFl, var )) != kOkRC ) + { + rc = cwLogError(rc,"Subnet variable creation failed for %s:%s on wrapper variable:%s:%s.",cwStringNullGuard(wrap_var->varDesc->proxyProcLabel),cwStringNullGuard(wrap_var->varDesc->proxyVarLabel),cwStringNullGuard(wrap_var->inst->label),cwStringNullGuard(wrap_var->label)); + goto errLabel; + } + + //printf("Proxy matched: %s %s %s : flags:%i.\n",inst->label, wrap_var->varDesc->proxyVarLabel, wrap_var->label,wrap_var->varDesc->flags ); + + var->flags |= kProxiedVarFl; + + if( cwIsFlag(wrap_var->varDesc->flags,kSubnetOutVarFl) ) + var->flags |= kProxiedOutVarFl; + } + } + + errLabel: + return rc; + } + + variable_t* _find_wrap_var( variable_t* wrap_varL, variable_t* var ) + { + for(variable_t* wrap_var=wrap_varL; wrap_var!=nullptr; wrap_var=wrap_var->var_link) + if( textIsEqual(wrap_var->varDesc->proxyProcLabel,var->inst->label) && textIsEqual(wrap_var->varDesc->proxyVarLabel,var->label) && (wrap_var->label_sfx_id==var->label_sfx_id) ) + return wrap_var; + + return nullptr; + } + + rc_t _connect_wrapped_vars( instance_t* inst, variable_t* wrap_varL ) + { + rc_t rc = kOkRC; + for(variable_t* var=inst->varL; var!=nullptr; var=var->var_link) + { + if( cwIsFlag(var->flags,kProxiedVarFl) ) + { + variable_t* wrap_var; + if((wrap_var = _find_wrap_var(wrap_varL,var)) == nullptr ) + { + rc = cwLogError(kEleNotFoundRC,"The wrapped variable '%s:%i' not found on '%s:%i'.",var->label,var->label_sfx_id,inst->label,inst->label_sfx_id); + goto errLabel; + } + + if( cwIsFlag(var->flags,kProxiedOutVarFl) ) + { + //printf("Proxy connection: %i %s:%i-%s:%i -> %s:%i-%s:%i\n",var->flags, + // var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id, + // wrap_var->inst->label,wrap_var->inst->label_sfx_id,wrap_var->label,wrap_var->label_sfx_id ); + + var_connect(var,wrap_var); + } + else + { + //printf("Proxy connection: %i %s:%i-%s:%i -> %s:%i-%s:%i\n",var->flags, + // wrap_var->inst->label,wrap_var->inst->label_sfx_id,wrap_var->label,wrap_var->label_sfx_id, + // var->inst->label,var->inst->label_sfx_id,var->label,var->label_sfx_id ); + + var_connect(wrap_var,var); + } + } + } + + errLabel: + return rc; + } + + + + bool _is_var_inst_already_created( instance_t* inst, const char* var_label, const proc_inst_parse_state_t& pstate ) { for(unsigned i=0; ivarL; var!=nullptr; var=var->var_link) + if( textIsEqual(var->label,var_label) ) + return true; + return false; } @@ -1545,7 +1656,12 @@ namespace cw return n; } - rc_t _create_instance( flow_t* p, const object_t* proc_inst_cfg, unsigned sfx_id, network_t& net, instance_t*& inst_ref ) + rc_t _create_instance( flow_t* p, + const object_t* proc_inst_cfg, + unsigned sfx_id, + network_t& net, + variable_t* proxyVarL, + instance_t*& inst_ref ) { rc_t rc = kOkRC; proc_inst_parse_state_t pstate = {}; @@ -1558,7 +1674,7 @@ namespace cw if((rc = _parse_proc_inst_cfg( net, proc_inst_cfg, sfx_id, pstate )) != kOkRC ) goto errLabel; - // locate the class desc + // locate the proc class desc if(( class_desc = class_desc_find(p,pstate.inst_clas_label)) == nullptr ) { rc = cwLogError(kSyntaxErrorRC,"The flow class '%s' was not found.",cwStringNullGuard(pstate.inst_clas_label)); @@ -1586,15 +1702,22 @@ namespace cw inst->net = &net; // parse the in-list ,fill in pstate.in_array, and create var instances for var's referenced by in-list - if((rc = _parse_in_list( net, inst, pstate )) != kOkRC ) + if((rc = _parse_in_list( net, inst, proxyVarL, pstate )) != kOkRC ) { rc = cwLogError(rc,"in-list parse failed on proc instance '%s:%i'.",cwStringNullGuard(inst->label),sfx_id); goto errLabel; } + // create the vars that are connected to the wrapper proxy vars + if((rc = _create_proxied_vars( inst, proxyVarL )) != kOkRC ) + { + rc = cwLogError(rc,"Proxy vars create failed on proc instance '%s:%i'.",cwStringNullGuard(inst->label),sfx_id); + goto errLabel; + } + // 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 ) && cwIsNotFlag(vd->type,kRuntimeTFl) ) + if( !_is_var_inst_already_created( inst, vd->label, pstate ) && cwIsNotFlag(vd->type,kRuntimeTFl) ) { variable_t* var = nullptr; if((rc = var_create( inst, vd->label, kBaseSfxId, kInvalidId, kAnyChIdx, vd->val_cfg, kInvalidTFl, var )) != kOkRC ) @@ -1632,6 +1755,14 @@ namespace cw goto errLabel; } + // Connect the wrapped vars in this subnet proc + if((rc = _connect_wrapped_vars( inst, proxyVarL )) != kOkRC ) + { + rc = cwLogError(rc,"Wrapped 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. @@ -1924,10 +2055,11 @@ namespace cw } } -cw::rc_t cw::flow::network_create( flow_t* p, - const object_t* networkCfg, - network_t& net, - unsigned polyCnt, +cw::rc_t cw::flow::network_create( flow_t* p, + const object_t* networkCfg, + network_t& net, + variable_t* proxyVarL, + unsigned polyCnt, network_order_id_t orderId ) { rc_t rc = kOkRC; @@ -1956,8 +2088,8 @@ cw::rc_t cw::flow::network_create( flow_t* p, } net.proc_arrayAllocN = polyCnt * net.procsCfg->child_count(); - net.proc_array = mem::allocZ(net.proc_arrayAllocN); - net.proc_arrayN = 0; + net.proc_array = mem::allocZ(net.proc_arrayAllocN); + net.proc_arrayN = 0; for(unsigned i=0; iclass_desc->cfg->getv("network",networkCfg)) != kOkRC ) + { + rc = cwLogError(rc,"The subnet 'network' cfg. was not found."); + goto errLabel; + } + + if((rc = network_create(proc->ctx,networkCfg,p->net,proc->varL)) != kOkRC ) + { + rc = cwLogError(rc,"Creation failed on the subnet internal network."); + goto errLabel; + } + + // Set the internal net pointer in the base proc instance + // so that network based utilities can scan it + proc->internal_net = &p->net; + + errLabel: + return rc; + } + + rc_t _destroy( instance_t* proc, inst_t* p ) + { + rc_t rc = kOkRC; + + network_destroy(p->net); + + return rc; + } + + rc_t _value( instance_t* proc, inst_t* p, variable_t* var ) + { + rc_t rc = kOkRC; + return rc; + } + + rc_t _exec( instance_t* proc, inst_t* p ) + { + rc_t rc = kOkRC; + + if((rc = exec_cycle(p->net)) != kOkRC ) + rc = cwLogError(rc,"poly internal network exec failed."); + + return rc; + } + + rc_t _report( instance_t* proc, inst_t* p ) + { return kOkRC; } + + class_members_t members = { + .create = std_create, + .destroy = std_destroy, + .value = std_value, + .exec = std_exec, + .report = std_report + }; + + } //------------------------------------------------------------------------------------------------------------------ // @@ -147,6 +221,7 @@ namespace cw inst_t* inst = mem::allocZ(); const object_t* networkCfg = nullptr; const char* order_label = nullptr; + variable_t* proxyVarL = nullptr; proc->userPtr = inst; @@ -181,7 +256,7 @@ namespace cw } } - if((rc = network_create(proc->ctx,networkCfg,inst->net,inst->count )) != kOkRC ) + if((rc = network_create(proc->ctx,networkCfg,inst->net,proxyVarL,inst->count)) != kOkRC ) { rc = cwLogError(rc,"Creation failed on the internal network."); goto errLabel; @@ -1003,7 +1078,9 @@ namespace cw inst->durSmpN += src_abuf->frameN; if( src_abuf->srate!=0 && inst->durSmpN % ((unsigned)src_abuf->srate*60) == 0 ) printf("audio file out: %5.1f min\n", inst->durSmpN/(src_abuf->srate*60)); - + + //if( 48000 <= inst->durSmpN && inst->durSmpN < 49000 ) + // printf("break\n"); } return rc; @@ -1785,6 +1862,8 @@ namespace cw if((rc = var_set(ctx,kSratePId,i,srate)) != kOkRC ) goto errLabel; } + + printf("%s: sr:%f hz:%f phs:%f dc:%f gain:%f\n",ctx->label,srate,hz,phase,dc,gain); // create one output audio buffer rc = var_register_and_set( ctx, "out", kBaseSfxId, @@ -1840,7 +1919,10 @@ namespace cw for(unsigned j=0; jframeN; ++j) v[j] = (sample_t)((gain * sin( inst->phaseA[i] + phase + (2.0 * M_PI * j * hz/srate)))+dc); - inst->phaseA[i] += 2.0 * M_PI * abuf->frameN * hz/srate; + inst->phaseA[i] += 2.0 * M_PI * abuf->frameN * hz/srate; + + //if( i==0 ) + // printf("hz:%f gain:%f phs:%f : %f\n",hz,gain,inst->phaseA[i],v[0]); } } diff --git a/cwFlowProc.h b/cwFlowProc.h index 64921e3..daaff15 100644 --- a/cwFlowProc.h +++ b/cwFlowProc.h @@ -2,6 +2,7 @@ namespace cw { namespace flow { + namespace subnet { extern class_members_t members; } namespace poly { extern class_members_t members; } namespace midi_in { extern class_members_t members; } namespace midi_out { extern class_members_t members; } diff --git a/cwFlowTypes.cpp b/cwFlowTypes.cpp index 63f9fbb..a03b1f7 100644 --- a/cwFlowTypes.cpp +++ b/cwFlowTypes.cpp @@ -1093,6 +1093,21 @@ namespace cw return rc; } + void _class_desc_print( const class_desc_t* cd ) + { + const var_desc_t* vd = cd->varDescL; + printf("%s\n",cwStringNullGuard(cd->label)); + + for(; vd!=nullptr; vd=vd->link) + { + const char* srcFlStr = vd->flags & kSrcVarFl ? "src" : " "; + const char* srcOptFlStr = vd->flags & kSrcOptVarFl ? "srcOpt" : " "; + const char* plyMltFlStr = vd->flags & kMultVarFl ? "mult" : " "; + + printf(" %10s 0x%08x %s %s %s %s\n", cwStringNullGuard(vd->label), vd->type, srcFlStr, srcOptFlStr, plyMltFlStr, cwStringNullGuard(vd->docText) ); + } + } + } } @@ -1280,15 +1295,19 @@ const char* cw::flow::value_type_flag_to_label( unsigned flag ) cw::flow::class_desc_t* cw::flow::class_desc_find( flow_t* p, const char* label ) { for(unsigned i=0; iclassDescN; ++i) - if( textCompare(p->classDescA[i].label,label) == 0 ) + if( textIsEqual(p->classDescA[i].label,label)) return p->classDescA + i; + + for(unsigned i=0; isubnetDescN; ++i) + if( textIsEqual(p->subnetDescA[i].label,label)) + return p->subnetDescA + i; + return nullptr; } - -cw::flow::var_desc_t* cw::flow::var_desc_find( class_desc_t* cd, const char* label ) +const cw::flow::var_desc_t* cw::flow::var_desc_find( const class_desc_t* cd, const char* label ) { - var_desc_t* vd = cd->varDescL; + const var_desc_t* vd = cd->varDescL; for(; vd != nullptr; vd=vd->link ) if( textCompare(vd->label,label) == 0 ) @@ -1296,6 +1315,11 @@ cw::flow::var_desc_t* cw::flow::var_desc_find( class_desc_t* cd, const char* lab return nullptr; } +cw::flow::var_desc_t* cw::flow::var_desc_find( class_desc_t* cd, const char* label ) +{ + return (var_desc_t*)var_desc_find( (const class_desc_t*)cd, label); +} + cw::rc_t cw::flow::var_desc_find( class_desc_t* cd, const char* label, var_desc_t*& vdRef ) { if((vdRef = var_desc_find(cd,label)) == nullptr ) @@ -1303,7 +1327,7 @@ cw::rc_t cw::flow::var_desc_find( class_desc_t* cd, const char* label, var_desc_ return kOkRC; } -const cw::flow::preset_t* cw::flow::class_preset_find( class_desc_t* cd, const char* preset_label ) +const cw::flow::preset_t* cw::flow::class_preset_find( const class_desc_t* cd, const char* preset_label ) { const preset_t* pr; for(pr=cd->presetL; pr!=nullptr; pr=pr->link) @@ -1316,20 +1340,10 @@ const cw::flow::preset_t* cw::flow::class_preset_find( class_desc_t* cd, const c void cw::flow::class_dict_print( flow_t* p ) { for(unsigned i=0; iclassDescN; ++i) - { - class_desc_t* cd = p->classDescA + i; - var_desc_t* vd = cd->varDescL; - printf("%s\n",cwStringNullGuard(cd->label)); - - for(; vd!=nullptr; vd=vd->link) - { - const char* srcFlStr = vd->flags & kSrcVarFl ? "src" : " "; - const char* srcOptFlStr = vd->flags & kSrcOptVarFl ? "srcOpt" : " "; - const char* plyMltFlStr = vd->flags & kMultVarFl ? "mult" : " "; - - printf(" %10s 0x%08x %s %s %s %s\n", cwStringNullGuard(vd->label), vd->type, srcFlStr, srcOptFlStr, plyMltFlStr, cwStringNullGuard(vd->docText) ); - } - } + _class_desc_print(p->classDescA+i); + + for(unsigned i=0; isubnetDescN; ++i) + _class_desc_print(p->subnetDescA+i); } diff --git a/cwFlowTypes.h b/cwFlowTypes.h index d207e0d..4fd0af6 100644 --- a/cwFlowTypes.h +++ b/cwFlowTypes.h @@ -25,7 +25,6 @@ namespace cw typedef struct abuf_str { - struct value_str* base; srate_t srate; // signal sample rate unsigned chN; // count of channels unsigned frameN; // count of sample frames per channel @@ -35,7 +34,6 @@ namespace cw typedef struct fbuf_str { - struct value_str* base; srate_t srate; // signal sample rate unsigned flags; // See kXXXFbufFl unsigned chN; // count of channels @@ -51,7 +49,6 @@ namespace cw typedef struct mbuf_str { - struct value_str* base; const midi::ch_msg_t* msgA; unsigned msgN; } mbuf_t; @@ -136,7 +133,8 @@ namespace cw kNoVarFl = 0x00, kSrcVarFl = 0x01, kSrcOptVarFl = 0x02, - kMultVarFl = 0x04 + kMultVarFl = 0x04, + kSubnetOutVarFl = 0x08 }; typedef struct class_members_str @@ -156,6 +154,10 @@ namespace cw unsigned type; // Value type id (e.g. kBoolTFl, kIntTFl, ...) unsigned flags; // Attributes for this var. (e.g. kSrcVarFl ) const char* docText; // User help string for this var. + + char* proxyProcLabel; + char* proxyVarLabel; + struct var_desc_str* link; // class_desc->varDescL list link } var_desc_t; @@ -168,17 +170,19 @@ namespace cw typedef struct class_desc_str { - const object_t* cfg; // + const object_t* cfg; // class cfg const char* label; // class label; - var_desc_t* varDescL; // varDescA[varDescN] value description list + var_desc_t* varDescL; // varDescL variable description linked on var_desc_t.link preset_t* presetL; // presetA[ presetN ] class_members_t* members; // member functions for this class unsigned polyLimitN; // max. poly copies of this class per network_t or 0 if no limit } class_desc_t; enum { - kInvalidVarFl = 0x00, - kLogVarFl = 0x01 + kInvalidVarFl = 0x00, + kLogVarFl = 0x01, + kProxiedVarFl = 0x02, + kProxiedOutVarFl = 0x04 }; // Note: The concatenation of 'vid' and 'chIdx' should form a unique identifier among all variables @@ -274,6 +278,10 @@ namespace cw class_desc_t* classDescA; // unsigned classDescN; // + class_desc_t* subnetDescA; // + unsigned subnetDescN; // + + external_device_t* deviceA; // deviceA[ deviceN ] external device description array unsigned deviceN; // @@ -321,14 +329,15 @@ namespace cw // Class and Variable Description // - class_desc_t* class_desc_find( flow_t* p, const char* class_desc_label ); + class_desc_t* class_desc_find( flow_t* p, const char* class_desc_label ); - var_desc_t* var_desc_find( class_desc_t* cd, const char* var_label ); - rc_t var_desc_find( class_desc_t* cd, const char* label, var_desc_t*& vdRef ); + var_desc_t* var_desc_find( class_desc_t* cd, const char* var_label ); + const var_desc_t* var_desc_find( const class_desc_t* cd, const char* var_label ); + rc_t var_desc_find( class_desc_t* cd, const char* var_label, var_desc_t*& vdRef ); - const preset_t* class_preset_find( class_desc_t* cd, const char* preset_label ); + const preset_t* class_preset_find( const class_desc_t* cd, const char* preset_label ); - void class_dict_print( flow_t* p ); + void class_dict_print( flow_t* p ); //------------------------------------------------------------------------------------------------------------------------ diff --git a/cwIoFlow.cpp b/cwIoFlow.cpp index 2ac38b1..57402ec 100644 --- a/cwIoFlow.cpp +++ b/cwIoFlow.cpp @@ -114,7 +114,6 @@ namespace cw { dev->ioDevIdx = ioDevIdx; dev->ioDevId = audioDeviceUserId( p->ioH, ioDevIdx ); - dev->abuf.base = nullptr; dev->abuf.srate = audioDeviceSampleRate( p->ioH, ioDevIdx ); dev->abuf.chN = audioDeviceChannelCount( p->ioH, ioDevIdx, inOrOutFl ); dev->abuf.frameN = dspFrameCnt;