Enumerate hotends for display in panel temperature settings
[clinton/Smoothieware.git] / src / modules / utils / panel / screens / FileScreen.cpp
1 /*
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/>.
6 */
7
8 #include "libs/Kernel.h"
9 #include "Panel.h"
10 #include "PanelScreen.h"
11 #include "MainMenuScreen.h"
12 #include "FileScreen.h"
13 #include "libs/nuts_bolts.h"
14 #include "libs/utils.h"
15 #include <string>
16 #include "libs/SerialMessage.h"
17 #include "StreamOutput.h"
18 #include "DirHandle.h"
19 #include "mri.h"
20
21 using namespace std;
22
23 FileScreen::FileScreen()
24 {
25 this->current_folder = "";
26 this->start_play = false;
27 }
28
29 // When entering this screen
30 void FileScreen::on_enter()
31 {
32 THEPANEL->lcd->clear();
33
34 // Default folder to enter
35 if ( this->current_folder.compare("") == 0 ) {
36 this->enter_folder("/");
37 } else {
38 this->enter_folder(this->current_folder);
39 }
40 }
41
42 // For every ( potential ) refresh of the screen
43 void FileScreen::on_refresh()
44 {
45 if ( THEPANEL->menu_change() ) {
46 this->refresh_menu();
47 }
48 if ( THEPANEL->click() ) {
49 this->clicked_line(THEPANEL->get_menu_current_line());
50 }
51 }
52
53 // Enter a new folder
54 void FileScreen::enter_folder(std::string folder)
55 {
56
57 // Rembember where we are
58 this->current_folder = folder;
59
60 // We need the number of lines to setup the menu
61 uint16_t number_of_files_in_folder = this->count_folder_content(this->current_folder);
62
63 // Setup menu
64 THEPANEL->setup_menu(number_of_files_in_folder + 1); // same number of files as menu items
65 THEPANEL->enter_menu_mode();
66
67 // Display menu
68 this->refresh_menu();
69 }
70
71 // Called by the panel when refreshing the menu, display .. then all files in the current dir
72 void FileScreen::display_menu_line(uint16_t line)
73 {
74 if ( line == 0 ) {
75 THEPANEL->lcd->printf("..");
76 } else {
77 THEPANEL->lcd->printf("%s", (this->file_at(line - 1).substr(0, 18)).c_str());
78 }
79 }
80
81 // When a line is clicked in the menu, act
82 void FileScreen::clicked_line(uint16_t line)
83 {
84 if ( line == 0 ) {
85 if ( this->current_folder.compare("/") == 0 ) {
86 // Exit file navigation
87 THEPANEL->enter_screen(this->parent);
88 } else {
89 // Go up one folder
90 this->current_folder = this->current_folder.substr(0, this->current_folder.find_last_of('/') + 1);
91 if ( this->current_folder[this->current_folder.length() - 1] == '/' && this->current_folder.length() != 1 ) {
92 this->current_folder.erase(this->current_folder.length() - 1, 1);
93 }
94 this->enter_folder(this->current_folder);
95 }
96 } else {
97 //printf("enter file\r\n");
98 // Enter file
99 string path = this->current_folder;
100 if ( path.compare("/") == 0 ) {
101 path = "";
102 }
103 path = path + "/" + this->file_at( line - 1 );
104 if ( this->is_a_folder( path ) ) {
105 this->enter_folder(path);
106 return;
107 }
108
109 // start printing that file...
110 this->play_path = path;
111 this->start_play = true;
112 }
113
114 }
115
116 // Check wether a line is a folder or a file
117 bool FileScreen::is_a_folder( string path )
118 {
119 // In the special case of /local/ ( the mbed flash chip ) we don't have sub-folders, everything is a file
120 if ( path.substr(0, 7).compare("/local/") == 0 ) {
121 return false;
122 }
123 // Else, check if it's a folder or not
124 DIR *d;
125 d = opendir(path.c_str());
126 if (d == NULL) {
127 return false;
128 } else {
129 closedir(d);
130 return true;
131 }
132 }
133
134 // Find the "line"th file in the current folder
135 string FileScreen::file_at(uint16_t line)
136 {
137 DIR *d;
138 struct dirent *p;
139 uint16_t count = 0;
140 d = opendir(this->current_folder.c_str());
141 if (d != NULL) {
142 while ((p = readdir(d)) != NULL) {
143 if ( count == line ) {
144 string to_return = lc(string(p->d_name));
145 //printf("line: %u string:%s\r\n", line, to_return.c_str());
146 //if( to_return[to_return.length()-1] == '.' ){ to_return[to_return.length()-1] = 0x00; }
147 closedir(d);
148 return to_return;
149 }
150 count++;
151 }
152 }
153
154 if (d != NULL) closedir(d);
155 return "";
156 }
157
158 // Count how many files there are in the current folder
159 uint16_t FileScreen::count_folder_content(std::string folder)
160 {
161 DIR *d;
162 struct dirent *p;
163 uint16_t count = 0;
164 d = opendir(folder.c_str());
165 if (d != NULL) {
166 while ((p = readdir(d)) != NULL) {
167 count++;
168 }
169 closedir(d);
170 return count;
171 } else {
172 return 0;
173 }
174 }
175 void FileScreen::on_main_loop()
176 {
177 if (this->start_play) {
178 this->start_play = false;
179 THEPANEL->set_playing_file(this->play_path);
180 this->play(this->play_path);
181 THEPANEL->enter_screen(this->parent);
182 return;
183 }
184 }
185
186 void FileScreen::play(string path)
187 {
188 struct SerialMessage message;
189 message.message = string("play ") + path + " -q";
190 message.stream = &(StreamOutput::NullStream);
191 THEKERNEL->call_event(ON_CONSOLE_LINE_RECEIVED, &message );
192 }