1 import javax.sound.midi.*;
6 * Moosique - The MIDI Tracker
8 * Main class that handles initiation, IO and sound FX.
10 * @author Andersson, Andreen, Lanneskog, Pehrson
14 public class Moosique {
16 private static MooGUI gui;
17 private static Sequence seq;
19 private static Sequencer sequencer = null;
20 private static Synthesizer synthesizer = null;
21 private static MidiChannel[] channels;
23 private static String filename;
24 private static long position;
27 * Starts the application.
29 public static void main (String[] args) {
30 System.out.println("\nMoosique version 1.0\n");
31 // Acquires MIDI devices and connects them.
32 System.out.print("Initializing MIDI devices.");
34 sequencer = MidiSystem.getSequencer();
35 System.out.print(".");
37 System.out.print(".");
38 synthesizer = MidiSystem.getSynthesizer();
39 System.out.print(".");
41 System.out.print(".");
42 sequencer.getTransmitter().setReceiver(synthesizer.getReceiver());
43 } catch (MidiUnavailableException e) {
44 System.out.println("Failed, quitting.");
47 System.out.println("Done");
49 //If a filename is given as the command-line argument, attempts to load a sequence from the file.
50 System.out.print("Loading MIDI sequence...");
51 if (args.length == 1) {
52 if (!load(args[0])) clearSequence();
54 // Otherwise creates a new empty one.
57 System.out.println("Done");
59 // Sets up channels and GUI.
60 System.out.print("Creating GUI...");
61 channels = synthesizer.getChannels();
62 gui = new MooGUI(seq);
63 System.out.println("Done");
67 * Returns a pointer to the current sequence.
68 * @return the current sequence
70 public static Sequence getSequence() {
75 * Returns a pointer to the current sequence.
76 * @return the current sequence
78 public static void clearSequence() {
81 seq = new Sequence(Sequence.PPQ, 96);
82 } catch (InvalidMidiDataException e) {}
83 // Sends sequence to GUI.
84 if (gui != null) gui.setSequence(seq);
89 * Starts playback of the current sequence.
91 public static void play() {
93 sequencer.setSequence(seq);
94 sequencer.setTickPosition(position);
95 } catch (InvalidMidiDataException e) {}
100 * Pauses playback of the current sequence.
102 public static void pause() {
107 * Resumes playback of the current sequence.
109 public static void resume() {
114 * Stops playback of the current sequence.
116 public static void stop() {
118 sequencer.setTickPosition(position);
122 * Rewinds the current sequence the given number of measures.
123 * @param measures the number of measures to rewind
125 public static long getPosition() {
130 * Rewinds the current sequence the given number of measures.
131 * @param measures the number of measures to rewind
133 public static void setPosition(long ticks) {
138 * Rewinds the current sequence the given number of measures.
139 * @param measures the number of measures to rewind
141 public static void rewind(long ticks) {
146 * Fast forwards the current sequence the given number of measures.
147 * @param measures the number of measures to fast forward
149 public static void forward(long ticks) {
154 * Loads the MooSequence in the given file.
155 * @param filename the filename to use
157 public static boolean load(String file) {
158 // Loads sequence from file
161 seq = MidiSystem.getSequence(new File(filename));
162 } catch (InvalidMidiDataException e) {
164 } catch (IOException e) {
165 JOptionPane.showMessageDialog(null, "File", "alert", JOptionPane.ERROR_MESSAGE);
169 // Sends sequence to GUI
170 if (gui != null) gui.setSequence(seq);
172 // Searches the sequence for NoteOn events
173 Track[] tracks = seq.getTracks();
174 MidiEvent noteOn, noteOff = null, nextEvent;
176 ShortMessage shortMsg;
177 for (int i = 0; i < tracks.length; i++) {
178 for (int j = 0; j < tracks[i].size(); j++) {
179 noteOn = tracks[i].get(j);
180 if (noteOn.getMessage() instanceof ShortMessage) {
181 if (((ShortMessage)noteOn.getMessage()).getCommand() == ShortMessage.NOTE_ON) {
182 // Finds the corresponding NoteOff event
183 for (int k = j + 1; k < tracks[i].size(); k++) {
184 nextEvent = tracks[i].get(k);
185 nextMsg = nextEvent.getMessage();
186 if (nextMsg instanceof ShortMessage) {
187 shortMsg = (ShortMessage) nextMsg;
188 if (shortMsg.getCommand() == ShortMessage.NOTE_OFF && shortMsg.getChannel() == ((ShortMessage)noteOn.getMessage()).getChannel() && shortMsg.getData1() == ((ShortMessage)noteOn.getMessage()).getData1()) {
194 // Replaces the NoteOn event with a MooNote, if possible with the corresponding NoteOff event
195 tracks[i].remove(noteOn);
196 if (noteOff != null) {
197 tracks[i].add(new MooNote(noteOn, noteOff));
199 tracks[i].add(new MooNote(noteOn));
209 * Saves the current sequence to the given filename
210 * @param filename the filename to use
212 public static void saveAs(String filename) throws IOException {
213 MidiSystem.write(seq, 1, new File(filename));
218 * Saves the current sequence to the previously given filename.
220 public static void save() throws IOException {
225 * Releases all reserved devices and exits the program.
227 public static void quit() {
228 if (sequencer.isOpen()) {
231 } catch (MidiUnavailableException e) {}