content: /*!
   *  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.util.ArrayList;
  import java.util.Iterator;
  import javax.sound.midi.MidiDevice;
  import javax.sound.midi.MidiUnavailableException;
  import javax.sound.midi.Sequencer;
  import javax.sound.midi.Synthesizer;
  
  
  public class MIDIAccess {
      
      protected ArrayList<MIDIDevice> _inputs;
      protected ArrayList<MIDIDevice> _outputs;
      private ArrayList<MIDIDeviceInfo> _inputInfos;
      private ArrayList<MIDIDeviceInfo> _outputInfos;
      private ArrayList<MIDIDevice> _synths;
      private ArrayList<MIDIDevice> _sequencers;
      private ArrayList<MIDIDevice> _otherDevices;
      private AppletContext _context;
      
      private Object [] _inputInfosArray;
      private Object [] _outputInfosArray;
      
  
      public MIDIAccess(AppletContext context) {
          _context = context;
                  
          MidiDevice device;
          MidiDevice.Info[] infos = javax.sound.midi.MidiSystem.getMidiDeviceInfo();
          
          _inputs = new ArrayList<MIDIDevice>();
          _outputs = new ArrayList<MIDIDevice>();
          _inputInfos = new ArrayList<MIDIDeviceInfo>();
          _outputInfos = new ArrayList<MIDIDeviceInfo>();
          _synths = new ArrayList<MIDIDevice>();
          _sequencers = new ArrayList<MIDIDevice>();
          _otherDevices = new ArrayList<MIDIDevice>();
  
          for(int i = 0; i < infos.length; i++) {
                          
              try {
                  device = javax.sound.midi.MidiSystem.getMidiDevice(infos[i]);
              } catch (MidiUnavailableException e) {
                  System.out.println("could not get device " + infos[i]);
                  continue;
              }
              
              int numRecv = device.getMaxReceivers();
              int numTrans = device.getMaxTransmitters();
              MIDIDevice midiDevice;
              String type;
              Boolean available;
  
  
              if (numRecv == -1 && numTrans == -1) {
                  if (device instanceof Synthesizer) {
                      type = "synth";
                      available = checkDeviceAvailability(device);
                      if (available) {
                          _synths.add(new MIDIDevice(device,_synths.size(),type,_context));
                      }
                  } else if (device instanceof Sequencer) {
                      type = "sequencer";
                      available = checkDeviceAvailability(device);
                      if (available) {
                          _sequencers.add(new MIDIDevice(device,_sequencers.size(),type,_context));
                      }
                  } else {
                      type = "other";
                      available = checkDeviceAvailability(device);
                      if (available) {
                          _otherDevices.add(new MIDIDevice(device,_otherDevices.size(),type,_context));
                      }
                  }
              } else if (numRecv == 0) {
                  type = "input";
                  available = checkDeviceAvailability(device);
                  //System.out.println(device.getDeviceInfo().getName() + " " + available);
                  if (available) {
                      //System.out.println("adding input");
                      midiDevice = new MIDIDevice(device,_inputs.size(),type,_context); 
                      _inputs.add(midiDevice);
                      _inputInfos.add(midiDevice.info);
                  }
              } else if (numTrans == 0) {
                  type = "output";
                  available = checkDeviceAvailability(device);
                  if (available) {
                      //System.out.println("adding output");
                      midiDevice = new MIDIDevice(device,_outputs.size(),type,_context); 
                      _outputs.add(midiDevice);
                      _outputInfos.add(midiDevice.info);
                  }
              }
          }
          
          _inputInfosArray = _inputInfos.toArray();
          _outputInfosArray = _outputInfos.toArray();
      }
      
      public boolean closeInputs(){
          Iterator i = _inputs.iterator();
          while(i.hasNext()){
              MIDIDevice device = (MIDIDevice) i.next();
              device.close();
          }
          return true;
      }
  
      public boolean closeOutputs(){
          Iterator i = _outputs.iterator();
          while(i.hasNext()){
              MIDIDevice device = (MIDIDevice) i.next();
              device.close();
          }
          return true;
      }
  
      public MIDIDevice getInput(MIDIDeviceInfo info) {
          MIDIDevice device = _inputs.get(info.id);
          if(device.open()){
              return device;
          }
          return null;
      }
  
      public MIDIDevice getOutput(MIDIDeviceInfo info) {
          MIDIDevice device = _outputs.get(info.id);
          if(device.open()){
              return device;
          }
          return null;
      }
      
      public Object[] enumerateInputs(){
          return _inputInfosArray;
      }
  
      public Object[] enumerateOutputs(){
          return _outputInfosArray;
      }    
      
      public MIDIMessage createMIDIMessage(int command, int channel, int data1, int data2, int timeStamp){
          return new MIDIMessage(command,channel,data1,data2,Long.parseLong("" + timeStamp));
      }
  
      private boolean checkDeviceAvailability(MidiDevice device) {
          //if the device is currently in use, try to close it
          if (device.isOpen()) {
              try {
                  device.close();
                  return true;
              } catch (Exception e) {
                  System.out.println("MidiDevices.checkDevice() can not close device " + device.getDeviceInfo().getName() + " " + e);
                  return false;
              }
          }
          
          //if the device is not currently in use, try to open it
          try {
              device.open();
          } catch (MidiUnavailableException e) {
              System.out.println("MidiDevices.checkDevice() can not open device " + device.getDeviceInfo().getName() + " " + e);
              return false;
          }
          
          //device is available and can be opened, close it until we need it
          device.close();
  
          return true;
      }
  }
  