113 |
g_commandHistory.push_back(sCommand); |
g_commandHistory.push_back(sCommand); |
114 |
} |
} |
115 |
|
|
116 |
|
/** |
117 |
|
* This LSCP shell application is designed as thin client. That means the heavy |
118 |
|
* LSCP grammar evaluation tasks are peformed by the LSCP server and the shell |
119 |
|
* application's task are simply limited to forward individual characters typed |
120 |
|
* by the user to the LSCP server and showing the result of the LSCP server's |
121 |
|
* evaluation to the user on the screen. This has the big advantage that the |
122 |
|
* shell works perfectly with any machine running (some minimum recent version |
123 |
|
* of) LinuxSampler, no matter which precise LSCP version the server side |
124 |
|
* is using. Which reduces the maintenance efforts for the shell application |
125 |
|
* development tremendously. |
126 |
|
* |
127 |
|
* As soon as this application established a TCP connection to a LSCP server, it |
128 |
|
* sends this command to the LSCP server: |
129 |
|
* @code |
130 |
|
* SET SHELL INTERACT 1 |
131 |
|
* @endcode |
132 |
|
* which will inform the LSCP server that this LSCP client is actually a LSCP |
133 |
|
* shell application. The shell will then simply forward every single character |
134 |
|
* typed by the user immediately to the LSCP server, which in turn will evaluate |
135 |
|
* every single character typed by the user and will return immediately a |
136 |
|
* specially formatted string to the shell application like (assuming the user's |
137 |
|
* current command line was "CREATE AUasdf"): |
138 |
|
* @code |
139 |
|
* SHU:1:CREATE AU{{GF}}asdf{{CU}}{{SB}}DIO_OUTPUT_DEVICE |
140 |
|
* @endcode |
141 |
|
* which informs this shell application about the result of the LSCP grammar |
142 |
|
* evaluation and allows the shell to easily show that result of the evaluation |
143 |
|
* to the user on the screen. In the example reply above, the prefix "SHU:" just |
144 |
|
* indicates to the shell application that this response line is the result |
145 |
|
* of the latest grammar evaluation, the number followed (here 1) indicates the |
146 |
|
* semantic status of the current command line: |
147 |
|
* |
148 |
|
* - 0: Command line is complete, thus ENTER key may be hit by the user now. |
149 |
|
* - 1: Current command line contains syntax error(s). |
150 |
|
* - 2: Command line is incomplete, but contains no syntax errors so far. |
151 |
|
* |
152 |
|
* Then the actual current command line follows, with special markers: |
153 |
|
* |
154 |
|
* - Left of "{{GF}}" the command line is syntactically correct, right of that |
155 |
|
* marker the command line is syntactically wrong. |
156 |
|
* |
157 |
|
* - Marker "{{CU}}" indicates the current cursor position of the command line. |
158 |
|
* |
159 |
|
* - Right of "{{SB}}" follows the current auto completion suggestion, so that |
160 |
|
* string portion was not typed by the user yet, but is expected to be typed |
161 |
|
* by him next to retain syntax correctness. |
162 |
|
*/ |
163 |
int main(int argc, char *argv[]) { |
int main(int argc, char *argv[]) { |
164 |
String host = LSCP_DEFAULT_HOST; |
String host = LSCP_DEFAULT_HOST; |
165 |
int port = LSCP_DEFAULT_PORT; |
int port = LSCP_DEFAULT_PORT; |
220 |
char kbdPrevEscapeChar; |
char kbdPrevEscapeChar; |
221 |
|
|
222 |
// main thread's loop |
// main thread's loop |
223 |
|
// |
224 |
|
// This application runs 3 threads: |
225 |
|
// |
226 |
|
// - Keyboard thread: reads constantly on stdin for new characters (which |
227 |
|
// will block this keyboard thread until new character(s) were typed by |
228 |
|
// the user) and pushes the typed characters into a FIFO buffer. |
229 |
|
// |
230 |
|
// - Network thread: reads constantly on the TCP connection for new bytes |
231 |
|
// being sent by the LSCP server (which will block this network thread |
232 |
|
// until new bytes were received) and pushes the received bytes into a |
233 |
|
// FIFO buffer. |
234 |
|
// |
235 |
|
// - Main thread: this thread runs in the loop below. The main thread sleeps |
236 |
|
// (by using the "g_todo" semaphore) until either new keys on the keyboard |
237 |
|
// were stroke by the user or until new bytes were received from the LSCP |
238 |
|
// server. The main thread will then accordingly send the typed characters |
239 |
|
// to the LSCP server and/or show the result of the LSCP server's latest |
240 |
|
// evaluation to the user on the screen (by pulling those data from the |
241 |
|
// other two thread's FIFO buffers). |
242 |
while (true) { |
while (true) { |
243 |
// sleep until either new data from the network or from keyboard arrived |
// sleep until either new data from the network or from keyboard arrived |
244 |
g_todo.WaitIf(false); |
g_todo.WaitIf(false); |