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