/*
* LoopingMidiPlayer14.java
*
* This file is part of jsresources.org
*/
/*
* Copyright (c) 1999 - 2001 by Matthias Pfisterer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
|<--- this code is formatted to fit into 80 columns --->|
*/
import java.io.File;
import java.io.IOException;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.MetaEventListener;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.Track;
/** <titleabbrev>LoopingMidiPlayer14</titleabbrev>
<title>Looping a MIDI file (JDK1.4 and earlier)</title>
<formalpara><title>Purpose</title>
<para>Loops a MIDI file using loopstart/loopend meta messages
(JDK1.4 and earlier).</para></formalpara>
<formalpara><title>Usage</title>
<para>
<cmdsynopsis>
<command>java LoopingMidiPlayer14</command>
<arg choice="plain"><replaceable>midifile</replaceable></arg>
</cmdsynopsis>
</para></formalpara>
<formalpara><title>Parameters</title>
<variablelist>
<varlistentry>
<term><option><replaceable>midifile</replaceable></option></term>
<listitem><para>the name of the MIDI file that should be
played</para></listitem>
</varlistentry>
</variablelist>
</formalpara>
<formalpara><title>Bugs, limitations</title>
<para>This program always uses the default Sequencer and the default
Synthesizer to play on. For using non-default sequencers,
synthesizers or to play on an external MIDI port, see
<olink targetdoc="MidiPlayer"
targetptr="MidiPlayer">MidiPlayer</olink>.</para>
<para>This program does not work with the JDK 1.5. For looping
using the JDK 1.5, see <olink targetdoc="LoopingMidiPlayer15"
targetptr="LoopingMidiPlayer15">LoopingMidiPlayer15</olink>.</para>
</formalpara>
<formalpara><title>Source code</title>
<para>
<ulink url="LoopingMidiPlayer14.java.html">LoopingMidiPlayer14.java</ulink>
</para>
</formalpara>
*/
public class LoopingMidiPlayer14
{
public static void main(String[] args)
throws MidiUnavailableException, InvalidMidiDataException, IOException
{
final Sequencer sequencer;
/* We check if there is no command-line argument at all or the
* first one is '-h'. If so, we display the usage message and
* exit.
*/
if (args.length == 0 || args[0].equals("-h"))
{
printUsageAndExit();
}
String strFilename = args[0];
File midiFile = new File(strFilename);
/* We read in the MIDI file to a Sequence object. This object
* is set at the Sequencer later.
*/
Sequence sequence = MidiSystem.getSequence(midiFile);
/* Here, we set the loop points to loop over the whole
* sequence. In order to do so, we insert loopstart and loopend
* meta messages into the sequence.
*/
Track track = sequence.getTracks()[0];
final int MARKER = 6;
long loopStartTick = 0;
long loopEndTick = sequence.getTickLength();
addMetaEvent(track, MARKER, "loopstart".getBytes(), loopStartTick);
addMetaEvent(track, MARKER, "loopend".getBytes(), loopEndTick);
/* Now, we need a Sequencer to play the sequence. Here, we
* simply request the default sequencer with an implicitly
* connected synthesizer
*/
sequencer = MidiSystem.getSequencer();
/* The Sequencer is still a dead object. We have to open() it
* to become live. This is necessary to allocate some
* ressources in the native part.
*/
sequencer.open();
/* Next step is to tell the Sequencer which Sequence it has to
* play. In this case, we set it as the Sequence object
* created above.
*/
sequencer.setSequence(sequence);
/* To free system resources, it is recommended to close the
* synthesizer and sequencer properly.
*
* To accomplish this, we register a Listener to the
* Sequencer. It is called when there are "meta" events. Meta
* event 47 is end of track.
*
* Thanks to Espen Riskedal for finding this trick.
*/
sequencer.addMetaEventListener(new MetaEventListener()
{
public void meta(MetaMessage event)
{
if (event.getType() == 47)
{
sequencer.close();
System.exit(0);
}
}
});
/* Now, we can start over.
*/
sequencer.start();
}
private static void addMetaEvent(Track track, int type,
byte[] data, long tick)
{
MetaMessage message = new MetaMessage();
try
{
message.setMessage(type, data, data.length);
MidiEvent event = new MidiEvent( message, tick );
track.add(event);
}
catch (InvalidMidiDataException e)
{
e.printStackTrace();
}
}
private static void printUsageAndExit()
{
out("LoopingMidiPlayer14: usage:");
out("\tjava LoopingMidiPlayer14 <midifile>");
System.exit(1);
}
private static void out(String strMessage)
{
System.out.println(strMessage);
}
}
/*** LoopingMidiPlayer14.java ***/