/[svn]/linuxsampler/trunk/src/plugins/InstrumentEditor.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/plugins/InstrumentEditor.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1653 - (show annotations) (download) (as text)
Wed Jan 30 01:51:46 2008 UTC (16 years, 2 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 16139 byte(s)
* added support for notifying instrument editors on note-on / note-off
  events (e.g. to highlight the pressed keys on the virtual keyboard
  of gigedit)
* fixed return value of recently added Thread::TestCancel() method
* be verbose on DLL load errors (on Linux)

1 /***************************************************************************
2 * *
3 * Copyright (C) 2007, 2008 Christian Schoenebeck *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
18 * MA 02111-1307 USA *
19 ***************************************************************************/
20
21 #ifndef LS_INSTRUMENT_EDITOR_H
22 #define LS_INSTRUMENT_EDITOR_H
23
24 #include "../common/global.h"
25 #include "../common/Thread.h"
26
27 #include <set>
28
29 namespace LinuxSampler {
30
31 // just symbol prototyping
32 class InstrumentEditorListener;
33
34 /** @brief Instrument Editor Interface (external plugin)
35 *
36 * LinuxSampler allows to spawn arbitrary instrument editor applications
37 * within the sampler's own process. That way instrument editors are
38 * able to modify already loaded instruments live or on-the-fly, that is
39 * without having to load it again neither on sampler nor on editor side,
40 * which is essential for editing large instruments.
41 *
42 * Instrument editors have to implement this abstract base class, embedded
43 * into a DLL and placed into the respective sampler's library path. The
44 * sampler will load these external DLLs as plugins on startup. Whenever
45 * there's a request for editing an instrument, the sampler will try to
46 * launch a matching registered editor, by calling the respective
47 * plugin's @c Main() method.
48 */
49 class InstrumentEditor : protected Thread {
50 public:
51
52 /////////////////////////////////////////////////////////////////
53 // abstract methods
54 // (these have to be implemented by the descendant)
55
56 /**
57 * Entry point for the instrument editor's thread. As the
58 * instrument data structure is passed as typeless (void*)
59 * pointer, this is not type safe! The implementing instrument
60 * editor has to interpret the @a sTypeName and @a sTypeVersion
61 * arguments to determine if it's able to cast the instrument
62 * pointer to a known type and actually be able to work with it.
63 *
64 * @param pInstrument - pointer to the respective instrument object
65 * @param sTypeName - format of the instrument data structure
66 * (i.e. @c "libgig" )
67 * @param sTypeVersion - version of the instrument data structure
68 * (i.e. @c "3.0.1" ).
69 */
70 virtual int Main(void* pInstrument, String sTypeName, String sTypeVersion) = 0;
71
72 /**
73 * The instrument editor has to return @c true in case it supports
74 * the given instrument data structure type and version, it has to
75 * return @c false otherwise. This method will be called by the
76 * sampler to determine which editor is capable to work with a
77 * certain instrument.
78 *
79 * @param sTypeName - i.e. @c "libgig"
80 * @param sTypeVersion - i.e. @c "3.0.1"
81 */
82 virtual bool IsTypeSupported(String sTypeName, String sTypeVersion) = 0;
83
84 /**
85 * The instrument editor's name (i.e. @c "gigedit" ).
86 */
87 virtual String Name() = 0;
88
89 /**
90 * The instrument editor's version (i.e. @c "0.0.1" ).
91 */
92 virtual String Version() = 0;
93
94 /**
95 * Arbitrary textual description of the instrument editor
96 * (i.e. "Gigasampler and DLS format editor, GTK based").
97 */
98 virtual String Description() = 0;
99
100
101
102 /////////////////////////////////////////////////////////////////
103 // normal methods
104 // (usually not to be overriden by descendant)
105
106 /** @brief Dispatch pending sample removal event.
107 *
108 * @e SHOULD be called by the instrument editor @e before deleting
109 * samples, so the sampler can react by stopping usage of these
110 * samples to avoid a crash.
111 *
112 * After calling this method, the instrument editor @e MUST call
113 * @c NotifySamplesRemoved() after it actually deleted the samples, so
114 * the sampler can react by i.e. resuming playback of sampler engines.
115 *
116 * @param Samples - list of samples that will be deleted by the
117 * instrument editor
118 */
119 void NotifySamplesToBeRemoved(std::set<void*> Samples);
120
121 /** @brief Dispatch completed sample removal event.
122 *
123 * Inform the sampler that the by @c NotifySamplesToBeRemoved()
124 * previously announced samples have been deleted.
125 */
126 void NotifySamplesRemoved();
127
128 /** @brief Dispatch pending data structure modification event.
129 *
130 * @e SHOULD be called by the instrument editor @e before modifying
131 * data structures (except samples, which have their own dispatch
132 * methods) which could otherwise lead to undesired synchronisation
133 * issues and a crash. The respective data structure is passed as a
134 * typeless pointer @a pStruct , so the instrument editor additionally
135 * has to pass the name of the data structure (i.e. @c "gig::Region" ),
136 * so the sampler can cast the pointer to an appropriate type. The
137 * sampler will react by stopping usage of the respective data
138 * structure.
139 *
140 * After calling this method, the instrument editor @e MUST call
141 * @c NotifyDataStructureChanged() , so the sampler can react by
142 * resuming usage of the respective data structure for playback.
143 *
144 * @param pStruct - data structure going to be modified
145 * @param sStructType - name of the data structure (i.e. its C++
146 * struct or class name)
147 */
148 void NotifyDataStructureToBeChanged(void* pStruct, String sStructType);
149
150 /** @brief Dispatch completed data structure modification event.
151 *
152 * Inform the sampler that the by @c NotifyDataStructureToBeChanged()
153 * previously announced data structure has been completely modified.
154 *
155 * @param pStruct - data structure that has been modified
156 * @param sStructType - name of the data structure (i.e. its C++
157 * struct or class name)
158 */
159 void NotifyDataStructureChanged(void* pStruct, String sStructType);
160
161 /** @brief Dispatch sample reference changed event.
162 *
163 * @e SHOULD be called by the instrument editor @e after a certain data
164 * structure changed its reference / pointer to a sample, so the
165 * sampler can react by:
166 *
167 * - Caching the newly referenced sample if necessary.
168 * - Un-caching the old referenced sample if necessary.
169 *
170 * @e Note: the instrument editor additionally @e MUST embed this call
171 * into the respective @c NotifyDataStructureToBeChanged() and
172 * @c NotifyDataStructureChanged() calls for announcing the data
173 * structure whose sample reference is actually to be changed, so the
174 * sampler can react by suspending usage. For example:
175 * @code
176 * NotifyDataStructureToBeChanged(pDimReg, "gig::DimensionRegion");
177 * gig::Sample* pOldSample = pDimReg->pSample;
178 * pDimReg->pSample = pNewSample;
179 * NotifySampleReferenceChanged(pOldSample, pNewSample);
180 * NotifyDataStructureChanged(pDimReg, "gig::DimensionRegion");
181 * @endcode
182 * So calling this method alone is not safe!
183 *
184 * @param pOldSample - previous sample reference
185 * @param pNewSample - current sample reference
186 */
187 void NotifySampleReferenceChanged(void* pOldSample, void* pNewSample);
188
189 /**
190 * Launch the instrument editor for the given instrument. The
191 * editor will be spawned in its own thread and this method will
192 * return as soon as the editor's thread actually started.
193 */
194 void Launch(void* pInstrument, String sTypeName, String sTypeVersion);
195
196 /**
197 * Registers object that wants to be notified on events.
198 */
199 void AddListener(InstrumentEditorListener* pListener);
200
201 /**
202 * Unregisters object that doesn't want to be notified anymore.
203 */
204 void RemoveListener(InstrumentEditorListener* pListener);
205
206
207 /**
208 * Informs the instrument editor that a @e note @e on event occured
209 * (e.g. caused by a MIDI keyboard connected to the sampler).
210 * Communication acts asynchronously, that is this method call doesn't
211 * lock in any way and returns immediately. It is thus realtime safe.
212 *
213 * @e Note: this method is usually only called by the sampler.
214 *
215 * @see ActiveNotesChanged(), NoteIsActive()
216 */
217 void SendNoteOnToEditor(uint8_t Key, uint8_t Velocity);
218
219 /**
220 * Informs the instrument editor that a @e note @e off event occured
221 * (e.g. caused by a MIDI keyboard connected to the sampler).
222 * Communication acts asynchronously, that is this method call doesn't
223 * lock in any way and returns immediately. It is thus realtime safe.
224 *
225 * @e Note: this method is usually only called by the sampler.
226 *
227 * @see ActiveNotesChanged(), NoteIsActive()
228 */
229 void SendNoteOffToEditor(uint8_t Key, uint8_t Velocity);
230
231 /**
232 * Can be called by the instrument editor to check whether a new note
233 * on or note off MIDI event arrived to the sampler during the last
234 * call to this method. So this is a asynchronously, "polling" based
235 * communication mechanism, which works in conjunction with the
236 * NoteIsActive() method call.
237 */
238 bool NotesChanged();
239
240 /**
241 * Can be called by the instrument editor to check whether a new note
242 * on or note off MIDI event arrived to the sampler for @a Key during
243 * the last call to this method. So this is a asynchronously,
244 * "polling" based communication mechanism, which works in
245 * conjunction with the NoteIsActive() method call.
246 */
247 bool NoteChanged(uint8_t Key);
248
249 /**
250 * Can be called by the instrument editor to check which key / note
251 * is currently active by the sampler, e.g. to highlight the
252 * respective keys of a virtual keyboard in the instrument editor.
253 *
254 * @see NotesChanged(), NoteChanged()
255 */
256 bool NoteIsActive(uint8_t Key);
257
258 /**
259 * Constructor
260 */
261 InstrumentEditor();
262
263 /**
264 * Destructor
265 */
266 virtual ~InstrumentEditor();
267
268 protected:
269 std::set<InstrumentEditorListener*> listeners;
270
271 // derived abstract method from base class 'Thread'
272 virtual int Main();
273 private:
274 void* pInstrument;
275 String sTypeName;
276 String sTypeVersion;
277 void* pNotesChanged;
278 void* pNoteChanged;
279 void* pNoteIsActive;
280 };
281
282 /** @brief Instrument Editor Notifications
283 *
284 * This abstract interface class has to be implemented by classes that
285 * want to be notified on certain events of an instrument editor. This is
286 * typically used on sampler side, but might also be used by an instrument
287 * editor to get informed about modifications another instrument editor
288 * makes.
289 */
290 class InstrumentEditorListener {
291 public:
292 /** @brief Called after the instrument editor stopped running.
293 *
294 * Automatically called after the instrument editor application stopped
295 * running. This method has to be implemented by the descendant.
296 *
297 * @param pSender - instrument editor that died
298 */
299 virtual void OnInstrumentEditorQuit(InstrumentEditor* pSender) = 0;
300
301 /** @brief Called before samples are to be deleted.
302 *
303 * See the dispatcher method
304 * @c InstrumentEditor::NotifySamplesToBeRemoved() for details.
305 * This method has to be implemented by the descendant.
306 *
307 * @param Samples - list of samples that will be deleted by the
308 * instrument editor
309 * @param pSender - instrument editor that is going to do this
310 * modification
311 */
312 virtual void OnSamplesToBeRemoved(std::set<void*> Samples, InstrumentEditor* pSender) = 0;
313
314 /** @brief Called after samples have been deleted.
315 *
316 * See the dispatcher method
317 * @c InstrumentEditor::NotifySamplesRemoved() for details.
318 * This method has to be implemented by the descendant.
319 *
320 * @param pSender - instrument editor that did this modification
321 */
322 virtual void OnSamplesRemoved(InstrumentEditor* pSender) = 0;
323
324 /** @brief Called before data structure is to be modified.
325 *
326 * See the dispatcher method
327 * @c InstrumentEditor::NotifyDataStructureToBeChanged() for details.
328 * This method has to be implemented by the descendant.
329 *
330 * @param pStruct - data structure going to be modified
331 * @param sStructType - name of the data structure (i.e. its C++
332 * struct or class name)
333 * @param pSender - instrument editor that is going to do this
334 * modification
335 */
336 virtual void OnDataStructureToBeChanged(void* pStruct, String sStructType, InstrumentEditor* pSender) = 0;
337
338 /** @brief Called after data structure has been modified.
339 *
340 * See the dispatcher method
341 * @c InstrumentEditor::NotifyDataStructureChanged() for details.
342 * This method has to be implemented by the descendant.
343 *
344 * @param pStruct - data structure that has been modified
345 * @param sStructType - name of the data structure (i.e. its C++
346 * struct or class name)
347 * @param pSender - instrument editor that did this modification
348 */
349 virtual void OnDataStructureChanged(void* pStruct, String sStructType, InstrumentEditor* pSender) = 0;
350
351 /** @brief Called after some data structure changed its reference to a sample.
352 *
353 * @c InstrumentEditor::NotifySampleReferenceChanged() for details.
354 * This method has to be implemented by the descendant.
355 *
356 * @param pOldSample - previous sample reference
357 * @param pNewSample - current sample reference
358 * @param pSender - instrument editor that did this modification
359 */
360 virtual void OnSampleReferenceChanged(void* pOldSample, void* pNewSample, InstrumentEditor* pSender) = 0;
361 };
362
363 } // namespace LinuxSampler
364
365 #endif // LS_INSTRUMENT_EDITOR_H

  ViewVC Help
Powered by ViewVC