diff --git a/src/caw/html/ui.cfg b/src/caw/html/ui.cfg
index b97bf3f..cfdf0e6 100644
--- a/src/caw/html/ui.cfg
+++ b/src/caw/html/ui.cfg
@@ -13,6 +13,12 @@
button:{ name: netPrintBtnId, title:"Print Network" }
button:{ name: reportBtnId, title:"App Report" },
button:{ name: latencyBtnId, title:"Latency Reset"},
+
+ select:{ name: pgmSelId, title:"Programs", children: {} },
+ select:{ name: pgmPresetSelId, title:"Presets", children: {}, enable:false },
+
+ check: { name: runCheckId, title: "Run", enable:false },
+
},
row: {
diff --git a/src/caw/main.cpp b/src/caw/main.cpp
index 58bdae7..19af983 100644
--- a/src/caw/main.cpp
+++ b/src/caw/main.cpp
@@ -7,6 +7,7 @@
#include "cwObject.h"
#include "cwFileSys.h"
#include "cwIo.h"
+#include "cwVectOps.h"
#include "cwIoFlowCtl.h"
@@ -16,6 +17,7 @@
using namespace cw;
enum {
+ kUiSelId,
kExecSelId,
kTestSelId,
kHwReportSelId,
@@ -24,6 +26,7 @@ enum {
};
idLabelPair_t appSelA[] = {
+ { kUiSelId, "ui" },
{ kExecSelId, "exec" },
{ kTestSelId, "test" },
{ kHwReportSelId, "hw_report" },
@@ -38,10 +41,12 @@ typedef struct app_str
{
object_t* flow_cfg; // flow program cfg
object_t* io_cfg; // IO lib cfg.
- const char* cmd_line_pgm_label; //
- const char* cmd_line_cfg_fname;
-
- unsigned appSelId;
+ unsigned cmd_line_action_id; // kUiSelId | kExecSelId | kTestSelId ....
+ const char* cmd_line_pgm_fname; // pgm file passed from the comman dline
+ const char* cmd_line_pgm_label; // pgm label passed from the command line
+ unsigned pgm_preset_idx; // currently selected pgm preset
+
+ bool run_fl; // true if the program is running (and the 'run' check is checked)
io::handle_t ioH;
io_flow_ctl::handle_t ioFlowH;
@@ -56,7 +61,17 @@ enum
kNetPrintBtnId,
kReportBtnId,
kLatencyBtnId,
- kValueNumbId
+ kValueNumbId,
+
+ kPgmSelId,
+ kPgmPresetSelId,
+ kRunCheckId,
+
+
+ kPgmBaseSelId,
+ kPgmMaxSelId = kPgmBaseSelId + 1000,
+ kPgmPresetBaseSelId,
+ kPgmPresetMaxSelId = kPgmPresetBaseSelId + 1000
};
ui::appIdMap_t appIdMapA[] = {
@@ -67,7 +82,12 @@ ui::appIdMap_t appIdMapA[] = {
{ kPanelDivId, kNetPrintBtnId, "netPrintBtnId" },
{ kPanelDivId, kReportBtnId, "reportBtnId" },
{ kPanelDivId, kLatencyBtnId, "latencyBtnId" },
- { kPanelDivId, kValueNumbId, "valueNumbId" }
+
+ { kPanelDivId, kValueNumbId, "valueNumbId" },
+
+ { kPanelDivId, kPgmSelId, "pgmSelId" },
+ { kPanelDivId, kPgmPresetSelId, "pgmPresetSelId" },
+ { kPanelDivId, kRunCheckId, "runCheckId" }
};
const unsigned appIdMapN = sizeof(appIdMapA)/sizeof(appIdMapA[0]);
@@ -94,7 +114,7 @@ errLabel:
}
-rc_t _load_init_pgm( app_t& app, const char* pgm_label, bool& exec_complete_fl_ref )
+rc_t _load_init_pgm_no_gui( app_t& app, const char* pgm_label, bool& exec_complete_fl_ref )
{
rc_t rc = kOkRC;
unsigned pgm_idx;
@@ -132,6 +152,134 @@ errLabel:
return rc;
}
+
+rc_t _on_pgm_select(app_t* app, unsigned pgmSelOptId )
+{
+ rc_t rc = kOkRC;
+
+ unsigned pgm_idx = kInvalidIdx;
+ unsigned pgmPresetSelUuId = io::uiFindElementUuId( app->ioH, kPgmPresetSelId );
+ unsigned runCheckUuId = io::uiFindElementUuId( app->ioH, kRunCheckId );
+ unsigned preset_cnt = 0;
+
+ if( !(kPgmBaseSelId <= pgmSelOptId && pgmSelOptId <= kPgmMaxSelId ) )
+ {
+ rc = cwLogError(kInvalidStateRC,"An invalid pgm select id was encountered.");
+ goto errLabel;
+ }
+
+ // empty the contents of the preset select menu
+ if((rc = uiEmptyParent(app->ioH,pgmPresetSelUuId)) != kOkRC )
+ {
+ rc = cwLogError(rc,"The program preset menu clear failed.");
+ goto errLabel;
+ }
+
+ uiSetEnable( app->ioH, pgmPresetSelUuId, false ); // Disable the preset menu and run checkbox in anticipation of error.
+ uiSetEnable( app->ioH, runCheckUuId, false ); //
+ app->pgm_preset_idx = kInvalidIdx; // The preset menu is empty and so there can be no valid preset selected.
+ pgm_idx = pgmSelOptId - kPgmBaseSelId; // Calc the ioFlowCtl preset index of the selected preset.
+
+ // load the program
+ if((rc = program_load(app->ioFlowH, pgm_idx )) != kOkRC )
+ {
+ rc = cwLogError(rc,"Program load failed.");
+ goto errLabel;
+ }
+
+ preset_cnt = program_preset_count(app->ioFlowH);
+
+ // populate the preset menu
+ for(unsigned i=0; iioH, uuId, pgmPresetSelUuId, nullptr, kPgmPresetBaseSelId+i, kInvalidId, "optClass", program_preset_title(app->ioFlowH,i) )) != kOkRC )
+ {
+ rc = cwLogError(rc,"Error on populating the program preset select widget.");
+ goto errLabel;
+ }
+ }
+
+ if( preset_cnt > 0 )
+ {
+ uiSetEnable( app->ioH, pgmPresetSelUuId, true );
+ app->pgm_preset_idx = 0; // since it is showing - select the first preset as the default preset
+ }
+
+ uiSetEnable( app->ioH, runCheckUuId, true );
+
+errLabel:
+ return rc;
+}
+
+rc_t _on_pgm_preset_select( app_t* app, unsigned pgmPresetSelOptId )
+{
+ rc_t rc = kOkRC;
+
+ if( !(kPgmPresetBaseSelId <= pgmPresetSelOptId && pgmPresetSelOptId <= kPgmPresetMaxSelId ) )
+ {
+ rc = cwLogError(kInvalidStateRC,"An invalid pgm preset select id was encountered.");
+ goto errLabel;
+ }
+
+ app->pgm_preset_idx = pgmPresetSelOptId - kPgmPresetBaseSelId;
+
+
+errLabel:
+
+ return rc;
+}
+
+rc_t _on_pgm_run( app_t* app, bool run_check_fl )
+{
+ rc_t rc = kOkRC;
+
+ printf("run:%i %i\n",run_check_fl,app->run_fl);
+
+ if( run_check_fl == app->run_fl )
+ return rc;
+
+ if( run_check_fl && !program_is_initialized( app->ioFlowH) )
+ {
+ if((rc = program_initialize(app->ioFlowH, app->pgm_preset_idx )) != kOkRC )
+ {
+ rc = cwLogError(rc,"Program initialization failed.");
+ goto errLabel;
+ }
+ }
+
+ app->run_fl = run_check_fl;
+
+errLabel:
+ return rc;
+}
+
+rc_t _on_ui_init( app_t* app )
+{
+ rc_t rc = kOkRC;
+ unsigned pgmSelUuId = io::uiFindElementUuId( app->ioH, kPgmSelId );
+ unsigned pgm_cnt = program_count(app->ioFlowH);
+
+ // create pgm menu
+ for(unsigned i=0; iioH, uuId, pgmSelUuId, nullptr, kPgmBaseSelId+i, kInvalidId, "optClass", program_title(app->ioFlowH,i) )) != kOkRC )
+ {
+ rc = cwLogError(rc,"Error on populating the program select widget.");
+ goto errLabel;
+ }
+
+ }
+
+ if( pgm_cnt )
+ _on_pgm_select(app, kPgmBaseSelId );
+
+errLabel:
+ return rc;
+}
+
+
rc_t _ui_value_callback(app_t* app, const io::ui_msg_t& m )
{
switch( m.appId )
@@ -159,6 +307,18 @@ rc_t _ui_value_callback(app_t* app, const io::ui_msg_t& m )
//app->value = m.value->u.u;
//cwLogInfo("Setting value:%i",app->value);
break;
+
+ case kPgmSelId:
+ _on_pgm_select(app,m.value->u.u);
+ break;
+
+ case kPgmPresetSelId:
+ _on_pgm_preset_select(app,m.value->u.u);
+ break;
+
+ case kRunCheckId:
+ _on_pgm_run(app,m.value->u.b);
+ break;
}
return kOkRC;
@@ -194,6 +354,8 @@ rc_t _ui_callback( app_t* app, const io::ui_msg_t& m )
case ui::kInitOpId:
cwLogInfo("UI Init.");
+ if( app->cmd_line_action_id == kUiSelId )
+ _on_ui_init(app);
break;
case ui::kValueOpId:
@@ -250,8 +412,29 @@ rc_t _io_callback( void* arg, const io::msg_t* m )
break;
case io::kAudioTId:
- if( is_executable(app->ioFlowH) && m != nullptr )
- io_flow_ctl::exec(app->ioFlowH,*m);
+ {
+ bool executable_fl = is_executable(app->ioFlowH);
+
+ // if the app is executable and we are in 'run' mode
+ if(app->run_fl && executable_fl && m != nullptr )
+ {
+ io_flow_ctl::exec(app->ioFlowH,*m);
+ }
+ else
+ {
+ if( m != nullptr )
+ for(unsigned i=0; iu.audio->oBufChCnt; ++i)
+ vop::zero(m->u.audio->oBufArray[i],m->u.audio->dspFrameCnt);
+ }
+
+ // if the app is not executable then we should exit run mode
+ if(app->run_fl && !executable_fl )
+ {
+ app->run_fl = false;
+ uiSendValue(app->ioH, io::uiFindElementUuId( app->ioH, kRunCheckId ), false );
+ }
+
+ }
break;
case io::kAudioMeterTId:
@@ -281,9 +464,10 @@ void _print_command_line_help()
{
const char* usage =
"Usage:\n"
- " caw exec \n"
- " caw hw_report \n"
- " caw test ( | all) ( | all) (compare | echo | gen_report )* {args ...}\n"
+ " caw ui {} : Run with a GUI.\n"
+ " caw exec : Run without a GUI.\n"
+ " caw hw_report : Print the hardware details and exit.\n"
+ " caw test ( | all) ( | all) (compare | echo | gen_report )* {args ...}\n"
" caw test_stub ...\n";
cwLogPrint(usage);
@@ -295,7 +479,7 @@ rc_t _parse_main_cfg( app_t& app, int argc, char* argv[] )
rc_t rc = kOkRC;
const char* io_cfg_fn = nullptr;
- if( argc < 1 )
+ if( argc < 2 )
{
rc = kInvalidArgRC;
_print_command_line_help();
@@ -303,33 +487,32 @@ rc_t _parse_main_cfg( app_t& app, int argc, char* argv[] )
}
// Get the selector-id associated with the first command line arg. (e.g. exec, hw_report, ...)
- if((app.appSelId = labelToId( appSelA, argv[1], kInvalidId )) == kInvalidId )
+ if((app.cmd_line_action_id = labelToId( appSelA, argv[1], kInvalidId )) == kInvalidId )
{
rc = cwLogError(kInvalidArgRC,"The command line action '%s' is not valid.",argv[1]);
_print_command_line_help();
}
- // if 'exec' or 'hw_report' was selected
- if( app.appSelId == kExecSelId || app.appSelId == kHwReportSelId )
+ // if 'ui,'exec' or 'hw_report' was selected
+ if( app.cmd_line_action_id==kUiSelId || app.cmd_line_action_id == kExecSelId || app.cmd_line_action_id == kHwReportSelId )
{
- if( argc <= 3 )
+ if( argc < 3 )
{
rc = cwLogError(kInvalidArgRC,"The command line is missing required arguments.");
_print_command_line_help();
}
- // get the fourth cmd line arg (pgm label of the program to run from the cfg file in arg[2])
- app.cmd_line_pgm_label = argv[3];
- app.cmd_line_cfg_fname = argv[2];
-
- if( app.cmd_line_cfg_fname == nullptr )
+ // store the pgm cfg fname
+ app.cmd_line_pgm_fname = argv[2];
+
+ if( app.cmd_line_pgm_fname == nullptr )
{
rc = cwLogError(kInvalidArgRC,"No 'caw' program cfg file was provided.");
goto errLabel;
}
// parse the cfg. file
- if((rc = objectFromFile(app.cmd_line_cfg_fname,app.flow_cfg)) != kOkRC )
+ if((rc = objectFromFile(app.cmd_line_pgm_fname,app.flow_cfg)) != kOkRC )
{
rc = cwLogError(rc,"Parsing failed on the cfg. file '%s'.",argv[1]);
goto errLabel;
@@ -348,6 +531,10 @@ rc_t _parse_main_cfg( app_t& app, int argc, char* argv[] )
goto errLabel;
}
+ // get the fourth cmd line arg (pgm label of the program to run from the cfg file in arg[2])
+ if( argc >= 4 )
+ app.cmd_line_pgm_label = argv[3];
+
}
errLabel:
@@ -365,7 +552,6 @@ rc_t _io_main( app_t& app )
goto errLabel;
}
-
// execute the IO framework
while( !io::isShuttingDown(app.ioH))
{
@@ -402,7 +588,7 @@ void _test_stub( app_t& app )
int main( int argc, char* argv[] )
{
rc_t rc = kOkRC;
- app_t app = {};
+ app_t app = { .pgm_preset_idx=kInvalidIdx }; // all zero except ...
bool exec_complete_fl = false;
cw::log::createGlobal();
@@ -412,7 +598,7 @@ int main( int argc, char* argv[] )
if((rc= _parse_main_cfg(app, argc, argv )) != kOkRC )
goto errLabel;
- switch( app.appSelId )
+ switch( app.cmd_line_action_id )
{
case kTestSelId:
_run_test_suite(argc-2, (const char**)(argv + 2));
@@ -445,28 +631,34 @@ int main( int argc, char* argv[] )
goto errLabel;
}
- switch( app.appSelId )
+ switch( app.cmd_line_action_id )
{
case kHwReportSelId:
hardwareReport(app.ioH);
goto errLabel;
break;
+ case kExecSelId:
+ // the pgm to exec must have given
+ if( app.cmd_line_pgm_label == nullptr )
+ {
+ rc = cwLogError(kInvalidArgRC,"The label of the program to execute from %s was not given.",cwStringNullGuard(app.cmd_line_pgm_fname));
+ goto errLabel;
+ }
+
+ // load the requested program - and execute it if it is in or non-GUI non-real-time mode
+ if((rc = _load_init_pgm_no_gui(app, app.cmd_line_pgm_label, exec_complete_fl )) != kOkRC )
+ {
+ goto errLabel;
+ }
+ break;
+
}
- // if we are here then then program 'exec' was requested
-
- if( app.cmd_line_pgm_label == nullptr )
- {
- rc = cwLogError(kInvalidArgRC,"The label of the program to execute from %s was not given.",cwStringNullGuard(app.cmd_line_cfg_fname));
- goto errLabel;
- }
-
- // load the requested program - and execute it if it is in non-real-time mode
- if((rc = _load_init_pgm(app, app.cmd_line_pgm_label, exec_complete_fl )) != kOkRC )
- goto errLabel;
-
-
+ // if we are here then then program 'ui' or 'exec' was requested
+ assert( app.cmd_line_action_id==kExecSelId || app.cmd_line_action_id==kUiSelId );
+
+ // non-real-time programs will have already executed
if( !exec_complete_fl )
_io_main(app);