diff --git a/companion/src/firmwares/customfunctiondata.cpp b/companion/src/firmwares/customfunctiondata.cpp index 10083fba32c..64217322ec9 100644 --- a/companion/src/firmwares/customfunctiondata.cpp +++ b/companion/src/firmwares/customfunctiondata.cpp @@ -394,6 +394,19 @@ AbstractStaticItemModel * CustomFunctionData::repeatItemModel() return mdl; } +// static +AbstractStaticItemModel * CustomFunctionData::repeatLuaItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName("customfunctiondata.repeatLua"); + + mdl->appendToItemList(tr("On"), 0); + mdl->appendToItemList(tr("1x"), 1); + + mdl->loadItemList(); + return mdl; +} + // static AbstractStaticItemModel * CustomFunctionData::playSoundItemModel() { diff --git a/companion/src/firmwares/customfunctiondata.h b/companion/src/firmwares/customfunctiondata.h index 717ac05bffa..c27bdf71383 100644 --- a/companion/src/firmwares/customfunctiondata.h +++ b/companion/src/firmwares/customfunctiondata.h @@ -136,6 +136,7 @@ class CustomFunctionData { static QStringList gvarAdjustModeStringList(); static QString gvarAdjustModeToString(const int value); static AbstractStaticItemModel * repeatItemModel(); + static AbstractStaticItemModel * repeatLuaItemModel(); static AbstractStaticItemModel * playSoundItemModel(); static AbstractStaticItemModel * harpicItemModel(); static AbstractStaticItemModel * gvarAdjustModeItemModel(); diff --git a/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp b/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp index 50f82a1fbd9..d8ec947bb30 100644 --- a/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp +++ b/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp @@ -37,7 +37,8 @@ static bool fnHasRepeat(AssignFunc fn) || (fn == FuncPlayValue) || (fn == FuncPlayHaptic) || (fn == FuncPlaySound) - || (fn == FuncSetScreen); + || (fn == FuncSetScreen) + || (fn == FuncPlayScript); } static const YamlLookupTable customFnLut = { @@ -225,7 +226,9 @@ Node convert::encode(const CustomFunctionData& rhs) if (add_comma) { def += ","; } - if (rhs.repeatParam == 0) { + if (rhs.func == FuncPlayScript) { + def += ((rhs.repeatParam == 0) ? "On" : "1x"); + } else if (rhs.repeatParam == 0) { def += "1x"; } else if (rhs.repeatParam == -1) { def += "!1x"; @@ -374,7 +377,9 @@ bool convert::decode(const Node& node, } else if(fnHasRepeat(rhs.func)) { std::string repeat; getline(def, repeat); - if (repeat == "1x") { + if (rhs.func == FuncPlayScript) { + rhs.repeatParam = (repeat == "1x") ? 1 : 0; + } else if (repeat == "1x") { rhs.repeatParam = 0; } else if (repeat == "!1x") { rhs.repeatParam = -1; diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index c4ec20063d8..78a63fe8713 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -39,6 +39,7 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, playSoundId = tabModelFactory->registerItemModel(CustomFunctionData::playSoundItemModel()); harpicId = tabModelFactory->registerItemModel(CustomFunctionData::harpicItemModel()); repeatId = tabModelFactory->registerItemModel(CustomFunctionData::repeatItemModel()); + repeatLuaId = tabModelFactory->registerItemModel(CustomFunctionData::repeatLuaItemModel()); gvarAdjustModeId = tabModelFactory->registerItemModel(CustomFunctionData::gvarAdjustModeItemModel()); tabFilterFactory = new FilteredItemModelFactory(); @@ -193,7 +194,10 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, tableLayout->addLayout(i, 4, repeatLayout); fswtchRepeat[i] = new QComboBox(this); fswtchRepeat[i]->setProperty("index", i); - fswtchRepeat[i]->setModel(tabModelFactory->getItemModel(repeatId)); + if (functions[i].func == FuncPlayScript) + fswtchRepeat[i]->setModel(tabModelFactory->getItemModel(repeatLuaId)); + else + fswtchRepeat[i]->setModel(tabModelFactory->getItemModel(repeatId)); fswtchRepeat[i]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); fswtchRepeat[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents); repeatLayout->addWidget(fswtchRepeat[i], i + 1); @@ -324,6 +328,10 @@ void CustomFunctionsPanel::functionEdited() functions[index].clear(); functions[index].swtch = swtch; functions[index].func = (AssignFunc)fswtchFunc[index]->currentData().toInt(); + if (functions[index].func == FuncPlayScript) + fswtchRepeat[index]->setModel(tabModelFactory->getItemModel(repeatLuaId)); + else + fswtchRepeat[index]->setModel(tabModelFactory->getItemModel(repeatId)); refreshCustomFunction(index); emit modified(); lock = false; @@ -523,11 +531,13 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) } } else if (func == FuncPlayScript) { - widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM; + widgetsMask |= CUSTOM_FUNCTION_FILE_PARAM | CUSTOM_FUNCTION_REPEAT; if (modified) { Helpers::getFileComboBoxValue(fswtchParamArmT[i], cfn.paramarm, 8); + cfn.repeatParam = fswtchRepeat[i]->currentData().toInt(); } Helpers::populateFileComboBox(fswtchParamArmT[i], scriptsSet, cfn.paramarm); + fswtchRepeat[i]->setCurrentIndex(fswtchRepeat[i]->findData(cfn.repeatParam)); } else { if (modified) diff --git a/companion/src/modeledit/customfunctions.h b/companion/src/modeledit/customfunctions.h index 87775246d42..2bede10d627 100644 --- a/companion/src/modeledit/customfunctions.h +++ b/companion/src/modeledit/customfunctions.h @@ -87,6 +87,7 @@ class CustomFunctionsPanel : public GenericPanel int playSoundId; int harpicId; int repeatId; + int repeatLuaId; int gvarAdjustModeId; QSet tracksSet; diff --git a/radio/src/gui/128x64/model_special_functions.cpp b/radio/src/gui/128x64/model_special_functions.cpp index 16377d0f97d..6fa6cbe7612 100644 --- a/radio/src/gui/128x64/model_special_functions.cpp +++ b/radio/src/gui/128x64/model_special_functions.cpp @@ -307,7 +307,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF #if defined(SDCARD) else if (func == FUNC_PLAY_TRACK || func == FUNC_BACKGND_MUSIC || func == FUNC_PLAY_SCRIPT) { if (ZEXIST(cfn->play.name)) - lcdDrawSizedText(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, cfn->play.name, sizeof(cfn->play.name), attr); + lcdDrawSizedText(MODEL_SPECIAL_FUNC_3RD_COLUMN-6, y, cfn->play.name, sizeof(cfn->play.name), attr); else lcdDrawTextAtIndex(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, STR_VCSWFUNC, 0, attr); if (active && event==EVT_KEY_BREAK(KEY_ENTER)) { @@ -438,16 +438,22 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF if (active) CFN_ACTIVE(cfn) = checkIncDec(event, CFN_ACTIVE(cfn), 0, 1, eeFlags); } else if (HAS_REPEAT_PARAM(func)) { - if (CFN_PLAY_REPEAT(cfn) == 0) { - lcdDrawChar(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF+3, y, '-', attr); - } - else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) { - lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF+1, y, "!-", attr); + if (func == FUNC_PLAY_SCRIPT) { + lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF-3, y, (CFN_PLAY_REPEAT(cfn) == 0) ? "On" : "1x", attr); + if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn), 0, 1, eeFlags); } else { - lcdDrawNumber(MODEL_SPECIAL_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(cfn)*CFN_PLAY_REPEAT_MUL, RIGHT | attr); + if (CFN_PLAY_REPEAT(cfn) == 0) { + lcdDrawChar(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF+3, y, '-', attr); + } + else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) { + lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF+1, y, "!-", attr); + } + else { + lcdDrawNumber(MODEL_SPECIAL_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(cfn)*CFN_PLAY_REPEAT_MUL, RIGHT | attr); + } + if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(cfn), -1, 60/CFN_PLAY_REPEAT_MUL, eeFlags); } - if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(cfn), -1, 60/CFN_PLAY_REPEAT_MUL, eeFlags); } else if (attr) { REPEAT_LAST_CURSOR_MOVE(); diff --git a/radio/src/gui/212x64/model_special_functions.cpp b/radio/src/gui/212x64/model_special_functions.cpp index ab4e1eb006d..16c830cf0ac 100644 --- a/radio/src/gui/212x64/model_special_functions.cpp +++ b/radio/src/gui/212x64/model_special_functions.cpp @@ -416,18 +416,24 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF if (active) CFN_ACTIVE(cfn) = checkIncDec(event, CFN_ACTIVE(cfn), 0, 1, eeFlags); } else if (HAS_REPEAT_PARAM(func)) { - if (CFN_PLAY_REPEAT(cfn) == 0) { - lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN+2, y, "1x", attr); - } - else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) { - lcdDrawChar(MODEL_SPECIAL_FUNC_4TH_COLUMN-1, y, '!', attr); - lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN+2, y, "1x", attr); + if (func == FUNC_PLAY_SCRIPT) { + lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN+2, y, (CFN_PLAY_REPEAT(cfn) == 0) ? "On" : "1x", attr); + if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn), 0, 1, eeFlags); } else { - lcdDrawNumber(MODEL_SPECIAL_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(cfn)*CFN_PLAY_REPEAT_MUL, attr|RIGHT); - lcdDrawChar(MODEL_SPECIAL_FUNC_4TH_COLUMN+2+FW, y, 's', attr); + if (CFN_PLAY_REPEAT(cfn) == 0) { + lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN+2, y, "1x", attr); + } + else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) { + lcdDrawChar(MODEL_SPECIAL_FUNC_4TH_COLUMN-1, y, '!', attr); + lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN+2, y, "1x", attr); + } + else { + lcdDrawNumber(MODEL_SPECIAL_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(cfn)*CFN_PLAY_REPEAT_MUL, attr|RIGHT); + lcdDrawChar(MODEL_SPECIAL_FUNC_4TH_COLUMN+2+FW, y, 's', attr); + } + if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(cfn), -1, 60/CFN_PLAY_REPEAT_MUL, eeFlags); } - if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(cfn), -1, 60/CFN_PLAY_REPEAT_MUL, eeFlags); } else if (attr) { REPEAT_LAST_CURSOR_MOVE(); diff --git a/radio/src/gui/colorlcd/special_functions.cpp b/radio/src/gui/colorlcd/special_functions.cpp index 021638ea852..0e3041c8686 100644 --- a/radio/src/gui/colorlcd/special_functions.cpp +++ b/radio/src/gui/colorlcd/special_functions.cpp @@ -331,20 +331,28 @@ class SpecialFunctionEditPage : public Page line = specialFunctionOneWindow->newLine(&grid); new StaticText(line, rect_t{}, STR_REPEAT, 0, COLOR_THEME_PRIMARY1); - auto repeat = new NumberEdit( - line, rect_t{}, -1, - 60 / CFN_PLAY_REPEAT_MUL, GET_DEFAULT((int8_t)CFN_PLAY_REPEAT(cfn)), - SET_DEFAULT(CFN_PLAY_REPEAT(cfn))); - repeat->setDisplayHandler( - [](int32_t value) { - if (value == 0) - return std::string("1x"); - else if (value == (int8_t)CFN_PLAY_REPEAT_NOSTART) - return std::string("!1x"); - else { - return formatNumberAsString(value * CFN_PLAY_REPEAT_MUL, 0, 0, nullptr, "s"); - } - }); + if (func == FUNC_PLAY_SCRIPT) { + auto repeat = new Choice(line, rect_t{}, 0, 1, + GET_DEFAULT((int8_t)CFN_PLAY_REPEAT(cfn)), + SET_DEFAULT(CFN_PLAY_REPEAT(cfn))); + repeat->setTextHandler([](int32_t value) { + // 0 == repeat at 50ms interval for backward compatibility + return (value == 0) ? std::string("On") : std::string("1x"); + }); + } else { + auto repeat = new NumberEdit(line, rect_t{}, 0, 60 / CFN_PLAY_REPEAT_MUL, + GET_DEFAULT((int8_t)CFN_PLAY_REPEAT(cfn)), + SET_DEFAULT(CFN_PLAY_REPEAT(cfn))); + repeat->setDisplayHandler([](int32_t value) { + if (value == 0) + return std::string("1x"); + else if (value == (int8_t)CFN_PLAY_REPEAT_NOSTART) + return std::string("!1x"); + else { + return formatNumberAsString(value * CFN_PLAY_REPEAT_MUL, 0, 0, nullptr, "s"); + } + }); + } } } @@ -653,11 +661,15 @@ class SpecialFunctionButton : public Button lv_obj_clear_state(sfEnable, LV_STATE_CHECKED); lv_obj_clear_flag(sfEnable, LV_OBJ_FLAG_HIDDEN); } else if (HAS_REPEAT_PARAM(func)) { - sprintf(s, "(%s)", - (CFN_PLAY_REPEAT(cfn) == 0) ? "1x" : - (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) ? "!1x" : - formatNumberAsString(CFN_PLAY_REPEAT(cfn) * CFN_PLAY_REPEAT_MUL, 0, 0, nullptr, "s").c_str() - ); + if (func == FUNC_PLAY_SCRIPT) { + sprintf(s, "(%s)", (CFN_PLAY_REPEAT(cfn) == 0) ? "On" : "1x"); + } else { + sprintf(s, "(%s)", + (CFN_PLAY_REPEAT(cfn) == 0) ? "1x" : + (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) ? "!1x" : + formatNumberAsString(CFN_PLAY_REPEAT(cfn) * CFN_PLAY_REPEAT_MUL, 0, 0, nullptr, "s").c_str() + ); + } } lv_label_set_text(sfRepeat, s); diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index 6f9a5906a65..e7066910bb4 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -1083,15 +1083,25 @@ static bool resumeLua(bool init, bool allowLcdUsage) } else #endif if (ref <= SCRIPT_GFUNC_LAST) { + uint8_t idx; CustomFunctionData * fn; - - if (ref <= SCRIPT_FUNC_LAST) - fn = &g_model.customFn[ref - SCRIPT_FUNC_FIRST]; - else - fn = &g_eeGeneral.customFn[ref - SCRIPT_GFUNC_FIRST]; - - if (getSwitch(fn -> swtch)) { + CustomFunctionsContext * functionsContext; + + if (ref <= SCRIPT_FUNC_LAST) { + idx = ref - SCRIPT_FUNC_FIRST; + fn = &g_model.customFn[idx]; + functionsContext = &modelFunctionsContext; + } else { + idx = ref - SCRIPT_GFUNC_FIRST; + fn = &g_eeGeneral.customFn[idx]; + functionsContext = &globalFunctionsContext; + } + + tmr10ms_t tmr10ms = get_tmr10ms(); + + if (getSwitch(fn->swtch) && (functionsContext->lastFunctionTime[idx] == 0 || CFN_PLAY_REPEAT(fn) == 0)) { lua_rawgeti(lsScripts, LUA_REGISTRYINDEX, sid.run); + functionsContext->lastFunctionTime[idx] = tmr10ms; } else { if (sid.background == LUA_NOREF) continue; diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 84e74307cfc..4b4bd296900 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -61,9 +61,9 @@ #define HAS_ENABLE_PARAM(func) ((func) < FUNC_FIRST_WITHOUT_ENABLE || (func == FUNC_BACKLIGHT)) #if defined(COLORLCD) -#define HAS_REPEAT_PARAM(func) (IS_PLAY_FUNC(func) || IS_HAPTIC_FUNC(func) || func == FUNC_SET_SCREEN) +#define HAS_REPEAT_PARAM(func) (IS_PLAY_FUNC(func) || IS_HAPTIC_FUNC(func) || func == FUNC_PLAY_SCRIPT || func == FUNC_SET_SCREEN) #else -#define HAS_REPEAT_PARAM(func) (IS_PLAY_FUNC(func) || IS_HAPTIC_FUNC(func) ) +#define HAS_REPEAT_PARAM(func) (IS_PLAY_FUNC(func) || IS_HAPTIC_FUNC(func) || func == FUNC_PLAY_SCRIPT) #endif #define CFN_EMPTY(p) (!(p)->swtch) diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index ef8b5980ccb..9637fae6bc1 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -1477,7 +1477,12 @@ static void r_customFn(void* user, uint8_t* data, uint32_t bitoffs, } } } else if (HAS_REPEAT_PARAM(func)) { - if (val_len == 2 + if (func == FUNC_PLAY_SCRIPT) { + if (val_len == 2 && val[0] == '1' && val[1] == 'x') + CFN_PLAY_REPEAT(cfn) = 1; + else + CFN_PLAY_REPEAT(cfn) = 0; + } else if (val_len == 2 && val[0] == '1' && val[1] == 'x') { CFN_PLAY_REPEAT(cfn) = 0; @@ -1629,7 +1634,9 @@ static bool w_customFn(void* user, uint8_t* data, uint32_t bitoffs, // "," if (!wf(opaque,",",1)) return false; } - if (CFN_PLAY_REPEAT(cfn) == 0) { + if (func == FUNC_PLAY_SCRIPT) { + if (!wf(opaque,(CFN_PLAY_REPEAT(cfn) == 0) ? "On" : "1x",2)) return false; + } else if (CFN_PLAY_REPEAT(cfn) == 0) { // "1x" if (!wf(opaque,"1x",2)) return false; } else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) {