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

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