diff --git a/cwFlowDecl.h b/cwFlowDecl.h index 67a23a5..60f373c 100644 --- a/cwFlowDecl.h +++ b/cwFlowDecl.h @@ -128,6 +128,13 @@ namespace cw unsigned ch_cnt; // 0=kAnyChIdx only, kInvalidCnt=no channels, 1=mono, 2=stereo, ... unsigned user_id; // uuId of the UI element that represents this var + + bool disable_fl; // true if this ui var is disabled + bool hide_fl; // true if this ui var is hidden + + bool new_disable_fl; + bool new_hide_fl; + } ui_var_t; struct proc_str; @@ -156,6 +163,8 @@ namespace cw typedef struct ui_net_str { struct network_str* net; + + bool ui_create_fl; // Set via network flag 'ui_create_fl'. ui_proc_t* procA; // procA[procN] unsigned procN; @@ -168,7 +177,7 @@ namespace cw } ui_net_t; - typedef rc_t (*ui_callback_t)( void* arg, const ui_var_t* ui_var ); + typedef rc_t (*ui_callback_t)( void* arg, ui_var_t* ui_var ); } diff --git a/cwFlowNet.cpp b/cwFlowNet.cpp index cb91c21..658d356 100644 --- a/cwFlowNet.cpp +++ b/cwFlowNet.cpp @@ -95,7 +95,9 @@ namespace cw const object_t* out_dict_cfg; // cfg. node to the out-list io_stmt_t* oStmtA; - unsigned oStmtN; + unsigned oStmtN; + + const object_t* ui_cfg; // cfg. node to ui } proc_inst_parse_state_t; @@ -1462,6 +1464,37 @@ namespace cw return rc1; } + rc_t _proc_parse_ui_cfg(proc_t* proc, const proc_inst_parse_state_t& pstate) + { + rc_t rc = kOkRC; + bool ui_create_fl = false; + + if( pstate.ui_cfg == nullptr ) + goto errLabel; + + if( pstate.ui_cfg->is_dict() == false ) + { + rc = cwLogError(kSyntaxErrorRC,"The UI cfg. record is not a dictionary."); + goto errLabel; + } + + if( pstate.ui_cfg->find("create_fl") == nullptr ) + ui_create_fl = proc->ctx->ui_create_fl; + + // parse the optional args + if((rc = pstate.ui_cfg->getv_opt("create_fl", ui_create_fl )) != kOkRC ) + goto errLabel; + + if( ui_create_fl ) + proc->flags |= kUiCreateProcFl; + + errLabel: + if( rc != kOkRC ) + rc = cwLogError(kSyntaxErrorRC,"The proc instance cfg. '%s:%i' UI configuration parse failed.",pstate.proc_label,pstate.proc_label_sfx_id); + + return rc; + } + rc_t _proc_verify_required_record_fields( const proc_t* proc ) { rc_t rc = kOkRC; @@ -1610,6 +1643,7 @@ namespace cw if((rc = proc_inst_cfg->pair_value()->getv_opt("args", arg_dict, "in", pstate.in_dict_cfg, "out", pstate.out_dict_cfg, + "ui", pstate.ui_cfg, "preset", pstate.preset_labels, "presets", pstate.presets_dict, "log", pstate.log_labels )) != kOkRC ) @@ -1859,6 +1893,7 @@ namespace cw } + /* rc_t _process_net_preset(proc_t* proc, const object_t* net_preset_cfgD) { rc_t rc = kOkRC; @@ -1893,7 +1928,7 @@ namespace cw return rc; } - + */ void _pstate_destroy( proc_inst_parse_state_t pstate ) { @@ -2070,6 +2105,11 @@ namespace cw if((rc = _proc_call_value_func_on_all_variables( proc )) != kOkRC ) goto errLabel; + // parse the proc UI cfg record + if(pstate.ui_cfg != nullptr ) + if((rc = _proc_parse_ui_cfg(proc,pstate)) != kOkRC ) + goto errLabel; + // validate the proc's state. if((rc = proc_validate(proc)) != kOkRC ) { @@ -3430,10 +3470,11 @@ namespace cw ui_var->label = var->label; ui_var->label_sfx_id = var->label_sfx_id; ui_var->has_source_fl= is_connected_to_source( var ); + ui_var->disable_fl = ui_var->has_source_fl; ui_var->vid = var->vid; ui_var->ch_cnt = var_channel_count( net.procA[i], var->label, var->label_sfx_id ); ui_var->ch_idx = var->chIdx; - ui_var->value_tid = var->type; + ui_var->value_tid = (var->varDesc->type & flow::kTypeMask) == kAllTFl ? kAllTFl : var->type; ui_var->desc_flags = var->varDesc->flags; ui_var->desc_cfg = var->varDesc->cfg; ui_var->user_id = kInvalidId; @@ -3472,6 +3513,7 @@ namespace cw goto errLabel; ui_net_ref->poly_idx = net.poly_idx; + ui_net_ref->ui_create_fl = p->ui_create_fl; if( net.poly_link != nullptr ) _form_net_ui_desc(p,*net.poly_link,ui_net_ref->poly_link); diff --git a/cwFlowTypes.cpp b/cwFlowTypes.cpp index 80cb8c9..5c31854 100644 --- a/cwFlowTypes.cpp +++ b/cwFlowTypes.cpp @@ -30,9 +30,12 @@ namespace cw { kSrcVarDescFl, "src" }, { kSrcOptVarDescFl, "src_opt" }, { kNoSrcVarDescFl, "no_src" }, - { kInitVarDescFl, "init" }, - { kMultVarDescFl, "mult" }, - { kUdpOutVarDescFl, "out" }, + { kInitVarDescFl, "init" }, + { kMultVarDescFl, "mult" }, + { kUdpOutVarDescFl, "out" }, + { kUiCreateVarDescFl, "no_ui" }, // even if the proc ui is enabled, don't show this var + { kUiDisableVarDescFl,"ui_disable" }, + { kUiHideVarDescFl, "ui_hide" }, { kInvalidVarDescFl, "" } }; @@ -644,6 +647,10 @@ cw::flow::class_desc_t* cw::flow::class_desc_find( flow_t* p, const char* label return nullptr; } +const cw::flow::class_desc_t* cw::flow::class_desc_find( const flow_t* p, const char* class_desc_label ) +{ return class_desc_find( const_cast(p), class_desc_label ); } + + const cw::flow::var_desc_t* cw::flow::var_desc_find( const class_desc_t* cd, const char* label ) { const var_desc_t* vd = cd->varDescL; @@ -681,6 +688,131 @@ const cw::flow::class_preset_t* cw::flow::class_preset_find( const class_desc_t* return nullptr; } +cw::rc_t cw::flow::class_preset_value_channel_count( const class_preset_t* class_preset, const char* var_label, unsigned& ch_cnt_ref ) +{ + rc_t rc = kOkRC; + const object_t* var_cfg; + + ch_cnt_ref = 0; + + if( class_preset->cfg == nullptr ) + { + rc = cwLogError(rc,"The preset '%s' is not valid.", cwStringNullGuard(class_preset->label)); + goto errLabel; + } + + if((var_cfg = class_preset->cfg->find(var_label)) == nullptr ) + { + rc = cwLogError(rc,"Preset variable '%s' not found on preset '%s'.",cwStringNullGuard(var_label),cwStringNullGuard(class_preset->label)); + goto errLabel; + } + + if( var_cfg->is_list() ) + ch_cnt_ref = var_cfg->child_count(); + else + ch_cnt_ref = 1; + +errLabel: + return rc; +} + +cw::rc_t cw::flow::class_preset_value_channel_count( const class_desc_t* class_desc, const char* class_preset_label, const char* var_label, unsigned& ch_cnt_ref ) +{ + rc_t rc = kOkRC; + const class_preset_t* class_preset = nullptr; + + ch_cnt_ref = 0; + + if((class_preset = class_preset_find(class_desc, class_preset_label)) == nullptr ) + { + rc = cwLogError(kEleNotFoundRC,"The preset '%s' could not be found on the class description: '%s'.",cwStringNullGuard(class_preset_label),cwStringNullGuard(class_desc->label)); + goto errLabel; + } + + rc = class_preset_value_channel_count( class_preset, var_label, ch_cnt_ref ); + +errLabel: + return rc; +} + +cw::rc_t cw::flow::class_preset_value_channel_count( const flow_t* p, const char* class_desc_label, const char* class_preset_label, const char* var_label, unsigned& ch_cnt_ref ) +{ + rc_t rc = kOkRC; + const class_desc_t* class_desc; + + ch_cnt_ref = 0; + + if((class_desc = class_desc_find(p,class_desc_label)) == nullptr ) + { + rc = cwLogError(kEleNotFoundRC,"The class description '%s' could not be found.",cwStringNullGuard(class_desc_label)); + goto errLabel; + } + + rc = class_preset_value_channel_count(class_desc, class_preset_label, var_label, ch_cnt_ref ); + +errLabel: + return rc; +} + +cw::rc_t cw::flow::class_preset_has_var( const class_preset_t* class_preset, const char* var_label, bool& fl_ref ) +{ + rc_t rc = kOkRC; + const object_t* var_cfg; + + fl_ref = false; + + if( class_preset->cfg == nullptr ) + { + rc = cwLogError(rc,"The preset '%s' is not valid.", cwStringNullGuard(class_preset->label)); + goto errLabel; + } + + fl_ref = class_preset->cfg->find(var_label) != nullptr; + +errLabel: + return rc; + +} + +cw::rc_t cw::flow::class_preset_has_var( const class_desc_t* class_desc, const char* class_preset_label, const char* var_label, bool& fl_ref ) +{ + rc_t rc = kOkRC; + const class_preset_t* class_preset = nullptr; + + fl_ref = false; + + if((class_preset = class_preset_find(class_desc, class_preset_label)) == nullptr ) + { + rc = cwLogError(kEleNotFoundRC,"The preset '%s' could not be found on the class description: '%s'.",cwStringNullGuard(class_preset_label),cwStringNullGuard(class_desc->label)); + goto errLabel; + } + + rc = class_preset_has_var( class_preset, var_label, fl_ref ); + +errLabel: + return rc; +} + +cw::rc_t cw::flow::class_preset_has_var( const flow_t* p, const char* class_desc_label, const char* class_preset_label, const char* var_label, bool& fl_ref ) +{ + rc_t rc = kOkRC; + const class_desc_t* class_desc; + + fl_ref = false; + + if((class_desc = class_desc_find(p,class_desc_label)) == nullptr ) + { + rc = cwLogError(kEleNotFoundRC,"The class description '%s' could not be found.",cwStringNullGuard(class_desc_label)); + goto errLabel; + } + + rc = class_preset_has_var(class_desc, class_preset_label, var_label, fl_ref ); + +errLabel: + return rc; +} + + void cw::flow::class_dict_print( flow_t* p ) { for(unsigned i=0; iclassDescN; ++i) @@ -1569,6 +1701,33 @@ cw::rc_t cw::flow::var_send_to_ui( proc_t* proc, unsigned vid, unsigned chIdx return rc; } +cw::rc_t cw::flow::var_send_to_ui_enable( proc_t* proc, unsigned vid, unsigned chIdx, bool enable_fl ) +{ + rc_t rc = kOkRC; + variable_t* var = nullptr; + + if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) + { + var->ui_var->new_disable_fl = !enable_fl; + rc = var_send_to_ui(var); + } + return rc; +} + +cw::rc_t cw::flow::var_send_to_ui_show( proc_t* proc, unsigned vid, unsigned chIdx, bool show_fl ) +{ + rc_t rc = kOkRC; + variable_t* var = nullptr; + + if((rc = var_find(proc, vid, chIdx, var )) == kOkRC ) + { + var->ui_var->new_hide_fl = !show_fl; + rc = var_send_to_ui(var); + } + return rc; +} + + cw::rc_t cw::flow::var_register_and_set( proc_t* proc, const char* var_label, unsigned sfx_id, unsigned vid, unsigned chIdx, variable_t*& varRef ) { return var_register( proc, var_label, sfx_id, vid, chIdx, nullptr, varRef ); diff --git a/cwFlowTypes.h b/cwFlowTypes.h index 81f39e2..57f3abc 100644 --- a/cwFlowTypes.h +++ b/cwFlowTypes.h @@ -14,13 +14,16 @@ namespace cw // var_desc_t attribute flags enum { - kInvalidVarDescFl = 0x00, - kSrcVarDescFl = 0x01, - kSrcOptVarDescFl = 0x02, - kNoSrcVarDescFl = 0x04, - kInitVarDescFl = 0x08, - kMultVarDescFl = 0x10, - kUdpOutVarDescFl = 0x20 + kInvalidVarDescFl = 0x000, + kSrcVarDescFl = 0x001, + kSrcOptVarDescFl = 0x002, + kNoSrcVarDescFl = 0x004, + kInitVarDescFl = 0x008, + kMultVarDescFl = 0x010, + kUdpOutVarDescFl = 0x020, + kUiCreateVarDescFl = 0x040, + kUiDisableVarDescFl = 0x080, + kUiHideVarDescFl = 0x100 }; typedef struct class_members_str @@ -75,7 +78,7 @@ namespace cw kInvalidVarFl = 0x00, kLogVarFl = 0x01, kProxiedVarFl = 0x02, - kProxiedOutVarFl = 0x04 + kProxiedOutVarFl = 0x04, }; // Note: The concatenation of 'vid' and 'chIdx' should form a unique identifier among all variables @@ -114,12 +117,18 @@ namespace cw struct network_str; + + enum { + kUiCreateProcFl = 0x01 + }; typedef struct proc_str { struct flow_str* ctx; // global system context struct network_str* net; // network which owns this proc + unsigned flags; // See k???ProcFl + class_desc_t* class_desc; // char* label; // instance label @@ -292,8 +301,9 @@ namespace cw network_t* net; // The root of the network instance - ui_callback_t ui_callback; - void* ui_callback_arg; + bool ui_create_fl; // dflt: false Set by network flag: ui_create_fl, override with proc inst ui:{ create_fl } + ui_callback_t ui_callback; + void* ui_callback_arg; std::atomic ui_var_head; // Linked lists of var's to send to the UI variable_t ui_var_stub; @@ -319,8 +329,9 @@ namespace cw const char* var_desc_flag_to_attribute( unsigned flag ); const idLabelPair_t* var_desc_flag_array( unsigned& array_cnt_ref ); - void class_desc_destroy( class_desc_t* class_desc); - class_desc_t* class_desc_find( flow_t* p, const char* class_desc_label ); + void class_desc_destroy( class_desc_t* class_desc); + class_desc_t* class_desc_find( flow_t* p, const char* class_desc_label ); + const class_desc_t* class_desc_find( const flow_t* p, const char* class_desc_label ); 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 ); @@ -328,7 +339,88 @@ namespace cw bool var_desc_has_recd_format( var_desc_t* vd ); - const class_preset_t* class_preset_find( const class_desc_t* cd, const char* preset_label ); + const class_preset_t* class_preset_find( const class_desc_t* cd, const char* preset_label ); + + template + rc_t class_preset_value( const class_preset_t* class_preset, const char* var_label, unsigned ch_idx, T& val ) + { + rc_t rc = kOkRC; + const object_t* preset_val = nullptr; + + if((rc = class_preset->cfg->get(var_label, preset_val )) != kOkRC ) + { + rc = cwLogError(rc,"The preset variable '%s' on the preset '%s' could not be parsed.",cwStringNullGuard(var_label),cwStringNullGuard(class_preset->label)); + goto errLabel; + } + + if( preset_val->is_list() ) + { + if( ch_idx >= preset_val->child_count() || (preset_val = preset_val->child_ele( ch_idx )) == nullptr ) + { + rc = cwLogError(rc,"The channel index '%i' is invalid for the preset '%s:%s'.",ch_idx,cwStringNullGuard(class_preset->label),cwStringNullGuard(var_label)); + goto errLabel; + } + } + + // + if((rc = preset_val->value( val )) != kOkRC ) + { + rc = cwLogError(rc,"The preset value '%s:%s ch:%i' could not be parsed.",cwStringNullGuard(class_preset->label),cwStringNullGuard(var_label),ch_idx); + goto errLabel; + } + + errLabel: + return rc; + } + + template + rc_t class_preset_value( const class_desc_t* class_desc, const char* class_preset_label, const char* var_label, unsigned ch_idx, T& val ) + { + rc_t rc = kOkRC; + const class_preset_t* class_preset = nullptr; + + if((class_preset = class_preset_find(class_desc, class_preset_label)) == nullptr ) + { + rc = cwLogError(kEleNotFoundRC,"The preset '%s' could not be found on the class description: '%s'.",cwStringNullGuard(class_preset_label),cwStringNullGuard(class_desc->label)); + goto errLabel; + } + + rc = class_preset_value(class_preset, var_label, ch_idx, val ); + + errLabel: + return rc; + } + + template + rc_t class_preset_value( const flow_t* p, const char* class_desc_label, const char* class_preset_label, const char* var_label, unsigned ch_idx, T& val ) + { + rc_t rc = kOkRC; + const class_desc_t* class_desc; + if((class_desc = class_desc_find(p,class_desc_label)) == nullptr ) + { + rc = cwLogError(kEleNotFoundRC,"The class description '%s' could not be found.",cwStringNullGuard(class_desc_label)); + goto errLabel; + } + + rc = class_preset_value( class_desc, class_preset_label, var_label, ch_idx, val ); + + errLabel: + return rc; + } + + + rc_t class_preset_value_channel_count( const class_preset_t* class_preset, const char* var_label, unsigned& ch_cnt_ref ); + rc_t class_preset_value_channel_count( const class_desc_t* class_desc, const char* class_preset_label, const char* var_label, unsigned& ch_cnt_ref ); + rc_t class_preset_value_channel_count( const flow_t* p, const char* class_desc_label, const char* class_preset_label, const char* var_label, unsigned& ch_cnt_ref ); + + + rc_t class_preset_has_var( const class_preset_t* class_preset, const char* var_label, bool& fl_ref ); + rc_t class_preset_has_var( const class_desc_t* class_desc, const char* class_preset_label, const char* var_label, bool& fl_ref ); + rc_t class_preset_has_var( const flow_t* p, const char* class_desc_label, const char* class_preset_label, const char* var_label, bool& fl_ref ); + + + + //------------------------------------------------------------------------------------------------------------------------ // @@ -443,6 +535,8 @@ namespace cw // Send a variable value to the UI rc_t var_send_to_ui( variable_t* var ); rc_t var_send_to_ui( proc_t* proc, unsigned vid, unsigned chIdx ); + rc_t var_send_to_ui_enable( proc_t* proc, unsigned vid, unsigned chIdx, bool enable_fl ); + rc_t var_send_to_ui_show( proc_t* proc, unsigned vid, unsigned chIdx, bool show_fl ); //----------------- // diff --git a/cwIoFlowCtl.cpp b/cwIoFlowCtl.cpp index 57b72b6..4cb6950 100644 --- a/cwIoFlowCtl.cpp +++ b/cwIoFlowCtl.cpp @@ -527,7 +527,7 @@ namespace cw } template< typename T > - rc_t _ui_callback_tpl( io_flow_ctl_t* p, const flow::ui_var_t* ui_var ) + rc_t _ui_callback_tpl( io_flow_ctl_t* p, flow::ui_var_t* ui_var ) { rc_t rc; @@ -549,7 +549,7 @@ namespace cw } // This function is called with messages for the UI from the flow proc instances - rc_t _ui_callback( void* arg, const flow::ui_var_t* ui_var ) + rc_t _ui_callback( void* arg, flow::ui_var_t* ui_var ) { rc_t rc = kOkRC; @@ -560,6 +560,28 @@ namespace cw rc = cwLogError(kInvalidArgRC,"The user_id (uuid) of the variable was not set."); goto errLabel; } + + if( ui_var->new_disable_fl != ui_var->disable_fl ) + { + if((rc = uiSetEnable( p->ioH, ui_var->user_id, !ui_var->new_disable_fl )) != kOkRC ) + { + rc = cwLogError(rc,"UI enable/disable update failed."); + goto errLabel; + } + + ui_var->disable_fl = ui_var->new_disable_fl; + } + + if( ui_var->new_hide_fl != ui_var->hide_fl ) + { + if((rc = uiSetVisible( p->ioH, ui_var->user_id, !ui_var->new_hide_fl )) != kOkRC ) + { + rc = cwLogError(rc,"UI hide/show update failed."); + goto errLabel; + } + + ui_var->hide_fl = ui_var->new_hide_fl; + } switch( ui_var->value_tid & flow::kTypeMask ) {