🚸 Simplified Media Menu

This commit is contained in:
Scott Lahteine 2025-04-24 11:20:15 -05:00
parent f78aaf9562
commit 99c29cd924
11 changed files with 171 additions and 76 deletions

View file

@ -36,7 +36,7 @@ uint32_t Password::value, Password::value_entry;
//
// Authenticate user with password.
// Called from Setup, after SD Prinitng Stops/Aborts, and M510
// Called from Setup, after SD Printing Stops/Aborts, and M510
//
void Password::lock_machine() {
is_locked = true;

View file

@ -37,6 +37,8 @@ public:
static void access_menu_password();
static void authentication_done();
static void media_gatekeeper();
static void media_gatekeeper_sd();
static void media_gatekeeper_usb();
private:
static void authenticate_user(const screenFunc_t, const screenFunc_t);

View file

@ -175,9 +175,9 @@ void TFTGLCD::clr_screen() {
SPI_SEND_ONE(CLR_SCREEN);
WRITE(TFTGLCD_CS, HIGH);
#else
Wire.beginTransmission(uint8_t(LCD_I2C_ADDRESS)); //set I2C device address
Wire.beginTransmission(uint8_t(LCD_I2C_ADDRESS)); // Transmit to LCD via I2C
Wire.write(CLR_SCREEN);
Wire.endTransmission(); //transmit data
Wire.endTransmission(); // Send the data
#endif
}
@ -378,10 +378,6 @@ void MarlinUI::clear_for_drawing() { clear_lcd(); }
void MarlinUI::_set_contrast() { lcd.setContrast(contrast); }
#endif
#if !IS_TFTGLCD_PANEL
void lcd_moveto(const uint8_t col, const uint8_t row) { lcd.setCursor(col, row); }
#endif
static void center_text(FSTR_P const fstart, const uint8_t y) {
const uint8_t len = utf8_strlen(fstart);
lcd_moveto(len < LCD_WIDTH ? (LCD_WIDTH - len) / 2 : 0, y);

View file

@ -574,10 +574,8 @@ namespace LanguageNarrow_en {
LSTR MSG_CANCEL_OBJECT = _UxGT("Cancel Obj");
LSTR MSG_CANCEL_OBJECT_N = _UxGT("Cancel Obj {");
LSTR MSG_CONTINUE_PRINT_JOB = _UxGT("Continue Job");
LSTR MSG_MEDIA_MENU = MEDIA_TYPE_EN _UxGT(" Print");
LSTR MSG_TURN_OFF = _UxGT("Turn off now");
LSTR MSG_END_LOOPS = _UxGT("End Loops");
LSTR MSG_NO_MEDIA = _UxGT("No ") MEDIA_TYPE_EN;
LSTR MSG_DWELL = _UxGT("Sleep...");
LSTR MSG_USERWAIT = _UxGT("Click to Resume...");
LSTR MSG_PRINT_PAUSED = _UxGT("Print Paused");
@ -641,6 +639,10 @@ namespace LanguageNarrow_en {
LSTR MSG_RUN_AUTOFILES = _UxGT("Run Autofiles");
LSTR MSG_RUN_AUTOFILES_SD = _UxGT("Run SD Autofiles");
LSTR MSG_RUN_AUTOFILES_USB = _UxGT("Run USB Autofiles");
LSTR MSG_MEDIA_MENU = MEDIA_TYPE_EN _UxGT(" Print");
LSTR MSG_MEDIA_MENU_SD = _UxGT("Select from SD");
LSTR MSG_MEDIA_MENU_USB = _UxGT("Select from USB");
LSTR MSG_NO_MEDIA = _UxGT("No ") MEDIA_TYPE_EN _UxGT(" Detected");
LSTR MSG_ZPROBE_OUT = _UxGT("Z Probe Past Bed");
LSTR MSG_SKEW_FACTOR = _UxGT("Skew Factor");
@ -1130,6 +1132,9 @@ namespace LanguageWide_en {
LSTR MSG_CANCEL_OBJECT_N = _UxGT("Cancel Object {");
LSTR MSG_CONTINUE_PRINT_JOB = _UxGT("Continue Print Job");
LSTR MSG_MEDIA_MENU = _UxGT("Select from ") MEDIA_TYPE_EN;
LSTR MSG_MEDIA_MENU_SD = _UxGT("Select from SD Card");
LSTR MSG_MEDIA_MENU_USB = _UxGT("Select from USB Drive");
LSTR MSG_NO_MEDIA = _UxGT("No ") MEDIA_TYPE_EN _UxGT(" Found");
LSTR MSG_TURN_OFF = _UxGT("Turn off the printer");
LSTR MSG_END_LOOPS = _UxGT("End Repeat Loops");
LSTR MSG_MEDIA_NOT_INSERTED = _UxGT("No media inserted."); // ProUI

View file

@ -255,7 +255,9 @@ public:
#endif
#if HAS_MEDIA
#define MEDIA_MENU_GATEWAY TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper, menu_media)
#define MEDIA_MENU_GATEWAY TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper, menu_file_selector)
#define MEDIA_MENU_GATEWAY_SD TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper_sd, menu_file_selector_sd)
#define MEDIA_MENU_GATEWAY_USB TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper_usb, menu_file_selector_usb)
static void media_changed(const MediaPresence old_stat, const MediaPresence stat);
#endif
@ -864,7 +866,7 @@ public:
TERN_(REVERSE_SELECT_DIRECTION, encoderDirection = -(ENCODERBASE));
}
#else
#else // !HAS_ENCODER_ACTION
static void update_buttons() {}
static bool hw_button_pressed() { return false; }

View file

@ -212,7 +212,8 @@ void menu_move();
#if HAS_MEDIA
void menu_file_selector();
void menu_media();
void menu_file_selector_sd();
void menu_file_selector_usb();
#endif
////////////////////////////////////////////

View file

@ -226,6 +226,9 @@ class MenuItem_bool : public MenuEditItemBase {
* should be done before the menu loop (START_MENU / START_SCREEN).
*/
// CAUTION! When using menu items in a lambda or sub-function always use:
#define INJECT_MENU_ITEMS(FN) { FN; if (ui.screen_changed) return; }
/**
* SCREEN_OR_MENU_LOOP generates header code for a screen or menu
*

View file

@ -237,8 +237,8 @@ void menu_configuration();
void menu_main() {
const bool busy = printingIsActive();
#if HAS_MEDIA
const bool card_detected = card.isMounted(),
card_open = card_detected && card.isFileOpen();
const bool card_is_mounted = card.isMounted(),
card_open = card_is_mounted && card.isFileOpen();
#endif
START_MENU();
@ -248,45 +248,123 @@ void menu_main() {
#define MEDIA_MENU_AT_TOP
#endif
auto media_menus = [&]{
#if HAS_MEDIA
if (card_detected) {
if (!card_open) {
#if ENABLED(MENU_ADDAUTOSTART)
ACTION_ITEM(MSG_RUN_AUTOFILES, card.autofile_begin); // Run Auto Files
#endif
// Show "Attach" for drives that don't auto-detect media (yet)
//#define ATTACH_WITHOUT_INSERT_SD
#define ATTACH_WITHOUT_INSERT_USB
#if HAS_SD_DETECT
GCODES_ITEM(MSG_CHANGE_MEDIA, F("M21" TERN_(HAS_MULTI_VOLUME, "S"))); // M21 Change Media
#if HAS_MULTI_VOLUME
GCODES_ITEM(MSG_ATTACH_USB, F("M21U")); // M21 Attach USB Media
#endif
#else // - or -
ACTION_ITEM(MSG_RELEASE_MEDIA, []{ // M22 Release Media
queue.inject(F("M22"));
#if ENABLED(TFT_COLOR_UI)
// Menu display issue on item removal with multi language selection menu
if (encoderTopLine > 0) encoderTopLine--;
ui.refresh();
#endif
});
#endif
SUBMENU(MSG_MEDIA_MENU, MEDIA_MENU_GATEWAY); // Media Menu (or Password First)
}
// Show all "inserted" drives and mount as-needed
#define SHOW_UNMOUNTED_DRIVES
/**
* Previously:
* - The "selected" media is mounted?
* - [Run Auto Files]
* - HAS_SD_DETECT:
* - [Change Media] = M21 / M21S
* - HAS_MULTI_VOLUME?
* - [Attach USB Drive] = M21U
* - ELSE:
* - [Release Media] = M22
* - [Select from Media] (or Password Gateway) >
*
* - The "selected" media is not mounted?
* - HAS_SD_DETECT?
* - [No Media] (does nothing)
* - HAS_MULTI_VOLUME?
* - [Attach SD Card] = M21S
* - [Attach USB Drive] = M21U
* - ELSE:
* - [Attach Media] = M21
*
* Updated:
* - Something is mounted?
* - [Run SD/USB Autofiles]
* - [Release SD/USB] = M22
* - [Select from SD/USB] (or Password Gateway) >
*
* - Something is inserted and SHOW_UNMOUNTED_DRIVES?
* - [Select from SD/USB] (or Password Gateway) >
*
* - The "selected" Card is NOT DETECTED?
* - Trust all media detect methods?
* - [No Media] (does nothing)
* - HAS_MULTI_VOLUME?
* - [Attach SD Card] = M21S
* - [Attach USB Drive] = M21U
* - ELSE:
* - [Attach SD Card/USB Drive] = M21
*
* Ideal:
* - Password Gateway?
* - Use gateway passthroughs for all SD/USB Drive menu items...
* - [Run SD Autofiles]
* - [Run USB Autofiles]
* - [Select from SD Card] (or Password Gateway) >
* - [Select from USB Drive] (or Password Gateway) >
* - [Eject SD Card/USB Drive]
*/
auto media_menu_items = [&]{
#if HAS_MEDIA
if (card_open) return;
if (card_is_mounted) {
#if ENABLED(MENU_ADDAUTOSTART)
// [Run AutoFiles] for mounted drive(s)
if (card.isSDCardMounted())
ACTION_ITEM(MSG_RUN_AUTOFILES_SD, card.autofile_begin);
if (card.isFlashDriveMounted())
ACTION_ITEM(MSG_RUN_AUTOFILES_USB, card.autofile_begin);
#endif
#if ENABLED(TFT_COLOR_UI)
// Menu display issue on item removal with multi language selection menu
#define M22_ITEM(T) do{ \
ACTION_ITEM(T, []{ \
queue.inject(F("M22")); encoderTopLine -= (encoderTopLine > 0); ui.refresh(); \
}); \
}while(0)
#else
#define M22_ITEM(T) GCODES_ITEM(T, F("M22"))
#endif
// [Release Media] for mounted drive(s)
if (card.isSDCardMounted())
M22_ITEM(MSG_RELEASE_SD);
if (card.isFlashDriveMounted())
M22_ITEM(MSG_RELEASE_USB);
// [Select from SD/USB] (or Password First)
if (card.isSDCardMounted())
SUBMENU(MSG_MEDIA_MENU_SD, MEDIA_MENU_GATEWAY);
else if (TERN0(SHOW_UNMOUNTED_DRIVES, card.isSDCardInserted()))
SUBMENU(MSG_MEDIA_MENU_SD, MEDIA_MENU_GATEWAY_SD);
if (card.isFlashDriveMounted())
SUBMENU(MSG_MEDIA_MENU_USB, MEDIA_MENU_GATEWAY);
else if (TERN0(SHOW_UNMOUNTED_DRIVES, card.isFlashDriveInserted()))
SUBMENU(MSG_MEDIA_MENU_USB, MEDIA_MENU_GATEWAY_USB);
}
else {
#if HAS_SD_DETECT
ACTION_ITEM(MSG_NO_MEDIA, nullptr); // "No Media"
#else
#if HAS_MULTI_VOLUME
GCODES_ITEM(MSG_ATTACH_SD, F("M21S")); // M21S Attach SD Card
GCODES_ITEM(MSG_ATTACH_USB, F("M21U")); // M21U Attach USB Media
// NOTE: If the SD Card has no SD_DETECT it will always appear to be "inserted"
const bool att_sd = ENABLED(ATTACH_WITHOUT_INSERT_SD) || card.isSDCardInserted(),
att_usb = ENABLED(ATTACH_WITHOUT_INSERT_USB) || card.isFlashDriveInserted();
if (!att_sd && !att_usb) {
ACTION_ITEM(MSG_NO_MEDIA, nullptr); // [No Media]
}
else {
#if ALL(HAS_MULTI_VOLUME, SHOW_UNMOUNTED_DRIVES)
// [Select from SD/USB] (or Password First)
if (TERN0(SHOW_UNMOUNTED_DRIVES, card.isSDCardInserted()))
SUBMENU(MSG_MEDIA_MENU_SD, MEDIA_MENU_GATEWAY_SD);
if (TERN0(SHOW_UNMOUNTED_DRIVES, card.isFlashDriveInserted()))
SUBMENU(MSG_MEDIA_MENU_USB, MEDIA_MENU_GATEWAY_USB);
#else
GCODES_ITEM(MSG_ATTACH_MEDIA, F("M21")); // M21 Attach Media
#define M21(T) F("M21" TERN_(HAS_MULTI_VOLUME, T))
if (att_sd) GCODES_ITEM(MSG_ATTACH_SD, M21("S")); // M21 S - [Attach SD Card]
if (att_usb) GCODES_ITEM(MSG_ATTACH_USB, M21("U")); // M21 U - [Attach USB Drive]
#endif
#endif
}
}
#endif
#endif // HAS_MEDIA
};
if (busy) {
@ -317,7 +395,9 @@ void menu_main() {
else {
// SD Card / Flash Drive
TERN_(MEDIA_MENU_AT_TOP, media_menus());
#if ENABLED(MEDIA_MENU_AT_TOP)
INJECT_MENU_ITEMS(media_menu_items());
#endif
if (TERN0(MACHINE_CAN_PAUSE, printingIsPaused()))
ACTION_ITEM(MSG_RESUME_PRINT, ui.resume_print);
@ -407,7 +487,7 @@ void menu_main() {
// SD Card / Flash Drive
#if DISABLED(MEDIA_MENU_AT_TOP)
if (!busy) media_menus();
if (!busy) INJECT_MENU_ITEMS(media_menu_items());
#endif
#if HAS_SERVICE_INTERVALS

View file

@ -101,29 +101,27 @@ class MenuItem_sdfolder : public MenuItem_sdbase {
}
};
#if HAS_MULTI_VOLUME
void menu_media_select() {
START_MENU();
BACK_ITEM_F(TERN1(BROWSE_MEDIA_ON_INSERT, screen_history_depth) ? GET_TEXT_F(MSG_MAIN_MENU) : GET_TEXT_F(MSG_BACK));
#if HAS_SDCARD
ACTION_ITEM(MSG_SD_CARD, []{ card.selectMediaSDCard(); card.mount(); ui.goto_screen(menu_file_selector); });
#endif
#if HAS_USB_FLASH_DRIVE
ACTION_ITEM(MSG_USB_DISK, []{ card.selectMediaFlashDrive(); card.mount(); ui.goto_screen(menu_file_selector); });
#endif
END_MENU();
// Shortcut menu items to go directly to inserted — not necessarily mounted — drives
void menu_file_selector_sd() {
if (!card.isSDCardSelected()) {
card.release();
card.selectMediaSDCard();
}
#endif
/**
* "Select From Media" menu item. Depending on single or multiple drives:
* - menu_file_selector - List files on the current media
* - menu_media_select - Select one of the attached drives, then go to the file list
*/
void menu_media() {
ui.goto_screen(TERN(HAS_MULTI_VOLUME, menu_media_select, menu_file_selector));
if (!card.isSDCardMounted()) card.mount();
ui.goto_screen(menu_file_selector);
}
// Shortcut menu items to go directly to inserted — not necessarily mounted — drives
void menu_file_selector_usb() {
if (!card.isFlashDriveSelected()) {
card.release();
card.selectMediaFlashDrive();
}
if (!card.isFlashDriveMounted()) card.mount();
ui.goto_screen(menu_file_selector);
}
// Shortcut menu items to go directly to inserted — not necessarily mounted — drives
void menu_file_selector() {
ui.encoder_direction_menus();
@ -135,11 +133,9 @@ void menu_file_selector() {
#endif
START_MENU();
#if HAS_MULTI_VOLUME
ACTION_ITEM(MSG_BACK, []{ ui.goto_screen(menu_media_select); });
#else
BACK_ITEM_F(TERN1(BROWSE_MEDIA_ON_INSERT, screen_history_depth) ? GET_TEXT_F(MSG_MAIN_MENU) : GET_TEXT_F(MSG_BACK));
#endif
BACK_ITEM_F(TERN1(BROWSE_MEDIA_ON_INSERT, screen_history_depth) ? GET_TEXT_F(MSG_MAIN_MENU) : GET_TEXT_F(MSG_BACK));
if (card.flag.workDirIsRoot) {
#if !HAS_SD_DETECT
ACTION_ITEM(MSG_REFRESH, []{ encoderTopLine = 0; card.mount(); });

View file

@ -140,8 +140,18 @@ void Password::access_menu_password() {
#if ENABLED(PASSWORD_ON_SD_PRINT_MENU)
void Password::media_gatekeeper() {
authenticate_user(menu_media, menu_main);
authenticate_user(menu_file_selector, menu_main);
}
#if HAS_SDCARD
void Password::media_gatekeeper_sd() {
authenticate_user(menu_file_selector_sd, menu_main);
}
#endif
#if HAS_USB_FLASH_DRIVE
void Password::media_gatekeeper_usb() {
authenticate_user(menu_file_selector_usb, menu_main);
}
#endif
#endif
void Password::start_over() {

View file

@ -323,7 +323,7 @@ void MarlinUI::draw_status_screen() {
if (cm && pa)
add_control(SDCARD_ICON_X, SDCARD_ICON_Y, STOP, imgCancel, true, COLOR_CONTROL_CANCEL);
else
add_control(SDCARD_ICON_X, SDCARD_ICON_Y, menu_media, imgSD, cm && !pa, COLOR_CONTROL_ENABLED, COLOR_CONTROL_DISABLED);
add_control(SDCARD_ICON_X, SDCARD_ICON_Y, menu_file_selector, imgSD, cm && !pa, COLOR_CONTROL_ENABLED, COLOR_CONTROL_DISABLED);
#endif
#endif