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.InvalidMidiDataException;
25 import javax.sound.midi.MetaEventListener;
26 import javax.sound.midi.MetaMessage;
27 import javax.sound.midi.MidiDevice;
28 import javax.sound.midi.MidiEvent;
29 import javax.sound.midi.MidiSystem;
30 import javax.sound.midi.Sequence;
31 import javax.sound.midi.Sequencer;
32 import javax.sound.midi.ShortMessage;
33 import javax.sound.midi.Track;
34 
35 /**
36  * @test
37  * @bug 4204105
38  * @summary RFE: add loop() method(s) to Sequencer
39  * @key intermittent
40  */
41 public class Looping {
42 
main(String[] args)43     public static void main(String[] args) throws Exception {
44         out("4204105: RFE: add loop() method(s) to Sequencer");
45         boolean passed = testAll();
46         if (passed) {
47             out("Test PASSED.");
48         } else {
49             throw new Exception("Test FAILED.");
50         }
51     }
52 
53     /**
54      * Execute the test on all available Sequencers.
55      *
56      * @return true if the test passed for all Sequencers, false otherwise
57      */
testAll()58     private static boolean testAll() throws Exception {
59         boolean result = true;
60         MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
61         for (int i = 0; i < devices.length; i++) {
62             MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
63             if (device instanceof Sequencer) {
64                 result &= testSequencer((Sequencer) device);
65             }
66         }
67         return result;
68     }
69 
70     /**
71      * Execute the test on the passed Sequencer.
72      *
73      * @return true if the test is passed this Sequencer, false otherwise
74      */
testSequencer(Sequencer seq)75     private static boolean testSequencer(Sequencer seq) throws Exception{
76         boolean result = true;
77         out("testing: " + seq);
78 
79         result &= testGetSet(seq);
80 
81         seq.setSequence(createSequence());
82 
83         result &= testGetSet(seq);
84 
85         result &= testPlay(seq);
86 
87         return result;
88     }
89 
testGetSet(Sequencer seq)90     private static boolean testGetSet(Sequencer seq) {
91         boolean result = true;
92         Sequence sequence = seq.getSequence();
93         boolean isSequenceLoaded = (sequence != null);
94 
95         out("TestGetSet");
96 
97         try {
98             if (seq.getLoopStartPoint() != 0) {
99                 out("start point", isSequenceLoaded,
100                     "isn't 0!");
101                 result = false;
102             }
103         } catch (IllegalArgumentException iae) {
104             if (!isSequenceLoaded) {
105                 out("Caught permissable IllegalArgumentException:");
106             } else {
107                 out("Threw unacceptable IllegalArgumentException! FAILED");
108                 result = false;
109             }
110             out(iae.toString());
111         }
112 
113         if (seq.getLoopEndPoint() != -1) {
114             out("end point", isSequenceLoaded,
115                 "isn't -1!");
116             result = false;
117         }
118 
119         try {
120             seq.setLoopStartPoint(25);
121             if (seq.getLoopStartPoint() != 25) {
122                 out("setLoopStartPoint()", isSequenceLoaded,
123                     "doesn't set the start point correctly!");
124                 result = false;
125             }
126         } catch (IllegalArgumentException iae) {
127             if (!isSequenceLoaded) {
128                 out("Caught permissable IllegalArgumentException:");
129             } else {
130                 out("Threw unacceptable IllegalArgumentException! FAILED");
131                 result = false;
132             }
133             out(iae.toString());
134         }
135 
136         try {
137             seq.setLoopEndPoint(26);
138             if (seq.getLoopEndPoint() != 26) {
139                 out("setLoopEndPoint()", isSequenceLoaded,
140                     "doesn't set the end point correctly!");
141                 result = false;
142             }
143         } catch (IllegalArgumentException iae) {
144             if (!isSequenceLoaded) {
145                 out("Caught permissable IllegalArgumentException:");
146             } else {
147                 out("Threw unacceptable IllegalArgumentException! FAILED");
148                 result = false;
149             }
150             out(iae.toString());
151         }
152 
153         try {
154             seq.setLoopStartPoint(0);
155             if (seq.getLoopStartPoint() != 0) {
156                 out("setLoopStartPoint()", isSequenceLoaded,
157                     "doesn't set the start point correctly!");
158                 result = false;
159             }
160         } catch (IllegalArgumentException iae) {
161             if (!isSequenceLoaded) {
162                 out("Caught permissable IllegalArgumentException:");
163             } else {
164                 out("Threw unacceptable IllegalArgumentException! FAILED");
165                 result = false;
166             }
167             out(iae.toString());
168         }
169 
170         if (isSequenceLoaded) {
171             seq.setLoopEndPoint(sequence.getTickLength());
172             if (seq.getLoopEndPoint() != sequence.getTickLength()) {
173                 out("setLoopEndPoint()", isSequenceLoaded,
174                     "doesn't set the end point correctly!");
175                 result = false;
176             }
177         } else {
178             // fails
179             seq.setLoopEndPoint(-1);
180             if (seq.getLoopEndPoint() != -1) {
181                 out("setLoopEndPoint()", isSequenceLoaded,
182                     "doesn't set the end point correctly!");
183                 result = false;
184             }
185         }
186 
187         if (seq.getLoopCount() != 0) {
188             out("loop count", isSequenceLoaded,
189                 "isn't 0!");
190             result = false;
191         }
192 
193         seq.setLoopCount(1001);
194         if (seq.getLoopCount() != 1001) {
195             out("setLoopCount()", isSequenceLoaded,
196                 "doesn't set the loop count correctly!");
197             result = false;
198         }
199 
200         seq.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
201         if (seq.getLoopCount() != Sequencer.LOOP_CONTINUOUSLY) {
202             out("setLoopCount(Sequencer.LOOP_CONTINUOUSLY)", isSequenceLoaded,
203                 "doesn't set the loop count correctly!");
204             result = false;
205         }
206 
207         try {
208             seq.setLoopCount(-55);
209             out("setLoopCount()", isSequenceLoaded,
210                 "doesn't throw IllegalArgumentException on illegal value!");
211             result = false;
212         } catch (IllegalArgumentException e) {
213             // EXCEPTION IS EXPECTED
214             out("Caught permissable IAE");
215         }
216 
217         seq.setLoopCount(0);
218         if (seq.getLoopCount() != 0) {
219             out("setLoopCount()", isSequenceLoaded,
220                 "doesn't set the loop count correctly!");
221             result = false;
222         }
223 
224         return result;
225     }
226 
testPlay(Sequencer seq)227     private static boolean testPlay(Sequencer seq) {
228         boolean result = true;
229         long stopTime;
230 
231         out("TestPlay");
232 
233         TestMetaEventListener listener = new TestMetaEventListener();
234         seq.addMetaEventListener(listener);
235         long startTime = System.currentTimeMillis();
236         try {
237             seq.open();
238             out("Playing sequence, length="+(seq.getMicrosecondLength()/1000)+"millis");
239             seq.start();
240             while (true) {
241                 stopTime = listener.getStopTime();
242                 if (stopTime != 0) {
243                     break;
244                 }
245                 try {
246                     Thread.sleep(100);
247                 } catch (InterruptedException e) {
248                 }
249             }
250             long measuredDuration = stopTime - startTime;
251             out("play duration (us): " + measuredDuration);
252         } catch (Exception e) {
253             out("test not executed; exception:");
254             e.printStackTrace();
255         }
256         seq.close();
257         return result;
258     }
259 
260     /**
261      * Create a new Sequence for testing.
262      *
263      * @return a dummy Sequence, or null, if a problem occured while creating
264      *         the Sequence
265      */
createSequence()266     private static Sequence createSequence() {
267         Sequence sequence = null;
268         int lengthInSeconds = 2;
269         long lengthInMicroseconds = lengthInSeconds * 1000000;
270         int resolution = 480;
271         long lengthInTicks = (lengthInMicroseconds * 120 * resolution) / 60000000l;
272         out("length in ticks: " + lengthInTicks);
273         try {
274             sequence = new Sequence(Sequence.PPQ, resolution, 1);
275             Track track = sequence.createTrack();
276             ShortMessage mm = new ShortMessage();
277             mm.setMessage(0xF6, 0, 0);
278             MidiEvent me = new MidiEvent(mm, lengthInTicks);
279             track.add(me);
280         } catch (InvalidMidiDataException e) {
281             // DO NOTHING
282         }
283         out("sequence length (ticks): " + sequence.getTickLength());
284         out("sequence length (us): " + sequence.getMicrosecondLength());
285         return sequence;
286     }
287 
288 
out(String m1, boolean isSequenceLoaded, String m2)289     private static void out(String m1, boolean isSequenceLoaded, String m2) {
290         out(m1 + (isSequenceLoaded ? " with Sequence " : " without Sequence ") + m2);
291     }
292 
out(String message)293     private static void out(String message) {
294         System.out.println(message);
295     }
296 
297     private static class TestMetaEventListener implements MetaEventListener {
298         private long stopTime;
299 
300 
meta(MetaMessage m)301         public void meta(MetaMessage m) {
302             System.out.print("  Got MetaMessage: ");
303             if (m.getType() == 47) {
304                 stopTime = System.currentTimeMillis();
305                 System.out.println(" End Of Track -- OK");
306             } else {
307                 System.out.println(" unknown. Ignored.");
308             }
309         }
310 
getStopTime()311         public long getStopTime() {
312             return stopTime;
313         }
314     }
315 }
316