Source for gnu.javax.sound.midi.dssi.DSSISynthesizer

   1: /* DSSISynthesizer.java -- DSSI Synthesizer Provider
   2:    Copyright (C) 2005, 2006 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.javax.sound.midi.dssi;
  40: 
  41: import java.util.ArrayList;
  42: import java.util.Iterator;
  43: import java.util.List;
  44: 
  45: import javax.sound.midi.Instrument;
  46: import javax.sound.midi.MidiChannel;
  47: import javax.sound.midi.MidiMessage;
  48: import javax.sound.midi.MidiUnavailableException;
  49: import javax.sound.midi.Patch;
  50: import javax.sound.midi.Receiver;
  51: import javax.sound.midi.ShortMessage;
  52: import javax.sound.midi.Soundbank;
  53: import javax.sound.midi.SoundbankResource;
  54: import javax.sound.midi.Synthesizer;
  55: import javax.sound.midi.Transmitter;
  56: import javax.sound.midi.VoiceStatus;
  57: 
  58: /**
  59:  * DSSI soft-synth support.
  60:  *
  61:  * All DSSI soft-synths are expected to be installed in /usr/lib/dssi.
  62:  *
  63:  * @author Anthony Green (green@redhat.com)
  64:  *
  65:  */
  66: public class DSSISynthesizer implements Synthesizer
  67: {
  68:   /**
  69:    * The DSSI Instrument class.
  70:    *
  71:    * @author Anthony Green (green@redhat.com)
  72:    *
  73:    */
  74:   class DSSIInstrument extends Instrument
  75:   {
  76:     DSSIInstrument (Soundbank soundbank, Patch patch, String name)
  77:     {
  78:       super (soundbank, patch, name, null);
  79:     }
  80: 
  81:     /* @see javax.sound.midi.SoundbankResource#getData()
  82:      */
  83:     public Object getData()
  84:     {
  85:       return null;
  86:     }
  87: 
  88:   }
  89: 
  90: /**
  91:    * DSSISoundbank holds all instruments.
  92:    *
  93:    * @author Anthony Green (green@redhat.com)
  94:    *
  95:    */
  96:   class DSSISoundbank implements Soundbank
  97:   {
  98:     private String name;
  99:     private String description;
 100:     private List instruments = new ArrayList();
 101:     private List resources = new ArrayList();
 102:     private String vendor;
 103:     private String version;
 104: 
 105:     public DSSISoundbank(String name, String description, String vendor, String version)
 106:     {
 107:       this.name = name;
 108:       this.description = description;
 109:       this.vendor = vendor;
 110:       this.version = version;
 111:     }
 112: 
 113:     void add(Instrument instrument)
 114:     {
 115:       instruments.add(instrument);
 116:     }
 117: 
 118:     /* @see javax.sound.midi.Soundbank#getName()
 119:      */
 120:     public String getName()
 121:     {
 122:       return name;
 123:     }
 124: 
 125:     /* @see javax.sound.midi.Soundbank#getVersion()
 126:      */
 127:     public String getVersion()
 128:     {
 129:       return version;
 130:     }
 131: 
 132:     /* @see javax.sound.midi.Soundbank#getVendor()
 133:      */
 134:     public String getVendor()
 135:     {
 136:       return vendor;
 137:     }
 138: 
 139:     /* @see javax.sound.midi.Soundbank#getDescription()
 140:      */
 141:     public String getDescription()
 142:     {
 143:       return description;
 144:     }
 145: 
 146:     /* @see javax.sound.midi.Soundbank#getResources()
 147:      */
 148:     public SoundbankResource[] getResources()
 149:     {
 150:       return (SoundbankResource[])
 151:         resources.toArray(new SoundbankResource[resources.size()]);
 152:     }
 153: 
 154:     /* @see javax.sound.midi.Soundbank#getInstruments()
 155:      */
 156:     public Instrument[] getInstruments()
 157:     {
 158:       return (Instrument[])
 159:         instruments.toArray(new Instrument[instruments.size()]);
 160:     }
 161: 
 162:     /* @see javax.sound.midi.Soundbank#getInstrument(javax.sound.midi.Patch)
 163:      */
 164:     public Instrument getInstrument(Patch patch)
 165:     {
 166:       Iterator itr = instruments.iterator();
 167: 
 168:       while (itr.hasNext())
 169:       {
 170:         Instrument i = (Instrument) itr.next();
 171:         if (i.getPatch().equals(patch))
 172:           return i;
 173:       }
 174: 
 175:       return null;
 176:     }
 177:   }
 178: 
 179: /**
 180:    * The Receiver class receives all MIDI messages from a connected
 181:    * Transmitter.
 182:    *
 183:    * @author Anthony Green (green@redhat.com)
 184:    *
 185:    */
 186:   class DSSIReceiver implements Receiver
 187:   {
 188:     /* (non-Javadoc)
 189:      * @see javax.sound.midi.Receiver#send(javax.sound.midi.MidiMessage, long)
 190:      */
 191:     public void send(MidiMessage message, long timeStamp)
 192:         throws IllegalStateException
 193:     {
 194:       if (message instanceof ShortMessage)
 195:       {
 196:         ShortMessage smessage = (ShortMessage) message;
 197: 
 198:         switch (message.getStatus())
 199:         {
 200:         case ShortMessage.NOTE_ON:
 201:           int velocity = smessage.getData2();
 202:           if (velocity > 0)
 203:             channels[smessage.getChannel()].noteOn(smessage.getData1(),
 204:                                                    smessage.getData2());
 205:           else
 206:             channels[smessage.getChannel()].noteOff(smessage.getData1());
 207:           break;
 208:         case ShortMessage.CONTROL_CHANGE:
 209:           channels[smessage.getChannel()].controlChange(smessage.getData1(),
 210:                                                         smessage.getData2());
 211:           break;
 212:         default:
 213:           System.out.println ("Unhandled message: " + message.getStatus());
 214:           break;
 215:         }
 216:       }
 217:     }
 218: 
 219:     /* (non-Javadoc)
 220:      * @see javax.sound.midi.Receiver#close()
 221:      */
 222:     public void close()
 223:     {
 224:       // TODO Auto-generated method stub
 225:     }
 226: 
 227:   }
 228: 
 229:   static native void noteOn_(long handle, int channel, int noteNumber, int velocity);
 230:   static native void noteOff_(long handle, int channel, int noteNumber, int velocity);
 231:   static native void setPolyPressure_(long handle, int channel, int noteNumber, int pressure);
 232:   static native int getPolyPressure_(long handle, int channel, int noteNumber);
 233:   static native void controlChange_(long handle, int channel, int control, int value);
 234:   static native void open_(long handle);
 235:   static native void close_(long handle);
 236:   static native String getProgramName_(long handle, int index);
 237:   static native int getProgramBank_(long handle, int index);
 238:   static native int getProgramProgram_(long handle, int index);
 239:   static native void selectProgram_(long handle, int bank, int program);
 240: 
 241:   /**
 242:    * @author Anthony Green (green@redhat.com)
 243:    *
 244:    */
 245:   public class DSSIMidiChannel implements MidiChannel
 246:   {
 247:     int channel = 0;
 248: 
 249:     /**
 250:      * Default contructor.
 251:      */
 252:     public DSSIMidiChannel(int channel)
 253:     {
 254:       super();
 255:       this.channel = channel;
 256:     }
 257: 
 258:     /* (non-Javadoc)
 259:      * @see javax.sound.midi.MidiChannel#noteOn(int, int)
 260:      */
 261:     public void noteOn(int noteNumber, int velocity)
 262:     {
 263:       noteOn_(sohandle, channel, noteNumber, velocity);
 264:     }
 265: 
 266:     /* (non-Javadoc)
 267:      * @see javax.sound.midi.MidiChannel#noteOff(int, int)
 268:      */
 269:     public void noteOff(int noteNumber, int velocity)
 270:     {
 271:       noteOff_(sohandle, channel, noteNumber, velocity);
 272:     }
 273: 
 274:     /* (non-Javadoc)
 275:      * @see javax.sound.midi.MidiChannel#noteOff(int)
 276:      */
 277:     public void noteOff(int noteNumber)
 278:     {
 279:       noteOff_(sohandle, channel, noteNumber, -1);
 280:     }
 281: 
 282:     /* (non-Javadoc)
 283:      * @see javax.sound.midi.MidiChannel#setPolyPressure(int, int)
 284:      */
 285:     public void setPolyPressure(int noteNumber, int pressure)
 286:     {
 287:       setPolyPressure_(sohandle, channel, noteNumber, pressure);
 288:     }
 289: 
 290:     /* (non-Javadoc)
 291:      * @see javax.sound.midi.MidiChannel#getPolyPressure(int)
 292:      */
 293:     public int getPolyPressure(int noteNumber)
 294:     {
 295:       return getPolyPressure_(sohandle, channel, noteNumber);
 296:     }
 297: 
 298:     /* (non-Javadoc)
 299:      * @see javax.sound.midi.MidiChannel#setChannelPressure(int)
 300:      */
 301:     public void setChannelPressure(int pressure)
 302:     {
 303:       // TODO Auto-generated method stub
 304: 
 305:     }
 306: 
 307:     /* (non-Javadoc)
 308:      * @see javax.sound.midi.MidiChannel#getChannelPressure()
 309:      */
 310:     public int getChannelPressure()
 311:     {
 312:       // TODO Auto-generated method stub
 313:       return 0;
 314:     }
 315: 
 316:     /* @see javax.sound.midi.MidiChannel#controlChange(int, int)  */
 317:     public void controlChange(int controller, int value)
 318:     {
 319:       controlChange_(sohandle, channel, controller, value);
 320:     }
 321: 
 322:     /* (non-Javadoc)
 323:      * @see javax.sound.midi.MidiChannel#getController(int)
 324:      */
 325:     public int getController(int controller)
 326:     {
 327:       // TODO Auto-generated method stub
 328:       return 0;
 329:     }
 330: 
 331:     /* (non-Javadoc)
 332:      * @see javax.sound.midi.MidiChannel#programChange(int)
 333:      */
 334:     public void programChange(int program)
 335:     {
 336:       // TODO Auto-generated method stub
 337: 
 338:     }
 339: 
 340:     /* (non-Javadoc)
 341:      * @see javax.sound.midi.MidiChannel#programChange(int, int)
 342:      */
 343:     public void programChange(int bank, int program)
 344:     {
 345:       // TODO Auto-generated method stub
 346: 
 347:     }
 348: 
 349:     /* (non-Javadoc)
 350:      * @see javax.sound.midi.MidiChannel#getProgram()
 351:      */
 352:     public int getProgram()
 353:     {
 354:       // TODO Auto-generated method stub
 355:       return 0;
 356:     }
 357: 
 358:     /* (non-Javadoc)
 359:      * @see javax.sound.midi.MidiChannel#setPitchBend(int)
 360:      */
 361:     public void setPitchBend(int bend)
 362:     {
 363:       // TODO Auto-generated method stub
 364: 
 365:     }
 366: 
 367:     /* (non-Javadoc)
 368:      * @see javax.sound.midi.MidiChannel#getPitchBend()
 369:      */
 370:     public int getPitchBend()
 371:     {
 372:       // TODO Auto-generated method stub
 373:       return 0;
 374:     }
 375: 
 376:     /* (non-Javadoc)
 377:      * @see javax.sound.midi.MidiChannel#resetAllControllers()
 378:      */
 379:     public void resetAllControllers()
 380:     {
 381:       // TODO Auto-generated method stub
 382: 
 383:     }
 384: 
 385:     /* (non-Javadoc)
 386:      * @see javax.sound.midi.MidiChannel#allNotesOff()
 387:      */
 388:     public void allNotesOff()
 389:     {
 390:       // TODO Auto-generated method stub
 391: 
 392:     }
 393: 
 394:     /* (non-Javadoc)
 395:      * @see javax.sound.midi.MidiChannel#allSoundOff()
 396:      */
 397:     public void allSoundOff()
 398:     {
 399:       // TODO Auto-generated method stub
 400: 
 401:     }
 402: 
 403:     /* (non-Javadoc)
 404:      * @see javax.sound.midi.MidiChannel#localControl(boolean)
 405:      */
 406:     public boolean localControl(boolean on)
 407:     {
 408:       // TODO Auto-generated method stub
 409:       return false;
 410:     }
 411: 
 412:     /* (non-Javadoc)
 413:      * @see javax.sound.midi.MidiChannel#setMono(boolean)
 414:      */
 415:     public void setMono(boolean on)
 416:     {
 417:       // TODO Auto-generated method stub
 418: 
 419:     }
 420: 
 421:     /* (non-Javadoc)
 422:      * @see javax.sound.midi.MidiChannel#getMono()
 423:      */
 424:     public boolean getMono()
 425:     {
 426:       // TODO Auto-generated method stub
 427:       return false;
 428:     }
 429: 
 430:     /* (non-Javadoc)
 431:      * @see javax.sound.midi.MidiChannel#setOmni(boolean)
 432:      */
 433:     public void setOmni(boolean on)
 434:     {
 435:       // TODO Auto-generated method stub
 436: 
 437:     }
 438: 
 439:     /* (non-Javadoc)
 440:      * @see javax.sound.midi.MidiChannel#getOmni()
 441:      */
 442:     public boolean getOmni()
 443:     {
 444:       // TODO Auto-generated method stub
 445:       return false;
 446:     }
 447: 
 448:     /* (non-Javadoc)
 449:      * @see javax.sound.midi.MidiChannel#setMute(boolean)
 450:      */
 451:     public void setMute(boolean mute)
 452:     {
 453:       // TODO Auto-generated method stub
 454: 
 455:     }
 456: 
 457:     /* (non-Javadoc)
 458:      * @see javax.sound.midi.MidiChannel#getMute()
 459:      */
 460:     public boolean getMute()
 461:     {
 462:       // TODO Auto-generated method stub
 463:       return false;
 464:     }
 465: 
 466:     /* (non-Javadoc)
 467:      * @see javax.sound.midi.MidiChannel#setSolo(boolean)
 468:      */
 469:     public void setSolo(boolean solo)
 470:     {
 471:       // TODO Auto-generated method stub
 472: 
 473:     }
 474: 
 475:     /* (non-Javadoc)
 476:      * @see javax.sound.midi.MidiChannel#getSolo()
 477:      */
 478:     public boolean getSolo()
 479:     {
 480:       // TODO Auto-generated method stub
 481:       return false;
 482:     }
 483: 
 484:   }
 485: 
 486:   long sohandle;
 487:   long handle;
 488:   private Info info;
 489: 
 490:   MidiChannel channels[] = new MidiChannel[16];
 491: 
 492:   // The list of known soundbanks, and the default one.
 493:   List soundbanks = new ArrayList();
 494:   DSSISoundbank defaultSoundbank;
 495: 
 496:   /**
 497:    * Create a DSSI Synthesizer.
 498:    *
 499:    * @param info the DSSIInfo for this soft-synth
 500:    * @param soname the name of the .so file for this DSSI synth
 501:    * @param index the DSSI index for this soft-synth
 502:    */
 503:   public DSSISynthesizer(Info info, String soname, long index)
 504:   {
 505:     super();
 506:     this.info = info;
 507:     sohandle = DSSIMidiDeviceProvider.dlopen_(soname);
 508:     handle = DSSIMidiDeviceProvider.getDSSIHandle_(sohandle, index);
 509:     channels[0] = new DSSIMidiChannel(0);
 510:     defaultSoundbank = new DSSISoundbank("name", "description",
 511:                                          "vendor", "version");
 512:     soundbanks.add(defaultSoundbank);
 513: 
 514:     int i = 0;
 515:     String name;
 516:     do
 517:     {
 518:       name = getProgramName_(sohandle, i);
 519:       if (name != null)
 520:       {
 521:         defaultSoundbank.
 522:           add(new DSSIInstrument(defaultSoundbank,
 523:                                  new Patch(getProgramBank_(sohandle, i),
 524:                                            getProgramProgram_(sohandle, i)),
 525:                                  name));
 526:         i++;
 527:       }
 528:     } while (name != null);
 529:   }
 530: 
 531:   /* (non-Javadoc)
 532:    * @see javax.sound.midi.Synthesizer#getMaxPolyphony()
 533:    */
 534:   public int getMaxPolyphony()
 535:   {
 536:     // TODO Auto-generated method stub
 537:     return 0;
 538:   }
 539: 
 540:   /* (non-Javadoc)
 541:    * @see javax.sound.midi.Synthesizer#getLatency()
 542:    */
 543:   public long getLatency()
 544:   {
 545:     // DSSI and LADSPA provide no way to determine the latency.
 546:     // Let's just return 0 for now.
 547:     return 0;
 548:   }
 549: 
 550:   /* (non-Javadoc)
 551:    * @see javax.sound.midi.Synthesizer#getChannels()
 552:    */
 553:   public MidiChannel[] getChannels()
 554:   {
 555:     return channels;
 556:   }
 557: 
 558:   /* (non-Javadoc)
 559:    * @see javax.sound.midi.Synthesizer#getVoiceStatus()
 560:    */
 561:   public VoiceStatus[] getVoiceStatus()
 562:   {
 563:     // TODO Auto-generated method stub
 564:     return null;
 565:   }
 566: 
 567:   /* (non-Javadoc)
 568:    * @see javax.sound.midi.Synthesizer#isSoundbankSupported(javax.sound.midi.Soundbank)
 569:    */
 570:   public boolean isSoundbankSupported(Soundbank soundbank)
 571:   {
 572:     // TODO Auto-generated method stub
 573:     return false;
 574:   }
 575: 
 576:   /* @see javax.sound.midi.Synthesizer#loadInstrument(javax.sound.midi.Instrument)
 577:    */
 578:   public boolean loadInstrument(Instrument instrument)
 579:   {
 580:     // FIXME: perhaps this isn't quite right.  It can probably
 581:     // be in any soundbank.
 582:     if (instrument.getSoundbank() != defaultSoundbank)
 583:       throw new IllegalArgumentException ("Synthesizer doesn't support this instrument's soundbank");
 584: 
 585:     Patch patch = instrument.getPatch();
 586:     selectProgram_(sohandle, patch.getBank(), patch.getProgram());
 587:     return true;
 588:   }
 589: 
 590:   /* (non-Javadoc)
 591:    * @see javax.sound.midi.Synthesizer#unloadInstrument(javax.sound.midi.Instrument)
 592:    */
 593:   public void unloadInstrument(Instrument instrument)
 594:   {
 595:     // TODO Auto-generated method stub
 596: 
 597:   }
 598: 
 599:   /* (non-Javadoc)
 600:    * @see javax.sound.midi.Synthesizer#remapInstrument(javax.sound.midi.Instrument, javax.sound.midi.Instrument)
 601:    */
 602:   public boolean remapInstrument(Instrument from, Instrument to)
 603:   {
 604:     // TODO Auto-generated method stub
 605:     return false;
 606:   }
 607: 
 608:   /* @see javax.sound.midi.Synthesizer#getDefaultSoundbank()
 609:    */
 610:   public Soundbank getDefaultSoundbank()
 611:   {
 612:     return defaultSoundbank;
 613:   }
 614: 
 615:   /* @see javax.sound.midi.Synthesizer#getAvailableInstruments()
 616:    */
 617:   public Instrument[] getAvailableInstruments()
 618:   {
 619:     List instruments = new ArrayList();
 620:     Iterator itr = soundbanks.iterator();
 621:     while (itr.hasNext())
 622:     {
 623:       Soundbank sb = (Soundbank) itr.next();
 624:       Instrument ins[] = sb.getInstruments();
 625:       for (int i = 0; i < ins.length; i++)
 626:         instruments.add(ins[i]);
 627:     }
 628:     return (Instrument[])
 629:       instruments.toArray(new Instrument[instruments.size()]);
 630:   }
 631: 
 632:   /* (non-Javadoc)
 633:    * @see javax.sound.midi.Synthesizer#getLoadedInstruments()
 634:    */
 635:   public Instrument[] getLoadedInstruments()
 636:   {
 637:     // TODO Auto-generated method stub
 638:     return null;
 639:   }
 640: 
 641:   /* (non-Javadoc)
 642:    * @see javax.sound.midi.Synthesizer#loadAllInstruments(javax.sound.midi.Soundbank)
 643:    */
 644:   public boolean loadAllInstruments(Soundbank soundbank)
 645:   {
 646:     // TODO Auto-generated method stub
 647:     return false;
 648:   }
 649: 
 650:   /* (non-Javadoc)
 651:    * @see javax.sound.midi.Synthesizer#unloadAllInstruments(javax.sound.midi.Soundbank)
 652:    */
 653:   public void unloadAllInstruments(Soundbank soundbank)
 654:   {
 655:     // TODO Auto-generated method stub
 656:   }
 657: 
 658:   /* (non-Javadoc)
 659:    * @see javax.sound.midi.Synthesizer#loadInstruments(javax.sound.midi.Soundbank, javax.sound.midi.Patch[])
 660:    */
 661:   public boolean loadInstruments(Soundbank soundbank, Patch[] patchList)
 662:   {
 663:     // TODO Auto-generated method stub
 664:     return false;
 665:   }
 666: 
 667:   /* (non-Javadoc)
 668:    * @see javax.sound.midi.Synthesizer#unloadInstruments(javax.sound.midi.Soundbank, javax.sound.midi.Patch[])
 669:    */
 670:   public void unloadInstruments(Soundbank soundbank, Patch[] patchList)
 671:   {
 672:     // TODO Auto-generated method stub
 673: 
 674:   }
 675: 
 676:   /* @see javax.sound.midi.MidiDevice#getDeviceInfo()
 677:    */
 678:   public Info getDeviceInfo()
 679:   {
 680:     return info;
 681:   }
 682: 
 683:   /* @see javax.sound.midi.MidiDevice#open()
 684:    */
 685:   public void open() throws MidiUnavailableException
 686:   {
 687:     open_(sohandle);
 688:   }
 689: 
 690:   /* @see javax.sound.midi.MidiDevice#close()
 691:    */
 692:   public void close()
 693:   {
 694:     close_(sohandle);
 695:   }
 696: 
 697:   /* (non-Javadoc)
 698:    * @see javax.sound.midi.MidiDevice#isOpen()
 699:    */
 700:   public boolean isOpen()
 701:   {
 702:     // TODO Auto-generated method stub
 703:     return false;
 704:   }
 705: 
 706:   /* (non-Javadoc)
 707:    * @see javax.sound.midi.MidiDevice#getMicrosecondPosition()
 708:    */
 709:   public long getMicrosecondPosition()
 710:   {
 711:     // TODO Auto-generated method stub
 712:     return 0;
 713:   }
 714: 
 715:   /* @see javax.sound.midi.MidiDevice#getMaxReceivers()
 716:    */
 717:   public int getMaxReceivers()
 718:   {
 719:     return 1;
 720:   }
 721: 
 722:   /* @see javax.sound.midi.MidiDevice#getMaxTransmitters()
 723:    */
 724:   public int getMaxTransmitters()
 725:   {
 726:     return 0;
 727:   }
 728: 
 729:   /* @see javax.sound.midi.MidiDevice#getReceiver()
 730:    */
 731:   public Receiver getReceiver() throws MidiUnavailableException
 732:   {
 733:     return new DSSIReceiver();
 734:   }
 735: 
 736:   /* @see javax.sound.midi.MidiDevice#getTransmitter()
 737:    */
 738:   public Transmitter getTransmitter() throws MidiUnavailableException
 739:   {
 740:     return null;
 741:   }
 742: }