Skip to content

Commit 99c29cd

Browse files
committed
🚸 Simplified Media Menu
1 parent f78aaf9 commit 99c29cd

File tree

11 files changed

+169
-74
lines changed

11 files changed

+169
-74
lines changed

Marlin/src/feature/password/password.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ uint32_t Password::value, Password::value_entry;
3636

3737
//
3838
// Authenticate user with password.
39-
// Called from Setup, after SD Prinitng Stops/Aborts, and M510
39+
// Called from Setup, after SD Printing Stops/Aborts, and M510
4040
//
4141
void Password::lock_machine() {
4242
is_locked = true;

Marlin/src/feature/password/password.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class Password {
3737
static void access_menu_password();
3838
static void authentication_done();
3939
static void media_gatekeeper();
40+
static void media_gatekeeper_sd();
41+
static void media_gatekeeper_usb();
4042

4143
private:
4244
static void authenticate_user(const screenFunc_t, const screenFunc_t);

Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,9 @@ void TFTGLCD::clr_screen() {
175175
SPI_SEND_ONE(CLR_SCREEN);
176176
WRITE(TFTGLCD_CS, HIGH);
177177
#else
178-
Wire.beginTransmission(uint8_t(LCD_I2C_ADDRESS)); //set I2C device address
178+
Wire.beginTransmission(uint8_t(LCD_I2C_ADDRESS)); // Transmit to LCD via I2C
179179
Wire.write(CLR_SCREEN);
180-
Wire.endTransmission(); //transmit data
180+
Wire.endTransmission(); // Send the data
181181
#endif
182182
}
183183

@@ -378,10 +378,6 @@ void MarlinUI::clear_for_drawing() { clear_lcd(); }
378378
void MarlinUI::_set_contrast() { lcd.setContrast(contrast); }
379379
#endif
380380

381-
#if !IS_TFTGLCD_PANEL
382-
void lcd_moveto(const uint8_t col, const uint8_t row) { lcd.setCursor(col, row); }
383-
#endif
384-
385381
static void center_text(FSTR_P const fstart, const uint8_t y) {
386382
const uint8_t len = utf8_strlen(fstart);
387383
lcd_moveto(len < LCD_WIDTH ? (LCD_WIDTH - len) / 2 : 0, y);

Marlin/src/lcd/language/language_en.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,10 +574,8 @@ namespace LanguageNarrow_en {
574574
LSTR MSG_CANCEL_OBJECT = _UxGT("Cancel Obj");
575575
LSTR MSG_CANCEL_OBJECT_N = _UxGT("Cancel Obj {");
576576
LSTR MSG_CONTINUE_PRINT_JOB = _UxGT("Continue Job");
577-
LSTR MSG_MEDIA_MENU = MEDIA_TYPE_EN _UxGT(" Print");
578577
LSTR MSG_TURN_OFF = _UxGT("Turn off now");
579578
LSTR MSG_END_LOOPS = _UxGT("End Loops");
580-
LSTR MSG_NO_MEDIA = _UxGT("No ") MEDIA_TYPE_EN;
581579
LSTR MSG_DWELL = _UxGT("Sleep...");
582580
LSTR MSG_USERWAIT = _UxGT("Click to Resume...");
583581
LSTR MSG_PRINT_PAUSED = _UxGT("Print Paused");
@@ -641,6 +639,10 @@ namespace LanguageNarrow_en {
641639
LSTR MSG_RUN_AUTOFILES = _UxGT("Run Autofiles");
642640
LSTR MSG_RUN_AUTOFILES_SD = _UxGT("Run SD Autofiles");
643641
LSTR MSG_RUN_AUTOFILES_USB = _UxGT("Run USB Autofiles");
642+
LSTR MSG_MEDIA_MENU = MEDIA_TYPE_EN _UxGT(" Print");
643+
LSTR MSG_MEDIA_MENU_SD = _UxGT("Select from SD");
644+
LSTR MSG_MEDIA_MENU_USB = _UxGT("Select from USB");
645+
LSTR MSG_NO_MEDIA = _UxGT("No ") MEDIA_TYPE_EN _UxGT(" Detected");
644646

645647
LSTR MSG_ZPROBE_OUT = _UxGT("Z Probe Past Bed");
646648
LSTR MSG_SKEW_FACTOR = _UxGT("Skew Factor");
@@ -1130,6 +1132,9 @@ namespace LanguageWide_en {
11301132
LSTR MSG_CANCEL_OBJECT_N = _UxGT("Cancel Object {");
11311133
LSTR MSG_CONTINUE_PRINT_JOB = _UxGT("Continue Print Job");
11321134
LSTR MSG_MEDIA_MENU = _UxGT("Select from ") MEDIA_TYPE_EN;
1135+
LSTR MSG_MEDIA_MENU_SD = _UxGT("Select from SD Card");
1136+
LSTR MSG_MEDIA_MENU_USB = _UxGT("Select from USB Drive");
1137+
LSTR MSG_NO_MEDIA = _UxGT("No ") MEDIA_TYPE_EN _UxGT(" Found");
11331138
LSTR MSG_TURN_OFF = _UxGT("Turn off the printer");
11341139
LSTR MSG_END_LOOPS = _UxGT("End Repeat Loops");
11351140
LSTR MSG_MEDIA_NOT_INSERTED = _UxGT("No media inserted."); // ProUI

Marlin/src/lcd/marlinui.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,9 @@ class MarlinUI {
255255
#endif
256256

257257
#if HAS_MEDIA
258-
#define MEDIA_MENU_GATEWAY TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper, menu_media)
258+
#define MEDIA_MENU_GATEWAY TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper, menu_file_selector)
259+
#define MEDIA_MENU_GATEWAY_SD TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper_sd, menu_file_selector_sd)
260+
#define MEDIA_MENU_GATEWAY_USB TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper_usb, menu_file_selector_usb)
259261
static void media_changed(const MediaPresence old_stat, const MediaPresence stat);
260262
#endif
261263

@@ -864,7 +866,7 @@ class MarlinUI {
864866
TERN_(REVERSE_SELECT_DIRECTION, encoderDirection = -(ENCODERBASE));
865867
}
866868

867-
#else
869+
#else // !HAS_ENCODER_ACTION
868870

869871
static void update_buttons() {}
870872
static bool hw_button_pressed() { return false; }

Marlin/src/lcd/menu/menu.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ void menu_move();
212212

213213
#if HAS_MEDIA
214214
void menu_file_selector();
215-
void menu_media();
215+
void menu_file_selector_sd();
216+
void menu_file_selector_usb();
216217
#endif
217218

218219
////////////////////////////////////////////

Marlin/src/lcd/menu/menu_item.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ class MenuItem_bool : public MenuEditItemBase {
226226
* should be done before the menu loop (START_MENU / START_SCREEN).
227227
*/
228228

229+
// CAUTION! When using menu items in a lambda or sub-function always use:
230+
#define INJECT_MENU_ITEMS(FN) { FN; if (ui.screen_changed) return; }
231+
229232
/**
230233
* SCREEN_OR_MENU_LOOP generates header code for a screen or menu
231234
*

Marlin/src/lcd/menu/menu_main.cpp

Lines changed: 116 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,8 @@ void menu_configuration();
237237
void menu_main() {
238238
const bool busy = printingIsActive();
239239
#if HAS_MEDIA
240-
const bool card_detected = card.isMounted(),
241-
card_open = card_detected && card.isFileOpen();
240+
const bool card_is_mounted = card.isMounted(),
241+
card_open = card_is_mounted && card.isFileOpen();
242242
#endif
243243

244244
START_MENU();
@@ -248,45 +248,123 @@ void menu_main() {
248248
#define MEDIA_MENU_AT_TOP
249249
#endif
250250

251-
auto media_menus = [&]{
251+
// Show "Attach" for drives that don't auto-detect media (yet)
252+
//#define ATTACH_WITHOUT_INSERT_SD
253+
#define ATTACH_WITHOUT_INSERT_USB
254+
255+
// Show all "inserted" drives and mount as-needed
256+
#define SHOW_UNMOUNTED_DRIVES
257+
258+
/**
259+
* Previously:
260+
* - The "selected" media is mounted?
261+
* - [Run Auto Files]
262+
* - HAS_SD_DETECT:
263+
* - [Change Media] = M21 / M21S
264+
* - HAS_MULTI_VOLUME?
265+
* - [Attach USB Drive] = M21U
266+
* - ELSE:
267+
* - [Release Media] = M22
268+
* - [Select from Media] (or Password Gateway) >
269+
*
270+
* - The "selected" media is not mounted?
271+
* - HAS_SD_DETECT?
272+
* - [No Media] (does nothing)
273+
* - HAS_MULTI_VOLUME?
274+
* - [Attach SD Card] = M21S
275+
* - [Attach USB Drive] = M21U
276+
* - ELSE:
277+
* - [Attach Media] = M21
278+
*
279+
* Updated:
280+
* - Something is mounted?
281+
* - [Run SD/USB Autofiles]
282+
* - [Release SD/USB] = M22
283+
* - [Select from SD/USB] (or Password Gateway) >
284+
*
285+
* - Something is inserted and SHOW_UNMOUNTED_DRIVES?
286+
* - [Select from SD/USB] (or Password Gateway) >
287+
*
288+
* - The "selected" Card is NOT DETECTED?
289+
* - Trust all media detect methods?
290+
* - [No Media] (does nothing)
291+
* - HAS_MULTI_VOLUME?
292+
* - [Attach SD Card] = M21S
293+
* - [Attach USB Drive] = M21U
294+
* - ELSE:
295+
* - [Attach SD Card/USB Drive] = M21
296+
*
297+
* Ideal:
298+
* - Password Gateway?
299+
* - Use gateway passthroughs for all SD/USB Drive menu items...
300+
* - [Run SD Autofiles]
301+
* - [Run USB Autofiles]
302+
* - [Select from SD Card] (or Password Gateway) >
303+
* - [Select from USB Drive] (or Password Gateway) >
304+
* - [Eject SD Card/USB Drive]
305+
*/
306+
auto media_menu_items = [&]{
252307
#if HAS_MEDIA
253-
if (card_detected) {
254-
if (!card_open) {
255-
#if ENABLED(MENU_ADDAUTOSTART)
256-
ACTION_ITEM(MSG_RUN_AUTOFILES, card.autofile_begin); // Run Auto Files
257-
#endif
308+
if (card_open) return;
309+
310+
if (card_is_mounted) {
311+
#if ENABLED(MENU_ADDAUTOSTART)
312+
// [Run AutoFiles] for mounted drive(s)
313+
if (card.isSDCardMounted())
314+
ACTION_ITEM(MSG_RUN_AUTOFILES_SD, card.autofile_begin);
315+
if (card.isFlashDriveMounted())
316+
ACTION_ITEM(MSG_RUN_AUTOFILES_USB, card.autofile_begin);
317+
#endif
258318

259-
#if HAS_SD_DETECT
260-
GCODES_ITEM(MSG_CHANGE_MEDIA, F("M21" TERN_(HAS_MULTI_VOLUME, "S"))); // M21 Change Media
261-
#if HAS_MULTI_VOLUME
262-
GCODES_ITEM(MSG_ATTACH_USB, F("M21U")); // M21 Attach USB Media
263-
#endif
264-
#else // - or -
265-
ACTION_ITEM(MSG_RELEASE_MEDIA, []{ // M22 Release Media
266-
queue.inject(F("M22"));
267-
#if ENABLED(TFT_COLOR_UI)
268-
// Menu display issue on item removal with multi language selection menu
269-
if (encoderTopLine > 0) encoderTopLine--;
270-
ui.refresh();
271-
#endif
272-
});
273-
#endif
274-
SUBMENU(MSG_MEDIA_MENU, MEDIA_MENU_GATEWAY); // Media Menu (or Password First)
275-
}
319+
#if ENABLED(TFT_COLOR_UI)
320+
// Menu display issue on item removal with multi language selection menu
321+
#define M22_ITEM(T) do{ \
322+
ACTION_ITEM(T, []{ \
323+
queue.inject(F("M22")); encoderTopLine -= (encoderTopLine > 0); ui.refresh(); \
324+
}); \
325+
}while(0)
326+
#else
327+
#define M22_ITEM(T) GCODES_ITEM(T, F("M22"))
328+
#endif
329+
330+
// [Release Media] for mounted drive(s)
331+
if (card.isSDCardMounted())
332+
M22_ITEM(MSG_RELEASE_SD);
333+
if (card.isFlashDriveMounted())
334+
M22_ITEM(MSG_RELEASE_USB);
335+
336+
// [Select from SD/USB] (or Password First)
337+
if (card.isSDCardMounted())
338+
SUBMENU(MSG_MEDIA_MENU_SD, MEDIA_MENU_GATEWAY);
339+
else if (TERN0(SHOW_UNMOUNTED_DRIVES, card.isSDCardInserted()))
340+
SUBMENU(MSG_MEDIA_MENU_SD, MEDIA_MENU_GATEWAY_SD);
341+
if (card.isFlashDriveMounted())
342+
SUBMENU(MSG_MEDIA_MENU_USB, MEDIA_MENU_GATEWAY);
343+
else if (TERN0(SHOW_UNMOUNTED_DRIVES, card.isFlashDriveInserted()))
344+
SUBMENU(MSG_MEDIA_MENU_USB, MEDIA_MENU_GATEWAY_USB);
276345
}
277346
else {
278-
#if HAS_SD_DETECT
279-
ACTION_ITEM(MSG_NO_MEDIA, nullptr); // "No Media"
280-
#else
281-
#if HAS_MULTI_VOLUME
282-
GCODES_ITEM(MSG_ATTACH_SD, F("M21S")); // M21S Attach SD Card
283-
GCODES_ITEM(MSG_ATTACH_USB, F("M21U")); // M21U Attach USB Media
347+
// NOTE: If the SD Card has no SD_DETECT it will always appear to be "inserted"
348+
const bool att_sd = ENABLED(ATTACH_WITHOUT_INSERT_SD) || card.isSDCardInserted(),
349+
att_usb = ENABLED(ATTACH_WITHOUT_INSERT_USB) || card.isFlashDriveInserted();
350+
if (!att_sd && !att_usb) {
351+
ACTION_ITEM(MSG_NO_MEDIA, nullptr); // [No Media]
352+
}
353+
else {
354+
#if ALL(HAS_MULTI_VOLUME, SHOW_UNMOUNTED_DRIVES)
355+
// [Select from SD/USB] (or Password First)
356+
if (TERN0(SHOW_UNMOUNTED_DRIVES, card.isSDCardInserted()))
357+
SUBMENU(MSG_MEDIA_MENU_SD, MEDIA_MENU_GATEWAY_SD);
358+
if (TERN0(SHOW_UNMOUNTED_DRIVES, card.isFlashDriveInserted()))
359+
SUBMENU(MSG_MEDIA_MENU_USB, MEDIA_MENU_GATEWAY_USB);
284360
#else
285-
GCODES_ITEM(MSG_ATTACH_MEDIA, F("M21")); // M21 Attach Media
361+
#define M21(T) F("M21" TERN_(HAS_MULTI_VOLUME, T))
362+
if (att_sd) GCODES_ITEM(MSG_ATTACH_SD, M21("S")); // M21 S - [Attach SD Card]
363+
if (att_usb) GCODES_ITEM(MSG_ATTACH_USB, M21("U")); // M21 U - [Attach USB Drive]
286364
#endif
287-
#endif
365+
}
288366
}
289-
#endif
367+
#endif // HAS_MEDIA
290368
};
291369

292370
if (busy) {
@@ -317,7 +395,9 @@ void menu_main() {
317395
else {
318396

319397
// SD Card / Flash Drive
320-
TERN_(MEDIA_MENU_AT_TOP, media_menus());
398+
#if ENABLED(MEDIA_MENU_AT_TOP)
399+
INJECT_MENU_ITEMS(media_menu_items());
400+
#endif
321401

322402
if (TERN0(MACHINE_CAN_PAUSE, printingIsPaused()))
323403
ACTION_ITEM(MSG_RESUME_PRINT, ui.resume_print);
@@ -407,7 +487,7 @@ void menu_main() {
407487

408488
// SD Card / Flash Drive
409489
#if DISABLED(MEDIA_MENU_AT_TOP)
410-
if (!busy) media_menus();
490+
if (!busy) INJECT_MENU_ITEMS(media_menu_items());
411491
#endif
412492

413493
#if HAS_SERVICE_INTERVALS

Marlin/src/lcd/menu/menu_media.cpp

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -101,29 +101,27 @@ class MenuItem_sdfolder : public MenuItem_sdbase {
101101
}
102102
};
103103

104-
#if HAS_MULTI_VOLUME
105-
void menu_media_select() {
106-
START_MENU();
107-
BACK_ITEM_F(TERN1(BROWSE_MEDIA_ON_INSERT, screen_history_depth) ? GET_TEXT_F(MSG_MAIN_MENU) : GET_TEXT_F(MSG_BACK));
108-
#if HAS_SDCARD
109-
ACTION_ITEM(MSG_SD_CARD, []{ card.selectMediaSDCard(); card.mount(); ui.goto_screen(menu_file_selector); });
110-
#endif
111-
#if HAS_USB_FLASH_DRIVE
112-
ACTION_ITEM(MSG_USB_DISK, []{ card.selectMediaFlashDrive(); card.mount(); ui.goto_screen(menu_file_selector); });
113-
#endif
114-
END_MENU();
104+
// Shortcut menu items to go directly to inserted — not necessarily mounted — drives
105+
void menu_file_selector_sd() {
106+
if (!card.isSDCardSelected()) {
107+
card.release();
108+
card.selectMediaSDCard();
115109
}
116-
#endif
110+
if (!card.isSDCardMounted()) card.mount();
111+
ui.goto_screen(menu_file_selector);
112+
}
117113

118-
/**
119-
* "Select From Media" menu item. Depending on single or multiple drives:
120-
* - menu_file_selector - List files on the current media
121-
* - menu_media_select - Select one of the attached drives, then go to the file list
122-
*/
123-
void menu_media() {
124-
ui.goto_screen(TERN(HAS_MULTI_VOLUME, menu_media_select, menu_file_selector));
114+
// Shortcut menu items to go directly to inserted — not necessarily mounted — drives
115+
void menu_file_selector_usb() {
116+
if (!card.isFlashDriveSelected()) {
117+
card.release();
118+
card.selectMediaFlashDrive();
119+
}
120+
if (!card.isFlashDriveMounted()) card.mount();
121+
ui.goto_screen(menu_file_selector);
125122
}
126123

124+
// Shortcut menu items to go directly to inserted — not necessarily mounted — drives
127125
void menu_file_selector() {
128126
ui.encoder_direction_menus();
129127

@@ -135,11 +133,9 @@ void menu_file_selector() {
135133
#endif
136134

137135
START_MENU();
138-
#if HAS_MULTI_VOLUME
139-
ACTION_ITEM(MSG_BACK, []{ ui.goto_screen(menu_media_select); });
140-
#else
141-
BACK_ITEM_F(TERN1(BROWSE_MEDIA_ON_INSERT, screen_history_depth) ? GET_TEXT_F(MSG_MAIN_MENU) : GET_TEXT_F(MSG_BACK));
142-
#endif
136+
137+
BACK_ITEM_F(TERN1(BROWSE_MEDIA_ON_INSERT, screen_history_depth) ? GET_TEXT_F(MSG_MAIN_MENU) : GET_TEXT_F(MSG_BACK));
138+
143139
if (card.flag.workDirIsRoot) {
144140
#if !HAS_SD_DETECT
145141
ACTION_ITEM(MSG_REFRESH, []{ encoderTopLine = 0; card.mount(); });

Marlin/src/lcd/menu/menu_password.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,18 @@ void Password::access_menu_password() {
140140

141141
#if ENABLED(PASSWORD_ON_SD_PRINT_MENU)
142142
void Password::media_gatekeeper() {
143-
authenticate_user(menu_media, menu_main);
143+
authenticate_user(menu_file_selector, menu_main);
144144
}
145+
#if HAS_SDCARD
146+
void Password::media_gatekeeper_sd() {
147+
authenticate_user(menu_file_selector_sd, menu_main);
148+
}
149+
#endif
150+
#if HAS_USB_FLASH_DRIVE
151+
void Password::media_gatekeeper_usb() {
152+
authenticate_user(menu_file_selector_usb, menu_main);
153+
}
154+
#endif
145155
#endif
146156

147157
void Password::start_over() {

0 commit comments

Comments
 (0)