jdk/test/javax/sound/midi/Sequencer/Recording.java
changeset 41905 e8e5df013c6e
equal deleted inserted replaced
41904:524d908e49ea 41905:e8e5df013c6e
       
     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.MetaMessage;
       
    26 import javax.sound.midi.MidiEvent;
       
    27 import javax.sound.midi.MidiSystem;
       
    28 import javax.sound.midi.Receiver;
       
    29 import javax.sound.midi.Sequence;
       
    30 import javax.sound.midi.Sequencer;
       
    31 import javax.sound.midi.ShortMessage;
       
    32 import javax.sound.midi.Track;
       
    33 
       
    34 /**
       
    35  * @test
       
    36  * @bug 4932841
       
    37  * @key intermittent
       
    38  * @summary Sequencer's recording feature does not work
       
    39  */
       
    40 public class Recording {
       
    41 
       
    42     public static boolean failed = false;
       
    43     public static boolean passed = false;
       
    44     private static Sequencer seq = null;
       
    45 
       
    46     public static void main(String[] args) throws Exception {
       
    47         try {
       
    48             seq = MidiSystem.getSequencer();
       
    49 
       
    50             // create an arbitrary sequence which lasts 10 seconds
       
    51             Sequence sequence = createSequence(10, 120, 240);
       
    52 
       
    53             seq.setSequence(sequence);
       
    54             out("Set Sequence to Sequencer. Tempo="+seq.getTempoInBPM());
       
    55 
       
    56             Track track = sequence.createTrack();
       
    57             int oldSize = track.size();
       
    58             seq.recordEnable(track, -1);
       
    59 
       
    60             seq.open();
       
    61 
       
    62             // if getReceiver throws Exception, failed!
       
    63             failed = true;
       
    64             Receiver rec = seq.getReceiver();
       
    65 
       
    66             // start recording and add various events
       
    67             seq.startRecording();
       
    68 
       
    69             // is exception from here on, not failed
       
    70             failed = false;
       
    71 
       
    72             if (!seq.isRecording()) {
       
    73                 failed = true;
       
    74                 throw new Exception("Sequencer did not start recording!");
       
    75             }
       
    76             if (!seq.isRunning()) {
       
    77                 failed = true;
       
    78                 throw new Exception("Sequencer started recording, but is not running!");
       
    79             }
       
    80 
       
    81             // first: add an event to the middle of the sequence
       
    82             ShortMessage msg = new ShortMessage();
       
    83             msg.setMessage(0xC0, 80, 00);
       
    84             rec.send(msg, 5l * 1000l * 1000l);
       
    85 
       
    86             Thread.sleep(1000);
       
    87 
       
    88             // then add a real-time event
       
    89             msg = new ShortMessage();
       
    90             msg.setMessage(0xC0, 81, 00);
       
    91             long secondEventTick = seq.getTickPosition();
       
    92             rec.send(msg, -1);
       
    93 
       
    94             seq.stopRecording();
       
    95             if (seq.isRecording()) {
       
    96                 failed = true;
       
    97                 throw new Exception("Stopped recording, but Sequencer is still recording!");
       
    98             }
       
    99             if (!seq.isRunning()) {
       
   100                 failed = true;
       
   101                 throw new Exception("Stopped recording, but Sequencer but is not running anymore!");
       
   102             }
       
   103 
       
   104             seq.stop();
       
   105             if (seq.isRunning()) {
       
   106                 failed = true;
       
   107                 throw new Exception("Stopped Sequencer, but it is still running!");
       
   108             }
       
   109 
       
   110             // now examine the contents of the recorded track:
       
   111             // 1) number of events: should be 2 more
       
   112             int newSize = track.size();
       
   113             int addedEventCount = newSize - oldSize;
       
   114 
       
   115             out("Added "+addedEventCount+" events to recording track.");
       
   116             if (addedEventCount != 2) {
       
   117                 failed = true;
       
   118                 throw new Exception("Did not add 2 events!");
       
   119             }
       
   120 
       
   121             // 2) the first event should be at roughly "secondEventTick"
       
   122             MidiEvent ev = track.get(0);
       
   123             msg = (ShortMessage) ev.getMessage();
       
   124             out("The first recorded event is at tick position: "+ev.getTick());
       
   125             if (Math.abs(ev.getTick() - secondEventTick) > 1000) {
       
   126                 out(" -> but expected something like: "+secondEventTick+"! FAILED.");
       
   127                 failed = true;
       
   128             }
       
   129 
       
   130             ev = track.get(1);
       
   131             msg = (ShortMessage) ev.getMessage();
       
   132             out("The 2nd recorded event is at tick position: "+ev.getTick());
       
   133             out(" -> sequence's tick length is "+seq.getTickLength());
       
   134             if (Math.abs(ev.getTick() - (sequence.getTickLength() / 2)) > 1000) {
       
   135                 out(" -> but expected something like: "+(seq.getTickLength()/2)+"! FAILED.");
       
   136                 failed = true;
       
   137             }
       
   138 
       
   139             passed = true;
       
   140         } catch (Exception e) {
       
   141             out(e.toString());
       
   142             if (!failed) out("Test not failed.");
       
   143         }
       
   144         if (seq != null) {
       
   145             seq.close();
       
   146         }
       
   147 
       
   148         if (failed) {
       
   149             throw new Exception("Test FAILED!");
       
   150         }
       
   151         else if (passed) {
       
   152             out("Test Passed.");
       
   153         }
       
   154     }
       
   155 
       
   156     /**
       
   157      * Create a new Sequence for testing.
       
   158      */
       
   159     private static Sequence createSequence(int lengthInSeconds, int tempoInBPM,
       
   160                                            int resolution) {
       
   161         Sequence sequence = null;
       
   162         long lengthInMicroseconds = lengthInSeconds * 1000000;
       
   163         boolean createTempoEvent = true;
       
   164         if (tempoInBPM == 0) {
       
   165             tempoInBPM = 120;
       
   166             createTempoEvent = false;
       
   167             System.out.print("Creating sequence: "+lengthInSeconds+"sec, "
       
   168                              +"resolution="+resolution+" ticks/beat...");
       
   169         } else {
       
   170             System.out.print("Creating sequence: "+lengthInSeconds+"sec, "
       
   171                              +tempoInBPM+" beats/min, "
       
   172                              +"resolution="+resolution+" ticks/beat...");
       
   173         }
       
   174         //long lengthInTicks = (lengthInMicroseconds * resolution) / tempoInBPM;
       
   175         long lengthInTicks = (lengthInMicroseconds * tempoInBPM * resolution) / 60000000l;
       
   176         //out("expected length in ticks: " + lengthInTicks);
       
   177         try {
       
   178             sequence = new Sequence(Sequence.PPQ, resolution);
       
   179             Track track = sequence.createTrack();
       
   180             if (createTempoEvent) {
       
   181                 int tempoInMPQ = (int) (60000000l / tempoInBPM);
       
   182                 MetaMessage tm = new MetaMessage();
       
   183                 byte[] msg = new byte[3];
       
   184                 msg[0] = (byte) (tempoInMPQ >> 16);
       
   185                 msg[1] = (byte) ((tempoInMPQ >> 8) & 0xFF);
       
   186                 msg[2] = (byte) (tempoInMPQ & 0xFF);
       
   187 
       
   188                 tm.setMessage(0x51 /* Meta Tempo */, msg, msg.length);
       
   189                 track.add(new MidiEvent(tm, 0));
       
   190                 //out("regtest: tempoInMPQ="+tempoInMPQ);
       
   191                 //out("Added tempo event: new size="+track.size());
       
   192             }
       
   193             ShortMessage mm = new ShortMessage();
       
   194             mm.setMessage(0xF6, 0, 0);
       
   195             MidiEvent me = new MidiEvent(mm, lengthInTicks);
       
   196             track.add(me);
       
   197             //out("Added realtime event: new size="+track.size());
       
   198         } catch (InvalidMidiDataException e) {
       
   199             out(e);
       
   200         }
       
   201         out("OK");
       
   202 
       
   203         return sequence;
       
   204     }
       
   205 
       
   206     private static void out(Throwable t) {
       
   207         t.printStackTrace(System.out);
       
   208     }
       
   209 
       
   210     private static void out(String message) {
       
   211         System.out.println(message);
       
   212     }
       
   213 }