/[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 1879 - (show annotations) (download)
Sun Mar 29 18:43:40 2009 UTC (15 years ago) by schoenebeck
File size: 10856 byte(s)
* atomic.h was accidently included in the liblinuxsampler C++ API header
  files (fixes bug #122)

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

  ViewVC Help
Powered by ViewVC