Chromesthesia.java
1    package chromesthesia2;
2    
3    import painter.SPainter;
4    
5    import javax.swing.*;
6    import java.util.Scanner;
7    
8    public class Chromesthesia {
9        // INFRASTRUCTURE FOR THE PROGRAM -- LAUNCHING A "GRAPHICS" THREAD
10       public static void main(String[] args) {
11           SwingUtilities.invokeLater(new ThreadForGUI());
12       }
13   
14       private static class ThreadForGUI implements Runnable {
15           @Override
16           public void run() {
17               new Chromesthesia();
18           }
19       }
20   
21       public Chromesthesia() {
22           interpreter();
23       }
24   
25       // FEATURED VARIABLES
26       private static SPainter miro;
27       private static Pitch[] pitches;
28       private static String melody;
29   
30       // THE INTERPRETER
31       public static void interpreter() {
32           initialization(); // miro and pitches
33           while (true) {
34               String input = getInput();
35               if (input.equalsIgnoreCase("EXIT")) {
36                   break;
37               } else if (input.equalsIgnoreCase("AGAIN")) {
38                   if (melody == null) {
39                       showErrorMessage("NO EARLIER MELODY FOUND");
40                   } else {
41                       try {
42                           playMelody(melody, pitches);
43                       } catch (Exception ex) {
44                           showErrorMessage(ex.toString());
45                       }
46                   }
47               } else {
48                   try {
49                       melody = input;
50                       playMelody(melody, pitches);
51                   } catch (Exception ex) {
52                       showErrorMessage(ex.toString());
53                   }
54               }
55           }
56           cleanup(); // miro has to go
57       }
58   
59       // METHODS PERTAINING TO THE CHROMESTHETIC PITCHES
60       private static Pitch[] establishPitches(SPainter painter) {
61           Pitch[] pitches = new Pitch[21];
62           Pitch pitchMiddleC = new Pitch("C", painter);
63           pitches[0] = pitchMiddleC;
64           Pitch pitchLowC = new Pitch("C,", painter);
65           pitches[1] = pitchLowC;
66           Pitch pitchHighC = new Pitch("c", painter);
67           pitches[2] = pitchHighC;
68           Pitch pitchMiddleD = new Pitch("D", painter);
69           pitches[3] = pitchMiddleD;
70           Pitch pitchLowD = new Pitch("D,", painter);
71           pitches[4] = pitchLowD;
72           Pitch pitchHighD = new Pitch("d", painter);
73           pitches[5] = pitchHighD;
74           Pitch pitchMiddleE = new Pitch("E", painter);
75           pitches[6] = pitchMiddleE;
76           Pitch pitchLowE = new Pitch("E,", painter);
77           pitches[7] = pitchLowE;
78           Pitch pitchHighE = new Pitch("e", painter);
79           pitches[8] = pitchHighE;
80           // extending for F
81           Pitch pitchLowF = new Pitch("F", painter);
82           pitches[9] = pitchLowF;
83           Pitch pitchMidF = new Pitch("F,", painter);
84           pitches[10] = pitchMidF;
85           Pitch pitchHighF = new Pitch("f", painter);
86           pitches[11] = pitchHighF;
87           // G
88           Pitch pitchLowG = new Pitch("G", painter);
89           pitches[12] = pitchLowG;
90           Pitch pitchMidG = new Pitch("G,", painter);
91           pitches[13] = pitchMidG;
92           Pitch pitchHighG = new Pitch("g", painter);
93           pitches[14] = pitchHighG;
94           // A
95           Pitch pitchLowA = new Pitch("A", painter);
96           pitches[15] = pitchLowA;
97           Pitch pitchMidA = new Pitch("A,", painter);
98           pitches[16] = pitchMidA;
99           Pitch pitchHighA = new Pitch("a", painter);
100          pitches[17] = pitchHighA;
101          // B
102          Pitch pitchLowB = new Pitch("B", painter);
103          pitches[18] = pitchLowB;
104          Pitch pitchMidB = new Pitch("B,", painter);
105          pitches[19] = pitchMidB;
106          Pitch pitchHighB = new Pitch("b", painter);
107          pitches[20] = pitchHighB;
108          return pitches;
109      }
110  
111      private static Pitch find(String token, Pitch[] pitches) throws Exception {
112          for (int i = 0; i < pitches.length; i = i + 1) {
113              Pitch pitch = pitches[i];
114              if (pitch.abcName().equals(token)) {
115                  return pitch;
116              }
117          }
118          throw new Exception("### PITCH " + token + " NOT FOUND");
119      }
120  
121      private static void display(Pitch[] pitches) {
122          for (int i = 0; i < pitches.length; i = i + 1) {
123              System.out.println(pitches[i].toString());
124          }
125      }
126  
127      private static void playMelody(String melody, Pitch[] pitches) throws Exception {
128          Scanner scanner = new Scanner(melody);
129          while (scanner.hasNext()) {
130              String token = scanner.next();
131              String pitchName;
132              String duration = "";
133              if (token.indexOf(",") < 0) {
134                  pitchName = token.substring(0, 1);
135                  duration = token.substring(1);
136              } else {
137                  pitchName = token.substring(0, 2);
138                  duration = token.substring(2);
139              }
140              if (duration.length() == 0) {
141                  duration = "1";
142              }
143              Pitch pitch = find(pitchName, pitches);
144              pitch.play(duration);
145          }
146      }
147  
148      // INITIALIZATION, CLEANUP, GETTING INPUT, ERROR MESSAGING
149      static private void showErrorMessage(String message) {
150          miro.setVisible(false);
151          JOptionPane.showMessageDialog(null, message);
152      }
153  
154      private static void initialization() {
155          // ESTABLISH THE PAINTER AND GIVE IT A SUBSTANTIAL BRUSH WIDTH
156          miro = new SPainter("Chromesthesia", 500, 500);
157          miro.setVisible(false);
158          miro.setBrushWidth(7);
159          // ESTABLISH THE CHROMESTITIC PITCH CLASS OBJECTS
160          pitches = establishPitches(miro);
161          display(pitches);
162      }
163  
164      private static String getInput() {
165          miro.setVisible(false);
166          String label = "Please enter a melody in ABC notation, or EXIT ...     ";
167          String input = JOptionPane.showInputDialog(null, label);
168          miro.setVisible(true);
169          if (input == null) {
170              input = "";
171          }
172          return input;
173      }
174  
175      static private void cleanup() {
176          System.exit(0);
177      }
178  }