/[svn]/linuxsampler/trunk/src/engines/common/InstrumentScriptVM.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/common/InstrumentScriptVM.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2613 by schoenebeck, Tue Jun 10 15:17:01 2014 UTC revision 2942 by schoenebeck, Wed Jul 13 15:51:06 2016 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014 Christian Schoenebeck   * Copyright (c) 2014-2016 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 11  Line 11 
11  #define LS_INSTRUMENT_SCRIPT_VM_H  #define LS_INSTRUMENT_SCRIPT_VM_H
12    
13  #include "../../common/global.h"  #include "../../common/global.h"
14    #include "../../common/ConstCapacityArray.h"
15  #include "../../scriptvm/ScriptVM.h"  #include "../../scriptvm/ScriptVM.h"
16  #include "Event.h"  #include "Event.h"
17  #include "../../common/Pool.h"  #include "../../common/Pool.h"
18  #include "InstrumentScriptVMFunctions.h"  #include "InstrumentScriptVMFunctions.h"
19    #include "InstrumentScriptVMDynVars.h"
20    
21    /**
22     * Amount of bits on the left hand side of all pool_element_id_t numbers (i.e.
23     * event_id_t, note_id_t) being reserved for script VM implementation internal
24     * purposes.
25     *
26     * Right now there is only one bit reserved, which allows the VM (and its
27     * built-in functions) to distinguish user supplied @c Event IDs (event_id_t)
28     * from @c Note IDs (note_id_t).
29     */
30    #define INSTR_SCRIPT_EVENT_ID_RESERVED_BITS 1
31    
32    /**
33     * Used to mark IDs (in script scope) to actually be a note ID.
34     */
35    #define INSTR_SCRIPT_NOTE_ID_FLAG   (1 << (sizeof(pool_element_id_t) * 8 - 1))
36    
37    #define INSTR_SCRIPT_EVENT_GROUPS 28
38    
39    #define EVENT_STATUS_INACTIVE 0
40    #define EVENT_STATUS_NOTE_QUEUE 1
41    
42  namespace LinuxSampler {  namespace LinuxSampler {
43    
44      class AbstractEngineChannel;      class AbstractEngineChannel;
45        class InstrumentScript;
46    
47        /** @brief Convert IDs between script scope and engine internal scope.
48         *
49         * This class is used to translate unique IDs of events between script
50         * scope and sampler engine internal scope, that is:
51         * @code
52         * int (script scope) -> event_id_t (engine internal scope)
53         * int (script scope) -> note_id_t (engine internal scope)
54         * @endcode
55         * and vice versa:
56         * @code
57         * event_id_t (engine internal scope) -> int (script scope)
58         * note_id_t (engine internal scope)  -> int (script scope)
59         * @endcode
60         * This is required because engine internally notes and regular events are
61         * using their own, separate ID generating pool, and their ID number set
62         * may thus overlap.
63         *
64         * @see INSTR_SCRIPT_EVENT_ID_RESERVED_BITS
65         */
66        class ScriptID {
67        public:
68            enum type_t {
69                EVENT, ///< ID is actually an event ID
70                NOTE, ///< ID is actually a note ID
71            };
72    
73            /**
74             * Construct a ScriptID object with an ID from script scope.
75             */
76            ScriptID(uint id) : m_id(id) {}
77    
78            /**
79             * Returns a ScriptID object constructed with an event ID from engine
80             * internal scope.
81             */
82            inline static ScriptID fromEventID(event_id_t id) {
83                return ScriptID(id);
84            }
85    
86            /**
87             * Returns a ScriptID object constructed with a note ID from engine
88             * internal scope.
89             */
90            inline static ScriptID fromNoteID(note_id_t id) {
91                return ScriptID(INSTR_SCRIPT_NOTE_ID_FLAG | id);
92            }
93    
94            /**
95             * Whether the ID reflected by this ScriptID object is actually a note
96             * ID or rather an event ID.
97             */
98            inline type_t type() const {
99                return (m_id & INSTR_SCRIPT_NOTE_ID_FLAG) ? NOTE : EVENT;
100            }
101    
102            inline bool isNoteID() const {
103                return type() == NOTE;
104            }
105    
106            inline bool isEventID() const {
107                return type() == EVENT;
108            }
109    
110            /**
111             * Returns event ID (for engine internal scope) of the ID reflected by
112             * this ScriptID object, it returns 0 (being an invalid ID) if the ID
113             * reflected by this ScriptID object is not an event ID.
114             */
115            inline event_id_t eventID() const {
116                switch (type()) {
117                    case EVENT: return m_id;
118                    default:    return 0; // not an event id, return invalid ID
119                }
120            }
121    
122            /**
123             * Returns note ID (for engine internal scope) of the ID reflected by
124             * this ScriptID object, it returns 0 (being an invalid ID) if the ID
125             * reflected by this ScriptID object is not a note ID.
126             */
127            inline note_id_t noteID() const {
128                switch (type()) {
129                    case NOTE: return ~INSTR_SCRIPT_NOTE_ID_FLAG & m_id;
130                    default:   return 0; // not a note id, return invalid ID
131                }
132            }
133    
134            /**
135             * Integer cast operator, which returns an ID number of this ScripID
136             * object intended for script scope.
137             */
138            inline operator uint() const {
139                return m_id;
140            }
141    
142        private:
143            uint m_id;
144        };
145    
146        /** @brief List of Event IDs.
147         *
148         * Used for built-in script functions:
149         *     by_marks(), set_event_mark(), delete_event_mark()
150         */
151        class EventGroup : protected ConstCapacityArray<int> {
152        public:
153            EventGroup() : ConstCapacityArray<int>(CONFIG_MAX_EVENTS_PER_FRAGMENT), m_script(NULL) {}
154            void insert(int eventID);
155            void erase(int eventID);
156            void setScript(InstrumentScript* pScript) { m_script = pScript; }
157            inline int size() const { return ConstCapacityArray<int>::size(); }
158            inline void clear() { ConstCapacityArray<int>::clear(); }
159            inline int& operator[](uint index) { return ConstCapacityArray<int>::operator[](index); }
160            inline const int& operator[](uint index) const { return ConstCapacityArray<int>::operator[](index); }
161        protected:
162            InstrumentScript* m_script;
163        };
164    
165      /** @brief Real-time instrument script VM representation.      /** @brief Real-time instrument script VM representation.
166       *       *
167       * Holds the VM representation of all event handlers of the currently loaded       * Holds the VM representation of all event handlers of the currently loaded
168       * script, ready to be executed by the sampler engine.       * script, ready to be executed by the sampler engine.
169         *
170         * Even thought scripts (or to be more specific their event handler objects)
171         * are shared between sampler engine channels, the InstrumentScript struct
172         * instances though are not shared. Each sampler engine channel has its own
173         * instance of a InstrumentScript struct. That's important, because this
174         * struct also holds engine channel local informations, for example the
175         * events that occured on the respective engine channel.
176       */       */
177      struct InstrumentScript {      struct InstrumentScript {
178          VMParserContext*      parserContext; ///< VM represenation of the currently loaded script or NULL if not script was loaded. Note that it is also not NULL if parser errors occurred!          VMParserContext*      parserContext; ///< VM represenation of the currently loaded script or NULL if not script was loaded. Note that it is also not NULL if parser errors occurred!
# Line 32  namespace LinuxSampler { Line 181  namespace LinuxSampler {
181          VMEventHandler*       handlerNote; ///< VM representation of script's MIDI note on callback or NULL if current script did not define such an event handler.          VMEventHandler*       handlerNote; ///< VM representation of script's MIDI note on callback or NULL if current script did not define such an event handler.
182          VMEventHandler*       handlerRelease; ///< VM representation of script's MIDI note off callback or NULL if current script did not define such an event handler.          VMEventHandler*       handlerRelease; ///< VM representation of script's MIDI note off callback or NULL if current script did not define such an event handler.
183          VMEventHandler*       handlerController; ///< VM representation of script's MIDI controller callback or NULL if current script did not define such an event handler.          VMEventHandler*       handlerController; ///< VM representation of script's MIDI controller callback or NULL if current script did not define such an event handler.
184          Pool<ScriptEvent>*    pEvents; ///< Pool of all available script execution instances. ScriptEvents available to be allocated from the Pool are currently unused / not executiong, whereas the ScriptEvents allocated on the list are currently suspended / have not finished execution yet.          Pool<ScriptEvent>*    pEvents; ///< Pool of all available script execution instances. ScriptEvents available to be allocated from the Pool are currently unused / not executiong, whereas the ScriptEvents allocated on the list are currently suspended / have not finished execution yet (@see pKeyEvents).
185            RTList<ScriptEvent>*  pKeyEvents[128]; ///< Stores previously finished executed "note on" script events for the respective active note/key as long as the key/note is active. This is however only done if there is a "note" script event handler and a "release" script event handler defined in the script and both handlers use (reference) polyphonic variables. If that is not the case, then this list is not used at all. So the purpose of pKeyEvents is only to implement preserving/passing polyphonic variable data from "on note .. end on" script block to the respective "on release .. end on" script block.
186            RTAVLTree<ScriptEvent> suspendedEvents; ///< Contains pointers to all suspended events, sorted by time when those script events are to be resumed next.
187          AbstractEngineChannel* pEngineChannel;          AbstractEngineChannel* pEngineChannel;
188          String                code; ///< Source code of the instrument script. Used in case the sampler engine is changed, in that case a new ScriptVM object is created for the engine and VMParserContext object for this script needs to be recreated as well. Thus the script is then parsed again by passing the source code to recreate the parser context.          String                code; ///< Source code of the instrument script. Used in case the sampler engine is changed, in that case a new ScriptVM object is created for the engine and VMParserContext object for this script needs to be recreated as well. Thus the script is then parsed again by passing the source code to recreate the parser context.
189            EventGroup            eventGroups[INSTR_SCRIPT_EVENT_GROUPS]; ///< Used for built-in script functions: by_event_marks(), set_event_mark(), delete_event_mark().
190    
191          InstrumentScript(AbstractEngineChannel* pEngineChannel) {          InstrumentScript(AbstractEngineChannel* pEngineChannel);
192              parserContext = NULL;          ~InstrumentScript();
             bHasValidScript = false;  
             handlerInit = NULL;  
             handlerNote = NULL;  
             handlerRelease = NULL;  
             handlerController = NULL;  
             pEvents = NULL;  
             this->pEngineChannel = pEngineChannel;  
         }  
   
         ~InstrumentScript() {  
             resetAll();  
         }  
193    
194          void load(const String& text);          void load(const String& text);
195          void unload();          void unload();
196          void resetAll();          void resetAll();
197            void resetEvents();
198      };      };
199    
200      /** @brief Real-time instrument script virtual machine.      /** @brief Real-time instrument script virtual machine.
# Line 74  namespace LinuxSampler { Line 215  namespace LinuxSampler {
215          std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;          std::map<String,VMIntRelPtr*> builtInIntVariables() OVERRIDE;
216          std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;          std::map<String,VMInt8Array*> builtInIntArrayVariables() OVERRIDE;
217          std::map<String,int> builtInConstIntVariables() OVERRIDE;          std::map<String,int> builtInConstIntVariables() OVERRIDE;
218            std::map<String,VMDynVar*> builtInDynamicVariables() OVERRIDE;
219      protected:      protected:
220          ScriptEvent* m_event; ///< The event currently executed by exec().          ScriptEvent* m_event; ///< The event currently executed by exec().
221    
# Line 92  namespace LinuxSampler { Line 234  namespace LinuxSampler {
234          InstrumentScriptVMFunction_set_controller m_fnSetController;          InstrumentScriptVMFunction_set_controller m_fnSetController;
235          InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;          InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;
236          InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;          InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;
237            InstrumentScriptVMFunction_note_off m_fnNoteOff;
238            InstrumentScriptVMFunction_set_event_mark m_fnSetEventMark;
239            InstrumentScriptVMFunction_delete_event_mark m_fnDeleteEventMark;
240            InstrumentScriptVMFunction_by_marks m_fnByMarks;
241            InstrumentScriptVMFunction_change_vol m_fnChangeVol;
242            InstrumentScriptVMFunction_change_tune m_fnChangeTune;
243            InstrumentScriptVMFunction_change_pan m_fnChangePan;
244            InstrumentScriptVMFunction_change_cutoff m_fnChangeCutoff;
245            InstrumentScriptVMFunction_change_reso m_fnChangeReso;
246            InstrumentScriptVMFunction_event_status m_fnEventStatus;
247            InstrumentScriptVMDynVar_ENGINE_UPTIME m_varEngineUptime;
248    
249          friend class InstrumentScriptVMFunction_play_note;          friend class InstrumentScriptVMFunction_play_note;
250          friend class InstrumentScriptVMFunction_set_controller;          friend class InstrumentScriptVMFunction_set_controller;
251          friend class InstrumentScriptVMFunction_ignore_event;          friend class InstrumentScriptVMFunction_ignore_event;
252          friend class InstrumentScriptVMFunction_ignore_controller;          friend class InstrumentScriptVMFunction_ignore_controller;
253            friend class InstrumentScriptVMFunction_note_off;
254            friend class InstrumentScriptVMFunction_set_event_mark;
255            friend class InstrumentScriptVMFunction_delete_event_mark;
256            friend class InstrumentScriptVMFunction_by_marks;
257            friend class InstrumentScriptVMFunction_change_vol;
258            friend class InstrumentScriptVMFunction_change_tune;
259            friend class InstrumentScriptVMFunction_change_pan;
260            friend class InstrumentScriptVMFunction_change_cutoff;
261            friend class InstrumentScriptVMFunction_change_reso;
262            friend class InstrumentScriptVMFunction_event_status;
263            friend class InstrumentScriptVMDynVar_ENGINE_UPTIME;
264      };      };
265    
266  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2613  
changed lines
  Added in v.2942

  ViewVC Help
Powered by ViewVC