/[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 670 - (hide annotations) (download)
Tue Jun 21 18:00:52 2005 UTC (18 years, 10 months ago) by schoenebeck
File size: 10125 byte(s)
* don't reset volume, pan, pitch and MIDI controller values on instrument
  or audio output device change
* send 'CHANNEL_INFO' LSCP event on MIDI program change messages

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 670 void MidiInputPort::DispatchProgramChange(uint8_t Program, uint MidiChannel) {
176 schoenebeck 551 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 schoenebeck 670
193 schoenebeck 551 // 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 670
205 schoenebeck 411 Disconnect(pEngineChannel);
206 schoenebeck 670
207 schoenebeck 551 MidiChannelMapMutex.Lock();
208 schoenebeck 411 MidiChannelMap[MidiChannel].insert(pEngineChannel);
209 schoenebeck 551 MidiChannelMapMutex.Unlock();
210 schoenebeck 670
211     // mark engine channel as changed
212     pEngineChannel->StatusChanged(true);
213 schoenebeck 221 }
214    
215 schoenebeck 411 void MidiInputPort::Disconnect(EngineChannel* pEngineChannel) {
216 schoenebeck 551 MidiChannelMapMutex.Lock();
217 schoenebeck 411 try { for (int i = 0; i <= 16; i++) MidiChannelMap[i].erase(pEngineChannel); }
218 schoenebeck 221 catch(...) { /* NOOP */ }
219 schoenebeck 551 MidiChannelMapMutex.Unlock();
220 schoenebeck 670 // mark engine channel as changed
221     pEngineChannel->StatusChanged(true);
222 schoenebeck 221 }
223    
224     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC