/[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 2200 - (show annotations) (download)
Sun Jul 3 22:01:16 2011 UTC (12 years, 9 months ago) by iliev
File size: 41168 byte(s)
* added support for exporting effects to LSCP script
* Sampler Browser (work in progress): initial
  implementation of sampler channels

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

  ViewVC Help
Powered by ViewVC