From 4333cfccc89528c4095872a6e1a66b6b37f81401 Mon Sep 17 00:00:00 2001 From: Master92 Date: Fri, 8 Nov 2024 11:57:18 +0000 Subject: [PATCH 1/6] Add struct for generalized action description --- src/ui/page_input.c | 101 +++++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 30 deletions(-) diff --git a/src/ui/page_input.c b/src/ui/page_input.c index 8e8a49fd..80734256 100644 --- a/src/ui/page_input.c +++ b/src/ui/page_input.c @@ -31,18 +31,39 @@ typedef enum page_input_rows { ROW_COUNT } rowType_t; +typedef struct Action { + uint16_t id; + const char *name; + union { + void (* const btnFunction); + void (* const rollerFunction)(uint8_t); + } functionPtr; +} action_t; + /** * Compile-unit local variables, constants and fields */ static lv_coord_t col_dsc[] = {160, 200, 160, 160, 160, 120, LV_GRID_TEMPLATE_LAST}; static lv_coord_t row_dsc[] = {60, 60, 60, 60, 60, 60, 60, 60, 80, LV_GRID_TEMPLATE_LAST}; -const char *btnOptions[] = {"Toggle OSD", "Main menu", "Toggle DVR", "Center HT", "Calibrate HT", "Go Sleep!", "Toggle fan speed", "Star DVR", "Toggle source", "Cycle source"}; -void (* const btnFunctionPointers[])() = {&osd_toggle, &app_switch_to_menu, &dvr_toggle, &ht_set_center_position, &ht_calibrate, &go_sleep, &step_topfan, &dvr_star, &source_toggle, &source_cycle}; +static const action_t btnActions[] = { + {.id = 0, .name = "Toggle OSD", .functionPtr = &osd_toggle}, + {.id = 1, .name = "Main menu", .functionPtr = &app_switch_to_menu}, + {.id = 2, .name = "Toggle DVR", .functionPtr = &dvr_toggle}, + {.id = 3, .name = "Center HT", .functionPtr = &ht_set_center_position}, + {.id = 4, .name = "Calibrate HT", .functionPtr = &ht_calibrate}, + {.id = 5, .name = "Go Sleep!", .functionPtr = &go_sleep}, + {.id = 6, .name = "Toggle fan speed", .functionPtr = &step_topfan}, + {.id = 7, .name = "Star DVR", .functionPtr = &dvr_star}, + {.id = 8, .name = "Toggle source", .functionPtr = &source_toggle}, + {.id = 9, .name = "Cycle source", .functionPtr = &source_cycle}, +}; -const char *rollerOptions[] = {"Switch channel", "Change fan speed", "OLED Brightness"}; -void (* const rollerFunctionPointers[])(uint8_t) = {&tune_channel, &change_topfan, &change_oled_brightness}; -const uint16_t rollerDefaultOption = 0; +static const action_t rollerActions[] = { + {.id = 0, .name = "Switch channel", .functionPtr = &tune_channel}, + {.id = 1, .name = "Change fan speed", .functionPtr = &change_topfan}, + {.id = 2, .name = "OLED Brightness", .functionPtr = &change_oled_brightness} +}; static rowType_t selectedRow = ROW_COUNT; static lv_obj_t *pageItems[ROW_COUNT]; @@ -52,16 +73,36 @@ static uint16_t previousSelection; /** * Build a '\n'-separated list of all available options for the dropdown element */ -static void build_options_string(const char** input, size_t arraySize, char* output) { - output[0] = 0; - for (size_t i = 0; i < arraySize; i++) { - strcat(output, input[i]); - if (i < arraySize - 1) { +static void build_options_string(const action_t * const actions, size_t size, char* output) { + for (size_t i = 0; i < size; i++) { + strcat(output, actions[i].name); + if (i < size - 1) { strcat(output, "\n"); } } } +/** + * Get the action_t item from btnActions by the given id + * @return The action_t item or NULL if id was not found + */ +static const action_t* actionFromId(const action_t * const actions, size_t size, uint16_t id) { + for (size_t i = 0; i < size; i++) { + if (actions[i].id == id) { + return &actions[i]; + } + } + + return NULL; +} + +/** + * Get the array index of the action that has the given id. + */ +static size_t indexFromId(const action_t * const actions, size_t size, uint16_t id) { + return actionFromId(actions, size, id) - actions; +} + /** * Update the UI elements as the user navigates the page */ @@ -75,12 +116,12 @@ static void reset_dropdown_styles() { * Pick the associated function pointers for the globally configured actions */ static void update_inputs() { - roller_callback = rollerFunctionPointers[g_setting.inputs.roller]; - btn_click_callback = btnFunctionPointers[g_setting.inputs.left_click]; - btn_press_callback = btnFunctionPointers[g_setting.inputs.left_press]; - rbtn_click_callback = btnFunctionPointers[g_setting.inputs.right_click]; - rbtn_press_callback = btnFunctionPointers[g_setting.inputs.right_press]; - rbtn_double_click_callback = btnFunctionPointers[g_setting.inputs.right_double_click]; + roller_callback = actionFromId(rollerActions, ARRAY_SIZE(rollerActions), g_setting.inputs.roller)->functionPtr.rollerFunction; + btn_click_callback = actionFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.left_click)->functionPtr.btnFunction; + btn_press_callback = actionFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.left_press)->functionPtr.btnFunction; + rbtn_click_callback = actionFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_click)->functionPtr.btnFunction; + rbtn_press_callback = actionFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_press)->functionPtr.btnFunction; + rbtn_double_click_callback = actionFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_double_click)->functionPtr.btnFunction; } /** @@ -91,28 +132,28 @@ static void accept_dropdown(lv_obj_t *obj) { const uint16_t selectedOption = lv_dropdown_get_selected(obj); if (selectedRow == ROLLER) { - g_setting.inputs.roller = selectedOption; + g_setting.inputs.roller = rollerActions[selectedOption].id; ini_putl("inputs", "roller", g_setting.inputs.roller, SETTING_INI); } else { switch (selectedRow) { case LEFT_SHORT: - g_setting.inputs.left_click = selectedOption; + g_setting.inputs.left_click = btnActions[selectedOption].id; ini_putl("inputs", "left_click", g_setting.inputs.left_click, SETTING_INI); break; case LEFT_LONG: - g_setting.inputs.left_press = selectedOption; + g_setting.inputs.left_press = btnActions[selectedOption].id; ini_putl("inputs", "left_press", g_setting.inputs.left_press, SETTING_INI); break; case RIGHT_SHORT: - g_setting.inputs.right_click = selectedOption; + g_setting.inputs.right_click = btnActions[selectedOption].id; ini_putl("inputs", "right_click", g_setting.inputs.right_click, SETTING_INI); break; case RIGHT_LONG: - g_setting.inputs.right_press = selectedOption; + g_setting.inputs.right_press = btnActions[selectedOption].id; ini_putl("inputs", "right_press", g_setting.inputs.right_press, SETTING_INI); break; case RIGHT_DOUBLE: - g_setting.inputs.right_double_click = selectedOption; + g_setting.inputs.right_double_click = btnActions[selectedOption].id; ini_putl("inputs", "right_double_click", g_setting.inputs.right_double_click, SETTING_INI); break; default: @@ -156,9 +197,9 @@ static lv_obj_t *page_input_create(lv_obj_t *parent, panel_arr_t *arr) { } char rollerOptionsStr[128]; - build_options_string(rollerOptions, ARRAY_SIZE(rollerOptions), rollerOptionsStr); + build_options_string(rollerActions, ARRAY_SIZE(rollerActions), rollerOptionsStr); char btnOptionsStr[128]; - build_options_string(btnOptions, ARRAY_SIZE(btnOptions), btnOptionsStr); + build_options_string(btnActions, ARRAY_SIZE(btnActions), btnOptionsStr); lv_obj_t *page = lv_menu_page_create(parent, NULL); lv_obj_clear_flag(page, LV_OBJ_FLAG_SCROLLABLE); @@ -186,27 +227,27 @@ static lv_obj_t *page_input_create(lv_obj_t *parent, panel_arr_t *arr) { create_label_item(content, "Roller:", 1, ROLLER, 1); pageItems[ROLLER] = create_dropdown_item(content, rollerOptionsStr, 2, ROLLER, 320, row_dsc[ROLLER], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[ROLLER], g_setting.inputs.roller); + lv_dropdown_set_selected(pageItems[ROLLER], indexFromId(rollerActions, ARRAY_SIZE(rollerActions), g_setting.inputs.roller)); create_label_item(content, "Left short:", 1, LEFT_SHORT, 1); pageItems[LEFT_SHORT] = create_dropdown_item(content, btnOptionsStr, 2, LEFT_SHORT, 320, row_dsc[LEFT_SHORT], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[LEFT_SHORT], g_setting.inputs.left_click); + lv_dropdown_set_selected(pageItems[LEFT_SHORT], indexFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.left_click)); create_label_item(content, "Left long:", 1, LEFT_LONG, 1); pageItems[LEFT_LONG] = create_dropdown_item(content, btnOptionsStr, 2, LEFT_LONG, 320, row_dsc[LEFT_LONG], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[LEFT_LONG], g_setting.inputs.left_press); + lv_dropdown_set_selected(pageItems[LEFT_LONG], indexFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.left_press)); create_label_item(content, "Right short:", 1, RIGHT_SHORT, 1); pageItems[RIGHT_SHORT] = create_dropdown_item(content, btnOptionsStr, 2, RIGHT_SHORT, 320, row_dsc[RIGHT_SHORT], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[RIGHT_SHORT], g_setting.inputs.right_click); + lv_dropdown_set_selected(pageItems[RIGHT_SHORT], indexFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_click)); create_label_item(content, "Right long:", 1, RIGHT_LONG, 1); pageItems[RIGHT_LONG] = create_dropdown_item(content, btnOptionsStr, 2, RIGHT_LONG, 320, row_dsc[RIGHT_LONG], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[RIGHT_LONG], g_setting.inputs.right_press); + lv_dropdown_set_selected(pageItems[RIGHT_LONG], indexFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_press)); create_label_item(content, "Right double:", 1, RIGHT_DOUBLE, 1); pageItems[RIGHT_DOUBLE] = create_dropdown_item(content, btnOptionsStr, 2, RIGHT_DOUBLE, 320, row_dsc[RIGHT_DOUBLE], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[RIGHT_DOUBLE], g_setting.inputs.right_double_click); + lv_dropdown_set_selected(pageItems[RIGHT_DOUBLE], indexFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_double_click)); pageItems[BACK_BTN] = create_label_item(content, "< Back", 1, BACK_BTN, 1); From 19680e4784514a38e1b913fa5e097989b52c5d79 Mon Sep 17 00:00:00 2001 From: Master92 Date: Fri, 8 Nov 2024 12:09:13 +0000 Subject: [PATCH 2/6] Add inline forwarding overlay methods --- src/ui/page_input.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/ui/page_input.c b/src/ui/page_input.c index 80734256..e1663219 100644 --- a/src/ui/page_input.c +++ b/src/ui/page_input.c @@ -95,6 +95,8 @@ static const action_t* actionFromId(const action_t * const actions, size_t size, return NULL; } +static const action_t* btnActionFromId(uint16_t id) { return actionFromId(btnActions, ARRAY_SIZE(btnActions), id); } +static const action_t* rollerActionFromId(uint16_t id) { return actionFromId(rollerActions, ARRAY_SIZE(rollerActions), id); } /** * Get the array index of the action that has the given id. @@ -102,6 +104,8 @@ static const action_t* actionFromId(const action_t * const actions, size_t size, static size_t indexFromId(const action_t * const actions, size_t size, uint16_t id) { return actionFromId(actions, size, id) - actions; } +static size_t btnIndexFromId(uint16_t id) { return indexFromId(btnActions, ARRAY_SIZE(btnActions), (id)); } +static size_t rollerIndexFromId(uint16_t id) { return indexFromId(rollerActions, ARRAY_SIZE(rollerActions), (id)); } /** * Update the UI elements as the user navigates the page @@ -116,12 +120,12 @@ static void reset_dropdown_styles() { * Pick the associated function pointers for the globally configured actions */ static void update_inputs() { - roller_callback = actionFromId(rollerActions, ARRAY_SIZE(rollerActions), g_setting.inputs.roller)->functionPtr.rollerFunction; - btn_click_callback = actionFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.left_click)->functionPtr.btnFunction; - btn_press_callback = actionFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.left_press)->functionPtr.btnFunction; - rbtn_click_callback = actionFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_click)->functionPtr.btnFunction; - rbtn_press_callback = actionFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_press)->functionPtr.btnFunction; - rbtn_double_click_callback = actionFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_double_click)->functionPtr.btnFunction; + roller_callback = rollerActionFromId(g_setting.inputs.roller)->functionPtr.rollerFunction; + btn_click_callback = btnActionFromId(g_setting.inputs.left_click)->functionPtr.btnFunction; + btn_press_callback = btnActionFromId(g_setting.inputs.left_press)->functionPtr.btnFunction; + rbtn_click_callback = btnActionFromId(g_setting.inputs.right_click)->functionPtr.btnFunction; + rbtn_press_callback = btnActionFromId(g_setting.inputs.right_press)->functionPtr.btnFunction; + rbtn_double_click_callback = btnActionFromId(g_setting.inputs.right_double_click)->functionPtr.btnFunction; } /** @@ -227,27 +231,27 @@ static lv_obj_t *page_input_create(lv_obj_t *parent, panel_arr_t *arr) { create_label_item(content, "Roller:", 1, ROLLER, 1); pageItems[ROLLER] = create_dropdown_item(content, rollerOptionsStr, 2, ROLLER, 320, row_dsc[ROLLER], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[ROLLER], indexFromId(rollerActions, ARRAY_SIZE(rollerActions), g_setting.inputs.roller)); + lv_dropdown_set_selected(pageItems[ROLLER], rollerIndexFromId(g_setting.inputs.roller)); create_label_item(content, "Left short:", 1, LEFT_SHORT, 1); pageItems[LEFT_SHORT] = create_dropdown_item(content, btnOptionsStr, 2, LEFT_SHORT, 320, row_dsc[LEFT_SHORT], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[LEFT_SHORT], indexFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.left_click)); + lv_dropdown_set_selected(pageItems[LEFT_SHORT], btnIndexFromId(g_setting.inputs.left_click)); create_label_item(content, "Left long:", 1, LEFT_LONG, 1); pageItems[LEFT_LONG] = create_dropdown_item(content, btnOptionsStr, 2, LEFT_LONG, 320, row_dsc[LEFT_LONG], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[LEFT_LONG], indexFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.left_press)); + lv_dropdown_set_selected(pageItems[LEFT_LONG], btnIndexFromId(g_setting.inputs.left_press)); create_label_item(content, "Right short:", 1, RIGHT_SHORT, 1); pageItems[RIGHT_SHORT] = create_dropdown_item(content, btnOptionsStr, 2, RIGHT_SHORT, 320, row_dsc[RIGHT_SHORT], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[RIGHT_SHORT], indexFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_click)); + lv_dropdown_set_selected(pageItems[RIGHT_SHORT], btnIndexFromId(g_setting.inputs.right_click)); create_label_item(content, "Right long:", 1, RIGHT_LONG, 1); pageItems[RIGHT_LONG] = create_dropdown_item(content, btnOptionsStr, 2, RIGHT_LONG, 320, row_dsc[RIGHT_LONG], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[RIGHT_LONG], indexFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_press)); + lv_dropdown_set_selected(pageItems[RIGHT_LONG], btnIndexFromId(g_setting.inputs.right_press)); create_label_item(content, "Right double:", 1, RIGHT_DOUBLE, 1); pageItems[RIGHT_DOUBLE] = create_dropdown_item(content, btnOptionsStr, 2, RIGHT_DOUBLE, 320, row_dsc[RIGHT_DOUBLE], 2, 10, LV_GRID_ALIGN_START, &lv_font_montserrat_26); - lv_dropdown_set_selected(pageItems[RIGHT_DOUBLE], indexFromId(btnActions, ARRAY_SIZE(btnActions), g_setting.inputs.right_double_click)); + lv_dropdown_set_selected(pageItems[RIGHT_DOUBLE], btnIndexFromId(g_setting.inputs.right_double_click)); pageItems[BACK_BTN] = create_label_item(content, "< Back", 1, BACK_BTN, 1); From 98fb8d51313c25354f4d8e711487e821fc507966 Mon Sep 17 00:00:00 2001 From: Master92 Date: Fri, 8 Nov 2024 12:18:32 +0000 Subject: [PATCH 3/6] Add do nothing methods for buttons and roller --- src/ui/page_input.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ui/page_input.c b/src/ui/page_input.c index e1663219..8c502f2d 100644 --- a/src/ui/page_input.c +++ b/src/ui/page_input.c @@ -46,7 +46,11 @@ typedef struct Action { static lv_coord_t col_dsc[] = {160, 200, 160, 160, 160, 120, LV_GRID_TEMPLATE_LAST}; static lv_coord_t row_dsc[] = {60, 60, 60, 60, 60, 60, 60, 60, 80, LV_GRID_TEMPLATE_LAST}; +static void nop() {} +static void rollerNop(uint8_t key) { (void) key; } + static const action_t btnActions[] = { + {.id = 10, .name = "None", .functionPtr = &nop}, {.id = 0, .name = "Toggle OSD", .functionPtr = &osd_toggle}, {.id = 1, .name = "Main menu", .functionPtr = &app_switch_to_menu}, {.id = 2, .name = "Toggle DVR", .functionPtr = &dvr_toggle}, @@ -60,6 +64,7 @@ static const action_t btnActions[] = { }; static const action_t rollerActions[] = { + {.id = 3, .name = "None", .functionPtr = &rollerNop}, {.id = 0, .name = "Switch channel", .functionPtr = &tune_channel}, {.id = 1, .name = "Change fan speed", .functionPtr = &change_topfan}, {.id = 2, .name = "OLED Brightness", .functionPtr = &change_oled_brightness} From 74e066d371566160c32617b1cf567ae34097f9c6 Mon Sep 17 00:00:00 2001 From: Master92 Date: Fri, 8 Nov 2024 12:46:08 +0000 Subject: [PATCH 4/6] Initialize local char array with a zero-length string --- src/ui/page_input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/page_input.c b/src/ui/page_input.c index 8c502f2d..f18b551f 100644 --- a/src/ui/page_input.c +++ b/src/ui/page_input.c @@ -205,9 +205,9 @@ static lv_obj_t *page_input_create(lv_obj_t *parent, panel_arr_t *arr) { contentWidth += col_dsc[i]; } - char rollerOptionsStr[128]; + char rollerOptionsStr[128] = ""; build_options_string(rollerActions, ARRAY_SIZE(rollerActions), rollerOptionsStr); - char btnOptionsStr[128]; + char btnOptionsStr[128] = ""; build_options_string(btnActions, ARRAY_SIZE(btnActions), btnOptionsStr); lv_obj_t *page = lv_menu_page_create(parent, NULL); From 8cf8e584a91537cafbfc8b5dc85ed261393569ef Mon Sep 17 00:00:00 2001 From: Master92 Date: Tue, 12 Nov 2024 12:53:47 +0000 Subject: [PATCH 5/6] Also rename the star file --- src/ui/page_playback.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ui/page_playback.c b/src/ui/page_playback.c index ff120643..c8d98791 100644 --- a/src/ui/page_playback.c +++ b/src/ui/page_playback.c @@ -354,6 +354,8 @@ static void mark_video_file(int const seq) { system_exec(cmd); sprintf(cmd, "mv %s%s." REC_packJPG " %s%s." REC_packJPG, MEDIA_FILES_DIR, pnode->label, MEDIA_FILES_DIR, newLabel); system_exec(cmd); + sprintf(cmd, "mv %s%s" REC_starSUFFIX " %s%s.%s" REC_starSUFFIX, MEDIA_FILES_DIR, pnode->filename, MEDIA_FILES_DIR, newLabel, pnode->ext); + system_exec(cmd); walk_sdcard(); media_db.cur_sel = constrain(seq, 0, (media_db.count - 1)); From 34a19b254453b8da27e415a87b438ad2afc450ac Mon Sep 17 00:00:00 2001 From: Master92 Date: Tue, 12 Nov 2024 09:05:01 +0000 Subject: [PATCH 6/6] Fix disappearing navigation box --- src/ui/page_playback.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ui/page_playback.c b/src/ui/page_playback.c index ff120643..40954409 100644 --- a/src/ui/page_playback.c +++ b/src/ui/page_playback.c @@ -325,6 +325,10 @@ static void update_page() { } static void update_item(uint8_t cur_pos, uint8_t lst_pos) { + if (cur_pos == lst_pos) { + return; + } + lv_obj_clear_flag(pb_ui[cur_pos]._arrow, LV_OBJ_FLAG_HIDDEN); lv_obj_remove_style(pb_ui[cur_pos]._img, &style_pb_dark, LV_PART_MAIN); lv_obj_add_style(pb_ui[cur_pos]._img, &style_pb, LV_PART_MAIN);