/* * JSampler - a java front-end for LinuxSampler * * Copyright (C) 2005 Grigor Kirilov Iliev * * This file is part of JSampler. * * JSampler is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * JSampler is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with JSampler; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package org.jsampler; import java.util.Vector; import java.util.logging.Level; import javax.swing.SwingUtilities; import javax.swing.event.EventListenerList; import org.jsampler.event.AudioDeviceListEvent; import org.jsampler.event.AudioDeviceListListener; import org.jsampler.event.MidiDeviceListEvent; import org.jsampler.event.MidiDeviceListListener; import org.jsampler.event.SamplerChannelListEvent; import org.jsampler.event.SamplerChannelListListener; import org.jsampler.event.SamplerEvent; import org.jsampler.event.SamplerListener; import org.jsampler.task.AddChannel; import org.linuxsampler.lscp.*; /** * * @author Grigor Iliev */ public class DefaultSamplerModel implements SamplerModel { private ServerInfo serverInfo = null; private AudioOutputDriver[] aoDrvS = null; private MidiInputDriver[] miDrvS = null; private SamplerEngine[] engines = null; private int totalVoiceCount = 0; private int totalVoiceCountMax = 0; private final Vector channelModels = new Vector(); private final Vector audioDeviceModels = new Vector(); private final Vector midiDeviceModels = new Vector(); private final Vector listeners = new Vector(); private final EventListenerList listenerList = new EventListenerList(); /** Creates a new instance of DefaultSamplerModel */ public DefaultSamplerModel() { } /** * Registers the specified listener for receiving event messages. * @param l The SamplerListener to register. */ public void addSamplerListener(SamplerListener l) { listeners.add(l); } /** * Removes the specified listener. * @param l The SamplerListener to remove. */ public void removeSamplerListener(SamplerListener l) { listeners.remove(l); } /** * Registers the specified listener for receiving event messages. * @param listener The AudioDeviceListListener to register. */ public void addAudioDeviceListListener(AudioDeviceListListener listener) { listenerList.add(AudioDeviceListListener.class, listener); } /** * Removes the specified listener. * @param listener The AudioDeviceListListener to remove. */ public void removeAudioDeviceListListener(AudioDeviceListListener listener) { listenerList.remove(AudioDeviceListListener.class, listener); } /** * Registers the specified listener for receiving event messages. * @param listener The MidiDeviceListListener to register. */ public void addMidiDeviceListListener(MidiDeviceListListener listener) { listenerList.add(MidiDeviceListListener.class, listener); } /** * Removes the specified listener. * @param listener The MidiDeviceListListener to remove. */ public void removeMidiDeviceListListener(MidiDeviceListListener listener) { listenerList.remove(MidiDeviceListListener.class, listener); } /** * Registers the specified listener for receiving event messages. * @param listener The SamplerChannelListListener to register. */ public void addSamplerChannelListListener(SamplerChannelListListener listener) { listenerList.add(SamplerChannelListListener.class, listener); } /** * Removes the specified listener. * @param listener The SamplerChannelListListener to remove. */ public void removeSamplerChannelListListener(SamplerChannelListListener listener) { listenerList.remove(SamplerChannelListListener.class, listener); } /** * Gets information about the LinuxSampler instance the front-end is connected to. * * @return ServerInfo instance containing * information about the LinuxSampler instance the front-end is connected to. */ public ServerInfo getServerInfo() { return serverInfo; } /** * Sets information about the LinuxSampler instance the front-end is connected to. * * @param serverInfo ServerInfo instance containing * information about the LinuxSampler instance the front-end is connected to. */ public void setServerInfo(ServerInfo serverInfo) { this.serverInfo = serverInfo; } /** * Gets all audio output drivers currently available for the LinuxSampler instance. * * @return AudioOutputDriver array containing all audio output drivers * currently available for the LinuxSampler instance. */ public AudioOutputDriver[] getAudioOutputDrivers() { return aoDrvS; } /** * Sets the currently available audio output drivers for the LinuxSampler instance. * * @param drivers AudioOutputDriver array containing all audio output drivers * currently available for the LinuxSampler instance. */ public void setAudioOutputDrivers(AudioOutputDriver[] drivers) { aoDrvS = drivers; } /** * Gets the model of the audio device with ID deviceID. * @param deviceID The ID of the audio device whose model should be obtained. * @return The model of the specified audio device or null * if there is no audio device with ID deviceID. */ public AudioDeviceModel getAudioDeviceModel(int deviceID) { for(AudioDeviceModel m : audioDeviceModels) if(m.getDeviceID() == deviceID) return m; return null; } /** * Gets the current number of audio devices. * @return The current number of audio devices. */ public int getAudioDeviceCount() { return audioDeviceModels.size(); } /** * Gets the current list of audio device models. * @return The current list of audio device models. */ public AudioDeviceModel[] getAudioDeviceModels() { return audioDeviceModels.toArray(new AudioDeviceModel[audioDeviceModels.size()]); } /** * Adds the specified audio device. * @param device The audio device to be added. */ public void addAudioDevice(AudioOutputDevice device) { DefaultAudioDeviceModel model = new DefaultAudioDeviceModel(device); audioDeviceModels.add(model); fireAudioDeviceAdded(model); } /** * Removes the specified audio device. * @param deviceID The ID of the audio device to be removed. * @return true if the audio device is removed successfully, false * if the device list does not contain audio device with ID deviceID. */ public boolean removeAudioDevice(int deviceID) { for(int i = 0; i < audioDeviceModels.size(); i++) { AudioDeviceModel m = audioDeviceModels.get(i); if(m.getDeviceID() == deviceID) { audioDeviceModels.remove(i); fireAudioDeviceRemoved(m); return true; } } return false; } /** * Gets all MIDI input drivers currently available for the LinuxSampler instance. * * @return MidiInputDriver array containing all MIDI input drivers currently * available for the LinuxSampler instance. */ public MidiInputDriver[] getMidiInputDrivers() { return miDrvS; } /** * Sets the currently available MIDI input drivers for the LinuxSampler instance. * * @param drivers MidiInputDriver array containing all MIDI input drivers * currently available for the LinuxSampler instance. */ public void setMidiInputDrivers(MidiInputDriver[] drivers) { miDrvS = drivers; } /** * Gets the model of the MIDI device with ID deviceID. * @param deviceID The ID of the MIDI device whose model should be obtained. * @return The model of the specified MIDI device or null * if there is no MIDI device with ID deviceID. */ public MidiDeviceModel getMidiDeviceModel(int deviceID) { for(MidiDeviceModel m : midiDeviceModels) if(m.getDeviceID() == deviceID) return m; return null; } /** * Gets the current number of MIDI input devices. * @return The current number of MIDI input devices. */ public int getMidiDeviceCount() { return midiDeviceModels.size(); } /** * Gets the current list of MIDI device models. * @return The current list of MIDI device models. */ public MidiDeviceModel[] getMidiDeviceModels() { return midiDeviceModels.toArray(new MidiDeviceModel[midiDeviceModels.size()]); } /** * Adds the specified MIDI device. * @param device The MIDI device to be added. */ public void addMidiDevice(MidiInputDevice device) { DefaultMidiDeviceModel model = new DefaultMidiDeviceModel(device); midiDeviceModels.add(model); fireMidiDeviceAdded(model); } /** * Removes the specified MIDI device. * @param deviceID The ID of the MIDI device to be removed. * @return true if the MIDI device is removed successfully, false * if the device list does not contain MIDI device with ID deviceID. */ public boolean removeMidiDevice(int deviceID) { for(int i = 0; i < midiDeviceModels.size(); i++) { MidiDeviceModel m = midiDeviceModels.get(i); if(m.getDeviceID() == deviceID) { midiDeviceModels.remove(i); fireMidiDeviceRemoved(m); return true; } } return false; } /** * Gets a list of all available engines. * @return A list of all available engines. */ public SamplerEngine[] getEngines() { return engines; } /** * Sets the list of all available engines. * @param engines The new list of all available engines. */ public void setEngines(SamplerEngine[] engines) { this.engines = engines; } /** * Gets the model of the sampler channel with ID channelID. * @param channelID The ID of the sampler channel whose model should be obtained. * @return The model of the specified sampler channel or null * if there is no channel with ID channelID. */ public SamplerChannelModel getChannelModel(int channelID) { for(SamplerChannelModel m : channelModels) if(m.getChannelID() == channelID) return m; return null; } /** * Gets the current number of sampler channels. * @return The current number of sampler channels. */ public int getChannelCount() { return channelModels.size(); } /** * Gets the current list of sampler channel models. * @return The current list of sampler channel models. */ public SamplerChannelModel[] getChannelModels() { return channelModels.toArray(new SamplerChannelModel[channelModels.size()]); } /** * Creates a new sampler channel. The channel will be actually added to this model * when the back-end notifies for its creation. * @see #addChannel */ public void createChannel() { CC.getTaskQueue().add(new AddChannel()); // We leave this event to be notified by the LinuxSampler notification system. } /** * Adds the specified sampler channel. * @param channel The channel to be added. */ public void addChannel(SamplerChannel channel) { DefaultSamplerChannelModel model = new DefaultSamplerChannelModel(channel); channelModels.add(model); fireSamplerChannelAdded(model); } /** * Updates the settings of the specified channel. * @param channel A SamplerChannel instance containing the new settings * for the channel. */ public void changeChannel(SamplerChannel channel) { for(SamplerChannelModel m : channelModels) { if(m.getChannelID() == channel.getChannelID()) { m.setChannelInfo(channel); return; } } CC.getLogger().log ( Level.WARNING, "DefaultSamplerModel.unknownChannel!", channel.getChannelID() ); } /** * Removes the specified sampler channel. * @param channelID The ID of the channel to be removed. * @return true if the channel is removed successfully, false * if the channel's list does not contain channel with ID channelID. */ public boolean removeChannel(int channelID) { for(int i = 0; i < channelModels.size(); i++) { SamplerChannelModel m = channelModels.get(i); if(m.getChannelID() == channelID) { channelModels.remove(i); fireSamplerChannelRemoved(m); return true; } } return false; } /** * Determines whether there is at least one solo channel in the current list * of sampler channels. * @return true if there is at least one solo channel in the current list of * sampler channels, false otherwise. */ public boolean hasSoloChannel() { for(SamplerChannelModel m : channelModels) if(m.getChannelInfo().isSoloChannel()) return true; return false; } /** * Gets the number of solo channels in the current list of sampler channels. * @return The number of solo channels in the current list of sampler channels. */ public int getSoloChannelCount() { int count = 0; for(SamplerChannelModel m : channelModels) if(m.getChannelInfo().isSoloChannel()) count++; return count; } /** * Gets the number of muted channels in the current list of sampler channels. * This number includes the channels muted because of the presence of a solo channel. * @return The number of muted channels in the current list of sampler channels. */ public int getMutedChannelCount() { int count = 0; for(SamplerChannelModel m : channelModels) if(m.getChannelInfo().isMuted()) count++; return count; } /** * Gets the number of channels muted because of the presence of a solo channel. * @return The number of channels muted because of the presence of a solo channel. */ public int getMutedBySoloChannelCount() { int count = 0; for(SamplerChannelModel m : channelModels) if(m.getChannelInfo().isMutedBySolo()) count++; return count; } /** * Gets the total number of active voices. * @return The total number of active voices. */ public int getTotalVoiceCount() { return totalVoiceCount; } /** * Gets the maximum number of active voices. * @return The maximum number of active voices. */ public int getTotalVoiceCountMax() { return totalVoiceCountMax; } /** * Updates the current and the maximum number of active voices in the sampler. * @param count The new number of active voices. * @param countMax The maximum number of active voices. */ public void updateActiveVoiceInfo(int count, int countMax) { if(totalVoiceCount == count && totalVoiceCountMax == countMax) return; totalVoiceCount = count; totalVoiceCountMax = countMax; fireTotalVoiceCountChanged(); } /** * Notifies listeners that a sampler channel has been added. * @param channelModel A SamplerChannelModel instance. */ private void fireSamplerChannelAdded(SamplerChannelModel channelModel) { final SamplerChannelListEvent e = new SamplerChannelListEvent(this, channelModel); SwingUtilities.invokeLater(new Runnable() { public void run() { fireSamplerChannelAdded(e); } }); } /** * Notifies listeners that a sampler channel has been added. * This method should be invoked from the event-dispatching thread. */ private void fireSamplerChannelAdded(SamplerChannelListEvent e) { Object[] listeners = listenerList.getListenerList(); for(int i = listeners.length - 2; i >= 0; i -= 2) { if(listeners[i] == SamplerChannelListListener.class) { ((SamplerChannelListListener)listeners[i + 1]).channelAdded(e); } } } /** * Notifies listeners that a sampler channel has been removed. * @param channelModel A SamplerChannelModel instance. */ private void fireSamplerChannelRemoved(SamplerChannelModel channelModel) { final SamplerChannelListEvent e = new SamplerChannelListEvent(this, channelModel); SwingUtilities.invokeLater(new Runnable() { public void run() { fireSamplerChannelRemoved(e); } }); } /** * Notifies listeners that a sampler channel has been removed. * This method should be invoked from the event-dispatching thread. */ private void fireSamplerChannelRemoved(SamplerChannelListEvent e) { Object[] listeners = listenerList.getListenerList(); for(int i = listeners.length - 2; i >= 0; i -= 2) { if(listeners[i] == SamplerChannelListListener.class) { ((SamplerChannelListListener)listeners[i + 1]).channelRemoved(e); } } } /** * Notifies listeners that a MIDI device has been added. * @param model A MidiDeviceModel instance. */ private void fireMidiDeviceAdded(MidiDeviceModel model) { final MidiDeviceListEvent e = new MidiDeviceListEvent(this, model); SwingUtilities.invokeLater(new Runnable() { public void run() { fireMidiDeviceAdded(e); } }); } /** * Notifies listeners that a MIDI device has been added. * This method should be invoked from the event-dispatching thread. */ private void fireMidiDeviceAdded(MidiDeviceListEvent e) { Object[] listeners = listenerList.getListenerList(); for(int i = listeners.length - 2; i >= 0; i -= 2) { if(listeners[i] == MidiDeviceListListener.class) { ((MidiDeviceListListener)listeners[i + 1]).deviceAdded(e); } } } /** * Notifies listeners that a MIDI device has been removed. * @param model A MidiDeviceModel instance. */ private void fireMidiDeviceRemoved(MidiDeviceModel model) { final MidiDeviceListEvent e = new MidiDeviceListEvent(this, model); SwingUtilities.invokeLater(new Runnable() { public void run() { fireMidiDeviceRemoved(e); } }); } /** * Notifies listeners that a MIDI device has been removed. * This method should be invoked from the event-dispatching thread. */ private void fireMidiDeviceRemoved(MidiDeviceListEvent e) { Object[] listeners = listenerList.getListenerList(); for(int i = listeners.length - 2; i >= 0; i -= 2) { if(listeners[i] == MidiDeviceListListener.class) { ((MidiDeviceListListener)listeners[i + 1]).deviceRemoved(e); } } } /** * Notifies listeners that an audio device has been added. * @param model A AudioDeviceModel instance. */ private void fireAudioDeviceAdded(AudioDeviceModel model) { final AudioDeviceListEvent e = new AudioDeviceListEvent(this, model); SwingUtilities.invokeLater(new Runnable() { public void run() { fireAudioDeviceAdded(e); } }); } /** * Notifies listeners that an audio device has been added. * This method should be invoked from the event-dispatching thread. */ private void fireAudioDeviceAdded(AudioDeviceListEvent e) { Object[] listeners = listenerList.getListenerList(); for(int i = listeners.length - 2; i >= 0; i -= 2) { if(listeners[i] == AudioDeviceListListener.class) { ((AudioDeviceListListener)listeners[i + 1]).deviceAdded(e); } } } /** * Notifies listeners that an audio device has been removed. * @param model A AudioDeviceModel instance. */ private void fireAudioDeviceRemoved(AudioDeviceModel model) { final AudioDeviceListEvent e = new AudioDeviceListEvent(this, model); SwingUtilities.invokeLater(new Runnable() { public void run() { fireAudioDeviceRemoved(e); } }); } /** * Notifies listeners that an audio device has been removed. * This method should be invoked from the event-dispatching thread. */ private void fireAudioDeviceRemoved(AudioDeviceListEvent e) { Object[] listeners = listenerList.getListenerList(); for(int i = listeners.length - 2; i >= 0; i -= 2) { if(listeners[i] == AudioDeviceListListener.class) { ((AudioDeviceListListener)listeners[i + 1]).deviceRemoved(e); } } } /** Notifies listeners that the total number of active voices has changed. */ private void fireTotalVoiceCountChanged() { final SamplerEvent e = new SamplerEvent(this); SwingUtilities.invokeLater(new Runnable() { public void run() { fireTotalVoiceCountChanged(e); } }); } /** * Notifies listeners that the total number of active voices has changed. * This method should be invoked from the event-dispatching thread. */ private void fireTotalVoiceCountChanged(SamplerEvent e) { for(SamplerListener l : listeners) l.totalVoiceCountChanged(e); } }