]> ruin.nu Git - moosique.git/blob - Moosique.java
Implemented most of MooNote and Moosique
[moosique.git] / Moosique.java
1 import javax.sound.midi.*;
2 import javax.swing.*;
3 import java.io.*;
4
5 /* UPDATES
6         Killed superfluous exportMIDI method.
7         Added public static void quit()
8         Removed Sequence seq property.
9         Changed forward(int measures) and rewind(int measures) to forward(long ticks) and rewind(long ticks).
10         Added public static long getPosition()
11         Added public static void setPosition(long ticks)
12         Added public static void resume()
13 */
14
15 /*
16  * Moosique - The MIDI Tracker
17  * 
18  * Main class that handles initiation, IO and sound FX.
19  * 
20  * @author  Andersson, Andreen, Lanneskog, Pehrson
21  * @version 1
22  */
23  
24 public class Moosique {
25
26         private static MooGUI gui;
27         private static Sequence seq;
28
29         private static Sequencer sequencer = null;
30         private static Synthesizer synthesizer = null;
31         private static MidiChannel[] channels;
32
33         private static String filename;
34         private static long position;
35
36         /* 
37          * Starts the application.
38          */
39         public static void main (String[] args) {
40                 System.out.println("Moosique version 1.0");
41                 // Acquires MIDI devices and connects them.
42                 try {
43                         sequencer = MidiSystem.getSequencer();
44                         sequencer.open();
45                         synthesizer = MidiSystem.getSynthesizer();
46                         synthesizer.open();
47                         sequencer.getTransmitter().setReceiver(synthesizer.getReceiver());
48                 } catch (MidiUnavailableException e) {
49                         System.out.println("Unable to initialize MIDI devices.");
50                         quit();
51                 }
52
53                 //If a filename is given as the command-line argument, attempts to load a sequence from the file.
54                 try {
55                         if (args.length == 1) {
56                                 if (!load(args[0])) seq = new Sequence(Sequence.PPQ, 96);
57                         } else {
58                                 // Otherwise creates a new empty one.
59                                 seq = new Sequence(Sequence.PPQ, 96);
60                         }
61                 } catch (InvalidMidiDataException e) {}
62
63                 // Sets up channels and GUI.
64                 channels = synthesizer.getChannels();
65                 gui = new MooGUI();
66         }
67
68         /* 
69          * Returns a pointer to the current sequence.
70          * @return the current sequence
71          */
72         public static Sequence getSequence() {
73                 return seq;
74         }
75
76         /* 
77          * Starts playback of the current sequence.
78          */
79         public static void play() {
80                 try {
81                         sequencer.setSequence(seq);
82                 } catch (InvalidMidiDataException e) {}
83                 sequencer.setTickPosition(position);
84                 sequencer.start();
85         }
86
87         /* 
88          * Pauses playback of the current sequence.
89          */
90         public static void pause() {
91                 sequencer.stop();
92         }
93
94         /* 
95          * Resumes playback of the current sequence.
96          */
97         public static void resume() {
98                 sequencer.start();
99         }
100
101         /* 
102          * Stops playback of the current sequence.
103          */
104         public static void stop() {
105                 sequencer.stop();
106                 sequencer.setTickPosition(position);
107         }
108
109         /* 
110          * Rewinds the current sequence the given number of measures.
111          * @param measures      the number of measures to rewind
112          */
113         public static long getPosition() {
114                 return position;
115         }
116
117         /* 
118          * Rewinds the current sequence the given number of measures.
119          * @param measures      the number of measures to rewind
120          */
121         public static void setPosition(long ticks) {
122                 position = ticks;
123         }
124
125         /* 
126          * Rewinds the current sequence the given number of measures.
127          * @param measures      the number of measures to rewind
128          */
129         public static void rewind(long ticks) {
130                 position -= ticks;
131         }
132
133         /* 
134          * Fast forwards the current sequence the given number of measures.
135          * @param measures      the number of measures to fast forward
136          */
137         public static void forward(long ticks) {
138                 position += ticks;
139         }
140
141         /* 
142          * Loads the MooSequence in the given file.
143          * @param filename      the filename to use
144          */
145         public static boolean load(String file) {
146                 // Loads sequence from file
147                 filename = file;
148                 try {
149                         seq = MidiSystem.getSequence(new File(filename));
150                 } catch (InvalidMidiDataException e) {
151                         return false;
152                 } catch (IOException e) {
153                         JOptionPane.showMessageDialog(null, "File", "alert", JOptionPane.ERROR_MESSAGE); 
154                         return false;
155                 }
156
157                 // Sends sequence to GUI
158                 gui.setSequence(seq);
159
160                 // Searches the sequence for NoteOn events
161                 Track[] tracks = seq.getTracks();
162                 MidiEvent noteOn, noteOff = null, nextEvent;
163                 MidiMessage nextMsg;
164                 ShortMessage shortMsg;
165                 for (int i = 0; i < tracks.length; i++) {
166                         for (int j = 0; j < tracks[i].size(); j++) {
167                                 noteOn = tracks[i].get(j);
168                                 if (noteOn.getMessage() instanceof ShortMessage) {
169                                         if (((ShortMessage)noteOn.getMessage()).getCommand() == ShortMessage.NOTE_ON) {
170                                                 // Finds the corresponding NoteOff event
171                                                 for (int k = j + 1; k < tracks[i].size(); k++) {
172                                                         nextEvent = tracks[i].get(k);
173                                                         nextMsg = nextEvent.getMessage();
174                                                         if (nextMsg instanceof ShortMessage) {
175                                                                 shortMsg = (ShortMessage) nextMsg;
176                                                                 if (shortMsg.getCommand() == ShortMessage.NOTE_OFF && shortMsg.getChannel() == ((ShortMessage)noteOn.getMessage()).getChannel() && shortMsg.getData1() == ((ShortMessage)noteOn.getMessage()).getData1()) {
177                                                                         noteOff = nextEvent;
178                                                                         break;
179                                                                 }
180                                                         }
181                                                 }
182                                                 // Replaces the NoteOn event with a MooNote, if possible with the corresponding NoteOff event
183                                                 tracks[i].remove(noteOn);
184                                                 if (noteOff != null) {
185                                                         tracks[i].add(new MooNote(noteOn, noteOff));
186                                                 } else {
187                                                         tracks[i].add(new MooNote(noteOn));
188                                                 }
189                                         }
190                                 }
191                         }
192                 }
193                 return true;
194         }
195
196         /* 
197          * Saves the current sequence to the given filename
198          * @param filename      the filename to use
199          */
200         public static void saveAs(String filename) throws IOException {
201                 MidiSystem.write(seq, 1, new File(filename));
202
203         }
204
205         /* 
206          * Saves the current sequence to the previously given filename.
207          */
208         public static void save() throws IOException {
209                 saveAs(filename);
210         }
211
212         /* 
213          * Releases all reserved devices and exits the program.
214          */
215         public static void quit() {
216                 if (sequencer.isOpen()) {
217                         try {
218                                 sequencer.open();
219                         } catch (MidiUnavailableException e) {}
220                 }
221                 System.exit(0);
222         }
223 }