1 |
schoenebeck |
2581 |
/* |
2 |
schoenebeck |
2727 |
* Copyright (c) 2014-2015 Christian Schoenebeck |
3 |
schoenebeck |
2581 |
* |
4 |
|
|
* http://www.linuxsampler.org |
5 |
|
|
* |
6 |
|
|
* This file is part of LinuxSampler and released under the same terms. |
7 |
|
|
* See README file for details. |
8 |
|
|
*/ |
9 |
|
|
|
10 |
|
|
#ifndef LS_SCRIPTVM_H |
11 |
|
|
#define LS_SCRIPTVM_H |
12 |
|
|
|
13 |
|
|
#include <iostream> |
14 |
|
|
#include <vector> |
15 |
|
|
|
16 |
|
|
#include "../common/global.h" |
17 |
|
|
#include "common.h" |
18 |
|
|
#include "CoreVMFunctions.h" |
19 |
|
|
|
20 |
|
|
namespace LinuxSampler { |
21 |
|
|
|
22 |
|
|
class ParserContext; |
23 |
schoenebeck |
2588 |
class ExecContext; |
24 |
schoenebeck |
2581 |
|
25 |
schoenebeck |
2594 |
/** @brief Core virtual machine for real-time instrument scripts. |
26 |
|
|
* |
27 |
schoenebeck |
2727 |
* This is the core of the virtual machine and main entry class, used for |
28 |
|
|
* running real-time instrument scripts. This VM core encompasses the |
29 |
|
|
* instrument script parser, generalized virtual machine and very generic |
30 |
|
|
* built-in script functions. Thus this class only provides functionalities |
31 |
|
|
* which are yet independent of the actual purpose the virtual machine is |
32 |
|
|
* going to be used for. |
33 |
schoenebeck |
2594 |
* |
34 |
|
|
* The actual use case specific functionalites (i.e. MIDI processing) is |
35 |
schoenebeck |
2727 |
* then implemented by sampler engines' VM classes which are derived from |
36 |
|
|
* this generalized ScriptVM class. |
37 |
schoenebeck |
2594 |
* |
38 |
schoenebeck |
2727 |
* Typical usage of this class: |
39 |
|
|
* |
40 |
|
|
* - 1. Create an instance of this ScriptVM class (or of one of its deriving |
41 |
|
|
* classes). |
42 |
|
|
* - 2. Load a script by passing its source code to method loadScript(), |
43 |
|
|
* which will return the parsed represenation of the script. |
44 |
|
|
* - 3. Create a VM execution context by calling createExecContext(). |
45 |
|
|
* - 4. Execute the script by calling method exec(). |
46 |
|
|
* |
47 |
schoenebeck |
2594 |
* This class is re-entrant safe, but not thread safe. So you can share one |
48 |
|
|
* instance of this class between multiple (native) threads, but you @b must |
49 |
|
|
* @b not execute methods of the same class instance simultaniously from |
50 |
|
|
* different (native) threads. If you want to execute scripts simultaniously |
51 |
|
|
* multi threaded, then create a separate ScriptVM instance for each |
52 |
|
|
* (native) thread. Also note that one VMParserContext instance is tied to |
53 |
|
|
* exactly one ScriptVM instance. So you @b must @b not create a |
54 |
|
|
* VMParserContext with one ScriptVM instance and run it with a different |
55 |
|
|
* ScriptVM instance! |
56 |
|
|
*/ |
57 |
schoenebeck |
2581 |
class ScriptVM : public VMFunctionProvider { |
58 |
|
|
public: |
59 |
|
|
ScriptVM(); |
60 |
|
|
virtual ~ScriptVM(); |
61 |
schoenebeck |
2727 |
|
62 |
|
|
/** |
63 |
|
|
* Loads a script given by its source code (passed as argument @a s to |
64 |
|
|
* this method) and returns the parsed represenation of that script. |
65 |
|
|
* After calling this method you must check the returned VMParserContext |
66 |
|
|
* object whether there had been any parser errors. If there were no |
67 |
|
|
* parser errors, you may pass the VMParserContext object to method |
68 |
|
|
* exec() for actually executing the script. |
69 |
|
|
* |
70 |
|
|
* @param s - entire source code of the script to be loaded |
71 |
|
|
* @returns parsed represenation of the script |
72 |
|
|
*/ |
73 |
schoenebeck |
2588 |
VMParserContext* loadScript(const String& s); |
74 |
schoenebeck |
2727 |
|
75 |
|
|
/** |
76 |
|
|
* Same as above's loadScript() method, but this one reads the script's |
77 |
|
|
* source code from an input stream object (i.e. stdin or a file). |
78 |
|
|
* |
79 |
|
|
* @param is - input stream from which the entire source code of the |
80 |
|
|
* script is to be read and loaded from |
81 |
|
|
* @returns parsed represenation of the script |
82 |
|
|
*/ |
83 |
schoenebeck |
2588 |
VMParserContext* loadScript(std::istream* is); |
84 |
schoenebeck |
2727 |
|
85 |
|
|
/** |
86 |
|
|
* Dumps the translated tree of the already parsed script, given by |
87 |
|
|
* argument @a context, to stdout. This method is for debugging purposes |
88 |
|
|
* only. |
89 |
|
|
* |
90 |
|
|
* @param context - parsed represenation of the script |
91 |
schoenebeck |
2728 |
* @see loadScript() |
92 |
schoenebeck |
2727 |
*/ |
93 |
schoenebeck |
2588 |
void dumpParsedScript(VMParserContext* context); |
94 |
schoenebeck |
2727 |
|
95 |
|
|
/** |
96 |
|
|
* Creates a so called VM exceution context for a specific, already |
97 |
|
|
* parsed script (provided by argument @a parserContext). Due to the |
98 |
|
|
* general real-time design of this virtual machine, the VM execution |
99 |
|
|
* context differs for every script. So you must (re)create the |
100 |
|
|
* execution context for each script being loaded. |
101 |
schoenebeck |
2728 |
* |
102 |
|
|
* @param parserContext - parsed represenation of the script |
103 |
|
|
* @see loadScript() |
104 |
schoenebeck |
2727 |
*/ |
105 |
schoenebeck |
2588 |
VMExecContext* createExecContext(VMParserContext* parserContext); |
106 |
schoenebeck |
2727 |
|
107 |
|
|
/** |
108 |
|
|
* Execute a script by virtual machine. Since scripts are event-driven, |
109 |
|
|
* you actually execute only one specific event handler block (i.e. a |
110 |
|
|
* "on note ... end on" code block) by calling this method (not the |
111 |
|
|
* entire script), and hence you must provide one precise handler of the |
112 |
|
|
* script to be executed by this method. |
113 |
|
|
* |
114 |
|
|
* This method usually blocks until the entire script event handler |
115 |
|
|
* block has been executed completely. It may however also return before |
116 |
|
|
* completion if either a) a script runtime error occurred or b) the |
117 |
|
|
* script was suspened by the VM (either because script execution |
118 |
|
|
* exceeded a certain limit of time or the script called the built-in |
119 |
|
|
* wait() function). You must check the return value of this method to |
120 |
|
|
* find out which case applies. |
121 |
|
|
* |
122 |
schoenebeck |
2728 |
* @param parserContext - parsed represenation of the script (see loadScript()) |
123 |
schoenebeck |
2727 |
* @param execContext - VM execution context (see createExecContext()) |
124 |
|
|
* @param handler - precise event handler (i.e. "on note ... end on" |
125 |
|
|
* code block) to be executed |
126 |
|
|
* (see VMParserContext::eventHandlerByName()) |
127 |
|
|
* @returns current status of the vitual machine (i.e. script succeeded, |
128 |
|
|
* script runtime error occurred or script was suspended for |
129 |
|
|
* some reason). |
130 |
|
|
*/ |
131 |
|
|
VMExecStatus_t exec(VMParserContext* parserContext, VMExecContext* execContext, VMEventHandler* handler); |
132 |
|
|
|
133 |
|
|
/** |
134 |
|
|
* Returns built-in script function for the given function @a name. To |
135 |
|
|
* get the implementation of the built-in message() script function for |
136 |
|
|
* example, you would pass "message" here). |
137 |
|
|
* |
138 |
|
|
* This method is re-implemented by deriving classes to add more use |
139 |
|
|
* case specific built-in functions. |
140 |
|
|
* |
141 |
|
|
* @param name - name of the function to be retrieved (i.e. "wait" for the |
142 |
|
|
* built-in wait() function). |
143 |
|
|
*/ |
144 |
schoenebeck |
2594 |
VMFunction* functionByName(const String& name) OVERRIDE; |
145 |
schoenebeck |
2727 |
|
146 |
|
|
/** |
147 |
|
|
* Returns all built-in integer script variables. This method returns a |
148 |
|
|
* STL map, where the map's key is the variable name and the map's value |
149 |
|
|
* is the native pointer to the actual built-in variable. |
150 |
|
|
* |
151 |
|
|
* This method is re-implemented by deriving classes to add more use |
152 |
|
|
* case specific built-in variables. |
153 |
|
|
*/ |
154 |
schoenebeck |
2594 |
std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE; |
155 |
schoenebeck |
2727 |
|
156 |
|
|
/** |
157 |
|
|
* Returns all built-in (8 bit) integer array script variables. This |
158 |
|
|
* method returns a STL map, where the map's key is the array variable |
159 |
|
|
* name and the map's value is the native pointer to the actual built-in |
160 |
|
|
* array variable. |
161 |
|
|
* |
162 |
|
|
* This method is re-implemented by deriving classes to add more use |
163 |
|
|
* case specific built-in array variables. |
164 |
|
|
*/ |
165 |
schoenebeck |
2594 |
std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE; |
166 |
schoenebeck |
2727 |
|
167 |
|
|
/** |
168 |
|
|
* Returns all built-in constant integer script variables, which can |
169 |
|
|
* only be read, but not be altered by scripts. This method returns a |
170 |
|
|
* STL map, where the map's key is the variable name and the map's value |
171 |
|
|
* is the native pointer to the actual built-in constant variable. |
172 |
|
|
* |
173 |
|
|
* This method is re-implemented by deriving classes to add more use |
174 |
|
|
* case specific built-in constant integers. |
175 |
|
|
* |
176 |
|
|
* @b Note: the term "constant" is a bit misleading here, since |
177 |
|
|
* built-in constant integer variables may indeed change, i.e. for |
178 |
|
|
* built-in constant integers which i.e. reflect some kind of status of |
179 |
|
|
* the sampler. So rather see them as "read only" variables, not as |
180 |
|
|
* being actually consistent in time. |
181 |
|
|
*/ |
182 |
schoenebeck |
2594 |
std::map<String,int> builtInConstIntVariables() OVERRIDE; |
183 |
schoenebeck |
2588 |
|
184 |
|
|
VMParserContext* currentVMParserContext(); //TODO: should be protected (only usable during exec() calls, intended only for VMFunctions) |
185 |
|
|
VMExecContext* currentVMExecContext(); //TODO: should be protected (only usable during exec() calls, intended only for VMFunctions) |
186 |
schoenebeck |
2727 |
|
187 |
schoenebeck |
2581 |
protected: |
188 |
schoenebeck |
2588 |
ParserContext* m_parserContext; |
189 |
schoenebeck |
2581 |
CoreVMFunction_message fnMessage; |
190 |
|
|
CoreVMFunction_exit fnExit; |
191 |
|
|
CoreVMFunction_wait fnWait; |
192 |
schoenebeck |
2619 |
CoreVMFunction_abs fnAbs; |
193 |
|
|
CoreVMFunction_random fnRandom; |
194 |
|
|
CoreVMFunction_num_elements fnNumElements; |
195 |
schoenebeck |
2581 |
}; |
196 |
|
|
|
197 |
|
|
} // namespace LinuxSampler |
198 |
|
|
|
199 |
|
|
#endif // LS_INSTRUMENTSCRIPTVM_H |