/[svn]/linuxsampler/trunk/src/ls_instr_script.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/ls_instr_script.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2885 - (show annotations) (download)
Fri Apr 22 15:37:45 2016 UTC (3 years, 9 months ago) by schoenebeck
File size: 9039 byte(s)
* Instrument script classes now exported with the liblinuxsampler C++ API.
* Added new API method ScriptVM::syntaxHighlighting() which provides
  a convenient syntax highlighting backend for external instrument
  script editor applications.
* Bumped version (2.0.0.svn5).

1 /*
2 * Copyright (c) 2014-2016 Christian Schoenebeck
3 *
4 * http://www.linuxsampler.org
5 *
6 * This program is part of LinuxSampler and released under the same terms.
7 * See README file for details.
8 */
9
10 #include "common/global.h"
11 #include "scriptvm/ScriptVM.h"
12 #include "shell/CFmt.h"
13 #include "engines/common/InstrumentScriptVM.h"
14 #include "engines/gig/InstrumentScriptVM.h"
15 #include <iostream>
16
17 /*
18 This command line tool is currently merely for development and testing
19 purposes, regarding the real-time instrument script feature of the sampler.
20 You can use this command line application like this:
21
22 ls_instr_script core < src/scriptvm/examples/helloworld.txt
23
24 Which will peform 3 things:
25
26 1. Parses the given instrument script and prints any parser errors or
27 warnings.
28 2. It dumps the parsed VM tree (only interesting for LS developers).
29 3. If there were not parser errors, it will run each event handler defined in
30 the script.
31 */
32
33 using namespace LinuxSampler;
34 using namespace std;
35
36 static void printUsage() {
37 cout << "ls_instr_script - Parse real-time instrument script from stdin." << endl;
38 cout << endl;
39 cout << "Usage: ls_instr_script ENGINE [OPTIONS]" << endl;
40 cout << endl;
41 cout << " ENGINE\n";
42 cout << " Either \"core\", \"gig\", \"sf2\" or \"sfz\"." << endl;
43 cout << endl;
44 cout << " OPTIONS" << endl;
45 cout << " --syntax | -s" << endl;
46 cout << " Prints the script to stdout with colored syntax highlighting" << endl;
47 cout << " and exits immediately." << endl;
48 cout << endl;
49 cout << " --debug-syntax | -ds" << endl;
50 cout << " Prints a debugging representation (of the syntax" << endl;
51 cout << " highlighting backend) of the parsed script to stdout and exits" << endl;
52 cout << " immediately." << endl;
53 cout << endl;
54 cout << "If you pass \"core\" as argument, only the core language built-in" << endl;
55 cout << "variables and functions are available. However in this particular" << endl;
56 cout << "mode the program will not just parse the given script, but also" << endl;
57 cout << "execute the event handlers. All other arguments for ENGINE provide" << endl;
58 cout << "the sampler engine / sampler format specific additional built-in" << endl;
59 cout << "variables and functions, however they wil not be executed by this" << endl;
60 cout << "program." << endl;
61 cout << endl;
62 }
63
64 static void printCodeWithSyntaxHighlighting(ScriptVM* vm);
65 static void dumpSyntaxHighlighting(ScriptVM* vm);
66
67 int main(int argc, char *argv[]) {
68 if (argc < 2) {
69 printUsage();
70 return -1;
71 }
72 String engine = argv[1];
73 bool runScript = false;
74
75 ScriptVM* vm;
76 if (engine == "core") {
77 vm = new ScriptVM;
78 runScript = true;
79 } else if (engine == "sf2" || engine == "sfz") {
80 vm = new InstrumentScriptVM;
81 } else if (engine == "gig") {
82 vm = new gig::InstrumentScriptVM;
83 } else {
84 std::cerr << "Unknown ENGINE '" << engine << "'\n\n";
85 printUsage();
86 return -1;
87 }
88
89 // validate & parse arguments provided to this program
90 for (int iArg = 2; iArg < argc; ++iArg) {
91 const string opt = argv[iArg];
92 if (opt == "--") { // common for all command line tools: separator between initial option arguments and i.e. subsequent file arguments
93 iArg++;
94 break;
95 }
96 if (opt.substr(0, 1) != "-") break;
97
98 if (opt == "-s" || opt == "--syntax") {
99 printCodeWithSyntaxHighlighting(vm);
100 return 0;
101 } else if (opt == "-ds" || opt == "--debug-syntax") {
102 dumpSyntaxHighlighting(vm);
103 return 0;
104 } else {
105 cerr << "Unknown option '" << opt << "'" << endl;
106 cerr << endl;
107 printUsage();
108 return -1;
109 }
110 }
111
112 VMParserContext* parserContext = vm->loadScript(&std::cin);
113
114 std::vector<ParserIssue> errors = parserContext->errors();
115 std::vector<ParserIssue> warnings = parserContext->warnings();
116 std::vector<ParserIssue> issues = parserContext->issues();
117 if (warnings.empty() && errors.empty()) {
118 CFmt fmt; fmt.green();
119 printf("EOF. Script parse completed successfully (no errors, no warnings).\n");
120 } else if (!errors.empty()) {
121 CFmt fmt; fmt.red();
122 printf("EOF. Script parse completed with issues (%d errors, %d warnings):\n",
123 int(errors.size()), int(warnings.size()));
124 } else {
125 CFmt fmt; fmt.yellow();
126 printf("EOF. Script parse completed with issues (%d errors, %d warnings):\n",
127 int(errors.size()), int(warnings.size()));
128 }
129 for (int i = 0; i < issues.size(); ++i) {
130 CFmt fmt;
131 if (issues[i].isWrn()) fmt.yellow();
132 else if (issues[i].isErr()) fmt.red();
133 issues[i].dump();
134 }
135
136 printf("[Dumping parsed VM tree]\n");
137 vm->dumpParsedScript(parserContext);
138 printf("[End of parsed VM tree]\n");
139
140 if (!errors.empty()) {
141 if (parserContext) delete parserContext;
142 return -1;
143 }
144
145 if (!runScript) {
146 return 0;
147 }
148
149 if (!parserContext->eventHandler(0)) {
150 printf("No event handler exists. So nothing to execute.\n");
151 if (parserContext) delete parserContext;
152 return 0;
153 }
154
155 printf("Preparing execution of script.\n");
156 VMExecContext* execContext = vm->createExecContext(parserContext);
157 for (int i = 0; parserContext->eventHandler(i); ++i) {
158 VMEventHandler* handler = parserContext->eventHandler(i);
159 printf("[Running event handler '%s']\n", handler->eventHandlerName().c_str());
160 VMExecStatus_t result = vm->exec(parserContext, execContext, handler);
161 CFmt fmt;
162 if (result & VM_EXEC_ERROR) {
163 fmt.red();
164 printf("[Event handler '%s' finished with ERROR status]\n", handler->eventHandlerName().c_str());
165 } else if (result & VM_EXEC_SUSPENDED) {
166 fmt.yellow();
167 printf("[Event handler '%s' returned with SUSPENDED status: %d microseconds]\n",
168 handler->eventHandlerName().c_str(), execContext->suspensionTimeMicroseconds());
169 } else if (!(result & VM_EXEC_RUNNING)) {
170 fmt.green();
171 printf("[Event handler '%s' finished with SUCCESS status]\n", handler->eventHandlerName().c_str());
172 } else if (result & VM_EXEC_RUNNING) {
173 fmt.cyan();
174 printf("[Event handler '%s' finished with RUNNING status]\n", handler->eventHandlerName().c_str());
175 } else {
176 fmt.red();
177 printf("[Event handler '%s' finished with UNKNOWN status]\n", handler->eventHandlerName().c_str());
178 }
179 }
180
181 if (parserContext) delete parserContext;
182 if (execContext) delete execContext;
183 if (vm) delete vm;
184
185 return 0;
186 }
187
188 static void printCodeWithSyntaxHighlighting(ScriptVM* vm) {
189 vector<VMSourceToken> tokens = vm->syntaxHighlighting(&std::cin);
190
191 for (int i = 0; i < tokens.size(); ++i) {
192 const VMSourceToken& token = tokens[i];
193
194 CFmt fmt;
195 if (token.isKeyword()) {
196 fmt.bold();
197 } else if (token.isVariableName()) {
198 fmt.magenta();
199 } else if (token.isIdentifier()) {
200 if (token.isEventHandlerName()) {
201 fmt.bold();
202 fmt.cyan();
203 } else { // a function ...
204 fmt.cyan();
205 }
206 } else if (token.isNumberLiteral()) {
207 fmt.yellow();
208 } else if (token.isStringLiteral()) {
209 fmt.red();
210 } else if (token.isComment()) {
211 fmt.blue();
212 } else if (token.isPreprocessor()) {
213 fmt.green();
214 } else if (token.isNewLine()) {
215 }
216
217 printf("%s", token.text().c_str());
218 fflush(stdout);
219 }
220 }
221
222 static void dumpSyntaxHighlighting(ScriptVM* vm) {
223 vector<VMSourceToken> tokens = vm->syntaxHighlighting(&std::cin);
224
225 for (int i = 0; i < tokens.size(); ++i) {
226 const VMSourceToken& token = tokens[i];
227 const char* type = "OTHER";
228 if (token.isKeyword()) {
229 type = "KEYWORD";
230 } else if (token.isVariableName()) {
231 type = "VARIABLE";
232 } else if (token.isIdentifier()) {
233 if (token.isEventHandlerName()) {
234 type = "HANDLER_NAME";
235 } else { // a function ...
236 type = "FUNCTION";
237 }
238 } else if (token.isNumberLiteral()) {
239 type = "NUMBER";
240 } else if (token.isStringLiteral()) {
241 type = "STRING";
242 } else if (token.isComment()) {
243 type = "COMMENT";
244 } else if (token.isPreprocessor()) {
245 type = "PREPROC";
246 } else if (token.isNewLine()) {
247 type = "NL";
248 }
249 printf("L%d,C%d: %s \"%s\"\n", token.firstLine(), token.firstColumn(), type, token.text().c_str());
250 }
251 }

  ViewVC Help
Powered by ViewVC