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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2195 - (show annotations) (download)
Tue Jun 28 22:44:39 2011 UTC (12 years, 10 months ago) by iliev
File size: 40604 byte(s)
* Sampler Browser (work in progress): initial implementation of main pane

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2011 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.Vector;
26
27 import java.util.logging.Level;
28
29 import javax.swing.SwingUtilities;
30
31 import javax.swing.event.EventListenerList;
32
33 import net.sf.juife.Task;
34 import net.sf.juife.event.TaskEvent;
35 import net.sf.juife.event.TaskListener;
36
37 import org.jsampler.event.ListEvent;
38 import org.jsampler.event.ListListener;
39 import org.jsampler.event.MidiDeviceListEvent;
40 import org.jsampler.event.MidiDeviceListListener;
41 import org.jsampler.event.SamplerChannelListEvent;
42 import org.jsampler.event.SamplerChannelListListener;
43 import org.jsampler.event.SamplerEvent;
44 import org.jsampler.event.SamplerListener;
45
46 import org.jsampler.task.Audio;
47 import org.jsampler.task.Channel;
48 import org.jsampler.task.Global;
49 import org.jsampler.task.Midi;
50
51 import org.linuxsampler.lscp.*;
52
53
54 /**
55 * This class provides default implementation of the <code>SamplerModel</code> interface.
56 * Note that the setter methods of this class does <b>not</b> alter any settings
57 * on the backend side unless otherwise specified.
58 * @author Grigor Iliev
59 */
60 public class DefaultSamplerModel implements SamplerModel {
61 private ServerInfo serverInfo = null;
62 private AudioOutputDriver[] aoDrvS = null;
63 private MidiInputDriver[] miDrvS = null;
64 private SamplerEngine[] engines = null;
65
66 private int totalStreamCount = 0;
67 private int totalVoiceCount = 0;
68 private int totalVoiceCountMax = 0;
69
70 private float volume = 1;
71 private MidiInstrumentMap defaultMidiInstrumentMap;
72
73 private final Vector<SamplerChannelModel> channelModels = new Vector<SamplerChannelModel>();
74 private final Vector<AudioDeviceModel> audioDeviceModels = new Vector<AudioDeviceModel>();
75 private final Vector<MidiDeviceModel> midiDeviceModels = new Vector<MidiDeviceModel>();
76 private final Vector<MidiInstrumentMap> midiInstrMaps = new Vector<MidiInstrumentMap>();
77
78 private final EffectList effects = new EffectList();
79
80 private final Vector<SamplerListener> listeners = new Vector<SamplerListener>();
81 private final Vector<ListListener<MidiInstrumentMap>> mapsListeners =
82 new Vector<ListListener<MidiInstrumentMap>>();
83
84 private final EventListenerList listenerList = new EventListenerList();
85
86 private boolean channelListIsAdjusting = false;
87
88 private boolean modified = false;
89
90
91 /** Creates a new instance of DefaultSamplerModel */
92 public
93 DefaultSamplerModel() {
94 addMidiInstrumentMapListListener(getHandler());
95 }
96
97 /**
98 * Registers the specified listener for receiving event messages.
99 * @param l The <code>SamplerListener</code> to register.
100 */
101 @Override
102 public void
103 addSamplerListener(SamplerListener l) { listeners.add(l); }
104
105 /**
106 * Removes the specified listener.
107 * @param l The <code>SamplerListener</code> to remove.
108 */
109 @Override
110 public void
111 removeSamplerListener(SamplerListener l) { listeners.remove(l); }
112
113 /**
114 * Registers the specified listener for receiving event messages.
115 * @param listener The <code>AudioDeviceListListener</code> to register.
116 */
117 @Override
118 public void
119 addAudioDeviceListListener(ListListener<AudioDeviceModel> listener) {
120 listenerList.add(ListListener.class, listener);
121 }
122
123 /**
124 * Removes the specified listener.
125 * @param listener The <code>AudioDeviceListListener</code> to remove.
126 */
127 @Override
128 public void
129 removeAudioDeviceListListener(ListListener<AudioDeviceModel> listener) {
130 listenerList.remove(ListListener.class, listener);
131 }
132
133 /**
134 * Registers the specified listener for receiving event messages.
135 * @param listener The <code>MidiDeviceListListener</code> to register.
136 */
137 @Override
138 public void
139 addMidiDeviceListListener(MidiDeviceListListener listener) {
140 listenerList.add(MidiDeviceListListener.class, listener);
141 }
142
143 /**
144 * Removes the specified listener.
145 * @param listener The <code>MidiDeviceListListener</code> to remove.
146 */
147 @Override
148 public void
149 removeMidiDeviceListListener(MidiDeviceListListener listener) {
150 listenerList.remove(MidiDeviceListListener.class, listener);
151 }
152
153 /**
154 * Registers the specified listener for receiving event messages.
155 * @param listener The <code>ListListener</code> to register.
156 */
157 @Override
158 public void
159 addMidiInstrumentMapListListener(ListListener<MidiInstrumentMap> listener) {
160 mapsListeners.add(listener);
161 }
162
163 /**
164 * Removes the specified listener.
165 * @param listener The <code>ListListener</code> to remove.
166 */
167 @Override
168 public void
169 removeMidiInstrumentMapListListener(ListListener<MidiInstrumentMap> listener) {
170 mapsListeners.remove(listener);
171 }
172
173 /**
174 * Registers the specified listener for receiving event messages.
175 * @param listener The <code>SamplerChannelListListener</code> to register.
176 */
177 @Override
178 public void
179 addSamplerChannelListListener(SamplerChannelListListener listener) {
180 listenerList.add(SamplerChannelListListener.class, listener);
181 }
182
183 /**
184 * Removes the specified listener.
185 * @param listener The <code>SamplerChannelListListener</code> to remove.
186 */
187 @Override
188 public void
189 removeSamplerChannelListListener(SamplerChannelListListener listener) {
190 listenerList.remove(SamplerChannelListListener.class, listener);
191 }
192
193 /**
194 * Gets information about the LinuxSampler instance the front-end is connected to.
195 *
196 * @return <code>ServerInfo</code> instance containing
197 * information about the LinuxSampler instance the front-end is connected to.
198 */
199 @Override
200 public ServerInfo
201 getServerInfo() { return serverInfo; }
202
203 /**
204 * Sets information about the LinuxSampler instance the front-end is connected to.
205 *
206 * @param serverInfo <code>ServerInfo</code> instance containing
207 * information about the LinuxSampler instance the front-end is connected to.
208 */
209 public void
210 setServerInfo(ServerInfo serverInfo) { this.serverInfo = serverInfo; }
211
212 /**
213 * Gets all audio output drivers currently available for the LinuxSampler instance.
214 *
215 * @return <code>AudioOutputDriver</code> array containing all audio output drivers
216 * currently available for the LinuxSampler instance.
217 */
218 @Override
219 public AudioOutputDriver[]
220 getAudioOutputDrivers() { return aoDrvS; }
221
222 /**
223 * Sets the currently available audio output drivers for the LinuxSampler instance.
224 *
225 * @param drivers <code>AudioOutputDriver</code> array containing all audio output drivers
226 * currently available for the LinuxSampler instance.
227 */
228 public void
229 setAudioOutputDrivers(AudioOutputDriver[] drivers) { aoDrvS = drivers; }
230
231 /**
232 * Gets the model of the audio device at the specified position.
233 * @param index The position of the audio device to return.
234 * @return The model of the audio device at the specified position.
235 * @see #getAudioDeviceCount
236 */
237 @Override
238 public AudioDeviceModel
239 getAudioDevice(int index) {
240 return audioDeviceModels.get(index);
241 }
242
243 /**
244 * Gets the model of the audio device with ID <code>deviceId</code>.
245 * @param deviceId The ID of the audio device whose model should be obtained.
246 * @return The model of the specified audio device or <code>null</code>
247 * if there is no audio device with ID <code>deviceId</code>.
248 */
249 @Override
250 public AudioDeviceModel
251 getAudioDeviceById(int deviceId) {
252 for(AudioDeviceModel m : audioDeviceModels)
253 if(m.getDeviceId() == deviceId) return m;
254
255 return null;
256 }
257
258 /**
259 * Gets the current number of audio devices.
260 * @return The current number of audio devices.
261 */
262 @Override
263 public int
264 getAudioDeviceCount() { return audioDeviceModels.size(); }
265
266 /**
267 * Gets the current list of audio device models.
268 * @return The current list of audio device models.
269 */
270 @Override
271 public AudioDeviceModel[]
272 getAudioDevices() {
273 return audioDeviceModels.toArray(new AudioDeviceModel[audioDeviceModels.size()]);
274 }
275
276 /**
277 * Adds the specified audio device.
278 * @param device The audio device to be added.
279 */
280 @Override
281 public void
282 addAudioDevice(AudioOutputDevice device) {
283 DefaultAudioDeviceModel model = new DefaultAudioDeviceModel(device);
284 audioDeviceModels.add(model);
285 fireAudioDeviceAdded(model);
286 }
287
288 /**
289 * Removes the specified audio device.
290 * @param deviceId The ID of the audio device to be removed.
291 * @return <code>true</code> if the audio device is removed successfully, <code>false</code>
292 * if the device list does not contain audio device with ID <code>deviceId</code>.
293 */
294 @Override
295 public boolean
296 removeAudioDeviceById(int deviceId) {
297 for(int i = 0; i < audioDeviceModels.size(); i++) {
298 AudioDeviceModel m = audioDeviceModels.get(i);
299 if(m.getDeviceId() == deviceId) {
300 audioDeviceModels.remove(i);
301 fireAudioDeviceRemoved(m);
302 return true;
303 }
304 }
305
306 return false;
307 }
308
309 /**
310 * Schedules a new task for removing the specified audio device on the backend side.
311 * @param deviceId The ID of the audio device to be removed.
312 */
313 @Override
314 public void
315 removeBackendAudioDevice(int deviceId) {
316 CC.getTaskQueue().add(new Audio.DestroyDevice(deviceId));
317 }
318
319 /**
320 * Gets all MIDI input drivers currently available for the LinuxSampler instance.
321 *
322 * @return <code>MidiInputDriver</code> array containing all MIDI input drivers currently
323 * available for the LinuxSampler instance.
324 */
325 @Override
326 public MidiInputDriver[]
327 getMidiInputDrivers() { return miDrvS; }
328
329 /**
330 * Sets the currently available MIDI input drivers for the LinuxSampler instance.
331 *
332 * @param drivers <code>MidiInputDriver</code> array containing all MIDI input drivers
333 * currently available for the LinuxSampler instance.
334 */
335 public void
336 setMidiInputDrivers(MidiInputDriver[] drivers) { miDrvS = drivers; }
337
338 /**
339 * Gets the model of the MIDI device at the specified position.
340 * @param index The position of the MIDI device to return.
341 * @return The model of the MIDI device at the specified position.
342 */
343 @Override
344 public MidiDeviceModel
345 getMidiDevice(int index) {
346 return midiDeviceModels.get(index);
347 }
348
349 /**
350 * Gets the model of the MIDI device with ID <code>deviceId</code>.
351 * @param deviceId The ID of the MIDI device whose model should be obtained.
352 * @return The model of the specified MIDI device or <code>null</code>
353 * if there is no MIDI device with ID <code>deviceId</code>.
354 */
355 @Override
356 public MidiDeviceModel
357 getMidiDeviceById(int deviceId) {
358 for(MidiDeviceModel m : midiDeviceModels)
359 if(m.getDeviceId() == deviceId) return m;
360
361 return null;
362 }
363
364 /**
365 * Gets the current number of MIDI input devices.
366 * @return The current number of MIDI input devices.
367 */
368 @Override
369 public int
370 getMidiDeviceCount() { return midiDeviceModels.size(); }
371
372 /**
373 * Gets the current list of MIDI device models.
374 * @return The current list of MIDI device models.
375 */
376 @Override
377 public MidiDeviceModel[]
378 getMidiDevices() {
379 return midiDeviceModels.toArray(new MidiDeviceModel[midiDeviceModels.size()]);
380 }
381
382 /**
383 * Adds the specified MIDI device.
384 * @param device The MIDI device to be added.
385 */
386 @Override
387 public void
388 addMidiDevice(MidiInputDevice device) {
389 DefaultMidiDeviceModel model = new DefaultMidiDeviceModel(device);
390 midiDeviceModels.add(model);
391 fireMidiDeviceAdded(model);
392 }
393
394 /**
395 * Schedules a new task for adding new MIDI device.
396 * @param driver The desired MIDI input system.
397 * @param parameters An optional list of driver specific parameters.
398 */
399 @Override
400 public void
401 addBackendMidiDevice(String driver, Parameter... parameters) {
402 CC.getTaskQueue().add(new Midi.CreateDevice(driver, parameters));
403 }
404
405 /**
406 * Removes the specified MIDI device.
407 * @param deviceId The ID of the MIDI device to be removed.
408 * @return <code>true</code> if the MIDI device is removed successfully, <code>false</code>
409 * if the device list does not contain MIDI device with ID <code>deviceId</code>.
410 */
411 @Override
412 public boolean
413 removeMidiDeviceById(int deviceId) {
414 for(int i = 0; i < midiDeviceModels.size(); i++) {
415 MidiDeviceModel m = midiDeviceModels.get(i);
416 if(m.getDeviceId() == deviceId) {
417 midiDeviceModels.remove(i);
418 fireMidiDeviceRemoved(m);
419 return true;
420 }
421 }
422
423 return false;
424 }
425
426 /**
427 * Schedules a new task for removing the specified MIDI device.
428 * @param deviceId The ID of the MIDI input device to be destroyed.
429 */
430 @Override
431 public void
432 removeBackendMidiDevice(int deviceId) {
433 CC.getTaskQueue().add(new Midi.DestroyDevice(deviceId));
434 }
435
436 /**
437 * Gets the MIDI instrument map with ID <code>mapId</code>.
438 * @param mapId The ID of the MIDI instrument map to obtain.
439 * @return The MIDI instrument map with the specified ID or <code>null</code>
440 * if there is no MIDI instrument map with ID <code>mapId</code>.
441 */
442 @Override
443 public MidiInstrumentMap
444 getMidiInstrumentMapById(int mapId) {
445 for(MidiInstrumentMap m : midiInstrMaps)
446 if(m.getMapId() == mapId) return m;
447
448 return null;
449 }
450
451 /**
452 * Gets the MIDI instrument map at the specified position.
453 * @param index The position of the MIDI instrument map to return.
454 * @return The MIDI instrument map at the specified position.
455 */
456 @Override
457 public MidiInstrumentMap
458 getMidiInstrumentMap(int index) {
459 return midiInstrMaps.get(index);
460 }
461
462 /**
463 * Gets the current number of MIDI instrument maps.
464 * @return The current number of MIDI instrument maps.
465 */
466 @Override
467 public int
468 getMidiInstrumentMapCount() { return midiInstrMaps.size(); }
469
470 /**
471 * Gets the current list of MIDI instrument maps.
472 * @return The current list of MIDI instrument maps.
473 */
474 @Override
475 public MidiInstrumentMap[]
476 getMidiInstrumentMaps() {
477 return midiInstrMaps.toArray(new MidiInstrumentMap[midiInstrMaps.size()]);
478 }
479
480 /**
481 * Gets the position of the specified MIDI instrument map in the list.
482 * @param map The map whose index should be returned.
483 * @return The position of the specified map in the list,
484 * or -1 if <code>map</code> is <code>null</code> or
485 * the map list does not contain the specified map.
486 */
487 @Override
488 public int
489 getMidiInstrumentMapIndex(MidiInstrumentMap map) {
490 if(map == null) return -1;
491
492 for(int i = 0; i < getMidiInstrumentMapCount(); i++) {
493 if(getMidiInstrumentMap(i) == map) return i;
494 }
495
496 return -1;
497 }
498
499 /**
500 * Adds the specified MIDI instrument map.
501 * @param map The MIDI instrument map to be added.
502 * @throws IllegalArgumentException If <code>map</code> is <code>null</code>.
503 */
504 @Override
505 public void
506 addMidiInstrumentMap(MidiInstrumentMap map) {
507 if(map == null) throw new IllegalArgumentException("map should be non-null!");
508
509 midiInstrMaps.add(map);
510 fireMidiInstrumentMapAdded(map);
511 }
512
513 /**
514 * Schedules a new task for creating a new MIDI instrument map on the backend side.
515 * @param name The name of the MIDI instrument map.
516 * @throws IllegalArgumentException If <code>name</code> is <code>null</code>.
517 */
518 @Override
519 public void
520 addBackendMidiInstrumentMap(String name) {
521 if(name == null) throw new IllegalArgumentException("name should be non-null!");
522
523 CC.getTaskQueue().add(new Midi.AddInstrumentMap(name));
524 }
525
526 /**
527 * Removes the specified MIDI instrument map.
528 * @param mapId The ID of the MIDI instrument map to be removed.
529 * @return <code>true</code> if the MIDI instrument map is removed successfully,
530 * <code>false</code> if the MIDI instrument map's list does not contain
531 * MIDI instrument map with ID <code>mapId</code>.
532 */
533 @Override
534 public boolean
535 removeMidiInstrumentMapById(int mapId) {
536 for(int i = 0; i < midiInstrMaps.size(); i++) {
537 MidiInstrumentMap m = getMidiInstrumentMap(i);
538 if(m.getMapId() == mapId) {
539 midiInstrMaps.remove(i);
540 fireMidiInstrumentMapRemoved(m);
541 return true;
542 }
543 }
544
545 return false;
546 }
547
548 /**
549 * Removes the specified MIDI instrument map.
550 * @param map The MIDI instrument map to remove.
551 * @return <code>true</code> if the specified MIDI instrument map was in the list,
552 * <code>false</code> otherwise.
553 */
554 public boolean
555 removeMidiInstrumentMap(MidiInstrumentMap map) {
556 boolean b = midiInstrMaps.removeElement(map);
557 if(b) fireMidiInstrumentMapRemoved(map);
558 return b;
559 }
560
561 /** Removes all MIDI instrument maps. */
562 @Override
563 public void
564 removeAllMidiInstrumentMaps() {
565 for(int i = midiInstrMaps.size() - 1; i >= 0; i--) {
566 MidiInstrumentMap map = midiInstrMaps.get(i);
567 midiInstrMaps.removeElementAt(i);
568 fireMidiInstrumentMapRemoved(map);
569 }
570 }
571
572 /**
573 * Schedules a new task for removing the
574 * specified MIDI instrument map on the backend side.
575 * @param mapId The numerical ID of the MIDI instrument map to remove.
576 */
577 @Override
578 public void
579 removeBackendMidiInstrumentMap(int mapId) {
580 CC.getTaskQueue().add(new Midi.RemoveInstrumentMap(mapId));
581 }
582
583 /**
584 * Schedules a new task for changing the name of
585 * the specified MIDI instrument map on the backend side.
586 * @param mapId The numerical ID of the MIDI instrument map.
587 * @param name The new name for the specified MIDI instrument map.
588 */
589 @Override
590 public void
591 setBackendMidiInstrumentMapName(final int mapId, String name) {
592 final Task t = new Midi.SetInstrumentMapInfo(mapId, name);
593
594 t.addTaskListener(new TaskListener() {
595 public void
596 taskPerformed(TaskEvent e) {
597 /*
598 * Because with the invokation of the method the task is considered
599 * to be done, if the task fails, we must update the settings.
600 */
601 if(t.doneWithErrors()) {
602 Task t2 = new Midi.UpdateInstrumentMapInfo(mapId);
603 CC.getTaskQueue().add(t2);
604 }
605 }
606 });
607 CC.getTaskQueue().add(t);
608 }
609
610 /**
611 * Gets the default MIDI instrument map.
612 * @return The default MIDI instrument map or <code>null</code>
613 * if there are no maps created.
614 */
615 @Override
616 public MidiInstrumentMap
617 getDefaultMidiInstrumentMap() {
618 return defaultMidiInstrumentMap;
619 }
620
621 /**
622 * Gets the default MIDI instrument map.
623 * @return The default MIDI instrument map or <code>null</code>
624 * if there are no maps created.
625 */
626 private MidiInstrumentMap
627 findDefaultMidiInstrumentMap() {
628 for(int i = 0; i < getMidiInstrumentMapCount(); i++) {
629 MidiInstrumentMap m = getMidiInstrumentMap(i);
630 if(m.getInfo().isDefault()) return m;
631 }
632
633 return null;
634 }
635
636 /**
637 * Schedules a new task for mapping a MIDI instrument on the backend side.
638 * @param mapId The id of the MIDI instrument map.
639 * @param bank The index of the MIDI bank, which shall contain the instrument.
640 * @param program The MIDI program number of the new instrument.
641 * @param instrInfo Provides the MIDI instrument settings.
642 */
643 @Override
644 public void
645 mapBackendMidiInstrument(int mapId, int bank, int program, MidiInstrumentInfo instrInfo) {
646 CC.getTaskQueue().add(new Midi.MapInstrument(mapId, bank, program, instrInfo));
647 }
648
649 /**
650 * Schedules a new task for removing a MIDI instrument on the backend side.
651 * @param mapId The id of the MIDI instrument map containing the instrument to be removed.
652 * @param bank The index of the MIDI bank containing the instrument to be removed.
653 * @param program The MIDI program number of the instrument to be removed.
654 */
655 @Override
656 public void
657 unmapBackendMidiInstrument(int mapId, int bank, int program) {
658 CC.getTaskQueue().add(new Midi.UnmapInstrument(mapId, bank, program));
659 }
660
661 /**
662 * Gets a list of all available engines.
663 * @return A list of all available engines.
664 */
665 @Override
666 public SamplerEngine[]
667 getEngines() { return engines; }
668
669 /**
670 * Sets the list of all available engines.
671 * @param engines The new list of all available engines.
672 */
673 public void
674 setEngines(SamplerEngine[] engines) { this.engines = engines; }
675
676 /** Gets the list of internal effects */
677 public EffectList
678 getEffects() { return effects; }
679
680 @Override
681 public EffectInstance
682 getEffectInstanceById(int instanceId) {
683 for(int i = 0; i < getAudioDeviceCount(); i++) {
684 AudioDeviceModel m = getAudioDevice(i);
685 for(int j = 0; j < m.getSendEffectChainCount(); j++) {
686 EffectInstance ei =
687 m.getSendEffectChain(j).getEffectInstanceById(instanceId);
688
689 if(ei != null) return ei;
690 }
691 }
692
693 return null;
694 }
695
696 @Override
697 public void
698 updateEffectInstance(EffectInstanceInfo instance) {
699 EffectInstance ei = getEffectInstanceById(instance.getInstanceId());
700 if(ei == null) {
701 CC.getLogger().info("Unknow effect instance: " + instance.getInstanceId());
702 return;
703 }
704
705 ei.setInfo(instance);
706 }
707
708 /**
709 * Gets the model of the sampler channel in the specified position.
710 * @param index The position of the channel to return.
711 * @return The model of the specified sampler channel.
712 * @see #getchannelCount
713 */
714 @Override
715 public SamplerChannelModel
716 getChannel(int index) {
717 return channelModels.get(index);
718 }
719
720 /**
721 * Gets the model of the sampler channel with ID <code>channelId</code>.
722 * @param channelId The ID of the sampler channel whose model should be obtained.
723 * @return The model of the specified sampler channel or <code>null</code>
724 * if there is no channel with ID <code>channelId</code>.
725 */
726 @Override
727 public SamplerChannelModel
728 getChannelById(int channelId) {
729 for(SamplerChannelModel m : channelModels)
730 if(m.getChannelId() == channelId) return m;
731
732 return null;
733 }
734
735 /**
736 * Gets the position of the specified channel.
737 * @param channel The model of the channel.
738 * @return The position of the specified channel in the channel list or -1
739 * if the channel is not in the list.
740 */
741 @Override
742 public int
743 getChannelIndex(SamplerChannelModel channel) {
744 if(channel == null) return -1;
745 for(int i = 0; i < channelModels.size(); i++) {
746 if(channelModels.get(i).getChannelId() == channel.getChannelId()) return i;
747 }
748
749 return -1;
750 }
751
752 /**
753 * Gets the current number of sampler channels.
754 * @return The current number of sampler channels.
755 */
756 @Override
757 public int
758 getChannelCount() { return channelModels.size(); }
759
760 /**
761 * Gets the current list of sampler channel models.
762 * @return The current list of sampler channel models.
763 */
764 @Override
765 public SamplerChannelModel[]
766 getChannels() {
767 return channelModels.toArray(new SamplerChannelModel[channelModels.size()]);
768 }
769
770 /**
771 * Schedules a new task for adding a new sampler channel on the
772 * backend side. The channel will be actually added to this model
773 * when the backend notifies for its creation.
774 * @see #addChannel
775 */
776 @Override
777 public void
778 addBackendChannel() {
779 CC.getTaskQueue().add(new Channel.Add());
780 // We leave this event to be notified by the LinuxSampler notification system.
781 }
782
783 /**
784 * Adds the specified sampler channel.
785 * @param channel The channel to be added.
786 */
787 @Override
788 public void
789 addChannel(SamplerChannel channel) {
790 DefaultSamplerChannelModel model;
791 model = (channel == null) ? null : new DefaultSamplerChannelModel(channel);
792 if(model != null) channelModels.add(model);
793 fireSamplerChannelAdded(model);
794 }
795
796 /**
797 * Updates the settings of the specified channel.
798 * @param channel A <code>SamplerChannel</code> instance containing the new settings
799 * for the channel.
800 */
801 @Override
802 public void
803 updateChannel(SamplerChannel channel) {
804 for(SamplerChannelModel m : channelModels) {
805 if(m.getChannelId() == channel.getChannelId()) {
806 m.setChannelInfo(channel);
807 return;
808 }
809 }
810
811 CC.getLogger().log (
812 Level.WARNING, "DefaultSamplerModel.unknownChannel!", channel.getChannelId()
813 );
814 }
815
816 /**
817 * Determines whether there are known upcoming changes to the
818 * channel list, which should be considered as part of a single action.
819 */
820 @Override
821 public synchronized boolean
822 getChannelListIsAdjusting() { return channelListIsAdjusting; }
823
824 /**
825 * Sets whether the upcoming changes to the
826 * channel list should be considered part of a single action.
827 */
828 @Override
829 public synchronized void
830 setChannelListIsAdjusting(boolean b) {
831 channelListIsAdjusting = b;
832 }
833
834 /**
835 * Removes the specified sampler channel.
836 * Note that this method doesn't remove the channel in the backend,
837 * it is used to remove the channel from the model when those channel
838 * is removed in the backend.
839 * @param channelId The ID of the channel to be removed.
840 * @return <code>true</code> if the channel is removed successfully, <code>false</code>
841 * if the channel's list does not contain channel with ID <code>channelId</code>.
842 */
843 @Override
844 public boolean
845 removeChannelById(int channelId) {
846 for(int i = 0; i < channelModels.size(); i++) {
847 SamplerChannelModel m = channelModels.get(i);
848 if(m.getChannelId() == channelId) {
849 channelModels.remove(i);
850 fireSamplerChannelRemoved(m);
851 return true;
852 }
853 }
854
855 return false;
856 }
857
858 /**
859 * Removes all sampler channels.
860 * Note that this method doesn't remove the channel in the backend.
861 */
862 @Override
863 public void
864 removeAllChannels() {
865 if(channelModels.isEmpty()) return;
866
867 setChannelListIsAdjusting(true);
868 for(int i = channelModels.size() - 1; i > 0; i--) {
869 SamplerChannelModel m = channelModels.get(i);
870 channelModels.remove(i);
871 fireSamplerChannelRemoved(m);
872 }
873 setChannelListIsAdjusting(false);
874
875 SamplerChannelModel m = channelModels.get(0);
876 channelModels.remove(0);
877 fireSamplerChannelRemoved(m);
878 }
879
880 /**
881 * Schedules a new task for removing the specified sampler channel on the backend side.
882 * @param channelId The ID of the channel to be removed.
883 */
884 @Override
885 public void
886 removeBackendChannel(int channelId) {
887 CC.getTaskQueue().add(new Channel.Remove(channelId));
888 }
889
890 /**
891 * Schedules a new task for starting an instrument editor for editing
892 * the loaded instrument on the specified sampler channel.
893 * @param channelId The sampler channel number.
894 */
895 @Override
896 public void
897 editBackendInstrument(int channelId) {
898 CC.getTaskQueue().add(new Channel.EditInstrument(channelId));
899 }
900
901 /**
902 * Determines whether there is at least one solo channel in the current list
903 * of sampler channels.
904 * @return <code>true</code> if there is at least one solo channel in the current list of
905 * sampler channels, <code>false</code> otherwise.
906 */
907 @Override
908 public boolean
909 hasSoloChannel() {
910 for(SamplerChannelModel m : channelModels)
911 if(m.getChannelInfo().isSoloChannel()) return true;
912
913 return false;
914 }
915
916 /**
917 * Gets the number of solo channels in the current list of sampler channels.
918 * @return The number of solo channels in the current list of sampler channels.
919 */
920 @Override
921 public int
922 getSoloChannelCount() {
923 int count = 0;
924 for(SamplerChannelModel m : channelModels)
925 if(m.getChannelInfo().isSoloChannel()) count++;
926
927 return count;
928 }
929
930 /**
931 * Gets the number of muted channels in the current list of sampler channels.
932 * This number includes the channels muted because of the presence of a solo channel.
933 * @return The number of muted channels in the current list of sampler channels.
934 */
935 @Override
936 public int
937 getMutedChannelCount() {
938 int count = 0;
939 for(SamplerChannelModel m : channelModels)
940 if(m.getChannelInfo().isMuted()) count++;
941
942 return count;
943 }
944
945 /**
946 * Gets the number of channels muted because of the presence of a solo channel.
947 * @return The number of channels muted because of the presence of a solo channel.
948 */
949 @Override
950 public int
951 getMutedBySoloChannelCount() {
952 int count = 0;
953 for(SamplerChannelModel m : channelModels)
954 if(m.getChannelInfo().isMutedBySolo()) count++;
955
956 return count;
957 }
958
959 /**
960 * Gets the total number of active streams.
961 * @return The total number of active streams.
962 */
963 @Override
964 public int
965 getTotalStreamCount() { return totalStreamCount; }
966
967 /**
968 * Gets the total number of active voices.
969 * @return The total number of active voices.
970 */
971 @Override
972 public int
973 getTotalVoiceCount() { return totalVoiceCount; }
974
975 /**
976 * Gets the maximum number of active voices.
977 * @return The maximum number of active voices.
978 */
979 @Override
980 public int
981 getTotalVoiceCountMax() { return totalVoiceCountMax; }
982
983 /**
984 * Gets the golobal volume of the sampler.
985 * @return The golobal volume of the sampler.
986 */
987 @Override
988 public float
989 getVolume() { return volume; }
990
991 /**
992 * Sets the global volume.
993 * @param volume The new volume value.
994 */
995 @Override
996 public void
997 setVolume(float volume) {
998 if(this.volume == volume) return;
999
1000 this.volume = volume;
1001 fireVolumeChanged();
1002 }
1003
1004 /**
1005 * Schedules a new task for setting the global volume on the backend side.
1006 * @param volume The new volume value.
1007 */
1008 @Override
1009 public void
1010 setBackendVolume(float volume) {
1011 CC.getTaskQueue().add(new Global.SetVolume(volume));
1012 }
1013
1014 /**
1015 * Schedules a new task for resetting the sampler.
1016 */
1017 @Override
1018 public void
1019 resetBackend() { CC.getTaskQueue().add(new org.jsampler.task.Global.ResetSampler()); }
1020
1021 /**
1022 * Updates the current number of active disk streams in the sampler.
1023 * @param count The new number of active streams.
1024 */
1025 @Override
1026 public void
1027 updateActiveStreamsInfo(int count) {
1028 if(totalStreamCount == count) return;
1029
1030 totalStreamCount = count;
1031 fireTotalStreamCountChanged();
1032 }
1033
1034 /**
1035 * Updates the current and the maximum number of active voices in the sampler.
1036 * @param count The new number of active voices.
1037 * @param countMax The maximum number of active voices.
1038 */
1039 @Override
1040 public void
1041 updateActiveVoiceInfo(int count, int countMax) {
1042 if(totalVoiceCount == count && totalVoiceCountMax == countMax) return;
1043
1044 totalVoiceCount = count;
1045 totalVoiceCountMax = countMax;
1046 fireTotalVoiceCountChanged();
1047 }
1048
1049 /**
1050 * Determines whether the sampler configuration is modified.
1051 */
1052 @Override
1053 public boolean
1054 isModified() { return modified; }
1055
1056 /**
1057 * Sets whether the sampler configuration is modified.
1058 */
1059 @Override
1060 public void
1061 setModified(boolean b) { modified = b; }
1062
1063 /** Resets the model. */
1064 @Override
1065 public void
1066 reset() {
1067 removeAllMidiInstrumentMaps();
1068
1069 for(int i = channelModels.size() - 1; i >= 0; i--) {
1070 SamplerChannelModel m = channelModels.get(i);
1071 channelModels.remove(i);
1072 fireSamplerChannelRemoved(m);
1073 }
1074
1075 for(int i = midiDeviceModels.size() - 1; i >= 0; i--) {
1076 MidiDeviceModel m = midiDeviceModels.get(i);
1077 midiDeviceModels.remove(i);
1078 fireMidiDeviceRemoved(m);
1079 }
1080
1081 for(int i = audioDeviceModels.size() - 1; i >= 0; i--) {
1082 AudioDeviceModel m = audioDeviceModels.get(i);
1083 audioDeviceModels.remove(i);
1084 fireAudioDeviceRemoved(m);
1085 }
1086
1087 setServerInfo(null);
1088 setAudioOutputDrivers(null);
1089 setMidiInputDrivers(null);
1090 setEngines(null);
1091
1092 setVolume(0);
1093 setModified(false);
1094
1095 totalStreamCount = 0;
1096 totalVoiceCount = 0;
1097 totalVoiceCountMax = 0;
1098
1099 fireTotalStreamCountChanged();
1100 fireTotalVoiceCountChanged();
1101 fireDefaultMapChanged();
1102 }
1103
1104 /**
1105 * Notifies listeners that a sampler channel has been added.
1106 * This method can be invoked outside the event-dispatching thread.
1107 * @param channelModel A <code>SamplerChannelModel</code> instance.
1108 */
1109 private void
1110 fireSamplerChannelAdded(SamplerChannelModel channelModel) {
1111 final SamplerChannelListEvent e = new SamplerChannelListEvent(this, channelModel);
1112
1113 SwingUtilities.invokeLater(new Runnable() {
1114 public void
1115 run() { fireSamplerChannelAdded(e); }
1116 });
1117 }
1118 /**
1119 * Notifies listeners that a sampler channel has been added.
1120 */
1121 private void
1122 fireSamplerChannelAdded(SamplerChannelListEvent e) {
1123 setModified(true);
1124 Object[] listeners = listenerList.getListenerList();
1125
1126 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1127 if(listeners[i] == SamplerChannelListListener.class) {
1128 ((SamplerChannelListListener)listeners[i + 1]).channelAdded(e);
1129 }
1130 }
1131 }
1132
1133 /**
1134 * Notifies listeners that a sampler channel has been removed.
1135 * This method can be invoked outside the event-dispatching thread.
1136 * @param channelModel A <code>SamplerChannelModel</code> instance.
1137 */
1138 private void
1139 fireSamplerChannelRemoved(SamplerChannelModel channelModel) {
1140 final SamplerChannelListEvent e = new SamplerChannelListEvent(this, channelModel);
1141
1142 SwingUtilities.invokeLater(new Runnable() {
1143 public void
1144 run() { fireSamplerChannelRemoved(e); }
1145 });
1146 }
1147
1148 /**
1149 * Notifies listeners that a sampler channel has been removed.
1150 */
1151 private void
1152 fireSamplerChannelRemoved(SamplerChannelListEvent e) {
1153 setModified(true);
1154 Object[] listeners = listenerList.getListenerList();
1155
1156 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1157 if(listeners[i] == SamplerChannelListListener.class) {
1158 ((SamplerChannelListListener)listeners[i + 1]).channelRemoved(e);
1159 }
1160 }
1161 }
1162
1163 /**
1164 * Notifies listeners that a MIDI device has been added.
1165 * This method can be invoked outside the event-dispatching thread.
1166 * @param model A <code>MidiDeviceModel</code> instance.
1167 */
1168 private void
1169 fireMidiDeviceAdded(MidiDeviceModel model) {
1170 final MidiDeviceListEvent e = new MidiDeviceListEvent(this, model);
1171
1172 SwingUtilities.invokeLater(new Runnable() {
1173 public void
1174 run() { fireMidiDeviceAdded(e); }
1175 });
1176 }
1177 /**
1178 * Notifies listeners that a MIDI device has been added.
1179 */
1180 private void
1181 fireMidiDeviceAdded(MidiDeviceListEvent e) {
1182 setModified(true);
1183 Object[] listeners = listenerList.getListenerList();
1184
1185 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1186 if(listeners[i] == MidiDeviceListListener.class) {
1187 ((MidiDeviceListListener)listeners[i + 1]).deviceAdded(e);
1188 }
1189 }
1190 }
1191
1192 /**
1193 * Notifies listeners that a MIDI device has been removed.
1194 * This method can be invoked outside the event-dispatching thread.
1195 * @param model A <code>MidiDeviceModel</code> instance.
1196 */
1197 private void
1198 fireMidiDeviceRemoved(MidiDeviceModel model) {
1199 final MidiDeviceListEvent e = new MidiDeviceListEvent(this, model);
1200
1201 SwingUtilities.invokeLater(new Runnable() {
1202 public void
1203 run() { fireMidiDeviceRemoved(e); }
1204 });
1205 }
1206
1207 /**
1208 * Notifies listeners that a MIDI device has been removed.
1209 */
1210 private void
1211 fireMidiDeviceRemoved(MidiDeviceListEvent e) {
1212 setModified(true);
1213 Object[] listeners = listenerList.getListenerList();
1214
1215 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1216 if(listeners[i] == MidiDeviceListListener.class) {
1217 ((MidiDeviceListListener)listeners[i + 1]).deviceRemoved(e);
1218 }
1219 }
1220 }
1221
1222 /**
1223 * Notifies listeners that an audio device has been added.
1224 * This method can be invoked outside the event-dispatching thread.
1225 * @param model A <code>AudioDeviceModel</code> instance.
1226 */
1227 private void
1228 fireAudioDeviceAdded(AudioDeviceModel model) {
1229 final ListEvent<AudioDeviceModel> e = new ListEvent<AudioDeviceModel>(this, model);
1230
1231 SwingUtilities.invokeLater(new Runnable() {
1232 public void
1233 run() { fireAudioDeviceAdded(e); }
1234 });
1235 }
1236
1237 /**
1238 * Notifies listeners that an audio device has been added.
1239 */
1240 private void
1241 fireAudioDeviceAdded(ListEvent<AudioDeviceModel> e) {
1242 setModified(true);
1243 Object[] listeners = listenerList.getListenerList();
1244
1245 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1246 if(listeners[i] == ListListener.class) {
1247 ((ListListener<AudioDeviceModel>)listeners[i + 1]).entryAdded(e);
1248 }
1249 }
1250 }
1251
1252 /**
1253 * Notifies listeners that an audio device has been removed.
1254 * This method can be invoked outside the event-dispatching thread.
1255 * @param model A <code>AudioDeviceModel</code> instance.
1256 */
1257 private void
1258 fireAudioDeviceRemoved(AudioDeviceModel model) {
1259 final ListEvent<AudioDeviceModel> e = new ListEvent<AudioDeviceModel>(this, model);
1260
1261 SwingUtilities.invokeLater(new Runnable() {
1262 public void
1263 run() { fireAudioDeviceRemoved(e); }
1264 });
1265 }
1266
1267 /**
1268 * Notifies listeners that an audio device has been removed.
1269 * This method should be invoked from the event-dispatching thread.
1270 */
1271 private void
1272 fireAudioDeviceRemoved(ListEvent<AudioDeviceModel> e) {
1273 setModified(true);
1274 Object[] listeners = listenerList.getListenerList();
1275
1276 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1277 if(listeners[i] == ListListener.class) {
1278 ((ListListener<AudioDeviceModel>)listeners[i + 1]).entryRemoved(e);
1279 }
1280 }
1281 }
1282
1283 /**
1284 * Notifies listeners that a MIDI instrument map has been added to the list.
1285 * This method can be invoked outside the event-dispatching thread.
1286 */
1287 private void
1288 fireMidiInstrumentMapAdded(MidiInstrumentMap map) {
1289 final ListEvent<MidiInstrumentMap> e = new ListEvent<MidiInstrumentMap>(this, map);
1290
1291 SwingUtilities.invokeLater(new Runnable() {
1292 public void
1293 run() { fireMidiInstrumentMapAdded(e); }
1294 });
1295 }
1296
1297 /** Notifies listeners that a MIDI instrument map has been added to the list. */
1298 private void
1299 fireMidiInstrumentMapAdded(ListEvent<MidiInstrumentMap> e) {
1300 setModified(true);
1301 for(ListListener<MidiInstrumentMap> l : mapsListeners) l.entryAdded(e);
1302 }
1303
1304 /**
1305 * Notifies listeners that a MIDI instrument map has been removed from the list.
1306 * This method can be invoked outside the event-dispatching thread.
1307 */
1308 private void
1309 fireMidiInstrumentMapRemoved(MidiInstrumentMap map) {
1310 final ListEvent<MidiInstrumentMap> e = new ListEvent<MidiInstrumentMap>(this, map);
1311
1312 SwingUtilities.invokeLater(new Runnable() {
1313 public void
1314 run() { fireMidiInstrumentMapRemoved(e); }
1315 });
1316 }
1317 /** Notifies listeners that a MIDI instrument map has been removed from the list. */
1318 private void
1319 fireMidiInstrumentMapRemoved(ListEvent<MidiInstrumentMap> e) {
1320 setModified(true);
1321 for(ListListener<MidiInstrumentMap> l : mapsListeners) l.entryRemoved(e);
1322 }
1323
1324 /**
1325 * Notifies listeners that the global volume has changed.
1326 * This method can be invoked outside the event-dispatching thread.
1327 */
1328 private void
1329 fireVolumeChanged() {
1330 final SamplerEvent e = new SamplerEvent(this);
1331
1332 SwingUtilities.invokeLater(new Runnable() {
1333 public void
1334 run() { fireVolumeChanged(e); }
1335 });
1336 }
1337
1338 /**
1339 * Notifies listeners that the global volume has changed.
1340 */
1341 private void
1342 fireVolumeChanged(SamplerEvent e) {
1343 setModified(true);
1344 for(SamplerListener l : listeners) l.volumeChanged(e);
1345 }
1346
1347 /*
1348 * Notifies listeners that the total number of active streams has changed.
1349 * This method can be invoked outside the event-dispatching thread.
1350 */
1351 private void
1352 fireTotalStreamCountChanged() {
1353 final SamplerEvent e = new SamplerEvent(this);
1354
1355 SwingUtilities.invokeLater(new Runnable() {
1356 public void
1357 run() { fireTotalStreamCountChanged(e); }
1358 });
1359 }
1360
1361 /**
1362 * Notifies listeners that the total number of active streams has changed.
1363 */
1364 private void
1365 fireTotalStreamCountChanged(SamplerEvent e) {
1366 for(SamplerListener l : listeners) l.totalStreamCountChanged(e);
1367 }
1368
1369 /*
1370 * Notifies listeners that the total number of active voices has changed.
1371 * This method can be invoked outside the event-dispatching thread.
1372 */
1373 private void
1374 fireTotalVoiceCountChanged() {
1375 final SamplerEvent e = new SamplerEvent(this);
1376
1377 SwingUtilities.invokeLater(new Runnable() {
1378 public void
1379 run() { fireTotalVoiceCountChanged(e); }
1380 });
1381 }
1382
1383 /**
1384 * Notifies listeners that the total number of active voices has changed.
1385 */
1386 private void
1387 fireTotalVoiceCountChanged(SamplerEvent e) {
1388 for(SamplerListener l : listeners) l.totalVoiceCountChanged(e);
1389 }
1390
1391 /**
1392 * Notifies listeners that the default MIDI instrument map is changed.
1393 */
1394 private void
1395 fireDefaultMapChanged() {
1396 SamplerEvent e = new SamplerEvent(this);
1397 for(SamplerListener l : listeners) l.defaultMapChanged(e);
1398 }
1399
1400 private final Handler handler = new Handler();
1401
1402 private Handler
1403 getHandler() { return handler; }
1404
1405 private class Handler implements ListListener<MidiInstrumentMap> {
1406 /** Invoked when a new map is added to a list. */
1407 @Override
1408 public void
1409 entryAdded(ListEvent<MidiInstrumentMap> e) { updateDefaultMap(); }
1410
1411 /** Invoked when a map is removed from a list. */
1412 @Override
1413 public void
1414 entryRemoved(ListEvent<MidiInstrumentMap> e) { updateDefaultMap(); }
1415
1416 private void
1417 updateDefaultMap() {
1418 if(getDefaultMidiInstrumentMap() != findDefaultMidiInstrumentMap()) {
1419 defaultMidiInstrumentMap = findDefaultMidiInstrumentMap();
1420 fireDefaultMapChanged();
1421 }
1422 }
1423 }
1424 }

  ViewVC Help
Powered by ViewVC