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