/[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 2192 - (show annotations) (download)
Fri Jun 24 21:34:51 2011 UTC (12 years, 10 months ago) by iliev
File size: 39928 byte(s)
* Initial implementation of Sampler Browser
  (choose Window/Sampler Browser) - another way to view/edit
  the sampler configuration (work in progress - for now only
  support for viewing/editing send effects)

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 /**
681 * Gets the model of the sampler channel in the specified position.
682 * @param index The position of the channel to return.
683 * @return The model of the specified sampler channel.
684 * @see #getchannelCount
685 */
686 @Override
687 public SamplerChannelModel
688 getChannel(int index) {
689 return channelModels.get(index);
690 }
691
692 /**
693 * Gets the model of the sampler channel with ID <code>channelId</code>.
694 * @param channelId The ID of the sampler channel whose model should be obtained.
695 * @return The model of the specified sampler channel or <code>null</code>
696 * if there is no channel with ID <code>channelId</code>.
697 */
698 @Override
699 public SamplerChannelModel
700 getChannelById(int channelId) {
701 for(SamplerChannelModel m : channelModels)
702 if(m.getChannelId() == channelId) return m;
703
704 return null;
705 }
706
707 /**
708 * Gets the position of the specified channel.
709 * @param channel The model of the channel.
710 * @return The position of the specified channel in the channel list or -1
711 * if the channel is not in the list.
712 */
713 @Override
714 public int
715 getChannelIndex(SamplerChannelModel channel) {
716 if(channel == null) return -1;
717 for(int i = 0; i < channelModels.size(); i++) {
718 if(channelModels.get(i).getChannelId() == channel.getChannelId()) return i;
719 }
720
721 return -1;
722 }
723
724 /**
725 * Gets the current number of sampler channels.
726 * @return The current number of sampler channels.
727 */
728 @Override
729 public int
730 getChannelCount() { return channelModels.size(); }
731
732 /**
733 * Gets the current list of sampler channel models.
734 * @return The current list of sampler channel models.
735 */
736 @Override
737 public SamplerChannelModel[]
738 getChannels() {
739 return channelModels.toArray(new SamplerChannelModel[channelModels.size()]);
740 }
741
742 /**
743 * Schedules a new task for adding a new sampler channel on the
744 * backend side. The channel will be actually added to this model
745 * when the backend notifies for its creation.
746 * @see #addChannel
747 */
748 @Override
749 public void
750 addBackendChannel() {
751 CC.getTaskQueue().add(new Channel.Add());
752 // We leave this event to be notified by the LinuxSampler notification system.
753 }
754
755 /**
756 * Adds the specified sampler channel.
757 * @param channel The channel to be added.
758 */
759 @Override
760 public void
761 addChannel(SamplerChannel channel) {
762 DefaultSamplerChannelModel model;
763 model = (channel == null) ? null : new DefaultSamplerChannelModel(channel);
764 if(model != null) channelModels.add(model);
765 fireSamplerChannelAdded(model);
766 }
767
768 /**
769 * Updates the settings of the specified channel.
770 * @param channel A <code>SamplerChannel</code> instance containing the new settings
771 * for the channel.
772 */
773 @Override
774 public void
775 updateChannel(SamplerChannel channel) {
776 for(SamplerChannelModel m : channelModels) {
777 if(m.getChannelId() == channel.getChannelId()) {
778 m.setChannelInfo(channel);
779 return;
780 }
781 }
782
783 CC.getLogger().log (
784 Level.WARNING, "DefaultSamplerModel.unknownChannel!", channel.getChannelId()
785 );
786 }
787
788 /**
789 * Determines whether there are known upcoming changes to the
790 * channel list, which should be considered as part of a single action.
791 */
792 @Override
793 public synchronized boolean
794 getChannelListIsAdjusting() { return channelListIsAdjusting; }
795
796 /**
797 * Sets whether the upcoming changes to the
798 * channel list should be considered part of a single action.
799 */
800 @Override
801 public synchronized void
802 setChannelListIsAdjusting(boolean b) {
803 channelListIsAdjusting = b;
804 }
805
806 /**
807 * Removes the specified sampler channel.
808 * Note that this method doesn't remove the channel in the backend,
809 * it is used to remove the channel from the model when those channel
810 * is removed in the backend.
811 * @param channelId The ID of the channel to be removed.
812 * @return <code>true</code> if the channel is removed successfully, <code>false</code>
813 * if the channel's list does not contain channel with ID <code>channelId</code>.
814 */
815 @Override
816 public boolean
817 removeChannelById(int channelId) {
818 for(int i = 0; i < channelModels.size(); i++) {
819 SamplerChannelModel m = channelModels.get(i);
820 if(m.getChannelId() == channelId) {
821 channelModels.remove(i);
822 fireSamplerChannelRemoved(m);
823 return true;
824 }
825 }
826
827 return false;
828 }
829
830 /**
831 * Removes all sampler channels.
832 * Note that this method doesn't remove the channel in the backend.
833 */
834 @Override
835 public void
836 removeAllChannels() {
837 if(channelModels.isEmpty()) return;
838
839 setChannelListIsAdjusting(true);
840 for(int i = channelModels.size() - 1; i > 0; i--) {
841 SamplerChannelModel m = channelModels.get(i);
842 channelModels.remove(i);
843 fireSamplerChannelRemoved(m);
844 }
845 setChannelListIsAdjusting(false);
846
847 SamplerChannelModel m = channelModels.get(0);
848 channelModels.remove(0);
849 fireSamplerChannelRemoved(m);
850 }
851
852 /**
853 * Schedules a new task for removing the specified sampler channel on the backend side.
854 * @param channelId The ID of the channel to be removed.
855 */
856 @Override
857 public void
858 removeBackendChannel(int channelId) {
859 CC.getTaskQueue().add(new Channel.Remove(channelId));
860 }
861
862 /**
863 * Schedules a new task for starting an instrument editor for editing
864 * the loaded instrument on the specified sampler channel.
865 * @param channelId The sampler channel number.
866 */
867 @Override
868 public void
869 editBackendInstrument(int channelId) {
870 CC.getTaskQueue().add(new Channel.EditInstrument(channelId));
871 }
872
873 /**
874 * Determines whether there is at least one solo channel in the current list
875 * of sampler channels.
876 * @return <code>true</code> if there is at least one solo channel in the current list of
877 * sampler channels, <code>false</code> otherwise.
878 */
879 @Override
880 public boolean
881 hasSoloChannel() {
882 for(SamplerChannelModel m : channelModels)
883 if(m.getChannelInfo().isSoloChannel()) return true;
884
885 return false;
886 }
887
888 /**
889 * Gets the number of solo channels in the current list of sampler channels.
890 * @return The number of solo channels in the current list of sampler channels.
891 */
892 @Override
893 public int
894 getSoloChannelCount() {
895 int count = 0;
896 for(SamplerChannelModel m : channelModels)
897 if(m.getChannelInfo().isSoloChannel()) count++;
898
899 return count;
900 }
901
902 /**
903 * Gets the number of muted channels in the current list of sampler channels.
904 * This number includes the channels muted because of the presence of a solo channel.
905 * @return The number of muted channels in the current list of sampler channels.
906 */
907 @Override
908 public int
909 getMutedChannelCount() {
910 int count = 0;
911 for(SamplerChannelModel m : channelModels)
912 if(m.getChannelInfo().isMuted()) count++;
913
914 return count;
915 }
916
917 /**
918 * Gets the number of channels muted because of the presence of a solo channel.
919 * @return The number of channels muted because of the presence of a solo channel.
920 */
921 @Override
922 public int
923 getMutedBySoloChannelCount() {
924 int count = 0;
925 for(SamplerChannelModel m : channelModels)
926 if(m.getChannelInfo().isMutedBySolo()) count++;
927
928 return count;
929 }
930
931 /**
932 * Gets the total number of active streams.
933 * @return The total number of active streams.
934 */
935 @Override
936 public int
937 getTotalStreamCount() { return totalStreamCount; }
938
939 /**
940 * Gets the total number of active voices.
941 * @return The total number of active voices.
942 */
943 @Override
944 public int
945 getTotalVoiceCount() { return totalVoiceCount; }
946
947 /**
948 * Gets the maximum number of active voices.
949 * @return The maximum number of active voices.
950 */
951 @Override
952 public int
953 getTotalVoiceCountMax() { return totalVoiceCountMax; }
954
955 /**
956 * Gets the golobal volume of the sampler.
957 * @return The golobal volume of the sampler.
958 */
959 @Override
960 public float
961 getVolume() { return volume; }
962
963 /**
964 * Sets the global volume.
965 * @param volume The new volume value.
966 */
967 @Override
968 public void
969 setVolume(float volume) {
970 if(this.volume == volume) return;
971
972 this.volume = volume;
973 fireVolumeChanged();
974 }
975
976 /**
977 * Schedules a new task for setting the global volume on the backend side.
978 * @param volume The new volume value.
979 */
980 @Override
981 public void
982 setBackendVolume(float volume) {
983 CC.getTaskQueue().add(new Global.SetVolume(volume));
984 }
985
986 /**
987 * Schedules a new task for resetting the sampler.
988 */
989 @Override
990 public void
991 resetBackend() { CC.getTaskQueue().add(new org.jsampler.task.Global.ResetSampler()); }
992
993 /**
994 * Updates the current number of active disk streams in the sampler.
995 * @param count The new number of active streams.
996 */
997 @Override
998 public void
999 updateActiveStreamsInfo(int count) {
1000 if(totalStreamCount == count) return;
1001
1002 totalStreamCount = count;
1003 fireTotalStreamCountChanged();
1004 }
1005
1006 /**
1007 * Updates the current and the maximum number of active voices in the sampler.
1008 * @param count The new number of active voices.
1009 * @param countMax The maximum number of active voices.
1010 */
1011 @Override
1012 public void
1013 updateActiveVoiceInfo(int count, int countMax) {
1014 if(totalVoiceCount == count && totalVoiceCountMax == countMax) return;
1015
1016 totalVoiceCount = count;
1017 totalVoiceCountMax = countMax;
1018 fireTotalVoiceCountChanged();
1019 }
1020
1021 /**
1022 * Determines whether the sampler configuration is modified.
1023 */
1024 @Override
1025 public boolean
1026 isModified() { return modified; }
1027
1028 /**
1029 * Sets whether the sampler configuration is modified.
1030 */
1031 @Override
1032 public void
1033 setModified(boolean b) { modified = b; }
1034
1035 /** Resets the model. */
1036 @Override
1037 public void
1038 reset() {
1039 removeAllMidiInstrumentMaps();
1040
1041 for(int i = channelModels.size() - 1; i >= 0; i--) {
1042 SamplerChannelModel m = channelModels.get(i);
1043 channelModels.remove(i);
1044 fireSamplerChannelRemoved(m);
1045 }
1046
1047 for(int i = midiDeviceModels.size() - 1; i >= 0; i--) {
1048 MidiDeviceModel m = midiDeviceModels.get(i);
1049 midiDeviceModels.remove(i);
1050 fireMidiDeviceRemoved(m);
1051 }
1052
1053 for(int i = audioDeviceModels.size() - 1; i >= 0; i--) {
1054 AudioDeviceModel m = audioDeviceModels.get(i);
1055 audioDeviceModels.remove(i);
1056 fireAudioDeviceRemoved(m);
1057 }
1058
1059 setServerInfo(null);
1060 setAudioOutputDrivers(null);
1061 setMidiInputDrivers(null);
1062 setEngines(null);
1063
1064 setVolume(0);
1065 setModified(false);
1066
1067 totalStreamCount = 0;
1068 totalVoiceCount = 0;
1069 totalVoiceCountMax = 0;
1070
1071 fireTotalStreamCountChanged();
1072 fireTotalVoiceCountChanged();
1073 fireDefaultMapChanged();
1074 }
1075
1076 /**
1077 * Notifies listeners that a sampler channel has been added.
1078 * This method can be invoked outside the event-dispatching thread.
1079 * @param channelModel A <code>SamplerChannelModel</code> instance.
1080 */
1081 private void
1082 fireSamplerChannelAdded(SamplerChannelModel channelModel) {
1083 final SamplerChannelListEvent e = new SamplerChannelListEvent(this, channelModel);
1084
1085 SwingUtilities.invokeLater(new Runnable() {
1086 public void
1087 run() { fireSamplerChannelAdded(e); }
1088 });
1089 }
1090 /**
1091 * Notifies listeners that a sampler channel has been added.
1092 */
1093 private void
1094 fireSamplerChannelAdded(SamplerChannelListEvent e) {
1095 setModified(true);
1096 Object[] listeners = listenerList.getListenerList();
1097
1098 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1099 if(listeners[i] == SamplerChannelListListener.class) {
1100 ((SamplerChannelListListener)listeners[i + 1]).channelAdded(e);
1101 }
1102 }
1103 }
1104
1105 /**
1106 * Notifies listeners that a sampler channel has been removed.
1107 * This method can be invoked outside the event-dispatching thread.
1108 * @param channelModel A <code>SamplerChannelModel</code> instance.
1109 */
1110 private void
1111 fireSamplerChannelRemoved(SamplerChannelModel channelModel) {
1112 final SamplerChannelListEvent e = new SamplerChannelListEvent(this, channelModel);
1113
1114 SwingUtilities.invokeLater(new Runnable() {
1115 public void
1116 run() { fireSamplerChannelRemoved(e); }
1117 });
1118 }
1119
1120 /**
1121 * Notifies listeners that a sampler channel has been removed.
1122 */
1123 private void
1124 fireSamplerChannelRemoved(SamplerChannelListEvent e) {
1125 setModified(true);
1126 Object[] listeners = listenerList.getListenerList();
1127
1128 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1129 if(listeners[i] == SamplerChannelListListener.class) {
1130 ((SamplerChannelListListener)listeners[i + 1]).channelRemoved(e);
1131 }
1132 }
1133 }
1134
1135 /**
1136 * Notifies listeners that a MIDI device has been added.
1137 * This method can be invoked outside the event-dispatching thread.
1138 * @param model A <code>MidiDeviceModel</code> instance.
1139 */
1140 private void
1141 fireMidiDeviceAdded(MidiDeviceModel model) {
1142 final MidiDeviceListEvent e = new MidiDeviceListEvent(this, model);
1143
1144 SwingUtilities.invokeLater(new Runnable() {
1145 public void
1146 run() { fireMidiDeviceAdded(e); }
1147 });
1148 }
1149 /**
1150 * Notifies listeners that a MIDI device has been added.
1151 */
1152 private void
1153 fireMidiDeviceAdded(MidiDeviceListEvent e) {
1154 setModified(true);
1155 Object[] listeners = listenerList.getListenerList();
1156
1157 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1158 if(listeners[i] == MidiDeviceListListener.class) {
1159 ((MidiDeviceListListener)listeners[i + 1]).deviceAdded(e);
1160 }
1161 }
1162 }
1163
1164 /**
1165 * Notifies listeners that a MIDI device has been removed.
1166 * This method can be invoked outside the event-dispatching thread.
1167 * @param model A <code>MidiDeviceModel</code> instance.
1168 */
1169 private void
1170 fireMidiDeviceRemoved(MidiDeviceModel model) {
1171 final MidiDeviceListEvent e = new MidiDeviceListEvent(this, model);
1172
1173 SwingUtilities.invokeLater(new Runnable() {
1174 public void
1175 run() { fireMidiDeviceRemoved(e); }
1176 });
1177 }
1178
1179 /**
1180 * Notifies listeners that a MIDI device has been removed.
1181 */
1182 private void
1183 fireMidiDeviceRemoved(MidiDeviceListEvent e) {
1184 setModified(true);
1185 Object[] listeners = listenerList.getListenerList();
1186
1187 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1188 if(listeners[i] == MidiDeviceListListener.class) {
1189 ((MidiDeviceListListener)listeners[i + 1]).deviceRemoved(e);
1190 }
1191 }
1192 }
1193
1194 /**
1195 * Notifies listeners that an audio device has been added.
1196 * This method can be invoked outside the event-dispatching thread.
1197 * @param model A <code>AudioDeviceModel</code> instance.
1198 */
1199 private void
1200 fireAudioDeviceAdded(AudioDeviceModel model) {
1201 final ListEvent<AudioDeviceModel> e = new ListEvent<AudioDeviceModel>(this, model);
1202
1203 SwingUtilities.invokeLater(new Runnable() {
1204 public void
1205 run() { fireAudioDeviceAdded(e); }
1206 });
1207 }
1208
1209 /**
1210 * Notifies listeners that an audio device has been added.
1211 */
1212 private void
1213 fireAudioDeviceAdded(ListEvent<AudioDeviceModel> e) {
1214 setModified(true);
1215 Object[] listeners = listenerList.getListenerList();
1216
1217 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1218 if(listeners[i] == ListListener.class) {
1219 ((ListListener<AudioDeviceModel>)listeners[i + 1]).entryAdded(e);
1220 }
1221 }
1222 }
1223
1224 /**
1225 * Notifies listeners that an audio device has been removed.
1226 * This method can be invoked outside the event-dispatching thread.
1227 * @param model A <code>AudioDeviceModel</code> instance.
1228 */
1229 private void
1230 fireAudioDeviceRemoved(AudioDeviceModel model) {
1231 final ListEvent<AudioDeviceModel> e = new ListEvent<AudioDeviceModel>(this, model);
1232
1233 SwingUtilities.invokeLater(new Runnable() {
1234 public void
1235 run() { fireAudioDeviceRemoved(e); }
1236 });
1237 }
1238
1239 /**
1240 * Notifies listeners that an audio device has been removed.
1241 * This method should be invoked from the event-dispatching thread.
1242 */
1243 private void
1244 fireAudioDeviceRemoved(ListEvent<AudioDeviceModel> e) {
1245 setModified(true);
1246 Object[] listeners = listenerList.getListenerList();
1247
1248 for(int i = listeners.length - 2; i >= 0; i -= 2) {
1249 if(listeners[i] == ListListener.class) {
1250 ((ListListener<AudioDeviceModel>)listeners[i + 1]).entryRemoved(e);
1251 }
1252 }
1253 }
1254
1255 /**
1256 * Notifies listeners that a MIDI instrument map has been added to the list.
1257 * This method can be invoked outside the event-dispatching thread.
1258 */
1259 private void
1260 fireMidiInstrumentMapAdded(MidiInstrumentMap map) {
1261 final ListEvent<MidiInstrumentMap> e = new ListEvent<MidiInstrumentMap>(this, map);
1262
1263 SwingUtilities.invokeLater(new Runnable() {
1264 public void
1265 run() { fireMidiInstrumentMapAdded(e); }
1266 });
1267 }
1268
1269 /** Notifies listeners that a MIDI instrument map has been added to the list. */
1270 private void
1271 fireMidiInstrumentMapAdded(ListEvent<MidiInstrumentMap> e) {
1272 setModified(true);
1273 for(ListListener<MidiInstrumentMap> l : mapsListeners) l.entryAdded(e);
1274 }
1275
1276 /**
1277 * Notifies listeners that a MIDI instrument map has been removed from the list.
1278 * This method can be invoked outside the event-dispatching thread.
1279 */
1280 private void
1281 fireMidiInstrumentMapRemoved(MidiInstrumentMap map) {
1282 final ListEvent<MidiInstrumentMap> e = new ListEvent<MidiInstrumentMap>(this, map);
1283
1284 SwingUtilities.invokeLater(new Runnable() {
1285 public void
1286 run() { fireMidiInstrumentMapRemoved(e); }
1287 });
1288 }
1289 /** Notifies listeners that a MIDI instrument map has been removed from the list. */
1290 private void
1291 fireMidiInstrumentMapRemoved(ListEvent<MidiInstrumentMap> e) {
1292 setModified(true);
1293 for(ListListener<MidiInstrumentMap> l : mapsListeners) l.entryRemoved(e);
1294 }
1295
1296 /**
1297 * Notifies listeners that the global volume has changed.
1298 * This method can be invoked outside the event-dispatching thread.
1299 */
1300 private void
1301 fireVolumeChanged() {
1302 final SamplerEvent e = new SamplerEvent(this);
1303
1304 SwingUtilities.invokeLater(new Runnable() {
1305 public void
1306 run() { fireVolumeChanged(e); }
1307 });
1308 }
1309
1310 /**
1311 * Notifies listeners that the global volume has changed.
1312 */
1313 private void
1314 fireVolumeChanged(SamplerEvent e) {
1315 setModified(true);
1316 for(SamplerListener l : listeners) l.volumeChanged(e);
1317 }
1318
1319 /*
1320 * Notifies listeners that the total number of active streams has changed.
1321 * This method can be invoked outside the event-dispatching thread.
1322 */
1323 private void
1324 fireTotalStreamCountChanged() {
1325 final SamplerEvent e = new SamplerEvent(this);
1326
1327 SwingUtilities.invokeLater(new Runnable() {
1328 public void
1329 run() { fireTotalStreamCountChanged(e); }
1330 });
1331 }
1332
1333 /**
1334 * Notifies listeners that the total number of active streams has changed.
1335 */
1336 private void
1337 fireTotalStreamCountChanged(SamplerEvent e) {
1338 for(SamplerListener l : listeners) l.totalStreamCountChanged(e);
1339 }
1340
1341 /*
1342 * Notifies listeners that the total number of active voices has changed.
1343 * This method can be invoked outside the event-dispatching thread.
1344 */
1345 private void
1346 fireTotalVoiceCountChanged() {
1347 final SamplerEvent e = new SamplerEvent(this);
1348
1349 SwingUtilities.invokeLater(new Runnable() {
1350 public void
1351 run() { fireTotalVoiceCountChanged(e); }
1352 });
1353 }
1354
1355 /**
1356 * Notifies listeners that the total number of active voices has changed.
1357 */
1358 private void
1359 fireTotalVoiceCountChanged(SamplerEvent e) {
1360 for(SamplerListener l : listeners) l.totalVoiceCountChanged(e);
1361 }
1362
1363 /**
1364 * Notifies listeners that the default MIDI instrument map is changed.
1365 */
1366 private void
1367 fireDefaultMapChanged() {
1368 SamplerEvent e = new SamplerEvent(this);
1369 for(SamplerListener l : listeners) l.defaultMapChanged(e);
1370 }
1371
1372 private final Handler handler = new Handler();
1373
1374 private Handler
1375 getHandler() { return handler; }
1376
1377 private class Handler implements ListListener<MidiInstrumentMap> {
1378 /** Invoked when a new map is added to a list. */
1379 @Override
1380 public void
1381 entryAdded(ListEvent<MidiInstrumentMap> e) { updateDefaultMap(); }
1382
1383 /** Invoked when a map is removed from a list. */
1384 @Override
1385 public void
1386 entryRemoved(ListEvent<MidiInstrumentMap> e) { updateDefaultMap(); }
1387
1388 private void
1389 updateDefaultMap() {
1390 if(getDefaultMidiInstrumentMap() != findDefaultMidiInstrumentMap()) {
1391 defaultMidiInstrumentMap = findDefaultMidiInstrumentMap();
1392 fireDefaultMapChanged();
1393 }
1394 }
1395 }
1396 }

  ViewVC Help
Powered by ViewVC