1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6  *   Copyright (C) 2005 - 2015 Christian Schoenebeck                       *
7  *                                                                         *
8  *   This library is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This library is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this library; if not, write to the Free Software           *
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  ***************************************************************************/
23 
24 #ifndef __LS_INSTRUMENTMANAGER_H__
25 #define __LS_INSTRUMENTMANAGER_H__
26 
27 #include "../common/global.h"
28 #include "../common/Exception.h"
29 
30 #include <vector>
31 
32 namespace LinuxSampler {
33 
34     // just symbol prototyping
35     class EngineChannel;
36     class InstrumentEditor;
37 
38     /**
39      * Will be thrown by InstrumentManager implementations on errors.
40      */
41     class InstrumentManagerException : public Exception {
42         public:
InstrumentManagerException(String msg)43             InstrumentManagerException(String msg) : Exception(msg) {}
44     };
45 
46     /** @brief Abstract interface class for InstrumentManagers.
47      *
48      * Sampler engines should provide an InstrumentManager for allowing
49      * detailed information retrieval and setting of its managed instruments
50      * through this general API.
51      */
52     class InstrumentManager {
53         public:
54             /**
55              * Defines life-time of an instrument.
56              */
57             enum mode_t {
58                 ON_DEMAND      = 0, ///< Instrument will be loaded when needed, freed once not needed anymore.
59                 ON_DEMAND_HOLD = 1, ///< Instrument will be loaded when needed and kept even if not needed anymore.
60                 PERSISTENT     = 2  ///< Instrument will immediately be loaded and kept all the time.
61             };
62 
63             /**
64              * Reflects unique ID of an instrument.
65              */
66             struct instrument_id_t {
67                 String FileName; ///< File name of the instrument.
68                 uint   Index;    ///< Index of the instrument within the file.
69 
70                 // TODO: we should extend operator<() so it will be able to detect that file x and file y are actually the same files, e.g. because one of them is a symlink / share the same inode
71                 bool operator<(const instrument_id_t& o) const {
72                     return (Index < o.Index || (Index == o.Index && FileName < o.FileName));
73                 }
74 
75                 bool operator==(const instrument_id_t& o) const {
76                     return (Index == o.Index && FileName == o.FileName);
77                 }
78             };
79 
80             /**
81              * Rather abstract informations about an instrument.
82              */
83             struct instrument_info_t {
84                 String InstrumentName;
85                 String FormatVersion;
86                 String Product;
87                 String Artists;
88                 uint8_t KeyBindings[128];
89                 uint8_t KeySwitchBindings[128];
90             };
91 
92             /**
93              * Returns all managed instruments.
94              *
95              * This method has to be implemented by the descendant.
96              */
97             virtual std::vector<instrument_id_t> Instruments() = 0;
98 
99             /**
100              * Returns the current life-time strategy for the given
101              * instrument.
102              *
103              * This method has to be implemented by the descendant.
104              */
105             virtual mode_t GetMode(const instrument_id_t& ID) = 0;
106 
107             /**
108              * Change the current life-time strategy for the given
109              * instrument.
110              *
111              * This method has to be implemented by the descendant.
112              */
113             virtual void SetMode(const instrument_id_t& ID, mode_t Mode) = 0;
114 
115             /**
116              * Same as SetMode(), but with the difference that this method
117              * won't block.
118              */
119             void SetModeInBackground(const instrument_id_t& ID, mode_t Mode);
120 
121             /**
122              * Same as loading the given instrument directly on the given
123              * EngineChannel, but this method will not block, instead it
124              * will load the instrument in a separate thread.
125              *
126              * @param ID - the instrument to be loaded
127              * @param pEngineChannel - on which engine channel the instrument
128              *                         should be loaded
129              */
130             static void LoadInstrumentInBackground(instrument_id_t ID, EngineChannel* pEngineChannel);
131 
132             /**
133              * Stops the background thread that has been started by
134              * LoadInstrumentInBackground.
135              */
136             static void StopBackgroundThread();
137 
138             /**
139              * Returns the name of the given instrument as reflected by its
140              * file.
141              *
142              * This method has to be implemented by the descendant.
143              */
144             virtual String GetInstrumentName(instrument_id_t ID) = 0;
145 
146             /**
147              * Returns a textual identifier of the data structure for the
148              * given loaded instrument, which usually reflects the name of
149              * of the library used to load the instrument (i.e. "libgig").
150              *
151              * This method has to be implemented by the descendant.
152              */
153             virtual String GetInstrumentDataStructureName(instrument_id_t ID) = 0;
154 
155             /**
156              * Returns the version of the data structure for the given
157              * loaded instrument, which usually reflects the version of the
158              * library which was used to load the instrument (i.e. "3.1.0").
159              *
160              * This method has to be implemented by the descendant.
161              */
162             virtual String GetInstrumentDataStructureVersion(instrument_id_t ID) = 0;
163 
164             /**
165              * Spawn an appropriate editor for the given instrument that is
166              * actually capable to handle the instrument's format and data
167              * structure. The instrument editor will be hosted in the
168              * sampler's own process to allow immediate live-editing of the
169              * instrument while playing the instrument in parallel by the
170              * sampler.
171              *
172              * For this to work, instrument editor applications have to
173              * implement the abstract interface class @c InstrumentEditor
174              * and have to generate a plugin DLL that has to be placed into
175              * the appropriate plugin directory of the sampler.
176              *
177              * This method has to be implemented by the descendant.
178              *
179              * @param pEngineChannel - engine channel for which an instrument
180              *                         editor shall be launched for
181              * @param ID - the instrument for which an editor should be
182              *             spawned for
183              * @param pUserData - (optional) arbitrary 3rd party user data
184              *                    that will blindly be passed to
185              *                    InstrumentEditor::Main()
186              * @returns pointer to the launched editor
187              * @throws InstrumentManagerException - in case no compatible
188              *         instrument editor is registered to the sampler
189              */
190             virtual InstrumentEditor* LaunchInstrumentEditor(EngineChannel* pEngineChannel, instrument_id_t ID, void* pUserData = NULL) throw (InstrumentManagerException) = 0;
191 
192             /**
193              * Returns a list of instrument IDs of the provided instrument
194              * file in case the provided file's format is supported.
195              *
196              * @throws InstrumentManagerException if the format of the
197              *         provided instrument file is not supported
198              */
199             virtual std::vector<instrument_id_t> GetInstrumentFileContent(String File) throw (InstrumentManagerException) = 0;
200 
201             /**
202              * Get detailed informations about the provided instrument file.
203              *
204              * @throws InstrumentManagerException if the format of the
205              *         provided instrument file is not supported
206              */
207             virtual instrument_info_t GetInstrumentInfo(instrument_id_t ID) throw (InstrumentManagerException) = 0;
208     };
209 
210 }
211 
212 #endif // __LS_INSTRUMENTMANAGER_H__
213