/* * JSampler - a java front-end for LinuxSampler * * Copyright (C) 2005-2009 Grigor 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.task; import net.sf.juife.Task; import org.jsampler.CC; import org.jsampler.JSPrefs; import org.jsampler.SamplerChannelModel; import org.jsampler.SamplerModel; import org.linuxsampler.lscp.FxSend; import org.linuxsampler.lscp.event.MidiDataEvent; import static org.jsampler.JSI18n.i18n; import static org.jsampler.JSPrefs.*; /** * Provides the sampler channel's specific tasks. * @author Grigor Iliev */ public class Channel { /** Forbits the instantiation of this class. */ private Channel() { } /** * This task creates a new sampler channel.\ */ public static class Add extends EnhancedTask { /** Creates a new instance of Add. */ public Add() { setTitle("Channel.Add_task"); setDescription(i18n.getMessage("Channel.Add.desc")); } /** The entry point of the task. */ @Override public void exec() throws Exception { setResult(CC.getClient().addSamplerChannel()); int chnId = getResult(); JSPrefs p = CC.getViewConfig().preferences(); if(!p.getBoolProperty(USE_CHANNEL_DEFAULTS)) return; String s = p.getStringProperty(DEFAULT_ENGINE); if(s != null && s.length() > 0) { CC.getClient().loadSamplerEngine(s, chnId); } s = p.getStringProperty(DEFAULT_MIDI_INPUT); if(s != null && s.equals("firstDevice")) { assignFirstMidiDevice(); } else if(s != null && s.equals("firstDeviceNextChannel")) { assignFirstMidiDeviceNextChannel(); } s = p.getStringProperty(DEFAULT_AUDIO_OUTPUT); if(s != null && s.equals("firstDevice")) { assignFirstAudioDevice(); } s = p.getStringProperty(DEFAULT_MIDI_INSTRUMENT_MAP); if(s != null && s.equals("midiInstrumentMap.none")) { CC.getClient().setChannelMidiInstrumentMap(chnId, -1); } else if(s != null && s.equals("midiInstrumentMap.default")) { CC.getClient().setChannelMidiInstrumentMap(chnId, -2); } float volume = p.getIntProperty(DEFAULT_CHANNEL_VOLUME); volume /= 100; CC.getClient().setChannelVolume(chnId, volume); } private void assignFirstMidiDevice() throws Exception { if(CC.getSamplerModel().getMidiDeviceCount() < 1) return; int id = CC.getSamplerModel().getMidiDevices()[0].getDeviceId(); CC.getClient().setChannelMidiInputDevice(getResult(), id); } private void assignFirstMidiDeviceNextChannel() throws Exception { int channelId = getResult(); if(CC.getSamplerModel().getMidiDeviceCount() < 1) return; int id = CC.getSamplerModel().getMidiDevices()[0].getDeviceId(); CC.getClient().setChannelMidiInputDevice(channelId, id); boolean[] usedChannels = new boolean[16]; for(int i = 0; i < usedChannels.length; i++) usedChannels[i] = false; for(SamplerChannelModel m : CC.getSamplerModel().getChannels()) { if(m.getChannelId() == channelId) continue; if(m.getChannelInfo().getMidiInputDevice() != id) continue; if(m.getChannelInfo().getMidiInputPort() != 0) continue; int chn = m.getChannelInfo().getMidiInputChannel(); if(chn >= 0 && chn < 16) usedChannels[chn] = true; } int lastUsed = -1; for(int i = 0; i < usedChannels.length; i++) { if(usedChannels[i]) lastUsed = i; } if(lastUsed == -1) { CC.getClient().setChannelMidiInputChannel(channelId, 0); return; } if(lastUsed < 15) { CC.getClient().setChannelMidiInputChannel(channelId, lastUsed + 1); return; } int firstUnused = -1; for(int i = 0; i < usedChannels.length; i++) { if(!usedChannels[i]) { firstUnused = i; break; } } if(firstUnused == -1) { CC.getClient().setChannelMidiInputChannel(channelId, 0); return; } CC.getClient().setChannelMidiInputChannel(channelId, firstUnused); } private void assignFirstAudioDevice() throws Exception { if(CC.getSamplerModel().getAudioDeviceCount() < 1) return; int id = CC.getSamplerModel().getAudioDevices()[0].getDeviceId(); CC.getClient().setChannelAudioOutputDevice(getResult(), id); } } /** * This task removes the specified sampler channel. */ public static class Remove extends EnhancedTask { private int channel; /** * Creates new instance of Remove. * @param channel The numerical ID of the channel to remove. */ public Remove(int channel) { setTitle("Channel.Remove_task"); setDescription(i18n.getMessage("Channel.Remove.desc", channel)); this.channel = channel; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().removeSamplerChannel(channel); } } /** * This task resets the specified sampler channel. */ public static class Reset extends EnhancedTask { private int channel; /** * Creates new instance of Reset. * @param channel The numerical ID of the channel to reset. */ public Reset(int channel) { setTitle("Channel.Reset_task"); setDescription(i18n.getMessage("Channel.Reset.desc", channel)); this.channel = channel; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().resetChannel(channel); } } /** * This task sets an audio output channel of a specific sampler channel. */ public static class SetAudioOutputChannel extends EnhancedTask { private int chn; private int audioOut; private int audioIn; /** * Creates new instance of SetAudioOutputChannel. * @param channel The sampler channel number. * @param audioOut The sampler channel's audio output * channel which should be rerouted. * @param audioIn The audio channel of the selected audio output device where * audioOut should be routed to. */ public SetAudioOutputChannel(int channel, int audioOut, int audioIn) { setTitle("Channel.SetAudioOutputChannel_task"); String s = i18n.getMessage("Channel.SetAudioOutputChannel.desc", channel); setDescription(s); this.chn = channel; this.audioOut = audioOut; this.audioIn = audioIn; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setChannelAudioOutputChannel(chn, audioOut, audioIn); } } /** * This task sets the audio output device of a specific sampler channel. */ public static class SetAudioOutputDevice extends EnhancedTask { private int channel; private int deviceID; /** * Creates new instance of SetAudioOutputDevice. * @param channel The sampler channel number. * @param deviceID The numerical ID of the audio output device. */ public SetAudioOutputDevice(int channel, int deviceID) { setTitle("Channel.SetAudioOutputDevice_task"); String s = i18n.getMessage("Channel.SetAudioOutputDevice.desc", channel); setDescription(s); this.channel = channel; this.deviceID = deviceID; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setChannelAudioOutputDevice(channel, deviceID); } } /** * This task sets the MIDI input channel the specified sampler channel should listen to. */ public static class SetMidiInputChannel extends EnhancedTask { private int channel; private int midiChannel; /** * Creates new instance of SetMidiInputChannel. * @param channel The sampler channel number. * @param midiChannel The number of the new MIDI input channel where * channel should listen to or -1 to listen on all 16 MIDI channels. */ public SetMidiInputChannel(int channel, int midiChannel) { setTitle("Channel.SetMidiInputChannel_task"); String s = i18n.getMessage("Channel.SetMidiInputChannel.desc", channel); setDescription(s); this.channel = channel; this.midiChannel = midiChannel; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setChannelMidiInputChannel(channel, midiChannel); } } /** * This task sets the MIDI input device on a specific sampler channel. */ public static class SetMidiInputDevice extends EnhancedTask { private int channel; private int deviceID; /** * Creates new instance of SetMidiInputDevice. * @param channel The sampler channel number. * @param deviceID The numerical ID of the MIDI input device. */ public SetMidiInputDevice(int channel, int deviceID) { setTitle("Channel.SetMidiInputDevice_task"); String s = i18n.getMessage("Channel.SetMidiInputDevice.desc", channel); setDescription(s); this.channel = channel; this.deviceID = deviceID; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setChannelMidiInputDevice(channel, deviceID); } } /** * This task sets the MIDI input port of a specific sampler channel. */ public static class SetMidiInputPort extends EnhancedTask { private int channel; private int port; /** * Creates new instance of SetMidiInputPort. * @param channel The sampler channel number. * @param port The MIDI input port number * of the MIDI input device connected to the specified sampler channel. */ public SetMidiInputPort(int channel, int port) { setTitle("Channel.SetMidiInputPort_task"); setDescription(i18n.getMessage("Channel.SetMidiInputPort.desc", channel)); this.channel = channel; this.port = port; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setChannelMidiInputPort(channel, port); } } /** * This task loads a sampler engine in a specific sampler channel. */ public static class LoadEngine extends EnhancedTask { private String engine; private int channel; /** * Creates new instance of LoadEngine. * @param engine The name of the engine to load. * @param channel The number of the sampler channel * the deployed engine should be assigned to. */ public LoadEngine(String engine, int channel) { this.engine = engine; this.channel = channel; setTitle("Channel.LoadEngine_task"); Object[] objs = { engine, new Integer(channel) }; setDescription(i18n.getMessage("Channel.LoadEngine.desc", objs)); } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().loadSamplerEngine(engine, channel); } } /** * This task loads and assigns an instrument to a sampler channel. */ public static class LoadInstrument extends EnhancedTask { private String filename; private int instrIndex; private int channel; /** * Creates new instance of LoadInstrument. * @param filename The name of the instrument file * on the LinuxSampler instance's host system. * @param instrIndex The index of the instrument in the instrument file. * @param channel The number of the sampler channel the * instrument should be assigned to. */ public LoadInstrument(String filename, int instrIndex, int channel) { this.filename = filename; this.instrIndex = instrIndex; this.channel = channel; setTitle("Channel.LoadInstrument_task"); setDescription(i18n.getMessage("Channel.LoadInstrument.desc")); } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().loadInstrument(filename, instrIndex, channel, true); } } /** * This task assigns the specifed MIDI instrument map to the specified sampler channel. */ public static class SetMidiInstrumentMap extends EnhancedTask { private int channel; private int mapId; /** * Creates new instance of SetMidiInstrumentMap. * @param channel The sampler channel number. * @param mapId The numerical ID of the MIDI instrument * map that should be assigned to the specified sampler * channel or -1 to remove the current map binding. */ public SetMidiInstrumentMap(int channel, int mapId) { setTitle("Channel.SetMidiInstrumentMap_task"); String s = i18n.getMessage("Channel.SetMidiInstrumentMap.desc", channel); setDescription(s); this.channel = channel; this.mapId = mapId; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setChannelMidiInstrumentMap(channel, mapId); } } /** * This task mutes/unmutes a specific sampler channel. */ public static class SetMute extends EnhancedTask { private int channel; private boolean mute; /** * Creates new instance of SetMute. * @param channel The sampler channel to be muted/unmuted. * @param mute If true the specified channel is muted, * else the channel is unmuted. */ public SetMute(int channel, boolean mute) { setTitle("Channel.SetMute_task"); setDescription(i18n.getMessage("Channel.SetMute.desc", channel)); this.channel = channel; this.mute = mute; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setChannelMute(channel, mute); } } /** * This task solos/unsolos a specific sampler channel. */ public static class SetSolo extends EnhancedTask { private int channel; private boolean solo; /** * Creates new instance of SetSolo. * @param channel The sampler channel number. * @param solo Specify true to solo the specified channel, * false otherwise. */ public SetSolo(int channel, boolean solo) { setTitle("Channel.SetSolo_task"); setDescription(i18n.getMessage("Channel.SetSolo.desc", channel)); this.channel = channel; this.solo = solo; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setChannelSolo(channel, solo); } } /** * This taks sets the volume of a specific sampler channel. */ public static class SetVolume extends EnhancedTask { private int channel; private float volume; /** * Creates new instance of SetVolume. * @param channel The sampler channel number. * @param volume The new volume value. */ public SetVolume(int channel, float volume) { setTitle("Channel.SetVolume_task"); setDescription(i18n.getMessage("Channel.SetVolume.desc", channel)); this.channel = channel; this.volume = volume; } /** The entry point of the task. */ @Override public void exec() throws Exception { /* * Because of the rapid flow of volume change tasks in some cases * we need to do some optimization to decrease the traffic. */ boolean b = true; Task[] tS = CC.getTaskQueue().getPendingTasks(); for(int i = tS.length - 1; i >= 0; i--) { Task t = tS[i]; if(t instanceof SetVolume) { SetVolume scv = (SetVolume)t; if(scv.getChannelId() == channel) { CC.getTaskQueue().removeTask(scv); } } } CC.getClient().setChannelVolume(channel, volume); } /** * Gets the ID of the channel whose volume should be changed. * @return The ID of the channel whose volume should be changed. */ public int getChannelId() { return channel; } } /** * This task updates the settings of a specific sampler channel. */ public static class UpdateInfo extends EnhancedTask { private int channel; /** * Creates new instance of UpdateInfo. * @param channel The sampler channel to be updated. */ public UpdateInfo(int channel) { setTitle("Channel.UpdateInfo_task"); setDescription(i18n.getMessage("Channel.UpdateInfo.desc")); this.channel = channel; } /** The entry point of the task. */ @Override public void exec() throws Exception { /* * We don't want to bother the user if error occurs when updating * a channel because in most cases this happens due to a race * condition between delete/update events. So we just log this * error instead to indicate the failure of this task. */ setSilent(true); SamplerModel sm = CC.getSamplerModel(); sm.updateChannel(CC.getClient().getSamplerChannelInfo(channel)); } /** * Gets the ID of the channel for which information should be obtained. * @return The ID of the channel for which information should be obtained. */ public int getChannelId() { return channel; } } /** * This task creates an additional effect send on the specified sampler channel. */ public static class AddFxSend extends EnhancedTask { private int channel; private int midiCtrl; private String name; /** * Creates a new instance of AddFxSend. * @param channel The sampler channel, on which a new effect send should be added. * @param midiCtrl Defines the MIDI controller, which * will be able alter the effect send level. */ public AddFxSend(int channel, int midiCtrl) { this(channel, midiCtrl, null); } /** * Creates a new instance of AddFxSend. * @param channel The sampler channel, on which a new effect send should be added. * @param midiCtrl Defines the MIDI controller, which * will be able alter the effect send level. * @param name The name of the effect send entity. * The name does not have to be unique. */ public AddFxSend(int channel, int midiCtrl, String name) { setTitle("Channel.AddFxSend_task"); setDescription(i18n.getMessage("Channel.AddFxSend.desc")); this.channel = channel; this.midiCtrl = midiCtrl; this.name = name; } /** The entry point of the task. */ @Override public void exec() throws Exception { setResult(CC.getClient().createFxSend(channel, midiCtrl, name)); } } /** * This task removes the specified effect send on the specified sampler channel. */ public static class RemoveFxSend extends EnhancedTask { private int channel; private int fxSend; /** * Creates a new instance of RemoveFxSend. * @param channel The sampler channel, from which an effect send should be removed. * @param fxSend The ID of the effect send that should be removed. */ public RemoveFxSend(int channel, int fxSend) { setTitle("Channel.RemoveFxSend_task"); String s = i18n.getMessage("Channel.RemoveFxSend.desc", channel, fxSend); setDescription(s); this.channel = channel; this.fxSend = fxSend; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().destroyFxSend(channel, fxSend); } } /** * This task gets the list of effect sends on the specified sampler channel. */ public static class GetFxSends extends EnhancedTask { private int channel; /** * Creates a new instance of GetFxSends. */ public GetFxSends() { this(-1); } /** * Creates a new instance of GetFxSends. */ public GetFxSends(int channel) { setTitle("Channel.GetFxSends_task"); setDescription(i18n.getMessage("Channel.GetFxSends.desc", channel)); this.channel = channel; } /** The entry point of the task. */ @Override public void exec() throws Exception { setResult(CC.getClient().getFxSends(channel)); } /** * Gets the channel ID. */ public int getChannel() { return channel; } /** * Sets the channel, for which effect sends should be obtained. */ public void setChannel(int channel) { this.channel = channel; setDescription(i18n.getMessage("Channel.GetFxSends.desc", channel)); } } /** * This task updates the list of effect sends on the specified sampler channel. */ public static class UpdateFxSends extends EnhancedTask { private int channel; /** * Creates a new instance of UpdateFxSends. * @param channel The numerical ID of the sampler channel * whose effect send list should be updated. */ public UpdateFxSends(int channel) { setTitle("Channel.UpdateFxSends_task"); setDescription(i18n.getMessage("Channel.UpdateFxSends.desc", channel)); this.channel = channel; } /** The entry point of the task. */ @Override public void exec() throws Exception { SamplerChannelModel scm; scm = CC.getSamplerModel().getChannelById(channel); Integer[] fxSendIDs = CC.getClient().getFxSendIDs(channel); boolean found = false; for(FxSend fxs : scm.getFxSends()) { for(int i = 0; i < fxSendIDs.length; i++) { if(fxSendIDs[i] == fxs.getFxSendId()) { fxSendIDs[i] = -1; found = true; } } if(!found) scm.removeFxSendById(fxs.getFxSendId()); found = false; } FxSend fxs; for(int id : fxSendIDs) { if(id >= 0) { fxs = CC.getClient().getFxSendInfo(channel, id); scm.addFxSend(fxs); } } } } /** * This task updates the settings of a specific effect send. */ public static class UpdateFxSendInfo extends EnhancedTask { private int channel; private int fxSend; /** * Creates new instance of UpdateFxSendInfo. * @param channel The numerical ID of the sampler channel * containing the effect send entity that should be updated. * @param fxSend The numerical ID of the effect send * that should be updated. */ public UpdateFxSendInfo(int channel, int fxSend) { setTitle("Channel.UpdateFxSendInfo_task"); String s = "Channel.UpdateFxSendInfo.desc"; setDescription(i18n.getMessage(s, channel, fxSend)); this.channel = channel; this.fxSend = fxSend; } /** The entry point of the task. */ @Override public void exec() throws Exception { /* * We don't want to bother the user if error occurs when updating * an effect send because in most cases this happens due to a race * condition between delete/update events. So we just log this * error instead to indicate the failure of this task. */ setSilent(true); SamplerChannelModel scm; scm = CC.getSamplerModel().getChannelById(channel); scm.updateFxSend(CC.getClient().getFxSendInfo(channel, fxSend)); } } /** * This taks changes the name of a specific effect send. */ public static class SetFxSendName extends EnhancedTask { private int channel; private int fxSend; private String name; /** * Creates new instance of SetFxSendName. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect * send, which name should be changed. * @param name The new name of the effect send entity. */ public SetFxSendName(int channel, int fxSend, String name) { setTitle("Channel.SetFxSendName_task"); String s = "Channel.SetFxSendName.desc"; setDescription(i18n.getMessage(s, channel, fxSend)); this.channel = channel; this.fxSend = fxSend; this.name = name; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setFxSendName(channel, fxSend, name); } } /** * This taks sets the MIDI controller of a specific effect send. */ public static class SetFxSendAudioOutputChannel extends EnhancedTask { private int channel; private int fxSend; private int audioSrc; private int audioDst; /** * Creates new instance of SetFxSendAudioOutputChannel. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect send entity to be rerouted. * @param audioSrc The numerical ID of the effect send's audio output channel, * which should be rerouted. * @param audioDst The audio channel of the selected audio output device * where audioSrc should be routed to. */ public SetFxSendAudioOutputChannel(int channel, int fxSend, int audioSrc, int audioDst) { setTitle("Channel.SetFxSendAudioOutputChannel_task"); String s = "Channel.SetFxSendAudioOutputChannel.desc"; setDescription(i18n.getMessage(s, channel, fxSend)); this.channel = channel; this.fxSend = fxSend; this.audioSrc = audioSrc; this.audioDst = audioDst; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setFxSendAudioOutputChannel ( channel, fxSend, audioSrc, audioDst ); } } /** * This taks sets the volume of a specific effect send. */ public static class SetFxSendLevel extends EnhancedTask { private int channel; private int fxSend; private float volume; /** * Creates new instance of SetFxSendLevel. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect send, which * volume should be changed. * @param volume The new volume value. */ public SetFxSendLevel(int channel, int fxSend, float volume) { setTitle("Channel.SetFxSendLevel_task"); String s = i18n.getMessage("Channel.SetFxSendLevel.desc", channel, fxSend); setDescription(s); this.channel = channel; this.fxSend = fxSend; this.volume = volume; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setFxSendLevel(channel, fxSend, volume); } } /** * This taks sets the MIDI controller of a specific effect send. */ public static class SetFxSendMidiController extends EnhancedTask { private int channel; private int fxSend; private int midiCtrl; /** * Creates new instance of SetFxSendMidiController. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect * send, which MIDI controller should be changed. * @param midiCtrl The MIDI controller which shall be * able to modify the effect send's send level. */ public SetFxSendMidiController(int channel, int fxSend, int midiCtrl) { setTitle("Channel.SetFxSendMidiController_task"); String s = "Channel.SetFxSendMidiController.desc"; setDescription(i18n.getMessage(s, channel, fxSend)); this.channel = channel; this.fxSend = fxSend; this.midiCtrl = midiCtrl; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().setFxSendMidiController(channel, fxSend, midiCtrl); } } /** * This task starts an instrument editor for editing the loaded instrument * on the specified sampler channel. */ public static class EditInstrument extends EnhancedTask { private int chn; /** * Creates new instance of EditInstrument. * @param channel The sampler channel number. */ public EditInstrument(int channel) { setTitle("Channel.EditInstrument_task"); String s = i18n.getMessage("Channel.EditInstrument.desc"); setDescription(s); this.chn = channel; } /** The entry point of the task. */ @Override public void exec() throws Exception { CC.getClient().editChannelInstrument(chn); } } /** * This task starts an instrument editor for editing the loaded instrument * on the specified sampler channel. */ public static class SendMidiMsg extends EnhancedTask { private int chn; private MidiDataEvent.Type type; private int arg1; private int arg2; /** * Creates new instance of SendMidiMsg. * @param channel The sampler channel number. */ public SendMidiMsg(int channel, MidiDataEvent.Type type, int arg1, int arg2) { this.chn = channel; this.type = type; this.arg1 = arg1; this.arg2 = arg2; setTitle("Channel.SendMidiMsg_task"); String s = i18n.getMessage("Channel.SendMidiMsg.desc", channel); setDescription(s); } /** The entry point of the task. */ @Override public void exec() throws Exception { setSilent(true); CC.getClient().sendChannelMidiData(chn, type, arg1, arg2); } } }