/*! * 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(); } }