]> ruin.nu Git - moosique.git/blob - Moosique.java
Fixed some status thingies in Moosique
[moosique.git] / Moosique.java
1 import javax.sound.midi.*;
2 import javax.swing.*;
3 import java.io.*;
4
5 /*
6  * Moosique - The MIDI Tracker
7  * 
8  * Main class that handles initiation, IO and sound FX.
9  * 
10  * @author  Andersson, Andreen, Lanneskog, Pehrson
11  * @version 1
12  */
13  
14 public class Moosique {
15
16         private static MooGUI gui;
17         private static Sequence seq;
18
19         private static Sequencer sequencer = null;
20         private static Synthesizer synthesizer = null;
21         private static MidiChannel[] channels;
22
23         private static String filename;
24         private static long position;
25
26         /* 
27          * Starts the application.
28          */
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.");
33                 try {
34                         sequencer = MidiSystem.getSequencer();
35                         System.out.print(".");
36                         sequencer.open();
37                         System.out.print(".");
38                         synthesizer = MidiSystem.getSynthesizer();
39                         System.out.print(".");
40                         synthesizer.open();
41                         System.out.print(".");
42                         sequencer.getTransmitter().setReceiver(synthesizer.getReceiver());
43                 } catch (MidiUnavailableException e) {
44                         System.out.println("Failed, quitting.");
45                         quit();
46                 }
47                 System.out.println("Done");
48
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();
53                 } else {
54                         // Otherwise creates a new empty one.
55                         clearSequence();
56                 }
57                 System.out.println("Done");
58
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");
64         }
65
66         /* 
67          * Returns a pointer to the current sequence.
68          * @return the current sequence
69          */
70         public static Sequence getSequence() {
71                 return seq;
72         }
73
74         /* 
75          * Returns a pointer to the current sequence.
76          * @return the current sequence
77          */
78         public static void clearSequence() {
79                 // Creates sequence.
80                 try {
81                         seq = new Sequence(Sequence.PPQ, 96);
82                 } catch (InvalidMidiDataException e) {}
83                 // Sends sequence to GUI.
84                 if (gui != null) gui.setSequence(seq);
85         
86         }
87
88         /* 
89          * Starts playback of the current sequence.
90          */
91         public static void play() {
92                 try {
93                         sequencer.setSequence(seq);
94                         sequencer.setTickPosition(position);
95                 } catch (InvalidMidiDataException e) {}
96                 sequencer.start();
97         }
98
99         /* 
100          * Pauses playback of the current sequence.
101          */
102         public static void pause() {
103                 sequencer.stop();
104         }
105
106         /* 
107          * Resumes playback of the current sequence.
108          */
109         public static void resume() {
110                 sequencer.start();
111         }
112
113         /* 
114          * Stops playback of the current sequence.
115          */
116         public static void stop() {
117                 sequencer.stop();
118                 sequencer.setTickPosition(position);
119         }
120
121         /* 
122          * Rewinds the current sequence the given number of measures.
123          * @param measures      the number of measures to rewind
124          */
125         public static long getPosition() {
126                 return position;
127         }
128
129         /* 
130          * Rewinds the current sequence the given number of measures.
131          * @param measures      the number of measures to rewind
132          */
133         public static void setPosition(long ticks) {
134                 position = ticks;
135         }
136
137         /* 
138          * Rewinds the current sequence the given number of measures.
139          * @param measures      the number of measures to rewind
140          */
141         public static void rewind(long ticks) {
142                 position -= ticks;
143         }
144
145         /* 
146          * Fast forwards the current sequence the given number of measures.
147          * @param measures      the number of measures to fast forward
148          */
149         public static void forward(long ticks) {
150                 position += ticks;
151         }
152
153         /* 
154          * Loads the MooSequence in the given file.
155          * @param filename      the filename to use
156          */
157         public static boolean load(String file) {
158                 // Loads sequence from file
159                 filename = file;
160                 try {
161                         seq = MidiSystem.getSequence(new File(filename));
162                 } catch (InvalidMidiDataException e) {
163                         return false;
164                 } catch (IOException e) {
165                         JOptionPane.showMessageDialog(null, "File", "alert", JOptionPane.ERROR_MESSAGE); 
166                         return false;
167                 }
168
169                 // Sends sequence to GUI
170                 if (gui != null) gui.setSequence(seq);
171
172                 // Searches the sequence for NoteOn events
173                 Track[] tracks = seq.getTracks();
174                 MidiEvent noteOn, noteOff = null, nextEvent;
175                 MidiMessage nextMsg;
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()) {
189                                                                         noteOff = nextEvent;
190                                                                         break;
191                                                                 }
192                                                         }
193                                                 }
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));
198                                                 } else {
199                                                         tracks[i].add(new MooNote(noteOn));
200                                                 }
201                                         }
202                                 }
203                         }
204                 }
205                 return true;
206         }
207
208         /* 
209          * Saves the current sequence to the given filename
210          * @param filename      the filename to use
211          */
212         public static void saveAs(String filename) throws IOException {
213                 MidiSystem.write(seq, 1, new File(filename));
214
215         }
216
217         /* 
218          * Saves the current sequence to the previously given filename.
219          */
220         public static void save() throws IOException {
221                 saveAs(filename);
222         }
223
224         /* 
225          * Releases all reserved devices and exits the program.
226          */
227         public static void quit() {
228                 if (sequencer.isOpen()) {
229                         try {
230                                 sequencer.open();
231                         } catch (MidiUnavailableException e) {}
232                 }
233                 System.exit(0);
234         }
235 }