home *** CD-ROM | disk | FTP | other *** search
/ com!online 2002 April / comcd0402.iso / homepage / javaspecial / 07_01 / MusicKeyboard.java < prev    next >
Encoding:
Java Source  |  1999-09-03  |  9.4 KB  |  390 lines

  1. import java.awt.*;
  2. import java.applet.*;
  3. import java.util.Hashtable;
  4. import java.net.URL;
  5. import java.net.MalformedURLException;
  6.  
  7. /**
  8.  * An applet which allows the user to play the computer's
  9.  * keyboard as if it were a musical keyboard.
  10.  * 
  11.  * @author David Rantanen
  12.  * @version 1.3.jdk1.0 1999 September 3
  13.  */
  14.  
  15. public class MusicKeyboard extends Applet
  16. {
  17.  
  18.     /**
  19.      * The label at the top of the applet.
  20.      */
  21.     private Label readyLabel;
  22.  
  23.     /**
  24.      * The image representing the link to the author's web site.
  25.      */
  26.     private Image authorUrlImage;
  27.     
  28.     /**
  29.      * Data structure to hold all the Notes for all the key characters.
  30.      */
  31.     private Hashtable notes;
  32.  
  33.     /**
  34.      * Contains all the keyboard characters that have notes associated with them.
  35.      */
  36.     private String keys="Q2W3ER5T6Y7UI9O0P[=]qwertyuiop";
  37.  
  38.     /**
  39.      * The image of the musical keyboard showing which computer keys play which notes.
  40.      */
  41.     private Image keyboardImage;
  42.  
  43.     /**
  44.      * How to make the applet playable.
  45.      */
  46.     private final String instruction="Click on the keyboard image to activate.";
  47.     
  48.     /**
  49.      * My web page URL.
  50.      */
  51.     private final String myWebPage="http://members.aol.com/djrant/programming.html";
  52.     
  53.     /**
  54.      * Paints the applet, draws the keyboard image and the author url image
  55.      * on the applet.
  56.      *
  57.      * @param g The graphics context to use for painting.
  58.      */
  59.     
  60.     public void paint(Graphics g)
  61.     {
  62.         g.drawImage(keyboardImage, 24, 25, this);
  63.         g.drawImage(authorUrlImage, 75, bounds().height - 21, this);
  64.         super.paint(g);
  65.     }
  66.     
  67.     /**
  68.      * Plays the note corresponding to the value of key.
  69.      * If there is no such note, nothing happens.
  70.      * 
  71.      * @param key The integer value of the character that was pressed to play a note.
  72.      */
  73.     
  74.     private void play(int key)
  75.     {
  76.         Note note = (Note)notes.get(new Integer(key));
  77.         if (note == null)
  78.             return;
  79.         if (!note.isPlaying())
  80.             note.play();
  81.     }
  82.  
  83.     /**
  84.      * Silences the note corresponding to the value of key.
  85.      * 
  86.      * @param key The integer value of the character that was pressed to silence a note.
  87.      */
  88.     
  89.     private void silence(int key)
  90.     {
  91.         Note note = (Note)notes.get(new Integer(key));
  92.         if (note == null)
  93.             return;
  94.         note.stop();
  95.     }
  96.  
  97.     /**
  98.      * Silences all notes.
  99.      */
  100.     
  101.     private void silenceAll()
  102.     {
  103.         int numKeys = keys.length();
  104.         for (int i = 0; i < numKeys; i++)
  105.             silence(keys.charAt(i));
  106.     }
  107.     
  108.     /**
  109.      * Gets all the sound files for all the notes and puts them in a data structure
  110.      * for easy access.
  111.      */
  112.     
  113.     private void loadSounds()
  114.     {
  115.         URL base=getCodeBase();
  116.         
  117.         int numkeys=keys.length();        
  118.         for (int i=0; i<numkeys; i++)
  119.         {
  120.             int thisKey = keys.charAt(i);
  121.             String soundFile = getFileNameForKey(thisKey);
  122.             Note note = new Note( getAudioClip(base, "sounds/" + soundFile) );
  123.             notes.put(new Integer(thisKey), note);
  124.             
  125.             //make sure it's loaded into memory
  126.             note.play();
  127.             note.stop();
  128.         }
  129.     }
  130.  
  131.     /**
  132.      * Makes an image containing the text of the author's URL.
  133.      * 
  134.      * @return An image containing the text of the author's URL.
  135.      */
  136.     
  137.     private Image makeAuthorUrlImage()
  138.     {
  139.         Image au;
  140.         au = createImage(300, 17);
  141.         Graphics auG = au.getGraphics();
  142.         
  143.         auG.setColor(getBackground());
  144.         auG.fillRect(0, 0, 300, 17);
  145.         
  146.         auG.setColor(Color.blue);
  147.         auG.drawRect(0, 0, 299, 16);
  148.         auG.setFont(new Font("Courier", Font.PLAIN, 10));
  149.         auG.drawString(myWebPage, 5, 11);
  150.         
  151.         return au;
  152.     }
  153.  
  154.     /**
  155.      * Makes an image indicating which computer keys
  156.      * correspond to which musical keys.
  157.      * 
  158.      * @return A keyboard image indicating which computer keys
  159.      * correspond to which musical keys.
  160.      */
  161.     
  162.     private Image makeKeyboard()
  163.     {
  164.         Image kb;
  165.         kb = createImage(400, 100);
  166.         Graphics kbG = kb.getGraphics();
  167.         
  168.         kbG.setColor(Color.black);
  169.         kbG.fillRect(0, 0, 400, 100);
  170.         
  171.         //draw the "naturals"
  172.         kbG.setColor(Color.white);
  173.         for (int n = 0; n < 12; n++)
  174.         {
  175.             kbG.fillRect( 3 + (n * 33), 2, 31, 96);
  176.         }
  177.         //draw the "accidentals"
  178.         kbG.setColor(Color.black);
  179.         for (int n = 0; n < 11; n++)
  180.         {
  181.             switch (n)
  182.             {
  183.                 case 0:
  184.                 case 1:
  185.                 case 3:
  186.                 case 4:
  187.                 case 5:
  188.                 case 7:
  189.                 case 8:
  190.                 case 10:
  191.                 kbG.fillRect( 24 + (n * 33), 2, 22, 65);
  192.                 break;
  193.             }
  194.         }
  195.         //draw the characters
  196.         kbG.setFont(new Font("Courier", Font.BOLD, 24));
  197.         for (int n = 0, whiteIndex = 0; n < 20; n++)
  198.         {
  199.             int thisChar=keys.charAt(n);
  200.             
  201.             switch (thisChar)
  202.             {
  203.                 case 'Q':
  204.                 case 'W':
  205.                 case 'E':
  206.                 case 'R':
  207.                 case 'T':
  208.                 case 'Y':
  209.                 case 'U':
  210.                 case 'I':
  211.                 case 'O':
  212.                 case 'P':
  213.                 case '[':
  214.                 case ']':
  215.                 kbG.setColor(Color.black);
  216.                 kbG.drawString(keys.substring(n, n + 1), 9 + (whiteIndex * 33), 90);
  217.                 whiteIndex++;
  218.                 break;
  219.                 case '2':
  220.                 case '3':
  221.                 case '5':
  222.                 case '6':
  223.                 case '7':
  224.                 case '9':
  225.                 case '0':
  226.                 case '=':
  227.                 kbG.setColor(Color.white);
  228.                 kbG.drawString(keys.substring(n, n + 1), 28 + ((whiteIndex - 1) * 33), 60);
  229.                 break;
  230.             }
  231.         }
  232.         return kb;
  233.     }
  234.  
  235.     /**
  236.      * Gets the name of the sound file for a given character.
  237.      * 
  238.      * @param key The integer value of the character to be associated with a given note.
  239.      * @return The sound file name of the note for the given character.
  240.      */
  241.     
  242.     private String getFileNameForKey(int key)
  243.     {
  244.         switch (key)
  245.         {
  246.             case 'Q':
  247.             case 'q':
  248.              return "c2.au";
  249.             case 'W':
  250.             case 'w':
  251.              return "d2.au";             
  252.             case 'E':
  253.             case 'e':
  254.              return "e2.au";             
  255.             case 'R':
  256.             case 'r':
  257.              return "f2.au";             
  258.             case 'T':
  259.             case 't':
  260.              return "g2.au";             
  261.             case 'Y':
  262.             case 'y':
  263.              return "a2.au";             
  264.             case 'U':
  265.             case 'u':
  266.              return "b2.au";             
  267.             case 'I':
  268.             case 'i':
  269.              return "c3.au";             
  270.             case 'O':
  271.             case 'o':
  272.              return "d3.au";             
  273.             case 'P':
  274.             case 'p':
  275.              return "e3.au";             
  276.             case '[':
  277.              return "f3.au";             
  278.             case ']':
  279.              return "g3.au";             
  280.             case '2':
  281.              return "csharp2.au";             
  282.             case '3':
  283.              return "dsharp2.au";             
  284.             case '5':
  285.              return "fsharp2.au";             
  286.             case '6':
  287.              return "gsharp2.au";
  288.             case '7':
  289.              return "asharp2.au";
  290.             case '9':
  291.              return "csharp3.au";
  292.             case '0':
  293.              return "dsharp3.au";
  294.             case '=':
  295.              return "fsharp3.au";
  296.         }
  297.         return null;
  298.     }
  299.  
  300.     /**
  301.      * Tells the web browser to go to the author's web site.
  302.      */
  303.     
  304.     private void visitAuthor()
  305.     {
  306.         try
  307.         {
  308.             this.getAppletContext().showDocument(new URL(myWebPage));
  309.         }
  310.         catch (MalformedURLException e)
  311.         {
  312.         }
  313.     }
  314.  
  315.     /**
  316.      * Initializes the images, loads the sounds.
  317.      */
  318.     
  319.     public void init()
  320.     {
  321.         setLayout(new BorderLayout());
  322.         
  323.         keyboardImage = makeKeyboard();
  324.         authorUrlImage = makeAuthorUrlImage();
  325.         notes=new Hashtable(127);
  326.         loadSounds();
  327.         
  328.         readyLabel=new Label("", Label.CENTER);
  329.         add("North", readyLabel);
  330.         
  331.         readyLabel.setText(instruction);
  332.     }
  333.  
  334.     /**
  335.      * Handles the key events which play and stop the notes, and the
  336.      * mouse event which opens the browser to the author's web site.
  337.      * 
  338.      * All other events are referred to the superclass.
  339.      * 
  340.      * @param evt The event which is to be handled.
  341.      * @return true if the event was handled, false otherwise
  342.      */
  343.     
  344.     public boolean handleEvent(Event evt)
  345.     {
  346.         if (evt.id == Event.KEY_PRESS)
  347.         {
  348.             play(evt.key);
  349.             return true;
  350.         }
  351.         else if (evt.id == Event.KEY_RELEASE)
  352.         {
  353.             silence(evt.key);
  354.             return true;
  355.         }
  356.         else if (evt.id == Event.MOUSE_DOWN)
  357.         {
  358.             //See if the author url link image was clicked
  359.             if ( evt.x >= 75 && evt.x <= (75 + authorUrlImage.getWidth(this)) &&
  360.                 evt.y >= (bounds().height - 21) &&
  361.                 evt.y <= (bounds().height - 21 + authorUrlImage.getHeight(this)) )
  362.             {
  363.                 visitAuthor();
  364.                 return true;
  365.             }
  366.         }
  367.         else if (evt.id == Event.LOST_FOCUS)
  368.         {
  369.             silenceAll();
  370.             return true;
  371.         }
  372.  
  373.         return super.handleEvent(evt);
  374.     }
  375.     
  376.     /**
  377.      * Returns a string containing information about the author, version
  378.      * 
  379.      * @return a string containing information about the author, version
  380.      */
  381.     
  382.     public String getAppletInfo()
  383.     {
  384.         String me="David Rantanen";
  385.         String program="Musical Keyboard Applet";
  386.         return me + "'s " + program + " version 1.3.jdk1.0 djrant@aol.com";
  387.     }
  388. }
  389.  
  390.