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

  ViewVC Help
Powered by ViewVC