1 /*
   2  * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import javax.sound.midi.MidiDevice;
  25 import javax.sound.midi.MidiSystem;
  26 import javax.sound.midi.MidiUnavailableException;
  27 import javax.sound.midi.Receiver;
  28 import javax.sound.midi.Sequencer;
  29 import javax.sound.midi.Synthesizer;
  30 import javax.sound.midi.Transmitter;
  31 
  32 /**
  33  * @test
  34  * @bug 4616517
  35  * @summary Receiver.send() does not work properly. Tests open/close behaviour
  36  *          of MidiDevices. For this test, it is essential that the MidiDevice
  37  *          picked from the list of devices (MidiSystem.getMidiDeviceInfo()) is
  38  *          the same as the one used by
  39  *          MidiSystem.getReceiver()/getTransmitter(). To achieve this, default
  40  *          provider properties for Receivers/Transmitters are used.
  41  */
  42 public class OpenClose {
  43 
  44     private static boolean isTestExecuted;
  45     private static boolean isTestPassed;
  46 
  47     public static void main(String[] args) throws Exception {
  48         boolean failed = false;
  49         out("#4616517: Receiver.send() does not work properly");
  50         if (!isMidiInstalled()) {
  51             out("Soundcard does not exist or sound drivers not installed!");
  52             out("This test requires sound drivers for execution.");
  53             return;
  54         }
  55         MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
  56         MidiDevice outDevice = null;
  57         MidiDevice inDevice = null;
  58         for (int i = 0; i < infos.length; i++) {
  59             MidiDevice device = MidiSystem.getMidiDevice(infos[i]);
  60             if (! (device instanceof Synthesizer) &&
  61                 ! (device instanceof Sequencer)) {
  62                 if (device.getMaxReceivers() != 0) {
  63                     outDevice = device;
  64                 }
  65                 if (device.getMaxTransmitters() != 0) {
  66                     inDevice = device;
  67                 }
  68             }
  69         }
  70         if (outDevice != null) {
  71             // set the default provider properties
  72             System.setProperty(Receiver.class.getName(),
  73                                "#" + outDevice.getDeviceInfo().getName());
  74         }
  75         if (inDevice != null) {
  76             System.setProperty(Transmitter.class.getName(),
  77                                "#" + inDevice.getDeviceInfo().getName());
  78         }
  79         out("Using MIDI OUT Device: " + outDevice);
  80         out("Using MIDI IN Device: " + inDevice);
  81 
  82         isTestExecuted = false;
  83         if (outDevice != null) {
  84             isTestExecuted = true;
  85             TestHelper testHelper = new ReceiverTestHelper(outDevice);
  86             try {
  87                 doTest("Receiver", testHelper);
  88                 failed |= testHelper.hasFailed();
  89             } catch (Exception e) {
  90                 out("Exception occured, cannot test!");
  91                 isTestExecuted = false;
  92             }
  93         }
  94 
  95         if (inDevice != null) {
  96             isTestExecuted = true;
  97             TestHelper testHelper = new TransmitterTestHelper(inDevice);
  98             try {
  99                 doTest("Transmitter", testHelper);
 100                 failed |= testHelper.hasFailed();
 101             } catch (Exception e) {
 102                 out("Exception occured, cannot test!");
 103                 isTestExecuted = false;
 104             }
 105         }
 106 
 107         isTestPassed = ! failed;
 108 
 109         if (isTestExecuted) {
 110             if (isTestPassed) {
 111                 out("Test PASSED.");
 112             } else {
 113                 throw new Exception("Test FAILED.");
 114             }
 115         } else {
 116             out("Test NOT FAILED");
 117         }
 118     }
 119 
 120     private static void doTest(String type,
 121                                TestHelper testHelper) throws Exception {
 122         /* Case 1:
 123            - MidiDevice.open()
 124            - MidiDevice.close()
 125         */
 126         out("checking " + type + " case 1...");
 127         testHelper.checkClosed();
 128 
 129         testHelper.openDevice();
 130         testHelper.checkOpen();
 131 
 132         testHelper.closeDevice();
 133         testHelper.checkClosed();
 134 
 135         out("...OK");
 136 
 137         /* Case 2a:
 138            - MidiSystem.get[Receiver|Transmitter]()
 139            - [Receiver|Transmitter].close()
 140         */
 141         out("checking " + type + " case 2a...");
 142         testHelper.checkClosed();
 143 
 144         testHelper.fetchObjectMidiSystem();
 145         testHelper.checkOpen();
 146 
 147         testHelper.closeObjectMidiSystem();
 148         testHelper.checkClosed();
 149 
 150         out("...OK");
 151 
 152         /* Case 2b:
 153            - MidiDevice.get[Receiver|Transmitter]()
 154            - [Receiver|Transmitter].close()
 155         */
 156         out("checking " + type + " case 2b...");
 157         testHelper.checkClosed();
 158 
 159         testHelper.fetchObjectDevice();
 160         testHelper.checkClosed();
 161 
 162         testHelper.closeObjectDevice();
 163         testHelper.checkClosed();
 164 
 165         out("...OK");
 166 
 167         /* Case 3a:
 168            - MidiSystem.get[Receiver|Transmitter]()
 169            - MidiDevice.open()
 170            - MidiDevice.close()
 171            - [Receiver|Transmitter].close()
 172         */
 173         out("checking " + type + " case 3a...");
 174         testHelper.checkClosed();
 175 
 176         testHelper.fetchObjectMidiSystem();
 177         testHelper.checkOpen();
 178 
 179         testHelper.openDevice();
 180         testHelper.checkOpen();
 181 
 182         testHelper.closeDevice();
 183         testHelper.checkClosed();
 184 
 185         testHelper.closeObjectMidiSystem();
 186         testHelper.checkClosed();
 187 
 188         out("...OK");
 189 
 190         /* Case 3b:
 191            - MidiDevice.get[Receiver|Transmitter]()
 192            - MidiDevice.open()
 193            - MidiDevice.close()
 194            - [Receiver|Transmitter].close()
 195         */
 196         out("checking " + type + " case 3b...");
 197         testHelper.checkClosed();
 198 
 199         testHelper.fetchObjectDevice();
 200         testHelper.checkClosed();
 201 
 202         testHelper.openDevice();
 203         testHelper.checkOpen();
 204 
 205         testHelper.closeDevice();
 206         testHelper.checkClosed();
 207 
 208         testHelper.closeObjectDevice();
 209         testHelper.checkClosed();
 210 
 211         out("...OK");
 212 
 213         /* Case 4a:
 214            - MidiSystem.get[Receiver|Transmitter]()
 215            - MidiDevice.open()
 216            - [Receiver|Transmitter].close()
 217            - MidiDevice.close()
 218         */
 219         out("checking " + type + " case 4a...");
 220         testHelper.checkClosed();
 221 
 222         testHelper.fetchObjectMidiSystem();
 223         testHelper.checkOpen();
 224 
 225         testHelper.openDevice();
 226         testHelper.checkOpen();
 227 
 228         testHelper.closeObjectMidiSystem();
 229         testHelper.checkOpen();
 230 
 231         testHelper.closeDevice();
 232         testHelper.checkClosed();
 233 
 234         out("...OK");
 235 
 236         /* Case 4b:
 237            - MidiDevice.get[Receiver|Transmitter]()
 238            - MidiDevice.open()
 239            - [Receiver|Transmitter].close()
 240            - MidiDevice.close()
 241         */
 242         out("checking " + type + " case 4b...");
 243         testHelper.checkClosed();
 244 
 245         testHelper.fetchObjectDevice();
 246         testHelper.checkClosed();
 247 
 248         testHelper.openDevice();
 249         testHelper.checkOpen();
 250 
 251         testHelper.closeObjectDevice();
 252         testHelper.checkOpen();
 253 
 254         testHelper.closeDevice();
 255         testHelper.checkClosed();
 256 
 257         out("...OK");
 258 
 259         /* Case 5a:
 260            - MidiDevice.open()
 261            - MidiSystem.get[Receiver|Transmitter]()
 262            - MidiDevice.close()
 263            - [Receiver|Transmitter].close()
 264         */
 265         out("checking " + type + " case 5a...");
 266         testHelper.checkClosed();
 267 
 268         testHelper.openDevice();
 269         testHelper.checkOpen();
 270 
 271         testHelper.fetchObjectMidiSystem();
 272         testHelper.checkOpen();
 273 
 274         testHelper.closeDevice();
 275         testHelper.checkClosed();
 276 
 277         testHelper.closeObjectMidiSystem();
 278         testHelper.checkClosed();
 279 
 280         out("...OK");
 281 
 282         /* Case 5b:
 283            - MidiDevice.open()
 284            - MidiDevice.get[Receiver|Transmitter]()
 285            - MidiDevice.close()
 286            - [Receiver|Transmitter].close()
 287         */
 288         out("checking " + type + " case 5b...");
 289         testHelper.checkClosed();
 290 
 291         testHelper.openDevice();
 292         testHelper.checkOpen();
 293 
 294         testHelper.fetchObjectDevice();
 295         testHelper.checkOpen();
 296 
 297         testHelper.closeDevice();
 298         testHelper.checkClosed();
 299 
 300         testHelper.closeObjectDevice();
 301         testHelper.checkClosed();
 302 
 303         out("...OK");
 304 
 305         /* Case 6a:
 306            - MidiDevice.open()
 307            - MidiSystem.get[Receiver|Transmitter]()
 308            - [Receiver|Transmitter].close()
 309            - MidiDevice.close()
 310         */
 311         out("checking " + type + " case 6a...");
 312         testHelper.checkClosed();
 313 
 314         testHelper.openDevice();
 315         testHelper.checkOpen();
 316 
 317         testHelper.fetchObjectMidiSystem();
 318         testHelper.checkOpen();
 319 
 320         testHelper.closeObjectMidiSystem();
 321         testHelper.checkOpen();
 322 
 323         testHelper.closeDevice();
 324         testHelper.checkClosed();
 325 
 326         out("...OK");
 327 
 328         /* Case 6b:
 329            - MidiDevice.open()
 330            - MidiDevice.get[Receiver|Transmitter]()
 331            - [Receiver|Transmitter].close()
 332            - MidiDevice.close()
 333         */
 334         out("checking " + type + " case 6b...");
 335         testHelper.checkClosed();
 336 
 337         testHelper.openDevice();
 338         testHelper.checkOpen();
 339 
 340         testHelper.fetchObjectDevice();
 341         testHelper.checkOpen();
 342 
 343         testHelper.closeObjectDevice();
 344         testHelper.checkOpen();
 345 
 346         testHelper.closeDevice();
 347         testHelper.checkClosed();
 348 
 349         out("...OK");
 350 
 351         /* Case 7:
 352            - MidiSystem.get[Receiver|Transmitter]() // 1
 353            - MidiDevice.get[Receiver|Transmitter]() // 2
 354            - [Receiver|Transmitter].close() // 2
 355            - [Receiver|Transmitter].close() // 1
 356         */
 357         out("checking " + type + " case 7...");
 358         testHelper.checkClosed();
 359 
 360         testHelper.fetchObjectMidiSystem();
 361         testHelper.checkOpen();
 362 
 363         testHelper.fetchObjectDevice();
 364         testHelper.checkOpen();
 365 
 366         testHelper.closeObjectDevice();
 367         testHelper.checkOpen();
 368 
 369         testHelper.closeObjectMidiSystem();
 370         testHelper.checkClosed();
 371 
 372         out("...OK");
 373 
 374         /* Case 8:
 375            - MidiSystem.get[Receiver|Transmitter]() // 1
 376            - MidiDevice.get[Receiver|Transmitter]() // 2
 377            - [Receiver|Transmitter].close() // 1
 378            - [Receiver|Transmitter].close() // 2
 379         */
 380         out("checking " + type + " case 8...");
 381         testHelper.checkClosed();
 382 
 383         testHelper.fetchObjectMidiSystem();
 384         testHelper.checkOpen();
 385 
 386         testHelper.fetchObjectDevice();
 387         testHelper.checkOpen();
 388 
 389         testHelper.closeObjectMidiSystem();
 390         testHelper.checkClosed();
 391 
 392         testHelper.closeObjectDevice();
 393         testHelper.checkClosed();
 394 
 395         out("...OK");
 396 
 397         /* Case 9:
 398            - MidiDevice.get[Receiver|Transmitter]() // 2
 399            - MidiSystem.get[Receiver|Transmitter]() // 1
 400            - [Receiver|Transmitter].close() // 2
 401            - [Receiver|Transmitter].close() // 1
 402         */
 403         out("checking " + type + " case 9...");
 404         testHelper.checkClosed();
 405 
 406         testHelper.fetchObjectDevice();
 407         testHelper.checkClosed();
 408 
 409         testHelper.fetchObjectMidiSystem();
 410         testHelper.checkOpen();
 411 
 412         testHelper.closeObjectDevice();
 413         testHelper.checkOpen();
 414 
 415         testHelper.closeObjectMidiSystem();
 416         testHelper.checkClosed();
 417 
 418         out("...OK");
 419 
 420         /* Case 10:
 421            - MidiDevice.get[Receiver|Transmitter]() // 2
 422            - MidiSystem.get[Receiver|Transmitter]() // 1
 423            - [Receiver|Transmitter].close() // 1
 424            - [Receiver|Transmitter].close() // 2
 425         */
 426         out("checking " + type + " case 10...");
 427         testHelper.checkClosed();
 428 
 429         testHelper.fetchObjectDevice();
 430         testHelper.checkClosed();
 431 
 432         testHelper.fetchObjectMidiSystem();
 433         testHelper.checkOpen();
 434 
 435         testHelper.closeObjectMidiSystem();
 436         testHelper.checkClosed();
 437 
 438         testHelper.closeObjectDevice();
 439         testHelper.checkClosed();
 440 
 441         out("...OK");
 442 
 443         /* Case N - 1:
 444            - 10 x MidiSystem.get[Receiver|Transmitter]()
 445            - 10 x [Receiver|Transmitter].close()
 446         */
 447         out("checking " + type + " case N - 1...");
 448         TestHelper[] testHelpers = new TestHelper[10];
 449         for (int i = 0; i < 10; i++) {
 450             testHelpers[i] = (TestHelper) testHelper.clone();
 451         }
 452         testHelper.checkClosed();
 453 
 454         for (int i = 0; i < 10; i++) {
 455             testHelpers[i].fetchObjectMidiSystem();
 456             testHelper.checkOpen();
 457         }
 458 
 459 
 460         for (int i = 0; i < 9; i++) {
 461             testHelpers[i].closeObjectMidiSystem();
 462             testHelper.checkOpen();
 463         }
 464 
 465         testHelpers[9].closeObjectMidiSystem();
 466         testHelper.checkClosed();
 467 
 468         out("...OK");
 469     }
 470 
 471     private static void out(String message) {
 472         System.out.println(message);
 473     }
 474 
 475     private static abstract class TestHelper implements Cloneable {
 476         private MidiDevice device;
 477         private boolean failed;
 478 
 479         protected TestHelper(MidiDevice device) {
 480             this.device = device;
 481             failed = false;
 482         }
 483 
 484         protected MidiDevice getDevice() {
 485             return device;
 486         }
 487 
 488         public boolean hasFailed() {
 489             return failed;
 490         }
 491 
 492         public void openDevice() throws MidiUnavailableException {
 493             getDevice().open();
 494         }
 495 
 496         public void closeDevice() {
 497             getDevice().close();
 498         }
 499 
 500         public void checkOpen(){
 501             checkOpen(getDevice(), true);
 502         }
 503 
 504         public void checkClosed(){
 505             checkOpen(getDevice(), false);
 506         }
 507 
 508         private void checkOpen(MidiDevice device, boolean desiredState) {
 509             if (device.isOpen() != desiredState) {
 510                 out("device should be " +
 511                                     getStateString(desiredState) + ", but isn't!");
 512                 failed = true;
 513             }
 514         }
 515 
 516 
 517         private String getStateString(boolean state) {
 518             return state ? "open" : "closed";
 519         }
 520 
 521 
 522         public abstract void fetchObjectMidiSystem() throws MidiUnavailableException;
 523         public abstract void fetchObjectDevice() throws MidiUnavailableException;
 524         public abstract void closeObjectMidiSystem();
 525         public abstract void closeObjectDevice();
 526 
 527         public Object clone() {
 528             try {
 529                 return super.clone();
 530             } catch (CloneNotSupportedException e) {
 531                 return null;
 532             }
 533         }
 534     }
 535 
 536     private static class ReceiverTestHelper extends TestHelper {
 537         private Receiver receiverMidiSystem;
 538         private Receiver receiverDevice;
 539 
 540         public ReceiverTestHelper(MidiDevice device) {
 541             super(device);
 542         }
 543 
 544         public void fetchObjectMidiSystem() throws MidiUnavailableException {
 545             receiverMidiSystem = MidiSystem.getReceiver();
 546         }
 547 
 548 
 549         public void fetchObjectDevice() throws MidiUnavailableException {
 550             receiverDevice = getDevice().getReceiver();
 551         }
 552 
 553 
 554         public void closeObjectMidiSystem() {
 555             receiverMidiSystem.close();
 556         }
 557 
 558 
 559         public void closeObjectDevice() {
 560             receiverDevice.close();
 561         }
 562     }
 563 
 564     private static class TransmitterTestHelper extends TestHelper {
 565         private Transmitter transmitterMidiSystem;
 566         private Transmitter transmitterDevice;
 567 
 568         public TransmitterTestHelper(MidiDevice device) {
 569             super(device);
 570         }
 571 
 572         public void fetchObjectMidiSystem() throws MidiUnavailableException {
 573             transmitterMidiSystem = MidiSystem.getTransmitter();
 574         }
 575 
 576 
 577         public void fetchObjectDevice() throws MidiUnavailableException {
 578             transmitterDevice = getDevice().getTransmitter();
 579         }
 580 
 581 
 582         public void closeObjectMidiSystem() {
 583             transmitterMidiSystem.close();
 584         }
 585 
 586 
 587         public void closeObjectDevice() {
 588             transmitterDevice.close();
 589         }
 590     }
 591 
 592     /**
 593      * Returns true if at least one MIDI (port) device is correctly installed on
 594      * the system.
 595      */
 596     public static boolean isMidiInstalled() {
 597         boolean result = false;
 598         MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
 599         for (int i = 0; i < devices.length; i++) {
 600             try {
 601                 MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
 602                 result = ! (device instanceof Sequencer) && ! (device instanceof Synthesizer);
 603             } catch (Exception e1) {
 604                 System.err.println(e1);
 605             }
 606             if (result)
 607                 break;
 608         }
 609         return result;
 610     }
 611 }