/*!
* copyright 2012 abudaan http://abumarkub.net
* code licensed under MIT
* http://abumarkub.net/midibridge/license
*
*
*
*/
package net.abumarkub.midi;
import java.applet.AppletContext;
import java.net.MalformedURLException;
import java.net.URL;
import javax.sound.midi.*;
import netscape.javascript.JSObject;
public class MIDIDevice implements Receiver {
private MidiDevice _device;
private MidiDevice.Info _deviceInfo;
private Receiver _receiver;
private Transmitter _transmitter;
private Transmitter _transmitter2;
public MIDIDeviceInfo info;
private AppletContext _context;
private JSObject _jsEventListener;
public int id;
public String deviceType;
public String deviceName;
public String deviceManufacturer;
public String deviceVersion;
public String deviceDescription;
public MIDIDevice(MidiDevice device, int index, String type, AppletContext context) {
_device = device;
_deviceInfo = device.getDeviceInfo();
_context = context;
info = new MIDIDeviceInfo(index, type, _deviceInfo);
id = index;
deviceType = type;
deviceName = info.deviceName;
deviceManufacturer = info.deviceManufacturer;
deviceVersion = info.deviceVersion;
deviceDescription = info.deviceDescription;
System.out.println("[" + type + "]" + info.deviceName);
_receiver = null;
_transmitter = null;
_transmitter2 = null;
}
//sending messages from Java to Javascript is faster via AppletContext then via Live Connect
private void sendMessageViaContext(String url) {
try {
_context.showDocument(new URL(url));
} catch (MalformedURLException me) {
System.out.println(me);
} catch (Exception e) {
System.out.println(e);
}
}
@Override
public void close() {
if (_receiver != null) {
_receiver.close();
}
if (_transmitter != null) {
_transmitter.close();
}
if (_transmitter2 != null) {
_transmitter2.close();
}
if (_device.isOpen()) {
_device.close();
}
}
public boolean open() {
if (!_device.isOpen()) {
try {
_device.open();
} catch (MidiUnavailableException e) {
System.out.println("error opening device: " + e);
return false;
}
}
if (info.deviceType.equals("input")) {
try {
_transmitter = _device.getTransmitter();
_transmitter.setReceiver(this);
} catch (MidiUnavailableException e) {
System.out.println("error getting transmitter: " + e);
return false;
}
} else if (info.deviceType.equals("output")) {
try {
_receiver = _device.getReceiver();
} catch (MidiUnavailableException e) {
System.out.println("error getting receiver: " + e);
return false;
}
}
return true;
}
public boolean addEventListener(String id) {
if(deviceType.equals("output")){
System.out.println("Can not add eventlistener to an output");
return false;
}
if (id.equals("midimessage")) {
if (_transmitter == null) {
try {
_transmitter = _device.getTransmitter();
} catch (MidiUnavailableException e) {
System.out.println("Device " + deviceName + " could not open a transmitter " + e);
return false;
}
}
_transmitter.setReceiver(this);
return true;
}
return false;
}
//@TODO: currently you can connect only 1 eventlistener!
public boolean addEventListener(String id, JSObject eventListener) {
_jsEventListener = eventListener;
if(deviceType.equals("output")){
System.out.println("Can not add eventlistener to an output");
return false;
}
if (id.equals("midimessage")) {
if (_transmitter == null) {
try {
_transmitter = _device.getTransmitter();
} catch (MidiUnavailableException e) {
System.out.println("Device " + deviceName + " could not open a transmitter " + e);
return false;
}
}
_transmitter.setReceiver(this);
return true;
}
return false;
}
public boolean setDirectOutput(MIDIDevice device) {
if(deviceType.equals("output")){
System.out.println("Can not add an output to an output!");
return false;
}
System.out.println("setDirectOutput: " + device.deviceName);
if (_receiver != null) {
_receiver.close();
}
_receiver = device.getReceiver();
if (_receiver == null) {
return false;
}
if (_transmitter2 == null) {
try {
_transmitter2 = _device.getTransmitter();
} catch (MidiUnavailableException e) {
System.out.println("Device " + deviceName + " could not open a transmitter " + e);
return false;
}
}
_transmitter2.setReceiver(_receiver);
return true;
}
public void removeDirectOutput() {
if (_transmitter2 != null) {
_transmitter2.close();
}
if (_receiver != null) {
_receiver.close();
}
_transmitter2 = null;
_receiver = null;
}
public boolean hasDirectOutput() {
return _receiver != null;
}
public MidiDevice getDevice() {
return _device;
}
public Receiver getReceiver() {
return _receiver;
}
public Transmitter getTransmitter() {
return _transmitter;
}
public boolean sendMIDIMessage(MIDIMessage message) {
if(deviceType.equals("input")){
System.out.println("Can not send a MIDI message to an input!");
return false;
}
//System.out.println("sendMIDIMessage:" + message.command);
ShortMessage sm = new ShortMessage();
try {
sm.setMessage(message.command, message.channel, message.data1, message.data2);
_receiver.send(sm, message.timeStamp);
} catch (InvalidMidiDataException e) {
System.out.println("error sending MIDI message: " + e);
return false;
} catch (NullPointerException e) {
System.out.println("error sending MIDI message: " + e);
return false;
}
return true;
}
public boolean sendMIDIMessage(int command, int channel, int data1, int data2, int timeStamp) {
if(deviceType.equals("input")){
System.out.println("Can not send a MIDI message to an input!");
return false;
}
//System.out.println("sendMIDIMessage:" + message.command);
ShortMessage sm = new ShortMessage();
try {
sm.setMessage(command, channel, data1, data2);
_receiver.send(sm, timeStamp);
} catch (InvalidMidiDataException e) {
System.out.println("error sending MIDI message: " + e);
return false;
} catch (NullPointerException e) {
System.out.println("error sending MIDI message: " + e);
return false;
}
return true;
}
@Override
public void send(MidiMessage message, long timeStamp) {
//System.out.println(message.toString() + " " + _eventListener);
if (message instanceof ShortMessage) {
ShortMessage tmp = (ShortMessage) message;
MIDIMessage msg = new MIDIMessage(tmp, timeStamp);
//@TODO: loop over all event listeners, check if they want to be updated via AppletContext or Live Connect, and dispatch to all
if(1 == 2){//just a way of ignoring the AppletContext send method
String jsMsg = id + "," + msg.command + "," + msg.channel + "," + msg.data1 + "," + msg.data2 + "," + timeStamp + ",'" + msg.toString() + "'";
sendMessageViaContext("javascript:midiBridge.onMIDIData(" + jsMsg + ")");
}else{//currently sending via Live Connect is preferred
Object[] args = {msg};
_jsEventListener.call("listener",args);
}
}
}
@Override
public String toString() {
return info.toString();
}
}