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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1879 - (hide 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 schoenebeck 888 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 1879 * Copyright (C) 2005 - 2009 Christian Schoenebeck *
7 schoenebeck 888 * *
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 schoenebeck 973 #include <algorithm>
27    
28 iliev 1761 #include "../Sampler.h"
29 schoenebeck 1424 #include "../common/global_private.h"
30 schoenebeck 973 #include "../drivers/midi/MidiInstrumentMapper.h"
31 schoenebeck 1879 #include "../common/atomic.h"
32 schoenebeck 973
33     #define NO_MIDI_INSTRUMENT_MAP -1
34     #define DEFAULT_MIDI_INSTRUMENT_MAP -2
35    
36 schoenebeck 888 namespace LinuxSampler {
37    
38 schoenebeck 1879 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 iliev 1789 SetVoiceCount(0);
70     SetDiskStreamCount(0);
71 schoenebeck 1879 PTHIS->pSamplerChannel = NULL;
72 schoenebeck 1044 ResetMidiRpnController();
73 schoenebeck 888 }
74    
75 schoenebeck 1879 EngineChannel::~EngineChannel() {
76     if (PTHIS) delete PTHIS;
77     }
78    
79 schoenebeck 888 void EngineChannel::SetMute(int state) throw (Exception) {
80 schoenebeck 1879 if (PTHIS->iMute == state) return;
81     if (state < -1 || state > 1)
82 schoenebeck 888 throw Exception("Invalid Mute state: " + ToString(state));
83    
84 schoenebeck 1879 PTHIS->iMute = state;
85 schoenebeck 888
86     StatusChanged(true);
87     }
88    
89     int EngineChannel::GetMute() {
90 schoenebeck 1879 return PTHIS->iMute;
91 schoenebeck 888 }
92    
93     void EngineChannel::SetSolo(bool solo) {
94 schoenebeck 1879 if (PTHIS->bSolo == solo) return;
95     PTHIS->bSolo = solo;
96 schoenebeck 888 StatusChanged(true);
97     }
98    
99     bool EngineChannel::GetSolo() {
100 schoenebeck 1879 return PTHIS->bSolo;
101 schoenebeck 888 }
102    
103 schoenebeck 973 /*
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 schoenebeck 947 uint8_t EngineChannel::GetMidiProgram() {
122 schoenebeck 1879 return PTHIS->uiMidiProgram; // AFAIK atomic on all systems
123 schoenebeck 947 }
124    
125     void EngineChannel::SetMidiProgram(uint8_t Program) {
126 schoenebeck 1879 PTHIS->bProgramChangeReceived = true;
127     PTHIS->uiMidiProgram = Program; // AFAIK atomic on all systems
128 schoenebeck 947 }
129    
130     uint8_t EngineChannel::GetMidiBankMsb() {
131 schoenebeck 1879 return (PTHIS->bMidiBankMsbReceived && PTHIS->bMidiBankLsbReceived)
132     ? PTHIS->uiMidiBankMsb : 0;
133 schoenebeck 947 }
134    
135     void EngineChannel::SetMidiBankMsb(uint8_t BankMSB) {
136 schoenebeck 1879 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 schoenebeck 947 }
143    
144     uint8_t EngineChannel::GetMidiBankLsb() {
145 schoenebeck 1879 return (!PTHIS->bMidiBankMsbReceived && !PTHIS->bMidiBankLsbReceived)
146 schoenebeck 973 ? 0
147 schoenebeck 1879 : (PTHIS->bMidiBankMsbReceived && !PTHIS->bMidiBankLsbReceived)
148     ? PTHIS->uiMidiBankMsb
149     : PTHIS->uiMidiBankLsb;
150 schoenebeck 947 }
151    
152     void EngineChannel::SetMidiBankLsb(uint8_t BankLSB) {
153 schoenebeck 1879 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 schoenebeck 947 }
160    
161 schoenebeck 973 bool EngineChannel::UsesNoMidiInstrumentMap() {
162 schoenebeck 1879 return (PTHIS->iMidiInstrumentMap == NO_MIDI_INSTRUMENT_MAP);
163 schoenebeck 973 }
164    
165     bool EngineChannel::UsesDefaultMidiInstrumentMap() {
166 schoenebeck 1879 return (PTHIS->iMidiInstrumentMap == DEFAULT_MIDI_INSTRUMENT_MAP);
167 schoenebeck 973 }
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 schoenebeck 1879 if (find(maps.begin(), maps.end(), PTHIS->iMidiInstrumentMap) == maps.end()) {
177 schoenebeck 973 // it doesn't exist anymore, so fall back to NONE and throw an exception
178 schoenebeck 1879 PTHIS->iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;
179 schoenebeck 973 throw Exception("Assigned MIDI instrument map doesn't exist anymore, falling back to NONE");
180     }
181 schoenebeck 1879 return PTHIS->iMidiInstrumentMap;
182 schoenebeck 973 }
183    
184     void EngineChannel::SetMidiInstrumentMapToNone() {
185 schoenebeck 1879 if (PTHIS->iMidiInstrumentMap == NO_MIDI_INSTRUMENT_MAP) return;
186     PTHIS->iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;
187 iliev 1254 StatusChanged(true);
188 schoenebeck 973 }
189    
190     void EngineChannel::SetMidiInstrumentMapToDefault() {
191 schoenebeck 1879 if (PTHIS->iMidiInstrumentMap == DEFAULT_MIDI_INSTRUMENT_MAP) return;
192     PTHIS->iMidiInstrumentMap = DEFAULT_MIDI_INSTRUMENT_MAP;
193 iliev 1254 StatusChanged(true);
194 schoenebeck 973 }
195    
196     void EngineChannel::SetMidiInstrumentMap(int MidiMap) throw (Exception) {
197 schoenebeck 1879 if (PTHIS->iMidiInstrumentMap == MidiMap) return;
198 iliev 1254
199 schoenebeck 973 // 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 schoenebeck 1879 PTHIS->iMidiInstrumentMap = MidiMap; // assign the new map ID
204 iliev 1254 StatusChanged(true);
205 schoenebeck 973 }
206    
207 schoenebeck 1041 void EngineChannel::SetMidiRpnControllerMsb(uint8_t CtrlMSB) {
208 schoenebeck 1879 PTHIS->uiMidiRpnMsb = CtrlMSB;
209     PTHIS->bMidiRpnReceived = true;
210 schoenebeck 1041 }
211    
212     void EngineChannel::SetMidiRpnControllerLsb(uint8_t CtrlLSB) {
213 schoenebeck 1879 PTHIS->uiMidiRpnLsb = CtrlLSB;
214     PTHIS->bMidiRpnReceived = true;
215 schoenebeck 1041 }
216    
217 schoenebeck 1044 void EngineChannel::ResetMidiRpnController() {
218 schoenebeck 1879 PTHIS->uiMidiRpnMsb = PTHIS->uiMidiRpnLsb = 0;
219     PTHIS->bMidiRpnReceived = false;
220 schoenebeck 1044 }
221    
222 schoenebeck 1041 int EngineChannel::GetMidiRpnController() {
223 schoenebeck 1879 return (PTHIS->bMidiRpnReceived) ?
224     (PTHIS->uiMidiRpnMsb << 8) | PTHIS->uiMidiRpnLsb : -1;
225 schoenebeck 1041 }
226    
227 iliev 1297 uint EngineChannel::GetVoiceCount() {
228 schoenebeck 1879 return atomic_read(&PTHIS->voiceCount);
229 iliev 1297 }
230 schoenebeck 1879
231 iliev 1297 void EngineChannel::SetVoiceCount(uint Voices) {
232 schoenebeck 1879 atomic_set(&PTHIS->voiceCount, Voices);
233 iliev 1297 }
234    
235     uint EngineChannel::GetDiskStreamCount() {
236 schoenebeck 1879 return atomic_read(&PTHIS->diskStreamCount);
237 iliev 1297 }
238 schoenebeck 1879
239 iliev 1297 void EngineChannel::SetDiskStreamCount(uint Streams) {
240 schoenebeck 1879 atomic_set(&PTHIS->diskStreamCount, Streams);
241 iliev 1297 }
242 schoenebeck 1879
243 iliev 1761 SamplerChannel* EngineChannel::GetSamplerChannel() {
244 schoenebeck 1879 if (PTHIS->pSamplerChannel == NULL) {
245 iliev 1761 std::cerr << "EngineChannel::GetSamplerChannel(): pSamplerChannel is NULL, this is a bug!\n" << std::flush;
246     }
247 schoenebeck 1879 return PTHIS->pSamplerChannel;
248 iliev 1761 }
249 iliev 1297
250 iliev 1761 void EngineChannel::SetSamplerChannel(SamplerChannel* pChannel) {
251 schoenebeck 1879 PTHIS->pSamplerChannel = pChannel;
252 iliev 1761 }
253    
254     Sampler* EngineChannel::GetSampler() {
255     if (GetSamplerChannel() == NULL) return NULL;
256     return GetSamplerChannel()->GetSampler();
257     }
258    
259 iliev 1130 void EngineChannel::AddFxSendCountListener(FxSendCountListener* l) {
260 schoenebeck 1879 PTHIS->llFxSendCountListeners.AddListener(l);
261 iliev 1130 }
262    
263     void EngineChannel::RemoveFxSendCountListener(FxSendCountListener* l) {
264 schoenebeck 1879 PTHIS->llFxSendCountListeners.RemoveListener(l);
265 iliev 1130 }
266    
267     void EngineChannel::RemoveAllFxSendCountListeners() {
268 schoenebeck 1879 PTHIS->llFxSendCountListeners.RemoveAllListeners();
269 iliev 1130 }
270    
271     void EngineChannel::fireFxSendCountChanged(int ChannelId, int NewCount) {
272 schoenebeck 1879 for (int i = 0; i < PTHIS->llFxSendCountListeners.GetListenerCount(); i++) {
273     PTHIS->llFxSendCountListeners.GetListener(i)->FxSendCountChanged(ChannelId, NewCount);
274 iliev 1130 }
275     }
276    
277 schoenebeck 888 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC