Bug in RealTimeSequencer when used with Gervill

View: New views
2 Messages — Rating Filter:   Alert me  

Bug in RealTimeSequencer when used with Gervill

by Karl Helgason-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I found a bug in RealTimeSequencer when used with Gervill.
The doAutoConnect opens Gervill synthesizer explicitly
when it is supposed to open Gervill implicitly.

Here is the code that reproduced the bug:

// When we call MidiSystem.getSequencer()
// a instance of  RealTimeSequencer is created
// that is connected to Gervill Receiver opened implicitly
Sequencer seqr = MidiSystem.getSequencer();
seqr.open();

// When we call seqr.close the Receiver is also closed and
// hence the gervill synthesizer is also closed because the
// receiver was opened implicitly.
seqr.close();

// Here is the bug, RealTimeSequencer tries to auto connect
// again, but opens the Gervill synthesizer explicitly
// before it tries to get instance of Receiver opened implicitly.
seqr.open();

// Gervill synthesizer is never closed
// when we finally call seqr.close,
// because it was opened explicitly above.
seqr.close();

--------------------------------------
The error lies here below:
The doAutoConnect performs synth.open();
before it tries to get Receiver opened implicity
by calling getReceiverReferenceCounting.

    private void doAutoConnect() {
        if (Printer.trace) Printer.trace(">> RealTimeSequencer: doAutoConnect()");
        Receiver rec = null;
        // first try to connect to the default synthesizer
        // IMPORTANT: this code needs to be synch'ed with
        //            MidiSystem.getReceiver(boolean), because the same
        //            algorithm needs to be used!
        try {
            Synthesizer synth = MidiSystem.getSynthesizer();
            synth.open();
            if (synth instanceof ReferenceCountingDevice) {
                rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
                if (synth.getClass().toString().contains("com.sun.media.sound.MixerSynth")
                    && (synth.getDefaultSoundbank() == null)) {
                    // don't use this receiver if no soundbank available
                    rec = null;
                    synth.close();
                }
            } else {
                rec = synth.getReceiver();
            }
        } catch (Exception e) {
            // something went wrong with synth
        }
        if (rec == null) {
            // then try to connect to the default Receiver
            try {
                rec = MidiSystem.getReceiver();
            } catch (Exception e) {
                // something went wrong. Nothing to do then!
            }
        }
        if (rec != null) {
            autoConnectedReceiver = rec;
            try {
                getTransmitter().setReceiver(rec);
            } catch (Exception e) {}
        }
        if (Printer.trace) Printer.trace("<< RealTimeSequencer: doAutoConnect() succeeded");
    }

------------------------
Here is a example of corrected RealTimeSequencer.
It now works like MidiSystem.getSequencer(boolean).
e.g. is now correctly synch'ed with MidiSystem.getReceiver(boolean).


    private void doAutoConnect() {
        if (Printer.trace) Printer.trace(">> RealTimeSequencer: doAutoConnect()");
        Receiver rec = null;
        // first try to connect to the default synthesizer
        // IMPORTANT: this code needs to be synch'ed with
        //            MidiSystem.getReceiver(boolean), because the same
        //            algorithm needs to be used!
        try {
            Synthesizer synth = MidiSystem.getSynthesizer();
            if (synth instanceof ReferenceCountingDevice) {
                rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
                if (synth.getClass().toString().contains("com.sun.media.sound.MixerSynth")
                    && (synth.getDefaultSoundbank() == null)) {
                    // don't use this receiver if no soundbank available
                    rec = null;
                    synth.close();
                }
            } else {
                synth.open();
                try {
                    rec = synth.getReceiver();
                } finally {
                    // make sure that the synth is properly closed
                    if (rec == null) {
                         synth.close();
                    }
                }
            }
        } catch (Exception e) {
            // something went wrong with synth
        }
        if (rec == null) {
            // then try to connect to the default Receiver
            try {
                rec = MidiSystem.getReceiver();
            } catch (Exception e) {
                // something went wrong. Nothing to do then!
            }
        }
        if (rec != null) {
            autoConnectedReceiver = rec;
            try {
                getTransmitter().setReceiver(rec);
            } catch (Exception e) {}
        }
        if (Printer.trace) Printer.trace("<< RealTimeSequencer: doAutoConnect() succeeded");
    }
_______________________________________________
audio-engine-dev mailing list
audio-engine-dev@...
http://mail.openjdk.java.net/mailman/listinfo/audio-engine-dev

Re: Bug in RealTimeSequencer when used with Gervill

by Alex Menkov-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Karl,

Yes, it's real mis-synchronization of the code.
I've created a CR for the bug.
I'm going to update the code along with RealTimeSequencer code cleaning
(removing obsolete references to Beatnik code).

Regards
Alex

Karl Helgason wrote:

