2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
3 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
8 #include "libs/Kernel.h"
10 #include "PanelScreen.h"
12 #include "MainMenuScreen.h"
13 #include "FileScreen.h"
14 #include "libs/nuts_bolts.h"
15 #include "libs/utils.h"
17 #include "libs/SerialMessage.h"
18 #include "StreamOutput.h"
19 #include "DirHandle.h"
24 FileScreen::FileScreen()
26 this->start_play
= false;
29 // When entering this screen
30 void FileScreen::on_enter()
32 THEPANEL
->lcd
->clear();
34 // Default folder to enter
35 this->enter_folder(THEKERNEL
->current_path
.c_str());
38 void FileScreen::on_exit()
40 // reset to root directory, I think this is less confusing
41 THEKERNEL
->current_path
= "/";
44 // For every ( potential ) refresh of the screen
45 void FileScreen::on_refresh()
47 if ( THEPANEL
->menu_change() ) {
50 if ( THEPANEL
->click() ) {
51 this->clicked_line(THEPANEL
->get_menu_current_line());
56 void FileScreen::enter_folder(const char *folder
)
58 // Remember where we are
59 THEKERNEL
->current_path
= folder
;
61 // We need the number of lines to setup the menu
62 uint16_t number_of_files_in_folder
= this->count_folder_content();
65 THEPANEL
->setup_menu(number_of_files_in_folder
+ 1); // same number of files as menu items
66 THEPANEL
->enter_menu_mode();
72 // Called by the panel when refreshing the menu, display .. then all files in the current dir
73 void FileScreen::display_menu_line(uint16_t line
)
76 THEPANEL
->lcd
->printf("..");
79 string fn
= this->file_at(line
- 1, isdir
).substr(0, 18);
81 if(fn
.size() >= 18) fn
.back()= '/';
84 THEPANEL
->lcd
->printf("%s", fn
.c_str());
88 // When a line is clicked in the menu, act
89 void FileScreen::clicked_line(uint16_t line
)
92 string path
= THEKERNEL
->current_path
;
94 // Exit file navigation
95 THEPANEL
->enter_screen(this->parent
);
98 path
= path
.substr(0, path
.find_last_of('/'));
102 this->enter_folder(path
.c_str());
107 string path
= absolute_from_relative(this->file_at(line
- 1, isdir
));
109 this->enter_folder(path
.c_str());
113 // start printing that file...
114 this->play_path
= path
;
115 this->start_play
= true;
119 // only filter files that have a .g, .ngc or .nc in them and does not start with a .
120 bool FileScreen::filter_file(const char *f
)
123 return (fn
.at(0) != '.') &&
124 ((fn
.find(".g") != string::npos
) ||
125 (fn
.find(".ngc") != string::npos
) ||
126 (fn
.find(".nc") != string::npos
));
129 // Find the "line"th file in the current folder
130 string
FileScreen::file_at(uint16_t line
, bool& isdir
)
135 d
= opendir(THEKERNEL
->current_path
.c_str());
137 while ((p
= readdir(d
)) != NULL
) {
138 // only filter files that have a .g in them and directories not starting with a .
139 if(((p
->d_isdir
&& p
->d_name
[0] != '.') || filter_file(p
->d_name
)) && count
++ == line
) {
141 string fn
= p
->d_name
;
148 if (d
!= NULL
) closedir(d
);
153 // Count how many files there are in the current folder that have a .g in them and does not start with a .
154 uint16_t FileScreen::count_folder_content()
159 d
= opendir(THEKERNEL
->current_path
.c_str());
161 while ((p
= readdir(d
)) != NULL
) {
162 if((p
->d_isdir
&& p
->d_name
[0] != '.') || filter_file(p
->d_name
)) count
++;
170 void FileScreen::on_main_loop()
172 if (this->start_play
) {
173 this->start_play
= false;
174 THEPANEL
->set_playing_file(this->play_path
);
175 this->play(this->play_path
.c_str());
176 THEPANEL
->enter_screen(this->parent
);
181 void FileScreen::play(const char *path
)
183 struct SerialMessage message
;
184 message
.message
= string("play ") + path
;
185 message
.stream
= &(StreamOutput::NullStream
);
186 THEKERNEL
->call_event(ON_CONSOLE_LINE_RECEIVED
, &message
);