/[svn]/linuxsampler/trunk/src/drivers/midi/MidiInputPort.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/drivers/midi/MidiInputPort.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 675 - (show annotations) (download)
Wed Jun 22 22:09:28 2005 UTC (16 years, 1 month ago) by schoenebeck
File size: 11031 byte(s)
* update MIDI channel info on program change

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 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 "MidiInputPort.h"
25
26 #include "../../Sampler.h"
27
28 namespace LinuxSampler {
29
30 // *************** ParameterName ***************
31 // *
32
33 MidiInputPort::ParameterName::ParameterName(MidiInputPort* pPort) : DeviceRuntimeParameterString("Port " + ToString(pPort->GetPortNumber())) {
34 this->pPort = pPort;
35 }
36
37 MidiInputPort::ParameterName::ParameterName(MidiInputPort* pPort, String val) : DeviceRuntimeParameterString(val) {
38 this->pPort = pPort;
39 }
40
41 String MidiInputPort::ParameterName::Description() {
42 return "Name for this port";
43 }
44
45 bool MidiInputPort::ParameterName::Fix() {
46 return false;
47 }
48
49 std::vector<String> MidiInputPort::ParameterName::PossibilitiesAsString() {
50 return std::vector<String>();
51 }
52
53 void MidiInputPort::ParameterName::OnSetValue(String s) throw (LinuxSamplerException) {
54 return; /* FIXME: Nothing to do here */
55 }
56
57
58
59 // *************** MidiInputPort ***************
60 // *
61
62 MidiInputPort::~MidiInputPort() {
63 std::map<String,DeviceRuntimeParameter*>::iterator iter = Parameters.begin();
64 while (iter != Parameters.end()) {
65 Parameters.erase(iter);
66 delete iter->second;
67 iter++;
68 }
69 }
70
71 MidiInputPort::MidiInputPort(MidiInputDevice* pDevice, int portNumber) {
72 this->pDevice = pDevice;
73 this->portNumber = portNumber;
74 Parameters["NAME"] = new ParameterName(this);
75 pPreviousProgramChangeEngineChannel = NULL;
76 }
77
78 MidiInputDevice* MidiInputPort::GetDevice() {
79 return pDevice;
80 }
81
82 uint MidiInputPort::GetPortNumber() {
83 return portNumber;
84 }
85
86 std::map<String,DeviceRuntimeParameter*> MidiInputPort::PortParameters() {
87 return Parameters;
88 }
89
90 void MidiInputPort::DispatchNoteOn(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
91 // dispatch event for engines listening to the same MIDI channel
92 {
93 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
94 std::set<EngineChannel*>::iterator end = MidiChannelMap[MidiChannel].end();
95 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
96 }
97 // dispatch event for engines listening to ALL MIDI channels
98 {
99 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
100 std::set<EngineChannel*>::iterator end = MidiChannelMap[midi_chan_all].end();
101 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
102 }
103 }
104
105 void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
106 // dispatch event for engines listening to the same MIDI channel
107 {
108 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
109 std::set<EngineChannel*>::iterator end = MidiChannelMap[MidiChannel].end();
110 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
111 }
112 // dispatch event for engines listening to ALL MIDI channels
113 {
114 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
115 std::set<EngineChannel*>::iterator end = MidiChannelMap[midi_chan_all].end();
116 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
117 }
118 }
119
120 void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
121 // dispatch event for engines listening to the same MIDI channel
122 {
123 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
124 std::set<EngineChannel*>::iterator end = MidiChannelMap[MidiChannel].end();
125 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
126 }
127 // dispatch event for engines listening to ALL MIDI channels
128 {
129 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
130 std::set<EngineChannel*>::iterator end = MidiChannelMap[midi_chan_all].end();
131 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
132 }
133 }
134
135 void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
136 // dispatch event for engines listening to the same MIDI channel
137 {
138 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
139 std::set<EngineChannel*>::iterator end = MidiChannelMap[MidiChannel].end();
140 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
141 }
142 // dispatch event for engines listening to ALL MIDI channels
143 {
144 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
145 std::set<EngineChannel*>::iterator end = MidiChannelMap[midi_chan_all].end();
146 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
147 }
148 }
149
150 void MidiInputPort::DispatchSysex(void* pData, uint Size) {
151 // dispatch event for engines listening to the same MIDI channel
152 {
153 for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {
154 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
155 std::set<EngineChannel*>::iterator end = MidiChannelMap[MidiChannel].end();
156 for (; engineiter != end; engineiter++) {
157 Engine* pEngine = (*engineiter)->GetEngine();
158 if (pEngine) pEngine->SendSysex(pData, Size);
159 }
160 }
161 }
162 // dispatch event for engines listening to ALL MIDI channels
163 {
164 for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {
165 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
166 std::set<EngineChannel*>::iterator end = MidiChannelMap[midi_chan_all].end();
167 for (; engineiter != end; engineiter++) {
168 Engine* pEngine = (*engineiter)->GetEngine();
169 if (pEngine) pEngine->SendSysex(pData, Size);
170 }
171 }
172 }
173 }
174
175 void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
176 if (!pDevice || !pDevice->pSampler) {
177 std::cerr << "MidiInputPort: ERROR, no sampler instance to handle program change."
178 << "This is a bug, please report it!\n" << std::flush;
179 return;
180 }
181
182 Sampler* pSampler = (Sampler*) pDevice->pSampler;
183 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(Program);
184 if (!pSamplerChannel) return;
185
186 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
187 if (!pEngineChannel) return;
188
189 // disconnect from the engine channel which was connected by the last PC event
190 if (pPreviousProgramChangeEngineChannel)
191 Disconnect(pPreviousProgramChangeEngineChannel);
192
193 // now connect to the new engine channel and remember it
194 try {
195 Connect(pEngineChannel, (midi_chan_t) MidiChannel);
196 pPreviousProgramChangeEngineChannel = pEngineChannel;
197 }
198 catch (...) { /* NOOP */ }
199 }
200
201 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
202 if (MidiChannel < 0 || MidiChannel > 16)
203 throw MidiInputException("MIDI channel index out of bounds");
204
205 // firt check if desired connection is already established
206 MidiChannelMapMutex.Lock();
207 bool bAlreadyDone = MidiChannelMap[MidiChannel].count(pEngineChannel);
208 MidiChannelMapMutex.Unlock();
209 if (bAlreadyDone) return;
210
211 // remove all other connections of that engine channel (if any)
212 Disconnect(pEngineChannel);
213
214 // register engine channel on the desired MIDI channel
215 MidiChannelMapMutex.Lock();
216 MidiChannelMap[MidiChannel].insert(pEngineChannel);
217 MidiChannelMapMutex.Unlock();
218
219 // inform engine channel about this connection
220 pEngineChannel->Connect(this, MidiChannel);
221
222 // mark engine channel as changed
223 pEngineChannel->StatusChanged(true);
224 }
225
226 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
227 if (!pEngineChannel) return;
228
229 bool bChannelFound = false;
230
231 // unregister engine channel from all MIDI channels
232 MidiChannelMapMutex.Lock();
233 try {
234 for (int i = 0; i <= 16; i++) {
235 bChannelFound |= MidiChannelMap[i].count(pEngineChannel);
236 MidiChannelMap[i].erase(pEngineChannel);
237 }
238 }
239 catch(...) { /* NOOP */ }
240 MidiChannelMapMutex.Unlock();
241
242 // inform engine channel about the disconnection (if there is one)
243 if (bChannelFound) pEngineChannel->DisconnectMidiInputPort();
244
245 // mark engine channel as changed
246 pEngineChannel->StatusChanged(true);
247 }
248
249 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC