/[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 2611 by schoenebeck, Mon Jun 9 19:20:37 2014 UTC revision 2879 by schoenebeck, Tue Apr 19 14:07:53 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    
20    /**
21     * Amount of bits on the left hand side of all pool_element_id_t numbers (i.e.
22     * event_id_t, note_id_t) being reserved for script VM implementation internal
23     * purposes.
24     *
25     * Right now there is only one bit reserved, which allows the VM (and its
26     * built-in functions) to distinguish user supplied @c Event IDs (event_id_t)
27     * from @c Note IDs (note_id_t).
28     */
29    #define INSTR_SCRIPT_EVENT_ID_RESERVED_BITS 1
30    
31    /**
32     * Used to mark IDs (in script scope) to actually be a note ID.
33     */
34    #define INSTR_SCRIPT_NOTE_ID_FLAG   (1 << (sizeof(pool_element_id_t) * 8 - 1))
35    
36    #define INSTR_SCRIPT_EVENT_GROUPS 28
37    
38  namespace LinuxSampler {  namespace LinuxSampler {
39    
40      class AbstractEngineChannel;      class AbstractEngineChannel;
41        class InstrumentScript;
42    
43        /** @brief Convert IDs between script scope and engine internal scope.
44         *
45         * This class is used to translate unique IDs of events between script
46         * scope and sampler engine internal scope, that is:
47         * @code
48         * int (script scope) -> event_id_t (engine internal scope)
49         * int (script scope) -> note_id_t (engine internal scope)
50         * @endcode
51         * and vice versa:
52         * @code
53         * event_id_t (engine internal scope) -> int (script scope)
54         * note_id_t (engine internal scope)  -> int (script scope)
55         * @endcode
56         * This is required because engine internally notes and regular events are
57         * using their own, separate ID generating pool, and their ID number set
58         * may thu soverlap.
59         *
60         * @see INSTR_SCRIPT_EVENT_ID_RESERVED_BITS
61         */
62        class ScriptID {
63        public:
64            enum type_t {
65                EVENT, ///< ID is actually an event ID
66                NOTE, ///< ID is actually a note ID
67            };
68    
69            /**
70             * Construct a ScriptID object with an ID from script scope.
71             */
72            ScriptID(uint id) : m_id(id) {}
73    
74            /**
75             * Returns a ScriptID object constructed with an event ID from engine
76             * internal scope.
77             */
78            inline static ScriptID fromEventID(event_id_t id) {
79                return ScriptID(id);
80            }
81    
82            /**
83             * Returns a ScriptID object constructed with a note ID from engine
84             * internal scope.
85             */
86            inline static ScriptID fromNoteID(note_id_t id) {
87                return ScriptID(INSTR_SCRIPT_NOTE_ID_FLAG | id);
88            }
89    
90            /**
91             * Whether the ID reflected by this ScriptID object is actually a note
92             * ID or rather an event ID.
93             */
94            inline type_t type() const {
95                return (m_id & INSTR_SCRIPT_NOTE_ID_FLAG) ? NOTE : EVENT;
96            }
97    
98            inline bool isNoteID() const {
99                return type() == NOTE;
100            }
101    
102            inline bool isEventID() const {
103                return type() == EVENT;
104            }
105    
106            /**
107             * Returns event ID (for engine internal scope) of the ID reflected by
108             * this ScriptID object, it returns 0 (being an invalid ID) if the ID
109             * reflected by this ScriptID object is not an event ID.
110             */
111            inline event_id_t eventID() const {
112                switch (type()) {
113                    case EVENT: return m_id;
114                    default:    return 0; // not an event id, return invalid ID
115                }
116            }
117    
118            /**
119             * Returns note ID (for engine internal scope) of the ID reflected by
120             * this ScriptID object, it returns 0 (being an invalid ID) if the ID
121             * reflected by this ScriptID object is not a note ID.
122             */
123            inline note_id_t noteID() const {
124                switch (type()) {
125                    case NOTE: return ~INSTR_SCRIPT_NOTE_ID_FLAG & m_id;
126                    default:   return 0; // not a note id, return invalid ID
127                }
128            }
129    
130            /**
131             * Integer cast operator, which returns an ID number of this ScripID
132             * object intended for script scope.
133             */
134            inline operator uint() const {
135                return m_id;
136            }
137    
138        private:
139            uint m_id;
140        };
141    
142        /** @brief List of Event IDs.
143         *
144         * Used for built-in script functions:
145         *     by_marks(), set_event_mark(), delete_event_mark()
146         */
147        class EventGroup : protected ConstCapacityArray<int> {
148        public:
149            EventGroup() : ConstCapacityArray<int>(CONFIG_MAX_EVENTS_PER_FRAGMENT), m_script(NULL) {}
150            void insert(int eventID);
151            void erase(int eventID);
152            void setScript(InstrumentScript* pScript) { m_script = pScript; }
153            inline int size() const { return ConstCapacityArray<int>::size(); }
154            inline void clear() { ConstCapacityArray<int>::clear(); }
155            inline int& operator[](uint index) { return ConstCapacityArray<int>::operator[](index); }
156            inline const int& operator[](uint index) const { return ConstCapacityArray<int>::operator[](index); }
157        protected:
158            InstrumentScript* m_script;
159        };
160    
161      /** @brief Real-time instrument script VM representation.      /** @brief Real-time instrument script VM representation.
162       *       *
163       * Holds the VM representation of all event handlers of the currently loaded       * Holds the VM representation of all event handlers of the currently loaded
164       * script, ready to be executed by the sampler engine.       * script, ready to be executed by the sampler engine.
165         *
166         * Even thought scripts (or to be more specific their event handler objects)
167         * are shared between sampler engine channels, the InstrumentScript struct
168         * instances though are not shared. Each sampler engine channel has its own
169         * instance of a InstrumentScript struct. That's important, because this
170         * struct also holds engine channel local informations, for example the
171         * events that occured on the respective engine channel.
172       */       */
173      struct InstrumentScript {      struct InstrumentScript {
174          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 177  namespace LinuxSampler {
177          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.
178          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.
179          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.
180          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).
181            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.
182            RTAVLTree<ScriptEvent> suspendedEvents; ///< Contains pointers to all suspended events, sorted by time when those script events are to be resumed next.
183          AbstractEngineChannel* pEngineChannel;          AbstractEngineChannel* pEngineChannel;
184            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.
185            EventGroup            eventGroups[INSTR_SCRIPT_EVENT_GROUPS]; ///< Used for built-in script functions: by_event_marks(), set_event_mark(), delete_event_mark().
186    
187          InstrumentScript(AbstractEngineChannel* pEngineChannel) {          InstrumentScript(AbstractEngineChannel* pEngineChannel);
188              parserContext = NULL;          ~InstrumentScript();
             bHasValidScript = false;  
             handlerInit = NULL;  
             handlerNote = NULL;  
             handlerRelease = NULL;  
             handlerController = NULL;  
             pEvents = NULL;  
             this->pEngineChannel = pEngineChannel;  
         }  
   
         ~InstrumentScript() {  
             reset();  
         }  
189    
190          void load(const String& text);          void load(const String& text);
191          void reset();          void unload();
192            void resetAll();
193            void resetEvents();
194      };      };
195    
196      /** @brief Real-time instrument script virtual machine.      /** @brief Real-time instrument script virtual machine.
# Line 81  namespace LinuxSampler { Line 220  namespace LinuxSampler {
220          VMIntRelPtr  m_EVENT_ID;          VMIntRelPtr  m_EVENT_ID;
221          VMInt8RelPtr m_EVENT_NOTE;          VMInt8RelPtr m_EVENT_NOTE;
222          VMInt8RelPtr m_EVENT_VELOCITY;          VMInt8RelPtr m_EVENT_VELOCITY;
223          //VMIntArray m_KEY_DOWN; //TODO: ...          VMInt8Array  m_KEY_DOWN;
224          //VMIntArray m_POLY_AT; //TODO: ...          //VMIntArray m_POLY_AT; //TODO: ...
225          //int m_POLY_AT_NUM; //TODO: ...          //int m_POLY_AT_NUM; //TODO: ...
226    
# Line 90  namespace LinuxSampler { Line 229  namespace LinuxSampler {
229          InstrumentScriptVMFunction_set_controller m_fnSetController;          InstrumentScriptVMFunction_set_controller m_fnSetController;
230          InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;          InstrumentScriptVMFunction_ignore_event m_fnIgnoreEvent;
231          InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;          InstrumentScriptVMFunction_ignore_controller m_fnIgnoreController;
232            InstrumentScriptVMFunction_note_off m_fnNoteOff;
233            InstrumentScriptVMFunction_set_event_mark m_fnSetEventMark;
234            InstrumentScriptVMFunction_delete_event_mark m_fnDeleteEventMark;
235            InstrumentScriptVMFunction_by_marks m_fnByMarks;
236    
237          friend class InstrumentScriptVMFunction_play_note;          friend class InstrumentScriptVMFunction_play_note;
238          friend class InstrumentScriptVMFunction_set_controller;          friend class InstrumentScriptVMFunction_set_controller;
239          friend class InstrumentScriptVMFunction_ignore_event;          friend class InstrumentScriptVMFunction_ignore_event;
240          friend class InstrumentScriptVMFunction_ignore_controller;          friend class InstrumentScriptVMFunction_ignore_controller;
241            friend class InstrumentScriptVMFunction_note_off;
242            friend class InstrumentScriptVMFunction_set_event_mark;
243            friend class InstrumentScriptVMFunction_delete_event_mark;
244            friend class InstrumentScriptVMFunction_by_marks;
245      };      };
246    
247  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2611  
changed lines
  Added in v.2879

  ViewVC Help
Powered by ViewVC