1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6  *   Copyright (C) 2005 - 2016 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 #include "MidiInputDevice.h"
25 
26 #include "../../common/global_private.h"
27 #include "../../Sampler.h"
28 #include "MidiInputDeviceFactory.h"
29 
30 namespace LinuxSampler {
31 
32 // *************** ParameterActive ***************
33 // *
34 
ParameterActive()35     MidiInputDevice::ParameterActive::ParameterActive() : DeviceCreationParameterBool() {
36         InitWithDefault();
37     }
38 
ParameterActive(String active)39     MidiInputDevice::ParameterActive::ParameterActive(String active) : DeviceCreationParameterBool(active) {
40     }
41 
Description()42     String MidiInputDevice::ParameterActive::Description() {
43         return "Enable / disable device";
44     }
45 
Fix()46     bool MidiInputDevice::ParameterActive::Fix() {
47         return false;
48     }
49 
Mandatory()50     bool MidiInputDevice::ParameterActive::Mandatory() {
51         return false;
52     }
53 
DependsAsParameters()54     std::map<String,DeviceCreationParameter*> MidiInputDevice::ParameterActive::DependsAsParameters() {
55         return std::map<String,DeviceCreationParameter*>();
56     }
57 
DefaultAsBool(std::map<String,String> Parameters)58     optional<bool> MidiInputDevice::ParameterActive::DefaultAsBool(std::map<String,String> Parameters) {
59         return true;
60     }
61 
OnSetValue(bool b)62     void MidiInputDevice::ParameterActive::OnSetValue(bool b) throw (Exception) {
63         if (b) ((MidiInputDevice*)pDevice)->Listen();
64         else ((MidiInputDevice*)pDevice)->StopListen();
65     }
66 
Name()67     String MidiInputDevice::ParameterActive::Name() {
68         return "ACTIVE";
69     }
70 
71 
72 
73 // *************** ParameterPorts ***************
74 // *
75 
ParameterPorts()76     MidiInputDevice::ParameterPorts::ParameterPorts() : DeviceCreationParameterInt() {
77         InitWithDefault();
78     }
79 
ParameterPorts(String val)80     MidiInputDevice::ParameterPorts::ParameterPorts(String val) : DeviceCreationParameterInt(val) {
81     }
82 
Description()83     String MidiInputDevice::ParameterPorts::Description() {
84         return "Number of ports";
85     }
86 
Fix()87     bool MidiInputDevice::ParameterPorts::Fix() {
88         return false;
89     }
90 
Mandatory()91     bool MidiInputDevice::ParameterPorts::Mandatory() {
92         return false;
93     }
94 
DependsAsParameters()95     std::map<String,DeviceCreationParameter*> MidiInputDevice::ParameterPorts::DependsAsParameters() {
96         return std::map<String,DeviceCreationParameter*>();
97     }
98 
DefaultAsInt(std::map<String,String> Parameters)99     optional<int> MidiInputDevice::ParameterPorts::DefaultAsInt(std::map<String,String> Parameters) {
100         return 1;
101     }
102 
RangeMinAsInt(std::map<String,String> Parameters)103     optional<int> MidiInputDevice::ParameterPorts::RangeMinAsInt(std::map<String,String> Parameters) {
104         return 1;
105     }
106 
RangeMaxAsInt(std::map<String,String> Parameters)107     optional<int> MidiInputDevice::ParameterPorts::RangeMaxAsInt(std::map<String,String> Parameters) {
108         return optional<int>::nothing;
109     }
110 
PossibilitiesAsInt(std::map<String,String> Parameters)111     std::vector<int> MidiInputDevice::ParameterPorts::PossibilitiesAsInt(std::map<String,String> Parameters) {
112         return std::vector<int>();
113     }
114 
OnSetValue(int i)115     void MidiInputDevice::ParameterPorts::OnSetValue(int i) throw (Exception) {
116         MidiInputDevice* dev = static_cast<MidiInputDevice*> (pDevice);
117         Sampler* s = static_cast<Sampler*> (dev->pSampler);
118         std::map<uint, SamplerChannel*> channels = s->GetSamplerChannels();
119         std::map<uint, SamplerChannel*>::iterator iter = channels.begin();
120         for (; iter != channels.end(); iter++) {
121             SamplerChannel* chn = iter->second;
122             std::vector<MidiInputPort*> vPorts = chn->GetMidiInputPorts();
123             for (int k = 0; k < vPorts.size(); ++k) {
124                 if (vPorts[k]->GetDevice() != pDevice)
125                     continue;
126                 int port = vPorts[k]->GetPortNumber();
127                 if (port >= i) {
128                     String err = "Sampler channel " + ToString(iter->first);
129                     err += " is still connected to MIDI port " + ToString(port);
130                     throw Exception(err);
131                 }
132             }
133         }
134 
135         ((MidiInputDevice*)pDevice)->AcquirePorts(i);
136     }
137 
Name()138     String MidiInputDevice::ParameterPorts::Name() {
139         return "PORTS";
140     }
141 
142 
143 
144 // *************** MidiInputDevice ***************
145 // *
146 
MidiInputDevice(std::map<String,DeviceCreationParameter * > DriverParameters,void * pSampler)147     MidiInputDevice::MidiInputDevice(std::map<String,DeviceCreationParameter*> DriverParameters, void* pSampler) {
148         this->Parameters = DriverParameters;
149         this->pSampler   = pSampler;
150     }
151 
~MidiInputDevice()152     MidiInputDevice::~MidiInputDevice() {
153         std::map<String,DeviceCreationParameter*>::iterator iter = Parameters.begin();
154         while (iter != Parameters.end()) {
155             delete iter->second;
156             iter++;
157         }
158         Parameters.clear();
159     }
160 
GetPort(uint iPort)161     MidiInputPort* MidiInputDevice::GetPort(uint iPort) throw (MidiInputException) {
162         if (iPort >= Ports.size()) throw MidiInputException("There is no port " + ToString(iPort));
163         return Ports[iPort];
164     }
165 
PortCount()166     uint MidiInputDevice::PortCount() {
167         return (uint) Ports.size();
168     }
169 
DeviceParameters()170     std::map<String,DeviceCreationParameter*> MidiInputDevice::DeviceParameters() {
171         return Parameters;
172     }
173 
MidiInputDeviceID()174     int MidiInputDevice::MidiInputDeviceID() {
175         std::map<uint, MidiInputDevice*> mDevices = MidiInputDeviceFactory::Devices();
176         for (std::map<uint, MidiInputDevice*>::const_iterator it = mDevices.begin(); it != mDevices.end(); ++it) {
177             if (it->second == this) {
178                 return it->first;
179             }
180         }
181         return -1;
182     }
183 
AddMidiPortCountListener(MidiPortCountListener * l)184     void MidiInputDevice::AddMidiPortCountListener(MidiPortCountListener* l) {
185         portCountListeners.AddListener(l);
186     }
187 
RemoveMidiPortCountListener(MidiPortCountListener * l)188     void MidiInputDevice::RemoveMidiPortCountListener(MidiPortCountListener* l) {
189         portCountListeners.RemoveListener(l);
190     }
191 
fireMidiPortCountChanged(int NewCount)192     void MidiInputDevice::fireMidiPortCountChanged(int NewCount) {
193         for (int i = 0; i < portCountListeners.GetListenerCount(); i++) {
194             portCountListeners.GetListener(i)->MidiPortCountChanged(NewCount);
195         }
196     }
197 
fireMidiPortToBeRemoved(MidiInputPort * pPort)198     void MidiInputDevice::fireMidiPortToBeRemoved(MidiInputPort* pPort) {
199         for (int i = 0; i < portCountListeners.GetListenerCount(); i++) {
200             portCountListeners.GetListener(i)->MidiPortToBeRemoved(pPort);
201         }
202     }
203 
fireMidiPortAdded(MidiInputPort * pPort)204     void MidiInputDevice::fireMidiPortAdded(MidiInputPort* pPort) {
205         for (int i = 0; i < portCountListeners.GetListenerCount(); i++) {
206             portCountListeners.GetListener(i)->MidiPortAdded(pPort);
207         }
208     }
209 
AcquirePorts(uint newPorts)210     void MidiInputDevice::AcquirePorts(uint newPorts) {
211         //FIXME: hooo, this looks scary, no synchronization AT ALL yet!
212         int diff = int(this->Ports.size() - newPorts);
213         if (!diff)
214             return; // number of ports matches already, nothing to do
215 
216         while (diff != 0) {
217             if (diff > 0) { // we've got too many ports, remove one
218                 std::map<int,MidiInputPort*>::iterator portsIter = Ports.end();
219                 --portsIter;
220 
221                 fireMidiPortToBeRemoved(portsIter->second);
222                 delete portsIter->second;
223                 Ports.erase(portsIter);
224                 diff--;
225             }
226             if (diff < 0) { // we don't have enough ports, create one
227                 MidiInputPort* midiPort = this->CreateMidiPort();
228                 Ports[midiPort->portNumber] = midiPort;
229                 diff++;
230                 fireMidiPortAdded(midiPort);
231             }
232         }
233         fireMidiPortCountChanged((int)Ports.size());
234     }
235 
236 } // namespace LinuxSampler
237