/[svn]/jsampler/trunk/src/org/jsampler/MidiInstrumentMap.java
ViewVC logotype

Contents of /jsampler/trunk/src/org/jsampler/MidiInstrumentMap.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1755 - (show annotations) (download)
Tue Aug 12 16:31:35 2008 UTC (15 years, 8 months ago) by iliev
File size: 10307 byte(s)
* Reimplemented the MIDI bank/program assignment algorithm

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>
5 *
6 * This file is part of JSampler.
7 *
8 * JSampler is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * JSampler is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with JSampler; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22
23 package org.jsampler;
24
25 import java.util.TreeMap;
26 import java.util.Vector;
27
28 import javax.swing.SwingUtilities;
29
30 import org.jsampler.event.MidiInstrumentMapEvent;
31 import org.jsampler.event.MidiInstrumentMapListener;
32
33 import org.linuxsampler.lscp.MidiInstrumentEntry;
34 import org.linuxsampler.lscp.MidiInstrumentMapInfo;
35
36
37 /**
38 * Represents a MIDI instrument map used for mapping instruments
39 * to corresponding MIDI bank select and MIDI program change messages.
40 * @author Grigor Iliev
41 */
42 public class MidiInstrumentMap {
43 MidiInstrumentMapInfo info;
44
45 private final TreeMap<MidiInstrumentEntry, MidiInstrument> instrMap =
46 new TreeMap<MidiInstrumentEntry, MidiInstrument>();
47
48 private final Vector<MidiInstrumentMapListener> listeners =
49 new Vector<MidiInstrumentMapListener>();
50
51
52 /**
53 * Creates a new instance of <code>MidiInstrumentMap</code>.
54 * @param info Provides the map's properties.
55 */
56 public
57 MidiInstrumentMap(MidiInstrumentMapInfo info) { this.info = info; }
58
59 /**
60 * Registers the specified listener for receiving event messages.
61 * @param l The <code>MidiInstrumentMapListener</code> to register.
62 */
63 public void
64 addMidiInstrumentMapListener(MidiInstrumentMapListener l) { listeners.add(l); }
65
66 /**
67 * Removes the specified listener.
68 * @param l The <code>MidiInstrumentMapListener</code> to remove.
69 */
70 public void
71 removeMidiInstrumentMapListener(MidiInstrumentMapListener l) { listeners.remove(l); }
72
73 /*
74 * Creates a new instance of MidiInstrumentMap.
75 * @param mapId The ID of this MIDI instrument map.
76 * @param name The name of this MIDI instrument map.
77 *
78 public
79 MidiInstrumentMap(int mapId, String name) {
80 this.mapId = mapId;
81 setName(name);
82 }*/
83
84 /** Gets the ID of this MIDI instrument map. */
85 public int
86 getMapId() { return info.getMapId(); }
87
88 /**
89 * Gets the name of this MIDI instrument map.
90 * @return The name of this MIDI instrument map.
91 */
92 public String
93 getName() { return info.getName(); }
94
95 /**
96 * Sets the name of this MIDI instrument map.
97 * @param name The new name of this MIDI instrument map.
98 */
99 public void
100 setName(String name) {
101 if(info.getName().equals(name)) return;
102 info.setName(name);
103 fireNameChanged();
104 }
105
106 /**
107 * Gets the information about this MIDI instrument map.
108 * @return The information about this MIDI instrument map.
109 */
110 public MidiInstrumentMapInfo
111 getInfo() { return info; }
112
113 /**
114 * Sets the information about this MIDI instrument map.
115 * @param info The new information about this MIDI instrument map.
116 */
117 public void
118 setInfo(MidiInstrumentMapInfo info) {
119 this.info = info;
120 fireNameChanged();
121 }
122
123 /**
124 * Gets the indices of all MIDI banks that contain at least one instrument.
125 * @return The indices of all MIDI banks that contain at least one instrument.
126 */
127 public Integer[]
128 getMidiBanks() {
129 Vector<Integer> v = new Vector<Integer>();
130
131 for(MidiInstrumentEntry e : instrMap.keySet()) {
132 if(v.isEmpty()) v.add(e.getMidiBank());
133 else {
134 if(e.getMidiBank() < v.lastElement())
135 throw new RuntimeException("Unsorted map!");
136
137 if(e.getMidiBank() > v.lastElement()) v.add(e.getMidiBank());
138 }
139 }
140
141 return v.toArray(new Integer[v.size()]);
142 }
143
144 /**
145 * Gets the instrument in the specified MIDI bank with the specified program number.
146 * @param bank The index of the MIDI bank, containing the requested instrument.
147 * @param program The program number of the requested instrument.
148 * @return The instrument in MIDI bank <code>bank</code> with
149 * program number <code>program</code>, or <code>null</code> if
150 * there is no such instrument in the map.
151 */
152 public MidiInstrument
153 getMidiInstrument(int bank, int program) {
154 return instrMap.get(new MidiInstrumentEntry(bank, program));
155 }
156
157 /**
158 * Gets all instruments contained in the specified MIDI bank.
159 * @param bankIndex The index of the MIDI bank, whose instruments should be obtained.
160 * @return All instruments contained in the specified MIDI bank.
161 */
162 public MidiInstrument[]
163 getMidiInstruments(int bankIndex) {
164 Vector<MidiInstrument> v = new Vector<MidiInstrument>();
165
166 for(MidiInstrumentEntry e : instrMap.keySet()) {
167 if(e.getMidiBank() == bankIndex) v.add(instrMap.get(e));
168 }
169
170 return v.toArray(new MidiInstrument[v.size()]);
171 }
172
173 /**
174 * Gets all instruments contained in this MIDI instrument map.
175 * @return All instruments contained in this MIDI instrument map.
176 */
177 public MidiInstrument[]
178 getAllMidiInstruments() {
179 Vector<MidiInstrument> v = new Vector<MidiInstrument>();
180
181 for(MidiInstrument i : instrMap.values()) v.add(i);
182
183 return v.toArray(new MidiInstrument[v.size()]);
184 }
185
186 /**
187 * Creates a new or replaces an existing entry in this MIDI instrument map.
188 */
189 public void
190 mapMidiInstrument(MidiInstrumentEntry entry, MidiInstrument instrument) {
191 MidiInstrument mi = instrMap.remove(entry);
192 if(mi != null) fireInstrumentRemoved(entry, mi);
193 instrMap.put(entry, instrument);
194 fireInstrumentAdded(entry, instrument);
195 }
196
197 /**
198 * Removes an entry from this MIDI instrument map.
199 * @param entry The entry to remove.
200 * @return The MIDI instrument associated with the specified entry or
201 * <code>null</code> if there was no mapping for that entry.
202 */
203 public MidiInstrument
204 unmapMidiInstrument(MidiInstrumentEntry entry) {
205 MidiInstrument mi = instrMap.remove(entry);
206 if(mi != null) fireInstrumentRemoved(entry, mi);
207 return mi;
208 }
209
210 /**
211 * Gets a free entry.
212 */
213 public MidiInstrumentEntry
214 getAvailableEntry() {
215 int lb = CC.getViewConfig().preferences().getIntProperty("lastUsedMidiBank", 0);
216 int lp = CC.getViewConfig().preferences().getIntProperty("lastUsedMidiProgram", 0);
217
218 MidiInstrumentEntry e = getAvailableEntry(lb, lp + 1);
219 if(e != null) return e;
220
221 for(int i = lb; i <= 16129; i++) {
222 e = getAvailableEntry(i);
223 if(e != null) return e;
224 }
225
226 for(int i = 0; i < lb; i++) {
227 e = getAvailableEntry(i);
228 if(e != null) return e;
229 }
230
231 return null;
232 }
233
234 /**
235 * Gets a free entry.
236 * @param bank The bank number in which to search for available entry.
237 */
238 public MidiInstrumentEntry
239 getAvailableEntry(int bank) { return getAvailableEntry(bank, 0); }
240
241 /**
242 * Gets a free entry.
243 * @param bank The bank number in which to search for available entry.
244 * @param fromProgram the program number to start the search from.
245 */
246 public MidiInstrumentEntry
247 getAvailableEntry(int bank, int fromProgram) {
248 if(fromProgram > 127) return null;
249
250 Vector<MidiInstrument> instruments = new Vector<MidiInstrument>();
251
252 for(MidiInstrument instr : instrMap.values()) {
253 int p = instr.getInfo().getMidiProgram();
254 int b = instr.getInfo().getMidiBank();
255 if(b == bank && p >= fromProgram) instruments.add(instr);
256 if(b > bank) break;
257 }
258
259 if(instruments.isEmpty()) {
260 if(fromProgram < 128) return new MidiInstrumentEntry(bank, fromProgram);
261 else return new MidiInstrumentEntry(bank, 127);
262 }
263
264 int prevPrg = instruments.get(0).getInfo().getMidiProgram();
265 if(fromProgram < prevPrg) return new MidiInstrumentEntry(bank, fromProgram);
266
267 for(int i = 1; i < instruments.size(); i++) {
268 int prg = instruments.get(i).getInfo().getMidiProgram();
269 if(prg - prevPrg > 1) return new MidiInstrumentEntry(bank, prevPrg + 1);
270 prevPrg = prg;
271 }
272
273 if(prevPrg < 127) return new MidiInstrumentEntry(bank, prevPrg + 1);
274
275 return null;
276 }
277
278 /**
279 * Returns the name of this map.
280 * @return The name of this map.
281 */
282 public String
283 toString() { return getName(); }
284
285 /**
286 * Notifies listeners that the name of the MIDI instrument map has changed.
287 * Note that this method can be invoked outside the event-dispatching thread.
288 */
289 private void
290 fireNameChanged() {
291 final MidiInstrumentMapEvent e = new MidiInstrumentMapEvent(this);
292
293 SwingUtilities.invokeLater(new Runnable() {
294 public void
295 run() { fireNameChanged(e); }
296 });
297 }
298
299 /** Notifies listeners that the name of the MIDI instrument map has changed. */
300 private void
301 fireNameChanged(MidiInstrumentMapEvent e) {
302 for(MidiInstrumentMapListener l : listeners) l.nameChanged(e);
303 }
304
305 /**
306 * Notifies listeners that a MIDI instrument has been
307 * added to this MIDI instrument map.
308 * Note that this method can be invoked outside the event-dispatching thread
309 */
310 private void
311 fireInstrumentAdded(MidiInstrumentEntry entry, MidiInstrument instrument) {
312 final MidiInstrumentMapEvent e =
313 new MidiInstrumentMapEvent(this, entry, instrument);
314
315 SwingUtilities.invokeLater(new Runnable() {
316 public void
317 run() { fireInstrumentAdded(e); }
318 });
319 }
320
321 /**
322 * Notifies listeners that a MIDI instrument has been
323 * added to this MIDI instrument map.
324 */
325 private void
326 fireInstrumentAdded(MidiInstrumentMapEvent e) {
327 for(MidiInstrumentMapListener l : listeners) l.instrumentAdded(e);
328 }
329
330 /**
331 * Notifies listeners that a MIDI instrument has been
332 * removed from this MIDI instrument map.
333 */
334 private void
335 fireInstrumentRemoved(MidiInstrumentEntry entry, MidiInstrument instrument) {
336 final MidiInstrumentMapEvent e =
337 new MidiInstrumentMapEvent(this, entry, instrument);
338
339 SwingUtilities.invokeLater(new Runnable() {
340 public void
341 run() { fireInstrumentRemoved(e); }
342 });
343 }
344
345 /**
346 * Notifies listeners that a MIDI instrument has been
347 * removed from this MIDI instrument map.
348 */
349 private void
350 fireInstrumentRemoved(MidiInstrumentMapEvent e) {
351 for(MidiInstrumentMapListener l : listeners) l.instrumentRemoved(e);
352 }
353 }

  ViewVC Help
Powered by ViewVC