> I found a bug in RealTimeSequencer when used with Gervill.
> The doAutoConnect opens Gervill synthesizer explicitly
> when it is supposed to open Gervill implicitly.
>
> Here is the code that reproduced the bug:
>
> // When we call MidiSystem.getSequencer()
> // a instance of  RealTimeSequencer is created
> // that is connected to Gervill Receiver opened implicitly
> Sequencer seqr = MidiSystem.getSequencer();
> seqr.open();
>
> // When we call seqr.close the Receiver is also closed and
> // hence the gervill synthesizer is also closed because the
> // receiver was opened implicitly.
> seqr.close();
>
> // Here is the bug, RealTimeSequencer tries to auto connect
> // again, but opens the Gervill synthesizer explicitly
> // before it tries to get instance of Receiver opened implicitly.
> seqr.open();
>
> // Gervill synthesizer is never closed
> // when we finally call seqr.close,
> // because it was opened explicitly above.
> seqr.close();
>
> --------------------------------------
> The error lies here below:
> The doAutoConnect performs synth.open();
> before it tries to get Receiver opened implicity
> by calling getReceiverReferenceCounting.
>
>     private void doAutoConnect() {
>         if (Printer.trace) Printer.trace(">> RealTimeSequencer: doAutoConnect()");
>         Receiver rec = null;
>         // first try to connect to the default synthesizer
>         // IMPORTANT: this code needs to be synch'ed with
>         //            MidiSystem.getReceiver(boolean), because the same
>         //            algorithm needs to be used!
>         try {
>             Synthesizer synth = MidiSystem.getSynthesizer();
>             synth.open();
>             if (synth instanceof ReferenceCountingDevice) {
>                 rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
>                 if (synth.getClass().toString().contains("com.sun.media.sound.MixerSynth")
>                     && (synth.getDefaultSoundbank() == null)) {
>                     // don't use this receiver if no soundbank available
>                     rec = null;
>                     synth.close();
>                 }
>             } else {
>                 rec = synth.getReceiver();
>             }
>         } catch (Exception e) {
>             // something went wrong with synth
>         }
>         if (rec == null) {
>             // then try to connect to the default Receiver
>             try {
>                 rec = MidiSystem.getReceiver();
>             } catch (Exception e) {
>                 // something went wrong. Nothing to do then!
>             }
>         }
>         if (rec != null) {
>             autoConnectedReceiver = rec;
>             try {
>                 getTransmitter().setReceiver(rec);
>             } catch (Exception e) {}
>         }
>         if (Printer.trace) Printer.trace("<< RealTimeSequencer: doAutoConnect() succeeded");
>     }
>
> ------------------------
> Here is a example of corrected RealTimeSequencer.
> It now works like MidiSystem.getSequencer(boolean).
> e.g. is now correctly synch'ed with MidiSystem.getReceiver(boolean).
>
>
>     private void doAutoConnect() {
>         if (Printer.trace) Printer.trace(">> RealTimeSequencer: doAutoConnect()");
>         Receiver rec = null;
>         // first try to connect to the default synthesizer
>         // IMPORTANT: this code needs to be synch'ed with
>         //            MidiSystem.getReceiver(boolean), because the same
>         //            algorithm needs to be used!
>         try {
>             Synthesizer synth = MidiSystem.getSynthesizer();
>             if (synth instanceof ReferenceCountingDevice) {
>                 rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
>                 if (synth.getClass().toString().contains("com.sun.media.sound.MixerSynth")
>                     && (synth.getDefaultSoundbank() == null)) {
>                     // don't use this receiver if no soundbank available
>                     rec = null;
>                     synth.close();
>                 }
>             } else {
>                 synth.open();
>                 try {
>                     rec = synth.getReceiver();
>                 } finally {
>                     // make sure that the synth is properly closed
>                     if (rec == null) {
>                          synth.close();
>                     }
>                 }
>             }
>         } catch (Exception e) {
>             // something went wrong with synth
>         }
>         if (rec == null) {
>             // then try to connect to the default Receiver
>             try {
>                 rec = MidiSystem.getReceiver();
>             } catch (Exception e) {
>                 // something went wrong. Nothing to do then!
>             }
>         }
>         if (rec != null) {
>             autoConnectedReceiver = rec;
>             try {
>                 getTransmitter().setReceiver(rec);
>             } catch (Exception e) {}
>         }
>         if (Printer.trace) Printer.trace("<< RealTimeSequencer: doAutoConnect() succeeded");
>     }
> _______________________________________________
> audio-engine-dev mailing list
> audio-engine-dev@...
> http://mail.openjdk.java.net/mailman/listinfo/audio-engine-dev
_______________________________________________
audio-engine-dev mailing list
audio-engine-dev@...
http://mail.openjdk.java.net/mailman/listinfo/audio-engine-dev