/[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 551 - (show annotations) (download)
Tue May 17 18:16:54 2005 UTC (18 years, 11 months ago) by schoenebeck
File size: 9991 byte(s)
* Implemented MIDI program change as general, engine independant solution.
  The program number will determine the sampler channel to which the MIDI
  device will be connected to and the given MIDI channel defines on which
  MIDI channel that sampler channel should listen to. Also the program
  change will disconnect probably established connection from the previous
  program change event.

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 Disconnect(pEngineChannel);
206
207 MidiChannelMapMutex.Lock();
208 MidiChannelMap[MidiChannel].insert(pEngineChannel);
209 MidiChannelMapMutex.Unlock();
210 }
211
212 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
213 MidiChannelMapMutex.Lock();
214 try { for (int i = 0; i <= 16; i++) MidiChannelMap[i].erase(pEngineChannel); }
215 catch(...) { /* NOOP */ }
216 MidiChannelMapMutex.Unlock();
217 }
218
219 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC