1 /*
2 * @(#)Destination.h 3.00 21 August 2000
3 *
4 * Copyright (c) 2000 Pete Goodliffe (pete@cthree.org)
5 *
6 * This file is part of TSE3 - the Trax Sequencer Engine version 3.00.
7 *
8 * This library is modifiable/redistributable under the terms of the GNU
9 * General Public License.
10 *
11 * You should have received a copy of the GNU General Public License along
12 * with this program; see the file COPYING. If not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
14 *
15 */
16
17 #include "tse3/ins/Destination.h"
18
19 #include "tse3/ins/Instrument.h"
20 #include "tse3/Midi.h"
21
22 #include <vector>
23 #include <algorithm>
24 #include <map>
25
26 using namespace TSE3::Ins;
27
28 /******************************************************************************
29 * DestinationImpl class
30 *****************************************************************************/
31
32 namespace
33 {
34 struct DestinationInfo
35 {
DestinationInfo__anonb921deb50111::DestinationInfo36 DestinationInfo() : allChannels(false)
37 {
38 for (int n = 0; n < 16; ++n) instruments[n] = 0;
39 }
40 bool allChannels;
41 Instrument *instruments[16];
42 };
43 }
44
45 class TSE3::Ins::DestinationImpl
46 {
47 public:
48
49 Instrument *defaultInstrument;
50 std::vector<Instrument *> ilist;
51
52 typedef std::map<int, DestinationInfo> dmap_type;
53 dmap_type dmap;
54 };
55
56
57 /******************************************************************************
58 * Destination class
59 *****************************************************************************/
60
Destination()61 Destination::Destination()
62 : pimpl(new DestinationImpl)
63 {
64 pimpl->defaultInstrument = 0;
65 }
66
67
~Destination()68 Destination::~Destination()
69 {
70 delete pimpl;
71 }
72
73
defaultInstrument() const74 Instrument *Destination::defaultInstrument() const
75 {
76 return pimpl->defaultInstrument;
77 }
78
79
setDefaultInstrument(Instrument * instrument)80 void Destination::setDefaultInstrument(Instrument *instrument)
81 {
82 pimpl->defaultInstrument = instrument;
83 }
84
85
allChannels(int port)86 bool Destination::allChannels(int port)
87 {
88 DestinationImpl::dmap_type::iterator i = pimpl->dmap.find(port);
89 if (i != pimpl->dmap.end())
90 {
91 return i->second.allChannels;
92 }
93 else
94 {
95 return true;
96 }
97 }
98
99
port(int port)100 Instrument *Destination::port(int port)
101 {
102 DestinationImpl::dmap_type::iterator i = pimpl->dmap.find(port);
103 if (i != pimpl->dmap.end())
104 {
105 Instrument *instrument = i->second.allChannels
106 ? i->second.instruments[0]
107 : 0;
108 return instrument ? instrument : pimpl->defaultInstrument;
109 }
110 else
111 {
112 return pimpl->defaultInstrument;
113 }
114 }
115
116
setPort(int port,Instrument * instrument)117 void Destination::setPort(int port, Instrument *instrument)
118 {
119 if (instrument)
120 {
121 pimpl->dmap[port].allChannels = true;
122 pimpl->dmap[port].instruments[0] = instrument;
123 }
124 else
125 {
126 pimpl->dmap.erase(port);
127 }
128 notify(&DestinationListener::Destination_Altered,
129 TSE3::MidiCommand::AllChannels, port, instrument);
130 }
131
132
channel(int channel,int port)133 Instrument *Destination::channel(int channel, int port)
134 {
135 DestinationImpl::dmap_type::iterator i = pimpl->dmap.find(port);
136 if (i != pimpl->dmap.end() && channel >= 0 && channel < 16)
137 {
138 if (i->second.allChannels) channel = 0;
139 Instrument *instrument = i->second.instruments[channel];
140 return instrument ? instrument : pimpl->defaultInstrument;
141 }
142 else
143 {
144 return pimpl->defaultInstrument;
145 }
146 }
147
148
setChannel(int channel,int port,Instrument * instrument)149 void Destination::setChannel(int channel, int port,
150 Instrument *instrument)
151 {
152 if (channel < 0 || channel >= 16) return;
153
154 DestinationImpl::dmap_type::iterator i = pimpl->dmap.find(port);
155 if (i != pimpl->dmap.end())
156 {
157 if (i->second.allChannels)
158 {
159 for (int n = 1; n < 16; n++)
160 {
161 i->second.instruments[n] = i->second.instruments[0];
162 if (n != channel)
163 {
164 notify(&DestinationListener::Destination_Altered, n, port,
165 i->second.instruments[0]);
166 }
167 }
168 }
169 }
170 pimpl->dmap[port].allChannels = false;
171 pimpl->dmap[port].instruments[channel] = instrument;
172
173 notify(&DestinationListener::Destination_Altered, channel, port,
174 instrument);
175 }
176
177
178 /******************************************************************************
179 * Destination class: managing the ilist
180 *****************************************************************************/
181
numInstruments() const182 size_t Destination::numInstruments() const
183 {
184 return pimpl->ilist.size();
185 }
186
187
instrument(size_t index)188 Instrument *Destination::instrument(size_t index)
189 {
190 if (index < pimpl->ilist.size())
191 {
192 return pimpl->ilist[index];
193 }
194 else
195 {
196 return 0;
197 }
198 }
199
200
instrument(const std::string & title)201 Instrument *Destination::instrument(const std::string &title)
202 {
203 std::vector<Instrument*>::iterator i = pimpl->ilist.begin();
204 while (i != pimpl->ilist.end() && (*i)->title() != title)
205 {
206 ++i;
207 }
208 return (i == pimpl->ilist.end()) ? 0 : *i;
209 }
210
211
addInstrument(Instrument * instrument)212 void Destination::addInstrument(Instrument *instrument)
213 {
214 std::vector<Instrument*>::iterator i = pimpl->ilist.begin();
215 while (i != pimpl->ilist.end() && (*i)->title() < instrument->title())
216 {
217 ++i;
218 }
219
220 if (i == pimpl->ilist.end() || instrument->title() != (*i)->title())
221 {
222 pimpl->ilist.insert(i, instrument);
223 notify(&DestinationListener::Destination_InstrumentAdded, instrument);
224 };
225 }
226
227
removeInstrument(Instrument * instrument)228 void Destination::removeInstrument(Instrument *instrument)
229 {
230 // Check its in the managed list
231 std::vector<Instrument*>::iterator i
232 = find(pimpl->ilist.begin(), pimpl->ilist.end(), instrument);
233 if (i == pimpl->ilist.end()) return;
234
235 // Check every destination
236 DestinationImpl::dmap_type::iterator di = pimpl->dmap.begin();
237 while (di != pimpl->dmap.end())
238 {
239 int maxc = (di->second.allChannels) ? 1 : 16;
240 for (int channel = 0; channel < maxc; channel++)
241 {
242 if (di->second.instruments[channel] == instrument)
243 {
244 di->second.instruments[channel] = 0;
245 notify(&DestinationListener::Destination_Altered,
246 channel, di->first, (Instrument*)0);
247 }
248 }
249 ++di;
250 }
251 if (pimpl->defaultInstrument == instrument)
252 {
253 pimpl->defaultInstrument = 0;
254 }
255
256 pimpl->ilist.erase(i);
257 notify(&DestinationListener::Destination_InstrumentRemoved, instrument);
258 }
259
260