|
56 | 56 | #include "../feature/pause.h"
|
57 | 57 | #endif
|
58 | 58 |
|
| 59 | +#if ENABLED(ONE_CLICK_PRINT) |
| 60 | + #include "../../src/lcd/menu/menu.h" |
| 61 | +#endif |
| 62 | + |
59 | 63 | #define DEBUG_OUT EITHER(DEBUG_CARDREADER, MARLIN_DEV_MODE)
|
60 | 64 | #include "../core/debug_out.h"
|
61 | 65 | #include "../libs/hex_print.h"
|
@@ -290,7 +294,7 @@ void CardReader::printListing(MediaFile parent, const char * const prepend, cons
|
290 | 294 | while (parent.readDir(&p, longFilename) > 0) {
|
291 | 295 | if (DIR_IS_SUBDIR(&p)) {
|
292 | 296 |
|
293 |
| - size_t lenPrepend = prepend ? strlen(prepend) + 1 : 0; |
| 297 | + const size_t lenPrepend = prepend ? strlen(prepend) + 1 : 0; |
294 | 298 | // Allocate enough stack space for the full path including / separator
|
295 | 299 | char path[lenPrepend + FILENAME_LENGTH];
|
296 | 300 | if (prepend) { strcpy(path, prepend); path[lenPrepend - 1] = '/'; }
|
@@ -545,20 +549,28 @@ void CardReader::manage_media() {
|
545 | 549 |
|
546 | 550 | if (!stat) return; // Exit if no media is present
|
547 | 551 |
|
548 |
| - if (old_stat != 2) return; // First mount? |
| 552 | + bool do_auto = true; UNUSED(do_auto); |
549 | 553 |
|
550 |
| - DEBUG_ECHOLNPGM("First mount."); |
| 554 | + // First mount on boot? Load emulated EEPROM and look for PLR file. |
| 555 | + if (old_stat == 2) { |
| 556 | + DEBUG_ECHOLNPGM("First mount."); |
551 | 557 |
|
552 |
| - // Load settings the first time media is inserted (not just during init) |
553 |
| - TERN_(SDCARD_EEPROM_EMULATION, settings.first_load()); |
| 558 | + // Load settings the first time media is inserted (not just during init) |
| 559 | + TERN_(SDCARD_EEPROM_EMULATION, settings.first_load()); |
554 | 560 |
|
555 |
| - bool do_auto = true; UNUSED(do_auto); |
| 561 | + // Check for PLR file. Skip One-Click and auto#.g if found |
| 562 | + TERN_(POWER_LOSS_RECOVERY, if (recovery.check()) do_auto = false); |
| 563 | + } |
556 | 564 |
|
557 |
| - // Check for PLR file. |
558 |
| - TERN_(POWER_LOSS_RECOVERY, if (recovery.check()) do_auto = false); |
| 565 | + // Find the newest file and prompt to print it. |
| 566 | + TERN_(ONE_CLICK_PRINT, if (do_auto && one_click_check()) do_auto = false); |
559 | 567 |
|
560 |
| - // Look for auto0.g on the next idle() |
561 |
| - IF_DISABLED(NO_SD_AUTOSTART, if (do_auto) autofile_begin()); |
| 568 | + // Also for the first mount run auto#.g for machine init. |
| 569 | + // (Skip if PLR or One-Click Print was invoked.) |
| 570 | + if (old_stat == 2) { |
| 571 | + // Look for auto0.g on the next idle() |
| 572 | + IF_DISABLED(NO_SD_AUTOSTART, if (do_auto) autofile_begin()); |
| 573 | + } |
562 | 574 | }
|
563 | 575 |
|
564 | 576 | /**
|
@@ -887,6 +899,81 @@ void CardReader::write_command(char * const buf) {
|
887 | 899 | }
|
888 | 900 | #endif
|
889 | 901 |
|
| 902 | +#if ENABLED(ONE_CLICK_PRINT) |
| 903 | + |
| 904 | + /** |
| 905 | + * Select the newest file and ask the user if they want to print it. |
| 906 | + */ |
| 907 | + bool CardReader::one_click_check() { |
| 908 | + const bool found = selectNewestFile(); |
| 909 | + if (found) { |
| 910 | + //SERIAL_ECHO_MSG(" OCP File: ", longest_filename(), "\n"); |
| 911 | + //ui.init(); |
| 912 | + one_click_print(); |
| 913 | + } |
| 914 | + return found; |
| 915 | + } |
| 916 | + |
| 917 | + /** |
| 918 | + * Recurse the entire directory to find the newest file. |
| 919 | + * This may take a very long time so watch out for watchdog reset. |
| 920 | + * It may be best to only look at root for reasonable boot and mount times. |
| 921 | + */ |
| 922 | + void CardReader::diveToNewestFile(MediaFile parent, uint32_t &compareDateTime, MediaFile &outdir, char * const outname) { |
| 923 | + // Iterate the given parent dir |
| 924 | + parent.rewind(); |
| 925 | + for (dir_t p; parent.readDir(&p, longFilename) > 0;) { |
| 926 | + |
| 927 | + // If the item is a dir, recurse into it |
| 928 | + if (DIR_IS_SUBDIR(&p)) { |
| 929 | + // Get the name of the dir for opening |
| 930 | + char dirname[FILENAME_LENGTH]; |
| 931 | + createFilename(dirname, p); |
| 932 | + |
| 933 | + // Open the item in a new MediaFile |
| 934 | + MediaFile child; // child.close() in destructor |
| 935 | + if (child.open(&parent, dirname, O_READ)) |
| 936 | + diveToNewestFile(child, compareDateTime, outdir, outname); |
| 937 | + } |
| 938 | + else if (is_visible_entity(p)) { |
| 939 | + // Get the newer of the modified/created date and time |
| 940 | + const uint32_t modDateTime = uint32_t(p.lastWriteDate) << 16 | p.lastWriteTime, |
| 941 | + createDateTime = uint32_t(p.creationDate) << 16 | p.creationTime, |
| 942 | + newerDateTime = _MAX(modDateTime, createDateTime); |
| 943 | + // If a newer item is found overwrite the outdir and outname |
| 944 | + if (newerDateTime > compareDateTime) { |
| 945 | + compareDateTime = newerDateTime; |
| 946 | + outdir = parent; |
| 947 | + createFilename(outname, p); |
| 948 | + } |
| 949 | + } |
| 950 | + } |
| 951 | + } |
| 952 | + |
| 953 | + /** |
| 954 | + * Recurse the entire directory to find the newest file. |
| 955 | + * Make the found file the current selection. |
| 956 | + */ |
| 957 | + bool CardReader::selectNewestFile() { |
| 958 | + uint32_t dateTimeStorage = 0; |
| 959 | + MediaFile foundDir; |
| 960 | + char foundName[FILENAME_LENGTH]; |
| 961 | + foundName[0] = '\0'; |
| 962 | + |
| 963 | + diveToNewestFile(root, dateTimeStorage, foundDir, foundName); |
| 964 | + |
| 965 | + if (foundName[0]) { |
| 966 | + workDir = foundDir; |
| 967 | + workDir.rewind(); |
| 968 | + selectByName(workDir, foundName); |
| 969 | + //workDir.close(); // Not needed? |
| 970 | + return true; |
| 971 | + } |
| 972 | + return false; |
| 973 | + } |
| 974 | + |
| 975 | +#endif // ONE_CLICK_PRINT |
| 976 | + |
890 | 977 | void CardReader::closefile(const bool store_location/*=false*/) {
|
891 | 978 | file.sync();
|
892 | 979 | file.close();
|
|
0 commit comments