/home/akc/NetBeansProjects/CS1/src/chromesthesia2/Chromesthesia.java
  1 /*
  2  * This program interprets melodic lines given in ABC notation as a
  3  * chromesthete might.
  4  * 
  5  * A Pitch class will be defined, and will take center stage in the
  6  * processing.
  7  * 
  8  * Interpreting a melody in ABC notation will amount to flashing 
  9  * colored rectangles for prescribed durations, while sounding
 10  * the pitch! The color of the rectangle will correspond to pitch
 11  * class. The duration will correspond to the duration of the note.
 12  * 
 13  * For this first version of the program, the duration will be held
 14  * constant at 1 beat.
 15  * 
 16  * Three sorts of images will appear on the screen, the chromesthetic
 17  * output box, a text input box, and an error message box. Simplicity
 18  * of design is rendered by permitting only one box to be on the screen
 19  * at a time.
 20  * 
 21  * ABC represents notes in a manner consistent with these examples:
 22  * C, D, E, C D E c d e
 23  * 
 24  * Google ABC music representation if you would like to know more about it.
 25  */
 26 package chromesthesia2;
 27 
 28 import java.util.Scanner;
 29 import java.util.logging.Level;
 30 import java.util.logging.Logger;
 31 import javax.swing.JOptionPane;
 32 import javax.swing.SwingUtilities;
 33 import painter.SPainter;
 34 
 35 /**
 36  *
 37  * @author akc
 38  */
 39 public class Chromesthesia {
 40 
 41     // INFRASTRUCTURE FOR THE PROGRAM -- LAUNCHING A "GRAPHICS" THREAD
 42     
 43     public static void main(String[] args) {
 44         SwingUtilities.invokeLater(new ThreadForGUI());
 45     }
 46     
 47     private static class ThreadForGUI implements Runnable {
 48         @Override
 49         public void run() {
 50             new Chromesthesia();
 51         }
 52     }
 53     
 54     public Chromesthesia() {
 55         interpreter();
 56     }
 57     
 58     // FEATURED VARIABLES
 59     
 60     private static SPainter miro;
 61     private static Pitch[] pitches;
 62     private static String melody;
 63 
 64     // THE INTERPRETER
 65     
 66     public static void interpreter() {
 67         initialization(); // miro and pitches
 68         while (true) {
 69             String input = getInput();
 70             if (input.equalsIgnoreCase("EXIT")) {
 71                 break;
 72             } else if (input.equalsIgnoreCase("AGAIN")){
 73                 if (melody == null) {
 74                     showErrorMessage("NO EARLIER MELODY FOUND");
 75                 } else {
 76                     try {
 77                         playMelody(melody, pitches);
 78                     } catch (Exception ex) {
 79                         showErrorMessage(ex.toString());
 80                     }
 81                 }
 82             } else {
 83                 try {
 84                     melody = input;
 85                     playMelody(melody, pitches);
 86                 } catch (Exception ex) {
 87                     showErrorMessage(ex.toString());
 88                 }
 89             }
 90         }
 91         cleanup(); // miro has to go
 92     }
 93     
 94     // METHODS PERTAINING TO THE CHROMESTHETIC PITCHES
 95     
 96     private static Pitch[] establishPitches(SPainter painter) {
 97         Pitch[] pitches = new Pitch[21];
 98         Pitch pitchMiddleC = new Pitch("C", painter);
 99         pitches[0] = pitchMiddleC;
100         Pitch pitchLowC = new Pitch("C,", painter);
101         pitches[1] = pitchLowC;
102         Pitch pitchHighC = new Pitch("c", painter);
103         pitches[2] = pitchHighC;
104         Pitch pitchMiddleD = new Pitch("D", painter);
105         pitches[3] = pitchMiddleD;
106         Pitch pitchLowD = new Pitch("D,", painter);
107         pitches[4] = pitchLowD;
108         Pitch pitchHighD = new Pitch("d", painter);
109         pitches[5] = pitchHighD;
110         Pitch pitchMiddleE = new Pitch("E", painter);
111         pitches[6] = pitchMiddleE;
112         Pitch pitchLowE = new Pitch("E,", painter);
113         pitches[7] = pitchLowE;
114         Pitch pitchHighE = new Pitch("e", painter);
115         pitches[8] = pitchHighE;
116         Pitch pitchMiddleF = new Pitch("F", painter);
117         pitches[9] = pitchMiddleF;
118         Pitch pitchLowF = new Pitch("F,", painter);
119         pitches[10] = pitchLowF;
120         Pitch pitchHighF = new Pitch("f", painter);
121         pitches[11] = pitchHighF;
122         Pitch pitchMiddleG = new Pitch("G", painter);
123         pitches[12] = pitchMiddleG;
124         Pitch pitchLowG = new Pitch("G,", painter);
125         pitches[13] = pitchLowG;
126         Pitch pitchHighG = new Pitch("g", painter);
127         pitches[14] = pitchHighG;
128         Pitch pitchMiddleA = new Pitch("A", painter);
129         pitches[15] = pitchMiddleA;
130         Pitch pitchLowA = new Pitch("A,", painter);
131         pitches[16] = pitchLowA;
132         Pitch pitchHighA = new Pitch("a", painter);
133         pitches[17] = pitchHighA;
134         Pitch pitchMiddleB = new Pitch("B", painter);
135         pitches[18] = pitchMiddleB;
136         Pitch pitchLowB = new Pitch("B,", painter);
137         pitches[19] = pitchLowB;
138         Pitch pitchHighB = new Pitch("b", painter);
139         pitches[20] = pitchHighB;
140         return pitches;
141     }
142     
143     private static Pitch find(String token, Pitch[] pitches) throws Exception {
144         for (int i = 0; i < pitches.length; i = i + 1) {
145             Pitch pitch = pitches[i];
146             if (pitch.abcName().equals(token)) {
147                 return pitch;
148             }
149         }
150         throw new Exception("### PITCH " + token + " NOT FOUND");
151     }
152     
153     private static void display(Pitch[] pitches) {
154         for (int i = 0; i < pitches.length; i = i + 1) {
155             System.out.println(pitches[i].toString());
156         }
157     }
158     
159     private static void playMelody(String melody, Pitch[] pitches) throws Exception {
160         Scanner scanner = new Scanner(melody);
161         while (scanner.hasNext()) {
162             String token = scanner.next();
163             String pitchName;
164             String duration = "";
165             if (token.indexOf(",") < 0) {
166                 pitchName = token.substring(0, 1);
167                 duration = token.substring(1);
168             } else {
169                 pitchName = token.substring(0, 2);
170                 duration = token.substring(2);
171             }
172             if (duration.length() == 0) {
173                 duration = "1";
174             }
175             Pitch pitch = find(pitchName, pitches);
176             pitch.play(duration);
177         }
178     }
179     
180     // INITIALIZATION, CLEANUP, GETTING INPUT, ERROR MESSAGING
181     
182     static private void showErrorMessage(String message) {
183         miro.setVisible(false);
184         JOptionPane.showMessageDialog(null, message);
185     }
186     
187     private static void initialization() {
188     // ESTABLISH THE PAINTER AND GIVE IT A SUBSTANTIAL BRUSH WIDTH
189         miro = new SPainter("Chromesthesia", 500, 500);
190         miro.setVisible(false);
191         miro.setBrushWidth(7);
192     // ESTABLISH THE CHROMESTITIC PITCH CLASS OBJECTS
193         pitches = establishPitches(miro);
194         display(pitches);
195     }
196     
197     private static String getInput() {
198         miro.setVisible(false);
199         String label = "Please enter a melody in ABC notation, Play a melody again or EXIT ...     ";
200         String input = JOptionPane.showInputDialog(null, label);
201         miro.setVisible(true);
202         if (input == null) {
203             input = "";
204         }
205         return input;
206     }
207     
208     static private void cleanup() {
209         System.exit(0);
210     }
211 }
212