/home/jfernan6/NetBeansProjects/CSX/src/chromesthesia0/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 chromesthesia0;
 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[9];
 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          return pitches;
 96      }
 97      
 98      private static Pitch find(String token, Pitch[] pitches) throws Exception {
 99          for (int i = 0; i < pitches.length; i = i + 1) {
100              Pitch pitch = pitches[i];
101              if (pitch.abcName().equals(token)) {
102                  return pitch;
103              }
104         }        
105          throw new Exception("### PITCH " + token + "NOT FOUND");
106      }
107      
108      private static void display(Pitch[] pitches) {
109         for (int i = 0; i < pitches.length; i = i + 1) {
110              System.out.println(pitches[i].toString());
111          }
112      }
113      
114      private static void playMelody(String input, Pitch[] pitches) throws Exception {
115          Scanner scanner = new Scanner(input);
116          while (scanner.hasNext()) {
117              String token = scanner.next();
118              Pitch pitch = find(token, pitches);
119              pitch.play("1");
120          }
121      }
122  
123      // INITIALIZATION, CLEANUP, GETTING INPUT, ERROR MESSAGING
124      static private void showErrorMessage(String message) {
125          miro.setVisible(false);
126          JOptionPane.showMessageDialog(null, message);
127      }
128      
129      private static void initialization() {
130          // ESTABLISH THE PAINTER AND GIVE IT A SUBSTANTIAL BRUSH WIDTH
131          miro = new SPainter("Chromesthesia", 500, 500);
132          miro.setVisible(false);
133          miro.setBrushWidth(7);
134          // ESTABLISH THE CHROMESTITIC PITCH CLASS OBJECTS
135          pitches = establishPitches(miro);
136          display(pitches);
137      }
138      
139      private static String getInput() {
140          miro.setVisible(false);
141          String label = "Please enter a melody in ABC notation, or EXIT ...    ";
142          String input = JOptionPane.showInputDialog(null, label);
143          miro.setVisible(true);
144          if (input == null) {input = "";}
145          return input;
146      }
147      
148      static private void cleanup() {
149          System.exit(0);
150      }
151  }
152