2021-08-15 20:07:12 +00:00
# include "cwCommon.h"
# include "cwLog.h"
# include "cwCommonImpl.h"
# include "cwMem.h"
# include "cwText.h"
2024-04-22 20:02:40 +00:00
# include "cwNumericConvert.h"
2021-08-15 20:07:12 +00:00
# include "cwObject.h"
2024-04-22 20:02:40 +00:00
2021-08-15 20:07:12 +00:00
# include "cwAudioFile.h"
# include "cwVectOps.h"
# include "cwMtx.h"
2024-04-26 21:05:48 +00:00
# include "cwDspTypes.h" // coeff_t, sample_t, srate_t ...
2024-04-06 20:07:46 +00:00
# include "cwTime.h"
# include "cwMidiDecls.h"
2024-01-13 15:16:37 +00:00
# include "cwFlowDecl.h"
2021-08-15 20:07:12 +00:00
# include "cwFlow.h"
# include "cwFlowTypes.h"
2024-04-22 20:02:40 +00:00
# include "cwFlowNet.h"
2021-08-15 20:07:12 +00:00
# include "cwFlowProc.h"
namespace cw
{
namespace flow
{
typedef struct library_str
{
const char * label ;
class_members_t * members ;
} library_t ;
2024-03-25 14:46:45 +00:00
library_t g_library [ ] = {
2024-04-22 20:02:40 +00:00
{ " poly " , & poly : : members } ,
2024-04-06 20:07:46 +00:00
{ " midi_in " , & midi_in : : members } ,
{ " midi_out " , & midi_out : : members } ,
2021-12-28 01:25:18 +00:00
{ " audio_in " , & audio_in : : members } ,
{ " audio_out " , & audio_out : : members } ,
2024-04-30 23:58:10 +00:00
{ " audio_file_in " , & audio_file_in : : members } ,
{ " audio_file_out " , & audio_file_out : : members } ,
2021-12-28 01:25:18 +00:00
{ " audio_gain " , & audio_gain : : members } ,
{ " audio_split " , & audio_split : : members } ,
{ " audio_duplicate " , & audio_duplicate : : members } ,
{ " audio_merge " , & audio_merge : : members } ,
{ " audio_mix " , & audio_mix : : members } ,
{ " sine_tone " , & sine_tone : : members } ,
{ " pv_analysis " , & pv_analysis : : members } ,
{ " pv_synthesis " , & pv_synthesis : : members } ,
{ " spec_dist " , & spec_dist : : members } ,
{ " compressor " , & compressor : : members } ,
2022-12-05 22:21:54 +00:00
{ " limiter " , & limiter : : members } ,
2021-12-28 01:25:18 +00:00
{ " audio_delay " , & audio_delay : : members } ,
2022-12-05 22:21:54 +00:00
{ " dc_filter " , & dc_filter : : members } ,
2021-12-28 01:25:18 +00:00
{ " balance " , & balance : : members } ,
2023-01-05 12:26:25 +00:00
{ " audio_meter " , & audio_meter : : members } ,
2023-02-26 18:43:14 +00:00
{ " audio_marker " , & audio_marker : : members } ,
2024-04-22 20:02:40 +00:00
{ " xfade_ctl " , & xfade_ctl : : members } ,
{ " poly_mixer " , & poly_mixer : : members } ,
2024-04-26 21:05:48 +00:00
{ " sample_hold " , & sample_hold : : members } ,
{ " number " , & number : : members } ,
{ " timer " , & timer : : members } ,
{ " counter " , & counter : : members } ,
2024-04-30 23:58:10 +00:00
{ " list " , & list : : members } ,
{ " add " , & add : : members } ,
{ " preset " , & preset : : members } ,
2021-08-15 20:07:12 +00:00
{ nullptr , nullptr }
} ;
class_members_t * _find_library_record ( const char * label )
{
2024-03-25 14:46:45 +00:00
for ( library_t * l = g_library ; l - > label ! = nullptr ; + + l )
2021-08-15 20:07:12 +00:00
if ( textCompare ( l - > label , label ) = = 0 )
return l - > members ;
return nullptr ;
}
flow_t * _handleToPtr ( handle_t h )
{ return handleToPtr < handle_t , flow_t > ( h ) ; }
2022-12-17 13:16:21 +00:00
rc_t _is_var_flag_set ( const object_t * var_flags_obj , const char * flag_label , const char * classLabel , const char * varLabel , bool & is_set_flag_ref )
{
rc_t rc = kOkRC ;
is_set_flag_ref = false ;
if ( var_flags_obj ! = nullptr )
{
for ( unsigned k = 0 ; k < var_flags_obj - > child_count ( ) ; + + k )
{
const object_t * tag_obj = var_flags_obj - > child_ele ( k ) ;
const char * tag = nullptr ;
if ( tag_obj ! = nullptr & & tag_obj - > is_string ( ) & & ( rc = tag_obj - > value ( tag ) ) = = kOkRC & & tag ! = nullptr )
{
if ( strcmp ( tag , flag_label ) = = 0 )
is_set_flag_ref = true ;
}
else
{
rc = cwLogError ( kSyntaxErrorRC , " An invalid or non-string value was found in a flow class '%s' variable:'%s' 'flags' field. " , classLabel , varLabel ) ;
}
}
}
return rc ;
}
2024-03-25 14:46:45 +00:00
rc_t _parse_class_cfg ( flow_t * p , const object_t * classCfg )
2021-08-15 20:07:12 +00:00
{
rc_t rc = kOkRC ;
if ( ! classCfg - > is_dict ( ) )
return cwLogError ( kSyntaxErrorRC , " The class description dictionary does not have dictionary syntax. " ) ;
p - > classDescN = classCfg - > child_count ( ) ;
p - > classDescA = mem : : allocZ < class_desc_t > ( p - > classDescN ) ;
// for each class description
for ( unsigned i = 0 ; i < p - > classDescN ; + + i )
{
const object_t * class_obj = classCfg - > child_ele ( i ) ;
const object_t * varD = nullptr ;
const object_t * presetD = nullptr ;
class_desc_t * cd = p - > classDescA + i ;
cd - > cfg = class_obj - > pair_value ( ) ;
cd - > label = class_obj - > pair_label ( ) ;
// get the variable description
if ( ( rc = cd - > cfg - > getv_opt ( " vars " , varD ,
2024-04-22 20:02:40 +00:00
" presets " , presetD ,
" poly_limit_cnt " , cd - > polyLimitN ) ) ! = kOkRC )
2021-08-15 20:07:12 +00:00
{
rc = cwLogError ( rc , " Parsing failed while parsing class desc:'%s' " , cwStringNullGuard ( cd - > label ) ) ;
goto errLabel ;
}
// parse the preset dictionary
if ( presetD ! = nullptr )
{
if ( ! presetD - > is_dict ( ) )
{
rc = cwLogError ( rc , " The preset dictionary is not a dictionary on class desc:'%s' " , cwStringNullGuard ( cd - > label ) ) ;
goto errLabel ;
}
// for each preset in the class desc.
for ( unsigned j = 0 ; j < presetD - > child_count ( ) ; + + j )
{
const object_t * pair = presetD - > child_ele ( j ) ;
if ( ! pair - > pair_value ( ) - > is_dict ( ) )
{
rc = cwLogError ( kSyntaxErrorRC , " The preset '%s' in class desc '%s' is not a dictionary. " , cwStringNullGuard ( pair - > pair_label ( ) ) , cwStringNullGuard ( cd - > label ) ) ;
goto errLabel ;
}
preset_t * preset = mem : : allocZ < preset_t > ( ) ;
preset - > label = pair - > pair_label ( ) ;
preset - > cfg = pair - > pair_value ( ) ;
preset - > link = cd - > presetL ;
cd - > presetL = preset ;
}
}
2021-08-23 02:41:33 +00:00
// parse the variable dictionary
2021-08-15 20:07:12 +00:00
if ( varD ! = nullptr )
{
if ( ! varD - > is_dict ( ) )
{
rc = cwLogError ( rc , " The value dictionary is not a dictionary on class desc:'%s' " , cwStringNullGuard ( cd - > label ) ) ;
goto errLabel ;
}
// 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 ) ;
goto errLabel ;
}
// for each class value description
for ( unsigned j = 0 ; j < varD - > child_count ( ) ; + + j )
{
const object_t * var_obj = varD - > child_ele ( j ) ;
2022-12-17 13:16:21 +00:00
const object_t * var_flags_obj = nullptr ;
2021-08-15 20:07:12 +00:00
const char * type_str = nullptr ;
unsigned type_flag = 0 ;
2021-08-23 02:41:33 +00:00
bool srcVarFl = false ;
2022-11-11 18:09:07 +00:00
bool srcOptFl = false ;
2021-08-15 20:07:12 +00:00
var_desc_t * vd = mem : : allocZ < var_desc_t > ( ) ;
vd - > label = var_obj - > pair_label ( ) ;
vd - > cfg = var_obj - > pair_value ( ) ;
// get the variable description
2021-12-11 20:19:15 +00:00
if ( ( rc = vd - > cfg - > getv ( " type " , type_str ,
2021-08-15 20:07:12 +00:00
" doc " , vd - > docText ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Parsing failed on class:%s variable: '%s'. " , cd - > label , vd - > label ) ;
goto errLabel ;
}
// convert the type string to a numeric type flag
if ( ( type_flag = value_type_label_to_flag ( type_str ) ) = = kInvalidTId )
{
2024-04-26 21:05:48 +00:00
rc = cwLogError ( kSyntaxErrorRC , " Invalid type flag: '%s' class:'%s' value:'%s'. " , type_str , cd - > label , vd - > label ) ;
2021-08-15 20:07:12 +00:00
goto errLabel ;
}
// get the variable description
2022-12-17 13:16:21 +00:00
if ( ( rc = vd - > cfg - > getv_opt ( " flags " , var_flags_obj ,
2022-11-11 18:09:07 +00:00
" value " , vd - > val_cfg ) ) ! = kOkRC )
2021-08-15 20:07:12 +00:00
{
rc = cwLogError ( rc , " Parsing optional fields failed on class:%s variable: '%s'. " , cd - > label , vd - > label ) ;
goto errLabel ;
}
2022-12-17 13:16:21 +00:00
// check for 'src' flag
if ( ( rc = _is_var_flag_set ( var_flags_obj , " src " , cd - > label , vd - > label , srcVarFl ) ) ! = kOkRC )
goto errLabel ;
// check for 'src_opt' flag
if ( ( rc = _is_var_flag_set ( var_flags_obj , " src_opt " , cd - > label , vd - > label , srcOptFl ) ) ! = kOkRC )
goto errLabel ;
2021-08-15 20:07:12 +00:00
vd - > type | = type_flag ;
if ( srcVarFl )
vd - > flags | = kSrcVarFl ;
2022-11-11 18:09:07 +00:00
if ( srcOptFl )
vd - > flags | = kSrcOptVarFl ;
2021-08-15 20:07:12 +00:00
vd - > link = cd - > varDescL ;
cd - > varDescL = vd ;
}
}
}
errLabel :
return rc ;
}
2024-04-22 20:02:40 +00:00
/*
rc_t _setup_input ( flow_t * p , instance_t * in_inst , const char * in_var_label , const char * src_proc_label , const char * src_var_label )
2021-08-15 20:07:12 +00:00
{
rc_t rc = kOkRC ;
unsigned src_charN = textLength ( src_label_arg ) ;
variable_t * src_var = nullptr ;
instance_t * src_inst = nullptr ;
variable_t * in_var = nullptr ;
char sbuf [ src_charN + 1 ] ;
// copy the id into the buf
strncpy ( sbuf , src_label_arg , src_charN + 1 ) ;
// advance suffix to the '.'
char * suffix = sbuf ;
while ( * suffix & & * suffix ! = ' . ' )
+ + suffix ;
// if a '.' suffix was found
if ( * suffix )
{
* suffix = 0 ;
+ + suffix ;
}
// locate source instance
2024-04-22 20:02:40 +00:00
if ( ( rc = instance_find ( p , sbuf , kBaseSfxId , src_inst ) ) ! = kOkRC )
2021-08-15 20:07:12 +00:00
{
rc = cwLogError ( kSyntaxErrorRC , " The source instance '%s' was not found. " , cwStringNullGuard ( sbuf ) ) ;
goto errLabel ;
}
// locate source value
2024-04-22 20:02:40 +00:00
if ( ( rc = var_find ( src_inst , suffix , kBaseSfxId , kAnyChIdx , src_var ) ) ! = kOkRC )
2021-08-15 20:07:12 +00:00
{
rc = cwLogError ( rc , " The source var '%s' was not found on the source instance '%s'. " , cwStringNullGuard ( suffix ) , cwStringNullGuard ( sbuf ) ) ;
goto errLabel ;
}
// locate input value
2024-04-22 20:02:40 +00:00
if ( ( rc = var_find ( in_inst , in_var_label , kBaseSfxId , kAnyChIdx , in_var ) ) ! = kOkRC )
2021-08-15 20:07:12 +00:00
{
rc = cwLogError ( rc , " The input value '%s' was not found on the instance '%s'. " , cwStringNullGuard ( in_var_label ) , cwStringNullGuard ( in_inst - > label ) ) ;
goto errLabel ;
}
// verify that the src_value type is included in the in_value type flags
if ( cwIsNotFlag ( in_var - > varDesc - > type , src_var - > varDesc - > type ) )
{
rc = cwLogError ( kSyntaxErrorRC , " The type flags don't match on input:%s %s source:%s %s . " , in_inst - > label , in_var_label , src_inst - > label , suffix ) ;
goto errLabel ;
}
2021-12-28 01:25:18 +00:00
if ( src_var - > value = = nullptr )
{
2024-04-06 20:07:46 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The source value is null on the connection input:'%s' %s source:'%s' '%s' . " , in_inst - > label , in_var_label , src_inst - > label , suffix ) ;
2021-12-28 01:25:18 +00:00
goto errLabel ;
}
2021-12-30 02:52:46 +00:00
_connect_vars ( src_var , in_var ) ;
2021-08-15 20:07:12 +00:00
2021-12-28 01:25:18 +00:00
//cwLogInfo("'%s:%s' connected to source '%s:%s' %p.", in_inst->label, in_var_label, src_inst->label, suffix, in_var->value );
2021-08-15 20:07:12 +00:00
errLabel :
return rc ;
}
2024-04-22 20:02:40 +00:00
*/
2021-08-15 20:07:12 +00:00
2024-04-22 20:02:40 +00:00
rc_t _destroy ( flow_t * p )
{
rc_t rc = kOkRC ;
2021-08-15 20:07:12 +00:00
2024-04-22 20:02:40 +00:00
if ( p = = nullptr )
return rc ;
2021-08-23 02:41:33 +00:00
2024-04-22 20:02:40 +00:00
network_destroy ( p - > net ) ;
2021-08-23 02:41:33 +00:00
2024-04-22 20:02:40 +00:00
// release the class records
for ( unsigned i = 0 ; i < p - > classDescN ; + + i )
2021-08-15 20:07:12 +00:00
{
2024-04-22 20:02:40 +00:00
class_desc_t * cd = p - > classDescA + i ;
2021-08-15 20:07:12 +00:00
2024-04-22 20:02:40 +00:00
// release the var desc list
var_desc_t * vd0 = cd - > varDescL ;
var_desc_t * vd1 = nullptr ;
while ( vd0 ! = nullptr )
{
vd1 = vd0 - > link ;
mem : : release ( vd0 ) ;
vd0 = vd1 ;
}
2021-08-23 02:41:33 +00:00
2024-04-22 20:02:40 +00:00
// release the preset list
preset_t * pr0 = cd - > presetL ;
preset_t * pr1 = nullptr ;
while ( pr0 ! = nullptr )
{
pr1 = pr0 - > link ;
mem : : release ( pr0 ) ;
pr0 = pr1 ;
2021-08-23 02:41:33 +00:00
}
2021-08-15 20:07:12 +00:00
}
2024-04-22 20:02:40 +00:00
mem : : release ( p - > classDescA ) ;
2021-12-30 02:52:46 +00:00
2024-04-22 20:02:40 +00:00
mem : : release ( p ) ;
return rc ;
}
2021-08-23 02:41:33 +00:00
2024-04-22 20:02:40 +00:00
}
}
2021-12-28 01:25:18 +00:00
2024-04-22 20:02:40 +00:00
void cw : : flow : : print_abuf ( const abuf_t * abuf )
{
printf ( " Abuf: sr:%7.1f chs:%3i frameN:%4i %p " , abuf - > srate , abuf - > chN , abuf - > frameN , abuf - > buf ) ;
}
2021-12-30 02:52:46 +00:00
2024-04-22 20:02:40 +00:00
void cw : : flow : : print_external_device ( const external_device_t * dev )
{
printf ( " Dev: %10s type:%3i fl:0x%x : " , cwStringNullGuard ( dev - > devLabel ) , dev - > typeId , dev - > flags ) ;
if ( dev - > typeId = = kAudioDevTypeId )
print_abuf ( dev - > u . a . abuf ) ;
printf ( " \n " ) ;
}
2021-08-23 02:41:33 +00:00
2021-12-30 02:52:46 +00:00
2024-04-22 20:02:40 +00:00
cw : : rc_t cw : : flow : : create ( handle_t & hRef ,
const object_t & classCfg ,
const object_t & flowCfg ,
external_device_t * deviceA ,
unsigned deviceN )
{
rc_t rc = kOkRC ;
const object_t * networkCfg = nullptr ;
bool printClassDictFl = false ;
bool printNetworkFl = false ;
if ( ( rc = destroy ( hRef ) ) ! = kOkRC )
return rc ;
2021-12-30 02:52:46 +00:00
2024-04-22 20:02:40 +00:00
flow_t * p = mem : : allocZ < flow_t > ( ) ;
p - > flowCfg = & flowCfg ; // TODO: duplicate cfg?
p - > deviceA = deviceA ;
p - > deviceN = deviceN ;
2021-12-30 02:52:46 +00:00
2024-04-22 20:02:40 +00:00
// parse the class description array
if ( ( rc = _parse_class_cfg ( p , & classCfg ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " Error parsing the class description list. " ) ;
goto errLabel ;
}
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
// parse the main audio file processor cfg record
if ( ( rc = flowCfg . getv ( " framesPerCycle " , p - > framesPerCycle ,
" network " , networkCfg ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " Error parsing the required flow configuration parameters. " ) ;
goto errLabel ;
}
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
// parse the optional args
if ( ( rc = flowCfg . getv_opt ( " maxCycleCount " , p - > maxCycleCount ,
2024-04-26 21:05:48 +00:00
" multiPriPresetProbFl " , p - > multiPriPresetProbFl ,
" multiSecPresetProbFl " , p - > multiSecPresetProbFl ,
" multiPresetInterpFl " , p - > multiPresetInterpFl ,
2024-04-22 20:02:40 +00:00
" printClassDictFl " , printClassDictFl ,
" printNetworkFl " , printNetworkFl ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " Error parsing the optional flow configuration parameters. " ) ;
goto errLabel ;
}
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
for ( unsigned i = 0 ; i < deviceN ; + + i )
if ( deviceA [ i ] . typeId = = kAudioDevTypeId )
2021-08-23 02:41:33 +00:00
{
2024-04-22 20:02:40 +00:00
if ( deviceA [ i ] . u . a . abuf = = NULL )
2021-08-23 02:41:33 +00:00
{
2024-04-22 20:02:40 +00:00
rc = cwLogError ( kInvalidArgRC , " The audio '%s' device does not have a valid audio buffer. " , cwStringNullGuard ( deviceA [ i ] . devLabel ) ) ;
2021-08-23 02:41:33 +00:00
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
else
if ( deviceA [ i ] . u . a . abuf - > frameN ! = p - > framesPerCycle )
cwLogWarning ( " The audio frame count (%i) for audio device '%s' does not match the Flow framesPerCycle (%i). " , deviceA [ i ] . u . a . abuf - > frameN , p - > framesPerCycle ) ;
}
// print the class dict
if ( printClassDictFl )
class_dict_print ( p ) ;
2021-08-15 20:07:12 +00:00
2024-04-22 20:02:40 +00:00
// instantiate the network
if ( ( rc = network_create ( p , networkCfg , p - > net ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Network creation failed. " ) ;
goto errLabel ;
}
2021-08-23 02:41:33 +00:00
2024-04-22 20:02:40 +00:00
if ( printNetworkFl )
network_print ( p - > net ) ;
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
hRef . set ( p ) ;
errLabel :
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
if ( rc ! = kOkRC )
_destroy ( p ) ;
return rc ;
}
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
cw : : rc_t cw : : flow : : destroy ( handle_t & hRef )
{
rc_t rc = kOkRC ;
flow_t * p = nullptr ; ;
if ( ! hRef . isValid ( ) )
return rc ;
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
p = _handleToPtr ( hRef ) ;
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
_destroy ( p ) ;
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
hRef . clear ( ) ;
return rc ;
}
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
unsigned cw : : flow : : preset_cfg_flags ( handle_t h )
{
flow_t * p = _handleToPtr ( h ) ;
unsigned flags = 0 ;
if ( p - > multiPriPresetProbFl )
flags | = kPriPresetProbFl ;
if ( p - > multiSecPresetProbFl )
flags | = kSecPresetProbFl ;
if ( p - > multiPresetInterpFl )
flags | = kInterpPresetFl ;
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
return flags ;
}
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
cw : : rc_t cw : : flow : : exec_cycle ( handle_t h )
{
return exec_cycle ( _handleToPtr ( h ) - > net ) ;
}
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
cw : : rc_t cw : : flow : : exec ( handle_t h )
{
rc_t rc = kOkRC ;
flow_t * p = _handleToPtr ( h ) ;
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
while ( true )
{
rc = exec_cycle ( p - > net ) ;
2024-02-08 16:17:26 +00:00
2024-04-22 20:02:40 +00:00
if ( rc = = kEofRC )
2024-02-08 16:17:26 +00:00
{
2024-04-22 20:02:40 +00:00
rc = kOkRC ;
break ;
}
p - > cycleIndex + = 1 ;
if ( p - > maxCycleCount > 0 & & p - > cycleIndex > = p - > maxCycleCount )
{
cwLogInfo ( " 'maxCycleCnt' reached: %i. Shutting down flow. " , p - > maxCycleCount ) ;
break ;
2024-02-08 16:17:26 +00:00
}
2024-04-22 20:02:40 +00:00
}
2023-03-17 22:24:07 +00:00
2021-12-26 03:16:00 +00:00
return rc ;
}
2021-12-19 17:10:35 +00:00
cw : : rc_t cw : : flow : : apply_preset ( handle_t h , const char * presetLabel )
2021-08-15 20:07:12 +00:00
{
2021-12-19 17:10:35 +00:00
flow_t * p = _handleToPtr ( h ) ;
2024-04-22 20:02:40 +00:00
return network_apply_preset ( p - > net , presetLabel ) ;
2021-12-19 17:10:35 +00:00
}
2024-02-08 16:17:26 +00:00
cw : : rc_t cw : : flow : : apply_dual_preset ( handle_t h , const char * presetLabel_0 , const char * presetLabel_1 , double coeff )
2024-01-13 15:16:37 +00:00
{
2024-02-08 16:17:26 +00:00
flow_t * p = _handleToPtr ( h ) ;
2024-04-22 20:02:40 +00:00
return network_apply_dual_preset ( p - > net , presetLabel_0 , presetLabel_1 , coeff ) ;
2024-02-08 16:17:26 +00:00
}
2024-02-18 13:41:19 +00:00
cw : : rc_t cw : : flow : : apply_preset ( handle_t h , const multi_preset_selector_t & mps )
2024-02-08 16:17:26 +00:00
{
2024-04-22 20:02:40 +00:00
flow_t * p = _handleToPtr ( h ) ;
return network_apply_preset ( p - > net , mps ) ;
2024-02-18 13:41:19 +00:00
}
2024-01-13 15:16:37 +00:00
2021-12-26 03:16:00 +00:00
cw : : rc_t cw : : flow : : set_variable_value ( handle_t h , const char * inst_label , const char * var_label , unsigned chIdx , bool value )
2024-04-22 20:02:40 +00:00
{ return set_variable_value ( _handleToPtr ( h ) - > net , inst_label , var_label , chIdx , value ) ; }
2021-12-19 17:10:35 +00:00
2021-12-26 03:16:00 +00:00
cw : : rc_t cw : : flow : : set_variable_value ( handle_t h , const char * inst_label , const char * var_label , unsigned chIdx , int value )
2024-04-22 20:02:40 +00:00
{ return set_variable_value ( _handleToPtr ( h ) - > net , inst_label , var_label , chIdx , value ) ; }
2021-12-26 03:16:00 +00:00
cw : : rc_t cw : : flow : : set_variable_value ( handle_t h , const char * inst_label , const char * var_label , unsigned chIdx , unsigned value )
2024-04-22 20:02:40 +00:00
{ return set_variable_value ( _handleToPtr ( h ) - > net , inst_label , var_label , chIdx , value ) ; }
2021-12-26 03:16:00 +00:00
cw : : rc_t cw : : flow : : set_variable_value ( handle_t h , const char * inst_label , const char * var_label , unsigned chIdx , float value )
2024-04-22 20:02:40 +00:00
{ return set_variable_value ( _handleToPtr ( h ) - > net , inst_label , var_label , chIdx , value ) ; }
2021-12-26 03:16:00 +00:00
cw : : rc_t cw : : flow : : set_variable_value ( handle_t h , const char * inst_label , const char * var_label , unsigned chIdx , double value )
2024-04-22 20:02:40 +00:00
{ return set_variable_value ( _handleToPtr ( h ) - > net , inst_label , var_label , chIdx , value ) ; }
2021-08-15 20:07:12 +00:00
2023-01-05 12:26:25 +00:00
cw : : rc_t cw : : flow : : get_variable_value ( handle_t h , const char * inst_label , const char * var_label , unsigned chIdx , bool & valueRef )
2024-04-22 20:02:40 +00:00
{ return get_variable_value ( _handleToPtr ( h ) - > net , inst_label , var_label , chIdx , valueRef ) ; }
2023-01-05 12:26:25 +00:00
cw : : rc_t cw : : flow : : get_variable_value ( handle_t h , const char * inst_label , const char * var_label , unsigned chIdx , int & valueRef )
2024-04-22 20:02:40 +00:00
{ return get_variable_value ( _handleToPtr ( h ) - > net , inst_label , var_label , chIdx , valueRef ) ; }
2023-01-05 12:26:25 +00:00
cw : : rc_t cw : : flow : : get_variable_value ( handle_t h , const char * inst_label , const char * var_label , unsigned chIdx , unsigned & valueRef )
2024-04-22 20:02:40 +00:00
{ return get_variable_value ( _handleToPtr ( h ) - > net , inst_label , var_label , chIdx , valueRef ) ; }
2023-01-05 12:26:25 +00:00
cw : : rc_t cw : : flow : : get_variable_value ( handle_t h , const char * inst_label , const char * var_label , unsigned chIdx , float & valueRef )
2024-04-22 20:02:40 +00:00
{ return get_variable_value ( _handleToPtr ( h ) - > net , inst_label , var_label , chIdx , valueRef ) ; }
2023-01-05 12:26:25 +00:00
cw : : rc_t cw : : flow : : get_variable_value ( handle_t h , const char * inst_label , const char * var_label , unsigned chIdx , double & valueRef )
2024-04-22 20:02:40 +00:00
{ return get_variable_value ( _handleToPtr ( h ) - > net , inst_label , var_label , chIdx , valueRef ) ; }
2023-01-05 12:26:25 +00:00
2021-08-15 20:07:12 +00:00
2021-12-19 17:10:35 +00:00
void cw : : flow : : print_class_list ( handle_t h )
2021-08-15 20:07:12 +00:00
{
2021-12-19 17:10:35 +00:00
flow_t * p = _handleToPtr ( h ) ;
class_dict_print ( p ) ;
2021-08-15 20:07:12 +00:00
}
2021-12-19 17:10:35 +00:00
void cw : : flow : : print_network ( handle_t h )
2021-08-15 20:07:12 +00:00
{
2021-12-19 17:10:35 +00:00
flow_t * p = _handleToPtr ( h ) ;
for ( unsigned i = 0 ; i < p - > deviceN ; + + i )
print_external_device ( p - > deviceA + i ) ;
2024-04-22 20:02:40 +00:00
network_print ( p - > net ) ;
2021-08-15 20:07:12 +00:00
}
2024-04-26 21:05:48 +00:00
cw : : rc_t cw : : flow : : test ( const object_t * cfg , int argc , const char * argv [ ] )
2021-08-15 20:07:12 +00:00
{
rc_t rc = kOkRC ;
handle_t flowH ;
2023-03-17 22:24:07 +00:00
object_t * class_cfg = nullptr ;
2024-04-26 21:05:48 +00:00
const object_t * test_cases_cfg = nullptr ;
const object_t * test_cfg = nullptr ;
2023-03-17 22:24:07 +00:00
const char * flow_proc_fname ;
2024-04-26 21:05:48 +00:00
if ( argc < 2 | | textLength ( argv [ 1 ] ) = = 0 )
{
rc = cwLogError ( kInvalidArgRC , " No 'test-case' label was given on the command line. " ) ;
goto errLabel ;
}
2023-03-17 22:24:07 +00:00
2024-04-26 21:05:48 +00:00
if ( ( rc = cfg - > getv ( " flow_proc_fname " , flow_proc_fname ,
" test_cases " , test_cases_cfg ) ) ! = kOkRC )
2023-03-17 22:24:07 +00:00
{
rc = cwLogError ( rc , " The name of the flow_proc_dict file could not be parsed. " ) ;
goto errLabel ;
}
2024-04-26 21:05:48 +00:00
// find the user requested test case
if ( ( test_cfg = test_cases_cfg - > find_child ( argv [ 1 ] ) ) = = nullptr )
{
2024-04-30 23:58:10 +00:00
rc = cwLogError ( kInvalidArgRC , " The test case named '%s' was not found. " , argv [ 1 ] ) ;
2024-04-26 21:05:48 +00:00
goto errLabel ;
}
// parse the flow-proc-cfg
2023-03-17 22:24:07 +00:00
if ( ( rc = objectFromFile ( flow_proc_fname , class_cfg ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The flow proc dict could not be read from '%s'. " , cwStringNullGuard ( flow_proc_fname ) ) ;
goto errLabel ;
}
2021-08-15 20:07:12 +00:00
// create the flow object
2024-04-26 21:05:48 +00:00
if ( ( rc = create ( flowH , * class_cfg , * test_cfg ) ) ! = kOkRC )
2021-08-15 20:07:12 +00:00
{
rc = cwLogError ( rc , " Flow object create failed. " ) ;
goto errLabel ;
}
2023-03-17 22:24:07 +00:00
//print_network(flowH);
2021-08-15 20:07:12 +00:00
// run the network
if ( ( rc = exec ( flowH ) ) ! = kOkRC )
rc = cwLogError ( rc , " Execution failed. " ) ;
// destroy the flow object
if ( ( rc = destroy ( flowH ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Close the flow object. " ) ;
goto errLabel ;
}
errLabel :
2023-03-17 22:24:07 +00:00
if ( class_cfg ! = nullptr )
class_cfg - > free ( ) ;
2021-08-15 20:07:12 +00:00
return rc ;
}