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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 551 - (hide 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 schoenebeck 221 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 411 * Copyright (C) 2005 Christian Schoenebeck *
7 schoenebeck 221 * *
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 schoenebeck 551 #include "../../Sampler.h"
27    
28 schoenebeck 221 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 schoenebeck 551 pPreviousProgramChangeEngineChannel = NULL;
76 schoenebeck 221 }
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 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
92     {
93 schoenebeck 411 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
94     std::set<EngineChannel*>::iterator end = MidiChannelMap[MidiChannel].end();
95 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
96     }
97     // dispatch event for engines listening to ALL MIDI channels
98     {
99 schoenebeck 411 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
100     std::set<EngineChannel*>::iterator end = MidiChannelMap[midi_chan_all].end();
101 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOn(Key, Velocity);
102     }
103 schoenebeck 221 }
104    
105     void MidiInputPort::DispatchNoteOff(uint8_t Key, uint8_t Velocity, uint MidiChannel) {
106 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
107     {
108 schoenebeck 411 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
109     std::set<EngineChannel*>::iterator end = MidiChannelMap[MidiChannel].end();
110 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
111     }
112     // dispatch event for engines listening to ALL MIDI channels
113     {
114 schoenebeck 411 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
115     std::set<EngineChannel*>::iterator end = MidiChannelMap[midi_chan_all].end();
116 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendNoteOff(Key, Velocity);
117     }
118 schoenebeck 221 }
119    
120     void MidiInputPort::DispatchPitchbend(int Pitch, uint MidiChannel) {
121 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
122     {
123 schoenebeck 411 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
124     std::set<EngineChannel*>::iterator end = MidiChannelMap[MidiChannel].end();
125 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
126     }
127     // dispatch event for engines listening to ALL MIDI channels
128     {
129 schoenebeck 411 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
130     std::set<EngineChannel*>::iterator end = MidiChannelMap[midi_chan_all].end();
131 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendPitchbend(Pitch);
132     }
133 schoenebeck 221 }
134    
135     void MidiInputPort::DispatchControlChange(uint8_t Controller, uint8_t Value, uint MidiChannel) {
136 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
137     {
138 schoenebeck 411 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[MidiChannel].begin();
139     std::set<EngineChannel*>::iterator end = MidiChannelMap[MidiChannel].end();
140 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
141     }
142     // dispatch event for engines listening to ALL MIDI channels
143     {
144 schoenebeck 411 std::set<EngineChannel*>::iterator engineiter = MidiChannelMap[midi_chan_all].begin();
145     std::set<EngineChannel*>::iterator end = MidiChannelMap[midi_chan_all].end();
146 schoenebeck 274 for (; engineiter != end; engineiter++) (*engineiter)->SendControlChange(Controller, Value);
147     }
148 schoenebeck 221 }
149    
150 schoenebeck 244 void MidiInputPort::DispatchSysex(void* pData, uint Size) {
151 schoenebeck 274 // dispatch event for engines listening to the same MIDI channel
152     {
153     for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {
154 schoenebeck 411 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 schoenebeck 274 }
161 schoenebeck 244 }
162 schoenebeck 274 // dispatch event for engines listening to ALL MIDI channels
163     {
164     for (uint MidiChannel = 0; MidiChannel <= 16; MidiChannel++) {
165 schoenebeck 411 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 schoenebeck 274 }
172     }
173 schoenebeck 244 }
174    
175 schoenebeck 551 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 schoenebeck 411 void MidiInputPort::Connect(EngineChannel* pEngineChannel, midi_chan_t MidiChannel) {
202 schoenebeck 221 if (MidiChannel < 0 || MidiChannel > 16)
203     throw MidiInputException("MIDI channel index out of bounds");
204 schoenebeck 551
205 schoenebeck 411 Disconnect(pEngineChannel);
206 schoenebeck 551
207     MidiChannelMapMutex.Lock();
208 schoenebeck 411 MidiChannelMap[MidiChannel].insert(pEngineChannel);
209 schoenebeck 551 MidiChannelMapMutex.Unlock();
210 schoenebeck 221 }
211    
212 schoenebeck 411 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
213 schoenebeck 551 MidiChannelMapMutex.Lock();
214 schoenebeck 411 try { for (int i = 0; i <= 16; i++) MidiChannelMap[i].erase(pEngineChannel); }
215 schoenebeck 221 catch(...) { /* NOOP */ }
216 schoenebeck 551 MidiChannelMapMutex.Unlock();
217 schoenebeck 221 }
218    
219     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC