/[svn]/linuxsampler/trunk/src/engines/EngineChannel.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/EngineChannel.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1896 - (show annotations) (download)
Mon May 4 18:34:44 2009 UTC (14 years, 11 months ago) by persson
File size: 10507 byte(s)
* bugfix: two private structs had the same name, which could cause
  problems if the linker chose the wrong constructor

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2009 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 "EngineChannel.h"
25
26 #include <algorithm>
27
28 #include "../Sampler.h"
29 #include "../common/global_private.h"
30 #include "../drivers/midi/MidiInstrumentMapper.h"
31 #include "../common/atomic.h"
32
33 #define NO_MIDI_INSTRUMENT_MAP -1
34 #define DEFAULT_MIDI_INSTRUMENT_MAP -2
35
36 namespace LinuxSampler {
37
38 struct EngineChannel::private_data_t {
39 int iMute;
40 bool bSolo;
41 uint8_t uiMidiProgram;
42 uint8_t uiMidiBankMsb;
43 uint8_t uiMidiBankLsb;
44 uint8_t uiMidiRpnMsb; ///< MIDI Registered Parameter Number (upper 8 bits / coarse)
45 uint8_t uiMidiRpnLsb; ///< MIDI Registered Parameter Number (lower 8 bits / fine)
46 bool bMidiBankMsbReceived;
47 bool bMidiBankLsbReceived;
48 bool bProgramChangeReceived;
49 bool bMidiRpnReceived;
50 int iMidiInstrumentMap;
51 atomic_t voiceCount;
52 atomic_t diskStreamCount;
53 SamplerChannel* pSamplerChannel;
54 ListenerList<FxSendCountListener*> llFxSendCountListeners;
55 };
56
57 EngineChannel::EngineChannel() : p(new private_data_t) {
58 p->iMute = 0;
59 p->bSolo = false;
60 p->uiMidiBankMsb = 0;
61 p->uiMidiBankLsb = 0;
62 p->uiMidiProgram = 0;
63 p->bProgramChangeReceived =
64 p->bMidiBankMsbReceived =
65 p->bMidiBankLsbReceived = false;
66 p->iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;
67 SetVoiceCount(0);
68 SetDiskStreamCount(0);
69 p->pSamplerChannel = NULL;
70 ResetMidiRpnController();
71 }
72
73 EngineChannel::~EngineChannel() {
74 delete p;
75 }
76
77 void EngineChannel::SetMute(int state) throw (Exception) {
78 if (p->iMute == state) return;
79 if (state < -1 || state > 1)
80 throw Exception("Invalid Mute state: " + ToString(state));
81
82 p->iMute = state;
83
84 StatusChanged(true);
85 }
86
87 int EngineChannel::GetMute() {
88 return p->iMute;
89 }
90
91 void EngineChannel::SetSolo(bool solo) {
92 if (p->bSolo == solo) return;
93 p->bSolo = solo;
94 StatusChanged(true);
95 }
96
97 bool EngineChannel::GetSolo() {
98 return p->bSolo;
99 }
100
101 /*
102 We use a workaround for MIDI devices (i.e. old keyboards) which either
103 only send bank select MSB or only bank select LSB messages. Bank
104 selects will be modified according to the following table:
105
106 MIDI Sequence received: -> GetMidiBankMsb()= | GetMidiBankLsb()=
107 ---------------------------------------------------------------------------
108 program change -> 0 | 0
109 bank LSB, program change -> 0 | LSB value
110 bank MSB, program change -> 0 | MSB value
111 bank LSB, bank MSB, program change -> MSB value | LSB value
112 bank MSB, bank LSB, program change -> MSB value | LSB value
113 ---------------------------------------------------------------------------
114
115 That way we ensure those limited devices always to switch between the
116 following set of MIDI instrument banks: { 0, 1, 2, ..., 127 }
117 */
118
119 uint8_t EngineChannel::GetMidiProgram() {
120 return p->uiMidiProgram; // AFAIK atomic on all systems
121 }
122
123 void EngineChannel::SetMidiProgram(uint8_t Program) {
124 p->bProgramChangeReceived = true;
125 p->uiMidiProgram = Program; // AFAIK atomic on all systems
126 }
127
128 uint8_t EngineChannel::GetMidiBankMsb() {
129 return (p->bMidiBankMsbReceived && p->bMidiBankLsbReceived)
130 ? p->uiMidiBankMsb : 0;
131 }
132
133 void EngineChannel::SetMidiBankMsb(uint8_t BankMSB) {
134 if (p->bProgramChangeReceived) {
135 p->bProgramChangeReceived =
136 p->bMidiBankLsbReceived = false;
137 }
138 p->bMidiBankMsbReceived = true;
139 p->uiMidiBankMsb = BankMSB; // AFAIK atomic on all systems
140 }
141
142 uint8_t EngineChannel::GetMidiBankLsb() {
143 return (!p->bMidiBankMsbReceived && !p->bMidiBankLsbReceived)
144 ? 0
145 : (p->bMidiBankMsbReceived && !p->bMidiBankLsbReceived)
146 ? p->uiMidiBankMsb
147 : p->uiMidiBankLsb;
148 }
149
150 void EngineChannel::SetMidiBankLsb(uint8_t BankLSB) {
151 if (p->bProgramChangeReceived) {
152 p->bProgramChangeReceived =
153 p->bMidiBankMsbReceived = false;
154 }
155 p->bMidiBankLsbReceived = true;
156 p->uiMidiBankLsb = BankLSB; // AFAIK atomic on all systems
157 }
158
159 bool EngineChannel::UsesNoMidiInstrumentMap() {
160 return (p->iMidiInstrumentMap == NO_MIDI_INSTRUMENT_MAP);
161 }
162
163 bool EngineChannel::UsesDefaultMidiInstrumentMap() {
164 return (p->iMidiInstrumentMap == DEFAULT_MIDI_INSTRUMENT_MAP);
165 }
166
167 int EngineChannel::GetMidiInstrumentMap() throw (Exception) {
168 if (UsesNoMidiInstrumentMap())
169 throw Exception("EngineChannel is using no MIDI instrument map");
170 if (UsesDefaultMidiInstrumentMap())
171 throw Exception("EngineChannel is using default MIDI instrument map");
172 // check if the stored map still exists in the MIDI instrument mapper
173 std::vector<int> maps = MidiInstrumentMapper::Maps();
174 if (find(maps.begin(), maps.end(), p->iMidiInstrumentMap) == maps.end()) {
175 // it doesn't exist anymore, so fall back to NONE and throw an exception
176 p->iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;
177 throw Exception("Assigned MIDI instrument map doesn't exist anymore, falling back to NONE");
178 }
179 return p->iMidiInstrumentMap;
180 }
181
182 void EngineChannel::SetMidiInstrumentMapToNone() {
183 if (p->iMidiInstrumentMap == NO_MIDI_INSTRUMENT_MAP) return;
184 p->iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;
185 StatusChanged(true);
186 }
187
188 void EngineChannel::SetMidiInstrumentMapToDefault() {
189 if (p->iMidiInstrumentMap == DEFAULT_MIDI_INSTRUMENT_MAP) return;
190 p->iMidiInstrumentMap = DEFAULT_MIDI_INSTRUMENT_MAP;
191 StatusChanged(true);
192 }
193
194 void EngineChannel::SetMidiInstrumentMap(int MidiMap) throw (Exception) {
195 if (p->iMidiInstrumentMap == MidiMap) return;
196
197 // check if given map actually exists in the MIDI instrument mapper
198 std::vector<int> maps = MidiInstrumentMapper::Maps();
199 if (find(maps.begin(), maps.end(), MidiMap) == maps.end())
200 throw Exception("MIDI instrument map doesn't exist");
201 p->iMidiInstrumentMap = MidiMap; // assign the new map ID
202 StatusChanged(true);
203 }
204
205 void EngineChannel::SetMidiRpnControllerMsb(uint8_t CtrlMSB) {
206 p->uiMidiRpnMsb = CtrlMSB;
207 p->bMidiRpnReceived = true;
208 }
209
210 void EngineChannel::SetMidiRpnControllerLsb(uint8_t CtrlLSB) {
211 p->uiMidiRpnLsb = CtrlLSB;
212 p->bMidiRpnReceived = true;
213 }
214
215 void EngineChannel::ResetMidiRpnController() {
216 p->uiMidiRpnMsb = p->uiMidiRpnLsb = 0;
217 p->bMidiRpnReceived = false;
218 }
219
220 int EngineChannel::GetMidiRpnController() {
221 return (p->bMidiRpnReceived) ?
222 (p->uiMidiRpnMsb << 8) | p->uiMidiRpnLsb : -1;
223 }
224
225 uint EngineChannel::GetVoiceCount() {
226 return atomic_read(&p->voiceCount);
227 }
228
229 void EngineChannel::SetVoiceCount(uint Voices) {
230 atomic_set(&p->voiceCount, Voices);
231 }
232
233 uint EngineChannel::GetDiskStreamCount() {
234 return atomic_read(&p->diskStreamCount);
235 }
236
237 void EngineChannel::SetDiskStreamCount(uint Streams) {
238 atomic_set(&p->diskStreamCount, Streams);
239 }
240
241 SamplerChannel* EngineChannel::GetSamplerChannel() {
242 if (p->pSamplerChannel == NULL) {
243 std::cerr << "EngineChannel::GetSamplerChannel(): pSamplerChannel is NULL, this is a bug!\n" << std::flush;
244 }
245 return p->pSamplerChannel;
246 }
247
248 void EngineChannel::SetSamplerChannel(SamplerChannel* pChannel) {
249 p->pSamplerChannel = pChannel;
250 }
251
252 Sampler* EngineChannel::GetSampler() {
253 if (GetSamplerChannel() == NULL) return NULL;
254 return GetSamplerChannel()->GetSampler();
255 }
256
257 void EngineChannel::AddFxSendCountListener(FxSendCountListener* l) {
258 p->llFxSendCountListeners.AddListener(l);
259 }
260
261 void EngineChannel::RemoveFxSendCountListener(FxSendCountListener* l) {
262 p->llFxSendCountListeners.RemoveListener(l);
263 }
264
265 void EngineChannel::RemoveAllFxSendCountListeners() {
266 p->llFxSendCountListeners.RemoveAllListeners();
267 }
268
269 void EngineChannel::fireFxSendCountChanged(int ChannelId, int NewCount) {
270 for (int i = 0; i < p->llFxSendCountListeners.GetListenerCount(); i++) {
271 p->llFxSendCountListeners.GetListener(i)->FxSendCountChanged(ChannelId, NewCount);
272 }
273 }
274
275 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC