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
24import javax.sound.midi.MidiDevice;
25import javax.sound.midi.MidiSystem;
26import javax.sound.midi.MidiUnavailableException;
27import javax.sound.midi.Receiver;
28import javax.sound.midi.Sequencer;
29import javax.sound.midi.Synthesizer;
30import 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 */
42public 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}
612