1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6  *   Copyright (C) 2005 - 2014 Christian Schoenebeck                       *
7  *                                                                         *
8  *   This program 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 program 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 program; 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_MIDIINPUTDEVICE_H__
25 #define __LS_MIDIINPUTDEVICE_H__
26 
27 #include <stdexcept>
28 #include <set>
29 #include <map>
30 #include <vector>
31 
32 #include "../../common/global.h"
33 #include "../../common/Exception.h"
34 #include "../DeviceParameter.h"
35 #include "MidiInputPort.h"
36 #include "../../engines/Engine.h"
37 #include "../../EventListeners.h"
38 
39 namespace LinuxSampler {
40 
41     // just symbol prototyping
42     class MidiInputPort;
43     class Engine;
44     class MidiInputDeviceFactory;
45 
46     /**
47      * Midi input exception that should be thrown by the MidiInputDevice
48      * descendants in case initialization of the MIDI input system failed
49      * (which should be done in the constructor of the MidiInputDevice
50      * descendant).
51      */
52     class MidiInputException : public Exception {
53         public:
MidiInputException(const std::string & msg)54             MidiInputException(const std::string& msg) : Exception(msg) {}
55     };
56 
57     /** Abstract base class for MIDI input drivers in LinuxSampler
58      *
59      * This class will be derived by specialized classes which implement the
60      * connection to a specific MIDI input system (e.g. Alsa Sequencer,
61      * CoreMIDI). The MidiInputDevice desendant should just call the
62      * appropriate (protected) Dispatch* method here when an MIDI event
63      * occured. The dispatch* methods here will automatically forward the
64      * MIDI event to the appropriate, connected sampler engines.
65      */
66     class MidiInputDevice : public Device {
67         public:
68 
69             /////////////////////////////////////////////////////////////////
70             // type definitions
71 
72             /** Device Parameter 'ACTIVE'
73              *
74              * Used to activate / deactivate the MIDI input device.
75              */
76             class ParameterActive : public DeviceCreationParameterBool {
77                 public:
78                     ParameterActive();
79                     ParameterActive(String active);
80                     virtual String Description() OVERRIDE;
81                     virtual bool   Fix() OVERRIDE;
82                     virtual bool   Mandatory() OVERRIDE;
83                     virtual std::map<String,DeviceCreationParameter*> DependsAsParameters() OVERRIDE;
84                     virtual optional<bool> DefaultAsBool(std::map<String,String> Parameters) OVERRIDE;
85                     virtual void OnSetValue(bool b) throw (Exception) OVERRIDE;
86                     static String Name();
87             };
88 
89             /** Device Parameter 'PORTS'
90              *
91              * Used to increase / decrease the number of MIDI ports of the
92              * MIDI input device.
93              */
94             class ParameterPorts : public DeviceCreationParameterInt {
95                 public:
96                     ParameterPorts();
97                     ParameterPorts(String val);
98                     virtual String Description() OVERRIDE;
99                     virtual bool   Fix() OVERRIDE;
100                     virtual bool   Mandatory() OVERRIDE;
101                     virtual std::map<String,DeviceCreationParameter*> DependsAsParameters() OVERRIDE;
102                     virtual optional<int>    DefaultAsInt(std::map<String,String> Parameters) OVERRIDE;
103                     virtual optional<int>    RangeMinAsInt(std::map<String,String> Parameters) OVERRIDE;
104                     virtual optional<int>    RangeMaxAsInt(std::map<String,String> Parameters) OVERRIDE;
105                     virtual std::vector<int> PossibilitiesAsInt(std::map<String,String> Parameters) OVERRIDE;
106                     virtual void             OnSetValue(int i) throw (Exception) OVERRIDE;
107                     static String Name();
108             };
109 
110 
111 
112             /////////////////////////////////////////////////////////////////
113             // abstract methods
114             //     (these have to be implemented by the descendant)
115 
116             /**
117              * Start listen to MIDI input events on the MIDI input port.
118              * The MIDIInputPort descendant should forward all MIDI input
119              * events by calling the appropriate (protected) Dispatch*
120              * method of class MidiInputPort.
121              */
122             virtual void Listen() = 0;
123 
124             /**
125              * Stop to listen to MIDI input events on the MIDI input port.
126              * After this method was called, the MidiInputPort descendant
127              * should ignore all MIDI input events.
128              */
129             virtual void StopListen() = 0;
130 
131             /**
132              * Return device driver name
133              */
134             virtual String Driver() = 0;
135 
136             /**
137              * Create new Midi port
138              * This will be called by AcquirePorts
139              * Each individual device must implement this.
140              */
141             virtual MidiInputPort* CreateMidiPort() = 0;
142 
143 
144 
145             /////////////////////////////////////////////////////////////////
146             // normal methods
147             //     (usually not to be overriden by descendant)
148 
149             /**
150              * Return midi port \a iPort.
151              *
152              * @throws MidiInputException  if index out of bounds
153              */
154             MidiInputPort* GetPort(uint iPort) throw (MidiInputException);
155 
156             /**
157              * Returns amount of MIDI ports this MIDI input device currently
158              * provides.
159              */
160             uint PortCount();
161 
162             /**
163              * Return all device parameter settings.
164              */
165             std::map<String,DeviceCreationParameter*> DeviceParameters();
166 
167             /**
168              * Returns the unique ID number associated with this MIDIInputDevice
169              * instance. This ID number is unique among all MIDIInputDevice
170              * instances of the same Sampler instance and during the whole
171              * lifetime of the Sampler instance.
172              *
173              * @returns a value equal or larger than 0, a negative value only
174              *          on severe internal problems
175              */
176             int MidiInputDeviceID();
177 
178             /**
179              * Registers the specified listener to be notified
180              * when the number of MIDI input ports is changed.
181              */
182             void AddMidiPortCountListener(MidiPortCountListener* l);
183 
184             /**
185              * Removes the specified listener, to stop being notified of
186              * further MIDI input port count chances.
187              */
188             void RemoveMidiPortCountListener(MidiPortCountListener* l);
189 
190         protected:
191             std::map<String,DeviceCreationParameter*> Parameters;  ///< All device parameters.
192             std::map<int,MidiInputPort*> Ports;                    ///< All MIDI ports.
193             void* pSampler;                                        ///< Sampler instance. FIXME: should actually be of type Sampler*
194             ListenerList<MidiPortCountListener*> portCountListeners;
195 
196             /**
197              * Constructor
198              *
199              * FIXME: the pointer argument \a pSapmler should actually be of type Sampler*.
200              * Unfortunately the bidirectional relationship between this
201              * header and Sampler.h would clash on header file inclusion,
202              * so that's why I had to make it of type void* here. This is
203              * an annoying constraint of C++.
204              */
205             MidiInputDevice(std::map<String,DeviceCreationParameter*> DriverParameters, void* pSampler);
206 
207             /**
208              * Destructor
209              */
210             virtual ~MidiInputDevice();
211 
212             /**
213              * Notifies listeners that the amount of MIDI inpurt ports have
214              * been changed.
215              * @param NewCount The new number of MIDI input ports.
216              */
217             void fireMidiPortCountChanged(int NewCount);
218 
219             /**
220              * Notifies listeners that the supplied MIDI input port is
221              * going to be removed soon.
222              * @param pPort The MIDI input port that is going to be removed.
223              */
224             void fireMidiPortToBeRemoved(MidiInputPort* pPort);
225 
226             /**
227              * Notifies listeners that the supplied MIDI input port has
228              * just been added.
229              * @param pPort The MIDI input port that has been added.
230              */
231             void fireMidiPortAdded(MidiInputPort* pPort);
232 
233             /**
234              * Set number of MIDI ports required by the engine
235              * This can either do nothing, create more ports
236              * or destroy ports depenging on the parameter
237              * and how many ports already exist on this driver.
238              *
239              * @param Ports - number of ports to be left on this driver after this call.
240              */
241             void AcquirePorts(uint Ports);
242 
243             friend class ParameterActive;
244             friend class ParameterPorts;
245             friend class MidiInputDeviceFactory; // allow MidiInputDeviceFactory class to destroy midi devices
246             friend class MidiInputPort; // allow MidiInputPort to access pSampler
247     };
248 }
249 
250 #endif // __LS_MIDIINPUTDEVICE_H__
251